Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Kesalahan MySQL 1436:Tumpukan utas diserbu, dengan kueri sederhana

1436 - Overrun tumpukan utas:6136 byte digunakan dari tumpukan 131072 byte, dan dibutuhkan 128000 byte.

Kesalahan 1436 sesuai dengan ER_STACK_OVERRUN_NEED_MORE dalam kode mysql 5.1 :

[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

Pencetakan kode kesalahan yang terlihat ada di 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));

Dari nilai yang terlihat, margin adalah 128000, dan my_thread_stack_size adalah 131072.

Satu-satunya panggilan ke check_stack_overrun() yang mencoba mencadangkan 128000 byte adalah dari:

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

Nilai STACK_MIN_SIZE adalah 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.

Sejauh ini, semuanya berfungsi seperti yang diharapkan untuk server:

  • kode mengeksekusi pemicu, yang diimplementasikan withsp_head::execute.
  • waktu proses MySQL memeriksa bahwa setidaknya ada 128000 byte di tumpukan
  • pemeriksaan ini gagal (benar), dan eksekusi pemicu berakhir dengan kesalahan.

Jumlah tumpukan yang dibutuhkan oleh eksekusi pemicu MySQL tidak bergantung pada kompleksitas pemicu itu sendiri, atau konten/struktur tabel yang terlibat.

Apa yang nyata pertanyaannya adalah, saya kira, mengapa thread_stack hanya di 128K (131072).

Variabel server bernama 'thread_stack' diimplementasikan dalam C sebagai 'my_thread_stack_size' di 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 adalah nilai minimum untuk parameter ini. Nilai default adalah DEFAULT_THREAD_STACK, yang didefinisikan dalam 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

Jadi, secara default, ukuran tumpukan harus 192K (32bit) atau 256K (arsitektur 64bit).

Pertama, periksa bagaimana biner mysqld dikompilasi, untuk melihat apa nilai defaultnya:

[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

Di sistem saya, saya mendapatkan 256K pada platform 64 bit.

Jika ada nilai yang berbeda, mungkin seseorang membangun server dengan opsi kompilasi yang berbeda, seperti -DDEFAULT_THREAD_STACK (atau hanya memodifikasi sumbernya) ... Saya akan mempertanyakan dari mana biner itu berasal.

Kedua, periksa my.cnf untuk nilai default yang disediakan dalam file konfigurasi itu sendiri. Baris yang menetapkan nilai ke thread_stack secara eksplisit (dan dengan nilai rendah) pasti akan menyebabkan kesalahan terlihat.

Terakhir, periksa file log server untuk kesalahan seperti ini (lihat sql/mysqld.cc):

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

Kode server memanggil:

  • pthread_attr_setstacksize() untuk mengatur ukuran tumpukan
  • pthread_attr_getstacksize() untuk memverifikasi seberapa banyak tumpukan yang benar-benar dimiliki sebuah thread dan mengeluh di log jika pustaka pthread menggunakan lebih sedikit.

Singkat cerita, kesalahan terlihat karena thread_stack terlalu kecil dibandingkan dengan nilai default yang dikirimkan bersama server. Hal ini dapat terjadi:

  • saat melakukan pembuatan server khusus, dengan opsi kompilasi yang berbeda
  • saat mengubah nilai default di file my.cnf
  • jika ada yang tidak beres di perpustakaan pthread itu sendiri (secara teori dari membaca kode, saya belum pernah melihatnya sendiri).

Saya harap ini menjawab pertanyaan.

Salam,-- Marc Alff

Update (2014-03-11), untuk membuat "cara memperbaiki" lebih jelas.

Apa yang terjadi, kemungkinan besar, adalah bahwa nilai default untuk file thread_stack diubah di file my.cnf.

Cara memperbaikinya sepele, temukan di mana thread_stack diatur dalam file my.cnf, dan hapus pengaturannya (percaya kode server untuk memberikan nilai default yang layak, jadi ini tidak terjadi lagi lain kali) atau menambah tumpukan ukuran.

Pembaruan (2021-04-28), periksa dari mana thread_stack berasal:

Gunakan tabel performance_schema.variables_info untuk mengetahui dari mana variabel tertentu berasal.

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)

Di sini defaultnya adalah nilai pabrik (dikompilasi dalam biner mysqld).

Contoh lain:

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)

Di sini thread_stack diatur dalam file my.cnf yang dilaporkan.

Refman:

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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara Mengatur Replikasi Asinkron dari Galera Cluster ke server MySQL Standalone dengan GTID

  2. Masalah Java + Mysql UTF8

  3. MySQL bagaimana cara mengisi tanggal yang hilang dalam rentang?

  4. PHP dengan kesalahan MySQL 8.0+:Server meminta metode otentikasi yang tidak diketahui klien

  5. MySQL - Batasan Kunci Asing Bersyarat