1436 – 线程栈溢出:使用131072字节堆栈的6136字节,需要128000字节。
错误1436对应于mysql 5.1代码中的ER_STACK_OVERRUN_NEED_MORE:
malff@linux-8edv:include> pwd
/home/malff/BZR_TREE/mysql-5.1/include
malff@linux-8edv: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));
从所看到的值,margin为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:
malff@linux-8edv:sql> pwd
/home/malff/BZR_TREE/mysql-5.1/sql
malff@linux-8edv:sql> grep STACK_MIN_SIZE *.h
mysql_priv.h:#define STACK_MIN_SIZE 16000 // Abort if less stack during eval.
到目前为止,一切都符合服务器的预期:
>代码执行一个触发器,它被实现
sp_head ::执行。
> 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二进制文件是如何编译的,看看是什么默认值:
malff@linux-8edv:sql> pwd
/home/malff/BZR_TREE/mysql-5.1/sql
malff@linux-8edv:sql> ./mysqld --no-defaults --verbose --help | grep thread_stack
...
--thread_stack=# The stack size for each thread.
thread_stack 262144
在我的系统上,我在64位平台上得到256K。
如果有不同的值,也许有人使用不同的编译选项构建服务器,例如-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库本身出现问题(从理论上讲)
阅读代码,我从来没有看过它)。
我希望这回答这个问题。
问候,
– 马克·阿尔夫
更新(2014-03-11),使“如何修复”更明显。
在很可能的情况下,在my.cnf文件中更改了thread_stack文件的默认值。
如何修复它是微不足道的,然后找到thread_stack在my.cnf文件中设置的位置,并删除该设置(相信服务器代码提供一个不错的默认值,所以下次不会再发生)或增加堆栈尺寸。