Das Hinzufügen einer neuen Nullspalte zur Tabelle verursachte eine Sperre

7

Gestern haben wir eine Schemamigration in unserer Produktionsdatenbank durchgeführt, die wir für sicher hielten, bei der jedoch ein Problem aufgetreten ist. Es scheint, als würde das Hinzufügen der neuen Spalte eine Sperre verursachen und unsere Anwendung konnte nicht mehr auf die Tabelle zugreifen. Hier ist eine Erläuterung der Tabelle vor der Migration:

                                                                    Table "public.facilities"
              Column               |            Type             |                        Modifiers                        | Storage  | Stats target | Description
-----------------------------------+-----------------------------+---------------------------------------------------------+----------+--------------+-------------
 id                                | integer                     | not null default nextval('facilities_id_seq'::regclass) | plain    |              |
 name                              | character varying(255)      |                                                         | extended |              |
 phone                             | character varying(255)      |                                                         | extended |              |
 time_zone                         | character varying(255)      |                                                         | extended |              |
 company_id                        | integer                     |                                                         | plain    |              |
 created_at                        | timestamp without time zone |                                                         | plain    |              |
 updated_at                        | timestamp without time zone |                                                         | plain    |              |
 phnkey_id_token                   | character varying(255)      |                                                         | extended |              |
 phnkey_api_key                    | character varying(255)      |                                                         | extended |              |
 phnkey_auth_token                 | character varying(255)      |                                                         | extended |              |
 payment_provider_name             | character varying(255)      |                                                         | extended |              |
 payment_provider_data             | hstore                      |                                                         | extended |              |
 tenant_portal_key                 | character varying(255)      |                                                         | extended |              |
 uuid                              | uuid                        | default uuid_generate_v4()                              | plain    |              |
 deleted                           | boolean                     | default false                                           | plain    |              |
 deleted_on                        | timestamp without time zone |                                                         | plain    |              |
 deleted_by_id                     | integer                     |                                                         | plain    |              |
 accounting_method                 | character varying(255)      |                                                         | extended |              |
 last_exported_on                  | timestamp without time zone |                                                         | plain    |              |
 public_url                        | character varying(255)      |                                                         | extended |              |
 access_hours_same_as_office_hours | boolean                     | default false                                           | plain    |              |
 logo                              | character varying(255)      |                                                         | extended |              |
 next_lease_number                 | integer                     | default 1                                               | plain    |              |
 email                             | character varying           |                                                         | extended |              |
 fax                               | character varying           |                                                         | extended |              |
 store_number                      | character varying           |                                                         | extended |              |
 custom_portal_url                 | character varying           |                                                         | extended |              |
 brand_name                        | character varying           |                                                         | extended |              |
Indexes:
    "facilities_pkey" PRIMARY KEY, btree (id)
    "index_facilities_on_tenant_portal_key" UNIQUE, btree (tenant_portal_key)
    "index_facilities_on_uuid" UNIQUE, btree (uuid)
    "index_facilities_on_company_id" btree (company_id)

Und hier ist die Tabelle, nachdem wir die Spalte "Orientierungspunkte" hinzugefügt haben:

                                                                     Table "public.facilities"
              Column               |            Type             |                        Modifiers                        | Storage  | Stats target | Description
