Php 两个事务同时进行,数据重复
我有一个API,它同时接收两个请求。它还导致两个事务同时运行,从而复制数据。我的端点的伪代码是:Php 两个事务同时进行,数据重复,php,mysql,database,laravel,transactions,Php,Mysql,Database,Laravel,Transactions,我有一个API,它同时接收两个请求。它还导致两个事务同时运行,从而复制数据。我的端点的伪代码是: public function myEndpoint(Request $request) { $newOrderID = $request->get('order_id'); DB::beginTransaction(); try { $ordersCount = Order::where(['id' => $newOrderID])->count();
public function myEndpoint(Request $request)
{
$newOrderID = $request->get('order_id');
DB::beginTransaction();
try {
$ordersCount = Order::where(['id' => $newOrderID])->count();
if ($ordersCount === 0) {
Order::create(['id' => $newOrderID]);
$stat = Stat::where(['date' => Carbon::now()])->first();
$stat->orders_count = $stat->orders_count + 1;
$stat->save();
}
DB::commit();
} catch (Exception $e) {
DB::rollBack();
}
}
因此,端点是一个事务,它:
- 将新订单ID保存到表中
- 增量统计
这个问题有好的解决方案吗?您可以使用mysql触发器来解决重复条目。这是示例触发器。您不必检查php代码中是否存在
DROP TRIGGER IF EXISTS order_transaction_before_insert;
DELIMITER $$
CREATE TRIGGER order_transaction_before_insert
BEFORE INSERT ON order FOR EACH ROW
BEGIN
DECLARE msg varchar(128);
DECLARE foundCount INT;
SET foundCount = (
SELECT COUNT(*)
FROM order
WHERE
order_id = NEW.order_id
);
IF( foundCount > 0) THEN
SET msg = CONCAT('DuplicateEntryError: Trying to insert a duplicate value in order table for driver: ', NEW.order_id);
SIGNAL SQLSTATE VALUE '45000' SET MESSAGE_TEXT = msg;
END IF;
END; $$
DELIMITER ;
您可以使用mysql触发器来解析重复条目。这是示例触发器。您不必检查php代码中是否存在
DROP TRIGGER IF EXISTS order_transaction_before_insert;
DELIMITER $$
CREATE TRIGGER order_transaction_before_insert
BEFORE INSERT ON order FOR EACH ROW
BEGIN
DECLARE msg varchar(128);
DECLARE foundCount INT;
SET foundCount = (
SELECT COUNT(*)
FROM order
WHERE
order_id = NEW.order_id
);
IF( foundCount > 0) THEN
SET msg = CONCAT('DuplicateEntryError: Trying to insert a duplicate value in order table for driver: ', NEW.order_id);
SIGNAL SQLSTATE VALUE '45000' SET MESSAGE_TEXT = msg;
END IF;
END; $$
DELIMITER ;
如果已经在处理相同的订单id,则可以进行散列并锁定传入请求
胡闹
当请求传入时,检查订单id是否在哈希中
如果已在哈希中,则返回重复请求
检查订单id是否在DB中
如果不存在,则插入数据库
从散列中清除订单id
如果已经在处理相同的订单id,则可以进行散列并锁定传入请求
胡闹
当请求传入时,检查订单id是否在哈希中
如果已在哈希中,则返回重复请求
检查订单id是否在DB中
如果不存在,则插入数据库
从散列中清除订单id
假设您的订单ID只是某个任意(唯一)的自动增量值,它无论如何都不能用于检测重复项。两个传入插入之间还存在哪些其他信息可能会提示我们其中一个/两个都是重复的?为了回答这个问题,我们需要知道这一点。order ID是一个生成的ID,作为查询参数传递给端点,如https://example.com/api/my-endpoint?order_id=n1992bb3j1bbb3
。使用相同的订单ID多次并行发送此请求有时会导致我解释的情况。您能告诉我们有关此“统计”表的信息吗?“统计”表保存了“订单”表中插入的数量。如果查询不会更新“orders”表中重复键上的“statistics”表,那么唯一索引将是完美的。但这真的不可能,是吗?例如,在重复键插入“订单”时,查询不会在那里插入冗余数据,但仍会更新“统计”表中的计数器。使用lockForUpdate
检查重复的订单ID如何,以便其他事务需要等待?假设您的订单ID只是任意的(唯一的)自动递增值,无论如何不能用于检测重复项。两个传入插入之间还存在哪些其他信息可能会提示我们其中一个/两个都是重复的?为了回答这个问题,我们需要知道这一点。order ID是一个生成的ID,作为查询参数传递给端点,如https://example.com/api/my-endpoint?order_id=n1992bb3j1bbb3
。使用相同的订单ID多次并行发送此请求有时会导致我解释的情况。您能告诉我们有关此“统计”表的信息吗?“统计”表保存了“订单”表中插入的数量。如果查询不会更新“orders”表中重复键上的“statistics”表,那么唯一索引将是完美的。但这真的不可能,是吗?例如,在重复键插入到“订单”时,查询不会在那里插入冗余数据,但仍会更新“统计”表中的计数器。在检查重复订单ID时使用lockForUpdate
如何,以便其他事务需要等待?