Using transactions.. still getting outdated objects?

I am worried I’m not understanding how Yii2 implements transactions… or I’m missing something else entirely in how Yii2 ActiveRecords work.

Occasionally, I am getting an error in the block of code below. The error is “The object being updated is outdated.”

$transaction = \common\models\QueueLog::getDb()->beginTransaction();
$log = $this->getLog();
$log->custom_data = json_encode($data);
$log->save() || throw new \Exception(json_encode($log->getErrors()));
$transaction->commit();

getLog() is just a findModel() method, except it will create the log object if it doesn’t see it in the database. In other words, it’s a findOrCreate() method for QueueLog ActiveRecords.

I’m just not understanding how ANYTHING can be outdated if I’m inside the transaction block?

This error message is created by the optimistic locking feature you can enable in ActiveRecord. As far as I see the problem is not related to your transaction but lies in the way you have configured the Optimisitc Locking feature.

Unrelated to the issue: your transaction code is missing a rollback part:

$transaction = \common\models\QueueLog::getDb()->beginTransaction();
try {
    $log = $this->getLog();
    $log->custom_data = json_encode($data);
    $log->save() || throw new \Exception(json_encode($log->getErrors()));
    $transaction->commit();
} catch(\Throwable $e) {
    $transaction->rollBack();
    throw $e;
}

See also Working with Databases: Database Access Objects | The Definitive Guide to Yii 2.0 | Yii PHP Framework