Erro de tamanho de linha com o MySQL

11

Estou executando um servidor MySQL no meu Macbook (para teste). A versão é 5.6.20 do Homebrew. Comecei a executar erros de "tamanho da linha muito grande" e pude reduzi-lo a este caso de teste. Mesa:

mysql> describe test;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(11)  | NO   | PRI | NULL    | auto_increment |
| stuff | longtext | YES  |     | NULL    |                |
+-------+----------+------+-----+---------+----------------+

Status da tabela:

mysql> show table status where Name = 'test';
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time | Check_time | Collation       | Checksum | Create_options | Comment |
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
| test | InnoDB |      10 | Compact    |    1 |          16384 |       16384 |               0 |            0 |   5242880 |              2 | 2014-08-28 23:51:12 | NULL        | NULL       | utf8_general_ci |     NULL |                |         |
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+

O erro que estou recebendo quando tento inserir uma linha na tabela em que a stuffcoluna tem mais de 5033932 bytes.

mysql> select length(stuff) from test;
+---------------+
| length(stuff) |
+---------------+
|       5033932 |
+---------------+

mysql> update test set stuff = concat(stuff, 'a');
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.

Eu procurei esse erro, a maioria das respostas envolve ter muitas colunas TEXT e cada uma possui 768 bytes armazenados em linha. Como você pode ver, esse não é o meu caso. Além disso, o número 5033932 permanece o mesmo, independentemente do número de colunas que tenho na tabela. No meu aplicativo original, havia cinco colunas e as atualizações ainda falharam quando o tamanho da coluna excedeu 5033932.

Também vi pessoas resolverem o problema alternando os formatos de linha, que tentarei um pouco, mas gostaria de entender exatamente o que está causando esse erro.

Desde já, obrigado!

geoffliu
fonte

Respostas:

12

Uma alteração nas notas de versão 5.6.20:

Refazer gravações de log para campos BLOB grandes armazenados externamente pode substituir o ponto de verificação mais recente. O patch 5.6.20 limita o tamanho das gravações de redo log do BLOB para 10% do tamanho do arquivo de redo log. O patch 5.7.5 corrige o erro sem impor uma limitação. Para o MySQL 5.5, o bug continua sendo uma limitação conhecida.

Como resultado do limite de gravação de BLOB de redo log introduzido para o MySQL 5.6, innodb_log_file_size deve ser definido como um valor maior que 10 vezes o maior tamanho de dados de BLOB encontrado nas linhas de suas tabelas mais o tamanho de outros campos de tamanho variável (VARCHAR, VARBINARY e campos do tipo TEXTO). Não fazer isso pode resultar em erros "Tamanho da linha muito grande".

(ênfase minha)

O padrão innodb_log_file_sizeé 50331648, o que significa que o maior valor de BLOB / TEXT que você pode criar, independentemente do tipo de dados, é próximo a 5033164 e você descobriu que o valor exato é 5033932. Suponho que internamente o cálculo envolva algum fator de falsificação.

Portanto, você precisa aumentar innodb_log_file_sizese deseja armazenar dados BLOB / TEXT maiores. Felizmente, alterar o tamanho do arquivo de log é muito mais fácil na 5.6 do que nas versões anteriores do InnoDB. Apenas adicione uma linha no seu my.cnf com o novo valor e reinicie o mysqld.

Bill Karwin
fonte
pequena notícia, você deve reiniciar ou parar e iniciar novamente para deixar a mudança ser afetados, de recarga não funciona
Hieu Vo
11
Esse limite de refazer tamanho é reduzido para 10% do total de innodb_log_file_size (innodb_log_file_size * innodb_log_files_in_group) do mysql 5.6.22. E o longblob pode ter um comprimento máximo de 4294967295 (2 ^ 32 - 1) caracteres, ou seja, 4 GB. Para armazenar esse valor do bloco longo, devemos ter no mínimo innodb_log_file_size de 40 GB (innodb_log_file_size * innodb_log_files_in_group).
19416 kasi