1436 - Saturação da pilha de threads:6.136 bytes usados de uma pilha de 131.072 bytes e 128.000 bytes necessários.
O erro 1436 corresponde a ER_STACK_OVERRUN_NEED_MORE no código mysql 5.1:
[email protected]:include> pwd
/home/malff/BZR_TREE/mysql-5.1/include
[email protected]:include> grep 1436 mysqld_error.h
#define ER_STACK_OVERRUN_NEED_MORE 1436
O código que imprime o erro visto está em sql/sql_parse.cc,function check_stack_overrun() :
bool check_stack_overrun(THD *thd, long margin,
uchar *buf __attribute__((unused)))
{
long stack_used;
DBUG_ASSERT(thd == current_thd);
if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >=
(long) (my_thread_stack_size - margin))
{
char ebuff[MYSQL_ERRMSG_SIZE];
my_snprintf(ebuff, sizeof(ebuff), ER(ER_STACK_OVERRUN_NEED_MORE),
stack_used, my_thread_stack_size, margin);
my_message(ER_STACK_OVERRUN_NEED_MORE, ebuff, MYF(ME_FATALERROR));
Dos valores vistos, margin é 128000 e my_thread_stack_size é 131072.
A única chamada para check_stack_overrun() que tenta reservar 128.000 bytes é de:
bool
sp_head::execute(THD *thd)
{
/* Use some extra margin for possible SP recursion and functions */
if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (uchar*)&old_packet))
DBUG_RETURN(TRUE);
O valor de STACK_MIN_SIZE é 16.000:
[email protected]:sql> pwd
/home/malff/BZR_TREE/mysql-5.1/sql
[email protected]:sql> grep STACK_MIN_SIZE *.h
mysql_priv.h:#define STACK_MIN_SIZE 16000 // Abort if less stack during eval.
Até agora, tudo funciona como esperado para o servidor:
- o código executa um gatilho, que é implementado com sp_head::execute.
- o tempo de execução do MySQL verifica se há pelo menos 128.000 bytes na pilha
- esta verificação falha (com razão) e a execução do gatilho termina com um erro.
A quantidade de pilha necessária para a execução do gatilho do MySQL não depende da complexidade do gatilho em si, ou do conteúdo/estrutura das tabelas envolvidas.
O que real A questão é, eu acho, por que o thread_stack está apenas em 128K (131072).
A variável do servidor chamada 'thread_stack' é implementada em C como 'my_thread_stack_size' em sql/mysqld.cc :
{"thread_stack", OPT_THREAD_STACK,
"The stack size for each thread.", &my_thread_stack_size,
&my_thread_stack_size, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK,
1024L*128L, ULONG_MAX, 0, 1024, 0},
1024L*128L é o valor mínimo para este parâmetro. O valor padrão é DEFAULT_THREAD_STACK, que é definido em include/my_pthread.h:
#ifndef DEFAULT_THREAD_STACK
#if SIZEOF_CHARP > 4
/*
MySQL can survive with 32K, but some glibc libraries require > 128K stack
To resolve hostnames. Also recursive stored procedures needs stack.
*/
#define DEFAULT_THREAD_STACK (256*1024L)
#else
#define DEFAULT_THREAD_STACK (192*1024)
#endif
#endif
Portanto, por padrão, o tamanho da pilha deve ser 192 K (32 bits) ou 256 K (arquiteturas de 64 bits).
Primeiro, verifique como o binário mysqld foi compilado, para ver qual é o valor padrão:
[email protected]:sql> pwd
/home/malff/BZR_TREE/mysql-5.1/sql
[email protected]:sql> ./mysqld --no-defaults --verbose --help | grep thread_stack
...
--thread_stack=# The stack size for each thread.
thread_stack 262144
No meu sistema, consegui 256K em uma plataforma de 64 bits.
Se houver valores diferentes, talvez alguém construa o servidor com diferentes opções de compilação, como -DDEFAULT_THREAD_STACK (ou apenas modifiquei a fonte) ... Eu questionaria de onde vem o binário nesse caso.
Em segundo lugar, verifique my.cnf para valores padrão fornecidos no próprio arquivo de configuração. Uma linha definindo um valor para thread_stack explicitamente (e com um valor baixo) definitivamente causaria o erro visto.
Por último, verifique o arquivo de log do servidor para um erro como este (consulte sql/mysqld.cc):
sql_print_warning("Asked for %lu thread stack, but got %ld",
my_thread_stack_size, (long) stack_size);
O código do servidor chama:
- pthread_attr_setstacksize() para definir o tamanho da pilha
- pthread_attr_getstacksize() para verificar quanta pilha um thread realmente tem e reclama no log se a biblioteca pthread usou menos.
Para encurtar a história, o erro é visto porque o thread_stack é muito pequeno em comparação com os valores padrão enviados com o servidor. Isso pode acontecer:
- ao fazer compilações personalizadas do servidor, com diferentes opções de compilação
- ao alterar o valor padrão no arquivo my.cnf
- se algo deu errado na própria biblioteca pthread (em teoria, ao ler o código, eu mesmo nunca vi).
Espero que isso responda a pergunta.
Atenciosamente, -- Marc Alff
Atualização (2014-03-11), para tornar o "como consertar" mais óbvio.
O que está acontecendo, muito provavelmente, é que o valor padrão para o arquivo thread_stack foi alterado no arquivo my.cnf.
Como corrigi-lo é trivial, então, encontre onde thread_stack está definido no arquivo my.cnf e remova a configuração (confiando no código do servidor para fornecer um valor padrão decente, para que isso não aconteça novamente na próxima vez) ou aumente a pilha Tamanho.
Update (2021-04-28), verifique de onde vem o thread_stack:
Use a tabela
performance_schema.variables_info
para descobrir de onde uma determinada variável vem. mysql> select * from variables_info where VARIABLE_NAME = 'thread_stack';
+---------------+-----------------+---------------+-----------+----------------------+----------+----------+----------+
| VARIABLE_NAME | VARIABLE_SOURCE | VARIABLE_PATH | MIN_VALUE | MAX_VALUE | SET_TIME | SET_USER | SET_HOST |
+---------------+-----------------+---------------+-----------+----------------------+----------+----------+----------+
| thread_stack | COMPILED | | 131072 | 18446744073709550592 | NULL | NULL | NULL |
+---------------+-----------------+---------------+-----------+----------------------+----------+----------+----------+
1 row in set (0.01 sec)
Aqui o padrão é o valor de fábrica (compilado no binário mysqld).
Outro exemplo:
mysql> select * from variables_info where VARIABLE_NAME = 'thread_stack';
+---------------+-----------------+----------------------------------------------------------------+-----------+----------------------+----------+----------+----------+
| VARIABLE_NAME | VARIABLE_SOURCE | VARIABLE_PATH | MIN_VALUE | MAX_VALUE | SET_TIME | SET_USER | SET_HOST |
+---------------+-----------------+----------------------------------------------------------------+-----------+----------------------+----------+----------+----------+
| thread_stack | EXPLICIT | /home/malff/CODE/GIT/GIT_TRUNK/build-dbg/mysql-test/var/my.cnf | 131072 | 18446744073709550592 | NULL | NULL | NULL |
+---------------+-----------------+----------------------------------------------------------------+-----------+----------------------+----------+----------+----------+
1 row in set (0.00 sec)
Aqui o thread_stack é definido no arquivo my.cnf relatado.
Refman:
https://dev.mysql .com/doc/refman/8.0/en/performance-schema-variables-info-table.html