Polardb 特殊场景下抛出There is no active transaction 求解
起因:线上的异常报警系统偶尔会出现“There is no active transaction” 的异常信息
线上有一些业务代码偶尔会抛出事务提交失败,经过排查之后,锁定问题点如下,虽然可以从业务从避免,但是还是想知道一下原因。
- 数据库需要是Polardb(mysql没有问题)
- 需要是新连接
- 事务开启之后只有读的操作 然后就提交OR回滚
- 少量读容易抛异常,大量读的情况下偶尔会有异常?(待确定)
// 业务代码模拟
public function test()
{
Db::beginTransaction();
// 随便的一些查询
Db::table('system_admin')->where('id',1)->value('username');
// if然后就没执行更新或者插入
Db::commit();
}
// Hyperf\DbConnection\Connection
public function getActiveConnection(): DbConnectionInterface
{
// 让其必定触发reconnect()
// if ($this->check()) {
// return $this;
// }
if (! $this->reconnect()) {
throw new ConnectionException('Connection reconnect failed.');
}
return $this;
}
追加防喷Buff
小菜鸟一个,我只是好奇问题本身,请不用衍生到一些别的问题;如果开杠,杠就是你对
问题本身追查部分细节
- 事务有没有成功开启
- 用Hyperf的事件监听确定开启了
- 利用Hyperf框架的isTransaction()确定commit的时候transactions = 1
- 确定commit只执行了一次
- 追查问题点
- 一通操作之后,经过对比发现了服务重启的时候容易异常
- 最后追查到新链接的时候必定抛出问题
猜测
Polardb 自身初始化的时候,我只读取,所以走到了读库,commit的时候异常了
之后再操作的时候,hyperf的mysql连接未销毁,commit没问题可能是Polardb 自身的一些机制问题
切换读写了?
- 多次读的时候偶尔异常的原因
- 通过Db::getPdo()->inTransaction()的时候
- 第一次读的时候必定是false
- 后续读有的时候是true,有的时候false
* 写问题的时候很困了,因为不能影响线上,都是晚上空闲的时候慢慢摸的,摸了几天,所以语序有点乱,如果有人追问的话可能会补充点细节,就酱 *
根本问题是连接地址的事务一致性问题。
选会话一致即可。