Qualche modo migliore per uscire dal log di MySQL InnoDB "in futuro"?


16

Ho questo errore InnoDB in MySQL 5.0. Mysqld è stato fermato in modo pulito, ma sono riuscito a perdere ib_logfile0 e ib_logfile1 in seguito. Ora dopo un avvio pulito, InnoDB ha eseguito il "ripristino di emergenza". Ho esaminato il business innodb_force_recovery = 4, ho riparato una tabella MyISAM sospesa e ora la replica è pronta, a parte questo. Grandi numeri commessi:

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.

Questo è su un server slave. L'errore sopra riportato sputa a centinaia. Ho trovato questa risposta: "inserisci ed elimina> 64 GB di dati, in modo che il numero di sequenza del registro si gonfia abbastanza grande".

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

Quel numero magico di 64 GB proviene da 4 GB * 16 dove il "numero maggiore" del registro innodb di quel ragazzo doveva aumentare da 0 a 15. Il mio va da 70 a 111 = 164 GB. Ci vorranno 5 giorni. Continuerò a lavorare per accelerare la mia sceneggiatura ed eseguirla in parallelo per accelerarla. Nel frattempo, spero che qualcun altro abbia una risposta migliore. Questo è sciocco.


Una risposta promettente: "Se si tratta di un server slave, la soluzione migliore sarebbe davvero quella di spostare il database da parte e installare una nuova istantanea dal master". Sfortunatamente ci sono 20.000 tabelle in 25 database, un mix di MyISAM e InnoDB, in produzione 24x7. Ci vorrebbe troppo tempo per chiudere tutto ciò ed eseguire una nuova replica completa prima di riavviare la replica.
IcarusNM,

4
Ora ho questa macchina a 8 core in ginocchio in una corsa inutile per creare ed eliminare 164 concerti di dati. L'unica alternativa che sto ascoltando è quella di annotare tutto su questo schiavo e ricominciare da capo. Tutto per cambiare efficacemente un numero in due file. Sicuramente c'è un ingegnere di InnoDB là fuori con un suggerimento professionale. Qualcuno ha mai aperto ib_logfile0 in Emacs, ha trovato il numero magico in esadecimale e l'ha appena cambiato?
IcarusNM,

Ecco un ottimo articolo su alcuni modi per farlo. Percona è sicuramente l'autorità su MySQL. percona.com/blog/2013/09/11/…
jbrahy

Risposte:


10

Questa era una situazione piuttosto rara. Spero di non finire mai più lì, con un InnoDB "il numero di sequenza del registro è in futuro!" errore. A causa dei miei particolari dettagli, la ricostruzione / il ripristino dei dati del mio server è stata l'ultima risorsa. Alcuni trucchi per aiutare erano buone idee, ma alla fine, ho deciso di continuare a migliorare il mio script Perl per giocare a questo gioco sciocco e sfornare quanti più concerti / ora possibile. Che diamine, è un buon stress test del sistema.

Ricorda: l'obiettivo è aumentare un singolo contatore ("numero sequenza log") che è memorizzato da qualche parte nelle intestazioni di ib_logfile0 e ib_logfile1 . Questo per falsificare InnoDB in modo da ignorare un apparente distorsione temporale e andare avanti con la vita. Ma nessuno sa come modificare quel numero. O se lo sanno, nessuno parla.

Ecco il mio prodotto finale. YMMV, ma l'utilizzo della funzione REPEAT di mysql per generare i dati internamente è altamente efficiente.

 #!/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");

La mia ricetta suggerita:

  1. Crea un database "indesiderato"
  2. Salvare lo script perl di cui sopra come junk.pl .
  3. Esegui junk.pl data1 e junk.pl data2 e junk.pl data3 , ecc. Tutto in una volta, per avviare tutti i core della CPU del tuo server di database. Aprire più conchiglie e avvolgere ogni esecuzione in un ciclo Bash: while true; do date; junk.pl dataX; done.

Guarda crescere il tuo LSN, magari in un altro ciclo:

 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

Il numero più grande è un INT a 32 bit senza segno che andrà a finire a 4 GB, aumentando ogni volta il numero più piccolo. In questo caso sopra è appena passato da 124 a 125. Il tuo obiettivo è nascosto nel mysqld.log che ti ha inviato su Google per questa soluzione ridicola in primo luogo. Una volta che hai tagliato il traguardo, il gioco è fatto! Blow the horns! Rilascia i coriandoli!

Barra laterale: questo ha scoperto un bug interessante in mysqld 5.0 con REPEAT: se vai a 20 MB, lancia un contatore interno e passa a ~ 96 KB. Nessun avviso o errore ovunque. Non avevo intenzione di perdere tempo a rintracciarlo. 10 MB funzionano alla grande. Se raggiungi un altro limite, potresti lamentarti. Ho diversi buffer innodb aumentati di default. Condire a piacere. Come sempre, guarda mysqld.log in una finestra.



