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 ...
随机推荐
- 理解AppDomain
在传统的 Win32的程序中,进程是独立的运行空间, 在一些大型系统中, 通常都是将系统中的核心功能分解出来用独立的进程来处理,一方面是为了能获得更高的系统性能.吞吐量 .另一方面是为了能隔离功能之间 ...
- 【代码审计】YzmCMS_PHP_v3.6 CSRF漏洞分析
0x00 环境准备 YzmCMS官网:http://www.yzmcms.com/ 程序源码下载:http://pan.baidu.com/s/1pKA4u99 测试网站首页: 0x01 代码分析 ...
- VS 2013 未找到与约束contractname Microsoft.VisualStudio.Utilities.IContentTypeRegistryService......匹配的导出
错误信息: 点击解决方案中的文件,就会提示这个错误.最近给vs2013安装了python的插件,安装了vs2017的python,可能是这两个导致了这个错误. 解决方案: 删除 C:\Users\ji ...
- IDEA导入springboot项目不能启动
由于工具没有识别到项目的pom.xml文件,所以需要在右侧的Maven栏目中点击 + 号,选中项目的pom.xml文件,则导入成功.
- mui---获取上一级窗口
我们在用MUI做APP的时候,会用到要获取上一级的窗口.具体方法:获取当前webview窗口的创建者. 代码: plus.webview.currentWebview().opener();
- MFC打开文件选择框和多选框,保存文件夹的选择,保存文件路径的选择
CString defaultDir = "C:\\"; //默认打开的文件路径 CString fileName = ""; //默认打开的文件名 CStri ...
- Spring实战系列
作者:arccosxy 转载请注明出处:http://www.cnblogs.com/arccosxy/ 稀里糊涂的做了2年的Java Web后端开发,很多东西连蒙带猜外加百度,也算是完成了几个重要 ...
- poj3080 Blue Jeans【KMP】【暴力】
Blue Jeans Time Limit: 1000MS Memory Limit: 65536K Total Submissions:21746 Accepted: 9653 Descri ...
- <转>记dynamic的一个小坑 -- RuntimeBinderException:“object”未包含“xxx”的定义
→转载地址← 创建一个控制台程序和一个类库, 在控制台创建一个匿名对象,然后再在类库中访问它,代码如下: namespace ConsoleApplication1 { class Program { ...
- [No0000137]字符编码详解
摘要 本文主要介绍了字符编码的基础知识,以及常见的字符编码类型,比如ASCII,Unicode,UTF-8,ISO 8859等,以及各种编码之间的关系,同时专门解释了中文字符相关的编码标准,包括GB2 ...