この記事では主に、MySQL における楽観的ロックと悲観的ロックの具体的な使用方法を紹介します。この記事では、サンプル コードを通じて詳細に紹介しています。あらゆる人の学習や仕事に一定の参考学習価値があります。必要な友人は、Micro Point の編集者をフォローします。読書、
悲観的ロックの概要 (百科事典):
ペシミスティック ロックは、その名前が示すように、外部 (システムの他の現在のトランザクションや外部システムからのトランザクション処理を含む) によって変更されるデータに対する保守的な態度を指すため、データ処理プロセス全体でデータがロックされます。州。悲観的ロックの実装は、多くの場合、データベースによって提供されるロック メカニズムに依存します (データ アクセスの排他性を真に保証できるのは、データベース層によって提供されるロック メカニズムだけです。それ以外の場合、たとえロック メカニズムがこのシステムに実装されていても、外部システムがデータを変更しないことを保証します)。
使用シナリオの例: MySQL InnoDB を例に挙げます。
商品テーブルにはステータスというフィールドがあり、ステータス 1 は商品が注文されていないことを意味し、ステータス 2 は商品が注文されていることを意味します。その後、特定の商品を注文するときに、次のことを確認する必要があります。商品のステータスが1であること。プロダクト ID が 1 であるとします。
1ロックを使用しない場合の操作方法は以下の通りです。
1 2 3 4 5 6 |
|
上記のシナリオでは、同時アクセスが多い場合に問題が発生する可能性があります。
前述したように、この商品は商品ステータスが 1 の場合にのみ注文できます。上記の最初のステップで問い合わせた商品のステータスは 1 です。ただし、更新操作の 3 番目のステップを実行すると、他の誰かが最初に製品を注文し、商品ステータスを 2 に変更した可能性がありますが、データが変更されたかどうかはわかりません。これにより、同じ問題が発生する可能性があります。注文が二重に行われたため、データが不整合になりました。したがって、この方法は安全ではありません。
2 悲観的ロックを使用して次のことを実現します。
上記のシナリオでは、商品情報のクエリから変更までの注文処理のプロセスがありますが、悲観的ロックを使用する原理は、商品情報をクエリした後、変更が完了するまで現在のデータをロックすることです。このプロセス中、商品はロックされているため、第三者が商品を変更することはありません。
注: 悲観的ロックを使用するには、mysql データベースの自動コミット属性をオフにする必要があります。これは、MySQL がデフォルトで自動コミット モードを使用するためです。つまり、更新操作を実行すると、MySQL は結果を即座にコミットします。
次のコマンドを使用して、MySQL を非自動コミット モードに設定できます。
1 |
|
自動コミットを設定したら、通常の業務を実行できるようになります。詳細は次のとおりです。
1 2 3 4 5 6 7 8 9 10 11 |
|
注: 上記の begin/commit はトランザクションの開始と終了です。前のステップで mysql の自動コミットをオフにしたため、トランザクションの送信を手動で制御する必要がありますが、ここでは詳しく説明しません。
上記の最初のステップでは、クエリ操作を実行しました。更新用に id=1 の t_goods からステータスを選択します。
通常のクエリとは異なり、データベースを通じて悲観的ロックを実装する select...for update メソッドを使用します。現時点では、t_goods テーブルでは、ID 1 のデータがロックされており、他のトランザクションはこのトランザクションが送信されるまで待機してから実行する必要があります。このようにして、現在のデータが他のトランザクションによって変更されないことを保証できます。
注: トランザクションでは、同じデータに対する SELECT... FOR UPDATE または LOCK IN SHARE MODE のみが、他のトランザクションの完了を待ってから実行されることに注意してください。通常、SELECT... はこの影響を受けません。 。上記の例では、select status from t_goods where id=1 for update; を実行した場合を考えます。別のトランザクションで select status from t_goods where id=1 for update; を実行すると、2 番目のトランザクションは最初のトランザクションの送信を待ちます。このとき 2 番目のクエリはブロックされますが、select status from t_goods を実行すると、 where id=1; 2 番目のトランザクションでは、データは通常どおりクエリでき、最初のトランザクションの影響を受けません。