国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

記一次 Mybatis 一級緩存清理無效引起的源碼走讀

voyagelab / 2807人閱讀

摘要:今天對象在學習時發現對象的方法并不能清理一級緩存同一下相同查詢條件返回的結果還是舊值。測試代碼如下上網搜索網上搜索找到了相同問題并沒有人解答。例如查看官方文檔實例有一個本地緩存在執行和時被清理。要明確地關閉它獲取打算做更多的工作你可以調用。

今天對象在學習 Mybatis 時發現 org.apache.ibatis.session.SqlSession 對象的 clearCache() 方法并不能清理一級緩存, 同一 session 下相同查詢條件返回的結果還是舊值。測試代碼如下

上網搜索

網上搜索找到了相同問題, 并沒有人解答。例如:https://www.iqismart.com/topi...

查看官方文檔

http://www.mybatis.org/mybati...

SqlSession 實例有一個本地緩存在執行 update,commit,rollback 和 close 時被清理。要明確地關閉它(獲取打算做更多的工作) ,你可以調用 clearCache()。

看起來, 沒什么問題, 方法也沒有被標記成廢棄.

打印詳細日志

先把日志配上, 看看有沒有打印什么有用的信息, 添加 slf4j、logback 依賴,添加 logback.xml , 日志級別設置為 DEBUG 運行后未看到跟清理緩存有關的信息, 調整日志級別為 TRACE 后依舊沒有.


    mybatis
    
        
            %d{HH:mm:ss.SSS} [%thread] %-5level %logger %msg%n
        
    
    
        mybatis.log
        UTF-8
        
            %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
        
    
    
        
        
    
看 clearCache() 源碼

上面方法都沒有收獲, 只能看源碼了.第一步, 先看一下 clearCache() 做了什么, 下面會大規模貼圖

注意 PerpetualCache 類的 cache 變量

org.apache.ibatis.cache.impl.PerpetualCache#cache 就是一個 HashMap

到此, clearCache() 已經完結, 最終就是調用一個 HashMap 的 clear() 方法

看 selectOne() 源碼


這一步沒有什么好看的, 就是封一層 selectList

第一個方法會間接調用第二個, 只是少了一個分頁相關的 RowBounds
把傳入的 statement 值變成 MappedStatement, 由于不是我們查看源碼的重點, 可以直接跳過.

不過可以學習到 Mybatis 其實是把我們寫的 xml 文件抽象成 MappedStatement , 在執行 sql 時需要先使用 statement (也就是我們 xml 中 select 標簽中的 id) 去配置中 get 出整個 MappedStatement, MappedStatement 包含了 resultMaps 之類的, 一會兒 sql 返回時映射結果集很可能要用到.

這一步把 MappedStatement 變成 BoundSql, BoundSql 應該就是每條 SQL 的抽象.

還會根據 MappedStatement (xml 文件)、parameter (sql 參數)、rowBounds (分頁信息)、BoundSql (SQL) 生成一個 CacheKey (緩存 key) .

已經跟我們想要了解的東西沾點邊了.

這一步是取 MappedStatement 對象的 Cache , 暫時不知道是什么緩存(可能是二級緩存), 可以知道的是和剛才看 clearCache() 清理的不是同一個東西. 調試發現返回值是 null, 不關心繼續往下看

這里到了 BaseExecutor 類, 152 行會根據 CacheKey 從 localCache 獲取結果.
而且和 clearCache() 方法清理的是同一個緩存對象.
基本可以確定 Mybatis 就是在這里從一級緩存獲取結果后返回, 需要重點關注.

階段性成果

反復運行發現如下規律:

如果第二次查詢前不加 sqlSession.clearCache(); 可以從 localCache get 出結果

如果第二次查詢前加 sqlSession.clearCache(); localCache get 結果為空

由此可以得出結論:

sqlSession.clearCache() 方法是有效的, 清理一級緩存后第二次查詢結果依然和第一次相同, 和 Mybatis 一級緩存并無關系.

既然如此, 要想知道結果, 只能繼續往下跟蹤, 看一級緩存為空后, Mybatis 是怎么處理的.

可以看出, 為空后調用了 queryFromDatabase 方法,從方法名可以理解, 會去數據庫查詢

