自增ID出现Duplicate entry ‘xxx’ for key
http://www.chinaunix.net 作者:乱.码 发表于:2008-04-26 17:06:23 【发表评论】【查看原文】【MySQL讨论区】【关闭】
MyISAM表结构,发现如果程序经常的insert数据,时间长了后就会出现Duplicate entry ‘xxx’ for key… 的问题,repair表后就回复正常了,ID是autoincrement的,也没有重复的键值,只有一个程序对其进行insert操作,不知道是不是Myisam引擎本身的问题呢?
这种问题是没有规律的,不一定什么时候就出现了,不过一般是数据量比较大的时候,比如达到6位数出现的几率就多了一点。
chouy 回复于:2008-04-17 15:17:29
引用:原帖由 乱.码 于 2008-4-17 14:52 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=8232262&ptid=1081926]
MyISAM表结构,发现如果程序经常的insert数据,时间长了后就会出现Duplicate entry ‘xxx’ for key… 的问题,repair表后就回复正常了,ID是autoincrement的,也没有重复的键值,只有一个程序对其进行insert操 …
我这里也出现了同样的问题:
一个表主键是 auto_increment 的 int, 测试发现这个表的数据很长时间没有更新, 查看发现:
max(id) 是 126, 然后 insert 一条数据报 duplicate key of ‘127’, 但在 select * 表时并没有 ID 为 127 这条数据.
重启 mysql 服务, 问题依旧. 插入一条 id = 150 的数据成功, 但 mysql 自己还是不能增加数据, 继续报错.
于是 mysqlcheck 了一个这个表, 问题解决.
我知道 myisam 这种存储引挚是有些问题, 经常会出错, 但我想问问这种问题出现的几率, mysqlcheck 是否可以百分百修复这个问题.
求高人指教.
yueliangdao0608 回复于:2008-04-17 15:46:14
坛子上讨论很多了。
设置
auto_increment_increment
和
auto_increment_offset
的值。
乱.码 回复于:2008-04-17 16:00:16
引用:原帖由 yueliangdao0608 于 2008-4-17 15:46 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=8232713&ptid=1081926]
坛子上讨论很多了。
设置
auto_increment_increment
和
auto_increment_offset
的值。
我这只有一个mysql服务器 不存在服务器的复制、同步等问题 设这有用嘛
yueliangdao0608 回复于:2008-04-17 16:01:19
RESET MASETER
重新设置一下你的SLAVE
乱.码 回复于:2008-04-17 16:09:24
引用:原帖由 yueliangdao0608 于 2008-4-17 16:01 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=8232896&ptid=1081926]
RESET MASETER
重新设置一下你的SLAVE
我这只有一个mysql服务器 也就是一个数据库 不存在主从的问题:em14:
yueliangdao0608 回复于:2008-04-17 16:24:27
不好意思,没有看清楚。
贴你的表结构看看。
还有你的版本
乱.码 回复于:2008-04-17 16:40:58
mysql> desc Syslog;
+——-+————–+——+—–+——————-+—————-+
| Field | Type | Null | Key | Default | Extra |
+——-+————–+——+—–+——————-+—————-+
| id | int(11) | | PRI | NULL | auto_increment |
| fac | tinyint(4) | | MUL | 0 | |
| pri | tinyint(4) | | MUL | 0 | |
| host | varchar(64) | YES | | NULL | |
| time | timestamp | YES | MUL | CURRENT_TIMESTAMP | |
| msg | varchar(255) | YES | | NULL | |
+——-+————–+——+—–+——————-+—————-+
5.0.18
chouy 回复于:2008-04-17 17:36:32
我的建库语句:
CREATE TABLE `sys_log` (
`log_id` int(11) NOT NULL AUTO_INCREMENT,
`log_type` enum(‘1′,’2′,’3′,’4’) NOT NULL DEFAULT ‘1’,
`log_level` enum(‘1′,’2′,’3’) NOT NULL DEFAULT ‘1’,
`log_time` varchar(14) NOT NULL DEFAULT ”,
`log_content` text NOT NULL,
`report_flag` enum(‘0′,’1’) NOT NULL DEFAULT ‘0’,
PRIMARY KEY (`log_id`)
) ENGINE=MyISAM AUTO_INCREMENT=26832 DEFAULT CHARSET=latin1
数据库版本:
5.0.21-community
我的数据库也是只有一个库, 没有主从和同步关系.
[ 本帖最后由 chouy 于 2008-4-17 17:38 编辑 ]
猪知猪之道 回复于:2008-04-17 17:36:39
引用:原帖由 乱.码 于 2008-4-17 16:40 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=8233381&ptid=1081926]
mysql> desc Syslog;
+——-+————–+——+—–+——————-+—————-+
| Field | Type | Null | Key | Default | Extra |
+——-+———– …
show create table Syslog 出来看看
乱.码 回复于:2008-04-17 17:41:27
show create table Syslog;
| Syslog | CREATE TABLE `Syslog` (
`id` int(11) NOT NULL auto_increment,
`fac` tinyint(4) NOT NULL default ‘0’,
`pri` tinyint(4) NOT NULL default ‘0’,
`host` varchar(64) default NULL,
`time` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
`msg` varchar(255) default NULL,
PRIMARY KEY (`id`),
KEY `priSyslog` (`pri`),
KEY `facSyslog` (`fac`),
KEY `timeSyslog` (`time`),
FULLTEXT KEY `msg` (`msg`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
后面3个KEY因为在上面建立了索引常用于查询 正考虑给删了 否则应该会影响插入效率吧 但不至于是问题所在吧
猪知猪之道 回复于:2008-04-17 17:47:17
下次出这样的问题建议你
analyze table Syslog; 看表到底有错误没
select MAX(id) from Syslog; 检查ID
show create table Syslog;
看 ) ENGINE=MyISAM AUTO_INCREMENT=1028 DEFAULT CHARSET=latin1 | 表最后的这个ID
乱.码 回复于:2008-04-18 10:33:35
引用:原帖由 猪知猪之道 于 2008-4-17 17:47 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=8234271&ptid=1081926]
下次出这样的问题建议你
analyze table Syslog; 看表到底有错误没
select MAX(id) from Syslog; 检查ID
show create table Syslog;
看 ) ENGINE=MyISAM AUTO_INCREMENT=1028 DEFAULT CHARSET=latin1 | …
出问题的时候我用了check 列出了类似这样的错误:
error | Found xxxx keys of yyyy
error | corrupt
其中xxxx != yyyy
select max(id) from Syslog;
返回的值也不等于 最后一条记录的ID
cocolala 回复于:2008-04-24 00:01:01
看来这个问题确实比较古怪,mysqlcheck 能解决它,不知道它做了什么事? 🙂
看了手册,只知道如果auto_increment列值达到了列的类型的最大值,那么下一次insert时,因为超出范围,mysql会用最大值赋值给auto increment计数器及列值,这时会与前面已经存在的记录冲突,报’duplicate key’
参见http://blog.chinaunix.net/u2/67276/showart_574312.html
int类型最大值上了10位数了,楼主是6位数时就出错,奇怪了!
yueliangdao0608 回复于:2008-04-24 09:12:09
引用:原帖由 cocolala 于 2008-4-24 00:01 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=8268513&ptid=1081926]
看来这个问题确实比较古怪,mysqlcheck 能解决它,不知道它做了什么事? 🙂
看了手册,只知道如果auto_increment列值达到了列的类型的最大值,那么下一次insert时,因为超出范围,mysql会用最大值赋值给auto in …
有符号的11位,无符号的10位。
这个的确有点可能,不过单表的记录超过亿了。我觉得是不是应该分一下表了。
cocolala 回复于:2008-04-24 11:26:09
引用:原帖由 乱.码 于 2008-4-18 10:33 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=8237154&ptid=1081926]
出问题的时候我用了check 列出了类似这样的错误:
error | Found xxxx keys of yyyy
error | corrupt
其中xxxx != yyyy
select max(id) from Syslog;
返回的值也不等于 最后一条记录的ID
看你mysqlcheck的结果,可知应该是因为mysql表损坏导致这种情况.
当指定插入127这个值时,mysql发现key中已经存在(可能是因为之前在insert时,刚好在127这个地方出问题了,更新key文件ok,但更新数据文件失败).根据约束规则,所以报duplicate key错误;
yueliangdao0608 回复于:2008-04-24 12:39:15
最直接的办法就是导出所有数据,然后导入
乱.码 回复于:2008-04-25 09:26:46
这个问题我实在没搞清楚为什么会出现,也不明白为什么会无缘无故出现表损坏的情况,难道myisam经常出现这个问题?不清楚。
因为我并非手动插入数据,而是有个C程序持续的往里写数据,并且是单进程、单线程的,绝对不会同时有两个session往里写数据,id字段,int类型,也就是auto_increment字段也是不指定的,让其自动增长,可就是当数据量达到6位数时就会出现这个问题,执行表修复就正常了,之后偶尔也会出现。
yueliangdao0608 回复于:2008-04-25 09:53:40
引用:原帖由 乱.码 于 2008-4-25 09:26 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=8276246&ptid=1081926]
这个问题我实在没搞清楚为什么会出现,也不明白为什么会无缘无故出现表损坏的情况,难道myisam经常出现这个问题?不清楚。
因为我并非手动插入数据,而是有个C程序持续的往里写数据,并且是单进程、单线程的, …
六位数?
你确定你的自增字段类型不是MEDIUMINT的?
乱.码 回复于:2008-04-25 10:22:55
引用:原帖由 yueliangdao0608 于 2008-4-25 09:53 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=8276460&ptid=1081926]
六位数?
你确定你的自增字段类型不是MEDIUMINT的?
不是 定义的int 系统识别的应该是int(11)
不是一到6位数就OVER了 比如有时是123456条记录OVER 有时是654321条记录OVER 我说的意思就是说在6位数时候比较常见:mrgreen:
sunnyfun 回复于:2008-04-25 12:51:12
可能连续写表写得太狠了吧,可以试试这样:
锁表→写个几百条→解锁→歇一会
如此循环。
yueliangdao0608 回复于:2008-04-25 13:11:03
如果写太多的话,还是建议换成INNODB引擎。
乱.码 回复于:2008-04-25 13:44:54
嗯,因为是应用程序的日志表,所以写会频繁些,偶尔会查询,不会很多,我也觉得应该改成INNODB引擎。
谢谢各位的回复:)
huifeideluotuo 回复于:2008-04-26 17:06:23
如果你是关键应用,机器性能不是很好(不经常死机)的情况下,我也推荐你用INNODB引擎,因为MYISAM引擎,在非法关闭mysql的时候,出现表损坏,虽然可以修复,但是以后还会出现,如果你对mysql性能不是特别苛刻,建议你用mysql官方提供的已经编译好的二进制版本。:wink: