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);