1.如何加锁避免脏读

避免脏写,需要依靠锁机制让多个事务更新同一行数据的时候串行化。
MySQL中,如果有一个事务A更新一行数据,首先会看这行数据是否被加锁,如果没加锁,这个事务就会创建一个锁,里面包含了当前事务的trx_id和等待状态,然后把锁跟这行数据关联在一起。
更新一行数据必须把对应的数据页从磁盘文件读取到缓存页中,所以,这行数据和关联的锁数据结构,都在内存里面。
11_锁 - 图1
此时,如果另一个事务B来更新这行数据,会发现,这行数据已经被加锁了,那么事务B也会生成一个锁数据结构,里面有它的trx_id,和等待状态。
11_锁 - 图2
接着事务A更新完了这行数据,就会把自己的锁释放掉。锁释放后,还会去找有没有其他事物对这行数据进行加锁了,就会发现事务B也加锁了。
于是,就会把事务B的锁里面的等待状态改为false,然后唤醒事务B继续执行,此时事务B就获取到了锁。
11_锁 - 图3

2.独占锁和共享锁

X锁,也就是Exclude独占锁,当一个事务加了独占锁之后,其他事物再要更新这行数据,都需要加独占锁,但是只能生成独占锁后在后面等待。
如果有事务读取这行数据,是不用加锁的,因为MySQL默认开启了mvcc机制,对一行数据的读和写两个操作默认是不会加锁互斥的。
如果查询的时候想加锁,也是可以的。MySQL支持一种共享锁(S锁),语法:select * from table lock in share mode,意思就是查询的时候对一行数据加共享锁。
如果别的事务更新这行数据加了独占锁,就不能再加共享锁,因为共享锁与独占锁是互斥的,此时这个查询就只能等待。
如果加了共享锁,其他事务也可以加共享锁,共享锁之间是不会互斥的。
查询操作也能加互斥锁:select * from table for update。意思是,查出来的数据还需要更新,在事务提交之前,其他事物都不要更新这个数据。
默认情况下更新数据会加独占锁,查询数据时根据mvcc机制读取快照。

3.表锁

一般情况,不会去主动加表锁

  1. -- 表级共享锁
  2. LOCK TABLES xxx READ;
  3. -- 表级独占锁
  4. LOCK TABLES xxx WRITE;
  5. -- 释放锁
  6. UNLOCK TABLES;
  7. -- 查看表是否加锁
  8. SHOW OPEN TABLES;

资料:https://blog.csdn.net/li1325169021/article/details/115189338