【发布时间】:2020-05-31 22:25:03
【问题描述】:
我们一直在遇到间歇性锁定超时错误(大约每天 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) - 我觉得这些可能会导致问题。
- 一些 eloquent 创建需要 3 秒,其他 23 秒(仅检查问题)。大多数订单的请求时间最长为 500 毫秒,因此这些是异常值。
有什么建议吗?
解决方法:订单uuid上没有主键。非常愚蠢的错误。导致 InnoDB 基本上为索引创建了一个 6 字节的键。并从连续插入锁定,然后更新..
【问题讨论】:
-
UUID 不连续;它们散落在各处。
-
@RickJames 你知道什么是 UUID 吗?我相信您将 v4 UUID 与顺序 ID 混淆了
标签: mysql laravel timeout locking innodb