แก้ไขตารางในฐานข้อมูลที่ใช้งานจริง


24

ระบบฐานข้อมูล "ยอดนิยม" (MySQL, Postgres ... ) ส่วนใหญ่จะจัดการกับการเปลี่ยนแปลงตารางบนฐานข้อมูลการผลิตจริง (เช่นการเพิ่มการลบหรือการเปลี่ยนประเภทของโคลลัส) ได้อย่างไร

ฉันรู้ว่าวิธีที่ถูกต้องคือการสำรองข้อมูลทุกอย่างกำหนดเวลาหยุดทำงานและทำการเปลี่ยนแปลง

แต่ ... ระบบฐานข้อมูลปัจจุบันสนับสนุนการทำสิ่งเหล่านี้ "ออนไลน์" โดยไม่หยุดอะไรหรือไม่? (อาจเป็นเพียงการชะลอการสืบค้นที่อ้างอิงคอลัมน์ที่เพิ่งมีการเปลี่ยนแปลง / ลบ)

และจะเกิดอะไรขึ้นเมื่อฉันเพิ่งALTER TABLE...สร้างฐานข้อมูลที่ทำงานอยู่ ทุกอย่างหยุดลงเมื่อสิ่งนี้เกิดขึ้นหรือไม่? ข้อมูลเสียหายหรือไม่ เป็นต้น

อีกครั้งฉันส่วนใหญ่หมายถึง Postgres หรือ MySQL เป็นสิ่งที่ฉันพบ

(และใช่ทุกครั้งที่ฉันต้องทำสิ่งนี้ก่อนที่ฉันจะทำ "วิธีการที่ถูกต้อง" สำรองสิ่งต่างๆจัดตารางเวลาดาวน์ไทน์ ฯลฯ ... แต่ฉันแค่อยากรู้ว่ามันเป็นไปได้ไหมที่จะทำสิ่งนี้ " สกปรก "หรือหากมีระบบฐานข้อมูลใด ๆ ที่รองรับการเปลี่ยนแปลงสคีมา" แบบเร็ว, สดและสกปรก ")


มีคนแนะนำOnline Schema Change สำหรับ MySQL จากสคริปต์ Facebook (โดยมีบทช่วยสอนที่นี่และแหล่งที่มาที่นี่ ) ... ดูเหมือนจะเป็นวิธีที่ดีในการทำให้ชุดของ "แฮ็ค" เป็นแบบอัตโนมัติ ... มีใครเคยใช้มา การผลิตคล้ายกับอะไร?


3
หมายเหตุ: การระบุ "วิธีที่ถูกต้อง" นั้นสัมพันธ์กับ MySQL ไม่ใช่ PostgreSQL "วิธีที่ถูกต้อง" ใน PostgreSQL นั้นง่ายมากแม้ว่ามันจะสามารถมีส่วนร่วมได้ การใช้pg_reorgสามารถช่วยในสถานการณ์ที่ยากขึ้น
ฌอน

ฉันชอบที่จะมีวิดีโอที่มีรายละเอียดเกี่ยวกับเรื่องนี้โดยมีคนอธิบายกลยุทธ์ให้ได้มากที่สุด
Sandeepan Nath

คำตอบ:


22

เมื่อคุณออกALTER TABLEใน PostgreSQL มันจะใช้ACCESS EXCLUSIVESELECTล็อคที่บล็อกทุกอย่างรวมทั้ง อย่างไรก็ตามการล็อคนี้สามารถค่อนข้างสั้นถ้าตารางที่ไม่ต้องใช้อีกครั้งเขียนไม่ใหม่UNIQUE, CHECKหรือFOREIGN KEYข้อ จำกัด จำเป็นต้องมีราคาแพงสแกนเต็มรูปแบบตารางการตรวจสอบ ฯลฯ

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

การดำเนินการช้าตามปกติบางอย่างสามารถเร่งความเร็วให้ปลอดภัยโดยไม่ต้องหยุดทำงาน ตัวอย่างเช่นหากคุณมีตารางtและคุณต้องการเปลี่ยนคอลัมน์customercode integer NOT NULLเป็นtextเพราะลูกค้าได้ตัดสินใจรหัสลูกค้าทั้งหมดจะต้องเริ่มต้นด้วยการXคุณสามารถเขียน:

ALTER TABLE t ALTER COLUMN customercode TYPE text USING ( 'X'||customercode::text );

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

ALTER TABLE t ADD COLUMN customercode_new text;
BEGIN;
LOCK TABLE t IN EXCLUSIVE MODE;
UPDATE t SET customercode_new = 'X'||customercode::text;
ALTER TABLE t DROP COLUMN customercode;
ALTER TABLE t RENAME COLUMN customercode_new TO customercode;
COMMIT;

นี้จะป้องกันไม่ให้เขียนไปtในระหว่างกระบวนการ; ชื่อล็อคEXCLUSIVEค่อนข้างหลอกลวงซึ่งยกเว้นทุกอย่างยกเว้นSELECT ; ACCESS EXCLUSIVEโหมดเป็นเพียงคนเดียวที่ไม่รวมอย่าง everyting ดูโหมดล็อค มีความเสี่ยงที่การดำเนินการนี้อาจทำให้เกิดการหยุดชะงักเนื่องจากการอัพเกรดล็อคที่จำเป็นALTER TABLEแต่สิ่งที่แย่ที่สุดคือคุณต้องทำอีกครั้ง

คุณยังสามารถหลีกเลี่ยงการล็อคที่และทำสิ่งที่ทั้งสดโดยการสร้างฟังก์ชั่นทริกเกอร์บนtว่าเมื่อใดก็ตามที่INSERTหรือUPDATEมาในโดยอัตโนมัติจากcustomercode_newcustomercode

นอกจากนี้ยังมีเครื่องมือในตัวเช่นกันCREATE INDEX CONCURRENTLYและALTER TABLE ... ADD table_constraint_using_indexได้รับการออกแบบมาเพื่อให้ DBAs สามารถลดระยะเวลาการล็อคแบบเอกสิทธิ์โดยการทำงานช้าลงในลักษณะที่เป็นมิตรกับการทำงานพร้อมกัน

pg_reorgเครื่องมือหรือทายาทpg_repackสามารถนำมาใช้สำหรับตารางการปรับโครงสร้างการดำเนินงานบางส่วนเช่นกัน


1
สิ่งสำคัญในสิ่งที่ @Craig กล่าวคือ "ถ้าไม่ต้องการการเขียนซ้ำ" การใช้เป็นการALTER TABLE t ADD COLUMN i INTดำเนินการที่รวดเร็ว (โดยทั่วไป <1ms) เมื่อได้รับการล็อค การรับล็อคสามารถจัดคิวการเชื่อมต่อได้ดังนั้นจึงไม่ "ฟรี" ... แม้ว่ามันจะดีกว่าสิ่งที่คุณต้องทำใน MySQL การเพิ่มNOT NULLข้อ จำกัด นั้นยากกว่าและไม่เหมาะกับการเสแสร้งของหัวใจ
ฌอน

มันน่าจะเป็นความเห็นเป็นเอกฉันท์ว่าเป็นผู้สืบทอดที่ดีขึ้นของpg_repack pg_reorg
Erwin Brandstetter

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

7

Percona มาพร้อมกับเครื่องมือของตัวเองสำหรับดำเนินการเปลี่ยนแปลงสคีมาออนไลน์

เครื่องมือนี้เรียกว่าpt-online-schema-change

มันเกี่ยวข้องกับทริกเกอร์ดังนั้นโปรดอ่านเอกสารอย่างละเอียด

ตามเอกสารประกอบการดำเนินการที่สำคัญคือ

  • ตรวจสติ
  • chunking
  • การเปลี่ยนแปลงสคีมาออนไลน์
    • สร้างและแก้ไขตารางชั่วคราว
    • จับการเปลี่ยนแปลงจากตารางไปยังตารางชั่วคราว
    • คัดลอกแถวจากตารางไปยังตารางชั่วคราว
    • ซิงโครไนซ์ตารางและตารางชั่วคราว
    • สลับ / เปลี่ยนชื่อตารางและตารางชั่วคราว
    • ทำความสะอาด

ขอบคุณดูเหมือนว่าเป็นแนวทางของ Facebook ที่ "ขายแล้ว" ซึ่งฉันเชื่อใจได้มากกว่า ...
NeuronQ

pt-online-schema-change เป็นวิธีที่เหมาะสมที่สุดหากคุณใช้เซิร์ฟเวอร์ MySQL ของคุณเอง ในฐานะที่เป็นเครื่องมือ Percona 2.2 (น่าเศร้า) พวกเขาไม่สนับสนุน RDS / Aurora บน AWS pt-online-schema-change แทรกทริกเกอร์บนตารางต้นทางเพื่อคัดลอกแถว (ลำดับความสำคัญต่ำสำหรับ MyISAM) ไปยัง table_temp ปลายทางและทำการล็อคแบบหล่นอย่างรวดเร็วเพียงครั้งเดียวและเปลี่ยนชื่อที่ท้ายเมื่อแถวทั้งหมดซิงค์กันระหว่างต้นทางและปลายทาง ตาราง
phpguru

6

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

ในฐานะนักพัฒนา Agile บางครั้งฉันจำเป็นต้องปรับโครงสร้างตารางใหม่โดยไม่ต้องหยุดทำงานเนื่องจากมีการแก้ไขและอ่านจากตารางเหล่านั้น

