テーブルで非常に簡単な更新を行っていますが、これも非常に簡単なトリガーをトリガーし、エラーが発生します
#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
フィールドです。したがって、理論的には静かに大きくなる可能性があります。この状況ではそうではありません。
実行されるトリガーは次のとおりです。
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 ;
このエラーが表示されるのはなぜですか?重いクエリが関係しているわけではありません。また、データベースはほとんど空で、community_fields_values
には2行しかなく、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));
表示された値から、マージンは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トリガーの実行に必要なスタックの量は、トリガーの複雑さ自体や、関係するテーブルのコンテンツ/構造に依存しません。
realの質問は、thread_stackが128K(131072)である理由です。
「thread_stack」という名前のサーバー変数は、sql/mysqld.ccの「my_thread_stack_size」としてCに実装されています。
{"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が設定されている場所を見つけ、設定を削除する(適切なデフォルト値を提供するためにサーバーコードを信頼するため、次回は再び発生しません)か、スタックを増やしますサイズ。
解決策ではありませんが、簡単な解決策は、my.cnfでthread_stackのサイズを増加させることです。
thread_stack = 256K
ユーザー "foo"が指摘したように、実際の問題を検出するには、トリガーコード全体をポストする方がより役立つ場合があります。