我们一直在经历间歇性的锁定超时错误(大约每天1到2,而不是250)。
在结帐时,我们获取所有用户的详细信息,保存订单,处理任何付款,然后更新订单。我想可能是第二次更新导致的。
我们的代码示例(不完全相同,但足够接近):
DB::transaction(function () use ($paymentMethod, $singleUseTokenId, $requiresPayment, $chargeAccount) {
// create order locally
$order = Order::create([
'blah' => $data['blah'],
]);
// handle payment
$this->handlePayment();
// update order with new status (with a secondary transaction for safety)
DB::transaction(function () use ($order) {
$order->update([
'status' => 'new status',
]);
}, 5);
}, 5); // Retry transaction 5 times - this reduced the lock timeout errors a lot我们得到的间歇性错误是(实际值被删除):
SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction (SQL: insert into `orders` (`user_id`, `customer_uuid`, `type_uuid`, `status_uuid`, `po_number`, `order_details`, `cart_identifier`, `cart_content`, `cart_sub_total`, `cart_tax`, `cart_grand_total`, `payment_type_uuid`, `shipping_address`, `uuid`, `updated_at`, `created_at`) 我读过很多关于它的文章,有些人说增加超时(似乎是一种解决办法)、乐观锁定(我认为事务已经做到了)等等。
从数据库面包屑中我可以看出,订单创建有时需要很长的时间(例如在3s时看到一个命令,由于通常是50‘s插入而在23s看到另一个命令),然后发生其他事情,它试图更新订单,但是该行仍然被从create()锁定。
备注:
有什么建议吗?
解决方案:在订单uuid上没有主键。非常愚蠢的错误。导致InnoDB基本上为索引创建一个6字节键。并从连续插入锁定,然后更新..
发布于 2020-02-17 17:27:35
如果您看到“锁定等待超时”错误,请查看其他事务。尤其有害的是长时间运行的交易。您可以在SHOW ENGINE INNODB STATUS\G中发现这些。攀爬InnoDB历史列表表明也有一些。目前正在运行的长事务将在information_schema.INNODB_TRX中列出。
注意:如果事务获取了独占锁,那么它直到事务结束才会释放,而不是查询的结束。
首先,排除长期运行的查询。例如,缓慢的更新将为其执行时间保留一个锁。
在所有查询都进行得相当快之后,请检查您的事务。让它们尽可能短。客户端通常打开一个事务,执行一两个查询,然后转到第三方API调用,或者做其他繁重的工作,并保持事务打开。与此同时,其他事务也将获得“锁定等待超时”。
https://stackoverflow.com/questions/60254803
复制相似问题