วิธีการต่อไปนี้มีความเสี่ยงต่ำเนื่องจากการเปลี่ยนแปลงนั้นทำในหลายขั้นตอนที่มีความเสี่ยงต่ำซึ่งง่ายต่อการย้อนกลับ:

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

เราใช้วิธีนี้หลายครั้งในการเปลี่ยนตารางการผลิตสดขนาดใหญ่โดยไม่ต้องหยุดทำงานโดยไม่มีปัญหาใด ๆ


3
ดี ... แต่ที่ว่าชนิดของ "ความเจ็บปวด" ที่ฉันกำลังมองหาเพื่อหลีกเลี่ยง :)
NeuronQ

@ NeuronQ " ไม่มีทางกลับง่าย " - มีอยู่ใน Postgres: เพียงแค่ใส่ทุกอย่างในการทำธุรกรรมและrollbackหากมีอะไรผิดพลาด
a_horse_with_no_name

2

ใช่ฐานข้อมูลที่ทันสมัยจำนวนมากจะช่วยให้คุณเพียงแค่เพิ่มคอลัมน์หรือเปลี่ยนลักษณะของคอลัมน์เช่นการเพิ่มหรือลบ nullable

หากคุณวางคอลัมน์ข้อมูลจะหายไป แต่ไม่มีความกลัวการทุจริตมากนัก


0

เครื่องมือ Percona ใช้ทริกเกอร์เพื่อช่วยในการปรับเปลี่ยนและจะไม่เล่นอย่างสวยงามหากตารางของคุณมีทริกเกอร์ที่มีอยู่แล้ว ฉันต้องเขียนสิ่งที่จัดการกับทริกเกอร์ที่มีอยู่ได้ดีเพราะมันสำคัญอย่างยิ่งต่อฐานข้อมูลของเราhttps://github.com/StirlingMarketingGroup/smg-live-alter


-1

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

ตัวอย่างของการดำเนินการเฉพาะสำหรับเซิร์ฟเวอร์ MSSQL อยู่ที่นี่: http://support.microsoft.com/kb/956176/en-us

ฉันจะสมมติว่า RMDB อื่นมีวิธีการที่คล้ายกันถึงแม้ว่าการใช้งานที่แน่นอนจะเป็นสิ่งที่คุณจะต้องตรวจสอบกับเอกสารของผู้ขาย


-1 นี่เป็นความผิดพลาดอย่างสมบูรณ์สำหรับ SQL Server: "ถ้าคุณเพิ่มคอลัมน์ใหม่อย่างน้อยใน MS SQL Server เอ็นจิ้นจะสร้างสำเนาชั่วคราวของตารางในขณะที่สร้างคำนิยามของตารางใหม่แล้วแทรกข้อมูลกลับ ในนั้น "
AK

@AlexKuznetsov - ฉันพบบรรทัดก่อนหน้ารวมถึงการเชื่อมโยงกับบางกรณีที่ระบุไว้ในรายการจะชี้แจงว่าสิ่งนี้ไม่ได้เกิดขึ้นเสมอไป ฉันแก้ไขประโยคเพื่อสะท้อนสิ่งนี้ดีขึ้น
SchmitzIT

1
คุณกำลังพูดถึงพฤติกรรมของ GUI, SSMS ไม่ใช่พฤติกรรมของ SQL Server เอง ตามลิงก์ของคุณคำแนะนำคือใช้ T-SQL โดยตรงเพื่อทำการเปลี่ยนแปลง DDL SSMS ไม่ใช่เครื่องมือที่ดีสำหรับการเปลี่ยน DDL
AK

@AlexKuznetsov - ฉันอ่านบทความว่ามีความเสี่ยงที่เกี่ยวข้อง แต่ไม่เป็นความท้อแท้ อย่างไรก็ตามฉันไม่ได้เชื่อมโยงบทความสำหรับบิต GUI แต่เป็นตัวบ่งชี้ถึงการดำเนินการบางอย่างที่นำไปสู่คำสั่ง ALTER ที่นำไปสู่การสร้างตารางชั่วคราวเนื่องจากการเปลี่ยนแปลงโครงสร้างข้อมูลพื้นฐาน ฉันยังไม่ได้ทดสอบว่าสิ่งเดียวกันนี้ใช้ได้กับการออกคำสั่งโดยตรงจาก T-SQL หรือไม่ แต่ฉันคิดว่ากระบวนการนี้ค่อนข้างคล้ายกันและเซิร์ฟเวอร์ SL นั้นทำงานในเบื้องหลัง
SchmitzIT

คุณสามารถเริ่ม Profiler, รันคำสั่ง ALTER TABLE โดยตรงและดูสิ่งที่เกิดขึ้น จากนั้นคุณสามารถเปลี่ยนตารางผ่านทางกล่องโต้ตอบและดูคำสั่งที่กำลังดำเนินการด้วยตัวคุณเอง
AK
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.