`ERRORE 1114 (HY000) la tabella… è piena` con innodb_file_per_table impostato su autoextend


26

Ho un database MySQL che contiene una grande quantità di dati (100-200 GB - un mucchio di misurazioni scientifiche). La stragrande maggioranza dei dati è archiviata in una tabella Sample. Ora sto creando una replica slave del database e volevo sfruttare i vantaggi di innodb_file_per_tabledurante il processo. Quindi ho impostato la innodb_file_per_tablemia configurazione slave e importato il dump del database. Con mia sorpresa, fallì

ERRORE 1114 (HY000) alla riga 5602: la tabella "Campione" è piena

Il file Sample.ibdè attualmente di circa 93 GB, con oltre 600 GB di spazio libero disponibile sulla partizione, quindi non è un problema di spazio libero su disco. Né sembra colpire alcun tipo di limite del file system (sto usando ext4).

Sarei grato per qualsiasi idea su quale potesse essere la causa o su cosa indagare.


Aggiornamento: sto usando mysql Ver 14.14 Distrib 5.1.66, for debian-linux-gnu (x86_64).

SELECT @@datadir; -- returns `/home/var/lib/mysql/`
SHOW VARIABLES LIKE '%innodb_data_file_path%'; -- ibdata1:10M:autoextend 

df -h /home/var/lib/mysql/
768G   31G  699G   5% /home

Risposte:


33

FATTI

Hai detto che stai usando ext4. Il limite della dimensione del file è di 16 TB. Pertanto, Sample.ibdnon dovrebbe essere pieno.

Hai detto che il tuo innodb_data_file_pathIS ibdata1:10M:autoextend. Pertanto, il file ibdata1 stesso non ha limiti alle sue dimensioni se non dal sistema operativo.

Perché questo messaggio sta arrivando? Si noti che il messaggio è "La tabella ... è piena", non "Il disco ... è pieno". Questa condizione completa della tabella è da un punto di vista logico . Pensa a InnoDB. Quali interazioni stanno succedendo?

Suppongo che InnoDB stia tentando di caricare 93 GB di dati come una singola transazione. Da dove verrebbe il Table is Fullmessaggio? Guarderei ibdata1, non in termini di dimensioni fisiche (che hai già escluso), ma in termini di limiti di transazione raggiunti.

Cosa c'è dentro ibdata1 quando innodb_file_per_table è abilitato e carichi nuovi dati in MySQL?

  • Dizionario dei dati
  • Doppio buffer di scrittura
    • Rete di sicurezza per prevenire la corruzione dei dati
    • Aiuta a bypassare il sistema operativo per la memorizzazione nella cache
  • Inserisci buffer (semplifica le modifiche agli indici secondari)
  • Segmenti di rollback
  • Annulla registri
  • Clicca qui per vedere una rappresentazione pittorica di ibdata1

I miei sospetti mi dicono che è colpa dei registri di annullamento e / o dei registri di ripetizione.

Cosa sono questi registri? Secondo il libro

sxs

Capitolo 10: "Motori di archiviazione" I paragrafi 3,4 dicono quanto segue:

Il motore InnoDB conserva due tipi di log: un registro di annullamento e un registro di ripetizione. Lo scopo di un registro di annullamento è di ripristinare le transazioni, nonché di visualizzare le versioni precedenti dei dati per le query in esecuzione nel livello di isolamento della transazione che lo richiede. Il codice che gestisce il registro degli annullamenti si trova in storage / innobase / buf / log / log0log.c .

Lo scopo del registro di ripetizione è archiviare le informazioni da utilizzare nel ripristino di emergenza. Consente al processo di recupero di rieseguire le transazioni che possono o meno essere state completate prima del crash. Dopo aver rieseguito tali transazioni, il database viene portato in uno stato coerente. Il codice relativo al registro di ripetizione si trova in storage / innobase / log / log0recv.c .

ANALISI

All'interno di ibdata1 sono presenti 1023 registri di annullamento (vedere Segmenti di rollback e Spazio di annullamento) . Poiché i registri di annullamento mantengono copie dei dati così come apparivano prima del ricaricamento, tutti i registri di annullamento 1023 hanno raggiunto il limite. Da un'altra prospettiva, tutti i 1023 registri di annullamento possono essere dedicati all'unica transazione che carica la Sampletabella.

MA ASPETTA...

