Todos los productos
Search
Centro de documentos

PolarDB:Hot row performance optimization

Última actualización: Sep 05, 2026

Las filas calientes son registros de la base de datos que se modifican con frecuencia. En escenarios de alta concurrencia, actualizar estas filas provoca una fuerte contención de bloqueos y tiempos de espera prolongados, lo que degrada el rendimiento del sistema. Para resolver este problema, PolarDB implementa optimizaciones en el kernel de la base de datos que mejoran significativamente el rendimiento del sistema.

Contexto

Las filas calientes presentan los siguientes desafíos:

  • Cuando una transacción actualiza un registro, adquiere un bloqueo sobre la fila destino y no lo libera hasta que la transacción se confirma o se revierte. Durante ese tiempo, solo una transacción puede actualizar la fila, por lo que las demás deben esperar. Esto significa que las solicitudes de actualización de una sola fila caliente se ejecutan de forma secuencial. Las estrategias tradicionales de fragmentación de bases de datos y tablas ofrecen mejoras de rendimiento limitadas en este escenario.

  • En estos escenarios, una gran cantidad de solicitudes de actualización de filas calientes puede llegar al sistema de base de datos del backend en poco tiempo. Esto genera una fuerte contención de bloqueos de fila y tiempos de espera prolongados, lo que degrada el rendimiento del sistema. Una espera larga en una solicitud de actualización puede afectar significativamente las operaciones del negocio.

Escalar el hardware no basta para cumplir estos requisitos de baja latencia. Por ello, PolarDB ofrece optimizaciones innovadoras en el kernel de la base de datos. El sistema identifica automáticamente las solicitudes de actualización de filas calientes y agrupa las actualizaciones de un mismo registro que ocurren dentro de un intervalo de tiempo específico. Luego, procesa los distintos grupos en paralelo mediante un pipeline. Estas optimizaciones mejoran notablemente el rendimiento del sistema.

Solución técnica

  • Del procesamiento secuencial al procesamiento por pipeline

    El procesamiento en paralelo es la forma más directa de mejorar el rendimiento de una base de datos, pero resulta difícil paralelizar por completo las operaciones de actualización sobre una misma fila caliente. PolarDB utiliza un enfoque innovador de procesamiento por pipeline para maximizar el paralelismo de estas operaciones.

    image

    Las sentencias SQL utilizadas para actualizar filas calientes se marcan con autocommit o COMMIT_ON_SUCCESS. La capa optimizada del kernel de MySQL identifica automáticamente las operaciones de actualización con estas marcas. Dentro de un intervalo de tiempo determinado, aplica un Hash a las operaciones recopiladas según su clave primaria o clave única. Para las operaciones que el Hash asigna al mismo bucket, el kernel las agrupa y las confirma en lotes según su orden de llegada.

    Para procesar estas operaciones mediante un pipeline, se utilizan dos unidades de ejecución que las agrupan. Cuando el primer grupo se recopila y está listo para confirmarse, el segundo comienza inmediatamente a recopilar operaciones de actualización. Cuando el segundo grupo se recopila y está listo para confirmarse, el primero ya se confirmó y empieza a recopilar un nuevo lote. Ambos grupos se alternan y se ejecutan en paralelo.

    Este modelo de procesamiento por pipeline aprovecha al máximo los recursos de hardware, aumenta la utilización de la CPU y mejora la capacidad de procesamiento en paralelo del sistema, lo que maximiza su rendimiento.

  • Eliminación de esperas al solicitar bloqueos de fila

    Para garantizar la coherencia lógica de los datos, una actualización adquiere primero un bloqueo sobre la fila destino. Si la solicitud de bloqueo no se concede de inmediato, entra en estado de espera. Esto no solo aumenta la latencia de procesamiento, sino que también activa la detección de interbloqueos, lo que añade sobrecarga adicional.

    Como se mencionó antes, las operaciones de actualización sobre un mismo registro se agrupan en orden cronológico. La primera operación de un grupo actúa como Leader: lee la fila destino y la bloquea. Las operaciones posteriores actúan como Followers. Cuando un Follower solicita un bloqueo sobre la fila destino y detecta que el Leader ya lo tiene, adquiere el bloqueo de inmediato sin esperar.

    Esta optimización reduce la cantidad de adquisiciones de bloqueos de fila y el tiempo asociado. Como resultado, el rendimiento general del sistema mejora de manera significativa.

  • Reducción de recorridos de índices B-tree

    MySQL gestiona los datos mediante índices B-tree. Cada consulta debe recorrer el índice para ubicar la fila destino. Entre más grande sea la tabla y más profundo el índice, más tiempo tomará el recorrido.

    En el mecanismo de agrupación descrito anteriormente, solo el Leader de cada grupo recorre el índice para ubicar el registro y luego almacena la fila actualizada en memoria (Row Cache). Después de que un Follower del mismo grupo adquiere correctamente el bloqueo, lee la fila destino directamente desde la memoria sin recorrer el índice de nuevo.

    Esto reduce la cantidad total de recorridos de índices y su sobrecarga asociada.

Requisitos previos

  • Su clúster de PolarDB debe ejecutar una de las siguientes versiones:

    • PolarDB for MySQL 5.6, con una versión secundaria del motor 20200601 o posterior.

    • PolarDB for MySQL 5.7, con una versión secundaria del motor 5.7.1.0.17 o posterior.

    • PolarDB for MySQL 8.0, con una versión secundaria del motor 8.0.1.1.10 o posterior.

  • binlog está habilitado.

  • El parámetro de clúster rds_ic_reduce_hint_enable debe estar deshabilitado.

    • En PolarDB for MySQL 5.6 y PolarDB for MySQL 8.0, este parámetro está deshabilitado de forma predeterminada.

    • En PolarDB for MySQL 5.7, este parámetro está habilitado de forma predeterminada. Antes de habilitar la optimización de filas calientes, debe change the parameter value a OFF.

    Nota

    Para garantizar la compatibilidad con los archivos de configuración de MySQL, PolarDB console antepone el prefijo loose_ a todos los parámetros del clúster. Para modificar el parámetro rds_ic_reduce_hint_enable en PolarDB console, seleccione el parámetro con el prefijo loose_, es decir, loose_rds_ic_reduce_hint_enable.

Limitaciones

La optimización de filas calientes no aplica en los siguientes escenarios:

  • La tabla que contiene la fila caliente es una tabla particionada.

  • Se definió un trigger en la tabla que contiene la fila caliente.

  • La fila caliente utiliza el mecanismo Statement Queue.

  • Si el binlog global está habilitado pero el binlog a nivel de sesión está deshabilitado, la optimización de filas calientes no se aplica a las sentencias UPDATE.

  • Después de habilitar la optimización de filas calientes, las columnas que dependen únicamente del atributo ON UPDATE CURRENT_TIMESTAMP para actualizaciones automáticas dejarán de actualizarse de forma automática. Debe asignar valores explícitamente a estas columnas en sus sentencias UPDATE mediante SET column_name = CURRENT_TIMESTAMP(n).

Uso

  1. Habilite la optimización de filas calientes.

    En PolarDB console, puede modify the following parameter para habilitar o deshabilitar la optimización de filas calientes.

    Parámetro

    Descripción

    hotspot

    Especifica si se habilita la función de optimización de filas calientes. Valores válidos:

    1. ON: habilitada.

    2. OFF (predeterminado): deshabilitada.

    Nota

    Para garantizar la compatibilidad con los archivos de configuración de MySQL, PolarDB console antepone el prefijo loose_ a todos los parámetros del clúster. Para modificar el parámetro hotspot en PolarDB console, seleccione el parámetro con el prefijo loose_, es decir, loose_hotspot.

  2. Utilice la sintaxis de hint para aplicar la optimización de filas calientes.

    Hint

    Obligatorio

    Descripción

    COMMIT_ON_SUCCESS

    Obligatorio

    Confirma la transacción si la actualización se completa correctamente.

    ROLLBACK_ON_FAIL

    Opcional

    Revierte la transacción si la actualización falla.

    TARGET_AFFECT_ROW(1)

    Opcional

    Indica que se espera que la solicitud actualice solo una fila. Si no se cumple esta condición, la actualización falla.

    Nota

    Dado que este hint confirma la transacción automáticamente, debe incluirlo en la última sentencia SQL de la transacción.

    Ejemplo: actualice el valor de la columna c en la tabla sbtest.

    UPDATE /*+ COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL TARGET_AFFECT_ROW(1) */ sbtest SET c = c + 1 WHERE id = 1;

Operaciones relacionadas

Parámetros personalizados

No es posible modificar los siguientes parámetros en PolarDB console. Para modificarlos, vaya a Quota Center, busque el identificador de cuota polardb_mysql_hotspot y haga clic en Apply en la columna Actions.

Parámetro

Descripción

hotspot_for_autocommit

Especifica si se habilita la optimización de filas calientes para las sentencias UPDATE en modo autocommit. Valores válidos:

  • ON: habilitada.

  • OFF (predeterminado): deshabilitada.

hotspot_update_max_wait_time

Tiempo máximo que un Leader espera a que los Followers se unan a un grupo durante un Group Update.

  • Unidad: microsegundos (us).

  • Valor predeterminado: 100.

hotspot_lock_type

Especifica si se habilita un nuevo tipo de bloqueo de fila para Group Update. Valores válidos:

  • ON: habilitado.

  • OFF (predeterminado): deshabilitado.

Nota
  • Si este parámetro está habilitado, cuando una operación de actualización solicita un bloqueo de fila para la misma fila caliente, adquiere el bloqueo de inmediato sin esperar. Esto mejora el rendimiento.

  • El nuevo tipo de bloqueo es un bloqueo que se adquiere de inmediato sin esperar.

Configuración de parámetros

Ejecute el siguiente comando para consultar la configuración de parámetros de la optimización de filas calientes.

SHOW variables LIKE "hotspot%";

Resultado de ejemplo:

+------------------------------+-------+
|Variable_name                 | Value |
+------------------------------+-------+
|hotspot                       | OFF   |
|hotspot_for_autocommit        | OFF   |
|hotspot_lock_type             | OFF   |
|hotspot_update_max_wait_time  | 100   |
+------------------------------+-------+

Estadísticas de uso

Ejecute el siguiente comando para consultar las estadísticas de uso de la optimización de filas calientes.

SHOW GLOBAL status LIKE 'Group_update%';

Prueba de rendimiento

Herramienta de prueba

Sysbench es una herramienta de pruebas de rendimiento multiplataforma y de código abierto. Se utiliza principalmente para benchmarks de bases de datos, como MySQL, y para pruebas de rendimiento del sistema en componentes como la CPU, la memoria, la E/S y los hilos. Admite pruebas multihilo y usa scripts de Lua para controlar de forma flexible la lógica de las pruebas. Es adecuada para escenarios como la evaluación de rendimiento de bases de datos y las pruebas de estrés.

Tabla y sentencia de prueba

  • Definición de la tabla

    CREATE TABLE sbtest (id INT UNSIGNED NOT NULL, c BIGINT UNSIGNED NOT NULL, PRIMARY KEY (id));
  • Sentencia de prueba

    UPDATE /*+ COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL TARGET_AFFECT_ROW(1) */ sbtest SET c = c + 1 WHERE id = 1;

Resultados de la prueba

PolarDB for MySQL 5.6

Escenario de prueba

Una sola fila caliente en una CPU de 8 núcleos.

Resultados de la prueba

En este escenario de prueba, habilitar la optimización de filas calientes mejora casi 50 veces el rendimiento de actualización de filas calientes relacionadas con inventarios bajo alta concurrencia.

Datos de la prueba (QPS)

image.png

Concurrencia

1

8

16

32

64

128

256

512

1024

Optimización de filas calientes deshabilitada

1365.31

1863.94

1866.6

1862.64

1867.32

1832.51

1838.31

1819.52

1833.2

Optimización de filas calientes habilitada

1114.79

7000.19

12717.32

22029.48

43096.06

61349.7

83098.69

90860.94

87689

PolarDB for MySQL 5.7

Escenario de prueba

Una sola fila caliente en una CPU de 8 núcleos.

Resultados de la prueba

En este escenario de prueba, habilitar la optimización de filas calientes mejora casi 35 veces el rendimiento de actualización de filas calientes relacionadas con inventarios bajo alta concurrencia.

Datos de la prueba

QPS

image.png

Concurrencia

1

8

16

32

64

128

256

512

1024

Optimización de filas calientes deshabilitada

1348.49

1892.29

1889.77

1895.86

1875.2

1850.26

1843.62

1849.92

1835.68

Optimización de filas calientes habilitada

1104.9

6886.89

12485.17

16003.23

16460.31

16548.86

27920.89

47893.96

66500.92

Latencia del percentil 95

image

Concurrencia

1

8

16

32

64

128

256

512

1024

Optimización de filas calientes deshabilitada

0.9

5.47

9.91

18.95

36.89

73.13

164.45

297.92

590.56

Optimización de filas calientes habilitada

1.08

1.44

1.58

3.25

5.28

9.56

12.08

13.22

18.28

PolarDB for MySQL 8.0

Escenario de prueba

Una sola fila caliente en una CPU de 8 núcleos.

Resultados de la prueba

En este escenario de prueba, habilitar la optimización de filas calientes mejora casi 26 veces el rendimiento de actualización de filas calientes relacionadas con inventarios bajo alta concurrencia.

Datos de la prueba

QPS

image

Concurrencia

1

8

16

32

64

128

256

512

1024

Optimización de filas calientes deshabilitada

1559.14

2103.82

2116.4

2082.1

2079.74

2031.64

1993.09

1977.6

1983.61

Optimización de filas calientes habilitada

1237.28

7443.04

12244.19

15529.52

23041.15

33931.18

53924.24

54598.6

50988.22

Latencia del percentil 95

image

Concurrencia

1

8

16

32

64

128

256

512

1024

Optimización de filas calientes deshabilitada

0.8

5

8.9

17.32

33.12

66.84

153.02

287.38

549.52

Optimización de filas calientes habilitada

0.97

1.34

1.89

3.19

4.82

5.88

7.17

13.46

28.16

Pasos de la prueba de rendimiento

  1. Prepare una instancia de ECS y install Sysbench.

  2. Coloque el siguiente archivo oltp_inventory.lua en el directorio src/lua del código fuente de 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()
    end
  3. Connect to the cluster by using the command line.

  4. Ejecute la prueba de Sysbench.

    1. Prepare los datos.

      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 prepare
    2. Ejecute la prueba.

      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

    Parámetros de entrada

    Parámetro

    Descripción

    mysql-host

    El endpoint del clúster.

    mysql-port

    El puerto del endpoint del clúster.

    mysql-user

    El nombre de usuario de la cuenta de la base de datos.

    mysql-password

    La contraseña de la cuenta de la base de datos.

    mysql-db

    El nombre de la base de datos.

    Parámetros de salida

    Parámetro

    Métrica

    Descripción

    tables

    Número de tablas

    Cantidad total de tablas utilizadas en la prueba.

    table_size

    Número de filas por tabla

    Cantidad de registros en cada tabla.

    Tamaño de los datos

    Tamaño de los datos de la tabla, medido en unidades como MB o GB.

    threads

    Número de hilos concurrentes

    Cantidad de hilos configurados.

    Estado de los hilos

    Estado en tiempo real de los hilos en ejecución.