mysql 高并发下的数据同步问题
目前,遇到这样一个使用 mysql 的问题,先描述下场景(为了方便答题,已经做了部分简化):
现在有两台机器,使用同一个数据库账户,同时访问操作一个 mysql 地址,它们都会有如下的操作:
- 根据 id 查询一条数据。
- 在原有的数据基础上做增量式改动。
- 将变动好的数据根据 id 进行更新。
所以,有时候会有这样的一个情况出现:
- 机器一根据某 id 查询得到数据。
- 机器二根据某 id 查询得到数据。
- 机器一在原有的数据基础上做增量式改动。
- 机器二在原有的数据基础上做增量式改动。
- 机器一请求 mysql 存储数据。
- 机器二请求 mysql 存储数据。
这个时候,机器一存储的数据的更新痕迹就被完全抹掉了。这里的这个过程,实际上应该“变成“串行化的,也就是说,两个增量式改动我都想保留。
尝试使用 mysql 的事务来解决这个问题,采用了串行化的隔离级别,但是我发现貌似没能解决,事务可以保证在某些语句出错的时候无额外影响,但是这里本来也没有错误。
当然,我对事务的了解并不深刻,也许用的不是很对。
这里还有一点,增量式改动比较耗时,并且需要数据依赖和额外计算,不能简单地通过 update
语句完成。
我用的是 nodejs 和 sequelize,暂时还没有找到解决方案。
大家如果有什么经验或者建议,希望能指教一二,不胜感激~
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这其实就是一个事务的脏读取问题。解决办法有两种:
1,事务开始
查询 (查询一个能作为未被其他事务更新的依凭,例如最后更新时间)
更新->更新的时候加上where并且update该数据的最后更新时间,例如where last_update_time(最后更新时间) = 该事务刚开始时查出来的那个时间。
commit提交。
解析下这种方法,其实就是利用update的where条件不受脏读取的影响,若该数据中途被其他事务更新过了,则update失败,回滚。
结果:事务a运行成功,事务b因为update条件不成立,回滚了。
2,使用select .... for update 进行锁表。
结果:事务b会等到事务a提交之后再运行。
个人建议,方法一和方法二都能够解决并发请求时脏读取的问题,最好是两种方法合并使用。