ALTER TABLE'da “donmuş” veritabanı


16

Üretim ortamımız, bu sabah bir tabloyu değiştirirken bir sütun ekleyerek bir süre dondu *.

Soruna neden olan SQL:ALTER TABLE cliente ADD COLUMN topicos character varying(20)[];

* Sistemimize giriş yapmak için aynı tablodan bir seçim yapmanız gerekir, böylece kimse değiştirme sırasında giriş yapamaz. Aslında sistemin normal operasyonları sürdürmesine izin vermek için süreci öldürmek zorunda kaldık.


Tablo Yapısı:

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();  

SINIRLARI, TETİKLEYİCİLERİ veya başka bir şeyi devre dışı bırakmalı mıyım?

Belki herhangi bir DB Ayarlama?

Daha fazla analiz için başka neler sağlamalıyım?

Sürüm: gcc tarafından derlenen x86_64-unknown-linux-gnu üzerinde PostgreSQL 9.4.5 (Debian 4.9.2-10) 4.9.2, 64-bit


Bir DDL ifadesi çalıştığı sürece tablo kilitlenir ve erişilemez. Bu konuda yapabileceğiniz hiçbir şey yok.
a_horse_with_no_name

iyi es beklenen değil, ama kesinlikle anlaşılabilir;)
Gonzalo Vasquez

Yanıtlar:


9

DDL işlemleri genellikle üzerinde işlem yaptıkları nesneyi kilitler, bu nedenle planlı bakım pencerelerinin dışında gerçekleştirilmemelidir (kullanıcılarınız bir kesintiye veya sistemin planlanan bir süre boyunca tamamen çevrimdışı olmasını beklerken) - yapabileceğiniz hiçbir şey yoktur bu konuda kolayca 1 .

Bazı işlemler yalnızca yazma kilidini tutar, böylece uygulamanız yalnızca etkilenen nesneleri okuyan istekleri sunmaya devam edebilir.

Belgeler, DDL işlemleri tarafından hangi kilitlerin tutulacağını listelemede oldukça iyi görünüyor.

Bu blog girişinde , bir sütun eklemenin çevrimiçi bir işlem olabileceğini öneren bir özet vardır ve sütun geçersiz kılınabilirse ve varsayılan değeri veya benzersiz bir kısıtlaması yoksa, belirttiğiniz ifadenin kilitler olmadan çalıştırılması gerektiği anlamına gelir (IIRC postgres olarak) aksi belirtilmedikçe sütunları NULLable olarak ayarlar). Ekleme sütunundan sonra başka işlemler yaptınız mı? Belki de üzerine bir dizin oluşturmak (varsayılan olarak tabloya yazma kilidi alır)?

1 Bazı çoğaltma / kümeleme / yansıtma düzenlemeleri, bir aynayı güncellemenize (değişiklik sırasında güncellemeleri duraklatmanıza ve daha sonra yeniden oynatmanıza), bu kopyayı canlı olarak kullanmaya geçmenize ve her kopya güncellenene kadar devam etmenize olanak tanır. kesinti süresi, DDL işlemi sırasında yapılan değişikliklerin yeniden oynatılması için geçen süreyle sınırlıdır. Bunun gibi canlı işlemler risksiz değildir, bu yüzden kesinlikle yapamazsanız, yapısal güncellemeleri gerçekleştirmek ve doğrulamak için uygun bir bakım penceresi ayarlamanız önerilir.


35

Çalıştırmak istediğiniz komut, tabloda bir ACCESS EXCLUSIVE kilidi alır ve bu tabloya diğer tüm erişimi engeller. Ancak bu kilidin süresi yalnızca birkaç milisaniye olmalıdır, çünkü eklemek istediğiniz sütun gibi bir sütun eklemek tablonun yeniden yazılmasını gerektirmez, sadece meta verilerin güncellenmesini gerektirir.

Sorunun nereden gelebileceği ve donuts için dolar bahse giriyorum, gördüğünüz sorun bunun kilit öncelikleridir. Birisi bu masada ACCESS SHARE kilidi gibi zayıf bir kilide sahip ve süresiz olarak kamp yapıyorlar (belki de sızdırılmış olan işlemde boş bir bağlantı? Psql'yi açan biri, tekrarlanabilir bir okuma modunda bir sorgu başlattı, ve sonra tatile gitti?).

EKLE KOLON, gereken ERİŞİMİ ÖZEL almaya çalışır ve ilk kilidin arkasında sıraya girer.

Şimdi gelecekteki tüm kilit istekleri, bekleyen ACCESS EXCLUSIVE isteğinin arkasında sıraya giriyor.

Kavramsal olarak, önceden verilen kilitle uyumlu gelen kilit istekleri, bekleyen ACCESS EXCLUSIVE'ı atlayabilir ve sırayla verilebilir, ancak PostgreSQL bunu böyle yapmaz.

Uzun ömürlü zayıf kilidi tutan süreci bulmanız gerekir.

Bunu, pg_locks tablosunu sorgulayarak yapabilirsiniz.

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

Eğer her şey kilitliyken bunu yaparsanız, sadece bir cevap almalısınız (birden fazla uzun ömürlü suçlu yoksa). Bunu zaten KOLONU EKLE'yi öldürdükten sonra yaparsanız, çok sayıda tanınmış kilit görebilirsiniz, ancak birkaç kez tekrarlarsanız, her seferinde bir veya birkaç tane kalmalıdır.

Daha sonra pg_lock'tan aldığınız PID'yi alabilir ve suçlunun ne yaptığını görmek için pg_stat_activity'ye sorgulayabilirsiniz:

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;

Bu nedenle, bir işlemin içinde bir sorgu çalıştırdı ve ardından işlemi kapatmadan boşta kaldı. Şimdi saat 13:13, yani 5 dakikadır atıl durumdalar.


6
Bu cevap hayatımı kurtardı
Mahendra

1
Benimkini de kurtardım, ilgili kısım lock prioritiesçok iyiydi, çünkü başka yerlerde okumadım, teşekkürler!
Edson Horacio Junior
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.