多线程测试spring事务隔离级别,发现没有效果啊:报错 -问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文

多线程测试spring事务隔离级别,发现没有效果啊:报错

kun坤 2020-06-06 22:46:47 145

闲的无事,就像测试下spring的事务隔离级别是否真的能工作,先说下环境,spring3.1.2,mysql5,innob引擎。mysql配置的隔离级别是read-commit,用的是spring的jdbcTemplate直接操作数据库。

测试逻辑是这样的,两个进程T1,T2向数据库同一字段写入内容。然后通过改变隔离级别来验证spring事务是否有效。

线程T1 线程T2
读取字段name:1111
休眠sleep,模拟业务处理 读取字段name:1111
休眠sleep,模拟业务处理
修改字段name:2222
修改字段name:1111


比如设置为 Isolation.REPEATABLE_READ,我的理解是这样的:T1的事务会对数据表的这行数据加锁,T2可以读取,但写入时需要获取锁,必须等待T1完成之后才能继续操作,但实际情况是T2直接提交了把name字段改为2222。

是不是我的理解有误,还是不能用这种多线程去测试spring的事务,请高手帮忙解惑。

多线程报错 spring事务隔离 多线程spring 多线程事务隔离 没有效果报错
分享到
取消 提交回答
全部回答(1)
  • kun坤
    2020-06-08 11:18:37

    你的测试用例其实并不严谨。

    T1, 因为它没有修改数据,所以,只要有基本的MVCC(多版本并发控制)的功能,就可以满足“可重复读”了,无论T2,T3,T4有没有修改数据,根本无需锁定表。 - 比如oracle,这时默认情况下,T1是从undo中读取"旧"数据。

    再考虑数据库可能采用行锁,其实你要测试事务隔离级别的步骤应该是这样:

    1. T1 T2 关闭autocommit;

    2.T1 - select (开事务)

    3.T2 - update t1看得到的记录(随便一条),注意不要commit

    4.T1 - update T2中事务影响到的那条记录(此时,T1的事务就被挂起了)

    5.T2 - 提交 - (这时,T1也解锁了)


    要做这样的测试,其实用单纯的数据库客户端开两个SESSION还直观一些,无论是用mysql或postgresql或oracle都能完成这个测试。

    确认用例正常后,再考虑多线程(JDBC),然后再考虑Spring的JDBCTemplate. 这样一步步做过去,出问题时,才容易找到原因,否则纠缠太多,不利于学习中的知识点各个击破。

    ######回复 @ganqing : 我认为乐观锁不算是数据库管理系统提供的功能。任何程序都可以自己实现。你的理解也没啥大问题吧: 隔离级别是一个定义,锁是实现的手段,对这个手段的优化,提高性能,就是数据库厂商要做的事了。如通过快照实现“可重复读”的目的就是为了提高并发性。######回复 @szf : 是不是我对于隔离级别的理解有问题?######我这么做主要是为了测试下,因为我之前理解的repeatable-read实现一般是是两种方式:一个是使用共享锁,就是T2必须等待T1完成后才能操作。二是使用类似hibernate乐观锁形式的版本检查,这样T1最后提交时发现版本有问题,报异常,操作不成功。但是目前mysql的repeatable-read实现不是上面的两种方式。######回复 @ganqing : 在测试用例的2. T1 - select * from t1 for update; 3. T2 - update t1 就会锁定了。 -- 这是你要的效果? 设计成这样的应用系统那就有够烂的 -- 实话实说哈,不要介意~######回复 @ganqing : 数据库开发者一般优化的方向是提高性能和并发的同时,保证事务完整性。 你提这样的要求的理由是什么? 你希望的操作流程是怎样的呢?######

    T1和T2的连接会话中,autocommit必须是0才行。 如果autocommit=1(默认),那么T1 select后, 这个事务就结束了。

    这时,即使select后,也要commit,否则锁表。


    还有,这个测试跟spring无关啊

    ######明白你的意思了,不过spring在创建数据库连接时已经setAutoCommit=false,T1的所有操作都是在一个事务里面,只在最后提交。######因为是使用spring进行事务管理的,在配置里面将事务的隔离级别设置成了 REPEATABLE_READ,所以和spring有关吧。还有你说的autoCommit设置成0,是在哪里啊,mysql配置?
    0 0
数据库
使用钉钉扫一扫加入圈子
+ 订阅

分享数据库前沿,解构实战干货,推动数据库技术变革

相似问题
最新问题
推荐课程