Grazie Jonas; Interessante. Penso che potrei attenermi al mio metodo sopra. Dimostra di usare gdb contro il mysqld in esecuzione che probabilmente non rischierei mai. Ma anche una buona informazione lì.
IcarusNM,

Per qualche strana ragione, usando MariaDB, non ottengo i numeri di sequenza di registro "piccolo numero [spazio] grande numero", ma solo un "grande numero", quindi purtroppo questo metodo non ha funzionato per me. Bene, ovviamente, il registro viene aggiornato, non so proprio quando fermarmi!
Gwyneth Llewelyn,

5

Hai tre (3) opzioni:

OPZIONE 01: Esegui rsync di Master to Slave (Downtime sul Master)

  • Step 01: Esegui reset master; sul master (registri binari Zaps)
  • Step 02: service mysql stopsul master
  • Step 03: service mysql stopsullo slave
  • Passaggio 04: rsync / var / lib / mysql dal master allo slave
  • Step 05: service mysql startsul master
  • Passaggio 06: utilizzare il primo registro binario sul master come registro da cui iniziare la replica. Utilizzare la dimensione del file di quel registro come posizione da cui iniziare la replica
  • Passo 07: service mysql stop --skip-slave-startsullo schiavo
  • Passaggio 08: eseguire il comando MODIFICA MASTER TO per impostare la replica dal registro e dalla posizione accertati dal passaggio 06
  • Passaggio 09: eseguire start slave;sullo slave e attendere che la replica raggiunga

OPZIONE 02: Esegui rsync di Master to Slave (Downtime minimo sul Master)

  • Passaggio 01: Eseguireset master; sul master (registri binari Zaps)
  • Step 02: service mysql stopsullo slave
  • Passaggio 03: rsync / var / lib / mysql dal master allo slave
  • Passaggio 04: ripetere il passaggio 03 fino a quando due rsync consecutivi impiegano lo stesso tempo
  • Step 05: service mysql stopsul master
  • Passaggio 06: rsync / var / lib / mysql dal master allo slave
  • Step 07: service mysql startsul master
  • Passaggio 08: utilizzare il primo registro binario sul master come registro da cui iniziare la replica. Utilizzare la dimensione del file di quel registro come posizione da cui iniziare la replica
  • Step 09: service mysql stop --skip-slave-start sullo schiavo
  • Passaggio 10: eseguire il comando MODIFICA MASTER TO per impostare la replica dal registro e dalla posizione accertati dal passaggio 08
  • Passaggio 11: eseguire start slave;sullo slave e attendere la replica

OPZIONE 03: utilizzare XtraBackup

Questo strumento software non solo farà una copia non invadente di un master in esecuzione, ma creerà anche i corrispondenti ib_logfiles per te. Dovresti impostare la replica

Ho pubblicato su StackExchange prima su questo argomento

Ho fatto queste cose molte volte per la società di web hosting del mio datore di lavoro. Un cliente aveva 3,7 TB da spostare e impiegava circa 16 ore. 64 GB è molto piccolo in confronto.


In OPTION 02 Step 05 dici di avviare il master. Quando è stato fermato? Rsync su un master live è coraggioso. Sono impressionato. E per fortuna sto usando innodb_file_per_table. Ma alla fine devi mordere il proiettile e fermare il master abbastanza a lungo da eseguire un'ultima sincronizzazione prima di iniziare la replica. È una possibilità a cui posso ricorrere, ma si tratta di un DBMS molto attivo. E guarderò XtraBackup per le mie informazioni.
IcarusNM,

@IcarusNM: Ah, errore di battitura. L'ho corretto. Grazie !!!
RolandoMySQLDBA

L'OPZIONE 02 potrebbe probabilmente ancora usare del lavoro. Ad esempio, dovresti fare il passaggio 2 prima del passaggio 1. Probabilmente vuoi un RESET SLAVE da qualche parte. Digitare nel passaggio 4. E si dice "primo registro binario" nel passaggio 5, ma si intende davvero "solo" o "ultimo" registro binario. E dovresti usare mysqlbinlog per accertare le posizioni del registro, non le dimensioni del file. E tutto ciò non funzionerà ancora a meno che tu non fermi il master ad un certo punto. Basare una posizione / tempo del registro su quando un rsync è finito è al massimo rischioso.
IcarusNM,

Faccio OPTION 2 da 4 anni con clienti DB Hosting che dispongono di dati nella gamma TeraByte. Funziona ogni volta contro un server in esecuzione. L'unico vero errore che potresti fare è sullo schiavo. Quell'errore sarebbe se la replica fosse stata impostata correttamente o meno. Inoltre, RESET SLAVEè utile, soprattutto se hai accumulato molti GB di log di inoltro. Dopo il processo rsync e il ripristino della replica, ricorda che il comando MODIFICA MASTER TO cancellerà anche i log di inoltro per te.
RolandoMySQLDBA

