Ответ 1
1436 - Переполнение стека потоков: 6136 байт, используемых для стека 131072 байт, и требуется 128000 байт.
Ошибка 1436 соответствует значению ER_STACK_OVERRUN_NEED_MORE в коде 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
Код печати ошибки отображается в 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));
Из видимых значений маржа составляет 128000, а my_thread_stack_size - 131072.
Единственный вызов check_stack_overrun(), который пытается зарезервировать 128000 байт, - это:
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);
Значение STACK_MIN_SIZE равно 16000:
[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.
Пока все работает так, как ожидалось для сервера:
- код выполняет триггер, который реализуется с помощью sp_head:: Execute.
- время выполнения MySQL проверяет, что в стеке имеется не менее 128000 байт.
- эта проверка завершается неудачно (это правильно), и выполнение триггера заканчивается ошибкой.
Объем стека, необходимый для запуска триггера MySQL, зависит не от самой сложности триггера, а от содержания/структуры используемых таблиц.
Какой реальный вопрос, я думаю, почему thread_stack только на 128K (131072).
Серверная переменная с именем "thread_stack" реализована в C как "my_thread_stack_size" в 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 - минимальное значение для этого параметра. Значение по умолчанию - DEFAULT_THREAD_STACK, которое определено в 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
Итак, по умолчанию размер стека должен быть 192K (32 бита) или 256K (архитектуры 64 бит).
Сначала проверьте, как скомпилирован бинарный файл mysqld, чтобы узнать, что является значением по умолчанию:
[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
В моей системе я получил 256 КБ на 64-битной платформе.
Если существуют разные значения, возможно, кто-то построит сервер с различными параметрами компиляции, такими как -DDEFAULT_THREAD_STACK (или просто изменил исходный код)... Я бы спросил, откуда происходит двоичный файл.
Во-вторых, проверьте my.cnf на значения по умолчанию, указанные в самом файле конфигурации. Строка, устанавливающая значение в thread_stack явно (и с низким значением), окончательно приведет к ошибке.
Наконец, проверьте файл журнала сервера на наличие такой ошибки (см. sql/mysqld.cc):
sql_print_warning("Asked for %lu thread stack, but got %ld",
my_thread_stack_size, (long) stack_size);
Код сервера вызывает:
- pthread_attr_setstacksize(), чтобы установить размер стека
- pthread_attr_getstacksize(), чтобы проверить, сколько стека имеет поток и жалуется в журнале, если библиотека pthread используется меньше.
Короче говоря, ошибка видна, потому что thread_stack слишком мал по сравнению со значениями по умолчанию, поставляемыми с сервером. Это может произойти:
- при выполнении пользовательских сборок сервера с различными компиляциями Параметры
- при изменении значения по умолчанию в файле my.cnf
- если что-то пошло не так в самой библиотеке pthread (теоретически из читая код, я никогда не видел его сам).
Надеюсь, это ответ на вопрос.
С уважением, - Марк Альф
Update (2014-03-11), чтобы сделать "как исправить" более очевидным.
Что происходит, по всей вероятности, является то, что значение по умолчанию для файла thread_stack было изменено в файле my.cnf.
Как исправить это тривиально, найдите, где thread_stack установлен в файле my.cnf, и либо удалите параметр (доверяя серверному коду, чтобы обеспечить достойное значение по умолчанию, так что это не повторится в следующий раз) или увеличьте размер стека.