ฐานข้อมูล“ ตรึง” บน ALTER TABLE


15

สภาพแวดล้อมการผลิตของเราเพิ่งแข็ง * เช้านี้สักพักเมื่อเปลี่ยนโต๊ะเพิ่มคอลัมน์จริง

การละเมิด SQL:ALTER TABLE cliente ADD COLUMN topicos character varying(20)[];

* การเข้าสู่ระบบของเราต้องเลือกจากตารางเดียวกันนั้นดังนั้นจึงไม่มีใครสามารถเข้าสู่ระบบในช่วงตารางการเปลี่ยนแปลง เราต้องฆ่ากระบวนการเพื่อให้ระบบกลับมาทำงานตามปกติ


โครงสร้างตาราง:

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

ฉันควรปิดการใช้งานข้อ จำกัด ทริกเกอร์หรืออย่างอื่นหรือไม่

บางทีการปรับแต่งฐานข้อมูลใด ๆ ?

ฉันต้องเตรียมอะไรอีกเพื่อการวิเคราะห์เพิ่มเติม

รุ่น: PostgreSQL 9.4.5 บน x86_64-unknown-linux-gnu รวบรวมโดย gcc (Debian 4.9.2-10) 4.9.2, 64-bit


ตราบใดที่คำสั่ง DDL กำลังเรียกใช้ตารางจะถูกล็อคและไม่สามารถเข้าถึงได้ ไม่มีอะไรที่คุณสามารถทำได้เกี่ยวกับเรื่องนี้
a_horse_with_no_name

ดีไม่ดีเท่าที่ควร แต่เป็นที่เข้าใจอย่างแน่นอน)
กอนซาโล่วาสเกซ

คำตอบ:


8

การดำเนินการ DDL มักจะล็อควัตถุที่พวกเขากำลังทำอยู่ดังนั้นจึงไม่ควรดำเนินการนอกหน้าต่างการบำรุงรักษาตามแผนที่วางไว้ (เมื่อผู้ใช้ของคุณคาดว่าจะเกิดความขัดข้องหรือระบบออฟไลน์อย่างสมบูรณ์จนถึงระยะเวลาตามแผน) - ไม่มีอะไรที่คุณทำได้ เกี่ยวกับสิ่งนี้ได้อย่างง่ายดาย1 .

การดำเนินการบางอย่างเก็บล็อกการเขียนเท่านั้นดังนั้นแอปพลิเคชันของคุณสามารถให้บริการตามคำขอที่อ่านเฉพาะวัตถุที่ได้รับผล

เอกสารประกอบนั้นค่อนข้างดีในการระบุว่าการล็อคใดที่มีแนวโน้มที่จะถูกจัดการโดยการดำเนินการ DDL

รายการบล็อกนี้มีบทสรุปที่แนะนำให้เพิ่มคอลัมน์สามารถเป็นการดำเนินการออนไลน์หากคอลัมน์นั้นเป็นโมฆะและไม่มีค่าเริ่มต้นหรือข้อ จำกัด ที่ไม่ซ้ำกันถึงแม้ว่านั่นหมายความว่าคำสั่งที่คุณควรเรียกใช้โดยไม่ล็อค (เช่น IIRC postgres ค่าเริ่มต้นคอลัมน์เป็น NULLable เว้นแต่คุณจะระบุไว้อย่างชัดเจน) คุณเรียกใช้การดำเนินการอื่นหลังจากคอลัมน์เพิ่มหรือไม่ บางทีการสร้างดัชนีตาม (ซึ่งจะใช้ล็อคการเขียนบนตารางโดยค่าเริ่มต้น)?

1 ข้อตกลงการจำลองแบบ / การทำคลัสเตอร์ / การมิเรอร์บางอย่างจะช่วยให้คุณอัปเดตมิเรอร์ (หยุดการอัปเดตชั่วคราวระหว่างการเปลี่ยนแปลงและเล่นซ้ำหลังจากนั้น) สลับไปที่การใช้สำเนานั้นเป็นแบบสดและต่อ ๆ ไป การหยุดทำงานจะถูก จำกัด ด้วยเวลาที่ใช้ในการเล่นซ้ำการเปลี่ยนแปลงที่เกิดขึ้นระหว่างการดำเนินการ DDL การดำเนินการเช่นนี้ไม่ได้มีความเสี่ยงดังนั้นถ้าคุณไม่สามารถแนะนำให้คุณจัดการหน้าต่างการบำรุงรักษาที่เหมาะสมเพื่อดำเนินการและตรวจสอบการปรับปรุงโครงสร้าง


