Preface
 
    As we know,InnoDB is index organized table.InnoDB engine supports row-level lock base on indexes,if there're no indexes on a certain table the record locks will upgrade to "table-level"(not really table lock,just locks all the records in the table) locks.Furthe more,in RR transaction isolation mode,It's more complicated.'cause there're gap locks(together with record locks,we call them next key locks) to prevent phantom read between multiple tansactions.Let's do some test watch the locking conflicts.
 
Procedure
 
Crete a test table as below.
 zlm@192.168.56.100: [zlm]>create table t1(
-> c1 int unsigned not null default '',
-> c2 int unsigned not null default '',
-> c3 int unsigned not null default '',
-> c4 int unsigned not null default '',
-> primary key(c1),
-> key(c2)
-> ) engine=innodb;
Query OK, rows affected (0.02 sec) zlm@192.168.56.100: [zlm]>insert into t1(c1,c2,c3,c4) values(,,,),(,,,),(,,,),(,,,),(,,,),(,,,),(,,,);
Query OK, rows affected (0.01 sec)
Records: Duplicates: Warnings: zlm@192.168.56.100: [zlm]>select * from t1;
+----+----+----+----+
| c1 | c2 | c3 | c4 |
+----+----+----+----+
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
+----+----+----+----+
rows in set (0.01 sec) zlm@192.168.56.100: [(none)]>select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ | //Make surej in RR transaction isolation level.
+-------------------------+
row in set (0.00 sec) zlm@192.168.56.100: [(none)]>show variables like 'innodb_status_output_locks';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| innodb_status_output_locks | ON |
+----------------------------+-------+
row in set (0.00 sec)
Test 1. session1 executes "select ...  for update" and session2 executes "select ... lock in share mode".(conflict)
 //Session1:
zlm@192.168.56.100: [zlm]>begin;select * from t1 where c1= for update;
Query OK, rows affected (0.00 sec) +----+----+----+----+
| c1 | c2 | c3 | c4 |
+----+----+----+----+
| | | | |
+----+----+----+----+
row in set (0.00 sec) //Session2:
monitor@192.168.56.100: [zlm]>begin;select * from t1 where c1= lock in share mode;
Query OK, rows affected (0.00 sec) ERROR (HY000): Lock wait timeout exceeded; try restarting transaction //Session2 requested a "S" record lock on the primary key column where c1=3 while session1 has holded the "X" record lock on the same position,so session2 was blocked util lock timeout.
Test 2. session1 executes "select ...  for update" and session2 executes ordinary query.(compatible)
 //Session1:
zlm@192.168.56.100: [zlm]>begin;select * from t1 where c1= for update;
Query OK, rows affected (0.00 sec) +----+----+----+----+
| c1 | c2 | c3 | c4 |
+----+----+----+----+
| | | | |
+----+----+----+----+
row in set (0.00 sec) //Session2:
monitor@192.168.56.100: [zlm]>select * from t1 where c1=;
+----+----+----+----+
| c1 | c2 | c3 | c4 |
+----+----+----+----+
| | | | |
+----+----+----+----+
row in set (0.00 sec) //Session1 didn't change this time and session2 request for non-lock consistent read.It read records from a consistent snapshop without locking.
Test 3. session1 executes "select ...  lock in share mode" and session2 executes "select ... for update".(conflict)
 //Session1:
zlm@192.168.56.100: [zlm]>begin;select * from t1 where c3= lock in share mode;
Query OK, rows affected (0.01 sec) Empty set (0.00 sec) //Session2:
monitor@192.168.56.100: [zlm]>begin;select * from t1 where c3= for update;
Query OK, rows affected (0.00 sec) ERROR (HY000): Lock wait timeout exceeded; try restarting transaction //Although there's no record satisfied with c3=7 but notice that there's no index on c3 column.Therefore,the session1 has holded a "S" record for all the records on column c1 in table t1.Then session2 asked for the "X" record lock for "c3=10"(even it does not exixt),it was blocked.
Test 4. session1 executes "select ...  lock in share mode" and session2 executes "select ... for update".(conflict)
 //Session1:
