Hot row performance optimization
Hot rows are database rows that are frequently modified. In high-concurrency scenarios, updating hot rows causes severe row lock contention and long wait times, degrading system performance. To address this issue, PolarDB implements optimizations at the database kernel level to significantly improve system performance.
Background
Hot rows present the following challenges:
When a transaction updates a data row, it acquires a lock on the target row and does not release the lock until the transaction is committed or rolled back. During this time, only one transaction can update the row, and other transactions must wait. This means that update requests for a single hot row are executed serially. Traditional database and table sharding strategies provide limited performance improvements in this scenario.
In these scenarios, a large number of update requests for hot rows can reach the backend database system in a short period. This leads to severe row lock contention and long wait times, which degrades system performance. A long wait for an update request can significantly impact business operations.
Simply scaling up hardware cannot meet these low-latency requirements. To address this, PolarDB provides innovative optimizations at the database kernel level. The system automatically identifies hot row update requests and groups updates to the same data row that occur within a specific time interval. Different groups are then processed in parallel using a pipeline. These optimizations greatly improve system performance.
Technical solution
From sequential to pipeline processing
Parallel processing is the most direct way to improve database performance, but it is difficult to fully parallelize update operations on the same hot row. PolarDB uses an innovative pipeline processing approach to maximize the parallelism of hot row update operations.
SQL statements used for hot row update operations are marked with
autocommitor COMMIT_ON_SUCCESS. The optimized MySQL kernel layer automatically identifies update operations with these marks. Within a certain time interval, it performs aHashon the collected update operations based on their primary key or unique key. For update operations that are mapped to the same bucket by theHash, the kernel groups and commits them in batches according to their arrival order.To process these update operations in a pipeline, two execution units are used to group them. When the first group is collected and ready to commit, the second group immediately starts collecting update operations. When the second group is collected and ready to commit, the first group has already been committed and begins collecting a new batch of update operations. The two groups alternate and execute in parallel.
This pipeline processing model fully utilizes hardware resources, increases CPU utilization, and improves the system's parallel processing capability, maximizing its throughput.
Eliminate waiting when requesting row locks
To ensure logical data consistency, an update first acquires a lock on the target data row. If the lock request cannot be granted immediately, the request enters a waiting state. This not only increases processing latency but also triggers deadlock detection, which adds extra overhead.
As mentioned earlier, update operations on the same data row are grouped in chronological order. The first update operation in a group is the Leader. It reads the target data row and locks it. Subsequent update operations are Followers. When a Follower requests a lock on the target data row and finds that the Leader already holds the row lock, it can acquire the lock immediately without waiting.
This optimization reduces the number of row lock acquisitions and the associated time overhead. As a result, overall system performance improves significantly.
Reduce B-tree index traversals
MySQL manages data by using B-tree indexes. Each query must traverse the index to locate the target data row. The larger the data table and the deeper the index, the longer the traversal takes.
In the grouping mechanism described earlier, only the Leader of each group traverses the index to locate the data row, and then caches the updated row in memory (Row Cache). After a Follower in the same group successfully acquires the lock, it reads the target data row directly from memory without traversing the index again.
This reduces the total number of index traversals and their associated overhead.
Prerequisites
Your PolarDB cluster must run one of the following versions:
PolarDB for MySQL 5.6, with a minor engine version of 20200601 or later.
PolarDB for MySQL 5.7, with a minor engine version of 5.7.1.0.17 or later.
PolarDB for MySQL 8.0, with a minor engine version of 8.0.1.1.10 or later.
binlog is enabled.
The cluster parameter
rds_ic_reduce_hint_enablemust be disabled.For PolarDB for MySQL 5.6 and PolarDB for MySQL 8.0, this parameter is disabled by default.
For PolarDB for MySQL 5.7, this parameter is enabled by default. Before you enable hot row optimization, you must change the parameter value to OFF.
NoteTo ensure compatibility with MySQL configuration files, the PolarDB console prefixes all cluster parameters with loose_. To modify the
rds_ic_reduce_hint_enableparameter in the PolarDB console, you must select the parameter with the loose_ prefix, which is loose_rds_ic_reduce_hint_enable.
Limitations
Hot row optimization does not apply in the following scenarios:
The table that contains the hot row is a partitioned table.
A trigger is defined on the table that contains the hot row.
The hot row uses the Statement Queue mechanism.
If global binlog is enabled but session-level binlog is disabled, hot row optimization is not applied to
UPDATEstatements.After you enable hot row optimization, columns that rely solely on the
ON UPDATE CURRENT_TIMESTAMPattribute for automatic updates will no longer be automatically updated. You must explicitly assign values to these columns in yourUPDATEstatements by usingSET column_name = CURRENT_TIMESTAMP(n).
Usage
Enable hot row optimization.
In the PolarDB console, you can modify the following parameter to enable or disable hot row optimization.
Parameter
Description
hotspot
Specifies whether to enable the hot row optimization feature. Valid values:
ON: enabled.
OFF (default): disabled.
NoteTo ensure compatibility with MySQL configuration files, the PolarDB console prefixes all cluster parameters with loose_. To modify the hotspot parameter in the PolarDB console, select the parameter with the loose_ prefix, which is loose_hotspot.
Use hint syntax to apply hot row optimization.
Hint
Required
Description
Required
Commits the transaction if the update is successful.
Optional
Rolls back the transaction if the update fails.
Optional
Specifies that the request is expected to update only one row. If this condition is not met, the update fails.
NoteBecause this hint automatically commits the transaction, you must include it in the last SQL statement of the transaction.
Example: Update the value of the
ccolumn in thesbtesttable.UPDATE /*+ COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL TARGET_AFFECT_ROW(1) */ sbtest SET c = c + 1 WHERE id = 1;
Related operations
Custom parameters
You cannot modify the following parameters in the PolarDB console. To modify them, go to Quota Center, find the quota ID polardb_mysql_hotspot, and then click Apply in the Actions column.
Parameter | Description |
hotspot_for_autocommit | Specifies whether to enable hot row optimization for
|
hotspot_update_max_wait_time | The maximum time a Leader waits for Followers to join a group during a Group Update.
|
hotspot_lock_type | Specifies whether to enable a new row lock type for Group Update. Valid values:
Note
|
Parameter settings
Run the following command to view the parameter settings for hot row optimization.
SHOW variables LIKE "hotspot%";Sample result:
+------------------------------+-------+
|Variable_name | Value |
+------------------------------+-------+
|hotspot | OFF |
|hotspot_for_autocommit | OFF |
|hotspot_lock_type | OFF |
|hotspot_update_max_wait_time | 100 |
+------------------------------+-------+Usage statistics
Run the following command to view usage statistics for hot row optimization.
SHOW GLOBAL status LIKE 'Group_update%';Performance test
Test tool
Sysbench is an open-source, cross-platform performance testing tool. It is primarily used for database benchmarks, such as for MySQL, and for system performance tests on components like the CPU, memory, I/O, and threads. It supports multi-threaded testing and uses Lua scripts to flexibly control test logic. It is suitable for scenarios such as database performance evaluation and stress testing.
Test table and statement
Table definition
CREATE TABLE sbtest (id INT UNSIGNED NOT NULL, c BIGINT UNSIGNED NOT NULL, PRIMARY KEY (id));Test statement
UPDATE /*+ COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL TARGET_AFFECT_ROW(1) */ sbtest SET c = c + 1 WHERE id = 1;
Test results
PolarDB for MySQL 5.6
Test scenario
A single hot row on an 8-core CPU.
Test results
In this test scenario, enabling hot row optimization improves update performance on inventory-related hot rows by nearly 50 times under high concurrency.
Test data (QPS)

Concurrency | 1 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
Hot row optimization disabled | 1365.31 | 1863.94 | 1866.6 | 1862.64 | 1867.32 | 1832.51 | 1838.31 | 1819.52 | 1833.2 |
Hot row optimization enabled | 1114.79 | 7000.19 | 12717.32 | 22029.48 | 43096.06 | 61349.7 | 83098.69 | 90860.94 | 87689 |
PolarDB for MySQL 5.7
Test scenario
A single hot row on an 8-core CPU.
Test results
In this test scenario, enabling hot row optimization improves update performance on inventory-related hot rows by nearly 35 times under high concurrency.
Test data
QPS

Concurrency | 1 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
Hot row optimization disabled | 1348.49 | 1892.29 | 1889.77 | 1895.86 | 1875.2 | 1850.26 | 1843.62 | 1849.92 | 1835.68 |
Hot row optimization enabled | 1104.9 | 6886.89 | 12485.17 | 16003.23 | 16460.31 | 16548.86 | 27920.89 | 47893.96 | 66500.92 |
95th percentile latency

Concurrency | 1 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
Hot row optimization disabled | 0.9 | 5.47 | 9.91 | 18.95 | 36.89 | 73.13 | 164.45 | 297.92 | 590.56 |
Hot row optimization enabled | 1.08 | 1.44 | 1.58 | 3.25 | 5.28 | 9.56 | 12.08 | 13.22 | 18.28 |
PolarDB for MySQL 8.0
Test scenario
A single hot row on an 8-core CPU.
Test results
In this test scenario, enabling hot row optimization improves update performance on inventory-related hot rows by nearly 26 times under high concurrency.
Test data
QPS

Concurrency | 1 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
Hot row optimization disabled | 1559.14 | 2103.82 | 2116.4 | 2082.1 | 2079.74 | 2031.64 | 1993.09 | 1977.6 | 1983.61 |
Hot row optimization enabled | 1237.28 | 7443.04 | 12244.19 | 15529.52 | 23041.15 | 33931.18 | 53924.24 | 54598.6 | 50988.22 |
95th percentile latency

Concurrency | 1 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
Hot row optimization disabled | 0.8 | 5 | 8.9 | 17.32 | 33.12 | 66.84 | 153.02 | 287.38 | 549.52 |
Hot row optimization enabled | 0.97 | 1.34 | 1.89 | 3.19 | 4.82 | 5.88 | 7.17 | 13.46 | 28.16 |
Performance test steps
Prepare an ECS instance and install Sysbench.
Place the following
oltp_inventory.luafile in thesrc/luadirectory of the Sysbench source code.#!/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() endRun the Sysbench test.
Prepare the 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 prepareRun the test.
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
Input parameters
Parameter
Description
mysql-host
The cluster endpoint.
mysql-port
The port of the cluster endpoint.
mysql-user
The username for the database account.
mysql-password
The password for the database account.
mysql-db
The database name.
Output parameters
Parameter
Metric
Description
tables
Number of tables
The total number of tables used in the test.
table_size
Number of rows per table
The number of records in each table.
Data size
The data size of the table, measured in units such as MB or GB.
threads
Number of concurrent threads
The number of configured threads.
Thread status
The real-time status of the running threads.