gap lock的前置条件:
1 事务隔离级别为REPEATABLE-READ, innodb_locks_unsafe_for_binlog参数为0,且sql走的索引为非唯一索引(无论是等值检索还是范围检索)
2 事务隔离级别为REPEATABLE-READ, innodb_locks_unsafe_for_binlog参数为0,且sql是一个范围的当前读操作,这时即使不是非唯一索引也会加gap lock
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
update加排他锁和间隔锁 set autocommit=0; mysql> update temp2 set name='abc' where id between 4 and 6; Query OK, 0 rows affected (0.01 sec) Rows matched: 0 Changed: 0 Warnings: 0 session2: insert into temp2 values(4,'d'); 会等待第一个锁释放 session1: 释放锁 commit; session2: Query OK, 1 row affected (7.65 sec) 等待结束释放锁 插入数据成功
例子如果链接1的update语句是update temp set name=‘abc’ where id >4; 而链接2的
插入数据的>
在默认情况下, mysql的事务隔离级别是可重复读,并且innodb_locks_unsafe_for_binlog
参数为0,这时默认采用next-key locks。所谓Next-Key Locks, 就是记录锁和间隔锁的结合,即除了锁住记录本身,还要再锁住索引之间的间隙。
插入意图锁是在插入数据时首先获得的一种间隔锁, 对这种间隔锁只要不同的事务插 入的数据位置是不一样的,虽然都是同一个间隔,也不会产生互斥关系
比如有一个索引有4和7两个值,如果两个事务分别插入5和6两个值时,虽然两个事务
都会在索引4和7之间施加间隔锁,但由于后续插入的数值不一样,所以两者不会互斥
比如下例中事务A对索引>100的值施加了排他间隔锁,而事务B在插入数据之前就试
图先施加插入意图锁而必须等待
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
CREATE TABLE child (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB; INSERT INTO child (id) values (90),(102); #开启事务A START TRANSACTION; #增加排它间隔锁 SELECT * FROM child WHERE id > 100 FOR UPDATE; +-----+ | id | +-----+ | 102 | +-----+ 1 row in set (0.00 sec) 另一个session窗口,开启事务B: START TRANSACTION; INSERT INTO child (id) VALUES (101); 这时候会有锁等待
可以通过show engine innodb status命令查看插入意向锁被阻止
自增锁自增锁是针对事务插入表中自增列时施加的一种特殊的表级锁,即
当一个事务在插入自增数据时,另一个事务必须等待前一个事务完
成插入,以便获得顺序的自增值
参数innodb_autoinc_lock_mode可以控制自增锁的使用方法
InnoDB锁相关系统变量查看当前系统隔离级别
1 2 3 4 5 6
show variables like 'tx_isolation'; +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | tx_isolation | REPEATABLE-READ | +---------------+-----------------+
查看是否开启自动提交
1 2
show variables like 'autocommit'; show variables like 'innodb_table_locks';
查看innodb事务等待事务的超时时间(秒)
1 2 3 4 5 6
mysql> show variables like 'innodb_lock_wait_timeout'; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | innodb_lock_wait_timeout | 50 | +--------------------------+-------+
innodb_locks_unsafe_for_binlog参数用来控制innodb中是否允许间隔锁,默认是OFF代表允许间隔锁,设置成ON则代表不使用间隔锁,只是使用行级锁
+ View Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
• mysql> show variables like 'innodb_locks_unsafe_for_binlog';
• +--------------------------------+-------+
• | Variable_name | Value |
• +--------------------------------+-------+
• | innodb_locks_unsafe_for_binlog | OFF |
• +--------------------------------+-------+
• 在my.cnf中配置innodb_locks_unsafe_for_binlog=on选项
• 链接1:
• mysql> set autocommit=0;
• mysql> update temp set name='abc' where id>=4;
• 链接2:
• mysql> set autocommit=0;
• Query OK, 0 rows affected (0.00 sec)
• mysql> insert into temp values(4,‘abc’); ##未出现等待的情况
• Query OK, 1 row affected (0.00 sec)
InnoDB事务隔离级别
InnoDB存储引擎提供了四种事务隔离级别,分别是:
READ UNCOMMITTED:读取未提交内容
READ COMMITTED:读取提交内容
REPEATABLE READ:可重复读,默认值。
SERIALIZABLE:串行化