只读事务与普通读
只读事务为了扩大事务的范围(single sql -》 java function),解决多次select不相等(即不可重复读)的问题;相当于在外面盖了一个整体的rr的隔离级别
注意隔离级别不是只读事务的目标,因为即使autocommit true,也有事务隔离级别可单独设定,只不过是对于single sql而言 work log 2020.4.7 1)
| rr级别事务,带update insert delete | 只读事务 | 普通读 | |
| autocommit | false | false | default true |
| 设置隔离级别 | rr | rr | 自行设定,默认rr |
图
=============================================================================================================================
2020.10.14 该理解有问题
并不是只读了,就rr了,也可以只读rc,只是只读事务让同一个方法中所有sql共享一个事务号,可配合rr级别,共享readview来避免重复读 mvcc巨无霸【重点】
=============================================================================================================================
事务的2步走:
autocommit fasle,宣告一个事务号,(一个连接是一个事务的充分非必要条件),开始【享受】
set 隔离级别
【享受】:(同中work log中2020.4.7 2)黄色背景的3点)
因为共享了事务号(mvcc巨无霸【重点】),事务内select无条件可见性:work log
同一事务内锁共享【注释死锁】
rr(如果不在一个事务中,那rr这种级别无法实现,如图中第4列),【可重复读实践】
【注释死锁】
con1 开启 transaction,set autocommit false
con1 select for update,获取锁x
con2 update
con2 等待锁x——死锁
con1 commit
1【可重复读实践】
/**
* https://www.cnblogs.com/silyvin/p/12657283.html
* ScefOrmSession
* private List<Map<String, Object>> query(String sql) {
* & jdbcUtil = utilThreadLocal.get();
& if(jdbcUtil == null)
jdbcUtil = jdbcPool.borrowObject();
* @return
*/
@RequestMapping(value = "rr")
@ResponseBody
public TestOrmImpl rr() {
ScefOrmSession scefOrmSession = new ScefJoinOrmSession();
TestOrmImpl orm = new TestOrmImpl();
orm.setId(1);
try {
scefOrmSession.startTransaction();
scefOrmSession.clearCache();
orm = (TestOrmImpl)scefOrmSession.queryForObject(orm);
System.out.println(orm.getDoubleField());
Thread.sleep(5000);
/**
* 手动修改doubleField
*/
scefOrmSession.clearCache();
orm = (TestOrmImpl)scefOrmSession.queryForObject(orm);
System.out.println(orm.getDoubleField());
scefOrmSession.commit();
} catch (Exception e) {
scefOrmSession.rollback();
} finally {
scefOrmSession.endTransaction();
}
return orm;
}
(a)第一种情况,2次io不用同一个连接,分别从池里拿,两次连接都是默认autocommit true,各自有各自事务号
private List<Map<String, Object>> query(String sql) {
AbstractJdbcUtil jdbcUtil = null;
GenericObjectPool<AbstractJdbcUtil> jdbcPool = null;
List list = null;
try {
jdbcPool = getJdbcPool();
// jdbcUtil = utilThreadLocal.get();
// if(jdbcUtil == null)
jdbcUtil = jdbcPool.borrowObject();
list = jdbcUtil.queryForList(sql);
} catch (Exception e) {
throw new DBException(e);
} finally {
if(jdbcUtil != null // && utilThreadLocal.get() == null)
jdbcPool.returnObject(jdbcUtil);
}
return list;
}
结果2次打印不一样
(b)第二种情况,将蓝色注释放开,都取threadlocal中那个连接:
public void startTransaction() {
AbstractJdbcUtil util = null;
try {
util = getJdbcPool().borrowObject();
// 重要,即使后面两句报错,也能在finally中的endTransaction将连接还给连接池
utilThreadLocal.set(util);
Connection connection = util.getConnection();
connection.setAutoCommit(false);
} catch (Exception e) {
throw new DBException("start transaction error");
}
}
setAutoCommit(false)开启事务,mysql默认rr,因此即使当中手动改了数据,由于rr,两次打印一样
2【只读事务实践】
work log 2020.4.28
只读事务没有报错,但是确实没有插入
浙公网安备 33010602011771号