ホームページ >データベース >mysql チュートリアル >mysqlのロック機構の詳細な紹介
1. 分離レベル
(1) 非コミット読み取り (RU)
この分離レベルでは、トランザクションはまったく分離されず、ダーティ リードが発生し、コミットされていないレコードを読み取ることができます。実際の場面では使われません。
(2) コミットされた読み取り (RC)
は、この分離レベルでは、送信されたレコードのみを読み取ることができます。いわゆるファントム読み取りは、同様のファントム読み取りの現象を指します。トランザクション内で同じクエリが複数回実行されると、返されるレコードはまったく同じではなくなります。ファントム読み取りの根本的な原因は、RC 分離レベルの下で、各ステートメントが送信されたトランザクションの更新を読み取るため、2 つのクエリの間に他のトランザクションが送信されると、2 つのクエリの結果が矛盾することになります。それにもかかわらず、読み取りコミット分離レベルは実稼働環境で広く使用されています。
(3) リピータブルリード (RR)
リピータブルリード分離レベルは、非リピータブルリードの問題を解決しますが、ファントムリードの問題はまだ解決しません。それでは、反復不可能な読書と幻の読書の違いは何でしょうか?非反復読み取りは変更、つまり 2 回読み取られた値が異なることに焦点を当てますが、ファントム読み取りはレコード数の変化 (挿入と削除) に焦点を当てます。一般に、教科書には、ファントム リードの問題はシリアル化分離レベルに達した場合にのみ解決できると記載されていますが、MySQL の innodb は、主に GAP ロックを通じてファントム リードの問題を解決します。さらに、すべてのデータベースがこの分離レベルを実装しているわけではありません。後で、mysql が反復読み取り分離レベルを実装する方法を簡単に紹介します。
(4) シリアル化可能
シリアル化された分離モードでは、ダーティ リードとファントムは排除されますが、トランザクションの同時実行性は急激に低下し、トランザクションの分離レベルはトランザクションの同時実行性に反比例し、トランザクションの分離レベルが高くなるほど、分離レベルが高くなるほど、トランザクションの同時実行性は低くなります。実際の運用環境では、DBA は同時実行性とビジネス ニーズを満たすこととの間でトレードオフを行い、適切な分離レベルを選択します。
2. 同時スケジューリング方法
分離レベルに密接に関係するもう 1 つの方法は、分離レベルを達成するための同時スケジューリングです。同時スケジューリングの実装メカニズムはデータベース ベンダーごとに異なりますが、基本原則はすべてロックを使用して、複数のトランザクションによって同時にデータ オブジェクトが変更されないように保護します。従来のロックベースの同時実行制御と比較して、マルチバージョン同時実行制御 (MVCC) の主な特徴は、読み取りが多く書き込みが少ないシナリオでのシステムの同時実行性が大幅に向上することです。そのため、ほとんどのリレーショナル データベースはすべて MVCC を実装しています。
3. 2 フェーズ ロック プロトコル
2 フェーズ ロック プロトコルの意味は、トランザクションが 2 つの段階に分かれており、第 1 段階はブロックを取得することであり、第 2 段階はブロックを解除することです。封鎖。 2 段階のブロッキングにより、同時スケジューリングの正確性が保証されます。 1 段階ロック (トランザクションに必要なすべてのロックを一度に取得する) と比較して、2 段階ロックは同時実行性を向上させますが、デッドロックが発生する可能性もあります。
4. デッドロック
いわゆるデッドロックとは、相手が取得する予定のリソースを複数のトランザクションがそれぞれ占有し、待ちのループが形成され、相互にトランザクションを続行できない状態を指します。実行する。
5. ロックの種類
ロックの種類に応じて、共有ロック、排他ロック、意図共有ロック、意図排他ロックに分けることができます。ロックの粒度に応じて、行ロックと表ロックに分けることができます。 mysql の場合、トランザクション メカニズムは基盤となるストレージ エンジンによって実装されるため、mysql レベルにはテーブル ロックのみがあり、トランザクションをサポートする innodb ストレージ エンジンには行ロック (レコード ロック)、ギャップ ロック、ネクスト キー ロックが実装されます。 。 innodb はインデックス構成テーブルであるため、Mysql のレコード ロックは本質的にインデックス レコードのロックであり、ギャップ ロックはネクスト キー ロックの下でのみ有効です。レコード ロックとレコード ロックの組み合わせの前のギャップ。 mysql は、ギャップ ロックとネクスト キー ロックを通じて RR 分離レベルを実装します。
説明:
更新操作 (読み取りはロックされない) の場合、アップリンク ロックはインデックスを介してのみ可能です。それ以外の場合は、クラスター化インデックスの各行に書き込みロックが設定されます。これは実際には次と同等です。テーブルの書き込みロック。
複数の物理レコードが同じインデックスに対応し、同時にアクセスされる場合、ロックの競合も発生します。
テーブルに複数のインデックスがある場合、異なるトランザクションが異なる行をロックする可能性があります。さらに、Innodb は行ロックを使用してデータ レコード (クラスター化インデックス) をロックします。
MVCC 同時実行制御メカニズムでは、読み取り操作がロックされていないという理由だけで、読み取り操作がブロックされる操作はなく、読み取り操作が操作をブロックすることもありません。
RocksDB は、オープンソースのストレージ エンジンとして、トランザクションの ACID 特性をサポートします。ACID の I (Isolation) をサポートするには、同時実行制御が不可欠です。この記事では主に、RocksDB のロック メカニズムの実装について説明します。この記事を通じて、読者が RocksDB 同時実行制御の原則を深く理解できることを願っています。この記事は主に次の 4 つの側面から始まります。まず、RocksDB のロックの基本構造を紹介します。次に、RocksDB の行ロック データ構造の設計におけるロック スペースのオーバーヘッドを紹介します。次に、いくつかの代表的なロック プロセスを紹介します。最後に、メカニズムの中で重要なデッドロック検出メカニズムを紹介します。
1. 行ロックのデータ構造
RocksDB の最小ロック粒度はキーであり、各キーは LockInfo 構造に対応します。すべてのキーはハッシュ テーブルを通じて管理され、ロックを検索する場合は、ハッシュ テーブルを通じてキーを直接見つけて、キーがロックされているかどうかを判断できます。ただし、グローバルにハッシュ テーブルが 1 つしかない場合、このハッシュ テーブルにアクセスするときに多くの競合が発生し、同時実行パフォーマンスに影響します。 RocksDB はまず Columnfamily によって分割され、各 Columnfamily のロックは LockMap によって管理され、各 LockMap は LockMapStripe とハッシュ テーブル (std::unowned_mapd6a67ad316a61e6201a4c37fe3c8a330acquire_snapshot(false),延迟获取快照(加锁后,再拿snapshot)
5).再次调用get_for_update,由于此时key已经被加锁,重试一定可以成功。
6).执行更新操作
7).跳转到1,继续执行,直到主键不符合条件时,则结束。
3.3.基于二级索引的更新
这种场景与3.2类似,只不过多一步从二级索引定位主键过程。
1).创建Snapshot,基于迭代器扫描二级索引
2).根据二级索引反向找到主键,实际上也是调用get_row_by_rowid,这个过程就会尝试对key加锁
3).继续根据二级索引遍历下一个主键,尝试加锁
4).当返回的二级索引不符合条件时,则结束
4.死锁检测算法
死锁检测采用DFS((Depth First Search,深度优先算法),基本思路根据加入等待关系,继续查找被等待者的等待关系,如果发现成环,则认为发生了死锁,当然在大并发系统下,锁等待关系非常复杂,为了将死锁检测带来的资源消耗控制在一定范围,可以通过设置deadlock_detect_depth来控制死锁检测搜索的深度,或者在特定业务场景下,认为一定不会发生死锁,则关闭死锁检测,这样在一定程度上有利于系统并发的提升。需要说明的是,如果关闭死锁,最好配套将锁等待超时时间设置较小,避免系统真发生死锁时,事务长时间hang住。死锁检测基本流程如下:
1.定位到具体某个分片,获取mutex
2.调用AcquireLocked尝试加锁
3.若上锁失败,则触发进行死锁检测
4.调用IncrementWaiters增加一个等待者
5.如果等待者不在被等待者map里面,则肯定不会存在死锁,返回
6.对于被等待者,沿着wait_txn_map_向下检查等待关系,看看是否成环
7.若发现成环,则将调用DecrementWaitersImpl将新加入的等待关系解除,并报死锁错误。
相关的数据结构:
class TransactionLockMgr { // Must be held when modifying wait_txn_map_ and rev_wait_txn_map_. std::mutex wait_txn_map_mutex_; // Maps from waitee -> number of waiters. HashMap<TransactionID, int> rev_wait_txn_map_; // Maps from waiter -> waitee. HashMap<TransactionID, autovector<TransactionID>> wait_txn_map_; DecrementWaiters // IncrementWaiters // } struct TransactionOptions { bool deadlock_detect = false; //是否检测死锁 int64_t deadlock_detect_depth = 50; //死锁检测的深度 int64_t lock_timeout = -1; //等待锁时间,线上一般设置为5s int64_t expiration = -1; //持有锁时间, }
以上がmysqlのロック機構の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。