違い: 悲観的ロックは、データ処理に対する悲観的な態度です。同時実行性の競合が発生すると常に考えています。データを取得および変更するとき、他の人がデータを変更するため、データは全体的にロックされる必要があります。データ処理プロセス。オプティミスティック ロックでは、データ処理が楽観的であり、通常は競合が発生しないと考えられます。データの更新が送信された場合にのみ、データの競合が検出されます。
このチュートリアルの動作環境: Windows7 システム、mysql8 バージョン、Dell G3 コンピューター。
悲観的ロックと楽観的ロックは人によって定義された概念であり、同時リソースを処理するためのアイデアおよび一般的な方法として理解できます。
これらを、mysql で提供されるロック機構 (テーブル ロック、行ロック、排他的ロック、共有ロック) と混同しないでください。
1. 悲観的ロック
名前が示すように、データ処理に対して悲観的な態度を示し、同時実行の競合が発生すると常に信じています。変更された場合、他の人がデータを変更します。したがって、データ処理プロセス全体を通じてデータをロックする必要があります。
悲観的ロックの実装は、通常、mysql の排他的ロック、悲観的ロックを実装するための更新の選択 .... など、データベースによって提供されるロック メカニズムに依存します。
例: 製品のフラッシュ セール プロセス中、売れすぎの状況を避けるために在庫数量が削減されます。
CREATE TABLE `tb_goods_stock` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `goods_id` bigint(20) unsigned DEFAULT '0' COMMENT '商品ID', `nums` int(11) unsigned DEFAULT '0' COMMENT '商品库存数量', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `modify_time` datetime DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `goods_id` (`goods_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品库存表';
製品在庫数量フィールド タイプを符号なしに設定して、データベース レベルで負の数値が発生しないようにします。
悲観的ロックを使用するには、mysql の自動コミット機能をオフにして autocommit = 0 に設定する必要があることに注意してください;
mysql の行レベルのロックはインデックスに基づいていることに注意してください。 SQL がインデックスを使用しない場合、テーブルレベルのロックを使用してテーブル全体がロックされます。
1. トランザクションを開き、販売する製品をクエリして、レコードをロックします。
begin;select nums from tb_goods_stock where goods_id = {$goods_id} for update;
2. 製品の数量が購入数量より大きいかどうかを判断します。満足できない場合は、トランザクションをロールバックします。
3. 条件が満たされている場合は、在庫を減らしてトランザクションを送信します。
update tb_goods_stock set nums = nums - {$num} where goods_id = {$goods_id} and nums >= {$num}; commit;
トランザクション中のロックは、トランザクションがコミットされると解放されます。
ペシミスティック ロックは、最初にロックしてから同時実行制御でデータを処理するという保守的な戦略を採用しており、データ処理の安全性は確保されますが、効率も低下します。
2. 楽観的ロック
名前が示すように、データの処理について楽観的です。通常の状況、および送信のみ データの競合は、データが更新されたときにのみ検出されます。
競合が見つかった場合は、エラー メッセージがユーザーに返され、ユーザーは操作方法を決定できます。
オプティミスティック ロックの実装は、データベースが提供するロック メカニズムに依存しません。独自に実装する必要があります。実装方法は、一般に、データのバージョンを記録することです。1 つはバージョン番号、そして 2 つはデータ バージョンです。もう 1 つはタイムスタンプによるものです。
テーブルにバージョン番号またはタイムスタンプ フィールドを追加します。データを読み取るときは、バージョン番号も一緒に読み取ります。データが更新されるときは、バージョン番号に 1 を加えます。
データ更新を送信するとき、現在のバージョン番号が最初に読み取られたバージョン番号と等しいかどうかを判断します。等しい場合は更新します。そうでない場合は、データの有効期限が切れているとみなされ、更新は拒否され、ユーザーは再操作を求められます。
CREATE TABLE `tb_goods_stock` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `goods_id` bigint(20) unsigned DEFAULT '0' COMMENT '商品ID', `nums` int(11) unsigned DEFAULT '0' COMMENT '商品库存数量', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `modify_time` datetime DEFAULT NULL COMMENT '更新时间', `version` bigint(20) unsigned DEFAULT '0' COMMENT '版本号', PRIMARY KEY (`id`), UNIQUE KEY `goods_id` (`goods_id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='商品库存表';
1. 販売する製品をクエリして、バージョン番号を取得します。
begin;select nums, version from tb_goods_stock where goods_id = {$goods_id};
2. 製品の数量が購入数量より大きいかどうかを判断します。満足できない場合は、トランザクションをロールバックします。
3. 条件が満たされる場合は、在庫を削減します。 (更新する場合は、現在のバージョンが手順 1 で取得したバージョンと同じであるかどうかを確認します。)
update tb_goods_stock set nums = nums - {$num}, version = version + 1 where goods_id = {$goods_id} and version = {$version} and nums >= {$num};
4. 更新操作が正常に実行されたかどうかを確認し、成功した場合は送信し、そうでない場合はロールバックします。
オプティミスティック ロックはプログラムの実装に基づいているため、デッドロックがなく、読み取りが多いアプリケーション シナリオに適しています。競合が頻繁に発生すると、上位層のアプリケーションが常にユーザーに再操作を要求するため、実際にはパフォーマンスが低下するため、この場合は悲観的ロックの方が適しています。
(推奨チュートリアル:mysql ビデオ チュートリアル)
以上がmysqlの楽観的ロックと悲観的ロックの違いは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。