Database "dibekukan" pada ALTER TABLE

15

Lingkungan produksi kami hanya membeku * pagi ini untuk sementara waktu ketika mengubah tabel, menambahkan kolom sebenarnya.

SQL yang menyinggung:ALTER TABLE cliente ADD COLUMN topicos character varying(20)[];

* Login ke sistem kami memerlukan pilih dari tabel yang sama, sehingga tidak ada yang bisa login selama tabel perubahan. Kami benar-benar harus mematikan proses untuk memungkinkan sistem melanjutkan operasi normal.


Struktur meja:

CREATE TABLE cliente
(
  rut character varying(30) NOT NULL,
  nombre character varying(150) NOT NULL,
  razon_social character varying(150) NOT NULL,
  direccion character varying(200) NOT NULL,
  comuna character varying(100) NOT NULL,
  ciudad character varying(100) NOT NULL,
  codigo_pais character varying(3) NOT NULL,
  activo boolean DEFAULT true,
  id serial NOT NULL,
  stock boolean DEFAULT false,
  vigente boolean DEFAULT true,
  clase integer DEFAULT 1,
  plan integer DEFAULT 1,
  plantilla character varying(15) DEFAULT 'WAYPOINT'::character varying,
  facturable integer DEFAULT 1,
  toolkit integer DEFAULT 0,
  propietario integer DEFAULT 0,
  creacion timestamp without time zone DEFAULT now(),
  codelco boolean NOT NULL DEFAULT false,
  familia integer DEFAULT 0,
  enabled_machines boolean DEFAULT false,
  enabled_canbus boolean DEFAULT false,
  enabled_horometro boolean DEFAULT false,
  enabled_comap boolean DEFAULT false,
  enabled_frio boolean DEFAULT false,
  enabled_panico boolean DEFAULT false,
  enabled_puerta boolean DEFAULT false,
  enabled_rpm boolean DEFAULT false,
  enabled_supervisor integer DEFAULT 0,
  demo boolean,
  interno boolean,
  mqtt_enable boolean NOT NULL DEFAULT false,
  topicos character varying(20)[],
  CONSTRAINT pk_cliente PRIMARY KEY (rut),
  CONSTRAINT fk_cliente_familiaid FOREIGN KEY (familia)
      REFERENCES cliente_familia (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT pk_pais FOREIGN KEY (codigo_pais)
      REFERENCES pais (codigo) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT unique_id_cliente UNIQUE (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE cliente
  OWNER TO waypoint;
GRANT ALL ON TABLE cliente TO waypoint;
GRANT ALL ON TABLE cliente TO waypointtx;
GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE cliente TO waypointtomcat;
GRANT SELECT ON TABLE cliente TO waypointphp;
GRANT SELECT ON TABLE cliente TO waypointpphppublic;
GRANT ALL ON TABLE cliente TO waypointsoporte;
GRANT SELECT, INSERT ON TABLE cliente TO waypointsalesforce;
GRANT SELECT ON TABLE cliente TO waypointadminuser;
GRANT SELECT ON TABLE cliente TO waypointagenda;
GRANT SELECT ON TABLE cliente TO waypointmachines;
GRANT SELECT ON TABLE cliente TO waypointreports;
GRANT SELECT ON TABLE cliente TO readonly;

CREATE INDEX index_cliente
  ON cliente
  USING btree
  (rut COLLATE pg_catalog."default");

CREATE INDEX index_cliente_activo
  ON cliente
  USING btree
  (activo);

CREATE INDEX index_cliente_id_activo
  ON cliente
  USING btree
  (id, activo);

CREATE INDEX index_cliente_rut_activo
  ON cliente
  USING btree
  (rut COLLATE pg_catalog."default", activo);


CREATE TRIGGER trigger_default_admin
  AFTER INSERT
  ON cliente
  FOR EACH ROW
  EXECUTE PROCEDURE crea_default_admin();

CREATE TRIGGER trigger_default_grupo
  AFTER INSERT
  ON cliente
  FOR EACH ROW
  EXECUTE PROCEDURE crea_default_clientegrupo();  

Haruskah saya menonaktifkan KENDALA, PEMICU, atau yang lainnya?

Mungkin ada Tuning DB?

Apa lagi yang harus saya berikan untuk analisis lebih lanjut?

Versi: PostgreSQL 9.4.5 pada x86_64-unknown-linux-gnu, dikompilasi oleh gcc (Debian 4.9.2-10) 4.9.2, 64-bit

Gonzalo Vasquez
sumber
Selama pernyataan DDL berjalan, tabel terkunci dan tidak dapat diakses. Tidak ada yang bisa Anda lakukan tentang itu.
a_horse_with_no_name
yah, tidak menyenangkan seperti yang diharapkan, tetapi benar-benar dapat dimengerti;)
Gonzalo Vasquez

Jawaban:

8

Operasi DDL biasanya mengunci objek yang ditindaklanjuti, jadi jangan dilakukan di luar jendela pemeliharaan yang direncanakan (saat pengguna Anda mengharapkan gangguan atau sistem sepenuhnya offline hingga jumlah waktu yang direncanakan) - tidak ada yang dapat Anda lakukan tentang ini dengan mudah 1 .

Beberapa operasi hanya menyimpan kunci tulis, sehingga aplikasi Anda dapat terus melayani permintaan yang hanya membaca objek yang terpengaruh.

Dokumentasi tersebut tampaknya cukup baik dalam membuat daftar kunci apa yang mungkin dipegang oleh operasi DDL.

Entri blog ini memiliki ringkasan yang menyarankan menambahkan kolom dapat menjadi operasi online jika kolom tersebut dapat dibatalkan dan tidak memiliki nilai default atau kendala unik, meskipun itu menyiratkan bahwa pernyataan yang Anda nyatakan seharusnya dijalankan tanpa kunci (seperti postgres IIRC kolom default menjadi NULLable kecuali Anda secara eksplisit menyatakan sebaliknya). Apakah Anda menjalankan operasi lain setelah kolom tambahkan? Mungkin membuat indeks di atasnya (yang akan mengambil kunci tulis di atas meja secara default)?

1 Beberapa pengaturan replikasi / pengelompokan / mirroring akan memungkinkan Anda untuk memperbarui cermin (menjeda pembaruan selama perubahan dan mengulanginya setelah), beralih ke menggunakan salinan itu sebagai yang aktif, dan seterusnya sampai setiap salinan diperbarui, jadi downtime terbatas pada waktu yang diperlukan untuk memutar ulang perubahan yang dilakukan selama operasi DDL. Meskipun demikian, pengoperasian langsung seperti itu bukan tanpa risiko, jadi kecuali Anda benar-benar tidak dapat direkomendasikan Anda mengatur jendela perawatan yang tepat untuk melakukan dan memverifikasi pembaruan struktural di.

David Spillett
sumber
35

Perintah yang ingin Anda jalankan mengambil kunci ACCESS EKSKLUSIF di atas meja, mencegah semua akses lain ke meja itu. Tetapi durasi kunci ini harus hanya beberapa milidetik, karena menambahkan kolom seperti yang ingin Anda tambahkan tidak memerlukan tabel untuk ditulis ulang, itu hanya membutuhkan metadata untuk diperbarui.

Di mana masalahnya bisa masuk, dan saya yakin Anda dolar untuk donat bahwa itu adalah masalah yang Anda lihat, adalah prioritas utama. Seseorang memiliki kunci yang lemah, seperti kunci ACCESS SHARE, di atas meja itu, dan mereka berkemah di atasnya tanpa batas waktu (mungkin koneksi idle-in-transaction yang telah bocor? Seseorang yang membuka psql, memulai kueri dalam mode baca berulang, dan kemudian pergi berlibur?).

ADD COLUMN mencoba mengambil ACCESS EKSKLUSIF yang dibutuhkannya, dan ia mengantri di belakang kunci pertama.

Sekarang semua permintaan kunci di masa depan mengantri di belakang permintaan AKSES EKSKLUSIF yang menunggu.

Secara konseptual, permintaan kunci masuk yang kompatibel dengan kunci yang sudah diberikan dapat melompati ACCESS EXCLUSIVE yang menunggu dan dikabulkan dari giliran, tetapi bukan itu yang dilakukan PostgreSQL.

Anda perlu menemukan proses yang menahan kunci lemah berumur panjang.

Anda dapat melakukan ini dengan menanyakan tabel pg_locks.

select * from pg_locks where 
    granted and relation = 'cliente'::regclass \x\g\x

Jika Anda melakukan ini saat semuanya dikunci, Anda hanya akan mendapatkan satu jawaban (kecuali ada beberapa penyebab yang berumur panjang). Jika Anda melakukan ini setelah Anda sudah membunuh KOLOM TAMBAH, maka Anda mungkin melihat banyak kunci yang diberikan, tetapi jika Anda mengulanginya beberapa kali harus ada satu atau beberapa yang tinggal di sekitar setiap kali.

Anda kemudian dapat mengambil PID yang Anda dapatkan dari pg_lock, dan kueri dengan itu ke pg_stat_activity untuk melihat apa yang dilakukan pelaku:

select * from pg_stat_activity where pid=28731 \x\g\x

...

backend_start    | 2016-03-22 13:08:30.849405-07
xact_start       | 2016-03-22 13:08:36.797703-07
query_start      | 2016-03-22 13:08:36.799021-07
state_change     | 2016-03-22 13:08:36.824369-07
waiting          | f
state            | idle in transaction
backend_xid      |
backend_xmin     |
query            | select * from cliente limit 4;

Jadi, ia menjalankan kueri, di dalam transaksi, dan kemudian menganggur tanpa pernah menutup transaksi. Sekarang 13:13, jadi mereka menganggur selama 5 menit.

jjanes
sumber
6
Jawaban ini menyelamatkan hidup saya
Mahendra
1
Menyelamatkan milik saya juga, bagian tentang lock prioritiesitu sangat bagus, karena saya belum pernah membaca tentang itu di tempat lain, terima kasih!
Edson Horacio Junior