mysql 高并发下的数据同步问题

目前,遇到这样一个使用 mysql 的问题,先描述下场景(为了方便答题,已经做了部分简化):

现在有两台机器,使用同一个数据库账户,同时访问操作一个 mysql 地址,它们都会有如下的操作:

  • 根据 id 查询一条数据。
  • 在原有的数据基础上做增量式改动。
  • 将变动好的数据根据 id 进行更新。

所以,有时候会有这样的一个情况出现:

  • 机器一根据某 id 查询得到数据。
  • 机器二根据某 id 查询得到数据。
  • 机器一在原有的数据基础上做增量式改动。
  • 机器二在原有的数据基础上做增量式改动。
  • 机器一请求 mysql 存储数据。
  • 机器二请求 mysql 存储数据。

这个时候,机器一存储的数据的更新痕迹就被完全抹掉了。这里的这个过程,实际上应该“变成“串行化的,也就是说,两个增量式改动我都想保留。

尝试使用 mysql 的事务来解决这个问题,采用了串行化的隔离级别,但是我发现貌似没能解决,事务可以保证在某些语句出错的时候无额外影响,但是这里本来也没有错误。

当然,我对事务的了解并不深刻,也许用的不是很对。

这里还有一点,增量式改动比较耗时,并且需要数据依赖和额外计算,不能简单地通过 update 语句完成。

我用的是 nodejs 和 sequelize,暂时还没有找到解决方案。

大家如果有什么经验或者建议,希望能指教一二,不胜感激~

阅读 4k
1 个回答

这其实就是一个事务的脏读取问题。解决办法有两种:

1,事务开始
查询 (查询一个能作为未被其他事务更新的依凭,例如最后更新时间)
更新->更新的时候加上where并且update该数据的最后更新时间,例如where last_update_time(最后更新时间) = 该事务刚开始时查出来的那个时间。
commit提交。
解析下这种方法,其实就是利用update的where条件不受脏读取的影响,若该数据中途被其他事务更新过了,则update失败,回滚。
结果:事务a运行成功,事务b因为update条件不成立,回滚了。

2,使用select .... for update 进行锁表。
结果:事务b会等到事务a提交之后再运行。

个人建议,方法一和方法二都能够解决并发请求时脏读取的问题,最好是两种方法合并使用。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题