MVCC,MySQL中常见的锁

发布于:2025-03-01 ⋅ 阅读:(13) ⋅ 点赞:(0)

事务模块完整学习:MySQL事务

MVCC

Multi-Version Concurrency Control 多版本并发控制
【事务】
MVCC是一种用于数据库管理系统中实现并发控制的技术,它允许在同一时间对数据进行多个事务的读写操作,同时保证数据的一致性和隔离性。

原理

通过版本号的比较和管理,MVCC 可以在不使用锁的情况下,实现多个事务的并发读写操作。
读操作不会阻塞写操作,写操作也不会阻塞读操作,从而提高并发性能。

  1. 版本号
    MVCC 依赖于数据行的版本号来实现并发控制。
    在支持 MVCC 的数据库(如 MySQL 的 InnoDB 存储引擎)中,每一行数据都有一个隐藏的版本号字段,用于标识该行数据的版本。当数据被修改时,版本号会递增。

  2. 事务版本号 :每个事务在开始时都会被分配一个唯一的事务版本号,这个版本号在事务的生命周期内保持不变。


  3. 当一个事务执行读操作时,它会根据自身的事务版本号和数据行的版本号来判断应该读取哪个版本的数据。
    如果数据行的版本号小于等于事务的版本号,说明该数据行在事务开始之前已经存在或被修改,事务可以读取该版本的数据。这样可以避免读取到尚未提交的事务修改的数据,从而实现了读操作的一致性。


  4. 当一个事务执行写操作时,它会创建一个新的数据行版本,并将其版本号设置为当前系统的最大版本号加 1。
    同时,旧的数据行版本仍然保留,以便其他事务可以读取。在提交事务时,会将新的数据行版本标记为已提交。

共享锁 Shared Lock S锁

读锁。
加了共享锁后,其他事务也可以该数据加共享锁。
多个事务可以同时读取数据。

排他锁 Exclusive Lock X锁

写锁。
加排他锁后,其他事务不能对该数据加任何锁。因此能防止其他事务同时修改数据,保证了数据一致性。

INSERTUPDATEDELETE"SELECT... FOR UPDATE" 语句时,会对操作的数据加排他锁。

SELECT… FOR UPDATE” 语句

当执行 “SELECT… FOR UPDATE” 语句时,数据库会对查询结果集中的行加上排他锁。
一旦加上排他锁,其他事务就不能对这些行再加任何锁(包括共享锁和排他锁),直到当前持有排他锁的事务提交或回滚释放锁为止
这样可以保证在当前事务对这些数据进行操作时,不会被其他事务干扰,确保数据的一致性和完整性。

START TRANSACTION;
SELECT stock FROM products WHERE product_id = 1 FOR UPDATE;
-- 检查库存并进行扣减操作
UPDATE products SET stock = stock - 1 WHERE product_id = 1;
COMMIT;

意向锁 Intention Lock

表级别的锁,表示事务对表中数据行的加锁意图。
当一个事务想要对表中的某一行数据加共享锁时,会先对意向共享锁
当一个事务想要对表中的某一行数据加排他锁时,会先对意向排他锁

意向锁的存在是为了提高锁的检查效率,避免对表中的每一行数据都进行锁的检查:

假设没有意向锁,当一个事务想要对整个表加表级别的排他锁时,数据库需要逐行检查表中的每一行数据是否已经被其他事务加了行级锁。
如果表中的数据量非常大,这种逐行检查的操作会非常耗时,严重影响性能。
例如:想对一表加共享锁,而此表有一行加了排他锁,所以此表有一个意向排他锁,那我们就知道不能对此表加共享锁。

行锁 Row Lock

锁的粒度最小,并发性能最高。

表锁 Table Lock

锁的粒度最大,并发性能最低。
ALTER TABLE 语句。

间隙锁 Gap Lock

锁定一个范围内的数据,可以防止其他事务在该范围内插入新的数据,从而避免了幻读问题。(但是能修改🤓)

间隙锁通常与行锁一起使用,形成 Next-Key Lock(临键锁)。

临键锁(Next-Key Lock)

临键锁是间隙锁和行锁的组合,它锁定一个左开右闭的区间。