您的位置:首页 > 数据库 > MySQL

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

2016-06-05 14:14 489 查看
一.基本信息

版本: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 |

 

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



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

 

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



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

 

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

 


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

 


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

 

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

 


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;

 


同样:

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;

 


同样:

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.

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: