Mysql锁基础

mysql架构图

è¿éåå¾çæè¿°

共享锁

共享锁也称为读锁,读锁允许多个连接可以同一时刻并发的读取同一资源,互不干扰;

排他锁

排他锁也称为写锁,一个写锁会阻塞其他的写锁或读锁,保证同一时刻只有一个连接可以写入数据,同时防止其他用户对这个数据的读写。

锁的开销是较为昂贵的,锁策略其实就是保证了线程安全的同时获取最大的性能之间的平衡策略。

  • mysql锁策略:talbe lock(表锁)

表锁是mysql最基本的锁策略,也是开销最小的锁,它会锁定整个表;

具体情况是:若一个用户正在执行写操作,会获取排他的“写锁”,这可能会锁定整个表,阻塞其他用户的读、写操作;

若一个用户正在执行读操作,会先获取共享锁“读锁”,这个锁运行其他读锁并发的对这个表进行读取,互不干扰。只要没有写锁的进入,读锁可以是并发读取统一资源的。

通常发生在DDL语句\DML不走索引的语句中,比如这个DML update table set columnA=”A” where columnB=“B”. 如果columnB字段不存在索引(或者不是组合索引前缀),会锁住所有记录也就是锁表。如果语句的执行能够执行一个columnB字段的索引,那么会锁住满足where的行(行锁)。

  • mysql锁策略:row lock(行锁)

行锁可以最大限度的支持并发处理,当然也带来了最大开销,顾名思义,行锁的粒度实在每一条行数据。

MVCC(multiple-version-concurrency-control)是个行级锁的变种,它在普通读情况下避免了加锁操作,因此开销更低。 
虽然实现不同,但通常都是实现非阻塞读,对于写操作只锁定必要的行

  • 一致性读 (就是读取快照) 
    select * from table ….;
  • 当前读(就是读取实际的持久化的数据) 
    特殊的读操作,插入/更新/删除操作,属于当前读,处理的都是当前的数据,需要加锁。 
    select * from table where ? lock in share mode; 
    select * from table where ? for update; 
    insert; 
    update ; 
    delete;

注意:select …… from where…… (没有额外加锁后缀)使用MVCC,保证了读快照(mysql称为consistent read),所谓一致性读或者读快照就是读取当前事务开始之前的数据快照,在这个事务开始之后的更新不会被读到。INNODB的MVCC通常是通过在每行数据后边保存两个隐藏的列来实现(其实是三列,第三列是用于事务回滚,此处略去), 
一个保存了行的创建版本号,另一个保存了行的更新版本号(上一次被更新数据的版本号) 
这个版本号是每个事务的版本号,递增的。这样保证了innodb对读操作不需要加锁也能保证正确读取数据。

对于加锁读SELECT with FOR UPDATE(排他锁) or LOCK IN SHARE MODE(共享锁)、update、delete语句,要考虑是否是唯一索引的等值查询。

行锁中的间隙所:

对于使用到唯一索引 等值查询:比如,where columnA=”…” ,如果columnA上的索引被使用到, 
那么会在满足where的记录上加行锁(for update是排他锁,lock in shared 是共享锁,其他写操作加排他锁)。这里是行级锁,record lock。

对于范围查询(使用非唯一的索引): 
比如(做范围查询):where columnA between 10 and 30 ,会导致其他会话中10以后的数据都无法插入(next key lock),从而解决了幻读问题。

这里是next key lock 会包括涉及到的所有行。 
next key lock=recordLock+gapLock,不仅锁住相关数据,而且锁住边界,从而彻底避免幻读对于没有索引 而言会锁表。 
通常发生在DDL或DML不走索引的语句中,比如这个DML update table set columnA=”A” where columnB=“B”. 
如果columnB字段不存在索引(或者不是组合索引前缀),会锁住所有记录也就是锁表。如果语句的执行能够执行一个columnB字段的索引,那么会锁住满足where的行(行锁)。

关于死锁处理:

innodb_lock_wait_timeout 等待锁超时回滚事务: 
直观方法是在两个事务相互等待时,当一个等待时间超过设置的某一阀值时,对其中一个事务进行回滚,另一个事务就能继续执行。这种方法简单有效,在innodb中,参数innodb_lock_wait_timeout用来设置超时时间。

wait-for graph算法来主动进行死锁检测: 
innodb还提供了wait-for graph算法来主动进行死锁检测,每当加锁请求无法立即满足需要并进入等待时,wait-for graph算法都会被触发。

 

对于理解这些锁而言

  • 普通锁,本质是串行执行

  • 读写锁,可以实现读读并发

  • 数据多版本,可以实现读写并发

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值