sql >> Database teknologi >  >> RDS >> Mysql

MySQL-fejl 1436:Overløb af trådstak med simpel forespørgsel

1436 - Overløb af trådstak:6136 bytes brugt af en 131072 bytestak og 128000 bytes nødvendige.

Fejlen 1436 svarer til ER_STACK_OVERRUN_NEED_MORE i mysql 5.1-koden :

[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

Koden, der udskriver den set fejl, er i 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));

Ud fra de sete værdier er marginen 128000, og my_thread_stack_size er 131072.

Det eneste kald til check_stack_overrun(), der forsøger at reservere 128000 bytes, er fra:

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);

Værdien af ​​STACK_MIN_SIZE er 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.

Indtil videre fungerer alt som forventet for serveren:

  • koden udfører en trigger, som er implementeret med sp_head::execute.
  • MySQL runtime kontrollerer, at der er mindst 128000 bytes på stakken
  • denne kontrol mislykkes (med rette), og triggerudførelsen slutter med en fejl.

Mængden af ​​stak, der kræves af MySQL-triggerudførelsen, afhænger ikke af selve triggerkompleksiteten eller indholdet/strukturen af ​​de involverede tabeller.

Hvad det rigtige spørgsmålet er, gætter jeg på, hvorfor thread_stack kun er på 128K (131072).

Servervariablen med navnet 'thread_stack' er implementeret i C som 'my_thread_stack_size' i 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 er minimumsværdien for denne parameter. Standardværdien er DEFAULT_THREAD_STACK, som er defineret i 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

Så som standard skal stakstørrelsen være 192K (32bits) eller 256K (64bits arkitekturer).

Først skal du kontrollere, hvordan mysqld-binæren blev kompileret, for at se, hvad der er standardværdien:

[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

På mit system fik jeg 256K på en 64 bit platform.

Hvis der er forskellige værdier, er der måske nogen, der bygger serveren med forskellige kompileringsmuligheder, såsom -DDEFAULT_THREAD_STACK (eller bare har ændret kilden) ... Jeg vil stille spørgsmålstegn ved, hvor binæren kommer fra i så fald.

For det andet, tjek my.cnf for standardværdier, der er angivet i selve konfigurationsfilen. En linje, der udtrykkeligt indstiller en værdi til thread_stack (og med en lav værdi), vil definitivt forårsage fejlen set.

Til sidst skal du kontrollere serverlogfilen for en fejl som denne (se sql/mysqld.cc) :

sql_print_warning("Asked for %lu thread stack, but got %ld",
                  my_thread_stack_size, (long) stack_size);

Serverkoden kalder:

  • pthread_attr_setstacksize() for at indstille stakstørrelsen
  • pthread_attr_getstacksize() for at bekræfte, hvor meget stak en tråd egentlig har og klager i loggen, hvis pthread-biblioteket brugte mindre.

Lang historie kort, fejlen ses, fordi thread_stack er for lille sammenlignet med standardværdierne, der leveres med serveren. Dette kan ske:

  • når du laver brugerdefinerede builds af serveren, med forskellige kompileringsmuligheder
  • når du ændrer standardværdien i my.cnf-filen
  • hvis noget gik galt i selve pthread-biblioteket (i teorien efter at have læst koden, har jeg aldrig set det selv).

Jeg håber, at dette besvarer spørgsmålet.

Med venlig hilsen-- Marc Alff

Opdatering (2014-03-11), for at gøre "hvordan rettes" mere indlysende.

Det, der efter al sandsynlighed foregår, er, at standardværdien for thread_stack-filen blev ændret i my.cnf-filen.

Det er trivielt, hvordan man løser det, find hvor thread_stack er sat i my.cnf-filen, og fjern enten indstillingen (ved at stole på, at serverkoden giver en anstændig standardværdi, så dette ikke sker igen næste gang) eller øg stakken. størrelse.

Opdater (2021-04-28), tjek hvor trådstakken kommer fra:

Brug tabellen performance_schema.variables_info for at finde ud af, hvor en given variabel kommer fra.

mysql> select * from variables_info where VARIABLE_NAME = 'thread_stack';
+---------------+-----------------+---------------+-----------+----------------------+----------+----------+----------+
| VARIABLE_NAME | VARIABLE_SOURCE | VARIABLE_PATH | MIN_VALUE | MAX_VALUE            | SET_TIME | SET_USER | SET_HOST |
+---------------+-----------------+---------------+-----------+----------------------+----------+----------+----------+
| thread_stack  | COMPILED        |               | 131072    | 18446744073709550592 | NULL     | NULL     | NULL     |
+---------------+-----------------+---------------+-----------+----------------------+----------+----------+----------+
1 row in set (0.01 sec)

Her er standardværdien fabriksværdien (kompileret i mysqld binær).

Et andet eksempel:

mysql> select * from variables_info where VARIABLE_NAME = 'thread_stack';
+---------------+-----------------+----------------------------------------------------------------+-----------+----------------------+----------+----------+----------+
| VARIABLE_NAME | VARIABLE_SOURCE | VARIABLE_PATH                                                  | MIN_VALUE | MAX_VALUE            | SET_TIME | SET_USER | SET_HOST |
+---------------+-----------------+----------------------------------------------------------------+-----------+----------------------+----------+----------+----------+
| thread_stack  | EXPLICIT        | /home/malff/CODE/GIT/GIT_TRUNK/build-dbg/mysql-test/var/my.cnf | 131072    | 18446744073709550592 | NULL     | NULL     | NULL     |
+---------------+-----------------+----------------------------------------------------------------+-----------+----------------------+----------+----------+----------+
1 row in set (0.00 sec)

Her er trådstakken sat i den rapporterede my.cnf-fil.

Refman:

https://dev.mysql .com/doc/refman/8.0/en/performance-schema-variables-info-table.html



  1. Sådan køres Opret tabel DDL med UDFØR STRAKS i Oracle-databasen

  2. psql:FATAL:database <bruger> eksisterer ikke

  3. Partitionsfunktion COUNT() OVER mulig ved brug af DISTINCT

  4. Almindelige fejl i DBA i MS SQL Server