Skip to content
数据库锁

在数据库开发中,并发操作是常态——多用户同时读写数据、多服务同步操作同一表、分布式系统跨节点访问数据库,稍有不慎就会出现数据脏读、不可重复读、幻读等问题,导致数据不一致。而数据库锁,就是解决这些并发问题的核心工具,也是数据库模块开发中不可或缺的核心能力。

一、为什么需要数据库锁?

简单来说,数据库锁的核心作用是控制并发访问,避免多个事务同时操作数据导致的冲突。举个最常见的开发场景:

用户A和用户B同时给同一个账户充值100元,账户初始余额1000元。正常情况下,最终余额应为1200元,但如果没有锁控制,可能出现以下问题:

  1. 用户A读取余额:1000元;

  2. 用户B同时读取余额:1000元;

  3. 用户A操作:1000+100=1100,写入数据库;

  4. 用户B操作:1000+100=1100,覆盖写入数据库;

最终余额为1100元,少了100元——这就是典型的并发冲突(丢失更新)。而数据库锁,就是通过“排队”机制,让多个并发操作有序执行,避免此类问题。

核心目标:在保证数据一致性的前提下,尽可能提升并发性能(锁太严会导致性能下降,锁太松会导致数据错乱)。

二、锁的粒度

锁的粒度决定锁的影响范围

锁的粒度越小,影响范围越小,并发性能越好;粒度越大,数据越安全,但并发性能越差。开发中需根据业务场景选择合适粒度。

1. 全局锁

· 作用范围:整个数据库实例;

· 核心用途:全库备份、全库维护(如升级);

· 特点:锁定整个数据库,期间所有读写操作都被阻塞,并发性能极差,仅用于特殊场景;

· 示例:MySQL的FLUSH TABLES WITH READ LOCK(FTWRL),执行后全库只读,禁止写入。

2. 表锁

· 作用范围:整个数据表;

· 核心用途:表级操作(如ALTER TABLE、批量更新全表数据);

· 特点:锁定整个表,读写操作互斥(读锁共享,写锁排他),粒度大,并发性能一般;

· 适用场景:数据批量操作、表结构修改,避免操作过程中表数据被修改;

· 示例:MySQL的LOCK TABLES 表名 READ/WRITE,Redis的SETNX实现的表级分布式锁。

3. 行锁

· 作用范围:数据表中的某一行或多行数据;

· 核心用途:单条/多条数据的并发读写(如用户充值、订单修改);

· 特点:粒度最小,并发性能最好,仅锁定需要操作的行,不影响其他行的读写;

· 适用场景:高频并发读写、单条数据修改(最常用的锁粒度);

· 示例:MySQL InnoDB引擎的行锁(基于索引实现),Redis的Hash结构实现的行级分布式锁。

4. 页锁

· 作用范围:数据库的“页”(介于表和行之间的中间粒度);

· 特点:粒度介于表锁和行锁之间,并发性能中等;

· 说明:实际开发中极少用到,仅部分数据库(如MySQL MyISAM引擎、SQL Server)支持,InnoDB引擎不支持页锁。

三、锁的性质

所有锁本质上都围绕“读写”操作设计,核心分为共享锁和排他锁,两者的互斥规则是并发控制的核心。

1. 共享锁(S锁,读锁)

· 核心作用:用于读取数据,不允许修改;

· 互斥规则:多个事务可同时持有共享锁(读-读不互斥),但不能同时持有排他锁(读-写互斥);

· 示例:MySQL中执行SELECT ... FOR SHARE,会为查询的行添加共享锁,其他事务可读取,但不能修改。

2. 排他锁(X锁,写锁)

· 核心作用:用于修改数据(插入、更新、删除);

· 互斥规则:一个事务持有排他锁时,其他事务既不能持有共享锁,也不能持有排他锁(写-读、写-写都互斥);

· 示例:MySQL中执行UPDATE、DELETE、INSERT,或SELECT ... FOR UPDATE,会自动为操作的行添加排他锁,阻塞其他读写操作。

四、锁的实现方式

结合你数据库模块中的MySQL、Redis,重点区分“本地锁”和“分布式锁”,这是开发中最易混淆也最常用的分类。

1. 本地锁(单机锁)

· 作用范围:单个数据库实例、单个应用节点;

· 实现方式:数据库原生支持(如MySQL InnoDB行锁、表锁);

· 适用场景:单机应用、单数据库实例,无分布式部署需求;

· 注意:仅能控制单个节点的并发,多节点部署时会失效(如分布式应用中,多个节点同时操作同一数据,本地锁无法跨节点控制)。

2. 分布式锁

· 作用范围:多个应用节点、多个数据库实例(分布式系统);

· 实现方式:基于第三方组件实现(如Redis、ZooKeeper),跨节点同步锁状态;

· 适用场景:分布式应用、微服务架构(你当前的项目大概率会用到);

· 示例:用Redis的SETNX命令实现分布式锁,用ZooKeeper的临时有序节点实现分布式锁。

五、总结

数据库锁的核心是“平衡数据一致性与并发性能”,开发中无需追求“最复杂的锁机制”,只需根据业务场景选择合适的锁粒度、锁类型即可。