聊聊MySQL里的 record锁和 gap 锁-20201020

 
聊聊MySQL里的 record锁和 gap 锁
 
注意:隔离级别为 可重复读!!!
mysql> show variables like '%iso%';
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
| tx_isolation                | REPEATABLE-READ |
+-----------------------+-----------------+
#创建测试表
mysql> create table t2(id int,name varchar(10),primary key(id),key(name));
Query OK, 0 rows affected (0.46 sec)
#插入测试数据
mysql> insert into t2 values(1,'A'),(3,'A'),(5,'C'),(7,'G'),(10,'I');
Query OK, 5 rows affected (0.16 sec)
Records: 5  Duplicates: 0  Warnings: 0
 
mysql> commit;
Query OK, 0 rows affected (0.04 sec)
#确认目前的数据
mysql> select id,name from t2;
+----+------+
| id | name |
+----+------+
|  1 | A    |
|  3 | A    |
|  5 | C    |
|  7 | G    |
| 10 | I    |
+----+------+
5 rows in set (0.00 sec)
 
 
以下为record 锁 的操作步骤
case1
session1
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
 
mysql> select * from t2 where name='C' for update;
+----+------+
| id | name |
+----+------+
|  5 | C    |
+----+------+
1 row in set (0.00 sec)
 
session2
mysql> use sakila;
Database changed
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
 
mysql> select * from t2 where id=5 lock in share mode;
被hang住,哈哈 
 
#目前数据库中的锁的情况
 
case2
session1
mysql> select * from t2 where id=5 and name='C' for update;
+----+------+
| id | name |
+----+------+
|  5 | C    |
+----+------+
1 row in set (0.00 sec)
 
session2
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
 
mysql> select * from t2 where id=5 and name='B' for update;
哈哈 被锁 
 
#目前数据库中的锁的情况
 
结论:MySQL 二级索引上加的锁 会自动的在主键上也附加一个锁
 
 
以下为gap锁的测试步骤
case1
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
 
mysql> select * from t2 where name='C' for update;
+----+------+
| id | name |
+----+------+
|  5 | C    |
+----+------+
1 row in set (0.00 sec)
 
session2
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
 
mysql> insert into t2 values(6,'C');
哈哈 被锁 
 
#确认数据库中锁的情况,请注意最后 被锁的记录数和被锁的主键
 
session3
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
 
mysql> insert into t2 values(4,'B');
哈哈 照旧被锁
 
#确认下数据库中的锁
case2
3
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
 
mysql> select * from t2 where name='C' for update;
+----+------+
| id | name |
+----+------+
|  5 | C    |
+----+------+
1 row in set (0.00 sec)
 
session2
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
 
mysql> insert into t2 values(6,'E');
哈哈 照旧被锁
 
#确认数据库中的锁的情况
 
case3
session1
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
 
mysql> select * from t2 where name='C' for update;
+----+------+
| id | name |
+----+------+
|  5 | C    |
+----+------+
1 row in set (0.00 sec)
 
session2
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
 
mysql> insert into t2 values(2,'B');   
哈哈 照旧被锁
 
mysql> insert into t2 values(8,'F');
哈哈 照旧被锁
 
mysql> insert into t2 values(6,'G');
哈哈 照旧被锁
 
文末附上 那条牛逼的sql语句
SELECT
t1.lock_trx_id '事务id',
t2.trx_started '事务的开始时间',
CASE  t2.trx_state
WHEN 'LOCK WAIT' THEN '请求锁'
WHEN 'RUNNING' THEN '持有锁'
ELSE 'null'
END '事务状态' ,
CASE lock_mode           
WHEN 'X' THEN '排它锁'
WHEN 'X,GAP' THEN '排它锁,空隙锁'
WHEN 'S' THEN '共享锁'
ELSE 'null'
END '锁模式',
t1.lock_type '锁类型',
t1.lock_table '被锁的表',
t1.lock_index '锁的index',
t1.lock_space '表空间的id',
t1.lock_page '被锁的页号',
t1.lock_rec '被锁的记录数',
t1.lock_data '被锁行的主键'
FROM information_schema.innodb_locks t1
LEFT JOIN
information_schema.innodb_trx t2
ON t1.lock_trx_id=t2.trx_id;
 
 
创建时间:2021-12-22 10:41
浏览量:0