35

คำสั่งที่คุณต้องการเรียกใช้จะล็อคการเข้าถึงแบบเอกสิทธิ์เฉพาะบุคคลบนตารางเพื่อป้องกันการเข้าถึงตารางอื่น ๆ ทั้งหมด แต่ระยะเวลาของการล็อกนี้ควรเป็นเพียงไม่กี่มิลลิวินาทีเนื่องจากการเพิ่มคอลัมน์เช่นที่คุณต้องการเพิ่มนั้นไม่ต้องการให้ตารางเขียนซ้ำอีกครั้งเพียงแค่ต้องมีการอัปเดตเมทาดาทา

ปัญหาสามารถเข้ามาได้ที่ไหนและฉันพนันว่าคุณดอลลาร์เพื่อโดนัทว่าเป็นปัญหาที่คุณเห็นอยู่ในลำดับความสำคัญของการล็อค บางคนมีการล็อคที่อ่อนแอเช่นการล็อคการเข้าถึงหุ้นบนตารางนั้นและพวกเขากำลังตั้งแคมป์ไว้อย่างไม่มีกำหนด (อาจเป็นการเชื่อมต่อที่ไม่ทำงานในธุรกรรมที่รั่วไหลออกไปหรือไม่คนที่เปิด psql เริ่มสืบค้นในโหมดอ่านซ้ำ แล้วก็ไปเที่ยวพักผ่อน)

คอลัมน์เพิ่มพยายามใช้การเข้าถึงพิเศษที่ต้องการและเข้าคิวอยู่ด้านหลังล็อคแรก

ตอนนี้การร้องขอการล็อคในอนาคตทั้งหมดอยู่ในคิวหลังคำขอ ACCESS EXCLUSIVE ที่รออยู่

ตามหลักการแล้วคำขอล็อกขาเข้าที่เข้ากันได้กับการล็อกที่อนุญาตแล้วสามารถข้ามผ่านการรอการเข้าถึงพิเศษและได้รับการอนุญาต แต่นั่นไม่ใช่วิธี PostgreSQL

คุณจำเป็นต้องค้นหากระบวนการที่ถือล็อคอ่อนแอที่มีอายุยืน

คุณสามารถทำได้โดยการสอบถามตาราง pg_locks

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

หากคุณทำสิ่งนี้ในขณะที่ทุกอย่างถูกล็อกคุณควรได้รับคำตอบเดียวเท่านั้น (เว้นแต่จะมีผู้ร้ายหลายคน) หากคุณทำสิ่งนี้หลังจากที่คุณฆ่า ADD COLUMN แล้วคุณอาจเห็นการล็อกที่อนุญาตจำนวนมาก แต่ถ้าคุณทำซ้ำสองสามครั้งควรมีหนึ่งหรือไม่กี่ที่อยู่รอบ ๆ

จากนั้นคุณสามารถนำ PID ที่คุณได้รับจาก pg_lock และสอบถามกับสิ่งนั้นใน pg_stat_activity เพื่อดูว่าผู้กระทำผิดกำลังทำอะไร:

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;

ดังนั้นจึงเรียกใช้แบบสอบถามภายในธุรกรรมและจากนั้นไม่ได้ใช้งานโดยไม่ต้องปิดธุรกรรม ตอนนี้เป็น 13:13 ดังนั้นพวกเขาจึงไม่ได้ใช้งานเป็นเวลา 5 นาที


6
คำตอบนี้ช่วยชีวิตฉันไว้
ดรา

1
ฉันช่วยด้วยส่วนlock prioritiesที่ดีมากทำให้ฉันยังไม่ได้อ่านในที่อื่นขอบคุณ!
Edson Horacio Junior
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.