Mybatisキャッシングメカニズムの詳細な説明(第1レベルのキャッシュ+第2レベルのキャッシュ)

第1レベルのキャッシュとは何ですか

MyBatisには非常に強力なクエリキャッシュ機能が含まれており、非常に簡単に構成およびカスタマイズできます。MyBatis 3のキャッシュ実装に多くの改善が実装され、より強力で簡単に構成できるようになりました。Mybatisは、デフォルトで第1レベルのキャッシュ(ローカルセッションキャッシュ)のみをオンにします

まず、クエリキャッシュとは何かを知る必要がありますか?クエリキャッシュの役割は何ですか?

機能:Mybatisは、データの負荷を軽減し、データベースのパフォーマンスを向上させるためのクエリキャッシュを提供します。

次の図に示すように、各セッションには、部分的な独自のキャッシュがあります。これは、いわゆる第1レベルのキャッシュです。


どのような状況で第1レベルのキャッシュにヒットしますか

  1. 同じsqlパラメーター
  2. セッションに参加している必要があります
  3. 同じ方法で実行する必要があります
  4. 同じ名前名である必要があります(同じ名前名->同じマッパーファイル)
  5. クエリの前にclearCacheを実行できません
  6. 中級者は更新、削除、挿入を実行できません(SqlSessionではすべてのデータが空になります)

Mybatisのキャッシングメカニズムの詳細な説明

第1レベルのキャッシュは、SqlSessionレベルのキャッシュです。データベースを操作するときにsqlSessionオブジェクトを構築する必要があり、キャッシュされたデータを格納するためのデータ構造(HashMap)がsqlSessionオブジェクトにあることは誰もが知っています。

以下に示すように:

Mybatisのキャッシングメカニズムの詳細な説明

この図から、第1レベルのキャッシュ領域がSqlSessionに従って分割されていることがわかります。各クエリは最初にキャッシュ領域を検索し、データが見つからない場合はデータベースからデータをクエリしてから、クエリされたデータを第1レベルのキャッシュに書き込みます。Mybatis内部ストレージキャッシュはHashMapオブジェクトを使用し、キーはhashCode + sqlId + sqlステートメントです。値の値は、クエリマッピングから生成されたjavaオブジェクトです。ダーティリードを回避するためにキャッシュ内のデータが確実に正確なデータであることを保証するために、データを変更する(追加、削除、および変更操作)たびに、コミット操作を実行してキャッシュ領域をクリアします。


ここに写真の説明を挿入
ここに写真の説明を挿入

SqlSessionとExecutorはどちらもインターフェイスであり、実装はDefaultSqlSessionとCacheExecutorです。

  • クライアントはテストメソッドTest1と同等です
  • User @ Proxy動的プロキシ(疑似皇帝に相当し、転送を担当するだけです)==コード内のUserMapper(プロキシオブジェクト)は実際には役に立ちません
  • Executorインターフェースは、用事を実行してデータベース内のデータを取得するためのものです
  • SqlSessionはインターフェースです
  • 第1レベルのキャッシュは、CacheExecutorを介して実装されます

基礎となる実装の詳細な説明!

ここに写真の説明を挿入
ここに写真の説明を挿入

selectByIdメソッドにブレークポイントを入力し、基礎となる実装クラスPrepetualCacheにgetObject(オブジェクトキー)を入力します。これ
は、デバッグスタック情報を確認することで確認できます

  1. 上の図の緑色のボックスは、動的エージェントの実装です。意味がありません。これは単なる転送であるため、この部分は無視してください。
  2. 次に、selectOneにクエリを実行しますが、SelectListにクエリを実行してから、DefaultSqlSessionを介して変換します。

キャッシュに本当に関連しているのは、これらの行の実装です

キャッシュに本当に関連しているのは、これらの行の実装です

プロセスは次のとおりです
ここに写真の説明を挿入
ここに写真の説明を挿入

このステップ:

  • キャッシュキーに見られるように、メソッドと名前名およびセッションが含まれているため、これらはキャッシュヒットと同じように実行する必要があります。
  • キャッシュの一意のキーをカプセル化します

