Yii2使用乐观锁时如何规避删除操作的“数据已过期”问题?
Yii2乐观锁下删除操作报错“数据已过期”的解决方法
错误原因
启用乐观锁后,Yii2执行delete()时会验证模型的version字段与数据库中的值是否一致:
if optimistic locking is enabled and the data being deleted is outdated.
如果版本不匹配(比如数据已被其他请求修改,或前端未传递最新版本号),就会触发这个报错——本质是Yii2检测到你要删除的是“过时”的数据,避免并发操作导致的数据冲突。
解决步骤
1. 确保删除时携带最新版本号
前端在发起删除请求时,必须携带当前待办事项的最新version值。比如在页面的删除按钮中传递版本参数:
<?= Html::a('删除', ['todo/delete', 'id' => $model->id, 'version' => $model->version], [ 'class' => 'btn btn-danger', 'data' => [ 'confirm' => '确定删除该待办事项?', 'method' => 'post', ], ]) ?>
2. 控制器中正确处理版本验证
在删除动作中,将前端传递的版本号赋值给模型,再执行删除操作:
public function actionDelete($id, $version) { $model = $this->findModel($id); // 同步最新版本号,确保和数据库一致 $model->version = $version; try { if ($model->delete()) { Yii::$app->session->setFlash('success', '待办事项删除成功'); } } catch (\yii\db\StaleObjectException $e) { Yii::$app->session->setFlash('error', '数据已过期,请刷新页面后重试'); } return $this->redirect(['index']); }
这样Yii2会生成带版本条件的删除SQL:DELETE FROM todo WHERE id=:id AND version=:version,只有版本匹配时才会执行删除。
3. 特殊场景:跳过乐观锁强制删除
如果业务逻辑允许不做并发验证,可以直接用deleteAll()绕过乐观锁检查:
// 直接删除,不验证版本号 \app\models\Todo::deleteAll(['id' => $id]);
注意:这种方式会忽略乐观锁的保护,仅适用于无并发修改风险的场景。
内容的提问来源于stack exchange,提问作者Azizxon Zufarov
相关产品推荐
相关产品推荐

