Go-zero事务处理过程|青训营笔记

1,625 阅读1分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第3篇笔记。

在深入理解RDBMS的课程中,我们学习到了事务的一些特性。在简易tiktok的项目开发中,也需要开启事务保证数据库的一致性。接下来,我们将在go-zero框架下进行事务操作。

链接:深入理解RDBMS | 青训营笔记 - 掘金 (juejin.cn)

首先,在model_gen.go文件中注册事务上下文,TransCtx 暴露给logic开启事务:

func (m *defaultVideoModel) TransCtx(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error {
   return m.conn.TransactCtx(ctx, func(ctx context.Context, s sqlx.Session) error {
      return fn(ctx, s)
   })
}

接着注册定制的底层数据库操作功能:

1、插入数据

func (m *defaultVideoModel) TransInsert(ctx context.Context, session sqlx.Session, data *Video) (sql.Result, error) {
   query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, videoRowsExpectAutoSet)
   return session.ExecCtx(ctx, query, data.UserId, data.PlayUrl, data.CoverUrl, data.FavoriteCount, data.CommentCount, data.Title)
}

2、更新点赞表

func (m *defaultVideoModel) TransUpdateFavorite(ctx context.Context, session sqlx.Session, videoId int64) (sql.Result, error) {
   query := fmt.Sprintf("update %s set `favorite_count`=`favorite_count`+1  where `video_id` = ?", m.table)
   return session.ExecCtx(ctx, query, videoId)
}

点赞、评论、关注等操作都需要开启事务进行处理,先插入对应表,再更新user表、video表的状态,保持数据的一致性。

在go-zero中逻辑处理开启事务,req.Action_type == 1时,插入Favorite表并更新Video点赞数 :

if err := l.svcCtx.FavoriteModel.TransCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error {
   newFavorite := model.Favorite{
      VideoId: req.Video_id,
      UserId:  user_id,
   }

   _, err := l.svcCtx.FavoriteModel.TransInsert(ctx, session, &newFavorite)

   if err != nil {
      return err
   }

   if _, err := l.svcCtx.VideoModel.TransUpdateFavorite(ctx, session, req.Video_id); err != nil {
      return err
   }

   return nil
}); err != nil {
   return &types.Douyin_favorite_action_response{
      Status_code: 3,
      Status_msg:  "点赞事务失败",
   }, nil
}

req.Action_type == 2时,从Favorite表中删除并更新Video点赞数:

if err := l.svcCtx.FavoriteModel.TransCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error {
   _, err := l.svcCtx.FavoriteModel.TransDeleteByVideoIdAndUserId(ctx, session, req.Video_id, user_id)

   if err != nil {
      return err
   }

   if _, err := l.svcCtx.VideoModel.TransUpdateFavoriteDesc(ctx, session, req.Video_id); err != nil {
      return err
   }

   return nil
}); err != nil {
   return &types.Douyin_favorite_action_response{
      Status_code: 3,
      Status_msg:  "取消点赞事务失败",
   }, nil
}

至此,我们就利用go-zero框架完成了一次事务操作。类似的,评论和关注也采用这个事务流程,注意关注操作时需要同时更新Followee和Follower的数据。