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 ...
随机推荐
- [UI] 06 - jQuery
前言 From : http://www.runoob.com/jquery/jquery-intro.html Ref: jQuery 实例 一.什么是 jQuery ? jQuery是一个Java ...
- 【代码审计】OTCMS_PHP_V2.83_代码执行漏洞分析
0x00 环境准备 OTCMS官网:http://otcms.com 网站源码版本:网钛CMS PHP版 V2.83 [更新于2017.12.31] 程序源码下载:http://d.otcms.c ...
- OSG描边特效osgFX::Outline的修改
对一个三维场景中的物体实现描边特效,可以参考osg范例osgoutline 这个描边特效使用了模板缓存Stencil来实现,参见源代码osgFX/Outline.cpp 使用了两个Pass 第一个Pa ...
- redis如何后台启动
当安装好redis之后,运行redis-server命令之后,显示如图所示: 但是这样没有办法在这个tab下做任何操作了,因为这个时候使用Ctrl+c之后,就变成了这个样子 然后就关闭了,那么我想让r ...
- Java Debugging with Eclipse - Tutorial
1.1. What is debugging? Debugging allows you to run a program interactively while watching the sourc ...
- 《Thinkphp5使用Socket服务》 入门篇
上车啦!!! 今天来说一下thinkphp5.0下使用wokerman的socket服务. 安装: composer的安装方法,Windows下直接下个composer的应用程序,双击安装,环境变量同 ...
- Mongodb----整理
----------------------------------------------------------------------------------mongodb基本操作------- ...
- nvidia-smi failed because it couldn't communicate with the nvidia driver
Ubuntu装好CUDA之后过段时间提示NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. NV ...
- vim与程序员 vi/vim 的使用
vim与程序员 所有的 Unix Like 系统都会内建 vi 文书编辑器,其他的文书编辑器则不一定会存在. 但是目前我们使用比较多的是 vim 编辑器. vim 具有程序编辑的能力,可以主动的以 ...
- java虚拟机学习
//20181129 ·Java虚拟机的内存分为三个部分:栈stack.堆heap.方法区method area----包含在“堆”里面,因为作用特殊所以单独列出来 ·栈的特点: 栈描述的是方 ...