MySQL - повторяющаяся ошибка ввода при попытке добавить новый столбец
У меня есть база данных MySQL с таблицей, которая содержит 2 миллиона строк с использованием механизма innodb. Я хочу добавить еще один столбец, но я продолжаю получать следующую ошибку:
Error 1062: Duplicate entry '' for key 'PRIMARY' SQL Statement: ALTER TABLE `mydb`.`table` ADD COLUMN `country` VARCHAR(35) NULL DEFAULT NULL AFTER `email`
Как добавить столбец без получения этой ошибки?
EDIT: Определение таблицы
id int(11) NOT NULL AUTO_INCREMENT,
user_id varchar(45) NOT NULL,
first_name varchar(150) DEFAULT NULL,
last_name varchar(150) DEFAULT NULL,
gender varchar(10) DEFAULT NULL,
email varchar(100) DEFAULT NULL,
created_at bigint(20) DEFAULT NULL,
updated_at bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`,`user_id`),
UNIQUE KEY `user_id_UNIQUE` (`user_id`),
KEY `first_name` (`first_name`),
KEY `last_name` (`last_name`)
РЕДАКТИРОВАТЬ № 2: ВЫСТАВИТЬ ВЫВОДЫ
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Index_type
table 0 PRIMARY 1 id A 3516446 BTREE
table 0 PRIMARY 2 user_id A 3516446 BTREE
table 0 user_id_UNIQUE 1 user_id A 3516446 BTREE
table 1 first_name 1 first_name A 390716 BTREE
table 1 last_name 1 last_name A 439555 BTREE
Ответы
Ответ 1
Если это не то, что нужно сделать программе (динамически меняя таблицы), то просто подождите, а затем повторите попытку! Это сработало для меня.:) Я предполагаю, что есть некоторые специфичные для InnoDB процессы/состояния (возможно, все еще обрабатывается еще один ALTER, запрошенный всего лишь минуту назад?), В течение которого команда ALTER выйдет из строя, и вам просто нужно уловить момент, когда она преуспеет.
Ответ 2
Это решение блокирует таблицу при записи, но часто подходит для решения проблемы, если таблица не очень большая
LOCK TABLES my_table WRITE;
ALTER TABLE my_table
ADD COLUMN 'ts' DATETIME NULL AFTER 'id';
UNLOCK TABLES;
Ответ 3
При выполнении онлайн-операции ALTER TABLE поток, выполняющий операцию ALTER TABLE, будет применять "онлайн-журнал" операций DML, которые одновременно выполнялись в одной таблице из других потоков соединений. Когда применяются операции DML, можно встретить дублируемую ошибку ввода ключа (ERROR 1062 (23000): Дублировать запись), даже если дублирующаяся запись является временной и будет отменена более поздней записью в "онлайн-журнале", Это похоже на идею проверки ограничения внешнего ключа в InnoDB, в которой ограничения должны выполняться во время транзакции.
Ответ 4
Я запустил тот же код, и он отлично работает.
http://sqlfiddle.com/#!2/1937e
В качестве решения я попытался бы воссоздать таблицу, скопировать данные в нее, а затем переключить таблицы с помощью переименования.
- Если этот не работает, тогда он очистит его от вашей текущей конфигурации mysql, и нам понадобится дополнительная информация, чтобы понять это или, по крайней мере, воспроизвести его (версия mysql, mysql config, настройки базы данных, фактические данные и т.д.).
- Если он работает, то это, вероятно, проблема с таблицами или индексами, и вот несколько вещей, которые вы можете проверить (вы также можете начать с них, если не хотите воссоздавать таблицу):
- Убедитесь, что у вас нет триггеров, вызывающих другие вставки
- Убедитесь, что вы просто создаете столбец и не добавляете другие клавиши/индексы
- Убедитесь, что значение auto_increment не переполнено (для int более 2 000 000 000)
Если ничего из вышеизложенного, то, вероятно, у вас есть некоторые поврежденные данные, или вы пропустили поделиться некоторыми сведениями.
Ответ 5
Я думаю, есть еще некоторые ALTERs или INSERT, которые все еще обрабатываются.
Во-первых, чтобы проверить триггеры обработки с помощью следующих запросов:
SHOW FULL PROCESSLIST;
SELECT * FROM information_schema.INNODB_TRX\G
Затем убейте заблокированный запрос с помощью trx_mysql_thread_id: 132092, например:
KILL 132092;
Наконец, вот решение - OnlineSchemaChange (OSC). Он построил Facebook, поддерживает интерактивную альтернативную схему таблиц MySQL с минимальным воздействием.
Ответ 6
использовать столбец изменений
ALTER TABLE database
. table_name
CHANGE COLUMN id
id
INT (11) NOT NULL AUTO_INCREMENT,
ДОБАВИТЬ ПЕРВИЧНЫЙ КЛЮЧ (id
);