在 InnoDB 存储引擎中,行锁实际上是加在索引上的,而不是直接加在表的行数据上。这是因为 InnoDB 使用了聚集索引(Clustered Index)来组织数据,表数据本身就是按照主键排序的。这意味着每一行数据都存储在主键索引中,而非主键索引则指向主键索引中的对应位置。理解索引和行锁的关系
- 聚集索引(Clustered Index):
•InnoDB 使用聚集索引作为主索引来组织数据。
•每一行数据都存储在聚集索引中,按主键排序。
•非主键索引(Secondary Indexes)包含主键值,并指向对应的聚集索引条目。 - 非主键索引(Secondary Indexes):
•非主键索引也称为辅助索引,它们包含索引列的值以及对应的主键值。
•通过非主键索引可以快速定位到对应的主键索引条目,进而找到具体的行数据。
行锁的具体实现当 InnoDB 对表中的某一行数据加锁时,实际上是在相应的索引条目上加锁。这是因为: - 记录锁(Record Locks):
•记录锁加在聚集索引的条目上,锁定具体的行数据。
•如果事务需要读取或修改某一行数据,InnoDB 会在该行的主键索引条目上加锁。 - 间隙锁(Gap Locks):
•间隙锁加在索引条目之间的间隙上。
•例如,如果表中有记录 A 和 B,那么在 A 和 B 之间存在一个间隙,可以对这个间隙加锁。 - Next-Key Locks:
•Next-Key Locks 是记录锁和间隙锁的组合,锁定一个记录及其之后的下一个记录之前的间隙。
•例如,如果事务需要锁定记录 A,那么 InnoDB 会锁定记录 A 以及 A 之后的间隙。
示例假设我们有一个表 accounts,包含以下字段:CREATE TABLE accounts (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
balance DECIMAL(10, 2)
);
表中有两条记录:
id name balance
1 Alice 100.00
2 Bob 200.00
索引结构
•聚集索引(Clustered Index):
•主键索引按 id 排序。
•表数据按 id 排序存储。
•非主键索引(Secondary Index):
•假设还有一个非主键索引 idx_name,按 name 排序。
•非主键索引 idx_name 包含 name 列的值以及对应的 id 值。
示例事务事务 T1START TRANSACTION;
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
UPDATE accounts SET balance = 150.00 WHERE id = 1;
COMMIT;
事务 T2START TRANSACTION;
SELECT * FROM accounts WHERE name = 'Alice' FOR UPDATE;
INSERT INTO accounts (name, balance) VALUES ('Charlie', 125.00);
COMMIT;
锁的实现 - 事务 T1:
•SELECT * FROM accounts WHERE id = 1 FOR UPDATE;:T1 在聚集索引的 id = 1 条目上加了一个排他锁。
•UPDATE accounts SET balance = 150.00 WHERE id = 1;:T1 更新记录 id = 1。 - 事务 T2:
•SELECT * FROM accounts WHERE name = 'Alice' FOR UPDATE;:T2 通过非主键索引 idx_name 定位到 name = 'Alice',然后在聚集索引的 id = 1 条目上加了一个排他锁。
•INSERT INTO accounts (name, balance) VALUES ('Charlie', 125.00);:T2 插入一条新记录 name = 'Charlie'。
行锁在索引上的具体实现
•记录锁:加在聚集索引的条目上。
•间隙锁:加在聚集索引条目之间的间隙上。
•Next-Key Locks:加在聚集索引的条目及其之后的间隙上。
示例说明假设我们有以下记录:
id name balance
1 Alice 100.00
2 Bob 200.00
•记录锁:如果事务 T1 需要锁定记录 id = 1,那么 T1 会在聚集索引的 id = 1 条目上加一个排他锁。
•间隙锁:如果事务 T2 需要锁定 id = 1 和 id = 2 之间的间隙,那么 T2 会在聚集索引的 id = 1 和 id = 2 之间的间隙上加一个间隙锁。
•Next-Key Locks:如果事务 T1 需要锁定记录 id = 1 及其之后的间隙,那么 T1 会在聚集索引的 id = 1 条目及其之后的间隙上加一个 Next-Key Lock。
总结在 InnoDB 中,行锁实际上是加在索引上的,而不是直接加在表的行数据上。这是因为 InnoDB 使用聚集索引来组织数据,表数据本身就是按照主键排序的。通过在索引上加锁,InnoDB 能够实现高效且细粒度的并发控制,从而提高并发性能并保证数据的一致性和完整性。内容由AI生成