ロックデータベース:原理行レベルのロック、テーブルロック、楽観的ロック、悲観的ロック

まず、相対的な用語。

テーブル・レベル・ロック(表全体をロック)
、ページレベルロック(ロック1)
行レベルロック(ロック・ライン)
共有ロック(Sロックは、MyISAMテーブルは、読み取りロックと呼ばれる)
排他ロック(Xロックは、MyISAMテーブルが書き込みロックと呼ばれる)
ペシミスティック・ロック(抽象ロックの非現実的な存在)
楽観的ロック(ロックの抽象的、非現実的な存在)

二、InnoDBはMyISAMテーブルと

デフォルトのMyISAMストレージエンジンを使用する前に、MySQLの5.5は、その後のInnoDBを使用しています。現在のストレージエンジンを表示します。

show variables like '%storage_engine%';

MyISAMテーブルを使用すると、低性能が得られ、テーブル全体をロックしますレコードを更新し、ロックされている運用データを使用し、同時性は高くありません。もちろん、それはまた、デッドロックを存在しません。

最大の違いはInnoDBとMyISAMの2つの点である:まず、InnoDBがサポートするトランザクションを、第二は、InnoDBが使用され、行レベルのロックをつまり、あなたは何を変更する必要がある、あなたは何をすべきかあなただけのロックすることができます。

MySQLでは、行レベルのロックを直接レコードロックではなく、ロックインデックスインデックスは、SQL文の場合、主キーのインデックスの操作の2つです、MySQLはこの主キーのインデックスをロックするメインキーインデックスと非主キー索引に分け、非プライマリキーインデックスの操作if文、MySQLは最初にロックされ、非プライマリキーインデックスをロックします主キーのインデックスに関連します。

InnoDBの行ロックは、インデックスエントリロックを与えることによって達成され、インデックスがない場合、InnoDBがクラスタ化インデックスの隠されたロックによって記録されます。言い換えれば、あなたは、インデックス条件を介してデータを取得していない場合は、InnoDBのテーブルは、すべてのデータ、同じテーブルロックと実際の結果をロックしますインデックスがないので、ログの1がテーブル全体をスキャンするために、全表スキャンを持っている、あなたがテーブルをロックする必要が見つけます。

第三に、共有ロックと排他ロック

1.最初:データベースのデフォルトのCRUD操作は、排他ロックを追加し、クエリがすべてのロックを追加しません

共有ロック:リソースに対する共有ロックは、リソース自体が他のリソースを読み取ることができ、読み取ることができる(また、共有ロックは共有ロックがより共存できることを継続することができる)が、変更することはできません。すべての共有ロックが完全に解放された後に変更するには、それは待たなければなりません。構文は次のとおりです。
select * from table lock in share mode

排他ロック:リソースプラス排他ロック自体については、CRUDすることができ、他の人は何もできません。構文は次のとおりです。
select * from table for update- 排他自動ロックへの追加および削除

2.以下の例は、(:から回復に引用http://blog.csdn.net/samjustin1/article/details/52210125を):

T1は、としても、別のスレッドにスレッドT1、T2として理解することができ、要求が実行されたデータベース、他に代わってT2要求を表します。

例1:

T1: select * from table lock in share mode
以下の例も想定ので、クエリは長い時間がかかるであろうと仮定して)

T2: update table set column1='hello'

プロセス:

T1运行(并加共享锁)
T2运行
If T1还没执行完
T2等......
else锁被释放
T2执行
endif

T2は、アップデートを実行する前に、テーブルに排他ロックをテーブルを追加しようとするので、T2の理由は、待機する、およびデータベースの要件は、共有ロックと排他リソースロックと同じに共存することはできません。T2はT1の実行を待たなければならないので、共有ロックは、更新ステートメントを開始する前に排他ロックを追加するために、解放されます。

例2:

T1: select * from table lock in share mode

T2: select * from table lock in share mode

実行完了を待たずにT2 T1をここでは、しかし、すぐに実行することができます。

分析:
Tlの動作は、テーブルは、次に、同じリソース上で2つのロックが同時に(例えば、同一の表として)存在することができるコールlockBとして、テーブル上に共有ロックを追加し、そのようなコールlockAT2ランとして、ロックされています。これは、共有ロックと呼ばれ、共有ロックは互換性があります。共有ロックが同時にリソースを読んで、他の人々を防ぐが、リソースを変更するから他人を妨げないことをこれが意味。

例3:

T1: select * from table lock in share mode

T2: select * from table lock in share mode

T3: update table set column1='hello'

T2 T1は、あなたが実行するために待つことができない使い果たし、T3は、我々は、T1とT2を待つ必要が実行するために完了するまで実行されています。T3は、すべてのロックは、T1とT2のように共有することができる開放プラス排他ロックして、更新操作を実行する必要がありますので。

デッドロック:(実施例4)

T1: begin transelect * from table lock in share modeupdate table set column1='hello'

T2: begin transelect * from table lock in share modeupdate table set column1='world'

T1は、実行を選択し、更新を実行する準備ができたときにロックを共有し、選択を達成しながら表に、T1をT1とT2と仮定する、T2も表は、共有ロックを、ロック機構によれば、T1は、ロックが実行するために排他的ロックにアップグレードする必要が共有されています次の更新。前と同様、テーブルに排他ロック、必要があり、他の共有ロック(T2)が解除されるアップグレード、T2等がロック解除T1を共有しています。そして、デッドロック。

例5:

T1: begin tranupdate table set column1='hello' where id=10

