mysql InnoDB 并发事务 更新丢失

同一时间多个事务并发更新同一行数据,且更新后的数据是基于更新前的数据,造成了更新丢失的问题。

我将事务的隔离级别设置为了最高的 SERIALIZABLE ,但发现并不能解决这个问题。

在并发事务处理带来的问题中,“更新丢失”通常应该是完全避免的。但防止更新丢失,并不能单靠数据库事务控制器来解决,需要应用程序对要更新的数据加必要的锁来解决,因此,防止更新丢失应该是应用的责任。

这段话是引用的别人文章中的话,不是很理解。

我的想法有两种:

1、在后台程序中将并发的事务强制变为同步串行执行,但总感觉哪里不妥

2、控制数据库让多个事务对同一行数据进行操作时,不论读写,直接锁死该行数据,先来的事务获得读写的权限,事务完成,下一个事务再获取读写的权限进行操作,但问题如何实现啊?

请各位帮忙解疑,如果你能详细说明下在 node.js 、mysql、sequelize 中如何处理这样更好。

阅读 6.8k
3 个回答

会话的隔离级别设置为serializable的时候,其他会话对该表的写操作将被挂起;但是还是可以读取数据的,因此根据读取的数据做更新还可能会有问题。

应用程序中为了防止核心数据被并发修改,一般在查询数据的语句中增加for update的选项,从数据库层面避免造成同一条数据被两个事务同时进行操作。

我怀疑兄弟你没有显示开启事务吧? mysql innodb支持行锁,不论你的事务隔离级别是什么样的,只要你开启事务修改了一行数据还没有提交,你就获得了这行数据的写锁,其他事务就不能再修改这条记录。事务隔离级别只是确认其他事务能不能读取到你修改过未提交的数据记录而已,当你修改完成提交事务,其他事物才能获得这行记录的修改权限,才能执行修改操作,换句话说,对于innodb的某一行记录而言,多个会话对它的更新操作也只能是串行的,只有前一个事务修改完成并且提交,后一个事务才能进行更新操作。所以题主说的更新丢失的情况,要么是没有提交,要么是没有显示开启事务,记录被连续多个会话更新,再就是系统崩溃也会丢失未完成的事务操作。

  • 查询语句使用悲观锁策略,事务中的读语句改为select * ... for update
  • 或者就是使用乐观锁,表中加一个标示字段。

详细解释和代码:https://crossoverjie.top/2017...

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