我试图通过并行执行 MySQL 8.0 请求多次来处理提示。我的想法是使用 FOR UPDATE SKIP LOCKED 来避免选择重复的行,所以过程是这样的:
-选择值 = xxx limit 10 FOR UPDATE SKIP LOCKED 的行;
-将10个结果的值改为yyy;
-坚持和冲洗
我有一个 cron 在同一时间段(每分钟)执行此任务 10 次 因此,即使 FOR UPDATE SKIP LOCKED,该任务似乎也选择了相同的行。 这是我的实际要求:
SELECT bill.*
FROM billing bill
JOIN subscriber s ON s.subscriber_id = bill.subscriber_id
JOIN subscription sub ON s.subscriber_id = sub.subscriber_id
AND bill.subscription_id = sub.subscription_id
JOIN (
SELECT MAX(billing_date) billing_date,
subscriber_id,
subscription_id
FROM billing
WHERE billing_value = 'not_ok BILL010 3'
GROUP BY subscriber_id, subscription_id
) latest ON bill.subscriber_id = latest.subscriber_id
AND bill.subscription_id = latest.subscription_id
AND bill.billing_date = latest.billing_date
WHERE s.status = 'C'
AND sub.renewable = 1
AND sub.store = 'BizaoStore'
AND bill.billing_value = 'not_ok BILL010 3'
AND sub.purchase_token IN ('newgamz_cg', 'newgamz_cg_wait' )
AND bill.billing_value IN (
'not_ok bizao_tobe', 'not_ok BILL010 2',
'not_ok BILL010', 'not_ok BILL010 3')
AND bill.billing_date > '2023-04-04 00:00:00'
ORDER BY sub.created_at DESC
LIMIT 10 FOR UPDATE SKIP LOCKED;"
我正在使用 symfony 命令来执行这个请求,这里是代码片段:
$q = $entityManager->createNativeQuery($SQL, $rsm);
$billings = $q->getResult();
if($billings) {
foreach($billings as $billing){
$billing->setBillingValue("new value");
try{
$entityManager->persist($billing);
}
catch (Exception $e){
}
try{
$entityManager->flush();
}catch(Exception $e){
}
}
}
我的 cronjob 每分钟执行此命令 10 次,所以根据我的理解,我应该每分钟获取 10x10 行并更新它们。但这里发生的情况是,同时执行 10 次此请求有时会导致多次更新相同的行。 我没有正确理解什么?
这是我的数据库表: