面试题答案
一键面试1. 三种锁的定义
- 共享锁(Shared Lock,简称 S 锁):又称读锁,多个事务可以同时对同一数据加共享锁,用于读取操作,互不影响。当一个事务对数据加了共享锁后,其他事务只能再加共享锁,不能加排他锁。
- 排他锁(Exclusive Lock,简称 X 锁):又称写锁,一旦一个事务对数据加了排他锁,其他事务就不能再对该数据加任何锁,确保在写操作时数据的一致性。
- 意向共享锁(Intention Shared Lock,简称 IS 锁):表示事务意图在更低层次的资源上加共享锁。例如,事务想要给表中的某一行加共享锁,那么首先要给表加意向共享锁。
2. 相互作用
- IS 锁与 S 锁:如果一个事务要对某行数据加 S 锁,首先需要获得表级的 IS 锁。多个事务可以同时持有表级的 IS 锁,且可以在 IS 锁存在的情况下,对不同行数据加 S 锁。例如,事务 T1 给表 A 加了 IS 锁,事务 T2 也可以给表 A 加 IS 锁,然后 T1 可以给表 A 中的行 r1 加 S 锁,T2 可以给表 A 中的行 r2 加 S 锁。
- IS 锁与 X 锁:当一个事务持有表级的 IS 锁时,其他事务不能对该表加 X 锁。只有当表上没有任何 IS 锁(以及更低层次的 S 锁)时,才能加 X 锁。例如,事务 T1 给表 A 加了 IS 锁,此时事务 T2 不能给表 A 加 X 锁,必须等 T1 释放 IS 锁后,T2 才能加 X 锁。
- S 锁与 X 锁:一个数据上如果有 S 锁,其他事务只能再加 S 锁,不能加 X 锁;如果有 X 锁,则其他事务不能加任何锁。例如,事务 T1 给行 r 加了 S 锁,事务 T2 可以给行 r 再加 S 锁,但不能加 X 锁;若 T1 给行 r 加了 X 锁,T2 不能对行 r 加任何锁。
3. 对系统性能和数据一致性的影响
- 性能影响:
- 优点:意向锁机制减少了锁检查的范围,提高了并发性能。例如,在大表中,通过意向锁可以快速判断是否可以在表级或行级加锁,避免了对每一行都进行锁状态检查。
- 缺点:过多的意向锁可能导致锁竞争,尤其是在高并发写操作场景下,意向锁的获取和释放可能成为性能瓶颈。
- 数据一致性影响:
- 优点:通过意向锁与共享锁、排他锁的配合,确保了在并发访问数据时,读操作之间、读操作与写操作之间、写操作之间的数据一致性。例如,写操作(X 锁)会阻止其他读(S 锁)和写(X 锁)操作,保证了写操作时数据的一致性;读操作(S 锁)之间不相互影响,但会阻止写操作(X 锁),避免了脏读。
- 缺点:如果锁的使用不当,例如锁的粒度设置不合理,可能导致数据一致性问题。比如,使用表级锁而不是行级锁,可能会造成不必要的锁等待,影响数据的并发访问,进而影响数据一致性。
4. 举例说明
假设有一个银行转账的场景,从账户 A 向账户 B 转账 100 元。表结构如下:
CREATE TABLE accounts (
id INT PRIMARY KEY,
balance DECIMAL(10, 2)
);
- 使用意向锁和共享锁、排他锁的情况:
- 事务 T1 开始转账操作,首先获取 accounts 表的 IS 锁,然后获取账户 A 的 X 锁(因为要更新账户 A 的余额),获取账户 B 的 X 锁(因为要更新账户 B 的余额)。
START TRANSACTION; -- 获取表级 IS 锁(隐式操作) -- 获取账户 A 的 X 锁 SELECT balance FROM accounts WHERE id = A FOR UPDATE; -- 获取账户 B 的 X 锁 SELECT balance FROM accounts WHERE id = B FOR UPDATE; UPDATE accounts SET balance = balance - 100 WHERE id = A; UPDATE accounts SET balance = balance + 100 WHERE id = B; COMMIT;
- 此时,如果事务 T2 想要读取账户 A 的余额,由于 T1 持有 accounts 表的 IS 锁以及账户 A 的 X 锁,T2 只能等待 T1 释放锁。
START TRANSACTION; -- 等待 T1 释放锁 SELECT balance FROM accounts WHERE id = A; COMMIT;
- 如果没有意向锁机制,T2 在读取账户 A 余额时,需要检查表中每一行的锁状态,这将大大增加系统开销。而有意向锁后,T2 发现表上有 IS 锁,就知道有事务正在对表中的某些行进行操作,从而避免了不必要的检查,提高了并发性能,同时保证了数据一致性。