Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MySql事务未提交导致锁等待如何解决?

MySql事务未提交导致锁等待如何解决?

作者头像
chengcheng222e
发布于 2021-11-19 08:00:17
发布于 2021-11-19 08:00:17
4K00
代码可运行
举报
文章被收录于专栏:简栈文化简栈文化
运行总次数:0
代码可运行
背景

我们来先看一个图,了解一下故()事()的背景:

http://static.cyblogs.com/Jietu20211113-162059.jpg

2个跑批任务,其实做的事情是同一件事情,都是为了跟下游系统保持数据的一致性。大任务是每隔2h跑一次,小任务是每隔10mins跑一次。除了这2个定时任务以外,还有一个额外的监控任务来做类似的对账,如果发现出现对账不平,就会出现邮件/短信告警到相关的责任上。

这是一个非常有特点的定时任务跑批任务+监控告警的场景了。

从上面的场景上看,我们可以得出一些结论:为了保证一致性写了大小Job来保证,并且还给出了监控告警,说明数据的重要性是比较强的。

某天,出现了频繁的告警提示,每10分钟就告警一次,而且内容没有发生变化,说明同步的index没有变化过。

错误排查
任务有在正常的执行吗?

第一反应肯定是在思考,我的大任务与小任务都有正常执行吗?因为之前的都是正常的。看了一下日志与进程发现有在跑,除了多次任务,日志打印不明确,看不到具体分支的逻辑。总结一下问题点:

  • 任务很忌讳出现上一个任务没有跑完,下一个任务又继续开启一个新的任务,给服务器带来了不少的压力。一般如果对接了好的分布式调度能力,基本也很容易解决这个问题。
  • 关键分支日志打印不明确,导致定位很难

先修复上面2个问题,短时间对接一个新的分布式调度时间上不可能,只能简单的改shell脚本让其不执行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
d=`date`

count=`ps -ef |grep {jobKeyword} |grep -v grep | wc -l`
if [ $count -lt 1 ]; then
  echo "$d : do {jobKeyword} . " >> /data/{projectName}/sync.log
  python xxxxx.py
else
  echo "$d : {jobKeyword} no finished, this time do nothing. " >> /data/{projectName}/sync.log
fi

然后在重点的地方添加上日志,其实这些操作都是一些非常简单,但是可以带来明显效果的步骤。反正,我基本都是如此的去做的,你什么信息都拿不到,你根本无法入手。

部署上去后,发现每次在insert into一条数据的时候,日志就卡住了,结合代码确定,确定就是insert into的时候,数据库没有返回,而其他的表以及其他数据的都是可以正常操作的。

出现了LOCK WAIT

第一反应,就是看下这条SQL现在是一个什么状态?我们可以利用SHOW PROCESSLIST看下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select * from information_schema.PROCESSLIST t;

SELECT * FROM information_schema.innodb_trx ORDER BY trx_started ;

然后就发现该SQL语句的trx_state=LOCK WAIT,那说明没有获取到锁。那我们具体如何推断是谁没有释放锁了?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 第1:
SELECT * FROM information_schema.innodb_locks ;

# 第2步:12没有特别的先后顺序,之后为了确定trx_requested_lock_id以及是谁获取了锁lock_trx_id + local_data
SELECT * FROM information_schema.innodb_trx t where t.trx_state = 'LOCK WAIT';

# 第3步:找到对应的执行语句
select * from information_schema.PROCESSLIST t where t.id = {lock_trx_id}

可惜,那条语句已经是sleep的状态了,无法看到具体的SQL。在这里可以推断,就是有一条SQL在对数据{local_data}操作的时候获取了一把锁,但是因为事务未提交,导致后面的SQL再对{local_data}操作的时候要获取锁,无法获取到。理论上获取不到锁,一会儿也会释放掉报错出来。通过查询innodb_lock_wait_timeout=7200,默认值应该是50

解决掉问题

