การสำรองฐานข้อมูล MySQL ผ่านทาง ZFS snapshot


12

ฉันพบเว็บไซต์จำนวนหนึ่งที่พูดถึงเรื่องนี้ แต่ฉันก็ยังขาดรายละเอียดที่สำคัญบางประการ ขั้นตอนทั่วไปคือ

  • วิ่ง FLUSH TABLES WITH READ LOCK
  • ใช้สแน็ปช็อต ZFS
  • วิ่ง UNLOCK TABLES

แหล่งต่าง ๆ รายงานว่า InnoDB FLUSHซึ่งผมใช้ไม่ได้จริงเกียรติ คู่มือผู้ใช้ MySQL บันทึกว่ามีFLUSH TABLES...FOR EXPORTตัวแปรสำหรับใช้กับ InnoDB แต่ต้องระบุแต่ละตารางแยกต่างหากแทนที่จะสำรองฐานข้อมูลทั้งหมด ฉันต้องการหลีกเลี่ยงการระบุแต่ละตารางเป็นรายบุคคลเนื่องจากมีโอกาสดีที่รายการของตารางจะไม่ซิงค์กับตารางที่มีอยู่จริง

ปัญหาอื่น ๆ mysql -h"$HOST" -u"$USERNAME" -p"$PASSWORD" --execute="FLUSH TABLES WITH READ LOCK"ที่ผมมีคือผมวางแผนที่จะทำสิ่งที่ชอบ อย่างไรก็ตามการทำเช่นนี้จะปลดล็อกทันทีหลังจากออกจากเซสชัน มันสมเหตุสมผล แต่ก็ค่อนข้างน่ารำคาญเพราะฉันต้องกดปุ่มล็อกการอ่านเมื่อฉันถ่ายรูป

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


เหตุใดจึงมีรายการตารางคงที่ คุณสามารถสร้างรายการแบบไดนามิกที่รันไทม์
EEAA

1
ฐานข้อมูลบน VM หรือบนโลหะเปลือยหรือไม่ ที่เก็บข้อมูลอยู่ในเครื่องเดียวกันหรือไม่?
Michael Hampton

EEAA ยุติธรรมเพียงพอ
Andy Shulman

Michael ฐานข้อมูลและกล่อง ZFS เป็นเครื่องที่แตกต่างกัน แต่ไม่มีการจำลองเสมือน
Andy Shulman

@ AndyShulman ฉันคิดว่าคุณควรอธิบายเลย์เอาท์ให้ดีขึ้นหน่อย มันไม่สมเหตุสมผล
ewwhite

คำตอบ:


4

หากคุณใช้ InnoDB สำหรับตารางทั้งหมดและตั้งค่าinnodb_flush_log_at_trx_commitเป็น:

  • 1 (เนื้อหาของบัฟเฟอร์การบันทึก InnoDB จะถูกเขียนลงในไฟล์บันทึกของแต่ละการกระทำที่ทำรายการและไฟล์บันทึกนั้นจะถูกฟลัชไปที่ดิสก์) หรือ
  • 2 (เนื้อหาของบัฟเฟอร์การบันทึก InnoDB จะถูกเขียนไปยังล็อกไฟล์หลังจากการทำธุรกรรมแต่ละครั้งและไฟล์บันทึกถูกฟลัชลงดิสก์ประมาณหนึ่งครั้งต่อวินาที)

จากนั้นคุณไม่จำเป็นต้องใช้แท็บเล็ตฟลัชก่อนทำการสแน็ปช็อตเพียงแค่รัน ZFS สแน็ปช็อตโดยตรง InnoDB สามารถกู้คืนข้อมูลจากบันทึกการทำธุรกรรมโดยไม่ทำให้ข้อมูลสูญหาย

Ref: https://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit


ด้วยพจนานุกรมข้อมูลที่นำมาใช้ใน MySQL 8 แม้การดำเนินงาน DDL (การปรับเปลี่ยนสคีมา) ก็กลายเป็นอะตอม ก่อนหน้านั้นการดำเนินงาน DDL ระหว่างสแนปชอตของระบบไฟล์อาจให้ผลลัพธ์ที่แน่นอน (เช่นเสียหาย)
bernie

