Adakah jalan keluar yang lebih baik dari log MySQL InnoDB “di masa depan”?

16

Saya mendapatkan kesalahan InnoDB ini di MySQL 5.0. Mysqld dihentikan dengan bersih, tetapi saya berhasil kehilangan ib_logfile0 & ib_logfile1 sesudahnya. Sekarang setelah startup yang bersih, InnoDB telah melakukan "crash recovery". Saya telah melalui bisnis innodb_force_recovery = 4, memperbaiki tabel MyISAM yang hang, dan sekarang replikasi siap untuk dijalankan, terlepas dari ini. Jumlah besar yang disetujui:

111116 15:49:36  InnoDB: Error: page 393457 log sequence number 111 561,760,232
InnoDB: is in the future! Current system log sequence number 70 3,946,969,851.
InnoDB: Your database may be corrupt or you may have copied the InnoDB
InnoDB: tablespace but not the InnoDB log files. See
InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html
InnoDB: for more information.

Ini ada di server slave. Kesalahan di atas memuntahkan ratusan. Saya menemukan jawaban ini: "masukkan dan hapus data senilai> 64 GB, sehingga nomor urut log menjadi cukup besar".

http://forums.mysql.com/read.php?22,50163,50163#msg-50163

Angka ajaib 64GB itu berasal dari 4GB * 16 di mana innodb orang itu mencatat "angka utama" yang diperlukan untuk meningkat dari 0 menjadi 15. Tambang berjalan dari 70 menjadi 111 = 164 GB. Ini akan memakan waktu 5 hari. Saya akan terus berupaya mempercepat skrip saya, dan menjalankannya secara paralel untuk mempercepat skrip ini. Sementara itu, saya berharap orang lain memiliki jawaban yang lebih baik. Ini konyol.

IcarusNM
sumber
Satu jawaban yang menjanjikan: "Jika itu adalah server slave, solusi terbaik adalah memindahkan database dan menginstal snapshot baru dari master." Sayangnya ada 20.000 tabel di 25 basis data, campuran MyISAM dan InnoDB, dalam produksi 24x7. Butuh waktu terlalu lama untuk menutup semua itu dan melakukan replikasi penuh baru sebelum memulai replikasi lagi.
IcarusNM
4
Saya sekarang memiliki mesin 8-core ini berlutut dalam perlombaan yang tidak berguna untuk membuat dan menghapus 164 pertunjukan data. Satu-satunya alternatif yang saya dengar adalah mem-nuke semua yang ada di slave ini dan memulai dari awal. Semua untuk secara efektif mengubah satu nomor dalam dua file. Tentunya ada beberapa insinyur InnoDB di luar sana dengan tip pro. Adakah yang pernah membuka ib_logfile0 di Emacs, menemukan angka ajaib dalam hex, dan baru saja mengubahnya?
IcarusNM
Inilah artikel yang bagus tentang beberapa cara untuk melakukannya. Percona jelas merupakan otoritas pada MySQL. percona.com/blog/2013/09/11/…
jbrahy

Jawaban:

10

Ini adalah situasi yang sangat langka. Saya berharap untuk tidak pernah berakhir di sana lagi, dengan InnoDB "nomor urut log di masa depan!" kesalahan. Karena detail khusus saya, membangun kembali / memulihkan data server saya adalah pilihan terakhir. Beberapa kecurangan dalam membantu itu adalah ide yang bagus, tetapi pada akhirnya, saya memutuskan untuk terus meningkatkan skrip Perl saya untuk memainkan permainan konyol ini dan melakukan sebanyak mungkin pertunjukan / jam. Apa-apaan, ini adalah tes stres sistem yang baik.

Ingat: tujuannya adalah untuk meningkatkan penghitung tunggal ("nomor urut log") yang disimpan di suatu tempat di header ib_logfile0 dan ib_logfile1 . Ini untuk memalsukan InnoDB sehingga akan mengabaikan waktu yang jelas dan melanjutkan hidup. Tapi tidak ada yang tahu cara mengedit nomor itu. Atau jika mereka tahu, tidak ada yang berbicara.

Ini produk akhir saya. YMMV, tetapi menggunakan fungsi REPEAT mysql untuk menghasilkan data secara internal sangat efisien.

 #!/usr/bin/perl
 use DBI;
 $table = shift || die;
 $dbh = DBI->connect("DBI:mysql:junk:host=localhost", "user", "pass"); #Edit "junk" (DB name), user, and pass to suit.
 $dbh->do("DROP TABLE IF EXISTS $table");
 $dbh->do("CREATE TABLE $table (str TEXT) ENGINE=INNODB");
 $sth = $dbh->prepare("INSERT INTO $table (str) VALUES (REPEAT(?,1000000))");
 foreach (1..50) {
    $sth->execute('0123456789');   # 10 MB
 }
 $dbh->do("DELETE FROM $table");

