1. 程式人生 > >mybatis的緩存機制

mybatis的緩存機制

span 多表 緩存 操作 style 目的 clas batis mybatis

在實際項目中,通常對數據庫查詢的性能要求很高,而MyBatis提供了查詢緩存來緩存數據,從而達到提高性能的要求。

MyBatis的查詢緩存分為一級緩存和二級緩存。一級緩存是sqlsession級別的緩存,二級緩存是mapper級別的緩存,二級緩存是多個sqlsession共享的。

一級緩存可用性:

一級緩存基於sqlsession,sqlsession又是單線程不共享的。所以只能在本次請求中使用,而如果本次請求有commit操作,比如update、insert、delete,那麽緩存就會被刷新。簡單來說,只有連續兩次執行相同語句,一級緩存才有效果,比如:

select * from tb_user // 執行一次SQL語句

select * from tb_user // 緩存查詢

而如果有commit操作

select * from tb_user // 執行一次SQL語句

update tb_user set name = lay where id = 1 // commit 操作,清除了緩存

select * from tb_user // 第二次執行查詢SQL

第一種情況,個人認為基本上不太會出現。所以一級緩存在一定程度上來說,基本上沒有用

二級緩存可用性:

二級緩存是基於mapper的,也就是說,一個mapper會有一個緩存,多個mapper會有多個緩存。並且mapper的緩存是被所有sqlsession共享的,不會因為sqlsession的關閉而清空。

select * from tb_user // 第一個sqlsession進來

select * from tb_user // 第二個sqlsession進來,查詢到的是第一個sqlsession的緩存數據

緩存清空的情況

select * from tb_user  // 一個sqlsession進來

update tb_user set name = lay where id = 1 // 執行了commit操作,清空緩存
 
select * from tb_user // 第二個sqlsession進來,得重新執行sql

二級緩存屬於一個mapper,也就是當前mapper中如果執行了commit操作,當前mapper才會被清空,那麽顯而易見的問題就出現了。如果有多表關聯查詢,commit操作只清空當前的mapper,其它mapper有關聯的數據就還是舊的數據

,不是出現了數據不一致的情況了嗎?

比如:

select * from tb_user // 第一個mapper緩存了數據

select * from tb_class A
left join tb_user B on A.userId = B.id // 第二個mapper緩存了數據,並關聯tb_user的數據

update tb_user set name = lay where id = 1 // 第一個mapper中執行了commit操作,清空了第一個mapper的緩存數據

select * from tb_class A
left join tb_user B on A.userId = B.id // 第二個mapper的數據,查詢到的是緩存,而且是舊的數據

所以,由於mybatis的二級緩存的機制,多表查詢容易出現數據不一致問題,這點需要註意。當然網上也有一些解決方案,不過個人覺得那些方案會增加項目的復雜度,如果項目越來越大mapper的關聯越復雜,那些解決方案最終可能導致項目難以理解的問題。

因此,如果對數據的實時性要求不高,查詢頻率卻很高,比如某些排行榜?那麽當前mapper使用二級緩存能大大提高性能。如果對數據實時性要求很高,頻繁地執行commit操作,那麽當前mapper還是不使用二級緩存了。簡單來說,根據當前mapper的數據實時性來判斷是否使用二級緩存

mybatis的緩存機制