Baris panas adalah baris database yang sering dimodifikasi. Dalam skenario konkurensi tinggi, pembaruan baris panas menyebabkan kontensi kunci baris yang parah dan waktu tunggu yang lama, sehingga menurunkan performa sistem. Untuk mengatasi masalah ini, PolarDB menerapkan optimasi pada tingkat kernel database guna meningkatkan performa sistem secara signifikan.
Latar Belakang
Baris panas menimbulkan tantangan berikut:
Ketika suatu transaksi memperbarui baris data, transaksi tersebut mengambil kunci pada baris target dan tidak melepaskan kunci tersebut hingga transaksi di-commit atau di-rollback. Selama periode ini, hanya satu transaksi yang dapat memperbarui baris tersebut, sementara transaksi lain harus menunggu. Artinya, permintaan pembaruan terhadap satu baris panas dieksekusi secara serial. Strategi sharding tabel dan database tradisional memberikan peningkatan performa yang terbatas dalam skenario ini.
Dalam skenario tersebut, sejumlah besar permintaan pembaruan baris panas dapat mencapai sistem database backend dalam waktu singkat. Hal ini menyebabkan kontensi kunci baris yang parah dan waktu tunggu yang lama, sehingga menurunkan performa sistem. Waktu tunggu yang lama untuk permintaan pembaruan dapat berdampak signifikan terhadap operasi bisnis.
Peningkatan kapasitas perangkat keras saja tidak cukup untuk memenuhi persyaratan latensi rendah ini. Oleh karena itu, PolarDB menyediakan optimasi inovatif pada tingkat kernel database. Sistem secara otomatis mengidentifikasi permintaan pembaruan baris panas dan mengelompokkan pembaruan terhadap baris data yang sama yang terjadi dalam interval waktu tertentu. Kelompok-kelompok tersebut kemudian diproses secara paralel menggunakan pemrosesan pipeline. Optimasi ini sangat meningkatkan performa sistem.
Solusi Teknis
Dari pemrosesan serial ke pemrosesan pipeline
Pemrosesan paralel merupakan cara paling langsung untuk meningkatkan performa database, tetapi sulit untuk sepenuhnya memparalelkan operasi pembaruan pada baris panas yang sama. PolarDB menggunakan pendekatan pemrosesan pipeline yang inovatif untuk memaksimalkan paralelisme operasi pembaruan baris panas.
Pernyataan SQL yang digunakan untuk operasi pembaruan baris panas ditandai dengan
autocommitatau COMMIT_ON_SUCCESS. Lapisan kernel MySQL yang telah dioptimalkan secara otomatis mengenali operasi pembaruan dengan tanda tersebut. Dalam interval waktu tertentu, kernel melakukan operasiHashterhadap operasi pembaruan yang dikumpulkan berdasarkan primary key atau unique key-nya. Untuk operasi pembaruan yang dipetakan ke bucket yang sama oleh fungsiHash, kernel mengelompokkan dan meng-commit-nya secara batch sesuai urutan kedatangan.Untuk memproses operasi pembaruan ini dalam pipeline, dua unit eksekusi digunakan untuk mengelompokkannya. Saat kelompok pertama telah dikumpulkan dan siap di-commit, kelompok kedua segera mulai mengumpulkan operasi pembaruan. Ketika kelompok kedua telah dikumpulkan dan siap di-commit, kelompok pertama telah selesai di-commit dan mulai mengumpulkan batch baru operasi pembaruan. Kedua kelompok tersebut bergantian dan dieksekusi secara paralel.
Model pemrosesan pipeline ini memanfaatkan sumber daya perangkat keras secara optimal, meningkatkan utilisasi CPU, serta meningkatkan kemampuan pemrosesan paralel sistem, sehingga memaksimalkan throughput-nya.
Menghilangkan waktu tunggu saat meminta kunci baris
Untuk memastikan konsistensi data secara logis, pembaruan pertama-tama harus mengambil kunci pada baris data target. Jika permintaan kunci tidak dapat segera diberikan, permintaan tersebut masuk ke status menunggu. Hal ini tidak hanya meningkatkan latensi pemrosesan, tetapi juga memicu pendeteksian deadlock, yang menambah beban tambahan.
Seperti disebutkan sebelumnya, operasi pembaruan pada baris data yang sama dikelompokkan berdasarkan urutan waktu. Operasi pembaruan pertama dalam suatu kelompok bertindak sebagai Leader. Leader membaca baris data target dan menguncinya. Operasi pembaruan berikutnya bertindak sebagai Follower. Ketika Follower meminta kunci pada baris data target dan mengetahui bahwa Leader telah memegang kunci baris tersebut, Follower dapat langsung mendapatkan kunci tanpa perlu menunggu.
Optimasi ini mengurangi jumlah pengambilan kunci baris dan overhead waktu terkait. Akibatnya, performa sistem secara keseluruhan meningkat secara signifikan.
Mengurangi traversal indeks B-tree
MySQL mengelola data menggunakan indeks B-tree. Setiap kueri harus melakukan traversal indeks untuk menemukan baris data target. Semakin besar tabel data dan semakin dalam indeksnya, semakin lama waktu traversal-nya.
Dalam mekanisme pengelompokan yang dijelaskan sebelumnya, hanya Leader dari setiap kelompok yang melakukan traversal indeks untuk menemukan baris data, lalu menyimpan baris yang diperbarui dalam cache memori (Row Cache). Setelah Follower dalam kelompok yang sama berhasil mendapatkan kunci, Follower tersebut membaca baris data target langsung dari memori tanpa perlu melakukan traversal indeks lagi.
Hal ini mengurangi jumlah total traversal indeks beserta overhead-nya.
Prasyarat
Kluster PolarDB Anda harus menjalankan salah satu versi berikut:
PolarDB for MySQL 5.6, dengan versi mesin minor 20200601 atau lebih baru.
PolarDB for MySQL 5.7, dengan versi mesin minor 5.7.1.0.17 atau lebih baru.
PolarDB for MySQL 8.0, dengan versi mesin minor 8.0.1.1.10 atau lebih baru.
binlog diaktifkan.
Parameter kluster
rds_ic_reduce_hint_enableharus dinonaktifkan.Untuk PolarDB for MySQL 5.6 dan PolarDB for MySQL 8.0, parameter ini dinonaktifkan secara default.
Untuk PolarDB for MySQL 5.7, parameter ini diaktifkan secara default. Sebelum mengaktifkan optimasi baris panas, Anda harus mengubah nilai parameter menjadi OFF.
CatatanUntuk memastikan kompatibilitas dengan file konfigurasi MySQL, PolarDB console memberikan awalan loose_ pada semua parameter kluster. Untuk mengubah parameter
rds_ic_reduce_hint_enabledi PolarDB console, Anda harus memilih parameter dengan awalan loose_, yaitu loose_rds_ic_reduce_hint_enable.
Batasan
Optimasi baris panas tidak berlaku dalam skenario berikut:
Tabel yang berisi baris panas merupakan tabel partisi.
Pemicu (trigger) didefinisikan pada tabel yang berisi baris panas.
Baris panas menggunakan mekanisme Statement Queue.
Jika global binlog diaktifkan tetapi binlog tingkat sesi dinonaktifkan, optimasi baris panas tidak diterapkan pada pernyataan
UPDATE.Setelah Anda mengaktifkan optimasi baris panas, kolom yang hanya bergantung pada atribut
ON UPDATE CURRENT_TIMESTAMPuntuk pembaruan otomatis tidak akan lagi diperbarui secara otomatis. Anda harus secara eksplisit memberikan nilai pada kolom tersebut dalam pernyataanUPDATEAnda dengan menggunakanSET column_name = CURRENT_TIMESTAMP(n).
Penggunaan
Aktifkan optimasi baris panas.
Di PolarDB console, Anda dapat mengubah parameter berikut untuk mengaktifkan atau menonaktifkan optimasi baris panas.
Parameter
Deskripsi
hotspot
Menentukan apakah fitur optimasi baris panas diaktifkan. Nilai yang valid:
ON: diaktifkan.
OFF (default): dinonaktifkan.
CatatanUntuk memastikan kompatibilitas dengan file konfigurasi MySQL, PolarDB console memberikan awalan loose_ pada semua parameter kluster. Untuk mengubah parameter hotspot di PolarDB console, pilih parameter dengan awalan loose_, yaitu loose_hotspot.
Gunakan sintaks hint untuk menerapkan optimasi baris panas.
Hint
Wajib
Deskripsi
Wajib
Commit transaksi jika pembaruan berhasil.
Opsional
Rollback transaksi jika pembaruan gagal.
Opsional
Menentukan bahwa permintaan diharapkan hanya memperbarui satu baris. Jika kondisi ini tidak terpenuhi, pembaruan akan gagal.
CatatanKarena hint ini secara otomatis melakukan commit transaksi, Anda harus menyertakannya dalam pernyataan SQL terakhir dari transaksi.
Contoh: Perbarui nilai kolom
cpada tabelsbtest.UPDATE /*+ COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL TARGET_AFFECT_ROW(1) */ sbtest SET c = c + 1 WHERE id = 1;
Operasi Terkait
Parameter Kustom
Anda tidak dapat mengubah parameter berikut di PolarDB console. Untuk mengubahnya, buka Pusat Kuota, temukan ID kuota polardb_mysql_hotspot, lalu klik Apply pada kolom Actions.
Parameter | Deskripsi |
hotspot_for_autocommit | Menentukan apakah optimasi baris panas diaktifkan untuk pernyataan
|
hotspot_update_max_wait_time | Waktu maksimum yang ditunggu Leader untuk menunggu Follower bergabung dalam suatu Group Update.
|
hotspot_lock_type | Menentukan apakah jenis kunci baris baru untuk Group Update diaktifkan. Nilai yang valid:
Catatan
|
Pengaturan Parameter
Jalankan perintah berikut untuk melihat pengaturan parameter optimasi baris panas.
SHOW variables LIKE "hotspot%";Contoh hasil:
+------------------------------+-------+
|Variable_name | Value |
+------------------------------+-------+
|hotspot | OFF |
|hotspot_for_autocommit | OFF |
|hotspot_lock_type | OFF |
|hotspot_update_max_wait_time | 100 |
+------------------------------+-------+Statistik Penggunaan
Jalankan perintah berikut untuk melihat statistik penggunaan optimasi baris panas.
SHOW GLOBAL status LIKE 'Group_update%';Uji Performa
Tool Uji
Sysbench adalah tool pengujian performa open-source lintas platform. Tool ini terutama digunakan untuk benchmark database, seperti MySQL, dan untuk pengujian performa sistem pada komponen seperti CPU, memori, I/O, dan thread. Sysbench mendukung pengujian multi-threaded dan menggunakan skrip Lua untuk mengontrol logika pengujian secara fleksibel. Tool ini cocok untuk skenario seperti evaluasi performa database dan uji stres.
Tabel dan Pernyataan Uji
Definisi tabel
CREATE TABLE sbtest (id INT UNSIGNED NOT NULL, c BIGINT UNSIGNED NOT NULL, PRIMARY KEY (id));Pernyataan uji
UPDATE /*+ COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL TARGET_AFFECT_ROW(1) */ sbtest SET c = c + 1 WHERE id = 1;
Hasil Uji
PolarDB for MySQL 5.6
Skenario uji
Satu baris panas pada CPU 8-core.
Hasil uji
Dalam skenario uji ini, mengaktifkan optimasi baris panas meningkatkan performa pembaruan pada baris panas terkait inventaris hampir 50 kali lipat dalam kondisi konkurensi tinggi.
Data uji (QPS)

Concurrency | 1 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
Optimasi baris panas dinonaktifkan | 1365,31 | 1863,94 | 1866,6 | 1862,64 | 1867,32 | 1832,51 | 1838,31 | 1819,52 | 1833,2 |
Optimasi baris panas diaktifkan | 1114,79 | 7000,19 | 12717,32 | 22029,48 | 43096,06 | 61349,7 | 83098,69 | 90860,94 | 87689 |
PolarDB for MySQL 5.7
Skenario uji
Satu baris panas pada CPU 8-core.
Hasil uji
Dalam skenario uji ini, mengaktifkan optimasi baris panas meningkatkan performa pembaruan pada baris panas terkait inventaris hampir 35 kali lipat dalam kondisi konkurensi tinggi.
Data uji
QPS

Konkurensi | 1 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
Optimasi baris panas dinonaktifkan | 1348,49 | 1892,29 | 1889,77 | 1895,86 | 1875,2 | 1850,26 | 1843,62 | 1849,92 | 1835,68 |
Optimasi baris panas diaktifkan | 1104,9 | 6886,89 | 12485,17 | 16003,23 | 16460,31 | 16548,86 | 27920,89 | 47893,96 | 66500,92 |
Latensi persentil ke-95

Konkurensi | 1 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
Optimasi baris panas dinonaktifkan | 0,9 | 5,47 | 9,91 | 18,95 | 36,89 | 73,13 | 164,45 | 297,92 | 590,56 |
Optimasi baris panas diaktifkan | 1,08 | 1,44 | 1,58 | 3,25 | 5,28 | 9,56 | 12,08 | 13,22 | 18,28 |
PolarDB for MySQL 8.0
Skenario uji
Satu baris panas pada CPU 8-core.
Hasil uji
Dalam skenario uji ini, mengaktifkan optimasi baris panas meningkatkan performa pembaruan pada baris panas terkait inventaris hampir 26 kali lipat dalam kondisi konkurensi tinggi.
Data uji
QPS

Concurrency | 1 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
Optimasi baris panas dinonaktifkan | 1559,14 | 2103,82 | 2116,4 | 2082,1 | 2079,74 | 2031,64 | 1993,09 | 1977,6 | 1983,61 |
Optimasi baris panas diaktifkan | 1237,28 | 7443,04 | 12244,19 | 15529,52 | 23041,15 | 33931,18 | 53924,24 | 54598,6 | 50988,22 |
Latensi persentil ke-95

Konkurensi | 1 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
Optimasi baris panas dinonaktifkan | 0,8 | 5 | 8,9 | 17,32 | 33,12 | 66,84 | 153,02 | 287,38 | 549,52 |
Optimasi baris panas diaktifkan | 0,97 | 1,34 | 1,89 | 3,19 | 4,82 | 5,88 | 7,17 | 13,46 | 28,16 |
Langkah-langkah Uji Performa
Siapkan instance ECS dan instal Sysbench.
Tempatkan file
oltp_inventory.luaberikut di direktorisrc/luadari kode sumber Sysbench.#!/usr/bin/env sysbench -- it is to test inventory_hotspot performance sysbench.cmdline.options= { inventory_hotspot = {"enable ali inventory hotspot", 'off'}, tables = {"table number", 1}, table_size = {"table size", 1}, oltp_skip_trx = {'skip trx', true}, hotspot_rows = {'hotspot row number', 1} } function cleanup() drv = sysbench.sql.driver() con = drv:connect() for i = 1, sysbench.opt.tables do print(string.format("drop table sbtest%d ...", i)) drop_table(drv, con, i) end end function drop_table(drv, con, table_id) local query query = string.format("drop table if exists sbtest%d ", table_id) con:query(query) end function create_table(drv, con, table_id) local query query = string.format("CREATE TABLE sbtest%d (id INT UNSIGNED NOT NULL, c BIGINT UNSIGNED NOT NULL, PRIMARY KEY (id))", table_id) con:query(query) for i=1, sysbench.opt.table_size do con:query("INSERT INTO sbtest" .. table_id .. "(id, c) values (" ..i.. ", 1)") end end function prepare() drv = sysbench.sql.driver() con = drv:connect() for i = 1, sysbench.opt.tables do print(string.format("Creating table sbtest%d ...", i)) create_table(drv, con, i) end end function thread_init() drv = sysbench.sql.driver() con = drv:connect() begin_query = 'BEGIN' commit_query = 'COMMIT' end function event() local table_name table_name = "sbtest" .. sysbench.rand.uniform(1, sysbench.opt.tables) local min_line = math.min(sysbench.opt.table_size, sysbench.opt.hotspot_rows) local row_id = sysbench.rand.uniform(1, min_line) if not sysbench.opt.oltp_skip_trx then con:query(begin_query) end if (sysbench.opt.inventory_hotspot == "on") then con:query("UPDATE /*+ COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL TARGET_AFFECT_ROW(1) */ " .. table_name .. " SET c=c+1 WHERE id =" .. row_id) else con:query("UPDATE " .. table_name .. " SET c=c+1 WHERE id = " .. row_id) end if not sysbench.opt.oltp_skip_trx then if (sysbench.opt.inventory_hotspot == "on") then con:query(commit_query) end end end function thread_done() con:disconnect() endJalankan uji Sysbench.
Siapkan data.
sysbench --hotspot_rows=1 --histogram=on --mysql-user=<user> --inventory_hotspot=on --mysql-host=<host> --threads=1 --report-interval=1 --mysql-password=<password> --tables=1 --table-size=1 --oltp_skip_trx=true --db-driver=mysql --percentile=95 --time=300 --mysql-port=<port> --events=0 --mysql-db=<database> oltp_inventory prepareJalankan uji.
sysbench --db-driver=mysql --mysql-host=<host> --mysql-port=<port> --mysql-user=<user> --mysql-password=<password> --mysql-db=<database> --range-selects=0 --table_size=25000 --tables=250 --events=0 --time=600 --rand-type=uniform --threads=<threads> oltp_inventory run
Parameter input
Parameter
Deskripsi
mysql-host
Titik akhir kluster.
mysql-port
Port dari titik akhir kluster.
mysql-user
Username untuk akun database.
mysql-password
Password untuk akun database.
mysql-db
Nama database.
Parameter output
Parameter
Metrik
Deskripsi
tables
Jumlah tabel
Jumlah total tabel yang digunakan dalam uji.
table_size
Jumlah baris per tabel
Jumlah catatan dalam setiap tabel.
Ukuran data
Ukuran data tabel, diukur dalam satuan seperti MB atau GB.
threads
Jumlah thread konkuren
Jumlah thread yang dikonfigurasi.
Status thread
Status real-time dari thread yang sedang berjalan.