Laravel ORM 中的模型事件,没有开启事务,我们在开发的过程中如何保证数据的一致性?

Laravel 7.x ORM模型事件

场景如下

我在新建一篇“文章”之后,我需要初始化这篇文章的“统计”。

新建文章

public function createOrUpdate(Request $request)
{
  $input = $request->all();
  $mArticle = new Article();
  $article = $mArticle->findOrNew($input['id']);

  $article->user_id = auth()->user()['id'];
  $article->fill($input)->save();
}

使用created事件,在文章创建之后initStatistic()

protected static function boot()
{
    static::created(function ($article){
        $article->initStatistic();
  });
  parent::boot();
}

问题如下

当initStatistic()出现问题时,文章已经存在于数据库之中,而文章的统计和文章是强关联关系,必须要存在。这种情况下,如何保证数据库一致性呢?

九九一十八,一步一个脚印
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

解决方案,代码如下

public function createOrUpdate(Request $request)
{
try{
  $input = $request->all();
  $mArticle = new Article();
  DB::beginTransaction(); // 开启事务
  $article = $mArticle->findOrNew($input['id']);

  $article->user_id = auth()->user()['id'];
  $article->fill($input)->save();
  Db::commit(); // 提交事务
}catch(\Exception $exception){
    Db::rollback(); // 回滚事务
}
}

由于ORM的event没有实现ShouldQueue,不会将event放到queue【放到queue就是异步】,所以event里面的方法还是“同步的”,把代码放到try catch中,如果整个过程出现错误,就回滚事务。

3年前 评论
讨论数量: 4

你可以手工在事务中执行啊,把 createOrUpdate() 放到一个事务中。

3年前 评论

想要保证数据一致性,为什么不开事务?

3年前 评论

不开启事务,那就需要有一定的补偿机制
文章表数据入库,就往redis里面写入string数据,比如以article_id为key,value为1
initStatistic方法执行成功,article_id 加1,现在就是2。
最后一步,校验article_id的值,如果是1就删除,如果是2就删除redis数据。

实现的方法有很多,这算是最简单的一种。如果使用事务,我觉得更简单。

3年前 评论

解决方案,代码如下

public function createOrUpdate(Request $request)
{
try{
  $input = $request->all();
  $mArticle = new Article();
  DB::beginTransaction(); // 开启事务
  $article = $mArticle->findOrNew($input['id']);

  $article->user_id = auth()->user()['id'];
  $article->fill($input)->save();
  Db::commit(); // 提交事务
}catch(\Exception $exception){
    Db::rollback(); // 回滚事务
}
}

由于ORM的event没有实现ShouldQueue,不会将event放到queue【放到queue就是异步】,所以event里面的方法还是“同步的”,把代码放到try catch中,如果整个过程出现错误,就回滚事务。

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!