Alter 100M rows Amazon RDS table to add a new column - mysql

I'm trying to add a new column to a very very large table, but my alter command fails miserably
mySQL [sc_production]> ALTER TABLE job_assets ADD COLUMN browser varchar(10) DEFAULT NULL, ALGORITHM=INPLACE, LOCK=NONE;
ERROR 1317 (70100): Query execution was interruptedy
I've tried without the LOCK as well, but it also failed:
mySQL [sc_production]> ALTER TABLE job_assets ADD COLUMN browser varchar(10) DEFAULT NULL, ALGORITHM=INPLACE;
ERROR 1034 (HY000): Incorrect key file for table 'job_assets'; try to repair it
Is there any other way that I could do it ?
Creating a new table with this column and migrating all the data would be a huge huge pain
Edit:
I already have the max execution time set to 0
mySQL [sc_production]> show variables like '%max_execution_time%';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| max_execution_time | 0 |
Thanks

Related

MySQL 8 ignoring integer lengths

I have a MySQL 8.0.19 running in a Docker container and using the InnoDB engine. I have noticed that table integer field lengths are getting ignored.
The issue occurs with integer datatypes regardless if running a CREATE or ALTER query
CREATE TABLE `test` (
`id` int DEFAULT NULL,
`text_field` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`decimal_field` decimal(6,2) DEFAULT NULL,
`int_field` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
The lengths are showing as 0 in my MySQL client (Navicat), but the same occurs if checking in the console with SHOW FULL COLUMNS FROMtest;
mysql> SHOW FULL COLUMNS FROM `test`;
+---------------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+---------------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| id | int | NULL | YES | | NULL | | select,insert,update,references | |
| text_field | varchar(20) | utf8mb4_unicode_ci | YES | | NULL | | select,insert,update,references | |
| decimal_field | decimal(6,2) | NULL | YES | | NULL | | select,insert,update,references | |
| int_field | int | NULL | YES | | NULL | | select,insert,update,references | |
+---------------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
The Type column should be showing int(11) for the two integer fields, but it isn't.
Is this related to something in my MySQL settings, and if so, which variable would have to be changed?
This is a change documented in the MySQL 8.0.19 release notes:
Display width specification for integer data types was deprecated in
MySQL 8.0.17, and now statements that include data type definitions in
their output no longer show the display width for integer types, with
these exceptions:
The type is TINYINT(1). MySQL Connectors make the assumption that
TINYINT(1) columns originated as BOOLEAN columns; this exception
enables them to continue to make that assumption.
The type includes the ZEROFILL attribute.
This change applies to tables, views, and stored routines, and affects
the output from SHOW CREATE and DESCRIBE statements, and from
INFORMATION_SCHEMA tables.
For DESCRIBE statements and INFORMATION_SCHEMA queries, output is
unaffected for objects created in previous MySQL 8.0 versions because
information already stored in the data dictionary remains unchanged.
This exception does not apply for upgrades from MySQL 5.7 to 8.0, for
which all data dictionary information is re-created such that data
type definitions do not include display width. (Bug #30556657, Bug #97680)
The "length" of an integer column doesn't mean anything. A column of int(11) is the same as int(2) or int(40). They are all a fixed-size, 32-bit integer data type. They support the same minimum and maximum value.
The "length" of integer columns has been a confusing feature of MySQL for years. It's only a hint that affects the display width, not the storage or the range of values. Practically, it only matters when you use the ZEROFILL option.
mysql> create table t ( i1 int(6) zerofill, i2 int(12) zerofill );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t set i1 = 123, i2 = 123;
Query OK, 1 row affected (0.00 sec)
mysql> select * from t;
+--------+--------------+
| i1 | i2 |
+--------+--------------+
| 000123 | 000000000123 |
+--------+--------------+
1 row in set (0.00 sec)
So it's a good thing that the misleading integer "length" is now deprecated and removed. It has caused confusion for many years.
I can confirm that having upgraded AWS RDS to MySQL 8.0.19 that you can now sync using Navicat correctly.
However, PLEASE BE AWARE!!
When updating the id column, if auto_increment is set, Navicat removes auto_increment to change the length and then re-applies it at the end. This causes the auto_increment column to reassign the ids is sequencial order!
ALTER TABLE `database`.`table` MODIFY COLUMN `id` mediumint(0) NOT NULL FIRST;
...
...
ALTER TABLE `database`.`table` MODIFY COLUMN `id` mediumint(0) NOT NULL AUTO_INCREMENT;
If you are using table relationships and do not have the foreign keys setup properly, this will break your database!
Also, if you have id numbers of zero or below in your auto_increment column, this will cause the following error:
Result: 1062 - ALTER TABLE causes auto_increment resequencing,
resulting in duplicate entry '1' for key 'table.PRIMARY'
To avoid the above, you will need to manually change each tables id length to 0 and then save the changes before attempting to use the Navicat sync feature. When saving the changes using Navicat this will automatically change any other int column lengths to 0.
Please ensure you throughly test your changes on a copy of the database before trying to apply to any production databases.

Auto Increment has been reset back to 1 automatically

I've just run into an issue which I'm not able to solve.
I have a database table project_queues which is used as a queue, where I store some records. When the records are processed, they are deleted.
Deletion is invoked by rails construction record.destroy in a loop which triggers DELETE record FROM table on MySql database.
But now I've noticed, that in the table project_queues the autoIncrement Id (primary key) was set up back to 1. (Which damaged my references in the audit table. The Same record now points to multiple different project queues)
show create table project_queues;
CREATE TABLE `project_queues` (
`id` int(11) NOT NULL AUTO_INCREMENT,
...
...
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=1
I do not use TRUNCATE project_queues or drop the table construction and created it again in code.
Did somebody run into a similar issue like me? I can't find any anomalies in the log either.
I'm using Rails 5.2.3, MariaDB 10.1.
The connection from the application to database enforces this SQL modes:
NO_AUTO_VALUE_ON_ZERO
STRICT_ALL_TABLES
NO_AUTO_CREATE_USER
NO_ENGINE_SUBSTITUTION
NO_ZERO_DATE
NO_ZERO_IN_DATE
ERROR_FOR_DIVISION_BY_ZERO
But I don't think that these have something to do with AI.
Auto_increment can be reset by updates. Since you're using it as a queue I suppose you don't make updates, but it's worth asking.
Also, what table implementation do you use, MyIsam, InnoDB, other ... ?
Well ok, I found the problem (it's a known issue from 2013).
Here is how to reproduce the problem.
# Your MariaDB Server version: 10.1.29-MariaDB MariaDB Server
# Engine InnoDB
create database ai_test;
use ai_test;
CREATE TABLE IF NOT EXISTS ai_test(id INT AUTO_INCREMENT PRIMARY KEY,
a VARCHAR(50));
show table status like 'ai_test'
> Auto_increment: 1
INSERT INTO ai_test(a) VALUES ('first');
INSERT INTO ai_test(a) VALUES ('second');
INSERT INTO ai_test(a) VALUES ('third');
show table status like 'ai_test'
> Auto_increment: 4
MariaDB [ai_test]> Delete from ai_test where a = 'first';
MariaDB [ai_test]> Delete from ai_test where a = 'second';
MariaDB [ai_test]> Delete from ai_test where a = 'third';
show table status like 'ai_test' \G
> Auto_increment: 4
# Restart Server
sudo service rh-mariadb101-mariadb stop
sudo service rh-mariadb101-mariadb start
show table status like 'ai_test' \G
> Auto_increment: 1
I'll try to find some workaround to solve this problem, but I think this cause havoc to many use cases which refers to some archive tables or something like that.
References:
https://bugs.mysql.com/bug.php?id=64287
https://dev.mysql.com/worklog/task/?id=6204
https://openquery.com.au/blog/implementing-sequences-using-a-stored-function-and-triggers
Solved
I've upgraded 10.1.29-MariaDB MariaDB Server to 10.2.8-MariaDB MariaDB Server
Version >= 10.2.4 has solved the resetting of Auto Increment value

MySQL - Table does not exist and can not be created

MySQL 5.5.46 strange error: Table does not exist and can not be created.
Please, can anyone help?
drop table t_example;
Returns: drop table t_example Error Code: 1051. Unknown table 't_example' 0.000 sec
CREATE TABLE t_example(
`id_example` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`des_example` VARCHAR(45) NOT NULL,
`id_example` int unsigned NULL,
PRIMARY KEY (`id_example`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
Returns: Error Code: 1050. Table 't_example' already exists
select * from t_example;
Returns: Error Code: 1146. Table 't_example' doesn't exist
I'm using:
UBUNTU 14.04 LTS;
mysql Ver 14.14 Distrib 5.5.46, for debian-linux-gnu (x86_64) using readline 6.
I'm using root user.
Tried:
mysql> REPAIR TABLE t_example;
+----------------+--------+----------+--------------------------------------+
| Table | Op | Msg_type | Msg_text |
+ ---------------+--------+----------+--------------------------------------+
| mydb.t_example | repair | Error | Table 'mydb.t_example' doesn't exist |
| mydb.t_example | repair | status | Operation failed |
+----------------+--------+----------+--------------------------------------+
2 rows in set (0.00 sec)
Tried too: sudo mysqladmin flush-tables ... Also not solved the problem!
REAL EXAMPLE:
mysql> use flexible;
Database changed
mysql> select * from st_fin_centro_custo;
ERROR 1146 (42S02): Table 'flexible.st_fin_centro_custo' doesn't exist
mysql> CREATE TABLE st_fin_centro_custo(
-> `cod_centro_custo` INT UNSIGNED NOT NULL AUTO_INCREMENT,
-> `des_centro_custo` VARCHAR(45) NOT NULL,
-> PRIMARY KEY (`cod_centro_custo`))
-> ENGINE = InnoDB
-> DEFAULT CHARACTER SET = utf8
-> COLLATE = utf8_general_ci;
ERROR 1050 (42S01): Table '`flexible`.`st_fin_centro_custo`' already exists
mysql> drop table st_fin_centro_custo;
ERROR 1051 (42S02): Unknown table 'st_fin_centro_custo'
mysql>
Tried get from MySQL information_schema:
mysql> SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_TYPE
FROM information_schema.tables
where table_name like 'st_fin_centro_custo';
Empty set (0.00 sec)
mysql>
Note: creating the table with another name works fine.
Thanks a lot!
First select your data base schema by using use command<use schema>.
Then run DROP TABLE IF EXISTS t_example;
After that try to create your table
CREATE TABLE t_example(
`id_example` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`des_example` VARCHAR(45) NOT NULL,
PRIMARY KEY (`id_example`))
ENGINE = INNODB
DEFAULT CHARACTER SET = UTF8
COLLATE = UTF8_GENERAL_CI;
Also don't use duplicate column name.
Another solution is :
Change table name in the create table query, execute it and then rename the table.
Then, you can also drop this table and after it create it without getting error.
It's possible your table is corrupted.
Try REPAIR TABLE t_example;
First of all, try to restart mysqld. If it do not help, try to create this table into another database. Then copy newly created *.frm file to the target database folder. Restart mysqld one more time. Now try to get access/drop/create this table in proper DB.
Edit: How about to drop database and recreate if from the scratch? I hope it's not a production system.

MySQL Error : Invalid default value for 'CREATED_DATE'

I have created an LAMP instance in AWS and while creating DB, I am stuck with this error
Error Code: 1067. Invalid default value for 'CREATED_DATE'
I checked sql mode and here is the response
mysql> SHOW VARIABLES LIKE 'sql_mode';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_mode | |
+---------------+-------+
1 row in set (0.00 sec)
I am not sure whey this is happening. Here is my db script
CREATE TABLE ENTITIES (
ENTITY_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(30) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NOT NULL,
CREATED_DATE DATETIME DEFAULT CURRENT_TIMESTAMP,
UPDATED_DATE DATETIME ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_ENTITIES_id1 (ENTITY_ID ASC)
)
ENGINE = InnoDB
AUTO_INCREMENT=100
;
Any idea on how to fix this?
Change CREATED_DATE DATETIME DEFAULT CURRENT_TIMESTAMP
to
CREATED_DATE TIMESTAMP DEFAULT CURRENT_TIMESTAMP
The problem is not because of Amazon EC2 instance.
Amazon EC2 is virtual machine similar to your own local machine.
The error is due to mistake in mysql query you are using, refer the create table mysql query syntax corresponding to the mysql version you have installed in the Amazon EC2 instance.
Hope it will solve the issue.....

MySQL dynamic columns - column_create does not exist

MariaDB 5.3 introduced dynamic columns. From my understanding the next version of mysql should have similar features mariadb has?
I am currently running mysql 5.5.9 and I wanted to mess around with dynamic columns per row.
So I read up on the mysql website, in order to get this working:
innodb_file_format should be set to Barracuda.
Done.
--------------
show variables like "%innodb_file%"
--------------
+--------------------------+-----------+
| Variable_name | Value |
+--------------------------+-----------+
| innodb_file_format | Barracuda |
| innodb_file_format_check | ON |
| innodb_file_format_max | Barracuda |
| innodb_file_per_table | ON |
+--------------------------+-----------+
4 rows in set (0.00 sec)
I then go ahead and create my table for testing
CREATE TABLE `test` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`dyn` blob,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
I then try to insert
insert into test(`dyn`) VALUES (COLUMN_CREATE(1, "black", 3, "Linux"))
I get the following error:
FUNCTION db.COLUMN_CREATE does not exist
So my question is does mysql not offer these functions? Should I switch to mariadb for testing?
Based on the documentation, it seems that MySQL does not offer this feature.
The dynamic row format actually offers a different method for storing rows that may be more efficient in some cases, not a way to have a variable table schema:
When innodb_file_format is set to Barracuda and a table is created
with ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED, long column values
are stored fully off-page, and the clustered index record contains
only a 20-byte pointer to the overflow page.
If you need such a flexible schema, check out the entity-attribute-value pattern.