`
wx1569063608
  • 浏览: 22727 次
文章分类
社区版块
存档分类
最新评论

UPDATE 时主键冲突引发的思考

 
阅读更多
作/译者:叶金荣(Email: 13132456_ZIg8.gif),来源:http://imysql.cn,转载请注明作/译者和出处,并且不能用于商业用途,违者必究。
假设有一个表,结构如下:
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条记录更新成功了,后面的则失败,因为第三条记录如果也要更新,则会引发主键冲突。
这个时候,如果我们在更新时增加 ORDER BY 的话,则可以顺利更新成功。
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 的顺序来更新了,因此不会报错。
本文出自 “MySQL中文网”博客 http://www.imysql.cn/
 

本文出自 “老叶茶馆” 博客,转载请与作者联系!

转载于:https://my.oschina.net/yejr/blog/878650

分享到:
评论

相关推荐

    mysql双主主键冲突处理办法.docx

    然而,当使用双主主键(即复合主键,由两个或更多列组成的主键)时,由于网络延迟或同步问题,可能会导致主键冲突。以下是一些处理这种冲突的方法: 1. **查找冲突数据**: 你可以通过 SQL 查询来检查表中是否存在...

    EclipseSVN冲突详细解决方案.docx

    EclipseSVN冲突解决方案是指在使用Eclipse和SVN进行版本控制时,如何处理文件冲突的问题。文件冲突是指多个开发者同时修改同一个文件,导致文件内容不同步的情况。 在EclipseSVN中,文件冲突可能会导致以下情况: ...

    sql数据库,建立表,主键,和insert及update

    根据提供的文件信息,我们可以深入探讨以下几个关键知识点:SQL数据库、创建表、定义主键、以及INSERT和UPDATE操作。 ### SQL数据库概述 SQL(Structured Query Language)是一种专门用于管理关系型数据库的标准...

    打开和关闭主键(VB6.0代码编写)

    通常,当你想要插入大量数据并避免主键冲突时,可以设置CursorType为adOpenBatchInput(批处理输入模式),这样在插入数据时不会立即检查主键约束: ```vb Dim rs As New ADODB.Recordset rs.CursorLocation = ...

    使用ODI处理没有主键的表全攻略

    - 在自定义JKM时,需要考虑数据一致性,防止并发操作带来的数据丢失或冲突。 总结,处理没有主键的表需要根据实际情况选择合适的策略,通常结合业务逻辑和数据特性进行调整。在ODI中,虽然缺乏主键会带来挑战,但...

    JPA_5_联合主键

    使用联合主键的实体在进行CRUD(Create, Read, Update, Delete)操作时,需要注意以下几点: - **创建**:在创建新的实体时,必须为联合主键的所有字段提供值。 - **查询**:查询通常基于联合主键的所有字段进行,...

    生成UPDATE语句

    本篇文章将详细介绍如何根据指定的表结构来生成更新语句(UPDATE SQL),并特别关注基于主键更新的情况。这在Oracle数据库管理与开发中是一项非常实用的技术,尤其对于那些需要频繁更新数据库记录的应用场景来说更是...

    hibernate联合主键全攻略

    在探讨Hibernate中联合主键的使用时,我们首先需要理解什么是联合主键以及它在Hibernate框架中的实现方式。联合主键(Composite Primary Key),是指在数据库表中使用两个或多个字段共同作为主键来唯一标识每一行...

    FixUpdate与Update的区别1

    Update 函数是 Unity 中的一个特殊函数,它将在每帧渲染时被调用。这个函数通常用于更新游戏对象的状态、处理用户输入、进行碰撞检测等。在 Update 函数中,我们可以访问和修改游戏对象的各种属性,例如位置、旋转、...

    Windows更新WindowsUpdate重置工具Reset-WindowsUpdate.rar

    在Windows操作系统中,Windows Update是一项重要的服务,它负责为系统提供最新的安全补丁、功能更新以及驱动程序。然而,有时Windows Update可能会遇到问题,导致更新无法正常进行或更新过程失败。在这种情况下,...

    SQLITE数据库 UPDATE慢

    当多用户同时更新同一数据时,会引发等待和锁冲突。合理规划并发访问,或者在设计数据库时考虑并发控制,有助于减轻锁竞争。 6. **查询优化**:优化UPDATE语句本身也是提升性能的关键。避免在WHERE子句中使用复杂的...

    oracle数据库主键自动生成

    在 Oracle 数据库中,主键自动生成是指在插入数据时自动生成唯一的主键值,从而简化数据录入和维护工作。下面将详细介绍 Oracle 数据库主键自动生成的实现方法和相关知识点。 序列(Sequence) 序列是一种数据库...

    Oracle数据库中主键的智能生成.pdf

    在Oracle数据库中,主键是表的一个或多个字段,用于唯一标识表中的每...在处理并发插入时,还需要考虑锁定机制以防止主键冲突。这种方案虽然需要额外的编程工作,但在大型企业级应用中能有效保证数据的一致性和完整性。

    mysql如何实现 如果存在就update更新,不存在再insert插入.zip

    然而,当我们添加`ON DUPLICATE KEY UPDATE`子句时,它会在尝试插入的行存在唯一索引冲突时执行更新。这通常与主键或唯一约束相关联。例如: ```sql INSERT INTO table_name (column1, column2, ...) VALUES (value...

    WindowsUpdate修复工具.zip

    在使用Windows操作系统时,Windows Update是一项至关重要的服务,它负责为系统提供安全更新、功能增强以及驱动程序的更新。然而,有时Windows Update可能会遇到问题,导致无法正常运行。"WindowsUpdate修复工具.zip...

    eos开发中的联合主键使用

    当单一字段无法唯一标识一条记录时,就需要使用联合主键。例如,一个用户可能有多个账户,每个账户都有用户名和账户类型,那么在这种情况下,可以将“用户名”和“账户类型”作为联合主键,确保每条记录的唯一性。 ...

    sqoop重编译版本,解决了联合主键的同步问题

    原生的sqoop在迁移联合主键的表至hive时,只能识别一个主键,导致数据覆盖。本资源是把sqoop的源码按照官方推荐的issue解决方案重新编译后的版本。sqoop-1.4.7.bin__hadoop-2.6.0-2020.0508.tar.gz是已完成编译的tar...

    for_update_和_for_update_nowait_的区别

    当执行包含`FOR UPDATE`子句的`SELECT`语句时,Oracle会在所选择的行上放置排他锁(exclusive lock),即X锁,这种锁允许持有者读写数据,但阻止其他事务读写相同的行,直到原事务结束(通常是指提交或回滚)。...

    oracle主键自动增长

    触发器是一种特殊类型的存储过程,当特定事件发生时(如INSERT、UPDATE或DELETE操作),会自动执行触发器中的代码。 ##### 创建触发器 创建触发器的基本语法如下: ```sql CREATE [OR REPLACE] TRIGGER 触发器...

    SVN解决冲突(合并别人的修改)

    当两个开发者对同一文件的不同部分做了更改并试图提交到版本库时,SVN会标记出这些冲突,要求开发者手动解决。本文将详细介绍SVN中解决冲突、合并他人修改的过程,特别是对初学者来说,这些内容非常重要。 首先,让...

Global site tag (gtag.js) - Google Analytics