Probabilmente stai dicendo "Sto caricando una Sampletabella vuota ". Come sono coinvolti i registri di annullamento? Prima che la Sampletabella fosse caricata con 93 GB di dati, era vuota. La rappresentazione di ogni riga che non esisteva deve occupare uno spazio di pulizia nei registri di annullamento. Compilare 1023 registri di annullamento sembra banale data la quantità di dati che vengono riversati ibdata1. Non sono la prima persona a sospettare questo:

Dalla documentazione di MySQL 4.1, nota Posted by Chris Calender on September 4 2009 4:25pm:

Si noti che in 5.0 (pre-5.0.85) e in 5.1 (pre-5.1.38), è possibile ricevere l'errore "table is full" per una tabella InnoDB se InnoDB esaurisce gli slot di annullamento (bug # 18828).

Ecco la segnalazione di bug per MySQL 5.0: http://bugs.mysql.com/bug.php?id=18828

SUGGERIMENTI

Quando si crea il mysqldump della Sampletabella, utilizzare --no-autocommit

mysqldump --no-autocommit ... mydb Sample > Sample.sql

Questo metterà un esplicito COMMIT;dopo ogni INSERT. Quindi, ricaricare la tabella.

Se questo non funziona ( non ti piacerà ), fallo

mysqldump --no-autocommit --skip-extended-insert ... mydb Sample > Sample.sql

Questo renderà ogni INSERTO solo una riga. Mysqldump sarà molto più grande (10+ volte più grande) e potrebbe richiedere da 10 a 100 volte più a lungo per ricaricare.

In entrambi i casi, ciò eviterà che i registri di annullamento vengano inondati.

Provaci !!!

AGGIORNAMENTO 2013-06-03 13:05 EDT

SUGGERIMENTI AGGIUNTIVI

Se la tabella di sistema InnoDB (aka ibdata1) supera un limite di dimensione file e non è possibile utilizzare i registri di annullamento, è possibile aggiungere un altro tablespace di sistema (ibdata2).

Ho appena incontrato questa situazione solo due giorni fa. Ho aggiornato il mio vecchio post con quello che ho fatto: Vedi Database Design - Creazione di più database per evitare il mal di testa del limite sulla dimensione della tabella

In sostanza, è necessario modificare innodb_data_file_path per accogliere un nuovo file tablespace di sistema. Lasciami spiegare come:

SCENARIO

Sul disco (ext3), il server del mio client aveva il seguente:

[root@l*****]# ls -l ibd*
-rw-rw---- 1 s-em7-mysql s-em7-mysql     362807296 Jun  2 00:15 ibdata1
-rw-rw---- 1 s-em7-mysql s-em7-mysql 2196875759616 Jun  2 00:15 ibdata2

L'ambientazione era

innodb_data_file_path=ibdata1:346M;ibdata2:500M:autoextend:max:10240000M

Si noti che è ibdata2cresciuto a 2196875759616 che è 2145386484M.

Ho dovuto incorporare la dimensione del file ibdata2in innodb_data_file_path e aggiungereibdata3

innodb_data_file_path=ibdata1:346M;ibdata2:2196875759616;ibdata3:10M:autoextend

Quando ho riavviato mysqld, ha funzionato:

[root@l*****]# ls -l ibd*
-rw-rw---- 1 s-em7-mysql s-em7-mysql     362807296 Jun  3 17:02 ibdata1
-rw-rw---- 1 s-em7-mysql s-em7-mysql 2196875759616 Jun  3 17:02 ibdata2
-rw-rw---- 1 s-em7-mysql s-em7-mysql   32315015168 Jun  3 17:02 ibdata3

In 40 ore, è ibdata3cresciuto fino a 31G. MySQL funzionava ancora una volta.


Sto indovinando con il nome del proprietario che il tuo cliente stava utilizzando uno strumento di monitoraggio emergente ... Grazie, questo sembra aver risolto un problema anche per me.
Steve

Mi chiedo se questo sia ancora un problema (spero di no)
Evan Carroll,

3

Ho avuto lo stesso problema e ho fatto solo una cosa e ha funzionato.

Sembra che tu abbia una dimensione massima troppo bassa per il tuo innodb_data_file_pathnel tuo my.cnffile di configurazione. Basta cambiare il codice qui sotto -

innodb_data_file_path = ibdata1:10M:autoextend:max:512M

Nota importante Non è possibile ospitare più 512MBdi dati in tutte le InnoDB tabelle combinate.

Puoi anche passare a uno schema innodb per tabella usando innodb_file_per_table.

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.