Resep yang saya sarankan:

  1. Buat database 'sampah'
  2. Simpan script perl di atas sebagai junk.pl .
  3. Run junk.pl data1 , dan junk.pl data2 , dan data3 junk.pl , dll sekaligus, untuk sebanyak core CPU sebagai server database Anda memiliki, untuk memulai. Buka beberapa kerang dan bungkus masing-masing berjalan di loop Bash: while true; do date; junk.pl dataX; done.

Lihat LSN Anda tumbuh, mungkin di loop lain:

 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 124 3871092821
 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 124 4209892586
 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 125 85212387

Jumlah besar adalah 32-bit INT unsigned yang akan membungkus di 4GB, meningkatkan lebih kecil jumlah setiap kali. Dalam kasus di atas, itu baru saja bergulir dari 124 menjadi 125. Tujuan Anda tersembunyi di mysqld.log yang mengirimi Anda Google untuk solusi konyol ini sejak awal. Setelah Anda melewati garis finish, itu saja! Tiuplah klakson! Lepaskan confetti!

Bilah Samping: Ini menemukan bug yang menarik di mysqld 5.0 w / REPEAT: jika Anda pergi ke 20 MB, itu membalik beberapa penghitung internal dan berguling ke ~ 96 KB. Tidak ada peringatan atau kesalahan di mana pun. Saya tidak akan membuang waktu untuk melacaknya. 10 MB bekerja dengan sangat baik. Jika Anda mencapai batas lain, itu mungkin mengeluh. Saya memiliki berbagai buffer innodb yang ditingkatkan dari default. Bumbui secukupnya. Seperti biasa, tonton mysqld.log di satu jendela.

IcarusNM
sumber
Lihat ini percona.com/blog/2013/09/11/11 ...
Jonas Stensved
Terima kasih Jonas; Itu menarik. Saya pikir saya mungkin tetap dengan metode saya di atas. Dia menunjukkan menggunakan gdb terhadap menjalankan mysqld yang saya mungkin tidak akan pernah mengambil risiko. Tetapi informasi yang baik di sana juga.
IcarusNM
Untuk beberapa alasan aneh, menggunakan MariaDB, saya tidak mendapatkan nomor urut log 'angka kecil [spasi] angka besar' - tetapi hanya 'angka besar', jadi sayangnya metode ini tidak berhasil untuk saya. Yah, tentu saja, log diperbarui, saya hanya tidak tahu kapan harus berhenti!
Gwyneth Llewelyn
5

Anda memiliki tiga (3) opsi:

OPSI 01: Lakukan rsync Master to Slave (Downtime on the Master)

  • Langkah 01: Jalankan reset master;pada master (Zaps Binary Logs)
  • Langkah 02: service mysql stopdi master
  • Langkah 03: service mysql stopdi slave
  • Langkah 04: rsync / var / lib / mysql dari master ke slave
  • Langkah 05: service mysql startdi master
  • Langkah 06: Gunakan log biner pertama pada master sebagai log untuk memulai replikasi. Gunakan ukuran file dari log itu sebagai posisi untuk memulai replikasi
  • Langkah 07: service mysql stop --skip-slave-startpada budak
  • Langkah 08: Jalankan CHANGE MASTER TO perintah untuk mengatur replikasi dari log dan posisi dipastikan dari Langkah 06
  • Langkah 09: Jalankan start slave;pada slave dan biarkan replikasi menyusul

OPSI 02: Lakukan rsync Master to Slave (Minimal Downtime pada Master)

  • Langkah 01: Jalankan reset master;pada master (Zaps Binary Logs)
  • Langkah 02: service mysql stopdi budak
  • Langkah 03: rsync / var / lib / mysql dari master ke slave
  • Langkah 04: Ulangi Langkah 03 sampai dua rsyncs berturut-turut mengambil jumlah waktu yang sama
  • Langkah 05: service mysql stopdi master
  • Langkah 06: rsync / var / lib / mysql dari master ke slave
  • Langkah 07: service mysql startdi master
  • Langkah 08: Gunakan log biner pertama pada master sebagai log untuk memulai replikasi. Gunakan filesize log itu sebagai posisi untuk memulai replikasi dari
  • Langkah 09: service mysql stop --skip-slave-startpada budak
  • Langkah 10: Jalankan CHANGE MASTER TO perintah untuk mengatur replikasi dari log dan posisi dipastikan dari Langkah 08
  • Langkah 11: Jalankan start slave;pada slave dan biarkan replikasi menyusul

OPSI 03: Gunakan XtraBackup

