14.5.4 Phantom Rows 幻影行

所谓的幻读问题发生在一个事务 当相同的查询产生不同的结果集在不同的时间。

例如,如果一个SELECT 是执行2次,但是第2次返回的时间不第一次返回不同,行是变换的记录。

假设有一个索引是在child 表的id 列,需要读和锁定表的所有的记录 Id值大于100,

以便更新选择的记录的列

SELECT * FROM child WHERE id > 100 FOR UPDATE;

查询扫描 索引开始从第一个记录 id 是大于100.表包含记录id只有90和102.

如果锁设置在index records 在扫描的范围 不锁定插入到整个gaps(在这种情况下, gap是90到102)

另外的会话可以插入一个新值到表 id值为101.

如果你执行相同的SELECT 在相同的事务,你可能会看到一个新的激励 id值为101(一个幻读)

如果 我们注意 数据集为一个数据项,新的幻读child 会违反事务的隔离原则

以便在事务期间读取到的数据不会改变

CREATE TABLE `child` (
`sn` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
`id` int(16) NOT NULL,
`channelType` int(11) DEFAULT NULL COMMENT '通道识别',
`status` tinyint(4) NOT NULL COMMENT '短信转态,1.发送成功,2.发送失败,3.发送异常',
PRIMARY KEY (`sn`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8 COMMENT='短信发送成功记录表'; | 82 | 82 | 2 | 1 |
| 83 | 83 | 2 | 1 |
| 84 | 84 | 2 | 1 |
| 85 | 85 | 2 | 1 |
| 86 | 86 | 2 | 1 |
| 87 | 87 | 2 | 1 |
| 88 | 88 | 2 | 1 |
| 89 | 89 | 2 | 1 |
| 90 | 90 | 2 | 1 |
| 102 | 102 | 2 | 1 |
| 103 | 103 | 2 | 1 |
| 104 | 104 | 2 | 1 mysql> create index child_idx1 on child(id);
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0 Create Table: CREATE TABLE `child` (
`sn` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
`id` int(16) NOT NULL,
`channelType` int(11) DEFAULT NULL COMMENT '通道识别',
`status` tinyint(4) NOT NULL COMMENT '短信转态,1.发送成功,2.发送失败,3.发送异常',
PRIMARY KEY (`sn`),
KEY `child_idx1` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=150 DEFAULT CHARSET=utf8 COMMENT='短信发送成功记录表'
1 row in set (0.00 sec) Session 1: mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM child WHERE id > 100 FOR UPDATE;
+-----+-----+-------------+--------+
| sn | id | channelType | status |
+-----+-----+-------------+--------+
| 120 | 120 | 2 | 1 |
| 121 | 121 | 2 | 1 | Session 2: 此时的区间为[90,无穷) 这个区间记录都无法插入
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> insert into zjzc.child(id,channelType,status) values(1,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.child(id,channelType,status) values(80,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.child(id,channelType,status) values(85,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.child(id,channelType,status) values(87,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.child(id,channelType,status) values(88,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.child(id,channelType,status) values(89,1,1);
Query OK, 1 row affected (0.00 sec) mysql> insert into zjzc.child(id,channelType,status) values(90,1,1); --hang mysql> insert into zjzc.child(id,channelType,status) values(90,1,1); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql>
mysql> insert into zjzc.child(id,channelType,status) values(91,1,1);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> insert into zjzc.child(id,channelType,status) values(101,1,1);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> insert into zjzc.child(id,channelType,status) values(102,1,1);--hang mysql> insert into zjzc.child(id,channelType,status) values(103,1,1);
^CCtrl-C -- sending "KILL QUERY 2" to server ...
Ctrl-C -- query aborted.
^[[AERROR 1317 (70100): Query execution was interrupted
mysql> insert into zjzc.child(id,channelType,status) values(99999999,1,1); 全部锁住 为了防止幻读, InnoDB 使用一个算法叫做 next-key locking 组合了 index-row lock和gap lock. InnoDB 执行 row-level locking 以这样的方式 当他搜索或者扫描一个索引的时候, 它设置 共享或者排他锁 在遇到的index records上。因此, row-level locks are actually index-record locks. 此外,, a next-key lock 在一个Index record 也被称为"gap" 在那个index record 之前。 也就是说,一个next-key lock 是一个index-record lock加上一个区间锁 在index record之前的区间 如果一个session 有一个共享的或者排他的锁在记录R上在一个索引里, 另外的session 不能插入一个新的index 记录在这个区间 在记录R之前 当InnoDB 扫描一个索引,他也会锁定区间在最后的记录后面 就像前面的例子,为了阻止任何插入到表 id值是大于100 , 你可以使用 next-key locking来实现一个唯一性检查在你的应用里, 如果你读取你的数据在共享模式,不想看到重复对于一个你想要插入的记录, 然后呢可以安全的插入你的记录和知道 next-key lock 设置

14.5.4 Phantom Rows 幻影行的更多相关文章

  1. 14.3.4 Phantom Rows 幻影行

    14.3.4 Phantom Rows 幻影行 所谓的幻读为发生在一个事务 当相同的查询产生不同的结果集在不同的时间. 比如,如果一个SELECT被执行2次, 但是第2次返回的记录不是第一次返回的记录 ...

  2. InnoDB 存储引擎的锁机制

    测试环境隔离级别:REPEATABLE-READ 行级别的 - Share and Exclusive Locks 共享锁 S:允许持有S锁的事务对行进行读操作 排他锁 X: 允许持有X锁的事务对行进 ...

  3. 【原创】新说Mysql事务隔离级别

    引言 大家在面试中一定碰到过 说说事务的隔离级别吧? 老实说,事务隔离级别这个问题,无论是校招还是社招,面试官都爱问!然而目前网上很多文章,说句实在话啊,我看了后我都怀疑作者弄懂没!因为他们对可重复读 ...

  4. [51CTO]新说MySQL事务隔离级别!

    新说MySQL事务隔离级别! 事务隔离级别这个问题,无论是校招还是社招,面试官都爱问!然而目前网上很多文章,说句实在话啊,我看了后我都怀疑作者弄懂没!本文所讲大部分内容,皆有官网作为佐证,因此对本文内 ...

  5. 【转】新说Mysql事务隔离级别

    作者:孤独烟 转自:https://www.cnblogs.com/rjzheng/p/9955395.html 引言 大家在面试中一定碰到过 说说事务的隔离级别吧? 老实说,事务隔离级别这个问题,无 ...

  6. Shared and Exclusive Locks 共享和排它锁

    14.5 InnoDB Locking and Transaction Model InnoDB 锁和事务模型 14.5.1 InnoDB Locking 14.5.2 InnoDB Transact ...

  7. mysql 锁2

    官网地址 https://dev.mysql.com/doc/refman/5.5/en/innodb-transaction-isolation-levels.html 这里主要是说事务隔离级别,以 ...

  8. [MySQL Reference Manual]14 InnoDB存储引擎

    14 InnoDB存储引擎 14 InnoDB存储引擎 14.1 InnoDB说明 14.1.1 InnoDB作为默认存储引擎 14.1.1.1 存储引擎的趋势 14.1.1.2 InnoDB变成默认 ...

  9. Mysql事务及行级锁的理解

    在最近的开发中,碰到一个需求签到,每个用户每天只能签到一次,那么怎么去判断某个用户当天是否签到呢?因为当属表设计的时候,每个用户签到一次,即向表中插入一条记录,根据记录的数量和时间来判断用户当天是否签 ...

随机推荐

  1. android 中 ColorDrawable dw = new ColorDrawable(0x3ccccccc),关于颜色定义的总结

    android 中  ColorDrawable dw = new ColorDrawable(0x3ccccccc),关于颜色定义的总结 0x3ccccccc 拆分开来 0x-3c-cccccc   ...

  2. X86(32位)与X64(64位)有什么区别,如何选择对应的操作系统和应用程序?

    X86就是我们一般用的32位的系统,指针长度为32位(386起):X64就是64位的系统,指针长度为64位. 选择硬件对应的软件,建议通过以下三条考虑:1.64位操作系统相对32位操作系统理论上性能会 ...

  3. 【原创教程】一、Angular教程系列之认识angular

    为什么我会准备写这个原创教程系列? 写下这个标题之后,看着屏幕上空白的内容区,不知从何下手,想说的似乎有很多,似乎又没啥说的.有时候就会陷入这种矛盾中,有时候就是这样,于是,我下定决心这一次一定要把这 ...

  4. SVN服务器的搭建 分类: 网络 2014-11-27 01:18 204人阅读 评论(4) 收藏

    一.首先来下载和安装SVN服务器 现在Subversion已经迁移到apache网站上了,下载地址: http://subversion.apache.org/packages.html 这是二进制文 ...

  5. 3DTouch

    3DTouch 一.主屏按压(Home Screen Quik Actions) 1.静态标签 在info.plist文件中新增项 关键字 意义 UIApplicationShortcutItems ...

  6. React学习笔记(三) 组件传值

    组件嵌套后,父组件怎么向子组件发送数据呢? 答案是: this.props <script type="text/babel"> var MyFirst = React ...

  7. PHP设计模式之:外观模式

    外观模式: 外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用: 外观模式又称为门面模 ...

  8. sharepoint给文档库每个数据条添加权限

    前言 老大任务,做一个读取文档库把里面的每一条数据添加权限.挺起来很简单,但是做起来,还是很简单,哈哈.因为我没有接触过这些代码,所以得不断的请教了.大题明白了,简单实现了一下,应用控制台先做了一下简 ...

  9. JavaScript学习总结【6】、JS BOM

    1.BOM 简介 所谓的 BOM 即浏览器对象模型(Browser Object Model).BOM 赋予了 JS 操作浏览器的能力,即 window 操作.DOM 则用于创建删除节点,操作 HTM ...

  10. Python Standard Library 学习(一) -- Built-in Functions 内建函数

    内建函数列表 Built-in Functions abs() divmod() input() open() staticmethod() all() enumerate() int() ord() ...