MySQL的行级锁锁的到底是什么?
1 个回答
先解决心情在解决事情。追日在 MySQL 中,行级锁(Row-level Lock)锁定的实际上是**特定行在聚簇索引(主键索引)上的记录**,而不是具体的数据内容或辅助索引记录。行级锁的实现依赖于索引的设计和查询条件的使用情况。 ### 行级锁的本质 1. **基于聚簇索引**:在 MySQL 的 InnoDB 存储引擎中,行级锁是基于聚簇索引实现的。聚簇索引(通常是主键索引)管理了数据行的物理存储位置,因此,行级锁锁定的实际上是聚簇索引中具体行的位置(即主键对应的行记录)。 2. **辅助索引的访问方式**: - 如果查询使用了辅助索引(如非主键的唯一索引或普通索引),InnoDB 会首先通过辅助索引定位行,然后在定位到的行记录上加锁。 - 但最终的行锁仍然是加在聚簇索引上,即每行只有一把锁,统一管理在聚簇索引中,而不是直接锁定辅助索引中的位置。 3. **锁的范围**:行级锁只锁定满足查询条件的特定行记录,而不会锁定整个表,粒度较细。因此,即便有多个辅助索引,InnoDB 也只会锁定查询实际访问到的那行的聚簇索引记录。 ### 示例 假设我们有如下的 `users` 表,其中主键是 `id`,`email` 是唯一索引,`name` 是普通索引: ```sql CREATE TABLE users ( id INT PRIMARY KEY, -- 主键索引(聚簇索引) email VARCHAR(255) UNIQUE, -- 辅助唯一索引 name VARCHAR(50), -- 普通辅助索引 age INT ); ``` #### 使用主键锁定行 ```sql -- 事务 A START TRANSACTION; SELECT * FROM users WHERE id = 1 FOR UPDATE; ``` - 在这条语句中,事务 A 通过主键索引 `id` 查询并锁定 `id = 1` 的行。 - InnoDB 会直接在 `id = 1` 的聚簇索引记录上加锁。 #### 使用辅助索引锁定行 ```sql -- 事务 B START TRANSACTION; SELECT * FROM users WHERE email = 'test@example.com' FOR UPDATE; ``` - 在这条语句中,事务 B 使用 `email` 辅助索引来定位行。 - InnoDB 会通过 `email` 辅助索引找到 `id = 1` 这行数据,但最终锁定的仍然是 `id = 1` 的聚簇索引记录。 ### 总结 - **锁定的是聚簇索引上的行记录**:无论使用主键索引还是辅助索引查询,最终的行锁都加在该行的聚簇索引记录上。 - **统一管理和检测冲突**:由于所有行锁都加在聚簇索引上,MySQL 可以通过聚簇索引统一管理锁定和冲突检测,确保不同索引查询时的锁一致性。 - **并发控制的细粒度**:行级锁粒度细,只锁定实际查询到的行,因此并发性较高。发布于 2024-11-09 02:36 •IP属地 黑龙江举报评论收藏
公众号进入网站体验更佳

