数据库锁表:先看清锁在哪一行

锁表这件事,第一反应就去重启数据库的,十个里有好几个后来都后悔。数据库锁表大部分时候不是锁坏掉了,而是有人在等另一个人:一个跑了很久的查询,一个忘记提交的事务,一条卡在半路的 ALTER TABLE。监控上看到的是一排请求超时,数据库里其实是一张排队表。先看清谁堵着谁,再动手,顺序反了就是白折腾一整晚。

MySQL数据库

数据库锁表,八成是有人在等

连上去第一件事不是 kill。先 SHOW PROCESSLIST,State 那一列出现 Locked 或者 Waiting for table metadata lock 的,基本都是排队的;再看 information_schema.INNODB_TRX,重点不是有多少行,是 trx_started 那一列——开得最早、trx_state 还是 RUNNING 的那个,嫌疑最大。MySQL 8.0 之后 performance_schema.data_locks 和 data_lock_waits 更好用,谁等谁一行一行摆在那里;5.7 及更早还能查 information_schema.INNODB_LOCKS,8.0 里这两张表已经移除了,照着几年前的文章敲命令敲不出来,不是你的问题。

PROCESSLIST 只能说明有人在等,说不清是被谁等。等待链一长,它就给不出答案了。这也是为什么不少人 kill 掉一个会话,几秒钟之后同样的报错又回来——被干掉的那个只是队伍中间的一位,队伍前面的人还堵在那里。

锁还分好几类,行锁、表锁、元数据锁

类型分不清,处理办法就会用错。InnoDB 默认是行级锁,两个人同时改同一行才撞上;MyISAM 是表锁,一个人写整张表都在等,一些跑着老程序的老站点上还能见到这种。第三种最容易被误判:元数据锁 MDL,一条 ALTER TABLE 挂在那里没走完,后面所有查询一起排队,现象是网站突然全站卡住,可你去看 CPU、IO 都不高,磁盘也不忙。这种要去 performance_schema.metadata_locks 里找,光盯着 PROCESSLIST 只能看到一堆 Waiting。

有了 thread id,才谈得上动手

找到堵点之后,记两样东西再动手:trx_mysql_thread_id,还有那条 SQL 原文。kill 之前不看语句的,事后基本都说不清是谁干的。KILL QUERY 只把那条语句停掉,会话还在;KILL CONNECTION 直接断会话,事务回滚、锁释放,但连接池那边立刻少一条连接,应用要能扛住这一下。半夜操作尤其注意,别顺手把连接池管理账号的会话给断了,那是另一个事故的起点。

长事务比死锁更常见

死锁这件事,数据库自己会检测并回滚其中一个,报 1213,SHOW ENGINE INNODB STATUS 里能看到 LATEST DETECTED DEADLOCK 那一段。更常见的是长事务:开了事务去调第三方接口,等用户点确认,甚至在事务里发通知邮件,一挂就是几分钟。锁一直不放,后面一堆请求排着队,表现出来就是数据库锁表。所以看 trx_started 往往比看锁的细节更有用,一条开了很久还没提交的事务,比十条死锁更值得先处理。

还有一类容易被忽略的:慢查询把锁的时间拖长。本来一条 UPDATE 几十毫秒的事,索引没走对扫了半张表,锁的持有时间跟着被拉长,并发一上来就排队。这类问题 kill 是治不了的,kill 完明天还来。要么补索引,要么把大更新拆成小批,一次几千行那样跑。

备份和 DDL,最像元凶的两个

mysqldump 在 MyISAM 表上会拿读锁,导出期间写入就得等着;InnoDB 加 –single-transaction 能拿到一致性快照而不锁表,但前提是相关表都是 InnoDB,混着引擎就不好说了。DDL 更微妙,8.0 有 online DDL,加索引多数情况不阻塞写入,可它仍然要拿元数据锁,同一张表上并发一多,排队立刻起来。表大的时候,gh-ost、pt-online-schema-change 这类工具比硬上 ALTER 稳当,用不用得看业务能不能接受那段切换时间。具体行为还是以你所用版本的官方文档为准,版本之间差得挺多。

顺便提一句主从。主库上锁着,从库也可能跟着延迟,你看到的现象可能是从库那边读到的数据停了几分钟。这种先看复制视图里的延迟值,别在主库上乱 kill——有些等待本来就在从库回放,动主库那条只会让情况更乱。

一个顺手的排查顺序

顺序大概是:一,先对时间点,告警从几点几分开始;二,PROCESSLIST 看排队的人;三,INNODB_TRX 看未提交事务的年龄;四,data_lock_waits 找等待链的头;五,怀疑 DDL 就去 metadata_locks;六,记下 SQL 再 kill;七,回头把那条慢语句的索引和事务边界改掉。少走一步问题都不大,跳过头两步直接 kill 的,多半隔一会儿又炸一次。

生产库上现场试验是最贵的一课。有人为了看锁,直接在业务高峰开个事务跑 SELECT … FOR UPDATE,一挂十几分钟,然后自己成了下一个要排查的对象。要看锁,去从库、去测试环境,或者挑业务低峰做,别在主库高峰上玩。

下次再遇上,先别急着登录服务器,在心里问一句:谁在等谁。这句话问出来,一半的问题自己就散了。剩下那一半,多半是索引没建好,或者事务开得太长——那就不是当晚能解决的事,得排进改动清单。

【版权声明】:本站内容若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!

赞 (0)
爱家的头像爱家
GPU实例是什么,和买显卡根本不是一回事
上一篇 2026-11-12 21:44
负载均衡三角模式是什么?如何实现高效流量分配?
下一篇 2024-12-04 14:18

相关推荐

  • 如何使用MSSQL存储过程实现高效的数据分页?

    在MSSQL中,可以使用ROW_NUMBER()函数和CTE(公共表表达式)进行分页。假设我们有一个名为”Employees”的表,并想要获取第2页的数据,每页有10条记录,我们可以这样编写存储过程:,,“`sql,CREATE PROCEDURE GetPagedEmployees,@PageNumber INT,,@PageSize INT,AS,BEGIN, SELECT *, FROM (, SELECT ROW_NUMBER() OVER (ORDER BY EmployeeID) AS RowNum, *, FROM Employees, ) AS Emp, WHERE (RowNum ˃= (@PageNumber 1) * @PageSize + 1 AND RowNum

    2024-08-12
    0012
  • 无规则32k服务器究竟指的是什么?

    无规则32k服务器是一种网络服务器,它允许用户在没有特定游戏规则限制的情况下进行在线游戏。这种服务器通常用于支持32,000个并发连接,适用于大型多人在线游戏或社区。

    2024-07-25
    0026
  • 启明星辰的服务器品牌名称是什么?

    启明星辰的服务器名字没有公开的具体信息。公司不会公开其服务器的具体名称,因为这些信息可能关系到公司的安全和隐私。

    2024-07-25
    0020
  • git 克隆本地服务器_Git本地研发场景

    在Git本地研发场景中,克隆本地服务器的仓库至本地电脑进行版本控制管理,可以使用Git命令行工具通过SSH协议进行操作。执行git clone命令并输入服务器的主机名及仓库路径,即可实现快速克隆,无需联网,方便后续的代码开发和版本管理。

    2024-07-02
    0017

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

广告合作

QQ:14239236

在线咨询: QQ交谈

邮件:asy@cxas.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信