UPDATE 时主键冲突引发的思考
mysql> CREATE TABLE `a` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`id2` int(10) unsigned NOT NULL DEFAULT '0',PRIMARY KEY (`id`) ) ENGINE=MyISAM;
该表中只有6条记录,如下:
mysql> select * from a; +----+---------+ | id | city_id | +----+---------+ | 2 | 2 | | 3 | 3 | | 5 | 5 | | 4 | 4 | | 6 | 6 | | 7 | 7 | +----+---------+
现在想要把id字段分别-1,执行以下语句,得到报错:
mysql> update a set id=id-1; ERROR 1062 (23000): Duplicate entry '4' for key 'PRIMARY'
看看更新后的结果,可以看到:
mysql> select * from a; +----+---------+ | id | city_id | +----+---------+ | 1 | 2 | | 2 | 3 | | 5 | 5 | | 4 | 4 | | 6 | 6 | | 7 | 7 | +----+---------+
存储在最前面的2条记录更新成功了,后面的则失败,因为第三条记录如果也要更新,则会引发主键冲突。
mysql> update a set id=id-1 order by id; Query OK, 6 rows affected (0.00 sec) Rows matched: 6 Changed: 6 Warnings: 0
接下来,我们看看把它转成 innodb 表,结果会是怎样的。
mysql> alter table a engine = innodb; Query OK, 6 rows affected (0.01 sec) Records: 6 Duplicates: 0 Warnings: 0
mysql> select * from a; +----+---------+ | id | city_id | +----+---------+ | 2 | 2 | | 3 | 3 | | 4 | 4 | | 5 | 5 | | 6 | 6 | | 7 | 7 | +----+---------+
看到变化了吧,行数据按照 id 的顺序来显示了。
清空后,自己重新手工插入记录,再看看。
mysql> INSERT INTO `a` VALUES (2,2),(3,3),(5,5),(4,4),(6,6),(7,7); Query OK, 6 rows affected (0.00 sec) Records: 6 Duplicates: 0 Warnings: 0 mysql> select * from a; +----+---------+ | id | city_id | +----+---------+ | 2 | 2 | | 3 | 3 | | 4 | 4 | | 5 | 5 | | 6 | 6 | | 7 | 7 | +----+---------+
还是按照 id 的顺序来显示,然后我们再次执行之前的 update 语句:
mysql> update a set id = id - 1; Query OK, 6 rows affected (0.00 sec) Rows matched: 6 Changed: 6 Warnings: 0
可以看到,在 innodb 表的情况下,更新是可以成功的。
myisam表是堆组织表(Heap Organize Table, HOT),它的索引是采用 b-tree 方式存储的,数据显示时是随机顺序,而非按照主键的索引顺序来显示。
而innodb表是索引组织表(Index Organized Table, IOT),它的索引则是采用 clustered index 方式,因此主键会按照顺序存储,每次有记录有更新时,会重新整理更新其主键。因此无论是直接从 myisam 表转换过来的,还是后来插入的记录,显示时都会按照主键的顺序。
更新数据时,如果没有指定排序的字段或索引,则默认以随机顺序更新,所以 myisam 表如果不指定 ORDER BY 的话,则采用默认的存储顺序来更新,所以会发生主键冲突的情况。
而 innodb 表总是有主键(如果没有定义,则也有默认主键),如果更新时没有指定排序字段或索引,则按照主键顺序来更新,在上面的例子中,就是按照主键 id 的顺序来更新了,因此不会报错。
UPDATE 时主键冲突引发的思考相关推荐
- mysql主主 主键冲突_mysql主从复制原理,主主复制时主键冲突解决
主从复制原理: 1.master的增删改记录写入binlog: 2.slave的I/O Thread(负责读取master的binlog)读取binlog并将记录写入relaylog: 3.slave ...
- mysql insert 主键冲突_insert 时防止出现主键冲突错误的方法
最近几天,产品上线比较多,从内网测试库导出表的部分内容到线上也就比平时频繁多了,这时候可能会出现主键冲突: Error Code : 1062 Duplicate entry '1' for key ...
- insert时出现主键冲突的处理方法【转载】
原文出处:http://hi.baidu.com/ytjwt/blog/item/1ccc2c26022b0608908f9d8c.html 使用"insert into"语句进行 ...
- sqoop从hive导入数据到mysql时出现主键冲突
今天在将一个hive数仓表导出到mysql数据库时出现进度条一直维持在95%一段时间后提示失败的情况,搞了好久才解决.使用的环境是HUE中的Oozie的workflow任何调用sqoop命令,该死的o ...
- 批量插入数据表数据时,主键冲突的解决
2.使用普通的insert into on conflict合并写入,存在写入放大思路: 大量数据,批量插入到数据表中时,很容易造成主键冲突,重复数据有唯一约束插入不进去表中,报错的问题出现. 排查错 ...
- mysql 主从,主主,主主复制时的主键冲突解决
原理:slave 的i/o thread ,不断的去master抓取 bin_log, 写入到本地relay_log 然后sql thread不断的更新slave的数据 把主服务器所有的数据复制给从服 ...
- django使用postgresql时提示主键冲突
在django使用postgresql数据库时,当你使用默认主键,但当你手动使用添加记录到相关数据库时(非insert操作,如使用navicate直接在表中复制粘贴记录),此时django在插入数据时 ...
- Mysql从库主键卡住_从库宕机引发的主键冲突
刚刚接到报警短信,从库宕机,马上通知机房重启,在检查MySQL时,发现同步挂了,报主键冲突,询问开发是不是有往里面写数据,回答没有.这就奇怪了,怎么会无缘 刚刚接到报警短信,从库宕机,马上通知机房重启 ...
- DB2添加数据时主键、唯一键冲突的解决方法
DB2添加数据时主键.唯一键冲突的解决方法 参考文章: (1)DB2添加数据时主键.唯一键冲突的解决方法 (2)https://www.cnblogs.com/equation/articles/91 ...
最新文章
- 081_Introducing trigger handler class
- linux Fedora搭建hadoop平台总结
- C#如何测试代码运行时间
- JavaScript数组常用的方法总结
- 移动云帮我养出了一片致富鱼塘
- 马云终于露面了!发表千字演讲
- 设置按钮背景为透明去掉button按钮左右两边的留白
- 中rsa非对称加密_HTTP的数据传输中,对称加密和非对称加密的区别是什么?
- combobox的method是get为什么发的请求是post_深入理解http get和post请求的区别,读完之后,大部分程序员收藏了...
- 圈圈教你学USB第一章
- android 反编译 签名,Android反编译及重签名命令
- Javaweb 九大内置对象
- 从C到C++ 番外const的用法
- 希尔伯特的23个数学问题
- 二极管钳位、稳压二极管的应用
- php发邮件附件,PHP使用PHPMailer发送邮件和附件的方法
- 自然语言生成技术现状调查:核心任务、应用和评估(3)
- java中appletviewer是什么意思_自动生成供AppletViewer运行Java Applet的HTML文件
- HDMI传输设备上的ARC和EARC代表哪些功能?
- Knime北京房价工作流建立