mysql锁

内容仅为个人理解,我也在不断的纠正自己的理解。

1
2
3
-- 以下讨论都基于:Innodb,事务隔离机制采用RR
select @@global.tx_isolation;
REPEATABLE-READ

First Of All,Mysql数据库在事务隔离级别为RR的情况下,如果要避免幻读,就要通过间隙锁。那么如何最简单的实现间隙锁,就是通过select语句中 for update 排他锁。正常的select语句是不会加锁的。而是通过访问记录的版本链的过程,实现MVCC(多版本并发控制),也可以简单的理解为快照读,并不加锁。在select for update, 还有 insert, update, delete 的时候,就需要考虑锁机制了。另外mysql的锁,锁定的是索引,并不是数据。

行锁算法(注意是算法哦)

  • 普通行锁

    唯一索引,且查询的记录存在

  • 间隙锁

    锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况。

    常见于,键值不存在条件范围内,叫做间隙(GAP),引擎会对该“间隙”加锁。

  • Next-key Lock(行锁&间隙锁)

    相当于两种锁的结合。锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。

锁的类型:

共享锁(S)、排他锁(X)、意向共享(IS)、意向排他(IX)

行锁,表锁其实是锁的粒度的概念,共享锁和排它锁是具体的实现。

共享锁(S): 允许其他事务来读取,但是阻止其他事务,在该行获取该行的排它锁。简单的记忆:能读不能写。共享锁的查询举例: select … lock in share mode。

排它锁(X): 允许持有排它锁的事务读写数据,阻止其他事务获取该行的共享锁和排它锁。但是其他事务还是可以读的。(普通的select语句,并不影响数据查询)。

1
2
3
4
5
-- 排它锁的举例:
update ...
delete ...
insert ...
select ... for update

间隙锁之举例

前言:始终不要忘记间隙锁的目的,是为了解决幻读。所以开发工作中,要主动思考,规避在某些并发环境下,会出现幻读,常见做法便是:在sql中加入for update,或是乐观锁。在运维工作中,也要留意数据库,出现同样间隙锁的性能问题。(遇到过,数据库大量的insert 导致的间隙锁)

Author: Chandler Kwok
Link: http://yoursite.com/2020/04/16/mysql%E9%94%81/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.