mysql中读写锁的使用与性能调优
发布时间 - 2026-01-09 00:00:00 点击率:次SELECT ... FOR UPDATE 用于先查后改场景(如扣库存),加排他锁;SELECT ... LOCK IN SHARE MODE 用于协同只读场景(如报表),加共享锁;二者均需事务、索引支持,否则退化为表锁或间隙锁。
MySQL 中 SELECT ... FOR UPDATE 和 SELECT ... LOCK IN SHARE MODE 的适用场景
这两个语句是 InnoDB 实现行级读写锁的核心手段,但它们不是“加锁就能用”,而是必须在事务中生效,且只对索引列有效。如果 WHERE 条件未命中索引,InnoDB 会退化为表锁(或间隙锁组合),导致并发骤降。
-
SELECT ... FOR UPDATE:适用于需要“先查后改”的典型场景,比如扣减库存、转账前校验余额——它会加排他锁(X 锁),阻塞其他事务的读写
-
SELECT ... LOCK IN SHARE MODE:适合多事务需协同读取同一数据但不修改的场景,比如生成报表时防止基础数据被删——它加共享锁(S 锁),允许其他事务加 S 锁,但阻塞 X 锁 - 两者都要求事务隔离级别为
READ COMMITTED或REPEATABLE READ;在READ UNCOMMITTED下会被忽略
为什么 FOR UPDATE 有时锁住整张表而不是某几行
根本原因在于锁的粒度由执行计划决定,而非 SQL 表面写法。即使写了 WHERE id = 123,若 id 列没有索引,优化器无法定位具体行,只能走全表扫描,进而对所有聚簇索引记录加 X 锁——表现就是“锁表”。
- 用
EXPLAIN检查执行计划:type字段必须是const、ref或range,不能是ALL或index - 注意隐式类型转换:比如
WHERE user_id = '123'(字段是INT),会导致索引失效,锁范围扩大 - 唯一索引和普通索引行为不同:非唯一索引可能触发间隙锁(Gap Lock),锁住不存在的值区间,造成意外阻塞
高并发下锁等待超时与死锁的实际应对
Lock wait timeout exceeded 和 Deadlock found when trying to get lock 是线上最常遇到的两类锁问题,但它们成因和处理方式完全不同。
- 锁等待超时(
Lock wait timeout exceeded):通常是事务持有锁时间过长(比如事务里混入 HTTP 调用、日志写入或 sleep),应缩短事务生命周期,把非数据库操作移出事务块 - 死锁(
Deadlock found when trying to get lock):本质是循环等待,MySQL 会自动回滚代价小的事务。关键不是避免死锁(不可能完全避免),而是让应用能捕获errno 1213并重试——尤其对幂等性操作(如更新状态)必须支持重试逻辑 - 通过
SHOW ENGINE INNODB STATUS\G查看最近死锁详情,重点关注TRANSACTION块中的lock_mode X locks rec but not gap等描述,定位哪几行/哪个索引被争抢
替代方案:用 INSERT ... ON DUPLICATE KEY UPDATE 或 REPLACE INTO 规避显式锁
当业务逻辑本质是“存在则更新,不存在则插入”,硬上 SELECT ... FOR UPDATE + INSERT/UPDATE 不仅代码冗长,还放大锁竞争。这类场景优先考虑原子性更强的替代语法。
-
INSERT ... ON DUPLICATE KEY UPDATE:依赖唯一索引(主键或UNIQUE约束),整个操作由 InnoDB 内部加锁完成,无需手动控制事务顺序,性能更稳 -
REPLACE INTO:底层是DELETE + INSERT,会触发两次索引查找和锁操作,且可能引发自增 ID 跳变,在高并发下不如前者可控 - 注意:这两者仍会加锁,但锁的持有时间极短(仅在索引查找和行修改瞬间),且无事务上下文依赖,天然规避了长事务锁表风险
INSERT INTO order_lock (order_id, status, updated_at) VALUES (1001, 'processing', NOW()) ON DUPLICATE KEY UPDATE status = 'processing', updated_at = NOW();锁的复杂性不在语法本身,而在于它和索引、事务、隔离级别、执行路径深度耦合。一个没走索引的
FOR UPDATE,比十个没加锁的 UPDATE 更容易拖垮系统。
# mysql
# ai
# 隐式类型转换
# 为什么
# 有锁
# sql
# for
# select
# const
# errno
# int
# 循环
# delete
# 类型转换
# 并发
# 数据库
# http
# 死锁
# 加锁
# 不存在
# 锁住
# 重试
# 几行
# 不可能
# 两次
# 适用于
# 这两个
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
php增删改查怎么学_零基础入门php数据库操作必知基础【教程】
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
如何用手机制作网站和网页,手机移动端的网站能制作成中英双语的吗?
在线制作视频的网站有哪些,电脑如何制作视频短片?
Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理
Laravel如何实现文件上传和存储?(本地与S3配置)
微信小程序 input输入框控件详解及实例(多种示例)
Linux虚拟化技术教程_KVMQEMU虚拟机安装与调优
Internet Explorer官网直接进入 IE浏览器在线体验版网址
Claude怎样写约束型提示词_Claude约束提示词写法【教程】
北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?
如何在沈阳梯子盘古建站优化SEO排名与功能模块?
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
php读取心率传感器数据怎么弄_php获取max30100的心率值【指南】
如何用5美元大硬盘VPS安全高效搭建个人网站?
jimdo怎样用html5做选项卡_jimdo选项卡html5实现与切换效果【指南】
Laravel怎么发送邮件_Laravel Mail类SMTP配置教程
如何基于云服务器快速搭建网站及云盘系统?
手机软键盘弹出时影响布局的解决方法
网页制作模板网站推荐,网页设计海报之类的素材哪里好?
,网页ppt怎么弄成自己的ppt?
企业网站制作这些问题要关注
开心动漫网站制作软件下载,十分开心动画为何停播?
Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置
微信公众帐号开发教程之图文消息全攻略
黑客入侵网站服务器的常见手法有哪些?
Laravel定时任务怎么设置_Laravel Crontab调度器配置
谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复
php 三元运算符实例详细介绍
html5如何实现懒加载图片_ intersectionobserver api用法【教程】
Android仿QQ列表左滑删除操作
如何在阿里云部署织梦网站?
Laravel模型关联查询教程_Laravel Eloquent一对多关联写法
专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?
JS中页面与页面之间超链接跳转中文乱码问题的解决办法
bootstrap日历插件datetimepicker使用方法
Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验
教你用AI润色文章,让你的文字表达更专业
javascript事件捕获机制【深入分析IE和DOM中的事件模型】
Laravel中间件如何使用_Laravel自定义中间件实现权限控制
Laravel如何使用Eloquent进行子查询
Laravel如何使用.env文件管理环境变量?(最佳实践)
惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?
如何在局域网内绑定自建网站域名?
活动邀请函制作网站有哪些,活动邀请函文案?
如何用AWS免费套餐快速搭建高效网站?
深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?
谷歌浏览器如何更改浏览器主题 Google Chrome主题设置教程
Laravel如何生成PDF或Excel文件_Laravel文档导出工具与使用教程
Laravel storage目录权限问题_Laravel文件写入权限设置


