报错:【SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction】
webman的项目,偶尔报这个错误,经检查代码里并没有使用事务,请问下:webman的多进程模型,并发高的时候是否可能出现操作同一数据表时发生死锁的情况? 这种情况该怎么解决了 webman版本1.4.3 webman/think-orm 1.0
看看这篇帖子
我代码里面并没有用到事务呀
可以装一下webman官方的日志插件 里面有一段代码是"判断Db是否有未提交的事务" 可以先尝试一下 // 判断Db是否有未提交的事务 $has_uncommitted_transaction = false; if (class_exists(Connection::class, false)) { if ($log = $this->checkDbUncommittedTransaction()) { $has_uncommitted_transaction = true; $method = 'error'; $logs .= $log; } }
// 判断Db是否有未提交的事务 $has_uncommitted_transaction = false; if (class_exists(Connection::class, false)) { if ($log = $this->checkDbUncommittedTransaction()) { $has_uncommitted_transaction = true; $method = 'error'; $logs .= $log; } }
我前两天也遇到了,就是事务未提交或者回滚导致的死锁
存在unique索引的表在多进程INSERT的时候,即使不用事务也会出现deadlock的,而且这是最容易复现的
因为单个语句的操作,也是一个事务,只是不用显式的begin/commit/rolback transaction而已
看报错请求的trace 定位的是一条查询语句 ModelLeave::update(array("reads" => $v['reads'] . $member['id'] . ','), ['id' => $v['id']]); 但是从我业务逻辑上分析 这个修改应该只会有一个人,也就是一个进程来操作 不应该会出现并发情况。
没遇到过,多进程同时处理也不会出现死锁呀,update自带排它锁,你是按照主键修改的嘛?
是按照主键修改的
那不应该呀,按照主键修改 都是自带排它锁的,不应该出现死锁呀
update之前会不会就已经死锁了
这个有可能呀,楼主还得自己排查一下
不会是因为update之前死锁的 刚又出现了一次 是另一个方法 里面只有三行sql查询 $is = Distance::where([['name', '=', $member['name']]])->findOrEmpty()->toArray(); if ($is) { Distance::where([['id', '=', $is['id']]])->update(array('name' => $member['name'], 'lat' => $lat, 'lon' => $lon, 'res' => $distance, 'addtime' => date('Y-m-d H:i:s'))); } else { Distance::create(array('name' => $member['name'], 'lat' => $lat, 'lon' => $lon, 'res' => $distance, 'addtime' => date('Y-m-d H:i:s'))); } 其中update那行又报死锁错误了
这里的name 是不是唯一索引??
name不是唯一索引,id是主键,innodb表,没有任何索引
你得在检查一下是否 其他方法中有事务没有提交,同一个进程 一个mysql连接,会影响其他方法
例如方法出现bug导致 事务开启后 报错代码停止了,这个时候事务就是没有提交,会导致当前进程 所有方法 中的事务等待,会显示超时,所以最好在使用事务时候,使用try catch
查MSQL的日志看吧,空对空没意义
这个问题和thinkorm webman 没任何关系,仅仅是你SQL语句写的有问题。 这种错误“QLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction”, 本质含义,开启事务长时间未提交,大概率有记录被锁住,没有办法被提交释放锁,导致这个事务被撤销。 你没有开启事务,但是INNODB默认会开启事务。 你应该bing.com 搜索“mysql 死锁 事务长时间超时撤销”关键词去找一下答案,你要定位到引起锁的SQL语句是什么,然后分析原因。你这样报告thinkorm webman 版本没太多意义,这个问题不是这两个引起的。
看看这篇帖子
我代码里面并没有用到事务呀
可以装一下webman官方的日志插件
里面有一段代码是"判断Db是否有未提交的事务"
可以先尝试一下
// 判断Db是否有未提交的事务 $has_uncommitted_transaction = false; if (class_exists(Connection::class, false)) { if ($log = $this->checkDbUncommittedTransaction()) { $has_uncommitted_transaction = true; $method = 'error'; $logs .= $log; } }
我前两天也遇到了,就是事务未提交或者回滚导致的死锁
我代码里面并没有用到事务呀
存在unique索引的表在多进程INSERT的时候,即使不用事务也会出现deadlock的,而且这是最容易复现的
因为单个语句的操作,也是一个事务,只是不用显式的begin/commit/rolback transaction而已
看报错请求的trace 定位的是一条查询语句
ModelLeave::update(array("reads" => $v['reads'] . $member['id'] . ','), ['id' => $v['id']]);
但是从我业务逻辑上分析 这个修改应该只会有一个人,也就是一个进程来操作 不应该会出现并发情况。
没遇到过,多进程同时处理也不会出现死锁呀,update自带排它锁,你是按照主键修改的嘛?
是按照主键修改的
那不应该呀,按照主键修改 都是自带排它锁的,不应该出现死锁呀
update之前会不会就已经死锁了
这个有可能呀,楼主还得自己排查一下
不会是因为update之前死锁的 刚又出现了一次 是另一个方法 里面只有三行sql查询
$is = Distance::where([['name', '=', $member['name']]])->findOrEmpty()->toArray();
if ($is) {
Distance::where([['id', '=', $is['id']]])->update(array('name' => $member['name'], 'lat' => $lat, 'lon' => $lon, 'res' => $distance, 'addtime' => date('Y-m-d H:i:s')));
} else {
Distance::create(array('name' => $member['name'], 'lat' => $lat, 'lon' => $lon, 'res' => $distance, 'addtime' => date('Y-m-d H:i:s')));
}
其中update那行又报死锁错误了
这里的name 是不是唯一索引??
name不是唯一索引,id是主键,innodb表,没有任何索引
你得在检查一下是否 其他方法中有事务没有提交,同一个进程 一个mysql连接,会影响其他方法
例如方法出现bug导致 事务开启后 报错代码停止了,这个时候事务就是没有提交,会导致当前进程 所有方法 中的事务等待,会显示超时,所以最好在使用事务时候,使用try catch
查MSQL的日志看吧,空对空没意义
这个问题和thinkorm webman 没任何关系,仅仅是你SQL语句写的有问题。
这种错误“QLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction”,
本质含义,开启事务长时间未提交,大概率有记录被锁住,没有办法被提交释放锁,导致这个事务被撤销。
你没有开启事务,但是INNODB默认会开启事务。
你应该bing.com 搜索“mysql 死锁 事务长时间超时撤销”关键词去找一下答案,你要定位到引起锁的SQL语句是什么,然后分析原因。你这样报告thinkorm webman 版本没太多意义,这个问题不是这两个引起的。