MySQL シリーズの第 5 部、主な内容はロック (Lock) で、ロック、行ロック、ギャップ ロック、ロック ルールの詳細な分類が含まれます。
MySQL では、同時書き込みの問題を解決するためにロックが導入されています。たとえば、2 つのトランザクションが同じレコードに同時に書き込みます。同時に行うことが許可されている場合、ダーティ ライティング が発生します。これは、どの分離レベルでも発生が許可されない異常な状況です。ロックの機能は、ダーティ書き込みの問題を回避するために、2 つの同時書き込み操作を特定の順序で実行できるようにすることです。
まず最初に、この記事で使用されている例を宣言します
CREATE TABLE `user` ( `id` int(12) NOT NULL AUTO_INCREMENT, `name` varchar(36) NULL DEFAULT NULL, `age` int(12) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, INDEX `age`(`age`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1;insert into user values (5,'重塑',5),(10,'达达',10),(15,'刺猬',15);复制代码
この記事で説明されている例はすべて、MySQL InnoDB ストレージ エンジンとRepeatable Read (Repeatable Read) 分離レベルの下にあります。 。
ロックの粒度の観点から、MySQL のロックは、グローバル ロック、テーブル レベルのロック、行ロックの 3 つのタイプに分類できます。
グローバル ロックはデータベース全体をロックします。このとき、データベースは読み取り専用状態になります。DDL (データ定義) を含む、データベースを変更するすべてのステートメントLanguage) を追加して、データベースのグローバル ロックが解放されるまで、削除されたすべての DML (データ操作言語) ステートメントがブロックされます。
グローバル ロックを使用する最も一般的な場所は、フル データベース バックアップを実行することです。次のステートメントを通じてグローバル ロックのロック操作とロック解放操作を実装できます:
-- 加全局锁flush tables with read lock;-- 释放全局锁unlock table;复制代码
クライアント接続が切断されると、グローバル ロックは自動的に解除されます。
テーブル レベルのロックはテーブル全体をロックします。MySQL のテーブル レベルのロックには次のものが含まれます: テーブル ロック、メタデータ ロック(メタ データ ロック)、インテンション ロック(インテンション ロック)、および自動インクリメント ロック(AUTO-INC ロック)。
テーブル ロックのロックと解放方法:
lock table tableName read/write;
unlock table;
テーブル ロックをロックすると、同じクライアント接続の操作権限も制限されることに注意してください。 -レベルの読み取りロック (ロック テーブル ユーザー読み取り
) が追加され、同じクライアント接続で、テーブル レベルの読み取りロックが解放される前に、同じテーブル (ユーザー テーブル) は読み取りのみ可能になり、操作はできなくなります。他のクライアント接続はこのテーブル (ユーザー テーブル) に対して読み取り操作のみを実行できますが、書き込み操作は実行できません。
テーブル レベルの書き込みロック (ロック テーブル ユーザー書き込み
) が追加された場合、テーブルは同じクライアント接続で読み書きできますが、他のクライアント接続では読み取れません。書き込み操作を実行できません。
テーブル レベルのロックの 2 番目のタイプは、メタデータ ロック (MDL、メタデータ ロック) です。メタデータ ロックは、 client テーブルに入るときにロックが自動的にロックされ、クライアントがトランザクションを送信するときにロックが解放されます。これにより、次のシナリオでの問題が防止されます:
sessionA | sessionB |
---|---|
begin; | |
##テーブル ユーザーを変更して列の誕生日日時を追加; |
|
はトランザクションを開き、クエリを実行します。その後、別のクライアント sessionB
が birthday
フィールドを user
テーブルに追加し、sessionA
が別のクエリを実行します。メタデータ ロックにより、同じトランザクション内で前後 2 回クエリされたレコード、テーブルのフィールドと列の数が一致しない可能性があり、これは明らかに回避する必要があります。 DDL 操作は、他のトランザクションのメタデータ読み取りおよび書き込みロックと互換性のないメタデータ書き込みロックをテーブルに追加します。DML 操作は、テーブルにメタデータ読み取りロックを追加します。これは、他のトランザクションのメタデータ読み取りおよび書き込みロックと互換性があります。他のトランザクションのメタデータ。読み取りロックは共有されますが、他のトランザクションのメタデータ書き込みロックとは互換性がありません。
1.2.3 インテンション ロック
で、トランザクションがテーブル内の特定の行のロックを取得したいことを示します。 (共有ロックまたは排他ロック)。 意図的ロックは、テーブル ロックを適用し、テーブル内の各行をスキャンしてテーブルに行ロックがあるかどうかを確認する別のトランザクションによるシステムの消費を回避することです。
例如, 如果没有意向锁, 而有了意向锁之后,在 意向锁的加锁规则:
1.2.4 自增锁第四种表级锁是自增锁,这是一种特殊的表级锁,只存在于被设置为 自增锁会在 insert 语句执行完成后立即释放。同时,自增锁与其他事务的意向锁可共享,与其他事务的自增锁、共享锁和排它锁都是不兼容的。 1.3 行锁行锁是由存储引擎实现的,从行锁的兼容性来看,InnoDB 实现了两种标准行锁:共享锁(Shared Locks,简称S锁)和排它锁(Exclusive Locks,简称X锁)。 这两种行锁的兼容关系与上面元数据锁的兼容关系是一样的,可以用下面的表格表示。
而从行锁的粒度继续细分,又可以分为记录锁(Record Lock)、间隙锁(Gap Lock)、Next-key Lock。 1.3.1 记录锁(Record Lock)我们一般所说的行锁都是指记录锁,它会把数据库中的指定记录行加上锁。 假设事务A中执行以下语句(未提交): begin;update user set name='达闻西' where id=5;复制代码 ログイン後にコピー InnoDB 至少会在 id=5 这一行上加一把行级排它锁(X锁),不允许其他事务操作 id=5 这一行。
假设现在有另一个事务B想要执行一条更新语句: update user set name='大波浪' where id=5;复制代码 ログイン後にコピー 这时候,这条更新语句将被阻塞,直到事务A提交以后,事务B才能继续执行。 1.3.2 间隙锁(Gap Lock)间隙锁,顾名思义就是给记录之间的间隙加上锁。
不知道大家还记不记得幻读?
间隙锁的提出正是为了防止幻读中描述的幻影记录的插入而提出的,举个例子。
照理说在 RR 隔离级别下,同一个事务中两次查询相同的记录,结果应该是一样的。但是在经过更新语句的当前读查询后(更新语句的影响行数是2),N1和N2的查询结果并不相同,N2的查询将 而如果在 也就是说,当N2处的查询执行时, 1.3.3 Next-key LockNext-key Lock 其实就是记录锁与记录锁前面间隙的间隙锁组合的产物,它既阻止了其他事务在间隙的插入操作,也阻止了其他事务对记录的修改操作。 2. 加锁规则不知道大家有没有注意到,我在行锁部分描述记录锁、间隙锁加锁的具体记录时,用的是「至少」二字,并没有详细说明具体加锁的是哪些记录,这是因为记录锁、间隙锁和 Next-key Lock 的加锁规则是十分复杂的,这也是本文主要讨论的内容。 关于加锁规则的叙述将分为三个方面:唯一索引列、普通索引列和普通列,每一方面又将细分为等值查询和范围查询两方面。
在开始之前,先来回顾一下示例表以及表中可能存在的行级锁。 mysql> select * from user; +----+--------+------+| id | name | age | +----+--------+------+| 5 | 重塑 | 5 | | 10 | 达达 | 10 | | 15 | 刺猬 | 15 | +----+--------+------+3 rows in set (0.00 sec)复制代码 ログイン後にコピー 表中可能包含的行级锁首先是每一行的记录锁——(5,重塑,5),(10,达达,5),(15,刺猬,15)。 假设 user 表的索引值有最大值 maxIndex 和最小值 minIndex,user 表还可能存在间隙锁(minIndex,5),(5,10),(10,15),(15,maxIndex)。 共三个记录锁和四个间隙锁。 2.1 唯一索引列等值查询首先来说唯一索引列的等值查询,这里的等值查询可以分为两种情况:命中与未命中。 当唯一索引列的等值查询命中时:
上表の
したがって、一意のインデックス列の同等のクエリがヒットすると、ヒットしたレコードのみがロックされます。 一意のインデックス列の等価クエリが見つからない場合:
ユーザーテーブルに追加されたロックはギャップロック(1,5)であることがわかります。
2.2 一意のインデックス列範囲クエリ 範囲クエリは等しい値クエリよりも複雑で、テーブル内に境界値が存在するかどうか、および境界値にヒットするかどうかを考慮する必要があります。 まず、境界値がテーブルに存在するが欠落している状況を見てみましょう: sessionAsessionB
Next-key Lock
sessionB
|
以上がMySQL についての私の理解 5: ロックとロック ルールの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。