鍍金池/ 問(wèn)答/PHP  數(shù)據(jù)庫(kù)/ Yii2 php循環(huán)使用mysql事務(wù)

Yii2 php循環(huán)使用mysql事務(wù)

hi,各位好。
現(xiàn)在有十條數(shù)據(jù)需要插入,同時(shí)有十條數(shù)據(jù)需要更新。暫記需要插入的數(shù)據(jù)為a1,a2,a3...a10,需要更新的數(shù)據(jù)為b1,b2,b3...b10。

需要保證所有的數(shù)據(jù)都同時(shí)操作成功,或者同時(shí)操作失敗。(即事務(wù))。
而且需要將 a1插入后得到的主鍵ID更新到b1的一個(gè)字段,a2更新到b2的一個(gè)字段,依次類推。

我現(xiàn)在的做法是:

foreach($arr_a AS $a){
    //開(kāi)啟事務(wù)
    //插入 a1 得到 id1
    //將ID更新到 b1
    //結(jié)束事務(wù)或者回滾事務(wù)
}

但是這樣的話會(huì)有幾個(gè)問(wèn)題:
(1) 循環(huán)里面使用事務(wù)會(huì)導(dǎo)致性能問(wèn)題吧?
(2) 如果拋異常了,會(huì)導(dǎo)致部分?jǐn)?shù)據(jù)沒(méi)有辦法進(jìn)行操作了。最外層加事務(wù)?

請(qǐng)問(wèn)大神有什么好的解決方法嗎?求指導(dǎo)~感激不盡!

回答
編輯回答
小眼睛

需要保證所有的數(shù)據(jù)都同時(shí)操作成功,或者同時(shí)操作失敗。 是指如果a10操作失敗了,全部數(shù)據(jù)回滾到a1操作前嗎?如果是這樣的話,當(dāng)然是吧事務(wù)放在循環(huán)外層最合適。

如果只是 “a1插入后得到的主鍵ID更新到b1的一個(gè)字段” 是一個(gè)事務(wù),其中任意一組操作失敗不影響其他組操作的話,還是應(yīng)該將事務(wù)放在循環(huán)內(nèi)。

// 用于記錄失敗的操作的key
$error = [];

foreach($arr_a AS $key => $a){
    $transaction = Yii::$app->getDb()->beginTransaction();

    try {
        //插入 a1 得到 id1
        //將ID更新到 b1
        
        $transaction->commit();
    } catch (\Exception $e) {

        // 回滾
        $transaction->rollBack();
        // 記錄失敗的操作的key
        $error[] = $key;

        // 這里不拋異常
        continue;
    }
}

// 對(duì)記錄的 $error 進(jìn)行其他操作
2017年12月28日 13:33
編輯回答
入她眼

事務(wù)鎖很耗性能,最好在循環(huán)的外面放事務(wù),這樣可以一起成功或者一起失敗。

2018年5月31日 00:36