13

คุณต้องล็อคฐานข้อมูลเต็มรูปแบบเพื่อสำรองฐานข้อมูล (ส่วนใหญ่) อย่างสม่ำเสมอ

คู่มือhttps://dev.mysql.com/doc/refman/5.5/en/backup-methods.htmlพูดว่าตารางการล้างด้วย READ LOCKนั้นถูกต้องสำหรับสแน็ปช็อต ZFS โดยเฉพาะ

การสำรองข้อมูลโดยใช้ระบบไฟล์ภาพรวม

หากคุณใช้ระบบไฟล์ Veritas คุณสามารถสำรองข้อมูลดังนี้

  1. FLUSH TABLES WITH READ LOCKจากโปรแกรมไคลเอนต์รัน
  2. จากเชลล์อื่นให้เรียกใช้ mount vxfssnapshot
  3. UNLOCK TABLESจากลูกค้ารายแรกของรัน
  4. คัดลอกไฟล์จากภาพรวม
  5. unmount สแน็ปช็อต

ความสามารถในการจับภาพที่คล้ายกันอาจมีอยู่ในระบบไฟล์อื่นเช่น LVM หรือ ZFS

มันไร้สาระที่พวกเขาละทิ้งความจริงที่คุณต้องการFLUSH TABLES table_a, table_b, table_c FOR EXPORTสำหรับInnoDBจากคำแนะนำเหล่านี้ นอกจากนี้ยังโง่ที่จะต้องระบุแต่ละตารางเช่นนั้น แต่อย่างที่ EEAA บอกไว้คุณสามารถสร้างรายการตารางในขณะที่คุณเริ่มการสำรองข้อมูลได้อย่างง่ายดาย

สำหรับการล็อคคุณต้องเปิดใช้งานการเชื่อมต่อฐานข้อมูลในขณะที่ทำสแนปชอต

โดยทั่วไปฉันจะใช้ภาษา Perl หรือภาษาการเขียนโปรแกรมอื่นที่สามารถเชื่อมต่อล็อคฐานข้อมูลและในขณะที่รักษาการเชื่อมต่อฐานข้อมูลให้ถ่ายภาพจากนั้นปลดล็อคและปลดการเชื่อมต่อ มันไม่ซับซ้อน ฉันพนันได้เลยว่ามีเครื่องมือออกมาทำสิ่งนี้อยู่แล้ว แต่การเขียนมันง่าย

ฉันพูดง่ายไม่ซับซ้อน ฯลฯ ไม่กี่ครั้ง ฉันสมมติว่าคุณมีโปรแกรมพื้นฐานหรือทักษะการเขียนสคริปต์ที่ดี


ฉันหวังว่าจะเก็บสคริปต์ง่าย ๆ ไว้ใน Bash แต่คุณก็สามารถเปลี่ยนภาษาได้ทำให้เรื่องนี้ง่ายขึ้นมาก ฉันอาจจะอ่านคำตอบของคุณผิด แต่ดูเหมือนคุณกำลังบอกว่าฉันต้องดำเนินการทั้งสองอย่างFLUSH TABLES WITH READ LOCKแล้วFLUSH TABLES...FOR EXPORTในขณะที่การอ่านคู่มือ MySQL ของฉันบอกว่าควรจะมีเพียงสิ่งเดียวที่จำเป็น
Andy Shulman

ขอโทษฉันไม่ชัดเจน ฉันแค่ไปตามคู่มือและมันบอกว่าสองสิ่งที่แตกต่างกัน ฉันเดาว่าคุณถูกต้องและต้องการในภายหลังเท่านั้น แต่ตารางทั้งหมดควรถูกล็อคในคำสั่งเดียว
Ryan Babchishin

1
ระบุว่าเอกสารไม่ชัดเจนฐานข้อมูลทั้งหมดจะต้องถูกล็อคและการเชื่อมต่อฐานข้อมูลจะต้องได้รับการบำรุงรักษาในขณะที่มีการถ่ายภาพสแน็ปช็อตดูเหมือนง่ายกว่าที่จะปิดฐานข้อมูลลงสำรองและรีสตาร์ท มัน.
Andrew Henle

