测试准备

test库下建表tt

  1. CREATE TABLE `tt` (
  2. `id` int(11) NOT NULL,
  3. `code` int(11) DEFAULT NULL,
  4. `name` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  5. `vers` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  6. `version` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  7. PRIMARY KEY (`id`),
  8. KEY `idx_code` (`code`),
  9. KEY `idx_name` (`name`)
  10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

插入值

  1. INSERT INTO TEST.TT VALUES(1,1,'name1','5.7.11', '7');
  2. INSERT INTO TEST.TT VALUES(2,2,'name2','5.7.12','8');
  3. INSERT INTO TEST.TT VALUES(3,3,'name2','V5.7','9');
  4. INSERT INTO TEST.TT VALUES(4,3,'name4','5.7.15','10');
  5. INSERT INTO TEST.TT VALUES(5,6,'name6','5.7.16','11');
  6. INSERT INTO TEST.TT VALUES(6,7,'name7','v5.7','12');

打开InnoDB锁监控,具体参考https://dev.mysql.com/doc/refman/8.0/en/innodb-enabling-monitors.html:

  1. SET GLOBAL innodb_status_output=ON;
  2. SET GLOBAL innodb_status_output_locks=ON;

RR(repeatable-read)隔离级别

情况一

session1:

  1. sql>begin;
  2. sql>update tt set vers='vsss' where code=3 and name='name2'; ##执行计划是index merge(两个索引联合了)

session2:

  1. sql>update tt set vers='xx' where name='name2' and version=8;
  2. ...等待,直到50s超时

查看show engine innodb status \G

  1. =====================================
  2. 2021-06-10 17:31:37 0x7f2fac9aa700 INNODB MONITOR OUTPUT
  3. =====================================
  4. ...
  5. ...
  6. MySQL thread id 24, OS thread handle 139842735195904, query id 219 localhost root updating
  7. update tt set vers='xx' where name='name2' and version=8
  8. ------- TRX HAS BEEN WAITING 14 SEC FOR THIS LOCK TO BE GRANTED:
  9. RECORD LOCKS space id 34 page no 5 n bits 80 index idx_name of table `test`.`tt` trx id 6977 lock_mode X waiting
  10. Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
  11. 0: len 5; hex 6e616d6532; asc name2;;
  12. 1: len 4; hex 80000002; asc ;;
    ...

结论:上述dml,会话1 update所更改的二级索引值所在的gap范围会加锁,假如会话2更改的行所在的二级索引值在会话1的gap范围,则会话2在会话1的二级索引上等待锁。二级索引会对(单独用该索引)搜索到的行加锁(其他过滤条件不影响加锁行的范围)(此种情况为二级索引情况)

情况二

session1

  1. sql>begin;
  2. sql>update tt set vers='vsss' where code=3 and name<='name2' and name >'name1'; ##执行计划走code索引

session2

  1. sql>update tt set vers='ssss' where name='name2' and version=8; ##执行计划走name索引

查看show engine innodb status \G

  1. =====================================
  2. 2021-06-10 19:44:29 0x7f2fac9aa700 INNODB MONITOR OUTPUT
  3. =====================================
  4. ...
  5. ...
  6. MySQL thread id 26, OS thread handle 139842735736576, query id 252 localhost root updating
  7. update tt set vers='ssss' where name='name2' and version=8
  8. ------- TRX HAS BEEN WAITING 6 SEC FOR THIS LOCK TO BE GRANTED:
  9. RECORD LOCKS space id 34 page no 3 n bits 96 index PRIMARY of table `test`.`tt` trx id 6990 lock_mode X locks rec but not gap waiting
  10. Record lock, heap no 15 PHYSICAL RECORD: n_fields 7; compact format; info bits 0
  11. 0: len 4; hex 80000003; asc ;;
  12. 1: len 6; hex 000000001b4b; asc K;;
  13. 2: len 7; hex 32000001410282; asc 2 A ;;
  14. 3: len 4; hex 80000003; asc ;;
  15. 4: len 5; hex 6e616d6532; asc name2;;
  16. 5: len 4; hex 76737373; asc vsss;;
  17. 6: len 1; hex 39; asc 9;;
    ...

结论:session1和session2采用的是不同索引,索引session2是在等待session1的primary值为9的行记录的锁。(此种情况为主键锁等待)

情况三

修改tt表

  1. sql>update tt set id=10 where code=6;
  2. sql>select * from tt;
  3. +----+------+-------+--------+---------+
  4. | id | code | name | vers | version |
  5. +----+------+-------+--------+---------+
  6. | 1 | 1 | name1 | 5.7.11 | 7 |
  7. | 2 | 2 | name2 | 5.7.12 | 8 |
  8. | 3 | 3 | name2 | V5.7 | 9 |
  9. | 4 | 3 | name4 | 5.7.15 | 10 |
  10. | 6 | 7 | name7 | v5.7 | 12 |
  11. | 10 | 6 | name6 | 5.7.16 | 11 |
  12. +----+------+-------+--------+---------+

session1

  1. sql>begin;
  2. sql>update tt set vers='XXXBB' where code=3;

session2

  1. sql>insert into tt values(5,6,'name99','v5.7.28','13');
  2. ...等待,直到50s超时
  3. sql>insert into tt values(8,6,'name99','v5.7.28','13');
  4. ...等待,直到50s超时
  5. sql>insert into tt values(11,6,'name99','v5.7.28','13');
  6. Query OK, 1 row affected (0.00 sec)

结论:这个范围还跟主键有关

RC(read-commit)隔离级别

情况一

session1

  1. sql>begin;
  2. sql>update tt set vers='vsss' where version='9' and name='name2';

session2

  1. sql>update tt set vers='XXXXXcccc' where name='name2' and version='8';
  2. ...等待,直到50s超时

    sql>update tt force index(idx_name) set vers='XXXXXcccc' where name='name2' and id=2;
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1 Changed: 1 Warnings: 0
    [可以成功执行]

查看show engine innodb status \G

  1. =====================================
  2. 2021-06-10 20:31:13 0x7f58d064d700 INNODB MONITOR OUTPUT
  3. =====================================
  4. ...
  5. ...
  6. ------------
  7. TRANSACTIONS
  8. ------------...
  9. ---TRANSACTION 7947, ACTIVE 8 sec fetching rows
  10. mysql tables in use 1, locked 1
  11. LOCK WAIT 4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 1
  12. MySQL thread id 2, OS thread handle 140019430659840, query id 24 localhost root updating
  13. update tt set vers='XXXXXcccc' where name='name2' and version=8
  14. ------- TRX HAS BEEN WAITING 8 SEC FOR THIS LOCK TO BE GRANTED:
  15. RECORD LOCKS space id 34 page no 5 n bits 80 index idx_name of table `test`.`tt` trx id 7947 lock_mode X locks rec but not gap waiting
  16. Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
  17. 0: len 5; hex 6e616d6532; asc name2;;
  18. 1: len 4; hex 80000003; asc ;;
  19.  
  20. ------------------
  21. TABLE LOCK table `test`.`tt` trx id 7947 lock mode IX
  22. RECORD LOCKS space id 34 page no 5 n bits 80 index idx_name of table `test`.`tt` trx id 7947 lock_mode X locks rec but not gap
  23. Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
  24. 0: len 5; hex 6e616d6532; asc name2;;
  25. 1: len 4; hex 80000002; asc ;;
  26.  
  27. RECORD LOCKS space id 34 page no 3 n bits 96 index PRIMARY of table `test`.`tt` trx id 7947 lock_mode X locks rec but not gap
  28. Record lock, heap no 31 PHYSICAL RECORD: n_fields 7; compact format; info bits 0
  29. 0: len 4; hex 80000002; asc ;;
  30. 1: len 6; hex 000000001f0b; asc ;;
  31. 2: len 7; hex 280000016001ca; asc ( ` ;;
  32. 3: len 4; hex 80000002; asc ;;
  33. 4: len 5; hex 6e616d6532; asc name2;;
  34. 5: len 9; hex 585858585863636363; asc XXXXXcccc;;
  35. 6: len 1; hex 38; asc 8;;
  36.  
  37. RECORD LOCKS space id 34 page no 5 n bits 80 index idx_name of table `test`.`tt` trx id 7947 lock_mode X locks rec but not gap waiting
  38. Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
  39. 0: len 5; hex 6e616d6532; asc name2;;
  40. 1: len 4; hex 80000003; asc ;;
  41.  
  42. ---TRANSACTION 7946, ACTIVE 99 sec
  43. 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
  44. MySQL thread id 3, OS thread handle 140019430389504, query id 22 localhost root
  45. TABLE LOCK table `test`.`tt` trx id 7946 lock mode IX
  46. RECORD LOCKS space id 34 page no 5 n bits 80 index idx_name of table `test`.`tt` trx id 7946 lock_mode X locks rec but not gap
  47. Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
  48. 0: len 5; hex 6e616d6532; asc name2;;
  49. 1: len 4; hex 80000003; asc ;;
  50.  
  51. RECORD LOCKS space id 34 page no 3 n bits 96 index PRIMARY of table `test`.`tt` trx id 7946 lock_mode X locks rec but not gap
  52. Record lock, heap no 15 PHYSICAL RECORD: n_fields 7; compact format; info bits 0
  53. 0: len 4; hex 80000003; asc ;;
  54. 1: len 6; hex 000000001f0a; asc ;;
  55. 2: len 7; hex 270000013a031e; asc ' : ;;
  56. 3: len 4; hex 80000003; asc ;;
  57. 4: len 5; hex 6e616d6532; asc name2;;
  58. 5: len 4; hex 76737373; asc vsss;;
  59. 6: len 1; hex 39; asc 9;;
  60. ...
  61. ...

结论:会话1通过name索引(和version=9)找到一行记录,并在该二级索引值([name='name2',id=3])上加锁;这时会话2通过name索引(找到两行:[name='name2',id=2] [name='name2',id=3]),这时会等待 [name='name2',id=3]二级索引值记录行上的锁。(此种情况一开始会对二级索引所检索的值加锁 [例如有2行],根据其他条件 [过滤了一行] 找到的primary key [1行],则在这行primary key和二级索引 [过滤了一行] 的key上加锁,过滤掉的一行二级索引值的锁释放)

RR|RC隔离级别下行锁的情况的更多相关文章

  1. Mysql隔离级别,锁与MVCC

    关键词:事务,ACID,隔离级别,MVCC,共享锁,排它锁 阅读本文前请先阅读http://hedengcheng.com/?p=771 http://www.hollischuang.com/arc ...

  2. MySQL数据库引擎、事务隔离级别、锁

    MySQL数据库引擎.事务隔离级别.锁 数据库引擎InnoDB和MyISAM有什么区别 大体区别为: MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持.MyISAM类型的表强调的是性能 ...

  3. 重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系

    重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系 Innodb中的事务隔离级别和锁的关系 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁 ...

  4. Innodb中的事务隔离级别和锁的关系(转载)

    nodb中的事务隔离级别和锁的关系 原文:https://tech.meituan.com/innodb-lock.html ameng ·2014-08-20 15:50 前言: 我们都知道事务的几 ...

  5. 【转载】Innodb中的事务隔离级别和锁的关系

    前言 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所 ...

  6. MYSQL隔离级别 与 锁

    1.四种隔离级别下数据不一致的情况   脏读 不可重复读 幻读 RU 是 是 是 RC(快照读) 否 是 是 RC(当前读) 否 否 是 RR(快照读) 否 否 是 RR(当前读) 否 否 否 Ser ...

  7. 详解Mysql事务隔离级别与锁机制

    一.概述 我们的数据库一般都会并发执行多个事务,多个事务可能会并发的对相同的一批数据进行增删改查操作,可能 就会导致我们说的脏写. 胀读和不可重复读.幻读这些问题. 这些问题的本质都是数据库的多事务并 ...

  8. DB2之隔离级别和锁的论述

    在DB2数据库中, 是通过行级锁和表级锁协调作用来提供较好的并发性, 同时保证数据库中数据的安全. 在DB2中缺省情况下使用行级锁(当然需要IS/IX锁配合),只有当出现锁资源不足, 或者是用命令指定 ...

  9. 数据库事务中的隔离级别和锁+spring Transactional注解

    数据库事务中的隔离级别和锁 数据库事务在后端开发中占非常重要的地位,如何确保数据读取的正确性.安全性也是我们需要研究的问题.ACID首先总结一下数据库事务正确执行的四个要素(ACID): 原子性(At ...

  10. SQL Server事务的隔离级别和锁

    背景        当用户并发尝试访问同一数据的时,SQL Server尝试用锁来隔离不一致的数据和使用隔离级别查询数据时控制一致性(数据该如何读取),说起锁就会联想到事务,事务是一个工作单元,包括查 ...

随机推荐

  1. wget 和 curl的区别

    原文 https://www.codenong.com/s1190000022301195/ https://geek-docs.com/linux/linux-ask-answer/differen ...

  2. 【Frida】启动手机上的Frida插件

    运行以下命令可以保证Frida一直在手机上运行,不关机,Frida就不关 adb shell su -c "./data/local/frida-server-15.2.2-android- ...

  3. 单个Java文件连接数据库demo

      在单个java文件中,尝试连接数据库,跟python的模块包安装方式很接近,已经测试成功,把博客写一下,记录下来.   首先把jdb的驱动包下载下来,就是一个jar包,下面是官网下载地址 官网下载 ...

  4. wireguard 在openwrt中的配置

    按照网上教程正常配置,防火墙通信规则中,选择打开监听端口,目标设备:设备(输入),目标端口:监听端口. 客户端设置:注意路由器的IP地址(段)要填0.0.0.0/0.

  5. Python的入门学习Day 14~15——form”夜曲编程“

    Day 14 time: 2021.8.11. ​ 原文再续,输接上一回.在数据结构之上,我们又开启了新一章"循环"的学习.而今天,我们首先学习了"for"循环 ...

  6. Markdowm的下载方法

    1打开百度搜索,输入TYPORA打开下载页面,根据自己的系统(我的是WINDOWS64位)点"DOWN"进行下载安装. 2安装好后回到桌面新建一个文件夹(Markdown学习),然 ...

  7. NSA对下一代新技术的评估“网络透视”2010

    时间线回到2010年,那时候做渗透测试流行找目标还是通过Google hack,Google dork去寻找目标比如inurl:asp?id= 寻找asp网站可利用的注入点,在厉害点一键爬取域名在配合 ...

  8. 7.26-javascript

    折半查找:数据必须有序 //数组定义 let arr1 = [1,2,3,4,5]; //用字面量定义数组 let arr2 = new Array(1,2,3,4,5); //用字面量定义数组 le ...

  9. Go组件库总结之协程睡眠唤醒

    本篇文章我们用Go封装一个利用gopark和goready实现协程睡眠唤醒的库.文章参考自:https://github.com/brewlin/net-protocol 1.gopark和gorea ...

  10. element ui中el-tree文字显示不全解决方案

    // 问题描述 // 在项目中使用element-ui前端框架来开发界面时,使用el-tree组件实现树形菜单,遇到当节点文字过长会出现显示不全的问题 <el-tree ref="tr ...