mysql采用默认事务隔离级别REPEATABLE-READ;
然后我分别执行以下内容:
2、使用jdbc访问数据库:
3、这时候打印结果,发现线程进入阻塞,一直卡在这里
也就是说我开启的另一个事务仍然能读取到数据,只是在最后执行executeUpdate的时候才被锁定不能执行
4、命令行执行commit
5、结果命令行操作被jdbc操作替换掉,数据改为4。
这不就是说REPEATABLE-READ仍然出现了丢失更新,而且没有行锁定吗?
事务与并发到底是什么区别,我在测试多线程执行以上jdbc操作时,发现最后得到的结果总是不对。例我开十个线程,每个都对数据+1,结果可能只加了5.所以在并发情况下怎么做才能保证数据的安全?
被关于事务隔离级别错误信息误导,认为REPEATABLE-READ级别和SERIALIZABLE级别能解决丢失更新的问题,然而实际是不能的。
因为mysql的select ... from table;语句 不管哪种隔离级别都是不会阻塞的
在隔离级别下只有在更新数据时才会等待写锁(排它锁)的释放,所以我多个线程可以同时读取到number=3,基于此进行修改就必然会导致丢失更新。
所以解决办法为程序中加入悲观锁 或 乐观锁 机制。
悲观锁采用的是 select ... for update
这时事务B读取操作将无法执行,只有当事务A的commit完成,事务B才可以继续执行,相当于采用串行一个个执行。
乐观锁常用的是版本控制或时间戳控制
这时候事务B发现version=1已经不存在了,因为事务A首先执行完更新了数据库,把version字段设为了2,这样就会导致该事务提交失败,需要我们在程序中判断异常情况下如何继续操作。
以上就是我当前的理解,至于mysql本身支持的MVCC(多版本并发控制)还不知道怎么用,乐观锁的异常处理也不太清楚具体要怎么实现,可能是要根据具体的业务场景采用不同的处理手段吧。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。