Todos os produtos
Search
Central de documentação

PolarDB:Otimização de desempenho para linhas quentes

Última atualização: Jun 28, 2026

Linhas quentes são registros de banco de dados modificados com alta frequência. Em cenários de alta concorrência, a atualização dessas linhas causa contenção severa de bloqueios de linha e longos tempos de espera, o que degrada o desempenho do sistema. Para resolver esse problema, o PolarDB implementa otimizações no nível do kernel do banco de dados e melhora significativamente o desempenho do sistema.

Contexto

As linhas quentes apresentam os seguintes desafios:

  • Quando uma transação atualiza uma linha de dados, ela adquire um bloqueio na linha de destino e não o libera até a confirmação ou reversão da transação. Durante esse período, apenas uma transação pode atualizar a linha, enquanto as demais precisam aguardar. Consequentemente, as solicitações de atualização para uma única linha quente são executadas serialmente. Estratégias tradicionais de fragmentação de banco de dados e tabelas oferecem melhorias limitadas de desempenho nesse cenário.

  • Nesses cenários, um grande volume de solicitações de atualização para linhas quentes pode atingir o sistema de banco de dados back-end em curto período. Esse comportamento gera contenção grave de bloqueios de linha e longos tempos de espera, degradando o desempenho do sistema. Uma espera prolongada por uma solicitação de atualização pode impactar significativamente as operações de negócios.

Apenas aumentar o hardware não atende a esses requisitos de baixa latência. Para solucionar isso, o PolarDB fornece otimizações inovadoras no nível do kernel do banco de dados. O sistema identifica automaticamente solicitações de atualização de linhas quentes e agrupa atualizações na mesma linha de dados ocorridas dentro de um intervalo de tempo específico. Diferentes grupos são então processados em paralelo usando um pipeline. Essas otimizações melhoram drasticamente o desempenho do sistema.

Solução técnica

  • Do processamento sequencial para pipeline

    O processamento paralelo é a maneira mais direta de melhorar o desempenho do banco de dados, mas paralelizar totalmente as operações de atualização na mesma linha quente é difícil. O PolarDB utiliza uma abordagem inovadora de processamento em pipeline para maximizar o paralelismo das operações de atualização de linhas quentes.

    image

    Instruções SQL usadas para operações de atualização de linhas quentes são marcadas com autocommit ou COMMIT_ON_SUCCESS. A camada de kernel otimizada do MySQL identifica automaticamente operações de atualização com essas marcas. Dentro de um determinado intervalo de tempo, ela executa um Hash nas operações de atualização coletadas com base em sua chave primária ou chave exclusiva. Para operações de atualização mapeadas no mesmo bucket pelo Hash, o kernel as agrupa e confirma em lotes de acordo com a ordem de chegada.

    Para processar essas operações de atualização em um pipeline, duas unidades de execução as agrupam. Quando o primeiro grupo é coletado e está pronto para confirmação, o segundo grupo começa imediatamente a coletar operações de atualização. Quando o segundo grupo é coletado e está pronto para confirmação, o primeiro grupo já foi confirmado e começa a coletar um novo lote de operações de atualização. Os dois grupos se alternam e executam em paralelo.

    Esse modelo de processamento em pipeline utiliza totalmente os recursos de hardware, aumenta a utilização da CPU e melhora a capacidade de processamento paralelo do sistema, maximizando seu throughput.

  • Eliminação de espera ao solicitar bloqueios de linha

    Para garantir a consistência lógica dos dados, uma atualização primeiro adquire um bloqueio na linha de dados de destino. Se a solicitação de bloqueio não puder ser concedida imediatamente, a solicitação entra em estado de espera. Isso não apenas aumenta a latência de processamento, mas também aciona a detecção de deadlock, adicionando sobrecarga extra.

    Conforme mencionado anteriormente, as operações de atualização na mesma linha de dados são agrupadas em ordem cronológica. A primeira operação de atualização em um grupo é o Leader. Ela lê a linha de dados de destino e a bloqueia. As operações de atualização subsequentes são Followers. Quando um Follower solicita um bloqueio na linha de dados de destino e verifica que o Leader já possui o bloqueio da linha, ele pode adquirir o bloqueio imediatamente sem esperar.

    Essa otimização reduz o número de aquisições de bloqueio de linha e a sobrecarga de tempo associada. Como resultado, o desempenho geral do sistema melhora significativamente.

  • Redução de travessias de índice B-tree

    O MySQL gerencia dados usando índices B-tree. Cada consulta deve percorrer o índice para localizar a linha de dados de destino. Quanto maior a tabela de dados e mais profundo o índice, mais longa será a travessia.

    No mecanismo de agrupamento descrito anteriormente, apenas o Leader de cada grupo percorre o índice para localizar a linha de dados e, em seguida, armazena em cache a linha atualizada na memória (Row Cache). Depois que um Follower no mesmo grupo adquire o bloqueio com sucesso, ele lê a linha de dados de destino diretamente da memória sem percorrer o índice novamente.

    Isso reduz o número total de travessias de índice e sua sobrecarga associada.