Alat perangkat lunak ini tidak hanya akan membuat salinan master berjalan yang tidak mengganggu, tetapi juga akan membuat ib_logfiles yang sesuai untuk Anda. Anda harus mengatur replikasi

Saya telah memposting ke StackExchange sebelumnya tentang hal ini

Saya telah melakukan hal ini berkali-kali untuk perusahaan hosting web majikan saya. Satu klien memiliki 3.7TB untuk bergerak dan butuh sekitar 16 jam. 64GB sangat kecil dibandingkan.

RolandoMySQLDBA
sumber
Dalam OPSI 02 Langkah 05 Anda mengatakan untuk memulai master. Kapan itu dihentikan? Rsync pada master hidup adalah berani. Saya terkesan. Dan untungnya saya menggunakan innodb_file_per_table. Tetapi pada akhirnya Anda harus menggigit peluru dan menghentikan master cukup lama untuk menjalankan rsync terakhir sebelum memulai replikasi. Itu kemungkinan saya bisa menggunakan, tapi ini adalah DBMS yang sangat aktif. Dan saya akan melihat XtraBackup untuk info saya.
IcarusNM
@IcarusNM: Ah, salah ketik. Saya memperbaikinya. Terima kasih !!!
RolandoMySQLDBA
OPSI 02 mungkin masih dapat menggunakan beberapa pekerjaan. Misalnya, Anda harus melakukan langkah 2 sebelum langkah 1. Anda mungkin ingin RESET SLAVE di sana. Mengetik dalam langkah 4. Dan Anda mengatakan "log biner pertama" pada langkah 5 tetapi yang Anda maksud adalah log biner "hanya" atau "terakhir". Dan Anda harus menggunakan mysqlbinlog untuk memastikan posisi log, bukan ukuran file. Dan semua ini masih tidak akan berhasil kecuali Anda menghentikan master di beberapa titik. Mendasarkan posisi log / waktu pada saat rsync selesai beresiko terbaik.
IcarusNM
Saya telah melakukan OPTION 2 selama 4 tahun terakhir dengan klien DB Hosting yang memiliki data dalam TeraByte Range. Ini berfungsi setiap saat terhadap server yang berjalan. Satu-satunya kesalahan nyata yang bisa Anda lakukan adalah pada budak. Kesalahan itu adalah apakah replikasi dipasang dengan benar atau tidak. Selain itu, RESET SLAVEberguna, terutama jika Anda telah menumpuk banyak log relai GB. Setelah proses rsync dan pembangunan kembali replikasi, harap ingat perintah CHANGE MASTER TO TO juga akan menghapus log relai untuk Anda juga.
RolandoMySQLDBA
mmm ... aneh. saya mengatur slave saya menggunakan xtrabackup (seperti biasa) dan masih mendapatkan kesalahan log ini (percona mysql 5.5.x) ... sepertinya ada yang salah pada slave ini dan saya harus melakukannya lagi.
Harald
2

Saya menemukan mungkin ada cara yang lebih keren untuk menyelesaikan masalah ini dengan bekerja pada tabel yang dipartisi. Saya perlu menghapus partisi dari beberapa tahun yang lalu, dan harus menambahkan beberapa untuk 2014. Hampir semua partisi melaporkan kesalahan ini, begitu juga yang lama. Kecelakaan yang sangat buruk.

Jadi sementara DROPPING lama dan menggunakan REORGANISASI dari partisi MAXVALUE (yang terakhir), itu akan membuat file baru yang ok, jadi saya mendapatkan semakin sedikit peringatan. Sementara itu, ini membantu menambah penghitung urutan log, jadi saya tidak perlu memasukkan data palsu. Saya memiliki ini terjadi pada server master btw ...

Jadi ini:

ALTER TABLE Events DROP PARTITION p1530 , p1535 , p1540 , p1545 , 
p1550, p1555 , p1560 , p1565 , p1570 , p1575 , p1580 , p1585 , p1590 , 
p1595 , p1600 , p1605 , p1610 , p1615 , p1620 , p1625 , p1630 , p1635 , 
p1640 , p1645 , p1650 , p1655 , p1660 , p1665 , p1670 , p1675 , p1680 , 
p1685 , p1690 , p1695 , p1700 , p1705 , p1710 , p1715 , p1720 , p1725 , 
p1730 , p1735 , p1740 , p1745 , p1750 , p1755 , p1760 , p1765 , p1770 , 
p1775 , p1780 , p1785 , p1790 , p1795 , p1800 , p1805 , p1810 , p1815 , 
p1820 , p1825 , p1830 , p1835 , p1840;

Dan ini:

