0

0

SQL锁机制怎么理解_详细步骤拆解实现完整应用场景【技巧】

冰川箭仙

冰川箭仙

发布时间:2025-12-15 22:06:07

|

525人浏览过

|

来源于php中文网

原创

锁的本质是协调读写冲突,按粒度分为全局锁、表级锁、行级锁及间隙锁/Next-Key锁,按类型分为共享锁、排他锁和意向锁;实际加锁行为取决于SQL的索引使用、条件匹配和隔离级别。

sql锁机制怎么理解_详细步骤拆解实现完整应用场景【技巧】

锁的本质是协调读写冲突

数据库不是单线程程序,多个事务同时操作同一数据时,必须有人“排队”或“划地盘”。锁就是这个规则制定者——它不改变数据本身,而是告诉其他事务:“这块你暂时不能碰”。重点不在“加锁动作”,而在于“什么情况下必须加、加哪种、加多大范围”。

按粒度分:从整库到单行,选对范围才不卡死

锁的范围直接决定并发能力。范围越大,冲突越多;越小,控制越精细,但管理开销越高。

  • 全局锁:`FLUSH TABLES WITH READ LOCK`,整个实例只读。仅用于全库逻辑备份(如 mysqldump),InnoDB 一般不用,MVCC + `--single-transaction` 更安全高效。
  • 表级锁:`LOCK TABLES t WRITE`,整张表被独占。MyISAM 默认使用;InnoDB 在 DDL(如 ALTER TABLE)或显式调用时触发。适合批量导入、统计类低频操作。
  • 行级锁:InnoDB 默认行为。例如 `UPDATE users SET balance = balance - 100 WHERE id = 123`,只要 id 是主键或唯一索引,就只锁这一行。高并发点查/更新的核心依赖。
  • 间隙锁 & Next-Key 锁:防幻读的关键。比如 `SELECT * FROM orders WHERE price > 100 FOR UPDATE`,不仅锁住所有 price > 100 的现有行,还会锁住这些值之间的“空隙”,阻止新记录插入该区间。

按类型分:共享 vs 排他,读写权限要分清

锁不是“有或无”,而是带权限属性的访问凭证。

  • 共享锁(S 锁):`SELECT ... LOCK IN SHARE MODE` 或 `FOR SHARE`(MySQL 8.0+)。允许多个事务同时读,但谁都不能改。适合“查完要校验再决定是否操作”的场景,比如秒杀前检查库存是否充足。
  • 排他锁(X 锁):`SELECT ... FOR UPDATE`,或任何 `UPDATE/DELETE/INSERT` 隐式触发。当前事务独占读写权,其他事务连 S 锁都申请不到。这是修改数据前的强制安检门。
  • 意向锁(IS/IX):InnoDB 自动加,你不用写。比如你要给某行加 X 锁,引擎会先在表上加 IX 锁,告诉别人:“我下面要锁行了”。它不阻塞操作,只起快速探测作用,避免每次加行锁都要扫全表查有没有表锁。

真实 SQL 怎么触发锁?关键看三要素

同一句 `SELECT ... FOR UPDATE`,在不同条件下锁的范围可能差十倍。判断依据就三个:

Quinvio AI
Quinvio AI

AI辅助下快速创建视频,虚拟代言人

下载
  • WHERE 条件是否命中索引:`WHERE id = 100`(id 主键)→ 行锁;`WHERE name LIKE '%abc%'`(无索引或全表扫描)→ 退化为表锁。
  • 索引类型是否唯一:用唯一索引(主键/UNIQUE)精准定位 → 只锁匹配行;用普通二级索引 → 先锁二级索引项,再回主键索引加锁,可能锁多行。
  • 隔离级别是否为 SERIALIZABLE:该级别下所有普通 `SELECT` 都自动变成 `LOCK IN SHARE MODE`,慎用。

示例对比:
`SELECT * FROM user WHERE id = 5 FOR UPDATE` → 锁 id=5 的那一行
`SELECT * FROM user WHERE status = 1 FOR UPDATE`(status 无索引)→ 锁全表
`SELECT * FROM user WHERE age BETWEEN 20 AND 30 FOR UPDATE`(age 有索引)→ 加 Next-Key 锁,覆盖 [20,30] 区间及前后间隙

实战避坑:别让锁变成性能瓶颈

锁本身不是问题,滥用和误判才是。

  • 事务别拖太久:`BEGIN; SELECT ... FOR UPDATE; 处理业务逻辑几十秒; COMMIT;` —— 这等于把锁挂墙上展览,别人全得等。
  • 避免非必要锁:普通查询不用加 `FOR UPDATE`,InnoDB MVCC 能保证快照读,又快又安全。
  • 更新语句尽量走索引:没索引的 `WHERE` 条件会让 InnoDB 扫全表,锁住所有扫描过的行,极易引发锁等待甚至死锁。
  • 注意隐式锁升级:当一行锁数量超过阈值(默认 5000),InnoDB 可能自动升级为页锁甚至表锁,监控 `innodb_row_lock_waits` 指标可发现异常。

基本上就这些。理解锁,核心是建立“SQL → 索引路径 → 扫描范围 → 实际加锁类型”的映射链,而不是背口诀。动手跑几条带 `EXPLAIN` 和 `SELECT * FROM information_schema.INNODB_TRX` 的语句,比读十篇文档都管用。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

684

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

323

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

348

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1117

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

359

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

717

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

577

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

419

2024.04.29

菜鸟裹裹入口以及教程汇总
菜鸟裹裹入口以及教程汇总

本专题整合了菜鸟裹裹入口地址及教程分享,阅读专题下面的文章了解更多详细内容。

0

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.9万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 805人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号