MySQL - 尝试添加新列时出现重复输入错误

时间:2014-03-22 16:48:07

标签: mysql alter-table

我有一个MySQL数据库,其中包含一个使用innodb引擎的200万行的表。我想添加另一列,但我不断收到以下错误:

Error 1062: Duplicate entry '' for key 'PRIMARY' SQL Statement: ALTER TABLE `mydb`.`table`  ADD COLUMN `country` VARCHAR(35) NULL DEFAULT NULL AFTER `email` 

如何在不收到此错误的情况下添加列?

编辑:表格定义

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: SHOW INDEXES输出

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

7 个答案:

答案 0 :(得分:9)

它的解决方案会在写入时锁定表,但如果表格不是很大则通常适合解决问题

LOCK TABLES my_table WRITE;

ALTER TABLE my_table 
ADD COLUMN `ts` DATETIME NULL AFTER `id`;

UNLOCK TABLES;

答案 1 :(得分:8)

如果它不是程序需要做的事情(动态地改变表格),那么稍等片刻然后再试一次!它对我有用。 :)我猜有一些特定于InnoDB的进程/状态(可能还在刚刚处理的另一个ALTER处理?),在此期间ALTER命令会失败,你只需要抓住它成功的时刻。

答案 2 :(得分:3)

运行在线ALTER TABLE操作时,运行ALTER TABLE操作的线程将应用从其他连接线程在同一个表上并发运行的DML操作的“在线日志”。应用DML操作时,可能会遇到重复的键输入错误(ERROR 1062(23000):重复输入),即使重复的条目只是临时的,并且将被“在线日志”中的后续条目还原。这类似于InnoDB中的外键约束检查的想法,其中约束必须在事务期间保持。

答案 3 :(得分:1)

我运行了相同的代码并且运行正常。 http://sqlfiddle.com/#!2/1937e

作为解决方案,我会尝试重新创建表,将数据复制到表中,然后使用重命名切换表。

  • 如果无法正常工作,那么很明显它是您当前mysql配置的一个错误,我们需要更多详细信息来确定它输出或至少重现它(mysql版本,mysql配置,数据库设置,实际数据等)。
  • 如果它有效那么它可能是表或索引的问题,这里有一些你可以检查的东西(如果你不想重新创建,你也可以从这些开始表):
    1. 检查您是否有任何导致其他插入的触发器
    2. 检查您是否只是创建了一个列而不是添加其他键/索引
    3. 检查auto_increment值是否溢出(因为它超过2,000,000,000)

如果以上都不是,那么您可能有一些损坏的数据,或者您错过了分享一些细节。

答案 4 :(得分:1)

我猜还有一些其他ALTER或INSERT仍在处理中。

首先,使用以下查询检查处理触发器:

SHOW FULL PROCESSLIST;
SELECT * FROM information_schema.INNODB_TRX\G

然后,通过trx_mysql_thread_id:132092杀死锁定的查询,例如:

KILL 132092;

最后,这是一个解决方案 - OnlineSchemaChange (OSC)。它由Facebook构建,支持在线改变MySQL表模式,影响最小。

答案 5 :(得分:0)

使用更改列

ALTER TABLE table_nameid CHANGE COLUMN id id INT(11)NOT NULL AUTO_INCREMENT, 添加PRIMARY KEY({{1}});

答案 6 :(得分:0)

使用percona toolkit更改数据库方案而无需锁定表:https://www.percona.com/doc/percona-toolkit/3.0/pt-online-schema-change.html

这允许在应用方案更改时继续更新db。这对于大型DB尤其有用,因为大型DB的更新方案可能需要一段时间。