前置知识:
锁机制是什么?
锁机制,就是为了让多个事务更新同一行数据的时候串行化执行,避免同时更新一行数据。锁机制最基础的执行过程如下:
- 事务A现在准备对id=1的数据行进行更新,发现这行数据没有被加任何的锁;然后就创建一个锁,锁包含了事务A的id和等待状态,等待状态=false。然后对这行数据进行更新操作。
- 事务B也准备对id=1的数据行进行更新,首先检查这行数据是否被加锁了;发现这行数据已经有一个锁,这时候,事务B也生成一个锁,同样包含事务的id和等待状态,但是他的等待状态=true,因为有别的锁正在执行。
- 事务A执行完毕,释放锁,然后去检查是否有其他事务也对这行数据加了锁,发现了事务B创建的锁;然后将事务B的锁的等待状态改为true,然后唤醒事务B执行。
因为锁的机制,实质上这个是独占锁,保证了不会有多个事务同时更新同一个数据行。所以就避免了脏写的问题。
行级锁
数据行使用的锁,就是行级锁。行级锁里面,有独占锁(X锁)和共享锁(S锁)。
独占锁一般在事务更新数据行的时候自动加锁。只允许1个独占锁在活动,其它独占锁必须等待。
共享锁一般在查询数据的时候使用。但是一般查询数据并不需要用到锁,使用锁还会导致并发的降低。只需要在查询的时候加上”lock in share mode”就可以加上共享锁了。例如”SELECT * FROM tb_user lock in share mode”。
共享锁和独占锁之间是互斥的:一行数据被加了共享锁后,那么如果还有其他的事务对它进行加独占锁的话,那么只能等待,不会一起执行。
共享锁和共享锁之间不互斥的:一行数据被加了共享锁后,其他事务也是可以进行加共享锁的操作。
有一点值得注意:查询也可以进行加独占锁,只需要在查询语句后加上”for update”即可,例如”SELECT * FORM tb_user for update”。意思是,当前事务查询出来的数据加了独占锁,其他事务不能对当前数据行加锁操作了。
表级锁
数据表使用的锁成为表级锁。表级锁也有独占锁和共享锁,但是表的锁还有意向锁,也就是意向独占锁和意向共享锁。
使用”LOCK TABLES table_name READ”就可以加表级共享锁。
使用”LOCK TABLES table_name WRITE”就可以加表级独占锁。
事务对一行数据进行增删改的时候,会对这行数据加独占锁,也会对表进行加意向独占锁。
事务对一行数据进行查询的时候,会直接对表加一个意向共享锁。
意向锁之间不会互斥。