第 322 行先往一級緩存設置一個占位符, 并無實際含義
第 324 行執行查詢動作, 需要重點關注
第 326 行根據緩存 key 清理一級緩存
第 328 行重新設置一級緩存
第 330 行看到一個面熟的東西, 在 clearCache() 時會同時清理 localCache 和 localOutputParameterCache, 如果執行的是存儲過程, 會把參數緩存起來

繼續跟蹤 doQuery 方法

先是獲取 MappedStatement 的配置, 創建一個 StatementHandler, 加工成 JDBC 標準的 Statement , 這中間隱藏了無數細節, 還是那句話, 不是我們關心的重點, 繼續跟蹤 Query 方法

經過 RoutingStatementHandler 路由分發, 到達 SimpleStatementHandler

方法體只有三行
第一行拿出具體 SQL
第二行調用 statement.execute() 方法, 這里已經到了 JDBC 驅動層, mysql 驅動包會幫我們封裝請求包發送給 mysql 服務器并把響應結果映射到 jdbc 規范的對象中
第三行處理返回結果集

其實執行完 execute 方法, 就可以從 PreparedStatement 對象 get 出想要的結果集, 但貿然 get 會影響 Mybatis 處理, 還是繼續跟蹤 handleResultSets 方法吧

方法一開始聲明了一個 multipleResults , 這個就是最終的結果集.
接著分別處理 ResultMap 和 ResultSet, 把 mysql 返回的結果按照 xml 中的規則映射成指定對象
由于 xml 中的 select 并沒有定義 resultSets , 只關注上半部分即可, 斷點設在 198 行

可以看出 mysql 服務器返回的確實是舊值,

階段性成果
至此可以確定一級緩存清理無效的問題和應用沒有關系.

還能是什么問題呢, 難道是事務的隔離級別導致的, 應用只是簡單的查詢, 連事務管理器都沒有配置, 要有問題也只能懷疑 mysql 服務器.

查詢數據庫的默認隔離級別

mysql> SELECT @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ       |
+-----------------------+
1 row in set, 1 warning (0.00 sec)

mysql> SELECT @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| REPEATABLE-READ        |
+------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)

竟然是"可重復讀", 好了, 原因找到, 此貼終結.

解決

解決辦法就是把事務的默認隔離級別設置成 "讀已提交".

mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
Query OK, 0 rows affected (0.00 sec)

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68361.html

相關文章

  • Mybatis系列】從源碼角度深度理解Mybatis緩存特性

    摘要:一級緩存介紹及相關配置。在這個章節,我們學習如何使用的一級緩存。一級緩存實驗配置完畢后,通過實驗的方式了解一級緩存的效果。源碼分析了解具體的工作流程后,我們隊查詢相關的核心類和一級緩存的源碼進行走讀。 我,后端Java工程師,現在美團點評工作。愛健身,愛技術,也喜歡寫點文字。個人網站: http://kailuncen.me公眾號: KailunTalk (凱倫說) 前言 本文主要涉及...

    Ku_Andrew 評論0 收藏0
  • Mybatis系列】從源碼角度深度理解Mybatis緩存特性

    摘要:一級緩存介紹及相關配置。在這個章節,我們學習如何使用的一級緩存。一級緩存實驗配置完畢后,通過實驗的方式了解一級緩存的效果。源碼分析了解具體的工作流程后,我們隊查詢相關的核心類和一級緩存的源碼進行走讀。 我,后端Java工程師,現在美團點評工作。愛健身,愛技術,也喜歡寫點文字。個人網站: http://kailuncen.me公眾號: KailunTalk (凱倫說) 前言 本文主要涉及...

    young.li 評論0 收藏0
  • 一次線上bug處理-mybatis一級緩存引起

    摘要:問題線上定時任務計算出的金額不對定位問題查看日志好像也執行了但是金額為什么和數據庫的表里的不一致再查整個的定時任務日志日切日期 問題: 線上riskProvision定時任務,計算出的金額不對 定位問題: 查看日志 4.13 riskProvision 2017-04-13 01:10:00.009 [org.springframework.scheduling.quartz....

    sean 評論0 收藏0
  • 墻裂推薦:搜云庫技術團隊,面試必備技術干貨

    摘要:今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 面試必備 面試必備:深入Spring MVC DispatchServlet 源碼...

    SegmentFault 評論0 收藏0

發表評論

0條評論

voyagelab

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<