mysql场景测试_mysql在RR级别下各场景的锁定测试

一.基本信息

版本:10.0.20-MariaDB-log

事务隔离级别: REPEATABLE-READ

innodb_lock_wait_timeout=60

innodb_locks_unsafe_for_binlog=off

innodb_rollback_on_timeout=off

二. 表信息

CREATE TABLE t1

(

id int unsigned not null auto_increment,

vid int unsigned not null default 0,

name varchar(10) not null default '',

other varchar(20) not null default '',

primary key(id),

key vid(vid)

) engine =InnoDB;

Insert into t1 values(1,1,'zengxw1','I am a DBA'),(2,2,'zengxw2','I am a DBA 2');

select * from t1;

+----+-----+---------+--------------+

| id | vid | name    | other        |

+----+-----+---------+--------------+

|  1 |   1 | zengxw1 | I am a DBA   |

|  2 |   2 | zengxw2 | I am a DBA 2 |

三.场景一(排它锁与共享锁测试)

1b21da5bea5199861e557d25090a282c.png

因为排它锁与共享锁不兼容,肯定会锁。

四.场景二(无索引测试)

a62e666443c3fe650bc5d6b809e929ed.png

因为name字段上没有索引,所以锁会升级为表锁。

五.场景三(一个条件有索引,一个条件无索引测试)

16ccaa4682eed31ebf429aeb7dd7af15.png

因为vid字段上有索引,都会锁住vid=1对应的记录。

efd1c4462922f1a35ad7024a29137e6e.png

因为vid=1和vid=2锁定的记录不同。

五.场景四(vid为非唯一索引的插入测试一)

04ef78eeb668898bc4db3e5a289a3c54.png

Session 2同样插入:Insert into t1 values (4,4,'zengxw4','I am a DBA 4'),也会锁定,查找原因,是由于表中只有两条记录:vid=1和vid=2,

session 2的update操作,会在表上产生gap,

Gap范围为:[1,无穷大),此范围内的值都会锁,也就是上一个值到下一个值之间(同时需要考虑主键)。若vid的值为:1,2,3时,对应主键id分别为:1,2,5,其gap为[id任何值,1]到[2,2]再到[5,3]之间。

一句话vid要小于上一个值,vid和id都要大于或等于下一个值才不会锁。

Select * from t1;

----+-----+---------+--------------+

| id | vid | name    | other        |

+----+-----+---------+--------------+

|  1 |   1 | zengxw1 | I am a DBA   |

|  2 |   2 | ??      | I am a DBA 2 |

|  5 |   3 | ??      | I am a DBA 3 |

举例来说:

会话1执行:update t1 set name ='??' where vid=2;

会话2执行:

Insert into t1 values (4,3,'zengxw4','I am a DBA 4'); ---会锁

Insert into t1 values (6,3,'zengxw4','I am a DBA 4'); ---不会锁

Insert into t1 values (0,1,'zengxw3','I am a DBA 3'); --会锁

Insert into t1 values (10,1,'zengxw3','I am a DBA 3');--会锁

六.场景五(b为非唯一索引的插入测试二)

CREATE TABLE tt1( a INT, b INT, PRIMARY KEY (a), KEY(b));

insert into tt1 values(1,1), (3,1), (5,3), (7,6),(10,8);

select * from tt1;

+----+------+

| a  | b    |

+----+------+

|  1 |    1 |

|  3 |    1 |

|  5 |    3 |

|  7 |    6 |

| 10 |    8 |

+----+------+

会话一执行:

SELECT* FROM tt1 WHERE b =3 FOR UPDATE;

a42aa51f7586ed03049c48ca4fea499e.png

同样:

INSERT INTO tt1 SELECT 6,5; ---会锁

INSERT INTO tt1 SELECT 2,2; ---会锁

INSERT INTO tt1 SELECT 4,6; ---会锁

而INSERT INTO tt1 SELECT 8,6; --不锁

七.场景六(b为唯一索引的插入测试)

把vid改成唯一索引测试:

CREATE TABLE tt2( a INT, b INT, PRIMARY KEY (a), unique KEY(b));

insert into tt2 values(1,1), (3,3), (5,4), (7,7),(10,8);

select * from tt2;

+----+------+

| a  | b    |

+----+------+

|  1 |    1 |

|  3 |    3 |

|  5 |    4 |

|  7 |    7 |

| 10 |    8 |

会话一执行:

SELECT* FROM tt1 WHERE b =3 FOR UPDATE;

e169d94de8f4e368bdc4f49fa30ccae1.png

同样:

INSERT INTO tt2 SELECT 6,5; ---不锁

INSERT INTO tt2 SELECT 2,2; ---不锁

INSERT INTO tt2 SELECT 4,6; ---不锁

结论:当b为唯一索引时,RR级别下不存在gap锁,只有record锁。

总结:

1.  主键索引有record lock

2.  唯一辅助索引有record lock

3.  非唯一辅助索引有next-key lock

4.  没有索引的话,则是全表范围的next-key lock

5.  RC下只有record lock

6.  RR&innodb_locks_unsafe_for_binlog=1,只有record lock.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值