到这一步就很明确了,就是让未提交事务的SQL结束掉,或者提交掉。此时只有kill掉这个进程的选项了。执行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
kill {lock_trx_id};

再执行就立马发现数据没有了,获取到了锁。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT * FROM information_schema.innodb_trx t where t.trx_state = 'LOCK WAIT';
总结一下
  • innodb_lock_wait_timeout 设置不合理,时间太久了
  • 出现获取不到锁的场景,需要告警到邮件、手机上来。
  • 大任务与小任务的时间要搓开,出现这种情况也是对同一行数据进行X操作并且未释放锁导致的。把事务的时间搞短一点。可以每次都去获取连接,也不要一次连接执行很长时间。
实验性操作

就直接看脚本好了

http://static.cyblogs.com/Jietu20211113-171928.jpg

当右边的事务对同一条数据进行X操作的时候,它是要获取锁的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

这个时候可以去看下锁的表

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select * from information_schema.innodb_locks;
+-----------------+-------------+-----------+-----------+---------------+------------+------------+-----------+----------+-----------+
|lock_id         | lock_trx_id | lock_mode| lock_type | lock_table    | lock_index| lock_space | lock_page | lock_rec | lock_data |
+-----------------+-------------+-----------+-----------+---------------+------------+------------+-----------+----------+-----------+
|757082:3279:3:2 | 757082      | X         | RECORD    | `test`.`test` | PRIMARY    |      3279 |         3 |       2 | 1         |
|757081:3279:3:2 | 757081      | X         | RECORD    | `test`.`test` | PRIMARY    |      3279 |         3 |        2 | 1         |
+-----------------+-------------+-----------+-----------+---------------+------------+------------+-----------+----------+-----------+
2 rowsin set, 1 warning (0.00 sec)

查看一下设置的超时时间

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
|Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout|  50  |
+--------------------------+-------+

看关于事务的描述

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
show engine innodb status

查看当前的事务

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mysql> show processlist;
+----+-----------------+-----------+--------------------+---------+--------+------------------------+------------------+
| Id | User            | Host      | db                 | Command | Time   | State                  | Info             |
+----+-----------------+-----------+--------------------+---------+--------+------------------------+------------------+
|  5 | event_scheduler | localhost | NULL               | Daemon  | 286110 | Waiting on empty queue | NULL             |
|  8 | root            | localhost | test               | Sleep   |    956 |                        | NULL             |
|  9 | root            | localhost | test               | Sleep   |    754 |                        | NULL             |
| 10 | root            | localhost | information_schema | Query   |      0 | init                   | show processlist |
+----+-----------------+-----------+--------------------+---------+--------+------------------------+------------------+
4 rows in set (0.01 sec)
参考地址
  • https://blog.51cto.com/corasql/1923427

如果大家喜欢我的文章,可以关注个人订阅号。欢迎随时留言、交流。如果想加入微信群的话一起讨论的话,请加管理员微信号:chengcheng222e,他会拉你们进群。

简栈文化服务订阅号

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 简栈文化 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Mysql 异常:Lock wait timeout exceeded; try restarting transaction的解决办法
  接口响应时间超长,耗时几十秒才返回错误提示,后台日志中出现Lock wait timeout exceeded; try restarting transaction的错误
