sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLでドロップするときに、参照されるテーブルに対する排他的アクセスロックを回避する

    グーグルして、ドロップテーブル(または外部キーをドロップするか外部キーを追加する)が長い間スタックした理由を理解しようとしている人のために:

    PostgreSQL (バージョン9.4から13を見ました)外部キー制約は、実際には外部キーの両端のトリガーを使用して実装されています

    companyテーブル(主キーとしてのid)とbank_accountテーブル(主キーとしてのid、company.idを指す外部キーとしてのcompany_id)がある場合、実際には、bank_accountテーブルに2つのトリガーがあり、会社にも2つのトリガーがあります。テーブル。

    table_name タイミング trigger_name function_name
    bank_account 更新後 RI_ConstraintTrigger_c_1515961 RI_FKey_check_upd
    bank_account 挿入後 RI_ConstraintTrigger_c_1515960 RI_FKey_check_ins
    会社 更新後 RI_ConstraintTrigger_a_1515959 RI_FKey_noaction_upd
    会社 削除後 RI_ConstraintTrigger_a_1515958 RI_FKey_noaction_del

    これらのトリガーの最初の作成(主キーの作成時)には、これらのテーブルに対するSHARE ROW EXCLUSIVEロックが必要です(バージョン9.4以前ではACCESS EXCLUSIVEロックでした)。このロックは「データ読み取りロック」と競合しませんが、他のすべてのロック、たとえば会社のテーブルへの単純なINSERT / UPDATE/DELETEと競合します。

    これらのトリガーを削除するには(外部キーまたはテーブル全体をドロップする場合)、これらのテーブルでACCESSEXCLUSIVEロックが必要です。このロックは他のすべてのロックと競合します!

    したがって、最初に会社のテーブルから単純なSELECTを実行し(トランザクションがコミットまたはロールバックされるまで会社のテーブルのACCESS SHAREロックを保持する)トランザクションAを実行し、現在は他の作業を行っているシナリオを想像してみてください。 3分。トランザクションBでbank_accountテーブルを削除しようとしました。これにはACCESSEXCLUSIVEロックが必要であり、最初にACCESS SHAREロックが解放されるまで待機する必要があります。さらに、companyテーブルにアクセスする他のすべてのトランザクション(SELECT、または、INSERT / UPDATE / DELETE)は、ACCESSSHAREロックを待機しているACCESSEXCLUSIVEロックを待機するためにキューに入れられます。

    長時間実行されるトランザクションとDDLの変更には、慎重な処理が必要です。



    1. MySQLLEFTJOIN複数の条件

    2. 永続的な一時テーブル?

    3. SQL Server(T-SQL)のmsdbデータベースからデータベースメールメッセージを削除する

    4. Extract()がPostgreSQLでどのように機能するか