mysql悲観ロックと楽観ロックの理解と応用分析


本文の実例はmysqlの悲観的なロックと楽観的なロックを述べました。皆さんに参考にしてあげます。具体的には以下の通りです。
悲観的なロックと楽観的なロックは、人々が定義した概念です。
彼らをmysqlの中で提供するロック機構(表錠、行錠、列彼ロック、共有錠)と混同してはいけません。
一、悲観ロック
名前の通り、データの処理に対して悲観的で、いつも衝突が発生すると思って、データを取得して改正する時、他の人はデータを修正します。したがって、データ処理全体でデータをロックする必要があります。
悲観的なロックの実現は、通常、データベースによって提供されるロック機構によって実現されます。たとえば、mysqlの排他的ロック、select....for udateは悲観的なロックを実現します。
例:商品を秒殺する過程で、在庫の数量が減少して、超売りの状況が現れないようにする。

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='     ';
商品在庫数numsフィールドタイプをunsignedとして設定し、データベースレベルで負数が発生しないことを保証します。
なお、悲観的なロックを使用すると、mysqlの自動提出機能をオフにし、set aut comit=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;
事務提出時は事務中のロックを解除します。
悲観的なロックは併発制御で鍵をかけてからデータを処理する保守策をとっています。データ処理の安全性は保証されていますが、効率も低下しています。
二、楽観ロック
名前の通り、データの処理には楽観的な態度を持っています。データは一般的に衝突しないと楽観的に考えています。データの更新を提出する時だけ、データの衝突を検出することができます。
競合が発見されたら、エラー情報をユーザに返して、ユーザに操作を決定させます。
楽観的なロックの実現は、データベースに依存しないロック機構であり、私たち自身が実現する必要があります。実現方法は、一般的にデータバージョンを記録することです。
テーブルにバージョン番号またはタイムスタンプのフィールドを追加し、データを読み込む場合はバージョン番号を一緒に読み出し、データ更新時はバージョン番号を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データベースのロックに関するスキルのまとめ」「MySQL記憶プロセス技術大全」「MySQL常用関数大まとめ」「MySQLログ操作テクニック大全」「MySQL事務操作技術まとめ
この記事が皆様のMySQLデータベース計に役立つことを期待します。