chenchenchen
2021/09/06
3.7K0
MySQL线上维护三脚本
1. 获取process和lock的现场信息(get_processlist.sh) #!/bin/bash source /home/mysql/.bashrc DT=`date '+%Y%m%d_%H%M%S'` mysql -uroot -p123456 -S /data/3306/mysqldata/mysql.sock -e "select t1.* from information_schema.processlist t1,(select count(1) c from informatio
用户1148526
2021/12/07
3550
MySQL 死锁的详细分析方法
用数据库的时候,偶尔会出现死锁,针对我们的业务系统,出现死锁的直接结果就是系统卡顿、客户找事儿,所以我们也在想尽全力的消除掉数据库的死锁。出现死锁的时候,如果只是想解锁,用show full processlist看下kill掉就好了,如果想查找到详细的问题,一个办法是用show engine innodb status来查看简略信息或者开死锁日志,后期在MySQL日志里面慢慢分析。以上这写方法我们都用过,最近在看Innodb的书的时候发现另一种实时的分析方法,能最大限度的分析死锁的原因。
星哥玩云
2022/08/17
5500
Mysql长事务总结
在结果中idletime是计算产生的,也是事务的持续时间。但事务的trxquery是NUL,这并不是说事务什么也没执行,一个事务可能包含多个SQL,如果SQL执行完毕就不再显示了。当前事务正在执行,innodb也不知道这个事务后续还有没有sql,啥时候会commit。 因此trx_query不能提供有意义的信息。
mingjie
2022/05/12
9150
Mysql长事务总结
pt-online-schema-change使用
如果说你的数据量并发量不大,或者你的数据量很少没有到千万级别,也许pt-osc、gh-osc,online-ddl这些工具都用不着。但是,如果你的数据量很大,数据又很热。如果你没有这些工具,你可能无法完成对一个数据库新增一个字段或者任何一个简单的DDL语句。
chengcheng222e
2021/11/03
9410
pt-online-schema-change使用
技术分享 | MySQL 行锁超时排查方法优化
之前在 [如何有效排查解决 MySQL 行锁等待超时问题] 文章中介绍了如何监控解决行锁超时报错,当时介绍的监控方案主要是以 shell 脚本 + general_log 来捕获行锁等待信息,后来感觉比较麻烦,因此优化后改成用 Event + Procedure 的方法定时在 MySQl 内执行,将行锁等待信息记录到日志表中,并且加入了 pfs 表中的事务上下文信息,这样可以省去登陆服务器执行脚本与分析 general_log 的过程,更加便捷。
爱可生开源社区
2021/02/26
5110
技术分享 | MySQL 行锁超时排查方法优化
MySQL-长事务详解
『入门MySQL』系列文章已经完结,今后我的文章还是会以MySQL为主,主要记录下近期工作及学习遇到的场景或者自己的感悟想法,可能后续的文章不是那么连贯,但还是希望大家多多支持。言归正传,本篇文章主要介绍MySQL长事务相关内容,比如说我们开启的一个事务,一直没提交或回滚会怎样呢,出现事务等待情况应该如何处理,本篇文章将给你答案。
MySQL技术
2019/09/23
3.4K0
MySQL探秘(五):InnoDB锁的类型和状态查询
 锁是数据库系统区分于文件系统的一个关键特性。数据库使用锁来支持对共享资源进行并发访问,提供数据的完整性和一致性。此外,数据库事务的隔离性也是通过锁实现的。InnoDB在此方面一直优于其他数据库引擎。InnoDB会在行级别上对表数据上锁,而MyISAM只能在表级别上锁,二者性能差异可想而知。