zlm@192.168.56.100: [zlm]>begin;select * from t1 where c3= lock in share mode;
Query OK, rows affected (0.00 sec) Empty set (0.00 sec) //Session2:
monitor@192.168.56.100: [zlm]>begin;select * from t1 where c1= for update;
Query OK, rows affected (0.00 sec) ERROR (HY000): Lock wait timeout exceeded; try restarting transaction //This is similar with "test 3".Session1 has holded a "S" record lock of all records on column c3.The record where c1=6 means c3=5,it's also in the range of all records.So session2 was blocked.
Test 5. session1 executes "select ...  for update" and session2 executes "select ... for update".(conflict)
 
 //Session1:
zlm@192.168.56.100: [zlm]>begin;select * from t1 where c2= and c3= for update;
Query OK, rows affected (0.00 sec) +----+----+----+----+
| c1 | c2 | c3 | c4 |
+----+----+----+----+
| | | | |
+----+----+----+----+
row in set (0.00 sec) //Session2:
monitor@192.168.56.100: [zlm]>begin;select * from t1 where c2= and c3= for update;
Query OK, rows affected (0.00 sec) ERROR (HY000): Lock wait timeout exceeded; try restarting transaction //Because of the secondary index key on column c2,it generated a "X" record lock and a gap lock(record + gap = next key lock).Although the gap lock between two sessions can be coexistent,but record locks do not.So session2 was blocked.
Test 6. session1 executes "select ...  for update" and session2 executes "select ... for update".(compatible)
 //Session1:
zlm@192.168.56.100: [zlm]>begin;select * from t1 where c2= and c3= for update;
Query OK, rows affected (0.00 sec) +----+----+----+----+
| c1 | c2 | c3 | c4 |
+----+----+----+----+
| | | | |
+----+----+----+----+
row in set (0.00 sec) //Session2:
monitor@192.168.56.100: [zlm]>begin;select * from t1 where c2= and c3= for update;
Query OK, rows affected (0.00 sec) Empty set (0.00 sec) //This time session2 was not blocked.They've requested a different "X" record lock individually even they still hold the gap lock.
Test 7. session1 executes "select ...  for update" and session2 executes "select ... for update".(conflict)
 //Session1:
zlm@192.168.56.100: [zlm]>begin;select * from t1 where c2= and c3= for update;
Query OK, rows affected (0.00 sec) +----+----+----+----+
| c1 | c2 | c3 | c4 |
+----+----+----+----+
| | | | |
+----+----+----+----+
row in set (0.00 sec) //Session2:
monitor@192.168.56.100: [zlm]>begin;select * from t1 where c1= and c3= for update;
Query OK, rows affected (0.00 sec) ERROR (HY000): Lock wait timeout exceeded; try restarting transaction //The query condition in session2 is c1=4.It means c2=2,this is similar with test 5(asked for the equal line).
Test 8. session1 executes "select ...  for update" and session2 executes "select ... for update".(compatible)
 //Session1:
zlm@192.168.56.100: [zlm]>begin;update t1 set c4= where c2>=;
Query OK, rows affected (0.00 sec) Query OK, rows affected (0.00 sec)
Rows matched: Changed: Warnings: //Session2:
monitor@192.168.56.100: [zlm]>begin;select * from t1 where c1= for update;
Query OK, rows affected (0.00 sec) Empty set (0.00 sec) //The records according to the query condition c2>=4 were c1=8 and c1=10.
//Even though there's a index key on c1 but it's a primary key which doesn't generate gap lock.So session2 's asking for "X" record lock of c1=7 was not blocked.
Summary
  • We should pay more attention to innodb row-level locks.If there's no key on the relevant column,the locks will be escalated to "table-level"(all records will be locked) locks.
  • In the RR transaction isolation level,Secondary index generates gap locks(LOCK_ORDINARY) to prevent phantom read while primary index and unique index do not.They only hold record locks(LOCK_REC_NOT_GAP).
  • In the RC transaction isolation level,there're no gap locks.Therefore,it's concurrency is better than that in RR mode,but the consistency is poor as well.
  • As for which transaction isolation level we should choose is depend on your purpose:for more consistency or for more concurrency.
 

