InnoDB自增列重复值问题
2016-05-09 11:27
309 查看
InnoDB自增列重复值问题
问题重现先从问题入手,重现下这个bug
use test; drop table if exists t1; create table t1(id int auto_increment, a int, primary key (id)) engine=innodb; insert into t1 values (1,2); insert into t1 values (null,2); insert into t1 values (null,2); select * from t1; +----+------+ | id | a | +----+------+ | 1 | 2 | | 2 | 2 | | 3 | 2 | +----+------+ delete from t1 where id=2; delete from t1 where id=3; select * from t1; +----+------+ | id | a | +----+------+ | 1 | 2 | +----+------+
这里我们关闭mysql,再启动mysql,然后再插入一条数据
insert into t1 values (null,2); select * FROM T1; +----+------+ | id | a | +----+------+ | 1 | 2 | +----+------+ | 2 | 2 | +----+------+
我们看到插入了(2,2),而如果我没有重启,插入同样数据我们得到的应该是(4,2)。 上面的测试反映了mysqld重启后,InnoDB存储引擎的表自增id可能出现重复利用的情况。
自增id重复利用在某些场景下会出现问题。依然用上面的例子,假设t1有个历史表t1_history用来存t1表的历史数据,那么mysqld重启前,ti_history中可能已经有了(2,2)这条数据,而重启后我们又插入了(2,2),当新插入的(2,2)迁移到历史表时,会违反主键约束。
原因分析
InnoDB 自增列出现重复值的原因
mysql> show create table t1\G; *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `a` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=innodb AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 1 row in set (0.00 sec)
建表时可以指定 AUTO_INCREMENT值,不指定时默认为1,这个值表示当前自增列的起始值大小,如果新插入的数据没有指定自增列的值,那么自增列的值即为这个起始值。对于InnoDB表,这个值没有持久到文件中。而是存在内存中(dict_table_struct.autoinc)。那么又问,既然这个值没有持久下来,为什么我们每次插入新的值后, show create table t1看到AUTO_INCREMENT值是跟随变化的。其实show create table t1是直接从dict_table_struct.autoinc取得的(ha_innobase::update_create_info)。
知道了AUTO_INCREMENT是实时存储内存中的。那么,mysqld 重启后,从哪里得到AUTO_INCREMENT呢? 内存值肯定是丢失了。实际上mysql采用执行类似select max(id)+1 from t1;方法来得到AUTO_INCREMENT。而这种方法就是造成自增id重复的原因。
MyISAM自增值
MyISAM也有这个问题吗?MyISAM是没有这个问题的。myisam会将这个值实时存储在.MYI文件中(mi_state_info_write)。mysqld重起后会从.MYI中读取AUTO_INCREMENT值(mi_state_info_read)。因此,MyISAM表重启是不会出现自增id重复的问题。
问题修复
相关文章推荐
- Qt元对象系统(二)【根据moc文件解析Q_OBJECT】
- 在ASP.NET 2.0中操作数据之三十二:数据控件的嵌套
- Python正则表达式
- centos各版本含义
- java.util.concurrent.Exchanger应用范例与原理浅析--转载
- 凸包模版 HDU1392 Surround the Trees
- AppCan + 腾讯浏览服务:更快的APP
- 日志减肥
- Xcode绘制图片水印
- Android中的DatePicker颜色处理以及其他属性介绍
- FPGA基础知识0(查找表LUT和编程方式)
- git clone分支
- 大脑皮质网络中社区内和社区间同步与相关性的竞争|Competition between intra-community and inter-community synchronization...
- [VS+OpenCV] 程序运行过程正常,当跳出函数是出现断言错误
- 测试的艺术--通用测试案例篇(一)
- cglib 代理
- redux react-redux
- 一个面试大牛的经历
- lable上显示不同的字体颜色
- Mysql与Oracle的区别