Pré-requisitos

  • Seu cluster PolarDB deve executar uma das seguintes versões:

    • PolarDB for MySQL 5.6, com versão secundária do mecanismo 20200601 ou posterior.

    • PolarDB for MySQL 5.7, com versão secundária do mecanismo 5.7.1.0.17 ou posterior.

    • PolarDB for MySQL 8.0, com versão secundária do mecanismo 8.0.1.1.10 ou posterior.

  • O binlog está habilitado.

  • O parâmetro de cluster rds_ic_reduce_hint_enable deve estar desabilitado.

    • Para PolarDB for MySQL 5.6 e PolarDB for MySQL 8.0, esse parâmetro é desabilitado por padrão.

    • Para PolarDB for MySQL 5.7, esse parâmetro é habilitado por padrão. Antes de ativar a otimização de linhas quentes, altere o valor do parâmetro para OFF.

    Nota

    Para garantir compatibilidade com arquivos de configuração do MySQL, o console do PolarDB adiciona o prefixo loose_ a todos os parâmetros de cluster. Para modificar o parâmetro rds_ic_reduce_hint_enable no console do PolarDB, selecione o parâmetro com o prefixo loose_, que é loose_rds_ic_reduce_hint_enable.

Limitações

A otimização de linhas quentes não se aplica nos seguintes cenários:

  • A tabela que contém a linha quente é particionada.

  • Um trigger está definido na tabela que contém a linha quente.

  • A linha quente utiliza o mecanismo Statement Queue.

  • Se o binlog global estiver habilitado, mas o binlog no nível de sessão estiver desabilitado, a otimização de linhas quentes não será aplicada a instruções UPDATE.

  • Após ativar a otimização de linhas quentes, colunas que dependem exclusivamente do atributo ON UPDATE CURRENT_TIMESTAMP para atualizações automáticas deixarão de ser atualizadas automaticamente. Atribua valores explicitamente a essas colunas em suas instruções UPDATE usando SET column_name = CURRENT_TIMESTAMP(n).

Uso

  1. Ative a otimização de linhas quentes.

    No console do PolarDB, modifique o seguinte parâmetro para ativar ou desativar a otimização de linhas quentes.

    Parâmetro

    Descrição

    hotspot

    Define se o recurso de otimização de linhas quentes deve ser ativado. Valores válidos:

    1. ON: ativado.

    2. OFF (padrão): desativado.

    Nota

    Para garantir compatibilidade com arquivos de configuração do MySQL, o console do PolarDB adiciona o prefixo loose_ a todos os parâmetros de cluster. Para modificar o parâmetro hotspot no console do PolarDB, selecione o parâmetro com o prefixo loose_, que é loose_hotspot.

  2. Use a sintaxe de hint para aplicar a otimização de linhas quentes.

    Hint

    Obrigatório

    Descrição

    COMMIT_ON_SUCCESS

    Obrigatório

    Confirma a transação se a atualização for bem-sucedida.

    ROLLBACK_ON_FAIL

    Opcional

    Reverte a transação se a atualização falhar.

    TARGET_AFFECT_ROW(1)

    Opcional

    Especifica que a solicitação deve atualizar apenas uma linha. Se essa condição não for atendida, a atualização falha.

    Nota

    Como este hint confirma automaticamente a transação, inclua-o na última instrução SQL da transação.

    Exemplo: Atualize o valor da coluna c na tabela sbtest.

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

Operações relacionadas

Parâmetros personalizados

Não é possível modificar os seguintes parâmetros no console do PolarDB. Para modificá-los, acesse o Quota Center, localize o ID de cota polardb_mysql_hotspot e clique em Apply na coluna Actions.

Parâmetro

Descrição

hotspot_for_autocommit

Define se a otimização de linhas quentes deve ser ativada para instruções UPDATE no modo autocommit. Valores válidos:

  • ON: ativado.

  • OFF (padrão): desativado.

hotspot_update_max_wait_time

Tempo máximo que um Leader aguarda para que Followers entrem em um grupo durante uma Group Update.

  • Unidade: microssegundos (us).

  • Valor padrão: 100.

hotspot_lock_type

Define se um novo tipo de bloqueio de linha deve ser ativado para Group Update. Valores válidos:

  • ON: ativado.

  • OFF (padrão): desativado.

Nota
  • Se este parâmetro estiver ativado, quando uma operação de atualização solicitar um bloqueio de linha para a mesma linha quente, ela poderá adquirir o bloqueio imediatamente sem esperar. Isso melhora o desempenho.

  • O novo tipo de bloqueio pode ser adquirido imediatamente sem espera.

Configurações de parâmetros

Execute o seguinte comando para visualizar as configurações de parâmetros da otimização de linhas quentes.

SHOW variables LIKE "hotspot%";

Resultado de exemplo:

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

Estatísticas de uso

Execute o seguinte comando para visualizar as estatísticas de uso da otimização de linhas quentes.

SHOW GLOBAL status LIKE 'Group_update%';

Teste de desempenho

Ferramenta de teste

O Sysbench é uma ferramenta de teste de desempenho de código aberto e multiplataforma. É usada principalmente para benchmarks de banco de dados, como MySQL, e para testes de desempenho do sistema em componentes como CPU, memória, I/O e threads. Suporta testes multithread e usa scripts Lua para controlar flexivelmente a lógica de teste. É adequada para cenários como avaliação de desempenho de banco de dados e testes de estresse.

Tabela e instrução de teste

  • Definição da tabela

    CREATE TABLE sbtest (id INT UNSIGNED NOT NULL, c BIGINT UNSIGNED NOT NULL, PRIMARY KEY (id));
  • Instrução de teste

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

Resultados do teste

PolarDB for MySQL 5.6

Cenário de teste

Uma única linha quente em uma CPU de 8 núcleos.

Resultados do teste

Neste cenário de teste, ativar a otimização de linhas quentes melhora o desempenho de atualização em linhas quentes relacionadas a estoque em quase 50 vezes sob alta concorrência.

Dados do teste (QPS)

image.png

Concorrência

1

8

16

32

64

128

256

512

1024

Otimização de linhas quentes desativada

1365.31

1863.94

1866.6

1862.64

1867.32

1832.51

1838.31

1819.52

1833.2

Otimização de linhas quentes ativada

1114.79

7000.19

12717.32

22029.48

43096.06

61349.7

83098.69

90860.94

87689

PolarDB for MySQL 5.7

Cenário de teste

Uma única linha quente em uma CPU de 8 núcleos.

Resultados do teste

Neste cenário de teste, ativar a otimização de linhas quentes melhora o desempenho de atualização em linhas quentes relacionadas a estoque em quase 35 vezes sob alta concorrência.

Dados do teste

QPS

image.png

Concorrência

1

8

16

32

64

128

256

512

1024

Otimização de linhas quentes desativada

1348.49

1892.29

1889.77

1895.86

1875.2

1850.26

1843.62

1849.92

1835.68

Otimização de linhas quentes ativada

1104.9

6886.89

12485.17

16003.23

16460.31

16548.86

27920.89

47893.96

66500.92

Latência do percentil 95

image

Concorrência

1

8

16

32

64

128

256

512

1024

Otimização de linhas quentes desativada

0,9

5,47

9,91

18,95

36,89

73,13

164,45

297,92

590,56

Otimização de linhas quentes ativada

1,08

1,44

1,58

3,25

5,28

9,56

12,08

13,22

18,28

PolarDB for MySQL 8.0

Cenário de teste

Uma única linha quente em uma CPU de 8 núcleos.

Resultados do teste

Neste cenário de teste, ativar a otimização de linhas quentes melhora o desempenho de atualização em linhas quentes relacionadas a estoque em quase 26 vezes sob alta concorrência.

Dados do teste

QPS

image

Concorrência

1

8

16

32

64

128

256

512

1024

Otimização de linhas quentes desativada

1559.14

2103.82

2116.4

2082.1

2079.74

2031.64

1993.09

1977.6

1983.61

Otimização de linhas quentes ativada

1237.28

7443.04

12244.19

15529.52

23041.15

33931.18

53924.24

54598.6

50988.22

Latência do percentil 95

image

Concorrência

1

8

16

32

64

128

256

512

1024

Otimização de linhas quentes desativada

0,8

5

8,9

17,32

33,12

66,84

153,02

287,38

549,52

Otimização de linhas quentes ativada

0,97

1,34

1,89

3,19

4,82

5,88

7,17

13,46

28,16

Etapas do teste de desempenho

  1. Prepare uma instância ECS e instale o Sysbench.

  2. Coloque o seguinte arquivo oltp_inventory.lua no diretório src/lua do código-fonte do 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. Conecte-se ao cluster usando a linha de comando.

  4. Execute o teste do Sysbench.

    1. Prepare os dados.

      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. Execute o teste.

      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

    Descrição

    mysql-host

    O endpoint do cluster.

    mysql-port

    A porta do endpoint do cluster.

    mysql-user

    O nome de usuário da conta do banco de dados.

    mysql-password

    A senha da conta do banco de dados.

    mysql-db

    O nome do banco de dados.

    Parâmetros de saída

    Parâmetro

    Métrica

    Descrição

    tables

    Número de tabelas

    O número total de tabelas usadas no teste.

    table_size

    Número de linhas por tabela

    O número de registros em cada tabela.

    Tamanho dos dados

    O tamanho dos dados da tabela, medido em unidades como MB ou GB.

    threads

    Número de threads concorrentes

    O número de threads configuradas.

    Status da thread

    O status em tempo real das threads em execução.