PostgreSQL LOCK(ロック)
ロックは主にデータベースデータの一貫性を維持するためのもので、ユーザーが1行またはテーブル全体を変更するのを防ぐことができ、一般的に同時実行性の高いデータベースで使用されます。
複数のユーザーがデータベースにアクセスする際、同時操作を制御しないと、誤ったデータを読み取ったり保存したりする可能性があり、データベースの一貫性を損なう可能性があります。
データベースには2つの基本的なロックがあります:排他ロック(Exclusive Locks)と共有ロック(Share Locks)。データオブジェクトに排他ロックがかかっている場合、他のトランザクションはそれを読み取りまたは変更することができません。
共有ロックがかかっている場合、そのデータベースオブジェクトは他のトランザクションが読み取ることはできますが、変更することはできません。
LOCK コマンド構文
LOCK コマンドの基本構文は次のとおりです:
LOCK [ TABLE ] name IN lock_mode
- name:ロックする既存のテーブルの名前(スキーマ修飾は任意)。テーブル名の前にのみ指定された場合は、そのテーブルのみがロックされます。指定されない場合は、そのテーブルとそのすべての子テーブル(存在する場合)がロックされます。
- lock_mode:ロックモードは、そのロックがどのロックと競合するかを指定します。ロックモードが指定されていない場合は、最も制限の大きい ACCESS EXCLUSIVE モードが使用されます。指定可能な値は:ACCESS SHARE、ROW SHARE、ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE です。
一度ロックを取得すると、そのロックは現在のトランザクションの残りの期間保持されます。テーブルのロックを解除するコマンドはありません。ロックは常にトランザクションの終了時に解放されます。
デッドロック
2つのトランザクションが互いに相手の操作の完了を待っている場合、デッドロックが発生する可能性があります。PostgreSQL はそれらを検出してロールバックで終了させることができますが、デッドロックは依然として非常に不便です。アプリケーションがこの問題に遭遇しないようにするには、アプリケーションが同じ順序でオブジェクトをロックするように設計してください。
アドバイザリロック
PostgreSQL は、アプリケーション定義の意味を持つロックを作成する方法を提供します。これらはアドバイザリロックと呼ばれます。システムがそれらの使用を強制しないため、それらを正しく使用するかはアプリケーション次第です。アドバイザリロックは、MVCC モデルに適さないロック戦略に非常に役立ちます。
例えば、アドバイザリロックの一般的な用途の1つは、いわゆる「フラットファイル」データ管理システムで典型的な悲観的ロック戦略をシミュレートすることです。テーブルに格納されたフラグも同じ目的に使用できますが、アドバイザリロックはより高速で、テーブルの肥大化を回避し、セッションの終了時にサーバーによって自動的にクリーンアップされます。
例
COMPANY テーブルを作成する(COMPANY SQL ファイルをダウンロード)、データ内容は次のとおりです:
サンプルdb# select * from COMPANY; id | name | age | address | salary ----+-------+-----+-----------+-------- 1 | Paul | 32 | California| 20000 2 | Allen | 25 | Texas | 15000 3 | Teddy | 23 | Norway | 20000 4 | Mark | 25 | Rich-Mond | 65000 5 | David | 27 | Texas | 85000 6 | Kim | 22 | South-Hall| 45000 7 | James | 24 | Houston | 10000 (7 rows)
次の例では、サンプルdb データベースの COMPANY テーブルを ACCESS EXCLUSIVE モードでロックします。
LOCK 文はトランザクションモードでのみ機能します。
サンプルdb=#BEGIN; LOCK TABLE company1 IN ACCESS EXCLUSIVE MODE;
上記の操作で次の結果が得られます:
LOCK TABLE
上記のメッセージは、テーブルがトランザクションの終了までロックされていることを示しています。トランザクションを完了するには、トランザクションをロールバックまたはコミットする必要があります。
その他の拡張