FATTI
Hai detto che stai usando ext4
. Il limite della dimensione del file è di 16 TB. Pertanto, Sample.ibd
non dovrebbe essere pieno.
Hai detto che il tuo innodb_data_file_path
IS 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 Full
messaggio? 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
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 Sample
tabella.
MA ASPETTA...
Probabilmente stai dicendo "Sto caricando una Sample
tabella vuota ". Come sono coinvolti i registri di annullamento? Prima che la Sample
tabella 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 Sample
tabella, 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 è ibdata2
cresciuto a 2196875759616 che è 2145386484M
.
Ho dovuto incorporare la dimensione del file ibdata2
in 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, è ibdata3
cresciuto fino a 31G. MySQL funzionava ancora una volta.