You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 04:30:09