Bagaimana Anda memeriksa apakah cache kueri mysql diaktifkan?

Posting blog ini dimotivasi oleh diskusi internal tentang cara menonaktifkan sepenuhnya cache kueri di MySQL

Menurut , kita seharusnya dapat menonaktifkan “Query Cache” dengan cepat dengan mengubah query_cache_type  menjadi 0, tetapi seperti yang akan kita lakukan . Blog ini akan menunjukkan kepada Anda cara menonaktifkan "cache kueri" dengan benar, dan bagaimana praktik umum mungkin tidak sebaik yang kami kira.

Bisakah kita menonaktifkannya dengan mengubah variabel, atau memerlukan restart untuk menghindari mutex global?

Beberapa konteks Cache Kueri

Cache kueri menyimpan teks pernyataan "Pilih" bersama dengan hasil terkait yang dikirim ke klien. Jika pernyataan yang identik diterima nanti, server mengambil hasilnya dari cache kueri daripada mem-parsing dan mengeksekusi pernyataan itu lagi. Cache kueri dibagikan di antara sesi, sehingga kumpulan hasil yang dihasilkan oleh satu klien dapat dikirim sebagai tanggapan atas kueri yang sama yang dikeluarkan oleh klien lain

Namun, kueri yang dapat di-cache mengambil "kunci eksklusif" di cache kueri MySQL. Selain itu, penyisipan, pemutakhiran, penghapusan, atau modifikasi lain apa pun pada tabel menyebabkan entri apa pun yang relevan dalam cache kueri dihapus. Jika Anda melihat banyak "Menunggu kunci cache kueri" di daftar proses, Anda mungkin menderita kunci eksklusif ini. Dalam posting blog ini, Anda dapat melihat bagaimana mutex global dalam konkurensi tinggi ini dapat menyebabkan penurunan kinerja

Jika kita menghadapi situasi ini, bagaimana kita bisa menonaktifkannya?

Menonaktifkan Cache Kueri

Ada dua opsi yang dapat Anda ubah. query_cache_type  dan query_cache_size.

Jadi jika kita mengubah query_cache_size  menjadi “0”, apakah itu berarti cache dinonaktifkan? query_cache_type? Or both? And does MySQL require a restart to avoid the global mutex?

Kode sumber menunjukkan ini kepada kita

kirim_hasil_ke_klien

Kerang

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

int Cache_kueri. . send_result_to_client(THD * thd, const LEX_CSTRING &sql)