-----------------------------------+-----------------------------+---------------------------------------------------------+----------+--------------+-------------
 id                                | integer                     | not null default nextval('facilities_id_seq'::regclass) | plain    |              |
 name                              | character varying(255)      |                                                         | extended |              |
 phone                             | character varying(255)      |                                                         | extended |              |
 time_zone                         | character varying(255)      |                                                         | extended |              |
 company_id                        | integer                     |                                                         | plain    |              |
 created_at                        | timestamp without time zone |                                                         | plain    |              |
 updated_at                        | timestamp without time zone |                                                         | plain    |              |
 phnkey_id_token                   | character varying(255)      |                                                         | extended |              |
 phnkey_api_key                    | character varying(255)      |                                                         | extended |              |
 phnkey_auth_token                 | character varying(255)      |                                                         | extended |              |
 payment_provider_name             | character varying(255)      |                                                         | extended |              |
 payment_provider_data             | hstore                      |                                                         | extended |              |
 tenant_portal_key                 | character varying(255)      |                                                         | extended |              |
 uuid                              | uuid                        | default uuid_generate_v4()                              | plain    |              |
 deleted                           | boolean                     | default false                                           | plain    |              |
 deleted_on                        | timestamp without time zone |                                                         | plain    |              |
 deleted_by_id                     | integer                     |                                                         | plain    |              |
 accounting_method                 | character varying(255)      |                                                         | extended |              |
 last_exported_on                  | timestamp without time zone |                                                         | plain    |              |
 public_url                        | character varying(255)      |                                                         | extended |              |
 access_hours_same_as_office_hours | boolean                     | default false                                           | plain    |              |
 logo                              | character varying(255)      |                                                         | extended |              |
 next_lease_number                 | integer                     | default 1                                               | plain    |              |
 email                             | character varying           |                                                         | extended |              |
 fax                               | character varying           |                                                         | extended |              |
 store_number                      | character varying           |                                                         | extended |              |
 custom_portal_url                 | character varying           |                                                         | extended |              |
 brand_name                        | character varying           |                                                         | extended |              |
 landmarks                         | character varying           |                                                         | extended |              |
Indexes:
    "facilities_pkey" PRIMARY KEY, btree (id)
    "index_facilities_on_tenant_portal_key" UNIQUE, btree (tenant_portal_key)
    "index_facilities_on_uuid" UNIQUE, btree (uuid)
    "index_facilities_on_company_id" btree (company_id)

Gibt es hier etwas, das zu einer Tabellensperre beim Hinzufügen der Spalte "Orientierungspunkte" führen würde? Wir versuchen nur, die Ausfallzeit in der Zukunft zu vermeiden.

Weitere Informationen: Die Tabelle hat 304 Zeilen und war in einem Zustand, in dem unsere Anwendung sie 8 Minuten lang nicht verwenden konnte.

Die Anwendung ist eine Rails-App und wir haben eine Rake-Task verwendet, um die Migration durchzuführen. Hier ist der Code, den wir verwendet haben:

class AddLandmarkToFacility < ActiveRecord::Migration
  def change
    add_column :facilities, :landmarks, :string
  end
end

Was meiner Meinung nach zu dieser ALTERAussage führt:

ALTER TABLE "facilities" ADD "landmarks" character varying;
tubaguy50035
quelle

Antworten:

9

ALTER TABLEerfordert ein ACCESS EXCLUSIVESchloss. Aus dem Dokument :

ALTER TABLE ändert die Definition einer vorhandenen Tabelle. Im Folgenden werden mehrere Unterformulare beschrieben. Beachten Sie, dass die erforderliche Sperrstufe für jedes Unterformular unterschiedlich sein kann. Eine ACCESS EXCLUSIVE-Sperre wird gehalten, sofern nicht ausdrücklich anders angegeben . Wenn mehrere Unterbefehle aufgelistet sind, ist die gesperrte Sperre die strengste, die für einen Unterbefehl erforderlich ist

Das Hinzufügen einer Spalte dauert normalerweise nicht einige Minuten, wenn es keinen Standardwert gibt oder wenn die Tabelle klein ist, und in Ihrem Fall sind Sie in beiden Fällen gut.

Um diese Sperre zu erhalten, sollten andere Transaktionen jedoch keine Sperren für dieselbe Tabelle enthalten. Es gibt mehrere Dinge zu beachten:

  • Ein einfaches SELECTauf einem Tisch erfordert eine Sperre, die andere daran hindert, ein zu tun ALTER TABLE.
  • Sperren werden erst am Ende ihrer Transaktion freigegeben, nicht am Ende der Anweisung, die sie benötigt.
  • Sobald ein ALTER TABLE ...ADD COLUMNauf eine Sperre wartet, werden auch andere Transaktionen, die an SELECTden Tisch wollen, blockiert.

Die Folgen sind:

  • Wenn Transaktionen mit langer Laufzeit die Tabelle lesen, blockieren sie ALTER TABLEdie Migration, bis sie abgeschlossen sind.

  • Wenn die Migration selbst Teil einer größeren Transaktion ist, blockiert dies andere Prozesse, die auf die Tabelle zugreifen möchten, bis sie festgeschrieben wird.

Daniel Vérité
quelle