我在表上进行了非常简单的更新,这也触发了一个非常简单的触发器,这给了我错误
#1436 - Thread stack overrun: 6136 bytes used of a 131072 byte stack, and 128000 bytes needed.
我执行的查询:
UPDATE field_values SET value = 'asaf' WHERE field_values.id =1
值字段是一个text字段。因此,从理论上讲,它可能变得安静。在这种情况下情况并非如此。
text
正在执行的触发器是:
DELIMITER $$ CREATE TRIGGER field_value_update_trigger BEFORE UPDATE ON community_fields_values FOR EACH ROW BEGIN INSERT INTO user_field_log (user_id, field_id, value) VALUES (NEW.user_id, NEW.field_id, NEW.value); END; $$ DELIMITER ;
为什么显示此错误?好像没有涉及任何繁重的查询。另请注意,数据库几乎是空的,其中只有2行,community_fields_values而user_field_log
community_fields_values
user_field_log
MySQL版本:5.1.44
错误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中,函数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。
试图保留128000个字节的对check_stack_overrun()的唯一调用来自:
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.
到目前为止,一切都按预期对服务器起作用:
MySQL触发器执行所需的堆栈数量并不取决于触发器复杂性本身,也不取决于所涉及表的内容/结构。
在什么 真正 的问题是,我想,为什么只在128K(131072)的thread_stack。
在sql / mysqld.cc中,名为“ thread_stack”的服务器变量在C中作为“ my_thread_stack_size”实现:
{"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);
服务器代码调用:
长话短说,出现错误是因为thread_stack与服务器附带的默认值相比太小。可能会发生:
我希望这个回答这个问题。
问候-马克·阿尔夫
更新(2014-03-11),使“如何修复”更加明显。
这很可能是在my.cnf文件中更改了thread_stack文件的默认值。
然后,如何解决这个问题很简单,找到my.cnf文件中设置thread_stack的位置,然后删除设置(信任服务器代码以提供适当的默认值,这样下次就不会再发生这种情况)或增加堆栈尺寸。