mysql如何避免大批量数据修改锁全表_使用分批提交技术

MySQL UPDATE大表时看似锁全表,实为行锁升级+MVCC版本链拉长导致阻塞;分批更新须基于主键范围切分、控单事务≤1000行、加短延时,禁用OFFSET;无索引时优先加索引或改用主键子查询。UPDATE 大表时为什么锁全表MySQL 的 UPDATE 在未命中索引或扫描行数过多时,InnoDB 会升级锁粒度------从行锁退化为间隙锁甚至表级意向锁,配合事务隔离级别(尤其是 REPEATABLE READ),实际效果就是"像锁了整张表"。你看到的"卡住其他查询",往往不是真锁表,而是大量行锁堆积 + MVCC 版本链拉长,导致后续语句等锁、等回滚、等 purge 线程清理旧版本。常见错误现象:SHOW PROCESSLIST 里一堆 Updating 状态;SELECT 查询明显变慢甚至超时;INFORMATION_SCHEMA.INNODB_TRX 显示事务长时间运行且 TRX_ROWS_LOCKED 高达百万级。分批 UPDATE 的核心控制点分批不是简单加个 LIMIT 就完事。关键在三件事:用主键/唯一索引驱动分页、控制每批事务大小、避免 OFFSET 滚动扫描。必须基于主键范围切分,例如:WHERE id BETWEEN ? AND ?,而不是 LIMIT 1000 OFFSET 10000(后者越往后越慢,且可能漏数据)每批提交前确认影响行数,用 ROW_COUNT() 判断是否还有数据可处理单事务控制在 1000 行以内(具体看单行大小和 binlog 格式,STATEMENT 模式下大事务更危险)批次间加短延时(如 SLEEP(0.1)),缓解主从复制压力和锁竞争示例逻辑(伪代码):SET @start_id = 0;WHILE @start_id < (SELECT MAX(id) FROM t) DO UPDATE t SET status = 1 WHERE id > @start_id AND id <= @start_id + 1000; SELECT ROW_COUNT() INTO @affected; IF @affected = 0 THEN LEAVE; END IF; SET @start_id = @start_id + 1000; COMMIT; DO SLEEP(0.1);END WHILE;WHERE 条件没走索引怎么办这是最常踩的坑:以为加了 LIMIT 就安全,结果执行计划显示 type: ALL,全表扫描+全表加锁。分批的前提是每次都能快速定位到下一批起点。 文心快码 文心快码(Comate)是百度推出的一款AI辅助编程工具

相关推荐
爬也要爬着前进18 分钟前
redis主从搭建
数据库·redis·缓存
@Mike@37 分钟前
02-数据库学习笔记(SQL引擎)
数据库·笔记·学习
我的xiaodoujiao2 小时前
快速学习Python基础知识详细图文教程9--函数进阶
开发语言·python·学习·测试工具
笃行3502 小时前
国产化落地避坑 · 干货向|Oracle 迁金仓 KES,我把外连接消除排在隐性陷阱第一位
数据库
weixin_408099672 小时前
2026 图片去水印 API 接口完全指南:一键去除图片水印(附 Python/Java/PHP/C# 示例)
java·python·php·图片处理·api调用·图片去水印·石榴智能
老纪的技术唠嗑局2 小时前
花一年时间整理出的:AI 数据库混合搜索入门实践
数据库
去码头整点薯条ing3 小时前
某当网登录滑块【协议+OCR】
爬虫·python·ocr
川石课堂软件测试3 小时前
安全测试|常见SQL注入攻击方式、实例及预防
服务器·数据库·sql·功能测试·测试工具·安全·单元测试
笃行3503 小时前
国产化落地避坑 · 干货向|迁移后那条「测试能过、一上生产就查空」的 SQL,多半栽在 WHERE 函数顺序上
数据库
赶紧写完去睡觉3 小时前
Anaconda 创建虚拟环境与使用
python·pycharm·conda