InnoDB锁冲突案例演示的更多相关文章

  1. InnoDB锁冲突案例演示(续)

      Preface       I've demontstrated several InnoDB locking cases in my previous blog.I'm gonna do the ...

  2. MySQL记录锁、间隙锁、临键锁小案例演示

    生成间隙(gap)锁.临键(next-key)锁的前提条件 是在 RR 隔离级别下. 有关Mysql记录锁.间隙(gap)锁.临键锁(next-key)锁的一些理论知识之前有写过,详细内容可以看这篇文 ...

  3. KingbaseES R6 集群主机锁冲突导致的主备切换案例

    ​ 案例说明: 主库在业务高峰期间,客户执行建表等DDL操作,主库产生"AccessExclusiveLock "锁,导致大量的事务产生锁冲突,大量的会话堆积,客户端session ...

  4. InnoDB锁机制分析

    InnoDB锁机制常常困扰大家,不同的条件下往往表现出不同的锁竞争,在实际工作中经常要分析各种锁超时.死锁的问题.本文通过不同条件下的实验,利用InnoDB系统给出的各种信息,分析了锁的工作机制.通过 ...

  5. [转载] 数据库分析手记 —— InnoDB锁机制分析

    作者:倪煜 InnoDB锁机制常常困扰大家,不同的条件下往往表现出不同的锁竞争,在实际工作中经常要分析各种锁超时.死锁的问题.本文通过不同条件下的实验,利用InnoDB系统给出的各种信息,分析了锁的工 ...

  6. MySQL- InnoDB锁机制

    InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁.行级锁与表级锁本来就有许多不同之处,另外,事务的引入也带来了一些新问题.下面我们先介绍一点背景知识 ...

  7. MySQL InnoDB锁机制

    概述: 锁机制在程序中是最常用的机制之一,当一个程序需要多线程并行访问同一资源时,为了避免一致性问题,通常采用锁机制来处理.在数据库的操作中也有相同的问题,当两个线程同时对一条数据进行操作,为了保证数 ...

  8. 【锁】Innodb锁

    InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁.行级锁与表级锁本来就有许多不同之处,另外,事务的引入也带来了一些新问题.下面我们先介绍一点背景知识 ...

  9. MySQL基础篇(06):事务管理,锁机制案例详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.锁概念简介 1.基础描述 锁机制核心功能是用来协调多个会话中多线程并发访问相同资源时,资源的占用问题.锁机制是一个非常大的模块,贯彻MyS ...

随机推荐

  1. Entity Framework——读写分离

    1 实现 CustomDbContext扩展了DbContext,其构造函数带有形式参nameOrConnectionString,可以在使用CustomDbContext时指定数据库连接字符串. D ...

  2. localStorage和cookie操作

    localStorage和cookie操作代码: cookie: { isSupportCookie: function() { return navigator.cookieEnabled; }, ...

  3. 使用腾讯云mysql的一下小坑

    1. 数据库中标的命名,mybatis会给你全部转成驼峰命名,这样就会发现找不到数据库的表了.比如下面的,我在本地运行时ok, 表名称是t_blogtype,但是放到服务器就报错说找不到表. 2. 本 ...

  4. SecureCRT连接主机时(串口/网络),无法从键盘输入

    Session Option-Connection-Serial-Flow Control,里面的选项全部取消掉,再重启CRT就ok了...

  5. ARM Linux 内核 panic 之cache 一致性 ——Cortex-A9多核cache和TLB一致性广播

    ARM Linux 内核 panic 之cache 一致性 ——Cortex-A9多核cache和TLB一致性广播 Cortex-A9的多喝CPU可以接收和执行一致性广播操作,当其使能并处于SMP模式 ...

  6. 第24章 QSPI—读写串行FLASH

    本章参考资料:<STM32F76xxx参考手册>.<STM32F76xxx规格书>.库帮助文档<STM32F779xx_User_Manual.chm>及<S ...

  7. DQL-分组查询

    一.语法   select 分组函数,分组后的字段   from 表 [ where 筛选条件]   group by 分组的字段[having 分组后的筛选][order by 排序列表] 例如 S ...

  8. 463. Island Perimeter (5月29日)

    解答 class Solution { public: int islandPerimeter(vector<vector<int>>& grid) { int num ...

  9. MySQL学习之视图的使用

    视图基本操作 创建视图 视图的本质就是SQL指令(select语句) 基本语法:create view 视图名 as  select 指令; 在这里的select指令可以是单表数据,也可以是连接查询. ...

  10. 5 替换空格 JavaScript

    题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy.   原来一个空格字符,替换之后 ...