使用共享锁(S锁)
- 事务场景:
- 假设有事务
T1
,想要读取users
表中id
为1的记录,同时希望其他事务也能读取该记录,但不允许修改。
- 在MySQL中,使用
SELECT...LOCK IN SHARE MODE
语句来获取共享锁。例如:
START TRANSACTION;
SELECT id, name FROM users WHERE id = 1 LOCK IN SHARE MODE;
-- 这里事务T1对id为1的记录获取了共享锁,可以进行读取操作
-- 其他事务可以并发读取这条记录,但不能获取排他锁进行修改
COMMIT;
- 体现共享特性:多个事务可以同时获取共享锁,对同一数据进行读取操作。如果有事务
T2
也执行SELECT id, name FROM users WHERE id = 1 LOCK IN SHARE MODE;
,它可以顺利获取共享锁并读取数据,因为共享锁之间不互斥。
使用排他锁(X锁)
- 事务场景:
- 假设有事务
T3
,想要修改users
表中id
为1的记录,为了保证数据一致性,必须阻止其他事务读取或修改该记录。
- 在MySQL中,使用
SELECT...FOR UPDATE
语句来获取排他锁。例如:
START TRANSACTION;
SELECT id, name FROM users WHERE id = 1 FOR UPDATE;
-- 这里事务T3对id为1的记录获取了排他锁
-- 其他事务不能获取共享锁或排他锁来访问这条记录
UPDATE users SET name = 'new_name' WHERE id = 1;
COMMIT;
- 体现排他特性:排他锁具有排他性,一旦事务
T3
获取了排他锁,其他事务无论是想获取共享锁还是排他锁,都必须等待T3
释放锁。例如事务T4
执行SELECT id, name FROM users WHERE id = 1 LOCK IN SHARE MODE;
或SELECT id, name FROM users WHERE id = 1 FOR UPDATE;
,都会被阻塞,直到T3
执行COMMIT
或ROLLBACK
释放排他锁。
互斥性体现
- 共享锁与排他锁互斥:
- 如果事务
T1
持有id
为1记录的共享锁,此时事务T3
尝试获取该记录的排他锁,T3
会被阻塞。因为共享锁允许并发读取,但不允许修改,排他锁用于修改数据,二者不能同时存在。
- 反之,如果事务
T3
持有id
为1记录的排他锁,事务T1
尝试获取共享锁,T1
同样会被阻塞。这就保证了在数据修改时,不会有其他事务同时进行读取或修改操作,维护了数据的一致性和完整性。