多个事务更新同一行数据时,通过加锁避免脏写
- 依靠锁机制让多个事务更新一行数据的时候串行化,避免同时更新一行数据。
- 在MySQL里,假设有一行数据,此时有一个事务来更新这行数据,它会先判断有没有人加锁,如果没有人加锁,这个事务就会创建一个锁,里面包含了自己的trx_id和等待状态,然后把锁跟这行数据关联在一起。这行数据和关联的锁数据结构都是在内存里的。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200509092558656.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjAxMjkxMQ==,size_16,color_FFFFFF,t_70)
- 此时这行数据已经被加锁了,此时B过来想要修改这行数据,就会检查一下,当前这行数据有没有别人加锁,如果有,就等的排队,此时事务B也会生成一个锁数据结构,里面有他的trx_id和等待状态,
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020050909331267.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjAxMjkxMQ==,size_16,color_FFFFFF,t_70)
- 然后A更新完了之后,就会把自己的锁释放掉。锁一旦释放了,他就会去看看此时还有没有其他事务对这行数据加锁,它会发现B,然后把事务B的锁的等待状态改为false,然后唤醒B事务执行,此时B事务就获取到锁了。
共享锁和独占锁
- 更新的时候加的是独占锁,X锁。
- 如果有人在更新数据的时候,其他事务要读取这行数据,默认情况下时不加锁的,因为默认情况下,有人在更新数据的时候,你要去读取这行数据,直接默认就说开启MVCC机制。也就是说,此时对一行数据的读和写两个操作默认时不会加锁互斥的。此时你在读取数据,完全可以根据你的ReadView,去undolog版本链条里找一个你能够读取的版本,完全不用顾虑别人在不在更新。
- 如果执行查询的时候你想要加锁,那也是可以的MYSQL首先支持一种共享锁,
select * from table lock in share mode
,你在查询语句后面加上lock in share mode
,意思就说查询的时候对一行数据加共享锁 - 共享锁和独占锁是互斥的
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200509095906901.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjAxMjkxMQ==,size_16,color_FFFFFF,t_70)
- 更新数据的时候必然加独占锁,独占锁和独占锁是互斥的,此时别人不能更新,但是此时你要查询,默认不加锁,走mvcc机制读快照版本,但是你查询是可以手动加共享锁的,共享锁和独占锁是互斥的,但是共享锁和共享锁是不互斥
- 查询还能加互斥锁
select * from table for update
,一旦你查询的时候加了独占锁,此时在你事务提交之前,任何人都不能更新数据了,只能你在本事务里更新数据,等到你提交了,别人再更新数据。
表级锁
- 执行DDL语句的时候,eg
alter table
,并不是加表锁,而是通过MySql通用的元数据锁实现的,Metadata Locks
。不过执行DDL的时候,会阻塞所有的增删改操作;执行增删改的时候,会阻塞DDL - 表锁其实是InnoDB存储引擎的概念,InnoDB存储引擎提供了自己的表级锁,跟这里DDL语句用的元数据锁还不是一个概念。
- mysql的表锁,几乎很少用到;表锁分为2种,一种就说表锁,一种是表级的意向锁
LOCK TABLES xxx READ
LOCK TABLES xxx WRITE
- 如果有的事务在表里执行增删改操作的时候,会在行级加独占锁,此时同时会在表级加一个意向独占锁;如果又事务在表里执行查询操作,那么会在表级加一个意向共享锁。两种意向锁不会互斥
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200511090440540.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjAxMjkxMQ==,size_16,color_FFFFFF,t_70)