mysql的一则事务锁的问题Lock wait timeout exceeded.m
今天在测试环境上发现用户第三方登录出现问题,服务器日志报错如下:
出现这个问题感觉还是挺疑惑的,因为测试环境已经稳定运行了几个月的时间,一直没有出现过mysql事务锁的问题,于是开始着手查问题。
1. 问题分析
针对Lock wait timeout exceeded; try restarting transaction的错误出现的原因一般有:
- 在同一个事务内先后对库中同一条记录进行事务操作,如更新、删除等;
- 并发操作库中同一条记录,出现锁竞争,一个线程获取锁后迟迟不释放,导致另一个尝试获取锁的线程超时。
- 在innoDB引擎下,默认的innodblockwait_timeout参数设置锁等待的时间是50s,一旦数据库锁超过这个时间就会报错。
2. 查找问题
先从mysql角度来对问题进行分析,查看mysql server上的事务情况和锁的情况以及锁等待的情况。
2.1. 查看进程
SHOW PROCESSLIST;
输出结果为:
2.2. 查看事务情况
select * from informationschema.innodbtrx
其中字段说明如下(这里只简要列举关键的几个字段,需要了解更多的请自行到官网查询):
- trx_state:事务状态
- trx_start:事务开始时间
- trxrequestedlockid:innodblocks.lock_id
- trxwaitstarted:事务开始等待的时间
- trxmysqlthread_id:事务线程id
- trxtableslocked:事务拥有多少个锁
- trxisolationlevel:事务隔离级别
在我们的环境中执行后,结果为:
对比可以看到,记录的状态都为RUNNING,也就是正在执行的事务,并没有锁。
如果是事务锁定的情况如何解决?看事务表INNODB_TRX,里面是否有正在锁定的事务线程,看看ID是否在show processlist里面的sleep线程中,如果是,就证明这个sleep的线程事务一直没有commit或者rollback而是卡住了,我们需要手动kill掉。
2.3. 查看锁情况
SELECT * FROM informationschema.INNODBLOCKs;
可以看到锁也是没有的。
2.4. 查看锁等待情况
SELECT * FROM informationschema.INNODBLOCK_waits;
当前环境中也并无锁等待情况,这时就开始往其他方面分析了。
2.5. 查看mysql日志情况
由于当前测试环境是一个mysql的主从环境,所以会有很多的binlog日志,所以猜测是不是因为binlog空间占用太多的原因。进入mysql存储目录后发现:
可以看到binlog日志文件应该是已经及时被定时清理了,但是mysqld.log和slow.log都比较大,查看mysqld.log,会发现有大量的:
经过定位,发现这个是一个同事最近在调整的统计信息的定时任务,不小心把定时任务的频率调大了,导致频繁刷mysqld.log,定时任务频率恢复正常后,log日志不再增长。slow.log也是因为统计信息中的一些sql的问题导致的。
清空这两个文件:
echo > mysqld.logecho > slow.log
清空成功后,再尝试登录时,成功了。
虽然这里不是binlog的问题,但是还是有必要在这里安利下binlog的管理方法:
- 登录mysql:mysql -u root -p
- show binary logs; show variables like '%log%';show master logs;查看多少binlog日志,占用多少空间。
- 手动清理1:PURGE MASTER LOGS TO 'mysql-bin.002467'; 删除mysql-bin.002467以前所有binlog,这样删除可以保证*.index信息与binlog文件同步。
- 手动清理2:PURGE MASTER LOGS BEFORE DATESUB(CURRENTDATE, INTERVAL 10 DAY); 手动删除10天前的binlog日志。
- 设置自动清理:set global expirelogsdays = 5; 把binlog的过期时间设置为5天; mysql> flush logs; 刷新log使上面的设置生效。为保证在MYSQL重启后仍然有效,在my.cnf中也加入此参数设置expirelogsdays = 5。
更多可以参考:https://blog.csdn.net/atco/article/details/24259333
3. 总结
出现Lock wait timeout exceeded; try restarting transaction的原因一般为:
- 多线程并发更新时,一个线程事务操作比较耗时,导致其他线程获取锁超时,这个需要查看代码问题并且要kill掉mysql中锁死的线程。
- binlog日志文件过大,空间不足,清理binlog文件。
- 其他mysql日志文件过大,清理日志文件。
- 其他原因。
- 浅谈 Java 并发编程中的若干核心技术
- ASP.NET Core的路由[3]:Router的创建者——RouteBuilder
- ASP.NET Core的路由[2]:路由系统的核心对象——Router
- ASP.NET Core的路由[1]:注册URL模式与HttpHandler的映射关系
- 学习ASP.NET Core, 怎能不了解请求处理管道[6]: 管道是如何随着WebHost的开启被构建出来的?
- 学习ASP.NET Core, 怎能不了解请求处理管道[5]: 中间件注册可以除了可以使用Startup之外,还可以选择StartupFilter
- 学习ASP.NET Core, 怎能不了解请求处理管道[4]: 应用的入口——Startup
- 学习ASP.NET Core, 怎能不了解请求处理管道[3]: 自定义一个服务器感受一下管道是如何监听、接收和响应请求的
- .NET Core多平台开发体验[4]: Docker
- .NET Core多平台开发体验[3]: Linux (Windows Linux子系统)
- .NET Core多平台开发体验[2]: Mac OS X
- .NET Core多平台开发体验[1]: Windows
- 如何远程关闭一个ASP.NET Core应用?
- 【深度学习】谷歌deepdream原理及tensorflow实现
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- NgModule imports定义的运行时数据结构
- 用Windows电脑训练深度学习模型?超详细配置教程来了
- Angular No provider for EffectsRootModule错误消息
- Leetcode No.15 三数之和
- 正则表达式介绍与使用
- Angular StoreFeatureModule
- Angular Component之间的事件通知机制
- 如何将你的Python项目全面自动化?
- 正则表达式介绍与使用
- Angular ERROR NullInjectorError: R3InjectorError(AppModule)的错误分析
- 2.4-Air302(NB-IOT)-基础外设-延时,定时器
- Shell正则表达式一览表
- YAML基础语法
- 详解Kubernetes存储体系
- Python3 正则表达式特殊符号及用法.md