Je fais une mise à jour très simple sur une table, qui déclenche également un déclencheur vraiment simple, et cela me donne l'erreur
#1436 - Thread stack overrun: 6136 bytes used of a 131072 byte stack, and 128000 bytes needed.
La requête que j'exécute:
UPDATE field_values SET value = 'asaf' WHERE field_values.id =1
Le champ de valeur est un champ text
. Donc, en théorie, cela pourrait devenir assez gros. Ce qui n'est pas le cas dans cette situation.
Le déclencheur qui s'exécute est:
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 ;
Pourquoi cette erreur s'affiche-t-elle? Ce n'est pas comme s'il y avait une requête lourde impliquée. Notez également que la base de données est presque vide, seulement 2 lignes dans community_fields_values
et aucune ligne dans le user_field_log
Version MySQL: 5.1.44
L'erreur 1436 correspond à ER_STACK_OVERRUN_NEED_MORE dans le code mysql 5.1:
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
Le code affichant l'erreur vue est dans sql/sql_parse.cc, fonction 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));
D'après les valeurs vues, la marge est 128000 et my_thread_stack_size est 131072.
Le seul appel à check_stack_overrun () qui essaie de réserver 128000 octets provient 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);
La valeur de STACK_MIN_SIZE est 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.
Jusqu'à présent, tout fonctionne comme prévu pour le serveur:
La quantité de pile nécessaire à l'exécution du déclencheur MySQL ne dépend pas de la complexité du déclencheur lui-même, ni du contenu/de la structure des tables impliquées.
Quelle est la question réelle, je suppose, pourquoi la thread_stack est-elle uniquement à 128K (131072).
La variable serveur nommée 'thread_stack' est implémentée en C comme 'my_thread_stack_size' dans 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 est la valeur minimale pour ce paramètre. La valeur par défaut est DEFAULT_THREAD_STACK, qui est définie dans 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
Ainsi, par défaut, la taille de la pile doit être de 192 Ko (32 bits) ou 256 Ko (architectures 64 bits).
Tout d'abord, vérifiez comment le binaire mysqld a été compilé, pour voir quelle est la valeur par défaut:
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
Sur mon système, j'ai obtenu 256 Ko sur une plate-forme 64 bits.
S'il y a des valeurs différentes, peut-être que quelqu'un construit le serveur avec différentes options de compilation, comme -DDEFAULT_THREAD_STACK (ou juste modifié la source) ... Je me demande d'où vient le binaire dans ce cas.
Deuxièmement, vérifiez my.cnf pour les valeurs par défaut fournies dans le fichier de configuration lui-même. Une ligne définissant une valeur à thread_stack explicitement (et avec une valeur faible) provoquerait définitivement l'erreur vue.
Enfin, vérifiez le fichier journal du serveur pour une erreur comme celle-ci (voir sql/mysqld.cc):
sql_print_warning("Asked for %lu thread stack, but got %ld",
my_thread_stack_size, (long) stack_size);
Le code serveur appelle:
Pour faire court, l'erreur est constatée car le thread_stack est trop petit par rapport aux valeurs par défaut fournies avec le serveur. Cela peut arriver:
J'espère que cela répond à la question.
Cordialement, - Marc Alff
Mise à jour (2014-03-11), pour rendre plus évident le "comment réparer".
Ce qui se passe, selon toute vraisemblance, c'est que la valeur par défaut du fichier thread_stack a été modifiée dans le fichier my.cnf.
Comment résoudre ce problème est alors trivial, recherchez où thread_stack est défini dans le fichier my.cnf et supprimez le paramètre (en faisant confiance au code du serveur pour fournir une valeur par défaut décente, donc cela ne se reproduira pas la prochaine fois) ou augmentez la pile Taille.
Bien que ce ne soit pas une solution, mais une solution rapide pourrait être d'augmenter la taille de thread_stack en l'incrémentant dans votre my.cnf:
thread_stack = 256K
Comme l'a souligné l'utilisateur "foo", la publication de l'intégralité du code de déclenchement pourrait être plus utile pour détecter le vrai problème.