行级锁是施加在索引行数据上的锁,比如SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE语句是在t.c1=10的索引行上增加锁 ,来阻止其他事务对对应索引行的insert/update/delete操作。
当一个InnoDB表没有任何索引时, 则行级锁会施加在隐含创建的聚簇索引上,所以说当一条sql没有走任何索引时,那么将会在每一条聚集索引后面加X(排它)锁,这个类似于表锁,但原理上和表锁应该是完全不同的
1 2
mysql> create table temp(id int,name varchar(10)); mysql> insert into temp values(1,'a'),(2,'b'),(3,'c');
开启两个会话链接,链接同一个数据库,模拟排他锁
+ View Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
session1:
##update加排他锁
mysql> set autocommit=0; #模拟开启一个事务会话
Query OK, 0 rows affected (0.00 sec)
mysql> update temp set name='aa' where >
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
session2:
##update等待第一个锁释放
mysql> update temp set name='bb'where >
session1
##commit释放锁
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
session2
等待结束释放锁
update操作才会成功
Query OK, 1 row affected (5.81 sec)
Rows matched: 1 Changed: 1 Warnings: 0
看看事务的详细信息:
+ View Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
session1:
set autocommit=0;
update temp set name='a' where >
session2:
select trx_id,trx_state,trx_started,trx_tables_locked,trx_rows_locked from
information_schema.innodb_trx\G;
*************************** 1. row ***************************
trx_id: 35455759 #事务id
trx_state: RUNNING #事务状态
trx_started: 2018-10-08 18:15:26 #事务开启时间
trx_tables_locked: 1
trx_rows_locked: 4
1 row in set (0.00 sec)
update temp set name='b' where >
session3:
#查看锁等待
select * from information_schema.innodb_lock_waits;
#查看锁状态
select trx_id,trx_state,trx_started,trx_tables_locked,trx_rows_locked from information_schema.innodb_trx;
#查看锁的信息
select lock_id,lock_trx_id,lock_mode,lock_type,lock_index,lock_rec,lock_data from information_schema.innodb_locks;
看看该事务的锁信息
lock_type : RECORD 行级锁
lock_index:GEN_CLUSE_INDEX 聚集索引
给temp表加一个主键索引在看看
alter table temp add primary key(id); ##增加索引之后,记得把前面事务提交
1 2 3 4 5 6 7 8 9 10 11 12
session1: update加排它锁 set autocommit=0; update temp set name='a' where > session2: update temp set name='b' where > update不需要等待第一个锁释放,直接执行成功 session1: 进行提交事务 commit;
间隔锁
当 我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件 的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”, InnoDB也会对这个“间隙”加锁
间隔锁是施加在索引记录之间的间隔上的锁, 锁定一个范围的记录、但不包括记录本身,比如SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE语句,尽管有可能对c1字段来说当前表里没有=15 的值,但还是会阻止=15的数据的插入操作,是因为间隔锁已经把索引查询范围内的间隔数据也都锁住了
间隔锁的使用只在部分事务隔离级别才是生效的
间隔锁只会阻止其他事务的插入操作