`ERRO 1114 (HY000) a tabela… está cheia` com innodb_file_per_table definido para autoextend


26

Eu tenho um banco de dados MySQL que contém uma grande quantidade de dados (100-200GB - um monte de medições científicas). A grande maioria dos dados é armazenada em uma tabela Sample. Agora estou criando uma réplica escrava do banco de dados e queria aproveitar as vantagens innodb_file_per_tabledurante o processo. Então, defini innodb_file_per_tableminha configuração de escravo e importei o despejo do banco de dados. Para minha surpresa, falhou com

ERRO 1114 (HY000) na linha 5602: A tabela 'Amostra' está cheia

Sample.ibdAtualmente, o arquivo tem cerca de 93 GB, com mais de 600 GB de espaço disponível na partição; portanto, não é um problema de espaço livre em disco. Nem parece estar atingindo qualquer tipo de limite do sistema de arquivos (estou usando o ext4).

Ficaria grato por quaisquer idéias sobre o que poderia ser a causa ou o que investigar.


Atualização: estou 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

Respostas:


33

FATOS

Você disse que está usando ext4. O limite de tamanho do arquivo é 16 TB. Assim, Sample.ibdnão deve estar cheio.

Você disse que innodb_data_file_pathé ibdata1:10M:autoextend. Portanto, o próprio arquivo ibdata1 não tem limite para seu tamanho, exceto no sistema operacional.

Por que esta mensagem está chegando? Observe que a mensagem é "A tabela ... está cheia", não "O disco ... está cheio". Esta condição de tabela completa é do ponto de vista lógico . Pense no InnoDB. Que interações estão acontecendo?

Meu palpite é que o InnoDB está tentando carregar 93 GB de dados como uma única transação. De onde Table is Fullemanaria a mensagem? Eu examinaria o ibdata1, não em termos de tamanho físico (que você já descartou), mas em termos de quais limites de transação estão sendo atingidos.

O que há no ibdata1 quando innodb_file_per_table está ativado e você carrega novos dados no MySQL?

Minhas suspeitas me dizem que os logs de desfazer e / ou refazer são os culpados.

O que são esses logs? De acordo com o livro

sxs

Os parágrafos 3,4 do capítulo 10 dizem o seguinte:

O mecanismo do InnoDB mantém dois tipos de logs: um log de desfazer e um log de refazer. O objetivo de um log de desfazer é reverter as transações, bem como exibir as versões mais antigas dos dados para consultas em execução no nível de isolamento de transações que exige isso. O código que manipula o log de desfazer pode ser encontrado em storage / innobase / buf / log / log0log.c .

O objetivo do log de refazer é armazenar as informações a serem usadas na recuperação de falhas. Ele permite que o processo de recuperação execute novamente as transações que podem ou não ter sido concluídas antes da falha. Depois de reexecutar essas transações, o banco de dados é levado a um estado consistente. O código que trata do redo log pode ser encontrado em storage / innobase / log / log0recv.c .

ANÁLISE

Existem 1023 logs de desfazer dentro do ibdata1 (consulte Segmentos de reversão e espaço de desfazer) . Como os logs de desfazer mantêm cópias dos dados como apareceram antes do recarregamento, todos os 1023 Undo Logs atingiram seu limite. De outra perspectiva, todos os 1023 Undo Logs podem ser dedicados à transação que carrega a Sampletabela.

MAS ESPERE...

Você provavelmente está dizendo "Estou carregando uma Samplemesa vazia ". Como estão envolvidos os desfazer logs? Antes da Sampletabela ter sido carregada com 93 GB de dados, ela estava vazia. A representação de todas as linhas que não existiam deve ocupar algum espaço de limpeza nos logs de desfazer. O preenchimento de 1023 Desfazer Logs parece trivial, dada a quantidade de dados que é derramada ibdata1. Eu não sou a primeira pessoa a suspeitar disso:

Na documentação do MySQL 4.1, observe Posted by Chris Calender on September 4 2009 4:25pm:

Observe que no 5.0 (pré-5.0.85) e no 5.1 (pré-5.1.38), você pode receber o erro "tabela está cheia" para uma tabela do InnoDB se o InnoDB ficar sem slots de desfazer (bug # 18828).

Aqui está o relatório de erros do MySQL 5.0: http://bugs.mysql.com/bug.php?id=18828

SUGESTÕES

Quando você cria o mysqldump da Sampletabela, use --no-autocommit

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

Isso colocará um explícito COMMIT;depois de cada INSERT. Em seguida, recarregue a tabela.

Se isso não funcionar ( você não vai gostar disso ), faça isso

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

Isso fará com que cada INSERT tenha apenas uma linha. O mysqldump será muito maior (mais de 10 vezes maior) e poderá levar de 10 a 100 vezes mais para recarregar.

Em ambos os casos, isso evitará que os logs de desfazer sejam inundados.

De uma chance !!!

UPDATE 2013-06-03 13:05 EDT

SUGESTÃO ADICIONAL

Se a tabela do sistema InnoDB (também conhecida como ibdata1) atingir um limite de tamanho de arquivo e o Desfazer logs não puder ser usado, você poderá adicionar outro espaço de tabela do sistema (ibdata2).

Acabei de encontrar esta situação há apenas dois dias. Atualizei minha postagem antiga com o que fiz: Consulte Design do banco de dados - Criando vários bancos de dados para evitar a dor de cabeça do limite no tamanho da tabela

Em essência, é necessário alterar innodb_data_file_path para acomodar um novo arquivo de espaço de tabela do sistema. Deixe-me explicar como:

CENÁRIO

No disco (ext3), o servidor do meu cliente tinha o seguinte:

[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

A configuração era

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

Observe que ibdata2cresceu para 2196875759616, o que é 2145386484M.

Eu tive que incorporar o tamanho do arquivo ibdata2no innodb_data_file_path e adicionaribdata3

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

Quando reiniciei o mysqld, funcionou:

[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

Em 40 horas, ibdata3cresceu para 31G. O MySQL estava mais uma vez trabalhando.


Acho que pelo nome do proprietário, seu cliente estava usando uma ferramenta de monitoramento avançada ... Obrigado, isso parece ter corrigido um problema para mim também.
Steve

Eu me pergunto se isso ainda é um problema (a esperança não)
Evan Carroll

3

Eu tive o mesmo problema e fiz apenas uma coisa e funcionou.

Você parece ter um tamanho máximo muito baixo para o innodb_data_file_pathseu my.cnfarquivo de configuração. Basta alterar o código abaixo -

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

Nota importante Você não pode hospedar mais do que 512MBdados em todas as InnoDB tabelas combinadas.

Você também pode mudar para um esquema de innodb por tabela usando innodb_file_per_table.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.