aoho求索
2018/12/12
1.1K0
MySQL探秘(五):InnoDB锁的类型和状态查询
MySQL找出未提交事务的信息
我们经常会碰到这样的情况,某个事务执行完了未提交,后续再来一个DDL和DML操作,导致后面的session要么处于waiting for metadata lock,要么是锁等待超时。这时我们往往只能找到这个未提交的事务的事务id和session id,但是一般都处于sleep状态,不好分析事务内容到底是什么,所以通常都是粗鲁地kill这个session后解决问题,但是应用层的研发人员往往找不到到底是哪个事务引起的,后面再出现问题时还要重复kill。
用户1148526
2020/03/31
5.2K0
InnoDB如何快速杀掉堵塞会话的思考
我们在运维MySQL的过程中,肯定多多少少遇到过Innodb row lock的问题,如果在线上遇到我们可能会看到一大片的session处于堵塞状态通常我们在show processlist中会看到如下:
老叶茶馆
2021/01/12
1.1K0
InnoDB如何快速杀掉堵塞会话的思考
MySQL 锁机制和事务
InnoDB存储引擎支持行级锁 其大类可以细分为共享锁和排它锁两类 共享锁(S):允许拥有共享锁的事务读取该行数据。当一个事务拥有一行的共享锁时,另外的事务可以在同一行数据也获得共享锁,但另外的事务无法获得同一行数据上的排他锁
星哥玩云
2022/08/17
8610
MySQL 锁机制和事务
Mysql一分钟定位 Next-Key Lock,你需要几分钟
查看线程模型 show variables like 'thread_handling'
王清培
2020/01/27
4170
mysql innodb_trx参数详解
1、innodb_trx表提供了当前innodb引擎内每个事务的信息(只读事务除外),包括当一个事务启动,事务是否在等待一个锁,以及交易正在执行的语句(如果有的话)。查询语句:
用户14527
2022/03/24
4.2K0
MySQL 死锁与日志二三事
最近线上 MySQL 接连发生了几起数据异常,都是在凌晨爆发,由于业务场景属于典型的数据仓库型应用,白天压力较小无法复现。甚至有些异常还比较诡异,最后 root cause 分析颇费周折。那实际业务当中咱们如何能快速的定位线上 MySQL 问题,修复异常呢?下文我会根据两个实际 case,分享下相关的经验与方法。 1、Case1:部分数据更新失败 某天渠道同学反馈某报表极个别渠道数据为 0,大部分渠道数据正常。这个数据是由一个统计程序每天凌晨例行更新的,按理来说,要么全部正常,要么全部失败,那会是什么原因导
用户1177713
2018/02/24
2.9K0
MySQL 死锁与日志二三事
DBBrain最佳实践:未提交事务的处理与应对
DBBrain 上经常会有用户来咨询“未提交事务”的事件会有什么问题,该如何处理等。其实这个问题的影响属于可大可小,所以正好来专门分析一下,避免因为轻视了这个问题导致严重的业务故障。
王文安@DBA
2022/03/03
2.9K2
DBBrain最佳实践:未提交事务的处理与应对
MySQL/MariaDB的锁超详细讲解
使用begin或者start transaction来显式开启一个事务,显式开启的事务必须使用commit或者rollback显式提交或回滚。几种特殊的情况除外:行版本隔离级别下的更新冲突和死锁会自动回滚。
星哥玩云
2022/08/16
1.2K0
MySQL/MariaDB的锁超详细讲解
【MySQL】说透锁机制(三)行锁升表锁如何避免? 锁表了如何排查?
在上文我们曾小小的提到过,在索引失效的情况下,MySQL会把所有聚集索引记录和间隙都锁上,我们称之为锁表,或叫行锁升表锁.
天罡gg
2022/12/29
3K0
【MySQL】说透锁机制(三)行锁升表锁如何避免? 锁表了如何排查?
MySQL锁等待问题
昨天有个项目 一直登陆不上去,查看日志报错信息:ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
sunonzj
2022/06/21
7140
MySQL锁等待问题
[1156]MySQL数据库可用性监控脚本
从mysql性能字典表,innodb_lock_waits 是锁信息,innodb_trx是事务信息,有两条记录,需要放到一行中,因此,需要关联2次。
周小董
2022/08/23
1.2K0
为什么MySQL没有负载,但交易却跑不动?
在MySQL的数据库中,我们有时会发现MySQL数据库明明没有负载,CPU、硬盘、内存和网络等资源都很空闲,但很多SQL都pending在哪儿,MySQL数据库无法处理交易。这是怎么回事呢?
姚远OracleACE
2023/11/01
3490
为什么MySQL没有负载,但交易却跑不动?
相关推荐
Mysql 异常:Lock wait timeout exceeded; try restarting transaction的解决办法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验