ここに写真の説明を挿入

  • DefaultSqlSessionにCacheExecutorがあります
  • CacheExecutorにはSimpleexexutorがあります
  • SimpleexexutorにはLocalCache(PerpetualCacheタイプ)と呼ばれるものがあります
  • LocalCacheは、キャッシュを保存する実際の場所です
  • LocalCacheにキャッシュがあります(ハッシュマップ<オブジェクト、オブジェクト>タイプ)

ここに写真の説明を挿入
ここに写真の説明を挿入
ここに写真の説明を挿入

ここに写真の説明を挿入
ここに写真の説明を挿入

第1レベルのキャッシュを通過します!

ここに写真の説明を挿入

第1レベルのキャッシュのPUTプロセス

最初のいくつかのプロセスは上の図と同じです。
ここに写真の説明を挿入
キャッシュのライフサイクルはSqlSessionと同じです。

データの不整合はありますか?

データベース自体にトランザクション分離レベルがあり、デフォルトが繰り返し読み取りであるためではありません。つまり、データベース内の任意のトランザクションによって読み取られるデータは一貫しているため、データの不整合の問題はありません。


Mybatisセカンダリキャッシュ

ここに写真の説明を挿入

第2レベルのキャッシュ使用条件は、名前名注釈
putを使用して構成する必要があります。第2レベルのキャッシュの場合、このセッションを閉じて配置する必要があります(クロストランザクション読み取りを行わないと、ダーティ読み取りの問題が発生するため)

どのような状況で第1レベルのキャッシュにヒットしますか

  1. 同じsqlパラメーター
  2. セッションに参加している必要があります
  3. 同じ方法で実行する必要があります
  4. 同じ名前名である必要があります(同じ名前名->同じマッパーファイル)
  5. クエリの前にclearCacheを実行できません
  6. 中級者は更新、削除、挿入を実行できません(SqlSessionではすべてのデータが空になります)
  7. 条件セカンダリキャッシュを構成する必要がありますCachenamespaceアノテーション
  8. 第2レベルのキャッシュを配置する場合、このセッションを閉じて配置する必要があります(クロストランザクション読み取りを行わないと、ダーティ読み取りの問題が発生するため)

2番目のレベルのキャッシュはマッパーレベルのキャッシュです。複数のSqlSessionが同じマッパーのSQLステートメントで動作します。複数のSqlSessionが2番目のレベルのキャッシュを共有できます。2番目のレベルのキャッシュはSqlSessionにまたがることができます。

図:

Mybatisのキャッシングメカニズムの詳細な説明

第2レベルのキャッシュ領域は、マッパーの名前に応じて分割されます。**同じ名前のマッパークエリデータは同じ領域に配置されます。**マッパープロキシ方式を使用する場合、各マッパーの名前は異なり、第2レベルのキャッシュ領域として理解できます。マッパー、つまり名前名に従って分割されます。2つのマッパーファイルの名前名が同じである場合、異なるSqlSessionsがマッパーキャッシュを共有できます。

図:

Mybatisのキャッシングメカニズムの詳細な説明

デフォルトでは、ローカルセッションキャッシュを除いて、第2レベルのキャッシュは有効になっていません第1レベルのキャッシュでは、異なるSqlSession間の第1レベルのキャッシュが共有されないことも導入しました。したがって、2つのSqlSessionを使用して同じデータをクエリすると、両方がSQLをデータベースに送信します。

第2レベルのキャッシュをオンにすると、SqlSession間のデータを第2レベルのキャッシュで共有できます。第1レベルのキャッシュと同様に、第2レベルのキャッシュ領域は、挿入、更新、削除などの操作が実行され、コミットが送信された後にクリアされます。第1レベルのキャッシュと第2レベルのキャッシュが同時に存在する場合、第2レベルのキャッシュが最初にアクセスされ、次にそれぞれの第1レベルのキャッシュがアクセスされます。必要なデータがない場合、SQLはクエリのためにデータベースに送信されます。

おすすめ

転載: blog.csdn.net/weixin_44284160/article/details/109271495