T2: begin tranupdate table set column1='world' where id=20

この文は、最も一般的ですが、多くの人々は、それがデッドロックを生成する機会を持っていると思うが、実際には状況に依存します

idは、主キー(主キーインデックスデフォルト)である場合、このレコードは突然T1(ID = 10のレコード)は、レコードが排他ロックに追加され、T2は、記録に対するインデックスによって位置決めされると、同様に見つけ、そしてうしたがって、各更新のそれぞれのT1及びT2は、互いに独立していることを、添加排他ロックを記録するため= 20 ID。T2は待つ必要はありません。

idは一般的なものである場合、インデックスはありません。その後、T1は、ID = 20を見つけるために行番号= 10プラス排他的ロック、T2に、フルテーブルスキャンを必要とする場合。T1はT2の全表スキャンで、その結果、記録排他ロックとして追加されているので、しかしT1プラス排他ロック、テーブルに加えて意図的ロックのためのデータベースのデフォルトは、T2は、テーブル全体をスキャンするので、待つ必要が、実際には(上運びません意図的ロック)はT1の実行が完了すると、あること、解放され、T2待ちにつながっています。

それを解決するためにどのようにデッドロック?次のように一つの方法は次のとおりです。

例6:

T1: begin transelect * from table for updateupdate table set column1='hello'

T2: begin transelect * from table for updateupdate table set column1='world'

このように、選択T1は、テーブルプラス選択の実装で排他ロック、T2上で直接実行する場合、T1および他のものは完全には実装実行するために完了する必要があります。デッドロックを除きます。第3のユーザの上に、だけでなく、彼のために行ロックの存在のクエリを実行したい場合でも、第四、第五、ユーザはそのため待機します、待たなければなりませんでした。大規模な同時の場合、パフォーマンスがあまりにも優しいように見えるためにのために私たちは待ってみましょう。

だから、ここでは、(MSSQL、注意として:MySQLの更新ロックが存在しない)、いくつかのデータベースの更新ロックをご紹介します。

例7:

T1: begin transelect * from table (加更新锁)update table set column1='hello'

T2: begin transelect * from table (加更新锁)update table set column1='world'

実際には、更新ロックは、彼の行ロックの変化として見ることができるが、それはまた、他の人が読み取ることができる(また、ロックを共有可能)。しかし、無他の操作を、私は更新ロックを解除しない限り。選択するT1、プラス更新ロック。T2は、更新ロックを追加する準備ができて、実行しているが、そこでは、待たなければならなかった更新ロックを発見しました。理由選択T1のUSER3、USER4 ...テーブルのデータテーブルを照会する必要がある、とないが、実装にブロックされたとき、その後、効率を向上させ、実施例6に比べて、まだ照会することができます。

そして、計画や意図は、ロックをロックがあります。ある意図的ロック:自動的に排他ロックと組み合わせると、行が変化し、それが表に加えて意図的ロックがデフォルトになりますが、この時、ロックされたレコードがあることを示し、他のものは、あなたは、テーブルに加えてテーブルをロックすることはできません。何かの存在の同様の指標をロックする意図がない場合は、他の人がロックされているレコードと非効率的であるかどうかを確認するために、ロックテーブルを追加する前に、テーブル全体をスキャンする必要があります。これらの計画をロックし、プログラマが少し、理解して行きませんでした。

第四に、楽観と悲観的ロックロック

ケース:

項目は、ユーザが同時に在庫-1及び二つ以上のユーザーを購入する必要があり、後で、この時点で3つの手順を行った同時読み出しストックは、いくつかの動作を実行次に、nは、最後に行われたupdate table setインベントリ= N-1、これは間違っていることは明らかです。

ソリューション:

1.(実際には、すなわち白排他ロック)悲観的ロック

お問い合わせ在庫排他ロック(使用するプログラムselect * from table where id=10 for update

そして、最後に更新インベントリ、およびなど、その後の操作は、トランザクションをコミットします。

Bプログラム在庫数を照会するときにAがまだ排他的ロックを解放していない場合、それは待機します。

BとCのプログラム......

2.楽観的ロック(テーブル設計および実装するためのコードで)

一般的に、製品テーブルに追加されたバージョンのバージョンフィールドやタイムスタンプタイムスタンプフィールド

プログラム後に更新を実行するクエリは次のようになります。
update table set num=num-1 where id=10 and version=23

このように、データはそれを修正していることを確認し、データをチェックアウトするために一貫しており、他の幹部のプログラムが変更されていません。アップデートに失敗した場合もちろん、あなたが成功を確実にするために、更新を再試行を試みることができ、更新操作の前に、プログラムの他の実装が更新された在庫数を示します。更新に失敗した可能性を回避するためには、再試行の回数(アリババ開発ハンドブックと劣らず3回以上再試行回数)を調整するのが合理的です。

概要:上記の違いについて、あなたは楽観と悲観的ロックを見ることができます。

1.ペシミスティック・ロックは、プログラムは、他のプログラムはより低いスループットをもたらすもクエリを許可されていない排他ロックを排他的ロックを使用します。より多くのクエリの場合ならば、楽観的ロックを使用しています。

2.オプティミスティック・ロックの更新が失敗する可能性があり、さらに更新が何回か失敗した、これは危険です。あなたはより頻繁に書くのであれば、それほど厳しいスループットのために、悲観的ロックを使用しています。

楽観的ロックと読み、書かれた悲観的ロック:それは一つの文章です。



おすすめ

転載: www.cnblogs.com/windpoplar/p/11938432.html