Mysql 中的锁机制
在 MySQL 中,锁是一种机制,用于管理并发访问以确保数据的一致性和完整性。MySQL 支持多种类型的锁,主要分为以下几类:
- 全局锁:锁定整个数据库,适用于备份等操作,期间禁止所有其他操作。
- 表级锁:锁定整个表,其他事务在锁定期间无法对该表进行写操作,但可以进行读操作(取决于锁的类型)。
- 读锁(共享锁):多个事务可以同时获取读锁,允许并发读取,但不允许写入。
- 写锁(排他锁):只有一个事务可以获取写锁,阻止其他事务的读和写操作。
- 行级锁:只锁定特定的行,允许更高的并发性。
- 共享锁:允许其他事务读取被锁定的行,但不允许写入。
- 排他锁:阻止其他事务读取和写入被锁定的行。
- 意向锁:在 MySQL 中,意向锁(Intention Lock)是一种表级锁,用于指示一个事务希望在某些行上获取锁。意向锁主要用于优化事务的并发控制,防止锁的冲突。
- 意向共享锁(IS):表示事务希望在某些行上获取共享锁。
- 意向排他锁(IX):表示事务希望在某些行上获取排他锁。
假设有一个表 员工,包含员工的记录。 - 事务 T1:
- T1 先对 员工 表加一个意向排他锁(IX)。
- 然后,T1 想要对行 1 加排他锁。
- 事务 T2:
- T2 也想要对 员工 表加意向排他锁(IX)。
- 然后,T2 试图对行 2 加排他锁。
- 锁的流程:
- 当 T1 为表加 IX 锁时,其他事务不能在该表上加排他锁,但可以加意向共享锁。
- 一旦 T1 获取了表的意向排他锁,它就能顺利地在行 1 上获取排他锁。
- 同样,T2 也能在没有冲突的情况下加 IX 锁,并在行 2 上获取排他锁。
- 意向锁通过在表级上指示意图,帮助 MySQL 确保行级锁的有效获取,防止潜在的锁冲突,提高并发性能。
在 MySQL 中,自适应哈希索引锁是 InnoDB 存储引擎的一种优化机制,用于提高查询性能。自适应哈希索引会根据访问模式自动创建哈希索引,从而加速特定查询的处理。主要特点如下:
- 自动创建:InnoDB 会根据查询的频率和模式自动决定是否创建哈希索引。
- 提高性能:对于特定类型的查询(如点查找),哈希索引可以显著加快访问速度。
假设有一个员工表 employees,其主键为 employee_id,并且经常进行基于员工 ID 的查询。
- 许多事务频繁地查询 SELECT * FROM employees WHERE employee_id = 123;。
- 由于该查询模式频繁,InnoDB 会自动在 employee_id 列上创建一个自适应哈希索引。
- 当后续查询到该哈希索引时,查询可以直接使用哈希表而不是扫描 B+ 树索引,从而提高查询性能。
- 当自适应哈希索引被创建时,InnoDB 会在使用该哈希索引的查询上加锁,确保在查询过程中数据的一致性。
- 如果有多个事务尝试访问同一个哈希索引,可能会产生锁竞争。
- 自适应哈希索引锁通过自动优化查询过程,提高了 MySQL 的性能,但在高并发情况下,可能导致锁竞争。
元数据锁(MDL):在对表结构进行更改时(如添加列或索引),MySQL 会使用元数据锁,确保在DDL操作期间没有其他操作干扰。
在 MySQL 中,死锁是指两个或多个事务相互等待对方释放锁,导致所有相关事务无法继续执行的情况。死锁会影响数据库的并发性能,因此需要及时检测并处理。假设有两个事务 T1 和 T2:
- 事务 T1 首先锁定 表 A 的行 1。然后尝试锁定 表 B 的行 1。
- 事务 T2 首先锁定 表 B 的行 1。然后尝试锁定 表 A 的行 1。
- T1 锁定了表 A 的行 1,并等待获取表 B 的行 1。
- T2 锁定了表 B 的行 1,并等待获取表 A 的行 1。
- 此时,T1 和 T2 互相等待,导致死锁。
- 解决方式:MySQL 会自动检测死锁,并回滚其中一个事务,释放其占有的锁,以使另一个事务得以继续执行。
间隙锁:在 MySQL 中,间隙锁(Gap Lock)是一种特殊类型的锁,用于防止其他事务在已锁定记录的前后插入新的记录。间隙锁通常在使用 InnoDB 存储引擎时出现,主要用于支持多版本并发控制(MVCC)和避免幻读。
假设有一个员工表 employees,其中包含员工的薪资信息,且我们要查询薪资在某个范围内的员工。
+-------------+-------+
| employee_id | salary|
+-------------+-------+
| 1 | 5000 |
| 2 | 6000 |
| 3 | 7000 |
+-------------+-------+
- T1 执行查询 SELECT * FROM employees WHERE salary BETWEEN 5500 AND 7500 FOR UPDATE;。
- InnoDB 会对满足条件的记录加锁,并在 5500 和 7500 之间的间隙上加间隙锁。
- 由于 T1 的查询,InnoDB 会在 5500 和 6000 之间、以及 6000 和 7000 之间加上间隙锁,防止其他事务在这些间隙中插入新记录。
- 这样,其他事务无法插入薪资为 5800 或 6200 的新员工。
- 间隙锁通过锁定数据之间的“间隙”,有效防止幻读现象,确保事务的隔离性。
在 MySQL 中,Next-Key Lock 是一种结合了行锁和间隙锁的锁机制,主要用于 InnoDB 存储引擎。Next-Key Lock 旨在防止幻读,同时允许并发访问。
- Next-Key Lock 锁定的是一个范围,包括一个记录及其前后的间隙。
- 它锁定的目标是特定的行,同时也防止其他事务在该行之前或之后插入新的记录。
假设有一个员工表 employees,其结构如下:
+-------------+-------+
| employee_id | salary|
+-------------+-------+
| 1 | 5000 |
| 2 | 6000 |
| 3 | 7000 |
+-------------+-------+
- 事务 T1:
- T1 执行查询 SELECT * FROM employees WHERE salary >= 6000 FOR UPDATE;。
- InnoDB 将对 salary = 6000 的记录加锁,并且在 6000 之前和之后的间隙上加锁。
- 锁定情况:
- T1 锁定了记录 salary = 6000,同时在 5000 和 6000 之间(间隙锁)以及 6000 和 7000 之间(间隙锁)加了锁。
- 这样,其他事务无法插入薪资为 5800 或 6500 的新员工。
- Next-Key Lock 通过锁定目标行及其前后间隙,有效防止幻读现象,确保事务的隔离性和数据的一致性。
锁的类型和使用场景对于保证数据库的并发性能和数据一致性至关重要。
原文地址:https://blog.csdn.net/qq_41893505/article/details/144292508
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!