MySQL: Terkadang itu bukan database

Database


Latensi kueri di pusat data lebih besar daripada di tempat lain untuk hierarki replikasi, tetapi hanya di persentil atas. Ini memengaruhi produksi dan lalu lintas dari pusat data yang gagal melindungi produksi.

Ketika P50 dan P90 terlihat baik-baik saja, tetapi P99 dan P99.9 tidak, database bekerja secara normal dan hanya beberapa kueri yang lambat. Dugaan awal adalah bahwa “untuk beberapa pertanyaan, rencana telah berubah, tetapi hanya di pusat data itu.”

Tapi pertama-tama mari kita lihat ukuran dan skema database.

Skema yang dimaksud mempertahankan metadata untuk proses pengumpulan data perubahan, dan itu tidak banyak.

# du -sh *
0    coredumps
5.6G    data
704M    log
0    tmp
# du -sh data/theschema
93M    data/theschema

Dan sebagai pengingat:

Proses mysqld memiliki RES (resident set size) hanya 5,9 GB, padahal database diperbolehkan memiliki VIRT (virtual memory size) 71,8 G.

Saat ini berjalan pada pisau logam telanjang dan ini tidak datang lebih kecil. Dalam mesin virtual, ini bisa sekecil 1/4 blade – tetapi instance database memiliki overhead yang konstan dan hampir tidak masuk akal untuk menjadi lebih kecil.

Either way, itu kehabisan memori, bahkan jika itu di-host di iPhone. Tidak mungkin untuk memindai disk, bahkan jika ada kueri yang buruk. Dan bahkan dengan pemindaian memori, sesuatu yang kecil ini tidak melelahkan CPU atau memindai memori untuk waktu yang lama. Pasti ada yang berbau aneh di sekitar sini.

[information_schema]> select table_name, table_rows from tables where table_schema = 'schemaregistry' order by table_rows desc;
+--------------------+------------+
| TABLE_NAME         | TABLE_ROWS |
+--------------------+------------+
| table_01           |      14376 |
| table_02           |       9510 |
| table_03           |       3079 |
| table_04           |         84 |
| table_05           |          0 |
| db_waypoint        |          0 |
+--------------------+------------+
6 rows in set (0.00 sec)

Kita gunakan performance_schema Langsung meminta statistik untuk kueri yang telah dilihat dan lambat.

[performance_schema]> select 
     -> user, 
     -> event_name, 
     -> count_star, 
     -> avg_timer_wait/1000000000 as avg_ms 
     -> from events_statements_summary_by_user_by_event_name 
     -> where user = 'production_username'
     -> and event_name like  'statement/sql/%' and count_star > 0;
+----------------------+-----------------------------+------------+--------+
| user                 | event_name                  | count_star | avg_ms |
+----------------------+-----------------------------+------------+--------+
| production_username  | statement/sql/select        |   42121722 | 0.2913 |
| production_username  | statement/sql/set_option    |     270284 | 0.0708 |
| production_username  | statement/sql/show_warnings |      67571 | 0.0498 |
+----------------------+-----------------------------+------------+--------+
3 rows in set (0.01 sec)

P_S Tidak dimaksudkan untuk penggunaan manusia secara langsung. Tabel dioptimalkan untuk pengumpulan data yang cepat. Data tidak dikunci selama pembacaan agar tidak memperlambat pengumpulan, waktu dilaporkan dalam PicoSeconds (1/10^12) untuk menghindari instruksi DIV apa pun pada penulisan, dan buffer dibatasi dalam ukuran jadi jika beberapa tindakan adalah spam. P_Sdata hilang, tetapi server tidak melambat atau kehabisan memori.

Kami membagi hasilnya dengan 10^9 untuk mendapatkan waktu eksekusi pernyataan rata-rata, dan melaporkan statistik pernyataan apa pun sejak server mulai (atau pemotongan tabel) dikumpulkan untuk setiap pernyataan. Tampaknya pengguna produksi hanya menjalankan perintah pilih, setel perintah, dan tampilkan peringatan.

Sementara rata-rata terlihat bagus, maxima tidak:

[performance_schema]> select 
     -> event_name, 
     -> count_star, 
     -> avg_timer_wait/1000000000 as avg_ms, 
     -> max_timer_wait/1000000000 as max_ms 
     -> from events_statements_summary_by_user_by_event_name 
     -> where user = 'production_username' 
     -> and event_name like  'statement/sql/%' and count_star > 0;
+-----------------------------+------------+--------+------------+
| event_name                  | count_star | avg_ms | max_ms     |
+-----------------------------+------------+--------+------------+
| statement/sql/select        |   42121722 | 0.2913 | 14934.0024 |
| statement/sql/set_option    |     270284 | 0.0708 |     1.2732 |
| statement/sql/show_warnings |      67571 | 0.0498 |     0.9574 |
+-----------------------------+------------+--------+------------+
3 rows in set (0.00 sec)

Jadi ada pernyataan pilih yang menjalankan 14-an besar pada database yang tidak memiliki tabel dengan lebih dari 15k baris.

Kami memasukkan hierarki ini ke Vividcortex, monitor yang mengumpulkan data kinerja dari database dan memungkinkan kami melihat kueri spesifik yang berjalan lambat. Ini juga dapat membantu menentukan kemungkinan perbaikan.

Inventaris Vividcortex untuk streaming. Biasanya Vividcortex tidak akan dijalankan pada semua sampel, tetapi versi awal dan mockup yang diciutkan akan dijalankan. Namun, kami menginginkan replika khusus di Frankfurt, jadi sesuatu dengan nomor 6000.

Instalasi Vividcortex tipikal kami menginstal probe pada versi utama dan replika gabungan, karena kami tidak perlu mengisi antarmuka koleksi dengan semua permintaan dari semua mesin produksi. Sebuah contoh akan dilakukan.

Dalam hal ini, kami ingin salinan di lokasi tertentu: hanya satu pusat data yang berperilaku tidak normal, jadi kami ingin mesin lain di lokasi itu. Itu membutuhkan seni boneka khusus, tetapi berhasil. Namun, meskipun demikian, kami tidak mendapatkan kueri yang sangat menarik:

Kami mendapatkan jumlah kueri dan latensi rata-rata. Tetapi kita dapat melihat dari hitungan dan kata rata-rata bahwa ini tidak berguna: kami ingin melihat persentil atas. Juga, tidak semua pertanyaan menarik.

Sekarang, kami percaya bahwa sebagian besar kueri baik-baik saja, hanya beberapa contoh kueri yang sebagian besar baik-baik saja membutuhkan waktu lama yang tidak terduga. Dan kami ingin melihat mereka.

Kita sudah dapat melihat bahwa tampilan VividCortex default tidak berguna di sini, dan penjelajahan cepat dari antarmuka pengguna dengan cepat mengungkapkan bahwa alat ini mungkin tidak berguna untuk perburuan khusus kita.

Kami kembali ke P_S Dan buat barang-barang kami dengan tangan

Mari kita lihat apa yang ada di menu:

[performance_schema]> show tables like '%statement%';
+----------------------------------------------------+
| Tables_in_performance_schema (%statement%)         |
+----------------------------------------------------+
| events_statements_current                          |
| events_statements_histogram_by_digest              |
| events_statements_histogram_global                 |
| events_statements_history                          |
| events_statements_history_long                     |
| events_statements_summary_by_account_by_event_name |
| events_statements_summary_by_digest                |
| events_statements_summary_by_host_by_event_name    |
| events_statements_summary_by_program               |
| events_statements_summary_by_thread_by_event_name  |
| events_statements_summary_by_user_by_event_name    |
| events_statements_summary_global_by_event_name     |
| prepared_statements_instances                      |
+----------------------------------------------------+
13 rows in set (0.00 sec)

Saya tidak tahu tentang Anda, meskipun events_statements_summary_by_digest Kelihatannya enak menurutku Apa isinya?

[performance_schema]> desc events_statements_summary_by_digest;
+-----------------------------+-----------------+------+-----+---------+-------+
| Field                       | Type            | Null | Key | Default | Extra |
+-----------------------------+-----------------+------+-----+---------+-------+
| SCHEMA_NAME                 | varchar(64)     | YES  | MUL | NULL    |       |
| DIGEST                      | varchar(64)     | YES  |     | NULL    |       |
| DIGEST_TEXT                 | longtext        | YES  |     | NULL    |       |
| COUNT_STAR                  | bigint unsigned | NO   |     | NULL    |       |
| SUM_TIMER_WAIT              | bigint unsigned | NO   |     | NULL    |       |
| MIN_TIMER_WAIT              | bigint unsigned | NO   |     | NULL    |       |
| AVG_TIMER_WAIT              | bigint unsigned | NO   |     | NULL    |       |
| MAX_TIMER_WAIT              | bigint unsigned | NO   |     | NULL    |       |
| SUM_LOCK_TIME               | bigint unsigned | NO   |     | NULL    |       |
| SUM_ERRORS                  | bigint unsigned | NO   |     | NULL    |       |
| SUM_WARNINGS                | bigint unsigned | NO   |     | NULL    |       |
| SUM_ROWS_AFFECTED           | bigint unsigned | NO   |     | NULL    |       |
| SUM_ROWS_SENT               | bigint unsigned | NO   |     | NULL    |       |
| SUM_ROWS_EXAMINED           | bigint unsigned | NO   |     | NULL    |       |
| SUM_CREATED_TMP_DISK_TABLES | bigint unsigned | NO   |     | NULL    |       |
| SUM_CREATED_TMP_TABLES      | bigint unsigned | NO   |     | NULL    |       |
| SUM_SELECT_FULL_JOIN        | bigint unsigned | NO   |     | NULL    |       |
| SUM_SELECT_FULL_RANGE_JOIN  | bigint unsigned | NO   |     | NULL    |       |
| SUM_SELECT_RANGE            | bigint unsigned | NO   |     | NULL    |       |
| SUM_SELECT_RANGE_CHECK      | bigint unsigned | NO   |     | NULL    |       |
| SUM_SELECT_SCAN             | bigint unsigned | NO   |     | NULL    |       |
| SUM_SORT_MERGE_PASSES       | bigint unsigned | NO   |     | NULL    |       |
| SUM_SORT_RANGE              | bigint unsigned | NO   |     | NULL    |       |
| SUM_SORT_ROWS               | bigint unsigned | NO   |     | NULL    |       |
| SUM_SORT_SCAN               | bigint unsigned | NO   |     | NULL    |       |
| SUM_NO_INDEX_USED           | bigint unsigned | NO   |     | NULL    |       |
| SUM_NO_GOOD_INDEX_USED      | bigint unsigned | NO   |     | NULL    |       |
| SUM_CPU_TIME                | bigint unsigned | NO   |     | NULL    |       |
| COUNT_SECONDARY             | bigint unsigned | NO   |     | NULL    |       |
| FIRST_SEEN                  | timestamp(6)    | NO   |     | NULL    |       |
| LAST_SEEN                   | timestamp(6)    | NO   |     | NULL    |       |
| QUANTILE_95                 | bigint unsigned | NO   |     | NULL    |       |
| QUANTILE_99                 | bigint unsigned | NO   |     | NULL    |       |
| QUANTILE_999                | bigint unsigned | NO   |     | NULL    |       |
| QUERY_SAMPLE_TEXT           | longtext        | YES  |     | NULL    |       |
| QUERY_SAMPLE_SEEN           | timestamp(6)    | NO   |     | NULL    |       |
| QUERY_SAMPLE_TIMER_WAIT     | bigint unsigned | NO   |     | NULL    |       |
+-----------------------------+-----------------+------+-----+---------+-------+
37 rows in set (0.00 sec)

Pada titik ini mungkin ide yang baik untuk berhenti dan menetapkan beberapa fakta tentangnya P_S.
P_S Mengumpulkan data yang terkait dengan eksekusi perintah dan kinerja server.

[performance_schema]> show tables like 'setup%';
+---------------------------------------+
| Tables_in_performance_schema (setup%) |
+---------------------------------------+
| setup_actors                          |
| setup_consumers                       |
| setup_instruments                     |
| setup_objects                         |
| setup_threads                         |
+---------------------------------------+

Server adalah alat untuk pengumpulan, dan sumber data disebut alat.

Kami dapat meminta alat untuk mengumpulkan atau tidak mengumpulkan data untuk pengguna regulasi tertentu, aktor tertentu. Kita juga bisa meminta alat untuk mengabaikan objek tertentu, seperti tabel, skema, atau hal lainnya. Dan lagi sama untuk bidang tertentu.

Data yang dikumpulkan disimpan dalam buffer cincin yang telah dialokasikan sebelumnya atau ditambahkan ke koleksi tertentu. Semua hal ini memakan.

Konfigurasi dilakukan melalui tabel setup di atas, yang mengatur aliran data dari instrumen ke konsumen melalui dimensi filter.

Pengumpulan data peristiwa terjadi di tabel peristiwa, dalam hierarki, dari transaksi, pernyataan individual yang membentuk transaksi, hingga langkah-langkah eksekusi perintah, langkah, hingga menunggu (kebanyakan untuk IO atau kunci). Hal-hal ini bersarang, tetapi tidak harus berdasarkan 1:1 – misalnya, ekspresi dapat berisi harapan atau pernyataan lain.

root@streamingdb-6001 [performance_schema]> show tables like 'event%current';
+----------------------------------------------+
| Tables_in_performance_schema (event%current) |
+----------------------------------------------+
| events_stages_current                        |
| events_statements_current                    |
| events_transactions_current                  |
| events_waits_current                         |
+----------------------------------------------+
4 rows in set (0.00 sec)

Untuk setiap acara ini, kami memiliki _current, _history Dan _history_long Tabel misalnya events_statements_current Berisi satu entri untuk setiap koneksi aktif. events_statements_history Beberapa istilah terakhir untuk setiap koneksi aktif, dan events_statements_history_long Beberapa ribu kata terakhir di semua koneksi.

Ada koleksi lain tentang aspek lain dari server dan kumpulan pernyataan yang lebih umum, ringkasan.

Untuk dapat menjumlahkan ekspresi, ada konsep ekspresi digest_textdan akhirnya digestnomor hash yang dihasilkan dari teks ringkasan.

Jadi kalimat seperti

select id from atable where id in ( 1, 2, 3)
SeLeCt id FROM atable where id IN (92929, 29292, 17654, 363562);

harus dipertimbangkan dalam jumlah yang setara. Ini dilakukan dengan mengurai perintah dari pohon parse, yang menghilangkan semua perbedaan spasi dan huruf dalam kata kunci. Selama ini, semua konstanta dan daftar konstan dengan ? Atau '?' Masing-masing.

Teks ringkasan dikonversi untuk dua istilah di atas

select id from atable where id in ( ? )

Dan ringkasannya dapat dihasilkan dengan menjalankan fungsi hash pada teks ringkasan.

Kelemahannya adalah Anda tidak dapat menjelaskan intisari dengannya EXPLAIN perintah, jadi kita perlu memastikan untuk menyimpan versi kueri yang dapat ditafsirkan juga.

tentang kami, events_statements_summary_by_digest Itulah yang kami inginkan jadi kami mempersingkat set, dan menunggu sebentar, lalu meminta. Hasilnya tidak mungkin:

[performance_schema]> truncate events_statements_summary_by_digest;
...
[performance_schema]> select 
   -> count_star, avg_timer_wait/1000000000 as avg_ms,
   ->  QUANTILE_95/1000000000 as q95_ms, 
   -> first_seen, 
   -> last_seen,
   ->  query_sample_text 
   -> from events_statements_summary_by_digest 
   -> where schema_name = 'schemaregistry' 
   -> and QUANTILE_95/1000000000 > 0.1
   -> order by QUANTILE_95/1000000000 asc \G
*************************** 1. row ***************************
       count_star: 21
           avg_ms: 0.0782
           q95_ms: 0.1202
       first_seen: 2022-09-19 14:35:28.885824
        last_seen: 2022-09-19 14:38:06.110111
query_sample_text: SELECT @@session.autocommit
*************************** 2. row ***************************
       count_star: 21
           avg_ms: 0.0902
           q95_ms: 0.1514
       first_seen: 2022-09-19 14:35:28.886215
        last_seen: 2022-09-19 14:38:06.110382
query_sample_text: SET sql_mode='STRICT_ALL_TABLES,NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES'

Jadi kami memiliki perintah konfigurasi bawaan yang terkadang membutuhkan waktu lebih dari 0,1 ms untuk dieksekusi. Kami memiliki contoh kueri sederhana lainnya yang terkadang membutuhkan waktu 14 detik untuk dijalankan, 1000 kali lebih lama dari rata-rata.

Ya, dan sejauh yang saya gali, ketika seorang rekan kerja menelepon dan menunjuk ke dasbor mesin yang saya pakai.

Antarmuka jaringan yang sakit pasti akan menghambat kinerja sistem.

Salah satu mesin di replika gabungan untuk lokasi pusat data ini menunjukkan jumlah transmisi ulang jaringan yang tinggi dan kotak itu mungkin membutuhkan perhatian dari para insinyur operasi pusat data.

Kami bereksperimen sedikit dengan menghapus dan menambahkan kembali kotak ke kolam, dan kami yakin: setelah sistem diuji di kolam, penundaan tidak lagi layak diproduksi.

Gambar dari bilah judul: Pengalaman pengguna akhir dengan dan tanpa kotak rusak di kolam tiruan. Kotak yang buruk merusak pengalaman untuk semua pengguna.

Jadi akar masalahnya bukanlah satu kueri yang dieksekusi dengan buruk, tetapi semua kueri dalam kotak dari kumpulan, di lokasi yang sama, dieksekusi dengan buruk. Latensi kueri rata-rata dan bahkan P90 terlihat bagus, tetapi P99 dan P99.9 sangat buruk.

Kotak telah dikeluarkan dari kolam dan dijadwalkan untuk diganti. Kotak yang rusak akan menerima tiket DCOE.



Source link

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan.