1. MR。
公式文書からの翻訳:ロック読み込み
あなたがデータを照会し、同じトランザクション内の関連データを挿入または更新する場合は、通常のSELECT文では、十分な保護を与えるものではありません。他のトランザクションは、あなただけの照会同じ行を更新または削除することができます。InnoDBは、ロックの2種類が追加の安全性を提供している読み込み、サポートしています。
あなたがデータを照会し、同じトランザクションに関連するデータを挿入または変更する場合、従来のselect文は、適切な保護を提供していません。他のトランザクションは、あなたが照会されている行を変更または削除することができます。InnoDBは2つの読み込みロックは、セキュリティ・メカニズムを提供することができますサポートしています。
共有モードでSELECT ... LOCKが 読まれているすべての行に共有モードロックを設定します。他のセッションは、行を読み取ることができますが、あなたのトランザクションがコミットされるまで、それらを変更することはできません。これらの行のいずれかがまだコミットしていない別のトランザクションによって変更された場合は、クエリは、そのトランザクションが終了するまで待機した後、最新の値を使用しています。
共有モードでSELECT ... LOCKは、共有ロックを読み込み、他のセッションこれらのラインを読むことができるの行に設定されているが、トランザクションがコミットする前に、あなたはそれらを変更することはできません。これらの行は、修正すべきその他の事項があるが提出されていない場合は、クエリは、最新の値を使用して、トランザクションの終了後まで待ちます。
インデックスは、検索出会いを記録するために、 UPDATEがSELECT ... FOR 行と関連するすべてのインデックスエントリ、あなたはそれらの行のためのUPDATE文を発行した場合と同じようにロックします。他のトランザクションは、または特定のトランザクション分離レベルでデータを読み込むから共有モードでSELECT ... LOCKをやってから、それらの行を更新するからブロックされています。一貫した読み取りビューに存在するレコードに設定されたすべてのロックを無視して読み込みます。(;彼らは、レコードのインメモリコピーにログを元に戻す適用することにより、再構成されたレコードの古いバージョンをロックすることができません。)
レコードインデックス検索はUPDATEが、ラインおよび関連をロックし、それらの行と同じとアップデートステートメントを実行SELECT ... FORインデックス・エントリに遭遇しました。他のトランザクションがこれらの行の更新操作の実装にブロックされ、共有ロックを取得する、またはトランザクション分離レベル等からいくつかのデータを読み出します。一貫性読むには、(一貫性非ロック読み込み)読み込みビューの記録上の任意のロックを無視します。(記録の古いバージョンをロックすることはできません。彼らは、アンドゥログを適用することにより、再構築されたレコードのインメモリコピーです。)
トランザクションがコミットまたはロールバックされたときSHAREモードおよびUPDATEクエリのロックが設定したすべてのロックが解除されています。
注
自動コミットが無効になっているときUPDATE FOR SELECT使用して更新のための行のロックにのみ適用(どちらかのSTART TRANSACTIONとトランザクションを開始するか、自動コミットが有効になっている場合は0に自動コミットを設定することで、仕様に一致する行がロックされていません。
トランザクションがコミットまたはロールバックされた後、クエリのロックの設定すべての共有ロックと排他ロックが解除されます。
注:
更新操作のためのUPDATE行ロックFOR SELECTを使用するだけで、自動コミットに適用されます(開始STARTトランザクションがトランザクションを自動コミットまたは0に設定した場合)無効になっています。自動コミットが有効になっている場合は、対応の行がロックされません。
第二に、要約
ここで参考:排他ロックとMySQLでの共有ロック
共有ロック(Sロック、共有ロック):共有モードで... LOCK]を選択します。他のトランザクションがデータを読み取ることができますが、すべての共有ロックが解放されるまでのデータを変更することはできません。
データの行の後取引プラス共有ロックした場合、読み書きできる、他のトランザクションは、データがロックを共有することができるが、排他的ロックを追加することができず、データのみを読み取ることができ、データを変更することはできません。
排他ロック(Xロック、排他ロック):SELECT ... FOR UPDATE。データプラス排他ロック後のトランザクションは、他のトランザクションがデータロックのいずれかを追加することができない場合。データを読むだけでなく、データを変更するだけではなく、排他的ロックトランザクションを取得します。
注意:通常、デフォルトのSELECT文がロックされていないが、デフォルトCUD操作に加えて、排他ロック。
第三に、確認してください
注意:使用mysqlのバージョン5.8.9は、InnoDBのトランザクション分離レベルは、デフォルトの分離レベル反復可能読み取り(繰り返し読む)です。
次の状況を確認します。
- 現在のトランザクションが共有ロックを取得した後、あなたは他のトランザクションが読み取りおよび書き込み、共有ロックを取得できるかどうか、読み取りと書き込みができます。
- 2つのトランザクションが共有ロックを取得した後は、操作を更新することができます。
- 現在のトランザクションが排他ロックを取得した後、他のトランザクションは、あなたは、読み取りおよび書き込み、共有ロックを獲得できるかどうか。
- データは、より多くの排他ロックに追加することができるかどうか。
- 関係行ロックとインデックス。
- インデックスデータの繰り返し率は、全表スキャンになりますが高すぎます。
1、現在のトランザクションが共有ロックを取得した後、他のトランザクションが読み取りおよび書き込み、共有ロックを取得できるかどうか、読み取りと書き込みができます:あなたが読むことができる、あなたが共有ロックを取得することができ、書き込むことはできません
現在のトランザクションを書くことができます。
1つのトランザクションデータ共有ロックの列を得た後、トランザクション2は、行ブロックを更新します。
1提出トランザクションの後、2トランザクションは成功しました:
図2に示すように、ロックを取得した後にデータの行を共有する二つのトランザクションが、更新操作を実行できますではありません
2つのトランザクションが同時に行共有ロックでデータを取得し、トランザクション1は、行ブロックを更新します。
トランザクション2を提出した後、1つのトランザクションは成功しました:
図3に示すように、現在のトランザクションあなたは読み取りと書き込みとデータライン上の共有ロックを取得することができる場合、行排他ロックに他のトランザクションデータを取得する:他のトランザクションが読み取ることができ、共有ロックを取得できないが、書き込むことができません
可以读该行数据:
不可以获取该行数据共享锁:
不可以更新该行数据:
4、是否可对一条数据加多个排他锁:不可以
5、行锁和索引的关系:查询字段未加索引(主键索引、普通索引等)时,使用表锁
注:InnoDB行级锁基于索引实现。
未加索引时,两种行锁情况为(使用表锁):
- 事务1获取某行数据共享锁,其他事务可以获取不同行数据的共享锁,不可以获取不同行数据的排他锁
- 事务1获取某行数据排他锁,其他事务不可以获取不同行数据的共享锁、排他锁
加索引后,两种行锁为(使用行锁):
- 事务1获取某行数据共享锁,其他事务可以获取不同行数据的排他锁
- 事务1获取某行数据排他锁,其他事务可以获取不同行数据的共享锁、排他锁
未加索引表结构:
未加索引,事务1获取某行数据共享锁,事务2获取不同行数据共享锁成功:
未加索引,事务1获取某行数据共享锁,事务2更新不同行数据阻塞:
未加索引,事务1获取某行数据排他锁,事务2获取不同行数据共享锁阻塞:
未加索引,事务1获取某行数据排他锁,事务2获取不同行数据排他锁阻塞:
加索引后表结构:
加索引后,事务1获取某行数据共享锁,事务2更新不同行数据成功:
加索引后,事务1获取某行数据排他锁,事务2获取不同行数据共享锁成功:
加索引后,事务1获取某行数据排他锁,事务2获取不同行数据排他锁成功:
6、索引数据重复率太高会导致全表扫描:当表中索引字段数据重复率太高,则MySQL可能会忽略索引,进行全表扫描,此时使用表锁。可使用 force index 强制使用索引。
表结构:
CREATE TABLE `room` (
`id` int(11) NOT NULL AUTO_INCREMENT, `uid` int(11) NOT NULL, `username` varchar(200) NOT NULL DEFAULT '', `state` varchar(255) NOT NULL DEFAULT '-1', `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `index_uid` (`uid`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
表数据:
获取 uid = ‘11’ 的数据的行锁并更新,但更新失败:
降低数据重复率,更新成功:
强制使用索引,更新成功:force index(index_uid)
注意:ここでテーブルロックを使用する場合は、なぜ、他のトランザクションが排他ロックを取得できますか?
:を使用するので force index
、及び インデックスに基づいてInnoDBの行レベルロックを達成するので、ここでは行ロックを使用しています。
4つのInnoDB行ロックタイプ紹介
InnoDBの行ロックの三種類:
- レコードのロック:インデックス・エントリのロックは、資格のある行をロックします。他のトランザクションは、変更、およびロックエントリを削除することはできません。
- ギャップロック:インデックスエントリロック、レコードのロック範囲の間の「ギャップ」に、インデックスはアイテムそのものは含まれません。他のトランザクションの範囲内でデータを挿入するロックできません。
- ネクストキーロック:ロックインデックスエントリ自体とインデックス範囲、ギャップロックとロックのつまりレコード組み合わせ。マジックは、読書の問題を解決します。