タグ:公共号の記事
記事の声明3ロック分析を読み取るために、この記事に良いアイデアを読む前に:
支度をしています
物語の展開をスムーズにするためには、のは、テーブルを作成し、テーブル内の一部のレコードを挿入してみましょう、以下のSQL文は次のとおりです。
CREATE TABLE hero (
number INT,
name VARCHAR(100),
country varchar(100),
PRIMARY KEY (number),
KEY idx_name (name)
) Engine=InnoDB CHARSET=utf8;
INSERT INTO hero VALUES
(1, 'l刘备', '蜀'),
(3, 'z诸葛亮', '蜀'),
(8, 'c曹操', '魏'),
(15, 'x荀彧', '魏'),
(20, 's孙权', '吴');
复制代码
さてhero
、次のようにテーブルの場合に記録されています:
mysql> SELECT * FROM hero;
+--------+------------+---------+
| number | name | country |
+--------+------------+---------+
| 1 | l刘备 | 蜀 |
| 3 | z诸葛亮 | 蜀 |
| 8 | c曹操 | 魏 |
| 15 | x荀彧 | 魏 |
| 20 | s孙权 | 吴 |
+--------+------------+---------+
5 rows in set (0.01 sec)
复制代码
現象
ある:一人の学生が質問をQ&A冊子グループでREAD COMMITTED
不可解な事が分離レベルで起こりました。さて、最初にすべてのテクトニクスの、現在のセッションでは、デフォルトの分離レベルに設定されるだろうREAD COMMITTED
。
mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
Query OK, 0 rows affected (0.00 sec)
复制代码
トランザクションは、T1
最初に実行しました:
# T1中,隔离级别为READ COMMITTED
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM hero WHERE country = '魏' FOR UPDATE;
+--------+---------+---------+
| number | name | country |
+--------+---------+---------+
| 8 | c曹操 | 魏 |
| 15 | x荀彧 | 魏 |
+--------+---------+---------+
2 rows in set (0.01 sec)
复制代码
country
実装にこの文は、テーブル全体のスキャンモードスキャンクラスタ化インデックスを使用して行われなければならないので、列は、インデックス付きの列ではありませんEXPLAIN
文はまた、私たちの考えていることを証明します:
mysql> EXPLAIN SELECT * FROM hero WHERE country = '魏' FOR UPDATE;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | hero | NULL | ALL | NULL | NULL | NULL | NULL | 5 | 20.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.02 sec)
复制代码
私たちが知っている、MySQLの文を学んだ前に、分析をロックするにはREAD COMMITTED
全表スキャン方式を使用してクエリを実行した場合、次の分離レベル、InnoDBストレージエンジンは、サーバー層に記録するかどうかをテストし、各レコードプラスまともなレコードロックをオンにしますWHEREそれは、レコードのリリースロックアウトに適用されていない場合は、条件を満たしています。この例では、使用するFOR UPDATE
文を、プラスXタイプは確かに深刻なレコード・ロックです。2つだけのレコードが満たすWHERE
条件ので、実際にのみ、これらの2件の最終予選レコードを追加するX型正经记录锁
(つまり、あるnumber
列の値8
と15
二つのレコード)。もちろん、我々は使用することができますSHOW ENGINE INNODB STATUS
我々の分析を証明するためのコマンドを:
mysql> SHOW ENGINE INNODB STATUS\G
... 省略了很多内容
------------
TRANSACTIONS
------------
Trx id counter 39764
Purge done for trx's n:o < 39763 undo n:o < 0 state: running but idle
History list length 36
Total number of lock structs in row lock hash table 1
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 281479653009568, not started
0 lock struct(s), heap size 1160, 0 row lock(s)
---TRANSACTION 281479653012832, not started
0 lock struct(s), heap size 1160, 0 row lock(s)
---TRANSACTION 39763, ACTIVE 468 sec
2 lock struct(s), heap size 1160, 2 row lock(s)
MySQL thread id 19, OS thread handle 123145470611456, query id 586 localhost 127.0.0.1 root
TABLE LOCK table `xiaohaizi`.`hero` trx id 39763 lock mode IX
RECORD LOCKS space id 287 page no 3 n bits 72 index PRIMARY of table `xiaohaizi`.`hero` trx id 39763 lock_mode X locks rec but not gap
Record lock, heap no 4 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 4; hex 80000008; asc ;;
1: len 6; hex 000000009b4a; asc J;;
2: len 7; hex 80000001d3012a; asc *;;
3: len 7; hex 63e69bb9e6938d; asc c ;;
4: len 3; hex e9ad8f; asc ;;
Record lock, heap no 5 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 4; hex 8000000f; asc ;;
1: len 6; hex 000000009b4a; asc J;;
2: len 7; hex 80000001d30137; asc 7;;
3: len 7; hex 78e88d80e5bda7; asc x ;;
4: len 3; hex e9ad8f; asc ;;
... 省略了很多内容
复制代码
どちらのid
ある39763
取引を指しT1
、それはのためにあることが分かるheap no
値4
と5
二つのレコード追加X型正经记录锁
(lock_modeにXロックRECはなく、ギャップを )。
そして、また、分離レベルをオンにすることでREAD COMMITTED
、トランザクションT2
実行中:
# T2中,隔离级别为READ COMMITTED
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM hero WHERE country = '吴' FOR UPDATE;
(进入阻塞状态)
复制代码
明らかに、全表スキャンを介してこの文をロックする各クラスタ化インデックスのレコードを取得するために、実行されます。しかしので、number
値8
のレコードがされているT1
追加X型正经记录锁
、T2
持っていると思いますが、取得することはできません、だけでブロックする余裕ができ、この時間はSHOW ENGINE INNODB STATUS
、私たちの推測(のみ傍受部)であることを証明することができます:
---TRANSACTION 39764, ACTIVE 34 sec fetching rows
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1160, 1 row lock(s)
MySQL thread id 20, OS thread handle 123145471168512, query id 590 localhost 127.0.0.1 root Sending data
SELECT * FROM hero WHERE country = '吴' FOR UPDATE
------- TRX HAS BEEN WAITING 34 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 287 page no 3 n bits 72 index PRIMARY of table `xiaohaizi`.`hero` trx id 39764 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 4; hex 80000008; asc ;;
1: len 6; hex 000000009b4a; asc J;;
2: len 7; hex 80000001d3012a; asc *;;
3: len 7; hex 63e69bb9e6938d; asc c ;;
4: len 3; hex e9ad8f; asc ;;
复制代码
見ることができますT2
取得するために待機してheap no
いる4
レコードでX型正经记录锁
(lock_modeにXロックRECはなく、ギャップ待ち)。
これらは、我々はそれを分析することができ、通常のブロッキングロジックですが、もしT2
次の実行UPDATE
文:
# T2中,隔离级别为READ COMMITTED
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> UPDATE hero SET name = 'xxx' WHERE country = '吴';
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
复制代码
WTFは?そうであっても気軽に成功した実行され、ブロックされていませんか?同じWHERE
条件、同じ実行計画は、どのようにSELECT ... FOR UPDATE
してUPDATE
case文が同じではありませんロック?
理由
ハハ、はい、確かに違います。実際には、MySQLは読ん文の3種類をサポートしています。
-
(:一貫した読み取りも読取り一貫性、英語名として知られている)通常の読書。
これは、最後に追加されていない通常のSELECT文を指し、
FOR UPDATE
またはLOCK IN SHARE MODE
SELECT文。通常の読み取りモードを実行すると、生成されReadView
、読書記録するためのMVCC機構をロックされることはありません直接。小贴士: 对于SERIALIZABLE隔离级别来说,如果autocommit系统变量被设置为OFF,那普通读的语句会转变为锁定读,和在普通的SELECT语句后边加LOCK IN SHARE MODE达成的效果一样。 复制代码
-
ロック(:ロック読む英語名)をお読みください。
レコードを読んで、あなたは、レコードに対応するロックを取得する必要があります前に、これはトランザクションです。もちろん、ロックの種類へのアクセスは、現在のトランザクション分離レベル、要因の実施計画、クエリや他の文に依存し、参照がなされることがあります。
-
一貫性の半分は(:セミ一貫した読む英語名)をお読みください。
これは、一般的な読書とロックの間に挟まれたリードリードモードです。のみで
READ COMMITTED
分離レベル下(又は場合開いinnodb_locks_unsafe_for_binlogシステム変数で)使用UPDATE
するときステートメントを使用します。具体的な意味は、ときということであるUPDATE
文はロックがその他の事項のレコードに追加されている読み、InnoDB
最新バージョンは、レコードアウトを提出読み、その後のバージョンかどうかを決定しますUPDATE
文はWHERE
、条件に一致しない不一致の場合その結果、次のレコードのレコードロック、、マッチングレコードが再び読み込まれ、ロックに供されている場合。この取引のように単に作るためにUPDATE
ブロックされた他の文を最小限にするステートメントを。ヒント:の半一貫性はクラスタ化インデックスをロックレコードの場合にのみ適用読んで、ロックされたセカンダリインデックスの記録には適用されません。
明らかに、取引がされているため、当社のトップはしつこいの例T2
実行UPDATE
文が一貫性を読んだときの半分を使用しては、判定number
列の値8
と15
これら二つのレコードの最新バージョンでは、提出されcountry
た列の値がどちらもあるUPDATE
ステートメントWHERE
条件'吴'
ので、それらをロックしていない、彼らに直接進んでください。
あなたが考えることを忘れないで自分の仕事の過程で学生を分析するときに、この知識は簡単に、無視することができますSemi-Consistent Read
ああ、コードワードは、どのようなものをダ〜、役に立つああ前方に助けて、簡単ではありません
パンフレット
MySQLはパンフレットを見るために、より高度な知識を確認したいことがあります。「MySQLはそれがどのように動作するかです:GENERから理解MySQLの」リンク。冊子の主な内容は、MySQLの中核となる概念のいくつかを説明するための比較的単純な言語は、このような記録、インデックス、ページ、表スペース、クエリの最適化、取引のように、高度で、ビューの白色点からのもので、約単語の総数をロックオリジナルイラストの作品の何百もの以上40万言葉。私は主に、学習曲線ので、少しスムーズに、MySQLは先進平均プログラマの学習曲線を削減したいです-
余談
疲れ記事を書く、時にはあなたは、多くの修正の結果の後ろに実際にある非常に滑らかな読み取りを、感じます。あなたが前方に良いしてくださいヘルプを感じた場合には、ここに私のパブリック数時間から子牛を引いて、歓迎の注意程度の時間に、内側より呉服技術「我々は小さなカエルですが、」〜です非常に感謝: