mysql - 间歇性锁定等待超时 Laravel DB 事务(重试 5 次)
问题描述
我们一直在遇到间歇性锁定超时错误(大约每天 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`)
我已经阅读了很多关于它的内容,有些人说增加超时(似乎是一种解决方法)、乐观锁定(我认为事务已经这样做了)和其他事情。
从我从数据库面包屑中可以看出,订单创建有时需要很长时间(例如,在 3 秒时看到一个,在 23 秒时看到一个,因为它通常是 50 毫秒插入),然后发生其他事情并尝试更新订单但该行仍被 create() 锁定。
笔记:
- 我们在订单表上有 4 个外键(客户 uuid、用户 uuid、订单类型 uuid、订单状态 uuid)——我觉得这些可能会导致问题。
- 一些雄辩的创建需要 3 秒,其他 23 秒(仅检查问题)。在大多数订单上,请求最长为 500 毫秒,因此这些是异常值。
有什么建议么?
解决方法:订单uuid上没有主键。非常愚蠢的错误。导致 InnoDB 基本上为索引创建了一个 6 字节的键。并从连续插入锁定,然后更新..
解决方案
如果您看到“锁定等待超时”错误,请查看其他事务。特别有害的是长期运行的事务。你可以在SHOW ENGINE INNODB STATUS\G
. 攀登 InnoDB 历史列表表明也有。当前运行的长事务将列在information_schema.INNODB_TRX
.
请注意,如果事务抓住了排他锁,它直到事务结束才被释放,而不是查询结束。
首先,排除长时间运行的查询。例如,慢速 UPDATE 将为其执行时间持有一个锁。
在所有查询都以相当快的速度进行后,请检查您的交易。使它们尽可能短。客户通常会打开一个事务,执行一两个查询,然后转到第三方 API 调用或执行其他繁重的工作并保持事务处于打开状态。同时其他事务将获得“锁定等待超时”。
推荐阅读
- r - 如何在传单中自定义缩放级别
- javascript - 遍历数组并执行函数
- forms - ASP.NET Core 和 Bootstrap:如何将下拉列表放入表单组?
- javascript - ncaught TypeError:无法在 HTMLButtonElement.writePassword (tutor.js:113) 的 generatePassword (tutor.js:103) 处读取未定义的属性“推送”
- php - EasyAdmin 3:用户角色过滤器显示以前过滤器的数据
- c - 我应该何时存储原始对象或将其副本存储在数据结构中?
- sql - 插入statament java jstl标签
- javascript - 如何在 Ramda 中组合多个减速器?
- excel - 在不打开引用的其他工作表的情况下运行 Excel 宏
- python - Django - 确保每个用户只有一个 ACTIVE 产品