Comparação de Comportamento de Bloqueio ao Adicionar Campos em Grandes Tabelas em Oracle, MySQL e PostgreSQL

Comparação de Comportamento de Bloqueio ao Adicionar Campos em Grandes Tabelas em Oracle, MySQL e PostgreSQL

Este artigo analisa o impacto de bloqueios ao adicionar colunass em tabelas de alto volume em três sistemas de bancos de dados: Oracle, MySQL e PostgreSQL. A comparação abrange tipos de bloqueio, duração e efeitos em operações DML e consultas.

Ambiente de Teste

Os testes foram conduzidos com 50.000 registros nas seguintes versões:

Banco de Dados Versão Conjunto de Dados
Oracle 23.26.1.2.0 (26ai) 50.000 linhas
MySQL 8.0.45 50.000 linhas
PostgreSQL 16.13 50.000 linhas

Resumo dos Resultados

Tempo de Execução para Adicionar Colunas

Banco de Dados Sem Valor Padrão Com Valor Padrão Notas
Oracle ~50ms ~40ms Atualização de metadados apenas
MySQL 8.0+ ~1s <1ms Algoritmo INSTANT
PostgreSQL 11+ ~2ms ~2ms Recurso de valor padrão rápido

Tipos de Bloqueio

Banco de Dados Tipo de Bloqueio durante Adição de Coluna
Oracle Bloqueio DDL Exclusivo
MySQL Bloqueio MDL WRITE
PostgreSQL Bloqueio ACCESS EXCLUSIVE

Detalhes para Oracle

Resultados do Teste


Adicionar coluna sem valor padrão:
Início: 00:43:39.004
Fim: 00:43:39.054
Duração: aproximadamente 50ms

Adicionar coluna com valor padrão:
Início: 00:43:39.055
Fim: 00:43:39.095
Duração: aproximadamente 40ms

Mecanismo de Bloqueio do Oracle

Tipo de Bloqueio Descrição
Bloqueio DDL Exclusivo Impede outras operações DDL durante a adição
Row-X (SX) Bloqueio de linha exclusivo, mas permite consultas

Impacto em DML e Consultas

Tipo de Operação Efeito
SELECT Sem bloqueio (leitura consistente)
INSERT Bloqueio temporário durante DDL
UPDATE Bloqueio temporário durante DDL
DELETE Bloqueio temporário durante DDL

Recursos do Oracle


-- No Oracle 11g+, adicionar colunas com valor padrão usa atualização de metadados
-- Atualização física completa ocorre apenas quando necessário

ALTER TABLE tabela_grande ADD (campo_novo VARCHAR2(50) DEFAULT 'valor');

-- Requer atualização completa se:
-- 1. Valor padrão + restrição NOT NULL
-- 2. Coluna adicionada com NOT NULL explícito

Detalhes para MySQL

Resultados do Teste


Adicionar coluna sem valor padrão:
Início: 2026-03-24 00:39:15
Fim: 2026-03-24 00:39:16
Duração: aproximadamente 1s

Adicionar coluna com valor padrão (algoritmo INSTANT):
Início: 2026-03-24 00:39:16
Fim: 2026-03-24 00:39:16
Duração: <1ms (conclusão instantânea)

Mecanismo de Bloqueio do MySQL

Tipo de Bloqueio Descrição
Bloqueio MDL WRITE Bloqueio de metadados para escrita, impede DML durante DDL
Bloqueio MDL READ Bloqueio de metadados para leitura, adquirido por SELECT

Algoritmo INSTANT no MySQL 8.0


-- MySQL 8.0.12+ suporta o algoritmo INSTANT para adicionar colunas
-- Apenas metadados são modificados, sem alterar dados existentes

ALTER TABLE tabela_grande ADD COLUMN nova_coluna VARCHAR(50) DEFAULT 'valor';

-- Condições para uso do INSTANT:
-- 1. Coluna adicionada no final da tabela
-- 2. Com valor padrão ou permitindo NULL
-- 3. Sem operações complexas adicionais

Impacto em DML e Consultas

Tipo de Operação MySQL 5.7 MySQL 8.0 (INSTANT)
SELECT Bloqueado Sem bloqueio
INSERT Bloqueado Sem bloqueio
UDPATE Bloqueado Sem bloqueio
DELETE Bloqueado Sem bloqueio

Comparação entre Versões do MySQL

Versão Algoritmo para Adicionar Coluna Descrição
5.6 e anteriores COPY Cópia completa da tabela, bloqueio prolongado
5.7 INPLACE Atualização no local, ainda requer bloqueio de tabela
8.0.12+ INSTANT Apenas metadados modificados, conclusão imediata

Detalhes para PostgreSQL

Resultados do Teste


Adicionar coluna sem valor padrão:
Início: 2026-03-24 00:43:37.398548
Fim: 2026-03-24 00:43:37.400639
Duração: aproximadamente 2ms

Adicionar coluna com valor padrão:
Início: 2026-03-24 00:43:37.401066
Fim: 2026-03-24 00:43:37.403055
Duração: aproximadamente 2ms

Mecanismo de Bloqueio do PostgreSQL

Tipo de Bloqueio Descrição
Bloqueio ACCESS EXCLUSIVE Nível mais alto de bloqueio, impede todas as operações na tabela

Recurso de Valor Padrão Rápido no PostgreSQL 11+


-- PostgreSQL 11+ suporta valores padrão rápidos ao adicionar colunas
-- Apenas metadados são atualizados, sem reescrever a tabela

ALTER TABLE tabela_grande ADD COLUMN nova_coluna VARCHAR(50) DEFAULT 'valor';

-- Condições:
-- 1. Valor padrão é uma expressão constante
-- 2. Não envolve funções voláteis

Impacto em DML e Consultas

Tipo de Operação PostgreSQL 10 e anteriores PostgreSQL 11+
SELECT Bloqueado Bloqueio temporário
INSERT Bloqueado Bloqueio temporário
UPDATE Bloqueado Bloqueio temporário
DELETE Bloqueado Bloqueio temporário

Níveis de Blqoueio no PostgreSQL


Níveis de bloqueio (do menor para o maior):
1. ACCESS SHARE      - SELECT
2. ROW SHARE         - SELECT FOR UPDATE
3. ROW EXCLUSIVE     - INSERT/UPDATE/DELETE
4. SHARE UPDATE EXCLUSIVE - VACUUM, ANALYZE
5. SHARE             - CREATE INDEX
6. SHARE ROW EXCLUSIVE - CREATE TRIGGER
7. EXCLUSIVE         - REFRESH MATERIALIZED VIEW
8. ACCESS EXCLUSIVE  - ALTER TABLE, DROP TABLE

Duração do Bloqueio Comparada

Duração ao Adicionar Colunas

Banco de Dados Duração do Bloqueio Área de Impacto
Oracle Milissegundos Apenas durante operação DDL
MySQL 8.0 INSTANT <1ms Praticamente sem impacto
MySQL 5.7 INPLACE Segundos a minutos Requer verificação completa da tabela
PostgreSQL 11+ Milissegundos Apenas durante operação DDL

Impacto em Cenários com Grandes Volumes de Dados

Volume de Dados Oracle MySQL 8.0 PostgreSQL 11+
100.000 linhas ~50ms <1ms ~2ms
1.000.000 linhas ~50ms <1ms ~2ms
10.000.000 linhas ~50ms <1ms ~2ms
100.000.000 linhas ~50ms <1ms ~2ms

Recomendações de Boas Práticas

Para Oracle


-- Recomendado: usar valor padrão para evitar atualizações futuras
ALTER TABLE tabela_grande ADD (campo_novo VARCHAR2(50) DEFAULT 'valor');

-- Evitar: adicionar restrição NOT NULL (requer atualização completa)
ALTER TABLE tabela_grande ADD (campo_novo VARCHAR2(50) NOT NULL);  -- Não recomendado

-- Alternativa: adicionar NOT NULL em etapas
ALTER TABLE tabela_grande ADD (campo_novo VARCHAR2(50) DEFAULT 'valor');
-- Após atualização pela aplicação
ALTER TABLE tabela_grande MODIFY (campo_novo VARCHAR2(50) NOT NULL);

Para MySQL


-- Recomendado: usar algoritmo INSTANT (MySQL 8.0.12+)
ALTER TABLE tabela_grande ADD COLUMN nova_coluna VARCHAR(50) DEFAULT 'valor';

-- Verificar uso do INSTANT
ALTER TABLE tabela_grande ADD COLUMN nova_coluna VARCHAR(50), ALGORITHM=INSTANT;

-- Evitar: adicionar coluna no meio da tabela (não suporta INSTANT)
ALTER TABLE tabela_grande ADD COLUMN nova_coluna VARCHAR(50) AFTER id;  -- Requer COPY

-- Listar suporte de algoritmo
SHOW CREATE TABLE tabela_grande;

Para PostgreSQL


-- Recomendado: usar valor padrão rápido (PostgreSQL 11+)
ALTER TABLE tabela_grande ADD COLUMN nova_coluna VARCHAR(50) DEFAULT 'valor';

-- Evitar: usar funções voláteis como valor padrão
ALTER TABLE tabela_grande ADD COLUMN nova_coluna TIMESTAMP DEFAULT now();  -- Requer reescrita da tabela

-- Alternativa: usar valor constante
ALTER TABLE tabela_grande ADD COLUMN nova_coluna TIMESTAMP DEFAULT '2024-01-01';

-- Monitorar bloqueios
SELECT * FROM pg_locks WHERE relation = 'tabela_grande'::regclass;

Tags: Oracle MySQL postgresql bloqueio DDL alteração de esquema

Publicado em 6-8 20:10 por Thomas