ALTER table Events REORGANIZE PARTITION p3000 INTO (
PARTITION p3500 VALUES LESS THAN (TO_DAYS('2013-01-01')),
PARTITION p3510 VALUES LESS THAN (TO_DAYS('2013-01-04')),
PARTITION p3520 VALUES LESS THAN (TO_DAYS('2013-01-07')),
PARTITION p3530 VALUES LESS THAN (TO_DAYS('2013-01-10'))
...
PARTITION p4740 VALUES LESS THAN (TO_DAYS('2014-01-08')),
PARTITION p9000 VALUES LESS THAN MAXVALUE)

Itu akan secara efektif menjatuhkan setiap partisi dalam perubahan dan membuatnya kembali dengan salinan temporer dari konten yang ada di sana. Anda dapat melakukan ini per tabel jika Anda mau, aplikasi saya memungkinkan hal itu terjadi, jadi tidak perlu khawatir tentang cadangan yang disinkronkan dll.

Sekarang untuk sisa tabel, karena saya belum menyentuh semua partisi dalam proses beberapa akan dibiarkan dengan peringatan urutan log, untuk orang-orang yang rusak tapi dan ditutupi oleh tindakan reorganisasi ini saya mungkin akan menjalankan ini:

ALTER TABLE Events REBUILD PARTITION p0, p1;

atau itu

ALTER TABLE Events OPTIMIZE PARTITION p0, p1;

Jadi, itu membuat saya berpikir, Anda bisa melakukan ini dengan tabel vanilla biasa, menambahkan sementara partisi dengan hash dan kemudian menghapusnya (atau menyimpannya, saya sangat merekomendasikan partisi).

Saya menggunakan mariadb, bukan mysql (jadi XtraDB)

Mungkin ini membantu seseorang. Saya masih menjalankannya, sejauh ini sangat bagus. Mengubah ENGINE sepertinya melakukan pekerjaan itu juga, jadi saya membawanya kembali / maju antara MyIsam dan mereka kembali ke InnoDB.

Ini cukup logis, jika Anda mengubah ENGINE, tabel menghilang dari innodb, jadi itu tidak akan menjadi masalah lagi.

ALTER TABLE Events ENGINE=MyISAM;
ALTER TABLE Events ENGINE=InnoDB;

sepertinya bekerja di sini. Saya dapat mengkonfirmasi beberapa hal di tabel yang dipartisi:

  • ALTER TABLE xyz ENGINE = InnoDB sangat lambat, untuk Aria (mariadb) dua kali lebih cepat, tetapi secara umum cara yang lambat untuk meningkatkan penghitung urutan log
  • ALTER TABLE xyz REBUILD PARTITION ALL adalah cara tercepat untuk 'memperbaiki' tabel dan membantu menambah penghitung
  • ALTER TABEL xYZ ANALYZE PARTITION ALL lambat dibandingkan dengan yang sebelumnya dan tidak menulis ulang partisi yang dianggap ok. REBUILD memastikan penulisan ulang skema tabel temp.

Saya menggunakan yang terakhir di beberapa tabel. Peringatan terjadi ketika mencoba membuka file dan ada satu untuk setiap definisi partisi yang dibuka dengan masalah counter. Hampir terguling meja hari ini untuk tabel terakhir. Saya pikir setelah itu semua diproses kita perlu membersihkan log biner.

pembaruan : Saya dapat menyimpulkan beberapa hal sekarang saya berhasil menyelesaikan masalah ini.

  • Kecelakaan saya disebabkan oleh reorganisasi partisi di atas meja dalam format Aria (MariaDB).
  • (Untuk saya) melakukan pembangunan kembali partisi bekerja yang terbaik dan tercepat untuk mendapatkan urutan counter. Mengubah mesin lambat dan Anda harus melakukannya dua kali untuk mempengaruhi innodb. mengubah ke innoDB cukup lambat vs. ke MyIsam atau Aria.
  • Saya memutakhirkan ke MariaDB 5.3 dan tidak ke 5.5 (adalah: 5.2) dan berfungsi dengan baik. Saya pikir ada terlalu banyak masalah dengan aria, partisi di 5.5 (dan bug yang dikonfirmasi) untuk menggunakan kombinasi itu.
  • Harus ada cara yang lebih baik untuk mengatur ulang penghitung urutan log.
Glenn Plas
sumber
Di bawah MariaDB, Anda dapat dengan cepat mengubah semua tabel menggunakan USE INFORMATION_SCHEMA; SELECT CONCAT("ALTER TABLE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` REBUILD PARTITION ALL;") AS MySQLCMD AS MySQLCMD FROM TABLES;(sumber: dba.stackexchange.com/questions/35073/… ) dan mem -tee-nya ke file yang akan dieksekusi sebagai serangkaian perintah.
Gwyneth Llewelyn