そもそも排他制御とは
排他制御とは、同じ資源(データやファイルなど)を複数の処理が同時に使おうとしたときに、矛盾や不整合が起きないように制御する仕組みのことです。
例えば、データベースで在庫数を更新する処理が、複数のユーザーから同時に走ると「在庫がマイナスになる」「最新の更新が上書きされる」といった不具合が起こり得ます。これを防ぐのが排他制御です。
代表的な方法には次のようなものがあります。
- ロック方式(行ロック・テーブルロックなど)
- トランザクション制御(コミット・ロールバック)
- 楽観的排他制御(更新時にバージョン番号や更新日時をチェック)
楽観的ロックと悲観的ロック
今回は、排他制御の中でも、ロック方式の単体テスト方法を紹介します。
ロック方式では楽観的ロックと悲観的ロックがあり、以下のような違いがあります。
-
楽観的ロック
- 「めったに同時更新は起きない」と考えて、更新時に競合チェックをする方式
-
悲観的ロック
- 「他の人が同時に触ると危ない」と考えて、最初からデータにロックをかけて独占する方式
今回は、悲観的ロックの単体テスト方法を紹介します。
単体テスト手順
準備
- トランザクション制御のスタート地点、ゴール地点にログを仕込む
以下のようにログを仕込みます。(※更新処理の内容は割愛します。)
\Log::debug('更新処理START');
// 更新処理
\Log::debug('更新処理END');
早く処理が終わってしまう場合は、sleepも仕込みましょう。
\Log::debug('更新処理START');
// 更新処理
sleep(15);
\Log::debug('更新処理END');
実行
-
同じデータを更新する処理を同時に実行
-
1の間にロックがかかっているか確認
以下のようなロックがかかっているか確認できるクエリを実行しましょう。
↓ロックがかかっている場合は、レコードが返ってきます。
SELECT ENGINE_TRANSACTION_ID,OBJECT_NAME,INDEX_NAME,LOCK_TYPE,LOCK_MODE,LOCK_DATA FROM performance_schema.data_locks;
確認
-
正しくデータが更新できているか確認
対象のデータベースを確認し、データが想定通り更新できているか確認しましょう。 -
ログの手順が想定通りか確認
ログを読み、出現する順番が想定通りか確認しましょう。
参考