マルチユーザーデータベースの登場により、同じデータの同時変更を制限する必要が生じました。これにより、パラレル変化を防ぎ、データの整合性を維持するためのさまざまなロックメカニズム(ロック管理)が登場しました。
アクセス制御がなければ、同時操作はデータの損傷や損失を引き起こす可能性があります。たとえば、二つのトランザクションが同時に1行を更新し、一方のトランザクションの変更が失われることがあります。厳しすぎないロックは競合問題(レースコンディション)を引き起こし、過剰なロックはパフォーマンスの低下(デッドロック、コンテンション)を引き起こします。
現代のDBMSには、ロックレベル(行レベル、ページレベル、テーブルレベル)とさまざまなモード(共有、排他、更新)があります。プログラマーは、トランザクションの分離レベルや明示的なロックコマンド(例:SELECT ... FOR UPDATE)を通じてこれを管理できます。
コード例:
-- トランザクションが完了するまで行をロックする BEGIN TRANSACTION; SELECT * FROM users WHERE id = 1 FOR UPDATE; UPDATE users SET name = 'New Name' WHERE id = 1; COMMIT;
主な特徴:
読み取りロック(共有ロック)と書き込みロック(排他ロック)の違いは何ですか?
共有ロックは、複数のトランザクションが同時にデータを読み取ることを許可しますが、変更することはできません。排他ロックは、一つのトランザクションのみがデータを変更でき、他のすべてのトランザクションにはアクセスが禁止されます。
SELECT文はロックを引き起こすことがありますか?
通常、SELECT文はロックを引き起こしませんが、SELECT ... FOR UPDATEを使用したり、高い分離レベル(例:SERIALIZABLE)を使用した場合、DBMSは行をロックする可能性があります。
コード例:
SELECT * FROM products WHERE id = 10 FOR UPDATE;
ロックは「失われた更新」から常に保護しますか?
いいえ、ロックのレベルや分離が適切に選択されていない場合、「ロストアップデート」が発生する可能性があります。これは、一つのトランザクションの変更が別のトランザクションによって失われることを意味します。競合管理メカニズムを慎重に選択する必要があります。
分析部門で二つのプログラムが同時に注文のステータスを更新します。速度向上のためにREAD UNCOMMITTEDレベルが設定されていますが、行のロックを避けるためです。これにより衝突や「失われた」更新が発生し、一部のデータが損傷しました。
利点:
欠点:
販売部門では、重要な処理をTRANSACTION + SELECT ... FOR UPDATEで包みました。行レベルでの読み取りと更新の操作を区別しました。
利点:
欠点: