Mencadangkan database MySQL melalui snapshot ZFS

12

Saya telah menemukan sejumlah situs berbicara tentang melakukan hal ini, tetapi saya kehilangan beberapa detail penting. Langkah umumnya adalah

  • Lari FLUSH TABLES WITH READ LOCK
  • Ambil snapshot ZFS
  • Lari UNLOCK TABLES

Berbagai sumber melaporkan bahwa InnoDB, yang saya gunakan, sebenarnya tidak menghormati a FLUSH. Catatan pengguna pengguna MySQL ada FLUSH TABLES...FOR EXPORTvarian untuk digunakan dengan InnoDB, tetapi itu membutuhkan menentukan setiap tabel secara individual, daripada mencadangkan seluruh database. Saya lebih suka menghindari menentukan setiap tabel secara individual karena ada kemungkinan daftar tabel akan menjadi tidak sinkron dengan tabel yang sebenarnya ada.

Masalah lain yang saya miliki adalah saya berencana untuk melakukan sesuatu seperti mysql -h"$HOST" -u"$USERNAME" -p"$PASSWORD" --execute="FLUSH TABLES WITH READ LOCK". Namun, ini langsung mengunci setelah sesi keluar. Ini masuk akal, tetapi juga cukup menjengkelkan karena saya perlu memegang kunci baca ketika saya mengambil foto saya.

Gagasan saya yang lain adalah mengambil cadangan panas menggunakan alat seperti Percona XtraBackup dan mengambil snapshot cadangan, tetapi saya lebih suka tidak membayar biaya untuk menulis semua data saya ke lokasi kedua hanya untuk memotretnya.

Andy Shulman
sumber
Mengapa daftar tabel statis? Anda pasti dapat membuat daftar secara dinamis saat runtime.
EEAA
1
Apakah basis data pada VM atau pada bare metal? Apakah penyimpanan bahkan di mesin yang sama?
Michael Hampton
EEAA, cukup adil.
Andy Shulman
Michael, basis data dan kotak ZFS adalah mesin yang berbeda, tetapi tidak ada yang tervirtualisasi.
Andy Shulman
@AndyShulman Saya pikir Anda harus menjelaskan tata letaknya sedikit lebih baik. Ini tidak masuk akal.
ewwhite

Jawaban:

4

Jika Anda hanya menggunakan InnoDB untuk semua tabel dan set innodb_flush_log_at_trx_commitke:

  • 1 (isi buffer log InnoDB ditulis ke file log pada setiap transaksi komit dan file log disiram ke disk) atau,
  • 2 (isi dari buffer log InnoDB ditulis ke file log setelah setiap transaksi komit dan file log dibilas ke disk kira-kira sekali per detik),

maka Anda tidak perlu FLUSH TABLES sebelum melakukan snapshot, cukup jalankan snapshot ZFS secara langsung. InnoDB dapat memulihkan data dari log komit transaksi tanpa kehilangan data.

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

Gea-Suan Lin
sumber
Dengan kamus data yang diperkenalkan di MySQL 8, bahkan operasi DDL (skema modifikasi) sekarang menjadi atom. Sebelum itu, operasi DDL selama snapshot sistem file dapat memberikan hasil yang sebagian berkomitmen (mis. Rusak).
bernie
13

Anda memerlukan kunci basis data lengkap untuk membuat cadangan (sebagian besar) database secara konsisten.

Manual https://dev.mysql.com/doc/refman/5.5/en/backup-methods.html mengatakan FLUSH TABLES WITH READ LOCK benar untuk snapshot ZFS secara khusus.

Membuat Cadangan Menggunakan Snapshot Sistem File

Jika Anda menggunakan sistem file Veritas, Anda dapat membuat cadangan seperti ini:

  1. Dari program klien, jalankan FLUSH TABLES WITH READ LOCK.
  2. Dari shell lain, jalankan mount vxfssnapshot.
  3. Dari klien pertama, jalankan UNLOCK TABLES.
  4. Salin file dari snapshot.
  5. Lepaskan snapshot.

Kemampuan snapshot serupa mungkin tersedia di sistem file lain, seperti LVM atau ZFS.

Ini adalah jenis konyol bahwa mereka ditinggalkan fakta bahwa Anda perlu FLUSH TABLES table_a, table_b, table_c FOR EXPORTuntuk InnoDB dari petunjuk ini. Ini juga bodoh untuk menentukan setiap tabel seperti itu. Tetapi seperti yang dikatakan EEAA, Anda dapat membuat daftar tabel saat Anda memulai pencadangan dengan cukup mudah.

Sedangkan untuk memegang kunci, Anda harus menjaga koneksi db aktif saat melakukan snapshot

Secara umum saya akan menggunakan sesuatu seperti Perl atau bahasa pemrograman lain yang dapat terhubung, mengunci db dan sambil mempertahankan koneksi db mengambil snapshot, lalu membuka kunci dan memutuskan sambungan. Itu tidak rumit. Saya bertaruh bahwa ada alat di luar sana yang sudah melakukan ini tetapi menulis satu itu mudah.

Saya katakan mudah, tidak kompleks, dll. Beberapa kali. Saya berasumsi Anda memiliki beberapa pemrograman dasar atau keterampilan menulis yang baik.

Ryan Babchishin
sumber
Saya berharap untuk menyimpan skrip konseptual yang begitu sederhana di Bash, tetapi Anda benar-benar beralih bahasa membuatnya lebih mudah. Saya mungkin salah membaca jawaban Anda, tetapi sepertinya Anda mengatakan saya perlu melakukan keduanya FLUSH TABLES WITH READ LOCKdan kemudian FLUSH TABLES...FOR EXPORT, sedangkan bacaan saya tentang manual MySQL mengatakan hanya perlu satu.
Andy Shulman
Maaf saya tidak jelas. Saya hanya pergi dengan manual dan mengatakan dua hal yang berbeda. Saya kira Anda benar dan hanya perlu nanti. Tetapi semua tabel harus dikunci dalam satu perintah.
Ryan Babchishin
1
Mengingat bahwa dokumentasi tidak terlalu jelas, seluruh basis data perlu dikunci, dan bahwa koneksi DB harus dipertahankan saat snapshot diambil, sepertinya lebih mudah untuk hanya mematikan DB, mendukungnya, dan memulai kembali Itu.
Andrew Henle
2
@ andrew mendesah ... saya mengerti. Tapi itu akan lambat, menyebabkan koneksi drop / gagal dan saya telah melihatnya menyebabkan database gagal kembali dengan benar (buruk untuk otomatisasi). Akan lebih baik untuk mendapatkan jawaban yang pasti dari mysql / Oracle. Mereka harus memiliki milis.
Ryan Babchishin
7

Saya telah merobek dan mengadaptasi skrip konseptual sederhana di Bash yang saya temukan di pos Server Fault lain oleh Tobia . Ini akan membuat Anda sekitar 90% dari perjalanan ke sana.

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

Di sini, mysqlperintah yang Anda gunakan dijalankan di latar belakang dan menyentuh file. Itu menunggu di latar belakang untuk file menghilang sebelum keluar dan dengan demikian membuka kunci tabel. Sementara itu skrip utama menunggu hingga file ada, kemudian membuat snapshot dan menghapus file.

File yang ditunjuk oleh $mysql_lockedharus dapat diakses oleh kedua mesin, yang Anda harus dapat melakukannya dengan cukup mudah karena mereka berdua dapat mengakses dataset umum (meskipun mereka mungkin menggunakan jalur yang berbeda, dan Anda harus memperhitungkan ini).

Michael Hampton
sumber
Saya tidak tahu skrip MySQL, jadi ini mungkin ide yang konyol, tetapi tidak bisakah Anda melakukannya system zfs snapshot...di dalam skrip utama? Atau apakah snap-shotting harus dijalankan dalam proses terpisah?
TripeHound
@ Tripehound, keduanya harus terjadi secara paralel
Ryan Babchishin
@RyanBabchishin, saya pikir dia benar. The SYSTEMperintah menjalankan hal-hal secara lokal. Jika saya menjalankan klien mysql pada kotak FreeBSD dan mengeksekusi LOCK; SYSTEM zfs snapshot; UNLOCK, sepertinya itu akan berhasil.
Andy Shulman
@Andy Saya baru saja mengatakan mereka harus terjadi secara paralel. Tidak masalah bagaimana Anda melakukannya.
Ryan Babchishin
2

Anda memerlukan FLUSH TABLES DENGAN READ LOCK untuk myisam karena itu tidak menjurnal.

Anda tidak benar-benar membutuhkan apa pun untuk innodb sama sekali, IMO, karena itu penjurnalan. Ini akan tetap konsisten, hanya memutar kembali jurnal secara otomatis jika ada sesuatu yang terjadi pada saat Anda mengambil snapshot atom.

Jika Anda ingin konsistensi tingkat aplikasi, aplikasi Anda harus menggunakan transaksi. Jika aplikasi Anda menggunakan transaksi dan innodb, snapshot apa pun akan konsisten menanyakan cara naik ke level aplikasi secara otomatis.

Jim Salter
sumber
2

Ini adalah solusi saya cara membuat snapshot ZFS sambil menjaga kunci:

mysql << EOF
    FLUSH TABLES WITH READ LOCK;
    system zfs snapshot data/db@snapname
    UNLOCK TABLES;
EOF
Petr Stastny
sumber