UPDATE 时主键冲突引发的思考【转】
假设有一个表,结构如下:
root@localhost : yayun 22:59:43> create table t1 (
-> id int unsigned not null auto_increment,
-> id2 int unsigned not null default '',
-> primary key (id)
-> )engine=myisam;
Query OK, 0 rows affected (0.00 sec) root@localhost : yayun 23:01:00>
改表中有6条记录,如下:
root@localhost : yayun 23:03:35> select * from t1;
+----+-----+
| id | id2 |
+----+-----+
| 2 | 2 |
| 3 | 3 |
| 5 | 5 |
| 4 | 4 |
| 6 | 6 |
| 7 | 7 |
+----+-----+
6 rows in set (0.00 sec) root@localhost : yayun 23:03:42>
现在想要把id字段分别-1,执行以下语句,得到报错:
root@localhost : yayun 23:03:42> update t1 set id=id - 1;
ERROR 1062 (23000): Duplicate entry '' for key 'PRIMARY'
root@localhost : yayun 23:04:59>
看看更新后的结果,可以看到:
root@localhost : yayun 23:05:58> select * from t1;
+----+-----+
| id | id2 |
+----+-----+
| 1 | 2 |
| 2 | 3 |
| 5 | 5 |
| 4 | 4 |
| 6 | 6 |
| 7 | 7 |
+----+-----+
6 rows in set (0.00 sec) root@localhost : yayun 23:06:05>
存储在最前面的2条记录更新成功了,后面的则失败,因为第三条记录如果也要更新,则会引发主键冲突。
这个时候,如果我们在更新时增加 ORDER BY 的话,则可以顺利更新成功。
root@localhost : yayun 23:07:52> update t1 set id=id-1 order by id;
Query OK, 6 rows affected (0.00 sec)
Rows matched: 6 Changed: 6 Warnings: 0 root@localhost : yayun 23:08:20>
接下来,我们看看把它转成 innodb 表,结果会是怎样的。
root@localhost : yayun 23:09:21> alter table t1 engine = innodb;
Query OK, 6 rows affected (0.08 sec)
Records: 6 Duplicates: 0 Warnings: 0 root@localhost : yayun 23:09:23>
root@localhost : yayun 23:10:15> select * from t1;
+----+-----+
| id | id2 |
+----+-----+
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
+----+-----+
6 rows in set (0.00 sec) root@localhost : yayun 23:10:19>
看到变化了吧,行数据按照 id 的顺序来显示了。清空后,自己重新手工插入记录,再看看。
root@localhost : yayun 23:11:05> delete from t1;
Query OK, 6 rows affected (0.00 sec) root@localhost : yayun 23:11:28> INSERT INTO `t1` VALUES (2,2),(3,3),(5,5),(4,4),(6,6),(7,7);
Query OK, 6 rows affected (0.09 sec)
Records: 6 Duplicates: 0 Warnings: 0 root@localhost : yayun 23:11:33>
还是按照 id 的顺序来显示,然后我们再次执行之前的 update 语句:
root@localhost : yayun 23:12:03> update t1 set id = id - 1;
Query OK, 6 rows affected (0.03 sec)
Rows matched: 6 Changed: 6 Warnings: 0 root@localhost : yayun 23:12:29>
可以看到,在 innodb 表的情况下,更新是可以成功的。
总结:
myisam表是堆组织表(Heap Organize Table, HOT),它的索引是采用 b-tree 方式存储的,数据显示时是随机顺序,而非按照主键的索引顺序来显示。
而innodb表是索引组织表(Index Organized Table, IOT),它的索引则是采用 clustered index 方式,因此主键会按照顺序存储,每次有记录有更新时,会重新整理更新其主键。因此无论是直接从 myisam 表转换过来的,还是后来插入的记录,显示时都会按照主键的顺序。
更新数据时,如果没有指定排序的字段或索引,则默认以随机顺序更新,所以 myisam 表如果不指定 ORDER BY 的话,则采用默认的存储顺序来更新,所以会发生主键冲突的情况。
而 innodb 表总是有主键(如果没有定义,则也有默认主键),如果更新时没有指定排序字段或索引,则按照主键顺序来更新,在上面的例子中,就是按照主键 id 的顺序来更新了,因此不会报错。
原文地址
http://imysql.com/2008_06_17_sth_about_update_duplicate_key
UPDATE 时主键冲突引发的思考【转】的更多相关文章
- Entity Framework中Remove、Modified实体时,在修改或删除时引发主键冲突的问题
问题: try { string fileId = context.NewsT.Where(t => t.Id == Model.Id).FirstOrDefault().FileId; str ...
- insert时出现主键冲突的处理方法【转载】
原文出处:http://hi.baidu.com/ytjwt/blog/item/1ccc2c26022b0608908f9d8c.html 使用"insert into"语句进行 ...
- sqoop从hive导入数据到mysql时出现主键冲突
今天在将一个hive数仓表导出到mysql数据库时出现进度条一直维持在95%一段时间后提示失败的情况,搞了好久才解决.使用的环境是HUE中的Oozie的workflow任何调用sqoop命令,该死的o ...
- insert时出现主键冲突的处理方法
使用"insert into"语句进行数据库操作时可能遇到主键冲突,用户需要根据应用场景进行忽略或者覆盖等操作.总结下,有三种解决方案来避免出错. 测试表:CREATE TABLE ...
- mysql 主从,主主,主主复制时的主键冲突解决
原理:slave 的i/o thread ,不断的去master抓取 bin_log, 写入到本地relay_log 然后sql thread不断的更新slave的数据 把主服务器所有的数据复制给从服 ...
- mysql修改数据 -- 主键冲突
mysql 插入数据唯一键冲突 前提: 修改数据三种可用的方法解决主键冲突的问题 1. insert into ... on duplicate key update set ... 2. updat ...
- sqlite里执行查询提示未启用约束、主键冲突之——数据竟能超字段长度存储
数据表设计如图:szflbm为主键 数据表主键数据: 以上数据在查询时,执行到该语句adapter.Fill(table); 提示主键冲突. 解决: 1.尝试修改数据,把ZC1改成ZZ,正常.说明原因 ...
- MySql中利用insert into select 准备数据uuid主键冲突
MYSQL 中表1需要准备大量数据,内容主要取自表2,id必须为32位uuid (项目所有表都是这样,没办法), 准备这样插入: INSERT INTO TBL_ONE (ID, SOID, SNAM ...
- sql解决主键冲突
在数据插入的时候,假设主键对应的值已经存在,则插入失败!这就是主键冲突.当主键存在冲突(duplicate key)的时候,可以选择性的进行处理,即忽略.更新或者替换. 1.忽略 insert ign ...
随机推荐
- 如何把大段文字转为带html标签的文字
开发网页的时候,有时候会遇到大段的隐私声明,用户协议等等,我们呀要复制粘贴展示出来,必须加大量的p标签,h1,h2,空格符,br标签,这对我们来说无疑是泪崩的,有个很好的办法,可以快速给这些文字加标签 ...
- react中实现搜索结果中关键词高亮显示
网上看到很多js实现的关键词高亮显示,方法都是一个道理,先获取要替换的文字区域,然后在用正则匹配到关键词,并进行替换. react中实现起来似乎更简单一些. 我这里的需求是通过搜索框搜索出新闻列表,在 ...
- [JS] ECMAScript 6 - Async : compare with c#
一段引言: Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大. 它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对 ...
- JPA实体类中常用的注解
这两天在看黎活明老师的JPA的讲解视频,现在只了解这么多,记录备用. import java.util.Date; import javax.persistence.Basic; import jav ...
- ElasticSearch6(二)-- Java API连接es
此ElasticSearch系列基于最新版的6.2.4版本. 一.pom.xml依赖 <dependencies> <dependency> <groupId>ju ...
- day08 服务
pasting ]注册电话的监听 tm.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE); [4 ...
- 【转】asp.net项目在IE11下出现“__doPostBack”未定义的解决办法
最近我们运营的网站有用户反馈在 IE 11 下<asp:LinkButton> 点击出现 "__doPostBack"未定义",经过一番google,终于知道 ...
- day8 八、文件操作模式、文件的复制与文件游标操作
一.文件操作 1.wr模式结合 ① w = open('1.txt', 'w', encoding='utf-8') # w:没有文件新建文件,有文件就清空文件 w.write('000\n') w. ...
- db2 reorg(转)
DB2 reorg RUNSTATS: db2 connect to rmdb11 user rmadmin using rmadmin 对所有用户表执行runstats(reorgchk加updat ...
- is7.5和iis8文件上传大小限制30M修改方法
C:\Windows\System32\inetsrv\config\schema\ 下的IIS_schema.xml文件,但是考虑到安全等问题,而且这个文件默认是只读的,所以不建议直接修改这个配置文 ...