序文悲観的ロックと楽観的ロックは、同時実行の問題を解決するために使用される 2 つのアイデアであり、異なるプラットフォームで独自の実装が行われます。たとえば、Java では、 synchronized は悲観的ロック (厳密ではなく、ロックのアップグレード プロセスがあり、重量ロックにアップグレードされた場合にのみ重量ロックと見なされます) の実装と見なすことができ、 Atomic*** アトミック クラスは楽観的ロックの実装と見なすことができます。 悲観的ロック 排他性と排他性が強く、処理プロセス全体を通じてデータがロックされます。これは通常、システムのミューテックスを通じて実現されます。他のスレッドがロックを取得しようとすると、ロックを保持しているスレッドがロックを解放するまでブロックされます。 楽観的ロック データの変更とアクセスについては、競合が発生しないと仮定して楽観的に考えてください。データが更新のために送信されたときにのみ、競合がチェックされます。競合がない場合、更新はスムーズに送信されます。競合がある場合は、すぐに失敗し、ユーザーにエラーが返され、次に何をするかをユーザーが選択できるようになります。一般的に、更新が正常に送信されるまで、失敗後も再試行が続けられます。 MySQL 自体はロック機構をサポートしています。たとえば、「最初にクエリを実行してから書き込む」という要件がある場合、プロセス全体がアトミック操作であり、途中で中断されないことが望まれます。このとき、クエリされたデータ行に「排他ロック」を追加することでこれを実現できます。現在のトランザクションがロックを解放しない限り、MySQL は現在のトランザクションがロックを解放するまで他のトランザクションが排他ロックを取得するのをブロックします。 MySQL の下部にあるこの種の排他ロックは、「悲観的ロック」と呼ばれます。 MySQL 自体は楽観的ロック機能を提供していないため、開発者が自分で実装する必要があります。一般的な方法は、データ行のバージョンをマークするためにテーブルにバージョン列を追加することです。データを更新する必要がある場合は、バージョンを比較する必要があります。バージョンが一貫している場合、その期間中にデータが他のトランザクションによって変更されていないことを意味します。そうでない場合は、データが他のトランザクションによって変更されており、再試行する必要があることを意味します。 実際の戦闘データベースに製品テーブルと注文テーブルという 2 つのテーブルがあるとします。 注文後、ユーザーは次の 2 つの操作を実行する必要があります。
初期データ: ID 1 の商品の在庫は 100 個で、注文テーブルのデータは空です。 クライアントは 10 個のスレッドを開始して同時に注文を行います。ロックフリー、悲観的、楽観的ロックのシナリオでのパフォーマンスはどうなるでしょうか? 以下はテーブルを作成するための SQL ステートメントです。 -- 商品テーブル CREATE TABLE `goods` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `goods_name` varchar(50) NOT NULL, `price` 小数点(10,2) NOT NULL, `stock` int(11) デフォルト '0', `version` int(10) unsigned NOT NULL DEFAULT '0', 主キー (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 デフォルト CHARSET=utf8 -- 注文テーブル CREATE TABLE `t_order` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `goods_id` bigint(20) NOT NULL, `order_time` 日時 NOT NULL、 BTREE を使用した主キー (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 デフォルト CHARSET=utf8 1. ロックなし何もアクションは実行されません。 //注文する private boolean order(){ 商品 goods = goodsMapper.selectById(1L); ブール値の成功 = false; (goods.getStock() > 0) の場合 { 商品の在庫数を1に設定します。 // 在庫を更新する goodsMapper.updateById(goods); // 注文を作成します orderMapper.save(goods.getId()); 成功 = true; } 成功を返します。 } コンソール出力は次のとおりです。 2. 悲観的ロック商品を照会する際に、FOR UPDATE を追加し、データ行に排他ロックを追加します。こうすることで、再度照会する際に他のスレッドがブロックされます。現在のスレッドのトランザクションがコミットされ、ロックが解除されるまで、他のスレッドは注文を続行できます。この方法では同時実行パフォーマンスが低くなります。 SQL文 @Select("SELECT * FROM goods WHERE id = #{id} FOR UPDATE") 商品selectForUpdate(Long id); コンソール出力は次のとおりです。 注意: FOR UPDATE が有効になるにはトランザクション内にある必要があり、クエリと更新は同じトランザクション内にある必要があります。 ! ! 3. 楽観的ロック実装のアイデアは、更新が行われるたびにバージョン番号を確認することです。バージョン番号が一貫している場合、その期間中に他のスレッドによってデータが変更されていないことを意味し、現在のスレッドは更新を正常に送信できます。そうでない場合は、データが他のスレッドによって変更されたことを意味し、現在のスレッドは、ビジネスが成功するまでスピンして再試行する必要があります。 データを更新するときはバージョン番号を増やす必要があります。 ! ! @Update("商品を更新します。SET stock = #{stock}、version = version+1 WHERE id = #{id} AND version = #{version}") int updateByVersion(Long id、Integer stock、Integer version); ビジネスコード ブール順序(){ 商品 goods = goodsMapper.selectById(1L); ブール値の成功 = false; (goods.getStock() > 0) の場合 { 商品の在庫数を1に設定します。 // バージョン番号で在庫を更新します int result = goodsMapper.updateByVersion(goods.getId(), goods.getStock(), goods.getVersion()); 結果 <= 0 の場合 // 更新に失敗しました。期間中に他のスレッドによってデータが変更されており、再帰的に再試行する必要があることを示しています。 return order(); } // 注文を作成します orderMapper.save(goods.getId()); 成功 = true; } 成功を返します。 } コンソール出力は次のとおりです。 要約するこれで、MySQL の悲観的ロックと楽観的ロックのソリューションに関するこの記事は終わりです。MySQL の悲観的ロックと楽観的ロックに関するより関連性の高いコンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: Linux での wget コマンドの基本的な使い方
>>: ウォーターフォールフローレイアウトを実装する3つの方法
border-radius で生成できる四角形やその他の図形に影を追加する場合 (「Adaptive...
Linuxでユーザーが所属するグループを変更する1. ユーザーのグループを設定する usermod ...
1. リストシンボルを設定するlist-style-type: attribute; //リストの...
目次1. インストール2. カプセル化に問題はない3. ファイルを作成する4. アドレス設定をリクエ...
<br />友人と話し合っていたとき、フレームワークのレイヤー設計の中で最も核となるのは...
目次1. ポーテナーの紹介2. Portainer アーキテクチャの概要3. Portainerのイ...
最近、個人のウェブサイトを書き直しました。Alibaba Cloudで新しいサーバーを購入しました。...
目次序文プロミスチェーンMDN エラー連鎖デフォルト処理略語非同期待機序文この記事を書いた理由は、ユ...
数字で始まる次の CSS クラス名は有効になりません。 .1番目{ 色: 赤; }有効な CSS ク...
フロントエンドがインターフェースを要求すると、バックエンドでインターフェースが定義されます。ステータ...
Docker テクノロジの開発により、マイクロサービスの実装にさらに便利な環境が提供されます。Doc...
次のような製品部品表があります。一部 部品ID 部品タイプ 製品ID ---------------...
複雑な表を作成するには HTML を使用します。複雑なテーブルでは通常、td の rowspan 属...
最も人気のあるフロントエンド フレームワークの 1 つとして、Vue は多くのフロントエンド開発エン...
MySQL v5.7.19 正式版(32/64 ビットインストール版および zip 解凍版) 1. ...