A instrução ALTER TABLE em uma tabela grande pode bloquear todas as novas transações por minutos ou horas. Quando uma instrução DDL de bloqueio mantém a fila de solicitações de bloqueio MDL-X aberta, cada transação que acessa essa tabela fica presa atrás dela — e se a fila crescer o suficiente, o esgotamento de conexões pode derrubar toda a sua aplicação. O DDL sem bloqueio elimina esse risco: a instrução DDL tenta adquirir o bloqueio em intervalos curtos, liberando sua posição na fila entre as tentativas para que as novas transações continuem em execução.
Como funciona
O sistema de bloqueio de metadados (MDL) do MySQL protege as tabelas durante as alterações de esquema. Uma instrução DDL de bloqueio solicita um bloqueio exclusivo MDL-X e mantém a fila de solicitações bloqueada até adquirir o bloqueio. Como o MDL-X tem a maior prioridade, cada nova transação que acessa a tabela fica presa atrás da instrução DDL — mesmo que o próprio DDL ainda esteja aguardando a conclusão de uma transação mais antiga.
O DDL sem bloqueio altera esse comportamento:
A instrução DDL tenta adquirir o bloqueio MDL-X dentro de um tempo limite curto (
loose_polar_nonblock_ddl_lock_wait_timeout, padrão: 1 segundo).Se o bloqueio não estiver disponível, a instrução DDL libera completamente sua posição na fila. Como a fila não está mais bloqueada, as transações pendentes e as novas podem adquirir seus próprios bloqueios e prosseguir normalmente.
Após um intervalo configurável (
loose_polar_nonblock_ddl_retry_interval, padrão: 6 segundos), a instrução DDL tenta novamente.Os passos 2–3 se repetem até
loose_polar_nonblock_ddl_retry_timestentativas.
Durante os intervalos de nova tentativa, a tabela permanece totalmente acessível. As transações por segundo (TPS) podem cair brevemente quando o DDL adquire o bloqueio, mas nunca chegam a zero.
O DDL sem bloqueio tem prioridade inferior ao DDL de bloqueio e maior chance de falhar ao adquirir o bloqueio MDL-X. Use-o quando a continuidade do negócio for mais importante do que a velocidade da alteração de esquema.
Versões compatíveis
O DDL sem bloqueio requer um dos seguintes:
PolarDB for MySQL 8.0.1 na versão de revisão 8.0.1.1.29 ou posterior
PolarDB for MySQL 8.0.2 na versão de revisão 8.0.2.2.12 ou posterior
Para verificar a versão de revisão do seu cluster, consulte Versões do mecanismo 5.6, 5.7 e 8.0.
Instruções DDL compatíveis
As instruções que suportam o DDL sem bloqueio dependem da sua versão de revisão.
| Versão de revisão | Instruções compatíveis | Observações |
|---|---|---|
| 8.0.1.1.29 ou posterior, ou 8.0.2.2.12 | ALTER TABLE apenas | Para desfragmentar uma tabela InnoDB, use ALTER TABLE table_name ENGINE=InnoDB em vez de OPTIMIZE TABLE table_name |
| 8.0.2.2.13 ou posterior | ALTER TABLE, OPTIMIZE TABLE, TRUNCATE TABLE | — |
Ativar o DDL sem bloqueio
Todos os quatro parâmetros são de nível de sessão. Defina-os na mesma sessão antes de executar a instrução DDL.
Passo 1: Ativar o modo DDL sem bloqueio
SET SESSION loose_polar_nonblock_ddl_mode = ON;O parâmetro loose_polar_nonblock_ddl_mode está desativado (OFF) por padrão.
Passo 2: Configurar o comportamento de nova tentativa
SET SESSION loose_polar_nonblock_ddl_retry_times = 4194304;
SET SESSION loose_polar_nonblock_ddl_retry_interval = 6;
SET SESSION loose_polar_nonblock_ddl_lock_wait_timeout = 1;| Parâmetro | Padrão | Valores válidos | Unidade | Quando alterar |
|---|---|---|---|---|
loose_polar_nonblock_ddl_retry_times | 0 (derivado de lock_wait_timeout) | 0–31536000 | — | Defina como 4194304 para alterações de esquema de longa duração em tabelas grandes |
loose_polar_nonblock_ddl_retry_interval | 6 | 1–31536000 | Segundos | Aumente para reduzir a contenção de bloqueio; diminua para concluir o DDL mais rapidamente |
loose_polar_nonblock_ddl_lock_wait_timeout | 1 | 1–31536000 | Segundos | Aumente se o bloqueio não for adquirido com frequência suficiente sob uma carga pesada de escrita |
Para mais informações sobre como aplicar esses parâmetros, consulte Configurar parâmetros de cluster e nó.
Passo 3: Executar a instrução DDL
ALTER TABLE table_name ADD INDEX index_name (column1, column2, column3);A instrução é executada com comportamento sem bloqueio para a sessão atual. Outras sessões não são afetadas.
Teste de desempenho
Os testes a seguir comparam o DDL de bloqueio, o DDL sem bloqueio e a ferramenta de alteração de esquema online gh-ost usando o SysBench. Para mais informações sobre o SysBench, consulte Teste de desempenho OLTP.
Test environment: PolarDB for MySQL 8.0, Cluster Edition, 8 núcleos de CPU, 64 GB de memória.
Configuração
Crie uma tabela com 1 milhão de linhas:
./oltp_read_write.lua --mysql-host="Cluster endpoint" --mysql-port="Port number" \ --mysql-user="Username" --mysql-password="Password" \ --mysql-db="sbtest" --tables=1 --table-size=1000000 \ --report-interval=1 --percentile=99 --threads=8 --time=6000 prepareSimule uma carga de trabalho de leitura/gravação:
./oltp_read_write.lua --mysql-host="Cluster endpoint" --mysql-port="Port number" \ --mysql-user="Username" --mysql-password="Password" \ --mysql-db="sbtest" --tables=1 --table-size=1000000 \ --report-interval=1 --percentile=99 --threads=8 --time=6000 runMantenha um bloqueio MDL iniciando uma transação e deixando-a aberta:
/* Session 1 */ BEGIN; SELECT * FROM sbtest1;Em uma segunda sessão, adicione uma coluna à tabela:
/* Session 2 */ ALTER TABLE sbtest1 ADD COLUMN d INT;Repita a alteração de esquema usando gh-ost (requer log binário — consulte Ativar log binário):
./gh-ost --assume-rbr --user="Username" --password="Password" \ --host="Cluster endpoint" --port="Port number" \ --database="sbtest" --table="sbtest1" --alter="ADD COLUMN d INT" \ --allow-on-master --aliyun-rds \ --initially-drop-old-table --initially-drop-ghost-table --execute
Impacto no TPS
DDL de bloqueio (DDL sem bloqueio desativado) — O TPS cai a zero e permanece assim até que o DDL seja concluído.

DDL sem bloqueio — O TPS cai periodicamente quando o DDL tenta novamente o bloqueio, mas nunca chega a zero. O impacto nos negócios é mínimo.

gh-ost — O TPS cai a zero em picos periódicos. O gh-ost funciona criando uma tabela ghost, aplicando as alterações nela e, em seguida, renomeando atomicamente a tabela ghost no lugar (a etapa de corte). Esse corte requer um breve bloqueio de tabela, que causa as quedas periódicas de TPS.

Comparação de velocidade em 100 milhões de linhas
Colunas foram adicionadas a uma tabela com 100 milhões de linhas usando DDL sem bloqueio (algoritmos INSTANT, INPLACE e COPY) e gh-ost.
Sem carga de trabalho — O DDL sem bloqueio é concluído mais rapidamente que o gh-ost.

Carga de trabalho de leitura/gravação — O DDL sem bloqueio ainda é concluído mais rapidamente que o gh-ost.

O DDL sem bloqueio mantém o TPS acima de zero durante toda a alteração de esquema e é concluído mais rapidamente que o gh-ost, tanto em ambientes sem carga quanto em cargas similares às de produção.
Tópicos relacionados
Se você tiver dúvidas sobre operações DDL, entre em contato conosco.