Mysql的锁机制

读与写关系的协调,是通过事务的隔离性来解决的。

脏读、不可重复读、幻读,都是在别人更新数据的时候,你怎么读的问题,读的不对,就有问题,读的方法对了,那就不存在这一系列的问题了。

但是当多个事务同时并发更新同一条数据的时候,就得靠锁机制了。

MYSQL锁机制的基本原理:

事务A来更新一条数据,这个时候,它会先查看一下这个数据有没有被别人加锁。如果没人加锁的话,说明它是第一个人,此时事务A就会创建一个锁,里面包含了自己的trx_id和等待状态,然后把锁和这行数据关联在一起。

同时,更新一行数据必须把它所在的数据页从磁盘文件中读取到缓存页才能进行更新,所以此时,这行数据和关联的锁数据结构都是在内存中的,如下图所示:

这时,事务B也来更新这一条数据,发现这条数据已经被加锁了,然后事务B会排队。这时,事务B也会生成一个锁数据结构,里面有它的trx_id和等待状态,但是因为它在等待,所以等待状态为true。如下图所示:

接着事务A更新完数据了,就会把自己的锁给释放掉,锁一旦释放,它就会去找是不是有其他人也对这行数据加锁了呢,它会发现事务B也对这行数据加锁了。于是,这个时候,就会把事务B里的锁的等待状态修改为false,然后唤醒事务B继续执行,此时事务B就获取到锁了,如下图所示:

 上面的例子中说的是两个事务去加锁,但实际上加锁的不是事务,而是线程。线程是实际操作人,而事务是一系列操作的合集,事务会影响到锁的影响范围。 关于这方面,就要谈一谈Mysql的两阶段锁协议了,可以参考我博客里Mysql专栏的另一篇文章:Mysql的两阶段锁协议_jerry_dyy的博客-CSDN博客_两阶段锁协议

共享锁与独占锁(行锁):

当有人在更新数据的时候,肯定已经加锁了,那其他事务可以读取这行数据吗?答案是:可以。

因为读取数据直接走MVCC机制的,你可以根据你的ReadView,去undo log版本链条里找到一个你能读取的版本,完全不用顾虑别人是否在更新。就算你真的等到它更新完了还提交了,基于MVCC机制你还是读不到更新后的值的。所以默认情况下的读完全不需要加锁。

正是通过MVCC机制,避免了读与写同时进行时的加锁,避免了频繁的进行加锁互斥,提高了Mysql并发性能。

思考:如果我的读操作不在事务中呢?Mysql InnoDB的所有操作都必须在事务中吗?

要是真想在执行查询操作的时候加锁,可以通过:

Select * from table lock in share mode,给查询加共享锁,也就是S锁。

Select * from table for update,给查询加独占锁,也就是X锁。

这个意思就是说,我查出来数据以后是用于更新的,其他闲杂人等都不要更新这个数据了。

共享锁与独占锁的互斥情况:

锁类型

独占锁

共享锁

独占锁

互斥

互斥

共享锁

互斥

不互斥

表锁与表意向锁:

有些人可能会以为当你执行增删改的时候默认加行锁,然后执行DDL语句的时候,比如alter table之类的语句,会默认在表级别加表锁。这么说也不太正确,但是也有一定的道理,因为确实你执行DDL的时候,会阻塞所有增删改操作;执行增删改的时候,会阻塞DDL操作。

但这是通过MySQL通用的元数据锁实现的,也就是Metadata Locks,但这还不是表锁的概念。因为表锁其实是InnoDB存储引擎的概念,InnoDB存储引擎提供了自己的表级锁,跟这里DDL语句用的元数据锁还不是一个概念。

表锁分为两种:表锁,表级意向锁

表锁极为鸡肋,很少用到,可以通过如下语法进行加表锁:

LOCK TABLES xxx READ:这个是加表级共享锁

LOCK TABLES xxx WRITE:这个是加表级独占锁

事务在表里执行增删改操作会加行级独占锁,同时会加一个表级意向独占锁;如果有事务在表里执行查询操作,那么会加一个表级意向共享锁。

表级意向共享锁与表级意向独占锁之间是绝对不互斥的。这样做的原因是为了和表级独占锁、表级共享锁之间进行互斥。

锁类型

表级独占锁

表级意向独占锁

表级共享锁

表级意向共享锁

表级独占锁

互斥

互斥

互斥

互斥

表级意向独占锁

互斥

不互斥

互斥

不互斥

表级共享锁

互斥

互斥

不互斥

不互斥

表级意向共享锁

互斥

不互斥

不互斥

不互斥

所以当你更新数据的时候,加了表级意向独占锁,那么此时别人就不能用LOCK TABLES xxx WRITE加表级独占锁了。

Mysql内部架构_jerry_dyy的博客-CSDN博客

Mysql存储模型_jerry_dyy的博客-CSDN博客

InnoDB内部架构_jerry_dyy的博客-CSDN博客

Buffer Pool 核心原理_jerry_dyy的博客-CSDN博客

Buffer Pool生产实践_jerry_dyy的博客-CSDN博客

Mysql事务隔离机制_jerry_dyy的博客-CSDN博客

Mysql的锁机制_jerry_dyy的博客-CSDN博客

Mysql的索引深度讲解_jerry_dyy的博客-CSDN博客

Mysql索引的使用_jerry_dyy的博客-CSDN博客

SQL语句的执行计划_jerry_dyy的博客-CSDN博客_sql语句的执行计划

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值