数据库在哪些复杂操作或并发冲突下会触发锁表现象?
- 内容介绍
- 文章标签
- 相关推荐
说到数据库死锁。循环等待导致的不可预期停滞
当多个事务互相请求对共享资源加锁时若出现循环依赖,数据库会检测并触发死锁。此时程序会自动回滚其中一个事务,以释放资源。
痛点:你是否在高并发场景下遇到“事务被回滚”的错误?这往往是因为未合理划分锁粒度或使用了过于复杂的关联查询。
维护操作中的表级锁
- 索引重建 / 调整:需要锁定相关表,防止修改导致不一致。
- 再看统计信息更新,一样可能加全表锁以保证准确性。
痛点:你是否因维护操作导致业务宕机?通常是因为在峰值期间执行了全表重建,导致业务无法访问。
备份与恢复期间的全表加锁
在备份或恢复过程中。为保证数据完整性,数据库会对所有受影响的表加上排他锁,阻止其他写入操作。
痛点:备份时间过长,让使用者无法正常写入;如何减少停机时间,
长事务对性能的侵蚀
长时间占用行、页或键范围锁。会让后续事务等待,从而导致响应延迟甚至超时。话说回来,
痛点:你的业务逻辑是否存在一次性处理大量数据的长事务?其实,这会直接拖累整体吞吐量。
并发控制与冲突排查
- 冲突锁:当两个事务需要同一组资源时如果无法继续,会触发死锁;DBMS 会选择回滚一个。
- NoLock/READ UNCOMMITTED:可减少读冲突,但可能读取脏数据;需根据业务一致性要求决定。
痛点:你是否频繁收到“死锁”日志?这说明事务间缺乏良好隔离与优先级控制。
Avoid Heavy Table Locks with Distributed Mechanisms
对于业务级复杂逻辑。可通过 Redis、ZooKeeper 等分布式锁代替行级/页级 DB 锁,降低数据库压力,提高可 性。
锁粒度与类型概览
- 共享锁: 允许多个读,但阻止写。
- X 排他锁: 只允许持有者读写,其余阻塞。其实,
- I 意向锁: 表示下层将要加共享或排他行级别的意图。用于提高并发效率,
- K 键范围/键槽: 适用于 B+ 树索引中的范围查询。不过,
从P&Q来看。行级 vs 页级 vs 全表加锁?
1️⃣ 行级 - 最细粒度,适合大多数 CRUD;2️⃣ 页级 - 针对大量行扫描;3️⃣ 全表 - 维护、DDL 或极端情况。建议: 尽量避免全表加锁,通过拆分表、分区或增量备份来减小影响面。
Mysql 中 SELECT ... FOR UPDATE 的陷阱
"SELECT ... FOR UPDATE" 会对所选行加排他行级别的 X 锁,即使只是读取也可能阻塞其它更新操作。请确认业务确实需要此功能,否则改用普通 SELECT 或 READ COMMITTED 隔离即可。
Xid 与隔离级别对 Lock 的影响
- SIMPLE READ / READ COMMITTED: 最小化读取冲突,仅对已提交数据进行读;适合 OLTP 场景,
- SERIALIZABLE: 最高隔离。需要更宽松的排他式读写,加大全局性能消耗。
Pain Point:如何根据业务需求设置隔离等级?
User Pain Points Recap & Best Practices
| Pain Point | 方法 / 建议 |
|---|---|
| 1. 长事务导致高等待时间 🔴 程序卡顿、超时频发 | - 分解为短周期批处理 💡 使用 “SEPOINT” 控制子事务 🔧 调整 batch size 至 100~500 条记录 |
| 2. 死锁频繁出现 | - 避免嵌套多层 SELECT JOIN 造成多重 lock 💡 按照统一顺序获取资源,例如先 lock A,再 lock B |
| 3. 维护期间业务不可用 | - 利用在线 DDL 或分区方式拆分 💡 定时执行。在低峰期完成 |
| 4. 并发读写冲突 | - 对热点字段使用 Redis 分布式缓存 💡 对大对象使用文件存储 + DB 指针 |
| 5. 全表加锁导致性能瓶颈 | - 使用 Partitioning 或 Sharding 减少单张大表压力 💡 对索引重建采用增量模式 |
从*注来看,上述方案均基于常见 MySQL 环境,可迁移至 MariaDB / PostgreSQL 等主流 RDBMS。*
。
说到数据库死锁。循环等待导致的不可预期停滞
当多个事务互相请求对共享资源加锁时若出现循环依赖,数据库会检测并触发死锁。此时程序会自动回滚其中一个事务,以释放资源。
痛点:你是否在高并发场景下遇到“事务被回滚”的错误?这往往是因为未合理划分锁粒度或使用了过于复杂的关联查询。
维护操作中的表级锁
- 索引重建 / 调整:需要锁定相关表,防止修改导致不一致。
- 再看统计信息更新,一样可能加全表锁以保证准确性。
痛点:你是否因维护操作导致业务宕机?通常是因为在峰值期间执行了全表重建,导致业务无法访问。
备份与恢复期间的全表加锁
在备份或恢复过程中。为保证数据完整性,数据库会对所有受影响的表加上排他锁,阻止其他写入操作。
痛点:备份时间过长,让使用者无法正常写入;如何减少停机时间,
长事务对性能的侵蚀
长时间占用行、页或键范围锁。会让后续事务等待,从而导致响应延迟甚至超时。话说回来,
痛点:你的业务逻辑是否存在一次性处理大量数据的长事务?其实,这会直接拖累整体吞吐量。
并发控制与冲突排查
- 冲突锁:当两个事务需要同一组资源时如果无法继续,会触发死锁;DBMS 会选择回滚一个。
- NoLock/READ UNCOMMITTED:可减少读冲突,但可能读取脏数据;需根据业务一致性要求决定。
痛点:你是否频繁收到“死锁”日志?这说明事务间缺乏良好隔离与优先级控制。
Avoid Heavy Table Locks with Distributed Mechanisms
对于业务级复杂逻辑。可通过 Redis、ZooKeeper 等分布式锁代替行级/页级 DB 锁,降低数据库压力,提高可 性。
锁粒度与类型概览
- 共享锁: 允许多个读,但阻止写。
- X 排他锁: 只允许持有者读写,其余阻塞。其实,
- I 意向锁: 表示下层将要加共享或排他行级别的意图。用于提高并发效率,
- K 键范围/键槽: 适用于 B+ 树索引中的范围查询。不过,
从P&Q来看。行级 vs 页级 vs 全表加锁?
1️⃣ 行级 - 最细粒度,适合大多数 CRUD;2️⃣ 页级 - 针对大量行扫描;3️⃣ 全表 - 维护、DDL 或极端情况。建议: 尽量避免全表加锁,通过拆分表、分区或增量备份来减小影响面。
Mysql 中 SELECT ... FOR UPDATE 的陷阱
"SELECT ... FOR UPDATE" 会对所选行加排他行级别的 X 锁,即使只是读取也可能阻塞其它更新操作。请确认业务确实需要此功能,否则改用普通 SELECT 或 READ COMMITTED 隔离即可。
Xid 与隔离级别对 Lock 的影响
- SIMPLE READ / READ COMMITTED: 最小化读取冲突,仅对已提交数据进行读;适合 OLTP 场景,
- SERIALIZABLE: 最高隔离。需要更宽松的排他式读写,加大全局性能消耗。
Pain Point:如何根据业务需求设置隔离等级?
User Pain Points Recap & Best Practices
| Pain Point | 方法 / 建议 |
|---|---|
| 1. 长事务导致高等待时间 🔴 程序卡顿、超时频发 | - 分解为短周期批处理 💡 使用 “SEPOINT” 控制子事务 🔧 调整 batch size 至 100~500 条记录 |
| 2. 死锁频繁出现 | - 避免嵌套多层 SELECT JOIN 造成多重 lock 💡 按照统一顺序获取资源,例如先 lock A,再 lock B |
| 3. 维护期间业务不可用 | - 利用在线 DDL 或分区方式拆分 💡 定时执行。在低峰期完成 |
| 4. 并发读写冲突 | - 对热点字段使用 Redis 分布式缓存 💡 对大对象使用文件存储 + DB 指针 |
| 5. 全表加锁导致性能瓶颈 | - 使用 Partitioning 或 Sharding 减少单张大表压力 💡 对索引重建采用增量模式 |
从*注来看,上述方案均基于常见 MySQL 环境,可迁移至 MariaDB / PostgreSQL 等主流 RDBMS。*
。

