按粒度分类
全局锁
- 含义:全局锁会锁定整个数据库实例,在其生效期间,其他事务无法对数据库进行任何读写操作。常用于数据迁移、数据备份场景。
表级锁
- 表锁:是对整张表进行锁定的机制。实现逻辑简单,加锁和释放锁速度快,系统负面影响小,能有效避免死锁问题。不过,因其锁定粒度大,锁定资源争用概率高,会降低并发度。MyISAM、MEMORY、CSV 等非事务性存储引擎主要使用表级锁定。
- 意向锁:属于表级锁,目的是实现多粒度锁机制,允许行锁和表锁共存。分为意向共享锁(IS)和意向排他锁(IX) 。意向共享锁表明事务后续想获取表中某些行的共享锁;意向排他锁则表示事务后续想获取表中某些行的排他锁。意向锁可快速判断表中是否已有记录被加锁,提升加锁效率。
- 元数据锁:在执行 DML(增删改查)或 DDL(结构变更)操作时,数据库会自动添加。用于保护数据库对象(如表、视图等)的元数据信息,防止在操作过程中,元数据被其他事务修改,保证数据结构的一致性和稳定性。
行级锁
- 记录锁:锁定单个数据记录。InnoDB 存储引擎中,若表建立时未设置索引,会使用隐式主键进行锁定。
- 间隙锁:锁定索引记录之间的 “间隙”,防止其他事务在该间隙插入数据。
- 临键锁:是记录锁和间隙锁的组合,既锁定当前行,又锁定该行之后的间隙。
- 插入意向锁:事务在插入数据时会获取,用于表示插入意向。它与其他事务的插入意向锁兼容,不同事务可并发插入数据到同一索引区间,提高插入操作的并发性能。
按行为分类
共享锁
SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;
- 含义:也叫读锁,允许事务读取数据,但不允许修改。多个事务可同时获取共享锁。
- 应用场景:适用于多个事务同时读取同一数据的场景,如报表生成、数据统计等操作,多个事务可同时加共享锁读取数据,互不干扰。
排他锁
SELECT * FROM table_name WHERE id = 1 FOR UPDATE;
- 含义:又称写锁,只允许一个事务对特定数据进行读写操作,其他事务无法对该数据加任何类型的锁。
- 应用场景:用于数据修改操作,如插入、更新、删除等。在进行这些操作前,需先加排他锁,防止其他事务同时修改数据,保证数据修改的原子性和一致性。
按模式分类
悲观锁
- 策略:一种假设并发冲突总会发生的策略,每次在访问数据前,都会对数据加锁,包括共享锁、排他锁等。
- 应用场景:在并发冲突概率较高,或对数据一致性要求极高的场景中适用。例如在金融交易系统中,资金转账操作需确保数据准确一致,常使用悲观锁防止并发问题。
乐观锁
- 策略:假设并发冲突不会发生,不主动加锁。通常通过版本号或时间戳字段实现。在更新数据时,先比较版本号或时间戳,若数据未被其他事务修改,才进行更新操作。
- 应用场景:适用于并发冲突概率较低的场景,能减少锁的开销,提高系统并发性能。如一些读操作频繁,写操作相对较少且冲突概率低的系统中可使用。
避免死锁
- 确保事务访问数据顺序一致:在多个事务并发访问数据时,通过合理加锁,确保事务按特定顺序访问数据,避免因并发操作导致数据不一致。
- 合理使用索引:建立合适索引,能让查询更精准,减少锁的范围,避免因索引不当导致锁升级为表锁,进而降低死锁风险
- 控制事务大小:使用较小事务,减少事务执行时间和锁持有时间,降低多个事务互相等待锁的可能性,从而避免死锁。
. 控制事务大小:使用较小事务,减少事务执行时间和锁持有时间,降低多个事务互相等待锁的可能性,从而避免死锁。 - 设置锁等待超时时间:通过设置合理的锁等待超时时间,当事务等待锁时间超过该值时自动回滚,打破死锁循环,防止因死锁导致系统长时间无法运行。在 MySQL 中,可通过相关参数配置来设置锁等待超时时间。