Mysql锁

Mysql提供了行锁、表锁和页面锁来解决数据之间的竞争的情况。在这三种锁的基础上,MySQL提供了不同的实现,具体使用的锁是需要根据存储引擎决定。

锁的申请规则:

  1. 申请读锁时,如果无锁可申请,如果只有读锁,可申请,如果有写锁,不可申请
  2. 申请写锁时,如果无锁可申请,如果有读锁,不可申请,如果有写锁,不可申请

行锁

行锁:顾名思义是为一个数据行加锁,即当MySQL进行数据加锁的时候,加锁的粒度是针对一条记录,对于其他记录的访问是无影响的。

在InnoDB中,行锁的实现主要有三类:读锁(共享锁)、意向读锁、写锁(排他锁)、意向写锁和间隙锁。

申请锁的时候会先判断该记录是否存在有关联的锁结构(是否有其他事务申请了锁)。如果没有其他事务持有锁(会根据锁的类型去判断是否可以申请锁),则会创建一个锁记录,记录事务ID,标记获取锁的状态为成功和锁的类型,然后成功获取锁。如果有其他的事务申请了锁,则创建一个锁记录,记录事务ID,标记获取锁的状态为失败以及锁的类型。当其他事务释放锁的时候,会去查找对应记录的锁记录信息,然后修改状态为获取成功,并唤醒对应的线程。

读锁

Mysql默认查询数据的时候,是不会加锁的,如果需要在Mysql读取数据的时候加上读锁,则可以使用select * from test for update;的方式加上排他锁,也可以使用select * from test lock in share mode 的方式加上共享读锁。

当给某一条记录加上读锁的时候,会先获取整个表意向读锁。当需要对MySQL的表添加排他锁的时候,就可以通过判断是否存在意向读锁,去判断是否存在有读锁的存在。(写锁的后面会介绍)

写锁

写锁是MysQL在更新数据的时候,会先申请一个写锁(排他锁)。申请写锁的时候,也会和读锁一致,先去申请一个意向写锁。

从上述两个加锁的粒度来说,意向读锁和意向写锁并不冲突,因为他们只是一个标志,代表表的是否存在有读锁或者写锁,具体是否加锁成功,是根据具体记录的锁记录信息判断,是否存在锁竞争。

间隙锁

在隔离级别中,读未提交、读已提交均会出现幻读的情况。幻读主要是出现在范围查询的时候,如果其他的事务提交了一批数据,事务在第二次查询的时候,会出现两次查询的结果不一致。在可重复读中实际已经解决了幻读的情况。解决幻读的方式可以有两种:MVCC机制和间隙锁。

间隙锁:锁定的数据是一个范围。例如 select * from test where id < 17 for update 会锁定id小于17的,如果想要插入一条记录ID 为16 的数据,则会阻塞,直到释放该间隙锁。

使用间隙锁解决幻读的时候,如果其他的事务想要插入数据到该范围中,则会阻塞,直到该间隙锁释放。因为其他的事务无法插入数据,所以不会出现幻读的情况。间隙锁的时候需要在可重复读隔离级别下才可以使用。

表锁

下面的均是针对MyIsam进行分析。

表锁是比行锁粒度更大的一个锁,锁定的对象为一张表。当表进行修改的时候,如果有其他的事务想要修改就会被阻塞(concurrent_insert需要设置为0,否则允许并发)。

如果希望能够并行插入数据的时候,可以设置 concurrent_insert 的值进行指定。如果指定的值为1,则如果表不存在空洞(没有被删除的数据),则允许在表的最后插入数据;如果指定的值为2,则无论表是否存在空洞,都会在表的最后插入数据。

页面锁

页面锁是介于行锁和表锁之间。锁定的对象是一个页面的数据,加锁和释放锁的开销介于行锁和表锁之间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值