あなたは、MySQLのロックを知っている必要があります

背景

ロックデータベースは、マルチスレッド高同時実行の場合には機構のデータの整合性と安定性を確保するために使用されます。MySQLの異なる基盤となるストレージエンジンは、ロックの粒度と異なるメカニズムのサポートが実現しています。MyISAMテーブルは、テーブルロックをサポートしていますInnoDBは、行とテーブルのロックをサポートしています。現在、MySQLのデフォルトのストレージエンジンはInnoDBはここで、あるのInnoDBロックを紹介します。

InnoDBストレージエンジン

InnoDBテーブルを使用することの二つの利点:まず、トランザクションをサポートするために、第二行ロックのサポートがあります。

MySQLのトランザクション

高い同時実行同時処理トランザクションの場合、いくつかの問題をもたらすでしょう

  1. ダーティリードは:トランザクションデータBのトランザクションが読み取るために提出されていないトランザクションのプロセスを意味します。例えば、転送の例では:トランザクションがコミットされたときに、小さなトランザクションが1000をオンにする小さなBを開け、小さなBだけではなく、お金が口座に入金されていると述べました。実際に口座に入金(その後、喜んでビブラートを磨くために行ってきました)、この時バックの小さなロールトランザクション、1000および背面に従事見つけたもののバランスと表示するには、この時間の小さなB。小さなBは、バランスを見て、お金が消えていたことがわかっ行くにビブラートを磨きます。

  2. 非反復可能読み取り:実装のプロセスに起因する矛盾した結果の現象は、別のトランザクションでは、このデータを修正し、トランザクションをコミットされたトランザクションの実行中にデータのクエリに複数回言及。たとえば:20の暁明年齢が発見され、今回のトランザクションAが再び読み込むトランザクションBは、暁明年齢が20に変更して提出しますトランザクションAが最初にボブの年齢は18歳で読んで、これは同じデータであり、非反復可能読み取ります。

  3. マジックを読む:データのバッチが完了した後に魔法の読み取りは、通常、そこに他の事項があり、原因と現象の条件を満たすようにデータを挿入し、操作を指します。トランザクションデータベース性別男性のステータスが1に変更された裕福な、この時間トランザクションBを示し、0人のお金レコードの状態で挿入され、この時間は、ユーザは、単にデータを変更表示されます。たとえば、私たちは、ファントム読み取りに登場回線に変更がないことがわかりました。選択操作のための魔法の読書は、挿入操作のために頻繁にあるダーティ・リードと非反復可能読み取り。

これらの質問の高い同時トランザクションを持っているので、私たちは、トランザクション分離レベルを持っていました

  • (非コミット読み取り)非コミット読み取り:最低レベルを、どのような場合には保証できません。

  • コミット読み取り(コミット読み取り):汚れが発生するの読み込みを避けることができます。

  • 反復可能読み取り(反復可能読み取り):ダーティリード防ぐことができ、またとないが発生して読み取ります。

  • シリアライズ(直列化):汚いを防止することができるが、非反復可能読み取りを読み取り、ファントムリードが発生します。

InnoDBのいくつかの一般的なロック機構

  1. 共有と排他ロック(共有および排他ロック)、InnoDBは、標準的な行ロックは排他ロックであり、二つの方法によって共有実装します。共有ロック(Sロック):トランザクションがロックを取得した後にデータを読み取ることができます排他ロック(Xロック):トランザクションがロックを取得した後にデータを更新または削除することができます。トランザクションが共有ロックSを取得した後で、2つのトランザクションが共有ロックのSを保持しているが、他の業務を許可していないXのロックを取得している、他のトランザクションはSロックを取得できます。トランザクションが排他ロック(X)を取得した場合、それは他のトランザクションがSまたはXのロックを取得はできません彼らが得ることができる前にロックが解放されるまで、トランザクションが待機しなければなりません。我々は、次のSQLの経験の下にすることができます。

#T1 
一貫したスナップショットWITHのSTART TRANSACTION; 
SELECT * FROMカテゴリWHERE SHAREモードでcategory_no = 2ロック。// 共享锁 
SELECT * FROMカテゴリWHERE category_no = 2 のための UPDATE。// 独占锁
COMMIT; 
#T2 
一貫したスナップショットWITHのSTART TRANSACTION; 
SELECT * FROMカテゴリWHERE SHAREモードでcategory_no = 2ロック。// 共享锁 
UPDATEカテゴリセットのカテゴリ名= '动漫' WHERE category_no = 2; // 独占锁
COMMIT;
 

 

  1. 意図的ロック(意図ロックが)、上記支持のInnoDBテーブルロックと行ロックが、意図的ロックは次のトランザクションを示すために使用されるテーブルロックは、ロックの種類(共有または排他)を取得することです。意図共有ロックに意図的ロック(IS)と意図排他ロック(IX)は、順番に続くトランザクションが共有ロックまたは排他ロックを取得する表します。意図的ロックは、買収を表示する必要はありません、我々は自動的に意味はあなたが共有ロックまたは排他ロックを取得したい場合は、それが最初の目的や意図排他ロックに共有ロックを取得しなければならない、と言うことです時に共有ロックまたは排他ロックを取得取得します。テーブル全体のリクエストを操作し、それがどのようなデータをロックしていないでしょうがない限り意図的ロックは何かをロックしません。存在の意味は、唯一のトランザクションはデータの行をロックしたり、データの行をロックしようとして存在していることを示すために使用されます。

    原文:意図ロックは、トランザクションがテーブルに行の後必要とするロックのタイプ(共有または排他)を示すテーブルレベルロックです。

  2. テーブルは、テーブルにインデックスがない場合は、インデックスレコードロックは、インデックスのロックされている場合、行をロックするレコードロック(レコードロック)が、次にInnoDBは隠されたクラスタ化インデックスのロックを作成します。だから我々は、ロック競合を減らすことができ、クエリクエリの実行中にインデックスを使用しようとします。

  3. 间隙锁(Gap Locks),间隙锁是一种记录行与记录行之间存在空隙或在第一行记录之前或最后一行记录之后产生的锁。间隙锁可能占据的单行,多行或者是空记录。通常的情况是我们采用范围查找的时候,比如在学生成绩管理系统中,如果此时有学生成绩 60,72,80,95,一个老师要查下成绩大于 72 的所有同学的信息,采用的语句是 select * from student where grade > 72 for update,这个时候 InnoDB 锁住的不仅是 80,95,而是所有在 72-80,80-95,以及 95 以上的所有记录。为什么会 这样呢?实际上是因为如果不锁住这些行,那么如果另一个事务在此时插入了一条分数大于 72 的记录,那会导致第一次的事务两次查询的结果不一样,出现了幻读。所以为了在满足事务隔离级别的情况下需要锁住所有满足条件的行。

  4. Next-Key Locks,NK 是一种记录锁和间隙锁的组合锁。是 2 和 3 的组合形式,既锁住行也锁住间隙。并且采用的左开右闭的原则。InnoDB 对于查询都是采用这种锁的。

     

举个例子

 
 
CREATE TABLE `a` (  
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,

`uid` int(10) unsigned DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `idx_uid` (`uid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO `a`(uid) VALUES (1);
INSERT INTO `a`(uid) VALUES (2);
INSERT INTO `a`(uid) VALUES (3);
INSERT INTO `a`(uid) VALUES (6);
INSERT INTO `a`(uid) VALUES (10);

# T1START TRANSACTION WITH CONSISTENT SNAPSHOT; //1
SELECT * FROM a WHERE uid = 6 for UPDATE; //2
COMMIT; //5

# T2START TRANSACTION WITH CONSISTENT SNAPSHOT; //3
INSERT INto a(uid) VALUES(11);
INSERT INto a(uid) VALUES(5);

//4
INSERT INto a(uid) VALUES(7);
INSERT INto a(uid) VALUES(8);
INSERT INto a(uid) VALUES(9);
SELECT * FROM a WHERE uid = 6 for UPDATE;
COMMIT;
ROLLBACK;
 
 

 


 

按照上面 1,2,3,4 的顺序执行会发现第 4 步被阻塞了,必须执行完第 5 步后才能插入成功。这里我们会很奇怪明明锁住的是uid=6 的这一行,为什么不能插入 5 呢?原因就是这里采用了 next-key 的算法,锁住的是(3,10)整个区间。感兴趣的可以试一下。

おすすめ

転載: www.cnblogs.com/pypua/p/11130506.html