2
@andrew ถอนหายใจ ... ฉันเข้าใจ แต่นั่นจะช้าทำให้การเชื่อมต่อหล่น / ล้มเหลวและฉันได้เห็นมันทำให้ฐานข้อมูลล้มเหลวในการกลับมาอย่างถูกต้อง (ไม่ดีสำหรับระบบอัตโนมัติ) จะเป็นการดีหากได้รับคำตอบที่ชัดเจนจาก mysql / Oracle พวกเขาจะต้องมีรายชื่อผู้รับจดหมาย
Ryan Babchishin

7

ผมเคยโดนตัดและปรับสคริปต์ง่ายแนวคิดในทุบตีซึ่งผมพบว่าในอีกเซิร์ฟเวอร์ผิดพลาดโพสต์โดยTobia คุณควรได้รับประมาณ 90% ของที่นั่น

mysql_locked=/var/run/mysql_locked

# flush & lock MySQL, touch mysql_locked, and wait until it is removed
mysql -hhost -uuser -ppassword -NB <<-EOF &
    flush tables with read lock;
    delimiter ;;
    system touch $mysql_locked
    system while test -e $mysql_locked; do sleep 1; done
    exit
EOF

# wait for the preceding command to touch mysql_locked
while ! test -e $mysql_locked; do sleep 1; done

# take a snapshot of the filesystem, while MySQL is being held locked
zfs snapshot zpool/$dataset@$(date +"%Y-%m-%d_%H:%M")

# unlock MySQL
rm -f $mysql_locked

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

ไฟล์ที่ชี้ไปตาม$mysql_lockedจำเป็นต้องสามารถเข้าถึงได้โดยเครื่องทั้งสองซึ่งคุณควรจะทำได้ง่ายพอเพราะทั้งคู่สามารถเข้าถึงชุดข้อมูลทั่วไป (แม้ว่าพวกเขาอาจใช้เส้นทางที่แตกต่างกันและคุณควรคำนึงถึงเรื่องนี้)


ฉันไม่รู้จักการเขียนสคริปต์ MySQL ดังนั้นนี่อาจเป็นความคิดที่งี่เง่า แต่คุณไม่สามารถทำได้system zfs snapshot...ในสคริปต์หลักใช่ไหม snap-shotting หรือต้องทำงานในกระบวนการที่แยกจากกัน?
TripeHound

@ Tripehound ทั้งสองอย่างต้องเกิดขึ้นพร้อมกันในทางใดทางหนึ่ง
Ryan Babchishin

@ RyanBabchishin ฉันคิดว่าเขาพูดถูก SYSTEMคำสั่งทำงานสิ่งที่ท้องถิ่น ถ้าฉันเรียกใช้ไคลเอนต์ mysql บนกล่อง FreeBSD และดำเนินการLOCK; SYSTEM zfs snapshot; UNLOCKดูเหมือนว่ามันจะทำงาน
Andy Shulman

@ Andy ฉันแค่บอกว่าพวกเขาต้องเกิดขึ้นพร้อมกัน ไม่สำคัญว่าคุณจะไปอย่างไร
Ryan Babchishin

2

คุณต้องล้างตารางด้วย READ LOCK สำหรับ myisam เพราะมันไม่ได้ถูกบันทึกไว้

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

หากคุณต้องการความสอดคล้องระดับแอปพลิเคชันของคุณควรใช้ธุรกรรม หากแอปพลิเคชันของคุณใช้ธุรกรรมและ innodb สแน็ปช็อตใด ๆ จะสอดคล้องกันโดยถามถึงระดับแอปพลิเคชันโดยอัตโนมัติ


2

นี่คือโซลูชันของฉันวิธีสร้างสแน็ปช็อต ZFS ขณะที่ยังล็อกอยู่:

mysql << EOF
    FLUSH TABLES WITH READ LOCK;
    system zfs snapshot data/db@snapname
    UNLOCK TABLES;
EOF
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.