mmm ... strano. ho impostato il mio slave usando xtrabackup (come sempre) e ho ancora questi errori di registro (percona mysql 5.5.x) ... sembra che ci sia stato qualcosa di sbagliato in questo slave e devo farlo di nuovo.
Harald

2

Ho scoperto che esiste forse un modo migliore per risolvere questo problema lavorando su tabelle partizionate. Avevo bisogno di eliminare le partizioni da alcuni anni e ne ho aggiunte alcune per il 2014. Quasi tutte le partizioni riportano questo errore, quindi anche quelle vecchie. Incidente molto brutto.

Quindi, mentre DROPPING vecchio e usando REORGANIZE della partizione MAXVALUE (l'ultima), creerà nuovi file che sono ok, quindi ricevo sempre meno avvisi. Nel frattempo, aiuta ad aumentare il contatore della sequenza di log, quindi non ho bisogno di inserire dati fasulli. Ho questo che succede su un server master tra ...

Così questo:

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;

E questo:

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)

Ciò eliminerà effettivamente ogni partizione nella modifica e la ricrea con una copia temporanea del contenuto di ciò che era presente. Puoi farlo per tabella se vuoi, la mia applicazione lo consente, quindi non devi preoccuparti di backup sincronizzati ecc.

Ora per il resto della tabella, dal momento che non ho toccato tutte le partizioni nel processo alcune verranno lasciate con l'avvertimento della sequenza di registro, per quelle che sono rotte ma e coperte da questa azione di riorganizzazione probabilmente eseguirò questo:

ALTER TABLE Events REBUILD PARTITION p0, p1;

o quello

ALTER TABLE Events OPTIMIZE PARTITION p0, p1;

Quindi, questo mi ha fatto pensare, potresti farlo con semplici tabelle alla vaniglia, aggiungere temporaneamente partizioni per hash e successivamente rimuoverlo (o tenerle, posso consigliare vivamente le partizioni).

Sto usando mariadb comunque, non mysql (quindi XtraDB)

Forse questo aiuta qualcuno. Lo sto ancora eseguendo, finora tutto bene. Anche cambiare ENGINE sembra fare il lavoro, quindi lo porto avanti / indietro tra MyIsam e loro in InnoDB.

È abbastanza logico, se cambi ENGINE, la tabella scompare da innodb, quindi non sarà più un problema.

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

sembra funzionare qui. Posso confermare alcune cose su tabelle partizionate:

  • ALTER TABLE xyz ENGINE = InnoDB è molto lento, per Aria (mariadb) due volte più veloce, ma in generale un modo lento per aumentare il contatore della sequenza di log
  • ALTER TABLE xyz REBUILD PARTITION ALL è il modo più veloce per 'riparare' le tabelle e aiutare ad aumentare il contatore
  • ALTER TABLE xyz ANALYZE PARTITION ALL è lentamente confrontato con il primo e non riscrive le partizioni che risultano ok. REBUILD assicura una riscrittura in uno schema di tabella temporanea.

Ho usato gli ultimi su diversi tavoli. Gli avvisi si verificano quando si tenta di aprire i file e ce n'è uno per ogni definizione di partizione che si apre con problemi di contatore. Oggi ho quasi rotolato sul bancone per gli ultimi tavoli. Penso che una volta elaborato sia necessario svuotare i registri binari.

aggiornamento : posso concludere alcune cose ora sono riuscito a risolvere questo problema.

  • Il mio crash è stato causato dalla riorganizzazione delle partizioni su un tavolo nel formato Aria (MariaDB).
  • (per me) fare una ricostruzione delle partizioni ha funzionato meglio e più velocemente per ottenere il contatore delle sequenze. Modificare il motore è lento e devi farlo due volte per influenzare innodb. la modifica a innoDB è piuttosto lenta rispetto a MyIsam o Aria.
  • Ho aggiornato a MariaDB 5.3 e non a 5.5 (era: 5.2) e funziona benissimo. Penso che ci siano troppi problemi con aria, le partizioni in 5.5 (e i bug confermati) per usare quella combinazione.
  • Dovrebbe esserci davvero un modo migliore per ripristinare il contatore della sequenza di registro.

Sotto MariaDB, puoi modificare rapidamente tutte le tabelle usando USE INFORMATION_SCHEMA; SELECT CONCAT("ALTER TABLE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` REBUILD PARTITION ALL;") AS MySQLCMD AS MySQLCMD FROM TABLES;(fonte: dba.stackexchange.com/questions/35073/… ) e collegarlo a un file per eseguirlo come una serie di comandi.
Gwyneth Llewelyn,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.