次の表を考えます。
create table permissions(id identity);
create table companies(id identity,
permission_id bigint not null,
foreign key(permission_id) references permissions(id) on delete cascade);
create table departments(id identity,
company_id bigint not null,
permission_id bigint not null,
foreign key(company_id) references companies(id),
foreign key(permission_id) references permissions(id) on delete cascade);
部門が削除されたら、次のステートメントをアトミックに実行したいと考えています。
departments
行が削除されますpermissions
部門行に関連付けられた行が削除されますcompanies
部門行に関連付けられた行が削除されますpermissions
会社 (前のポイント) に関連付けられた行が削除されます
質問:
- すべての外部キーに対して
READ_COMMITTED
トランザクション分離を使用すると、行は単一のアトミック ステートメントとして削除されますか? それとも、異常ON CASCADE DELETE
に対して脆弱な個別の削除ステートメントとして実行されますか?READ_COMMITTED
- 会社/部門が削除されたときに (可能であれば原子的に) 会社/部門のアクセス許可を削除するようにデータベースに指示するにはどうすればよいですか?
- SQL標準はこの質問について何か言っていますか? それとも、異なるデータベース間で動作が異なりますか?
説明:
- 会社/部門は権限テーブルを参照する必要があり、その逆ではありません。これは、クロージャー テーブル
permissions
を形成するためです(たとえば、ユーザーは会社に対して権限を持ち、会社は部門に対して権限を持っているため、ユーザーは部門に対して権限を持ちます)。階層関係はさまざまなタイプ (つまり、ユーザー、会社、部門) にまたがるため、権限テーブルは特定のタイプを指すことはできません。したがって、会社/部門は許可を参照する必要があり、その逆ではありません。 CASCADE
部門を削除したいとします。部門の許可、部門、および会社は削除されますが、会社の許可は削除されないため、許可を削除して残りを処理するだけでは十分ではありません。H2 はメイン ステートメントとは別のデータベース接続でトリガーを実行し、2 つのステートメントが同じ会社/部門の行で書き込みロックを要求するため、会社/部門が削除された後にトリガーを使用して権限を削除することはできません。これは、回避策がある H2 の制限が原因でした。https://groups.google.com/d/msg/h2-database/B3xG488RBhI/DOsIMVmPBnAJを参照companies
最初の接続は、削除している行をロックします。permissions
2 番目の接続 (トリガー)は、会社に関連付けられた行を削除しようとON CASCADE DELETE
しますが、会社もロックする必要があります。