只讀事務與普通讀


只讀事務為了擴大事務的范圍(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

一種mysql jvm死鎖

 

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

只讀事務沒有報錯,但是確實沒有插入

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM