数据库锁机制
-
MySQL 中的锁机制
-
共享锁(S 锁)和排他锁(X 锁)
-
在 MySQL 中,基于事务的隔离级别来实现锁机制。共享锁允许同时有多个事务读取同一数据,但不允许其他事务对该数据进行写操作。排他锁则在事务对数据进行写操作时使用,此时其他事务既不能读取也不能写入该数据。
-
例如,在一个事务中使用
SELECT... LOCK IN SHARE MODE
语句可以对查询的数据添加共享锁。如果另一个事务也想对同一数据添加排他锁,就会被阻塞,直到共享锁释放。而SELECT... FOR UPDATE
语句则会对查询的数据添加排他锁。
-
-
行级锁、表级锁和页级锁
-
行级锁:MySQL 的 InnoDB 存储引擎支持行级锁,这是一种细粒度的锁。它可以对表中的单行数据进行锁定,这样在多用户并发访问时,不同的事务可以同时操作不同行的数据,大大提高了并发性能。例如,当两个用户同时更新一个表中的不同行记录时,InnoDB 可以通过行级锁允许这两个操作同时进行,而不会相互干扰。
-
表级锁:MyISAM 存储引擎主要使用表级锁,这种锁的粒度比较粗。当一个事务对表进行操作时,会锁定整个表。例如,在一个事务对 MyISAM 表进行写操作时,其他事务无论是读还是写该表都需要等待锁的释放。虽然表级锁并发性能相对较差,但在某些特定的场景下(如批量操作)可能更高效。
-
页级锁:介于行级锁和表级锁之间,它锁定的是数据页(一个数据页包含多行数据)。这种锁在实际应用中相对较少,主要是为了平衡行级锁的高并发和表级锁的低开销,但它的实现和管理相对复杂。
-
-
意向锁
- 在 InnoDB 中,还有意向锁的概念。当一个事务在表中的某一行添加行级锁时,会自动在表级添加意向锁。意向锁主要是为了在事务处理过程中,让更高层次(如数据库引擎)快速了解表中是否有行级锁存在。例如,有事务对表中的某几行添加了排他行级锁,此时会在表级添加意向排他锁。当另一个事务想要对整个表添加表级锁时,通过检查意向锁就可以知道表中有行级锁,从而避免冲突。
-
-
其他数据库的锁机制示例(以 Oracle 为例)
-
行排他锁(RX)和共享行排他锁(SRX)
-
Oracle 也有类似的锁机制。行排他锁可以防止其他事务对同一行进行读写操作,而共享行排他锁允许其他事务对同一行进行读操作,但不能进行写操作。
-
例如,在 Oracle 中可以使用
SELECT... FOR UPDATE
语句来添加行排他锁,确保事务在更新数据时的独占性。
-
-
自动锁升级和降级
- Oracle 数据库有自动锁升级和降级的机制。当一个事务对大量行进行操作时,可能会从行级锁自动升级为表级锁,以减少锁管理的开销。相反,当事务的操作范围缩小,也可能会自动从表级锁降级为行级锁,提高并发性能。这种自动机制可以根据数据库的实际运行情况灵活调整锁的粒度。
-
-
数据库层面实现锁机制的一般步骤
-
事务开始:当一个事务开始时,数据库会根据事务的操作类型和隔离级别来确定是否需要加锁以及加何种锁。
-
锁获取:如果需要锁,事务会尝试获取相应的锁。如果锁已经被其他事务占用,根据数据库的锁等待策略,事务可能会等待一段时间或者直接返回错误。
-
数据操作:在获取锁之后,事务可以对锁定的数据进行读取或写入操作。
-
锁释放:当事务完成操作或者回滚时,会释放之前获取的锁,使其他事务能够访问相应的数据。
-