{

ulonglong engine_data;

  Kueri_cache_kueri * kueri;

#ifndef EMBEDDED_LIBRARY

  Blokir_cache_kueri * blok_result_pertama;

#berakhir jika

  Query_cache_block * result_block;

  Query_cache_block_table * block_table, *block_table_end;

  char * cache_key = NULL;

  size_t tot_length;

  Query_cache_query_flags tanda;

  DBUG_ENTER("Query_cache. send_result_to_client");

 

   /*

    Pengujian 'query_cache_size' tanpa a lock here is safe: the benda

    kami dapat lepas adalah that the query won't be served from cache, but we

    simpan di mutex mengunci in the case when query cache is disabled.

    Lihat juga a catatan on double-check locking usage above.

   */

  jika (dinonaktifkan() |. thd - >locked_tables_mode . .

      thd - >variabel.query_cache_type == 0 . . query_cache_size == 0)

    goto err;

. . .

MySQL akan memeriksa apakah cache kueri diaktifkan sebelum menguncinya. Itu memeriksa empat kondisi, dan salah satunya harus benar. Tiga yang terakhir mungkin sudah jelas, tapi apa fungsi “is_disabled()”? .  

C

1

2

3

batal disable_query_cache(batal) { m_query_cache_is_disabled= TRUE; }

. . .

bool dinonaktifkan(batal) { return m_query_cache_is_disabled; }

Kueri_cache

C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

batal Cache_kueri. . init()

{

  DBUG_ENTER("Query_cache. init");

  mysql_mutex_init(key_structure_guard_mutex,

                   &structure_guard_mutex, MY_MUTEX_INIT_FAST);

  mysql_cond_init(key_COND_cache_status_changed,

                  &COND_cache_status_changed);

  m_cache_lock_status = Cache_kueri. . BUKA KUNCI;

  diinisialisasi = 1;

  /*

Jika kita secara eksplisit mematikan query cache dari command line, query cache akan

dinonaktifkan untuk pengingat waktu hidup server. Ini karena kita

ingin menghindari mengunci mutex khusus QC jika cache kueri tidak mau

digunakan

*/

  jika (variabel_sistem_global. query_cache_type == 0)

    query_cache. disable_query_cache();

 

  DBUG_VOID_RETURN;

}

Jika variabel_sistem_global. query_cache_type == 0  kondisi benar akan memanggil  disable_query_cache . Artinya, jika kita menyetel   function, which sets m_query_cache_is_disabled = True, so is_disabled going to be “True”. That means if we are setting query_cache_type  ke 0 pada waktu proses, itu akan menghilangkan mutex global. Mari jalankan beberapa pengujian untuk mengonfirmasi hal ini dan lihat apakah global mutex menghilang setelah mengubah query_cache_type  menjadi 0.

Menjalankan tes

Konteks pada tes

  1. Kami menjalankan tes OLTP sederhana menggunakan sysbench sebagai berikut

Kerang

1

sysbench -- tes = "/usr/ . lua" -- laporan - interval=1 --max-time=120 --oltp-read-only=off --max-requests=0 --num-threads=4 --oltp-table-size=2000000 --mysql-host=localhost --mysql-db=test --db-driver=mysql --mysql-user=root run

  1. Bagian penting dari saya. file cnf

Kerang

1

2

3

4

query_cache_type = 1

query_cache_limit = 1jt

query_cache_size = 1G

performance_schema_instrument = 'wait/synch/%Query_cache%=COUNTED'

Bagaimana Anda memeriksa apakah cache kueri mysql diaktifkan?

Jadi pada dasarnya pengujian dijalankan selama dua menit masing-masing saat bermain dengan query_cache_type  dan query_cache_size.

  1. Memulai MySQL dengan query_cache_type = 1  dan query_cache_size=1G.
  2. Ubah query_cache_type  menjadi 0. Seperti yang kita lihat tidak ada yang berubah, MySQL masih menggunakan cache kueri.
  3. Tetapi ketika kami menghentikan sysbench dan memulai lagi (menutup dan membuka koneksi baru), kami dapat melihat tidak ada lagi penyisipan yang masuk ke cache kueri. Namun kami masih dapat melihat kueri seperti “Not Cache” yang berarti mengubah query_cache_type  berlaku hanya untuk koneksi baru, dan kami masih dapat melihat beberapa mutex.
  4. Memulai ulang MySQL dengan query_cache_type = 0  dan query_cache_size=0. Finally, we disabled the query cache and all the mutex is disappeared.
  5. Mulai ulang MySQL dengan cache kueri diaktifkan
  6. Kami mengubah query_cache_size = 0  dan hampir berhasil .
  7. Mengubah query_cache_type = 0  dan memulai ulang sysbench tidak .

Jadi, satu-satunya cara untuk menghentikan aktivitas apa pun di sekitar cache kueri memerlukan memulai ulang MySQL dengan query_cache_type = 0 . Menonaktifkannya atau bahkan menyetelnya ke "0" saat runtime tidak sepenuhnya menghentikan aktivitas mutex.   and query_cache_size=0. Disabling it or even set it to “0” on runtime is not completely stopping mutex activity.

Tetapi mengapa kita masih membutuhkan query_cache_size  sementara dalam teori query_cache_type should be enough?

Seperti yang dirujuk di atas, manual mengatakan jika query_cache_type = 0

Jangan menyimpan hasil dalam cache atau mengambil hasil dari cache kueri. Perhatikan bahwa ini tidak membatalkan alokasi buffer cache kueri. Untuk melakukannya, Anda harus menyetel query_cache_size ke 0

Berdasarkan pengujian kami, jika kami mengubah query_cache_type  menjadi 0, itu masih mengenai cache.

Jadi Anda mungkin berpikir “baiklah, saya tidak mengaktifkan cache kueri dan menggunakan default untuk tetap menonaktifkannya. ” Teruslah membaca, karena Anda mungkin salah. Menurut , mulai dari 5. 6. 8 query_cache_type = 0  disetel secara default, tetapi query_cache_size= 1048576  (1MB). This means that if we keep default configuration, we will still see activity in the query cache as follows:

Kerang

1

2

3

4

5

6

7

8

9

10

11

12

13

mysql - e "tampilkan status global seperti 'qca%';"

+---------------------------------------+---------+

. Nama_Variabel . Nilai .

+---------------------------------------+---------+

. Qcache_free_blocks . 1 .

. Qcache_free_memory . 1031320 .

. Qcache_hits . 0 .

. Qcache_inserts . 0 .

. Qcache_lowmem_prunes . 0 .

. Qcache_not_cached . 423294 .

. Qcache_queries_in_cache . 0 .

. Qcache_total_blocks . 1 .

+---------------------------------------+---------+

Tetapi jika kita hanya menambahkan query_cache_size = 0   ke . cnf dan periksa lagi (tentu saja setelah me-restart server).

Kerang

1

2

3

4

5

6

7

8

9

10

11

12

13

mysql - e "tampilkan status global seperti 'qca%';"

+---------------------------------------+-------+

. Nama_Variabel . Nilai .

+---------------------------------------+-------+

. Qcache_free_blocks . 0 .

. Qcache_free_memory . 0 .

. Qcache_hits . 0 .

. Qcache_inserts . 0 .

. Qcache_lowmem_prunes . 0 .

. Qcache_not_cached . 0 .

. Qcache_queries_in_cache . 0 .

. Qcache_total_blocks . 0 .

+---------------------------------------+-------+

Kami akhirnya tidak mendapatkan aktivitas terkait cache kueri sama sekali. Berapa banyak overhead yang disebabkan oleh ini?
Sekarang kami bertanya-tanya apakah kasus ini memerlukan laporan bug. Pantau terus, kami akan segera menerbitkan hasilnya di pos

Menggali lebih banyak kode

Mari kita lihat  fungsi. MySQL menggunakan fungsi ini untuk menyimpan kueri dalam cache kueri. Jika kita membaca kode kita dapat menemukan ini

C

1

2

jika (thd - >locked_tables_mode |. query_cache_size == 0)

    DBUG_VOID_RETURN;

Ini hanya memeriksa query_cache_size , tidak memeriksa jenis. Store Query is called in , which also does not check the query_cache_type .

Kesimpulan

Ada kontradiksi antara memeriksa cache kueri dan menyimpan data di cache kueri, yang memerlukan penyelidikan lebih lanjut. Namun seperti yang dapat kita lihat, tidak mungkin untuk sepenuhnya menonaktifkan cache kueri dengan cepat dengan mengubah query_cache_type   atau/dan query_cache_size to 0. Based on the code and the tests, if you want to make sure the query cache is fully disabled, change query_cache_size  dan query_cache_type to 0 and restart MySQL.

Adalah fakta yang diketahui bahwa cache kueri dapat menjadi titik perdebatan yang besar, dan kami tidak mencoba untuk membandingkan overhead kinerja karena ini sebagian besar bergantung pada jenis beban kerja. Namun, kami masih dapat melihat beberapa overhead jika cache kueri tidak sepenuhnya dinonaktifkan saat MySQL dimulai

Bagaimana cara memeriksa cache di MySQL?

MySQL menentukan kueri untuk di-cache dengan memeriksa variabel query_cache_type . Menyetel nilai ini ke 0 atau MATI mencegah caching atau pengambilan kueri yang disimpan dalam cache. Anda juga dapat menyetelnya ke 1 untuk mengaktifkan caching untuk semua kueri kecuali yang dimulai dengan pernyataan SELECT SQL_NO_CACHE.

Bagaimana cara mengaktifkan cache MySQL?

Keluar dari MySQL. Buka terminal dan jalankan perintah berikut untuk membuka file konfigurasi MySQL. Kami telah mengaktifkan cache kueri dengan menyetel variabel query_cache_type ke 1, dengan cache kueri individual sebesar 256Kb dan total cache sebesar 10Mb .

Bagaimana cara saya memeriksa apakah kueri MySQL sedang berjalan?

Untuk melihat kueri mana yang aktif dijalankan untuk instans DB MySQL di Amazon RDS, ikuti langkah-langkah ini. .
Sambungkan ke instans DB yang menjalankan MySQL
Jalankan perintah berikut. TAMPILKAN DAFTAR PROSES LENGKAP\G. .
Atau, jalankan kueri berikut untuk mengambil kumpulan hasil yang sama

Bagaimana cara menonaktifkan cache MySQL?

Jadi, satu-satunya cara untuk menghentikan aktivitas apa pun di sekitar cache kueri memerlukan memulai ulang MySQL dengan query_cache_type = 0 dan query_cache_size=0 .