Por favor, não se deixe enganar pela mensagem de erro The table 'my_table' is full
. Esse cenário raro não tem absolutamente nada a ver com espaço em disco. Esta condição de tabela completa tem a ver com o encanamento interno do InnoDB.
Primeiro, dê uma olhada neste diagrama da arquitetura InnoDB
Observe que o espaço de tabela do sistema (o arquivo ibdata) possui apenas 128 segmentos de reversão e 1023 slots de reversão por segmento de reversão. Isso limita o tamanho da capacidade de reversão de uma transação. Em outras palavras, se um único segmento de reversão precisar de mais de 1023 slots para suportar uma transação, a transação atingirá essa table is full
condição.
Pense no restaurante Red Lobster, em Nova Jersey . Pode ter capacidade para 200 pessoas. Se o restaurante estiver cheio, uma fila de pessoas poderá sair para esperar. Se as pessoas na fila ficarem impacientes, elas poderão sair porque o restaurante está cheio. Obviamente, a solução não seria aumentar Nova Jersey (ou obter mais espaço em disco). A solução seria aumentar o restaurante Red Lobster. Dessa forma, você pode aumentar a capacidade de assentos para, digamos, 240. Mesmo assim, uma fila pode se formar do lado de fora se mais de 240 pessoas decidirem vir para a Red Lobster.
Só para dar um exemplo, eu tinha um cliente com 2TB de espaço de tabela do sistema e innodb_file_per_table foi desativado. (346G para ibdata1, a redefinição para ibdata2). Eu executei esta consulta
SELECT SUM(data_length+index+length) InnoDBDataIndexSpace
FROM information_schema.tables WHERE engine='InnoDB';
Em seguida, subtraí InnoDBDataIndexSpace da soma dos tamanhos de arquivo para ibdata1 e ibdata2. Eu tenho duas coisas que me chocaram
- Restavam 106 GB dentro do espaço de tabela do sistema.
- Eu tenho essa mesma
Table is Full
condição
Isso significa que os 106 GB estavam sendo usados para o encanamento interno do InnoDB. O cliente estava usando ext3 no momento.
A solução para mim foi adicionar ibdata3. Eu discuti isso no meu post antigo Como resolver "A tabela ... está cheia" com "innodb_file_per_table"?
Eu discuti isso em outros posts também
Lembre-se de que essa condição pode ocorrer mesmo se innodb_file_per_table estiver ativado. Como? Rollbacks e Undo Logs são a fonte de picos não controlados e o crescimento do ibdata1 .
SUA PERGUNTA REAL
Como você está adicionando um índice a uma tabela e obtendo Table is Full
, a tabela deve ser enorme e não pode caber em um único segmento de reversão. Você deve fazer o seguinte:
PASSO 01
Coloque os dados em um arquivo de despejo
mysqldump --no-create-info mydb mytable > table_data.sql
PASSO 02
Entre no MySQL e execute este
USE mydb
CREATE TABLE mytable_new LIKE mytable;
ALTER TABLE mytable_new ADD INDEX ... ;
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;
PASSO 03
Carregue a tabela com o índice adicional com os dados
mysql -Dmydb < table_data.sql
Isso é tudo.
Veja, o problema é que o ALTER TABLE tentará injetar todas as linhas da sua enorme tabela como uma única transação. Usar o mysqldump irá inserir os dados na tabela (agora com um novo índice) milhares de linhas por vez, nem todas as linhas em uma única transação.
Não se preocupe. what if this doesn't work?
A tabela original será nomeada mytable_old
em caso de algo. pode servir como um backup. Você pode descartar o backup quando souber que a nova tabela funciona para você.
De uma chance !!!
ATUALIZAÇÃO 16/06/2014 - 11:13
Se você está preocupado com o despejo de dados maior, basta compactá-lo.
Você pode executar as mesmas etapas, mas da seguinte maneira
PASSO 01
Coloque os dados em um arquivo de despejo
mysqldump --no-create-info mydb mytable | gzip > table_data.sql.gz
PASSO 02
Entre no MySQL e execute este
USE mydb
CREATE TABLE mytable_new LIKE mytable;
ALTER TABLE mytable_new ADD INDEX ... ;
ALTER TABLE mytable RENAME mytable_old;
ALTER TABLE mytable_new RENAME mytable;
PASSO 03
Carregue a tabela com o índice adicional com os dados
gzip -d < table_data.sql.gz | mysql -Dmydb
ou
gunzip < table_data.sql.gz | mysql -Dmydb
ATUALIZAÇÃO 16/06/2014 - 12:55
Acabei de pensar em outro aspecto em relação a esta questão.
Como você está executando DDL e não DML, é possível que isso não seja o encanamento interno do InnoDB. Como o DDL não pode reverter para o InnoDB , o problema deve ser o encanamento externo. Onde esse encanamento externo está entupido? Eu suspeito que a pasta temporária para o sistema operacional. Por quê?
140616 13:04:33 InnoDB: Error: Write to file (merge) failed at offset 3 1940914176.
InnoDB: 1048576 bytes should have been written, only 970752 were written.
InnoDB: Operating system error number 0.
InnoDB: Check that your OS and file system support files of this size.
InnoDB: Check also that the disk is not full or a disk quota exceeded.
InnoDB: Error number 0 means 'Success'.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/operating-system-error-codes.html
140616 13:04:33 [ERROR] /usr/libexec/mysqld: The table 'my_table' is full
Veja o disk quota exceeded
? Onde essa cota de disco está sendo imposta?
Execute esta consulta
SHOW GLOBAL VARIABLES LIKE 'tmpdir';
Você disse que é /var/lib/mysqltmp
Agora, execute isso no sistema operacional
df -h /var/lib/mysqltmp
Algo me diz que o espaço para /var/lib/mysqltmp
estava se esgotando Afinal, você só tem 14G de graça. Aos olhos do DDL (para criar o índice), ocorreu uma reversão, não no arquivo ibdata1, mas no tmpdir
local. Se /var/lib/mysqltmp
não estiver montado em nenhum lugar, os dados temporários serão gravados na partição raiz. Se /var/lib/mysqltmp
estiver montado em algum lugar, essa montagem será preenchida com dados de linha. Em ambos os casos, não há espaço suficiente para concluir o DDL.
Você tem duas opções aqui
OPÇÃO 1
Você também pode criar um disco grande (talvez com mais de 100 GB) e montar /var/lib/mysqltmp
nesse disco grande.
OPÇÃO 2
Minhas sugestões em três etapas ainda devem funcionar, mesmo com o espaço em disco limitado que você possui
COMENTÁRIO
É uma pena a mensagem de erro que você postou diz
InnoDB: Operating system error number 0.
InnoDB: Error number 0 means 'Success'.
Isso significa que o sistema operacional está bem. Também não existe nenhum número de erro associado a essa situação.
Há outra coisa que você deve saber. A documentação do MySQL diz que a criação rápida de índice para o InnoDB ainda vai para o disco :
Durante a criação do índice, os arquivos são gravados no diretório temporário ($ TMPDIR no Unix,% TEMP% no Windows ou o valor da variável de configuração --tmpdir). Cada arquivo temporário é grande o suficiente para conter uma coluna que compõe o novo índice e cada um é removido assim que é mesclado no índice final.
Devido a uma limitação do MySQL, a tabela é copiada, em vez de usar “Fast Index Creation” quando você cria um índice em uma TEMPORARY TABLE. Isso foi relatado como Bug # 39833 do MySQL .
ATUALIZAÇÃO 16/06/2014 - 13:58 EDT
[mysqld]
datadir = /mnt/cbsvolume1/var/lib/mysql
tmpdir = /mnt/cbsvolume1/var/lib/mysql
Certifique-se de /mnt/cbsvolume1/var/lib/mysql
ter 100G ou mais grátis