1.共享锁(读锁)
语法:select … lock in share mode
若事务T1对记录A加上共享锁,则事务T1可以读A也可以修改A(如果修改A,共享锁变为排它锁),事务T2只能再对A加共享锁,而不能加排它锁,此时T1和T2只能读A而不能修改A(多个事务同时持有共享锁时,无法修改数据)。这保证了其他事务可以读A,但在事务T1释放A上的共享锁之前不能对A做任何修改
共享锁可以被多个事务持有,但是只能读,不能修改
2.排它锁(写锁、独占锁)
语法:select … for update
若事务T1对记录A加上排它锁,则事务T1可以读A也可以修改A,其它事务不能再对A加任何锁(共享锁/排它锁),直到T1释放A上的排它锁。这保证了其他事务在事务T1释放A上的排它锁之前不能再读取和修改A
排他锁不能被多个事务持有
3.MySQL中InnoDB加锁机制
- select… :不加锁
- select… lock in share mode:加共享锁
- select… for update:加排它锁
- update/delete/insert:默认加排它锁
4.【案例一】事务T1对记录A加共享锁并且修改A,事务T2不能再对A加共享锁
- 事务T1对记录A加共享锁并且修改A,此时共享锁变为排他锁
begin; select * from user where id = '1' lock in share mode; update user set name = "after" where id = "1";
- 事务T2不能再对A加共享锁(一直阻塞直到事务T1提交)
begin; select * from user where id = '1' lock in share mode;
5.【案例二】事务T1对记录A加共享锁,事务T2也对记录A加共享锁,此时事务T1不能修改记录A
- 事务T1对记录A加共享锁
begin; select * from user where id = '1' lock in share mode;
- 事务T2也对记录A加共享锁
begin; select * from user where id = '1' lock in share mode;
- 事务T1不能修改记录A(一直阻塞直到事务T2提交)
update user set name = "after" where id = "1";
5.【案例三】事务T1对记录A加上排它锁之后,事务T2能否读记录A?
事务T1
begin;
select * from user where id = '1' for update;
情况一:事务T2因为要加共享锁,所以不能读记录A,要等待事务T1释放id=1记录的排它锁
begin
select * from user where id = '1' lock in share mode;
情况二:事务T2因为要加排它锁,所以不能读记录A,要等待事务T1释放id=1记录的排它锁
begin
select * from user where id = '1' for update;
情况三:事务T2可以读A
begin
select * from user where id = '1';
commit;