Este artigo é a base de uma pequena série dedicada à solução HADR. Esta é uma solução simples de alta-disponibilidade que apareceu pela primeira vez no Db2 8.2, sendo baseada originalmente no HDR do Informix. O objetivo aqui não é abordar detalhes da solução que serão alvo de outros artigos mas apenas construir uma configuração de HADR que sirva para tornar visível o modelo base de funcionamento:
- Uma base de dados primária
- Uma base de dados standby
- Propagação de modificações da primária para a standby
- Validação básica de que o replay na secundária está a acontecer
O lab usa uma infraestrutura simples composta por dois containers Docker com o Db2 Community Edition 12.1.4 no mesmo host.
1. Objetivos do lab
No fim deste lab deverá ser capaz de:
- Explicar os papéis das bases de dados HADR primária e standby
- Construir um lab HADR mínimo com dois nós em Docker
- Configurar os parâmetros HADR em ambas as bases de dados
- Restaurar corretamente o backup da primary na standby
- Arrancar o HADR e confirmar que o par atinge o estado
PEER - Validar que alterações confirmadas na base de dados primária aparecem na standby
2. O que este artigo cobre e o que não cobre
Este artigo cobre:
- A arquitetura HADR básica
- Uma configuração simples com apenas uma base de dados standby e sem gestor de cluster pra automação
Este artigo não cobre:
- Gestor de cluster (Pacemaker)
- Failover automático
- Múltiplas bases de dados standby
- Ajustamento de configurações (exemplo: peer window, delayed replay)
3. Ambiente necessário
Para este lab, necessita:
- Docker e Docker Compose
- 8 GB de RAM costumam ser suficientes para um lab pequeno numa máquina com pouca carga
O Db2 LUW 12.1.4 Community Edition é descarregado do icr.io
Pressupostos importantes:
- O lab executa ambos os containers no mesmo host
- A tag da imagem é fixada em
12.1.4.0para manter o lab reproduzível
4. HADR em um minuto
No nível mais básico, o HADR funciona através dos seguintes eventos:
1. A base de dados primária recebe modificações de dados 2. O Db2 envia registos de log para a base de dados de standby 3. A base de dados de standby faz o replay desses registos de log 4. A base de dados standby fica pronta para takeover se a primary falhar
Os estados HADR mais importantes que verá numa solução HADR são:
| Estado | Significado |
|---|---|
REMOTE_CATCHUP | A base de dados standby está a receber as modificações e a fazer replay de logs, mas ainda não está totalmente sincronizada com a primária |
PEER | A base de dados primária e standby estão sincronizadas ao nível operacional normal para o modo de sincronização selecionado |
DISCONNECTED | A comunicação HADR está interrompida |
Para este artigo, a condição de sucesso é simples:
- O par HADR atinge
PEER - Uma alteração confirmada na base de dados primária torna-se visível na base de dados standby
- Conseguimos efetuar o takeover manual com sucesso
4.1 Porque é que o HADR começa com backup e restore
O HADR não constrói a base de dados standby copiando tabelas individualmente nem fazendo replay de tudo o que aconteceu na base de dados primary desde o início. A standby tem primeiro de arrancar a partir de uma imagem consistente da base de dados primária, e é por isso que a configuração começa com:
1. Criação de um backup da base de dados primária 2. Criação da base de dados standby através de restore desse backup
Essa sequência é importante do ponto de vista conceptual:
- O backup dá à base de dados de standby um ponto de arranque consistente e conhecido
- O restore torna a base de dados standby estruturalmente idêntica à primary nesse momento
- O HADR irá manter a standby atualizada através do envio e replay dos registos de logs gerados após o backup
4.2 O que fazem a primary e a standby
Os dois papéis não são simétricos.
| Papel | Responsabilidade |
|---|---|
| Primária | Aceita escritas das aplicações, gera registos de log e envia-os |
| Standby | Recebe os registos de log enviados, faz replay desses registos e mantém-se pronta para takeover |
Na configuração básica usada aqui:
- Todas as atualizações acontecem na base de dados primária
- A standby não serve workload aplicacional normal
- A standby pode ainda assim ser usada para verificações administrativas e queries pontuais de validação no lab
- A standby existe principalmente para se manter sincronizada e pronta
4.3 O que é que o HADR sincroniza
O HADR não sincroniza diretamente “linhas”. Sincroniza a base de dados primária e a standby através do fluxo de registos de log da base de dados:
- Uma aplicação faz commit na base de dados primária
- O Db2 escreve os registos de log correspondentes
- Esses registos de log são enviados para a base de dados de standby
- A base de dados de standby faz replay desses registos de log, atualizando a sua cópia da base de dados
É por isso que archive logging e roll-forward recovery são tão importantes na configuração de HADR. Sem a configuração de logging correta, a base de dados de standby não pode ser mantida através do replay do fluxo de registos de log provenientes da base de dados primária.
4.4 O que é que o modo de sincronização muda realmente
Um dos primeiros parâmetros HADR que as pessoas consideram é HADR_SYNCMODE. Ele define um trade-off importante entre latência e proteção de dados.
Em termos simples:
| Modo de sincronização | O que significa operacionalmente |
|---|---|
SYNC | O commit na primary só termina depois de a standby confirmar que os registos de log já foram escritos nos seus ficheiros de log. |
NEARSYNC | O commit na base de dados primária continua dependente de confirmação da standby, mas aqui a standby pode confirmar mais cedo: basta que os registos de log tenham sido recebidos e colocados em memória. A confirmação já não espera pela escrita dos logs em disco. |
ASYNC | O commit na base de dados primária termina após os registos de log da transação serem escritos em disco e serem entregues ao stack TCP para seguirem para a standby. |
SUPERASYNC | O commit termina imediatamente após escrita dos registos de log da transação em disco. |
Isto explica por que razão:
SYNCoferece a proteção mais forte porque no momento do commit o log já está persistido em ambas as bases de dados.NEARSYNCtem latência menor, porque a base de dados de standby não precisa de esperar pela escrita em disco antes de confirmar. Continua a ser um modo forte de proteção, mas aceita um risco ligeiramente maior: se ambas as bases de dados falharem em simultâneo antes de que a standby escreva os registos de log para disco, essas modificações perdem-se no standby.
Outra forma de pensar nos quatro modos de sincronização é:
| Prioridade | Modos mais adequados |
|---|---|
| Minimizar possível perda de transações | SYNC, depois NEARSYNC |
| Reduzir o impacto na latência de commit da base de dados primária | ASYNC, depois SUPERASYNC |
| Manter um equilíbrio prático em muitos cenários standard de HA | NEARSYNC |
A pergunta a fazer não será “qual é o melhor modo de sincronização?”. As perguntas que interessam são:
- Quanta latência adicional no commit da base de dados primária podemos tolerar?
- Qual o desfasamento máximo que a standby pode tolerar?
- Que exposição a perda de dados é aceitável em caso de falha da base de dados primária?
4.5 O que significa realmente o modo PEER
Quando o par HADR atinge PEER, o Db2 está a dizer-lhe que a relação HADR ficou totalmente estabelecida para o modo de sincronização selecionado.
Operacionalmente, isso significa:
- A comunicação entra as bases de dados está a funcionar
- A base de dados de standby está atualizada ao nível esperado para o modo de configuração configurado
- O par HADR está no seu estado operacional estável normal
Isso não significa que o ambiente seja automaticamente altamente disponível no sentido mais amplo de cluster. Neste artigo não existe cluster manager, nem relocalização de serviço, nem orquestração automática. PEER significa apenas que o par de bases de dados está saudável enquanto relação HADR.
4.6 Onde entrará o Pacemaker mais tarde
Este artigo ignora deliberadamente o uso do Pacemaker.
Porquê?
Porque o Pacemaker resolve um problema diferente:
- O HADR mantém as cópias da base de dados sincronizadas
- O Pacemaker automatiza o controlo de recursos e as decisões de failover em torno dessas cópias.
5. Criar o diretório de trabalho
Execute para criar a pasta de trabalho e mudar-se para lá.
mkdir db2-hadr-foundation-lab
cd db2-hadr-foundation-lab6. Criar docker-compose.yml
Estabeleça uma sessão de edição para criar o ficheiro docker-composer.yaml:
vi docker-compose.ymlCole o seguinte conteúdo:
services:
db2pri:
image: icr.io/db2_community/db2:12.1.4.0
container_name: db2pri
privileged: true
hostname: db2pri
environment:
LICENSE: accept
DB2INST1_PASSWORD: passw0rd
ports:
- "50000:50000"
volumes:
- db2pri_data:/database
healthcheck:
test: ["CMD", "su", "-", "db2inst1", "-c", "db2 list db directory"]
interval: 30s
timeout: 10s
retries: 15
start_period: 600s
db2std:
image: icr.io/db2_community/db2:12.1.4.0
container_name: db2std
privileged: true
hostname: db2std
environment:
LICENSE: accept
DB2INST1_PASSWORD: passw0rd
ports:
- "50001:50000"
volumes:
- db2std_data:/database
healthcheck:
test: ["CMD", "su", "-", "db2inst1", "-c", "db2 list db directory"]
interval: 30s
timeout: 10s
retries: 15
start_period: 600s
volumes:
db2pri_data:
name: db2pri_data
db2std_data:
name: db2std_data7. Arrancar os containers
Estabeleça a configuração definida no docker-compose.yml.
docker compose up -dEspere um pouco e verifique o estado dos containers:
docker psSe algum container ainda estiver a arrancar, espere e volte a verificar:
sleep 30
docker psNão continue enquanto ambos os contentores não estiverem healthy. Na configuração, estabeleci um timeout de 600s. Se não for suficiente, terá de ajustar no docker-compose.yml e repetir os passos anteriores para estabelecer de novo a configuração.
Verifique o nível de código do Db2:
docker compose exec db2pri su - db2inst1 -c "db2level"
docker compose exec db2std su - db2inst1 -c "db2level"Ambos os container devem indicar 12.1.4.0.
8. Criar a base de dados primary
Crie a base de dados primária no container db2pri:
docker compose exec db2pri su - db2inst1 -c "db2 create db HADRDB"Crie uma pequena tabela e insira alguns dados de exemplo:
docker compose exec db2pri su - db2inst1 -c \
"db2 connect to HADRDB && \
db2 create schema app && \
db2 \"create table app.orders (id int not null, amount decimal(10,2), primary key(id))\" && \
db2 \"insert into app.orders values (1,100.00),(2,250.00),(3,400.00)\" && \
db2 commit && \
db2 connect reset"9. Ativar archive logging na primary
O HADR exige roll-forward recovery, e por isso a base de dados primária terá de ser alterada.
Configure archive logging:
docker compose exec db2pri su - db2inst1 -c \
"mkdir -p /database/config/db2inst1/archive/HADRDB && \
db2 update db cfg for HADRDB using LOGARCHMETH1 DISK:/database/config/db2inst1/archive/HADRDB"Reinicie a instância:
docker compose exec db2pri su - db2inst1 -c \
"db2stop force && db2start"Verifique:
docker compose exec db2pri su - db2inst1 -c \
"db2 get db cfg for HADRDB | grep -i logarchmeth1"10. Configurar HADR na base de dados primária
Ajuste a configuração da base de dados para suportar HADR.
docker compose exec db2pri su - db2inst1 -c \
"db2 update db cfg for HADRDB using \
HADR_LOCAL_HOST db2pri \
HADR_LOCAL_SVC 60000 \
HADR_REMOTE_HOST db2std \
HADR_REMOTE_SVC 60000 \
HADR_REMOTE_INST db2inst1 \
HADR_SYNCMODE NEARSYNC \
HADR_TIMEOUT 120 \
LOGINDEXBUILD ON"Para este artigo:
| Parâmetro | Valor | Motivo |
|---|---|---|
HADR_LOCAL_HOST | db2pri | hostname da primary |
HADR_REMOTE_HOST | db2std | hostname da standby |
HADR_LOCAL_SVC / HADR_REMOTE_SVC | 60000 | porta de comunicação a usar pelo HADR |
HADR_SYNCMODE | NEARSYNC | modo de sincronização que escolhemos |
11. Produzir um backup offline da base de dados primária
Desative a base de dados e efetue o backup.
docker compose exec db2pri su - db2inst1 -c \
"rm -rf /database/config/db2inst1/backups/hadrdb && \
mkdir -p /database/config/db2inst1/backups/hadrdb && \
db2 deactivate db HADRDB && \
db2 backup db HADRDB to /database/config/db2inst1/backups/hadrdb"12. Copiar a imagem de backup para a standby
Copie o ficheiro de backup de forma a estar disponível no container db2std.
rm -rf /tmp/hadrdb-backup
mkdir -p /tmp/hadrdb-backup
docker cp db2pri:/database/config/db2inst1/backups/hadrdb/. /tmp/hadrdb-backup/
docker compose exec db2std su - db2inst1 -c "rm -rf /database/config/db2inst1/backups/hadrdb && mkdir -p /database/config/db2inst1/backups/hadrdb"
docker cp /tmp/hadrdb-backup/. db2std:/database/config/db2inst1/backups/hadrdb/13. Restaurar a base de dados na standby
Crie a base de dados standby através de restore do backup no container db2std.
docker compose exec db2std su - db2inst1 -c \
"db2 restore db HADRDB from /database/config/db2inst1/backups/hadrdb into HADRDB replace existing without prompting"SQL2540W com warning 2539 é aceitável aqui. Ele ocorre porque o restore foi concluído, mas a base de dados standby ainda não está pronta para utilização normal: continua a necessitar de recuperação adicional a partir dos logs. Este é justamente o estado esperado para ser que possa ser iniciada como standby através do comando START HADR AS STANDBY.
14. Configurar HADR na standby
Ajustamos as configurações de HADR na base de dados de standby.
docker compose exec db2std su - db2inst1 -c \
"db2 update db cfg for HADRDB using \
HADR_LOCAL_HOST db2std \
HADR_LOCAL_SVC 60000 \
HADR_REMOTE_HOST db2pri \
HADR_REMOTE_SVC 60000 \
HADR_REMOTE_INST db2inst1 \
HADR_SYNCMODE NEARSYNC \
HADR_TIMEOUT 120 \
LOGINDEXBUILD ON"Neste ponto:
- O backup já foi restaurado na standby
- Os parâmetros HADR do lado da standby já estão configurados
- A base de dados está pronta para
START HADR AS STANDBY
15. Arrancar o HADR
Arranque primeiro a base de dados de standby:
docker compose exec db2std su - db2inst1 -c \
"db2 start hadr on db HADRDB as standby"Depois arranque a base de dados primária:
docker compose exec db2pri su - db2inst1 -c \
"db2 start hadr on db HADRDB as primary"16. Confirmar o estado HADR
Verifique os estado do HADR em ambos os lados:
docker compose exec db2pri su - db2inst1 -c "db2pd -db HADRDB -hadr"
docker compose exec db2std su - db2inst1 -c "db2pd -db HADRDB -hadr"O par HADR deverá passar para PEER.
Também pode usar a função de tabela mon_get_hadr() para o mesmo efeito:
docker compose exec db2pri su - db2inst1 -c \
"db2 connect to HADRDB && db2 \"select hadr_role, hadr_state from table(mon_get_hadr(-2)) as t\" && db2 connect reset"17. Validações básicas
Agora efetue e confirme uma modificação na base de dados primária:
docker compose exec db2pri su - db2inst1 -c \
"db2 connect to HADRDB && db2 \"insert into app.orders values (4,500.00)\" && db2 commit && db2 connect reset"Valide que os dados estão também na base de dados de standby:
docker compose exec db2std su - db2inst1 -c \
"db2 connect to HADRDB && db2 \"select * from app.orders with ur\" && db2 connect reset"Neste ponto:
- A base de dados primária e a de standby estão configuradas corretamente
- O archive logging está ativo
- O HADR foi arrancado em ambos os lados e o par HADR está no modo operacional correto (
PEER) - As alterações efetuadas na base de dados primária são aplicadas na standby
Não demonstrámos:
- Takeover manual
- Failover automatizado
- Comportamento de client reroute
- Comportamento de replay-only window
Vamos ainda demonstrar a operação de takeover manual.
19. Fundamentos do takeover manual
Em Db2 HADR, um takeover muda os papéis das bases de dados:
- A standby torna-se a nova primária
- A antiga primária tornar-se-á standby, se conseguir voltar a ligar-se e assumir esse papel
Este é o mecanismo de failover mais simples de compreender porque é iniciado explicitamente por um operador ou administrador.
O comando básico é emitido na standby:
db2 takeover hadr on db HADRDBExiste também uma variante com opção by force:
db2 takeover hadr on db HADRDB by forceA diferença é importante:
| Comando | Utilização típica |
|---|---|
TAKEOVER HADR | Mudança de papel controlada quando ambos os lados estão suficientemente saudáveis para uma transição coordenada |
TAKEOVER HADR BY FORCE | Promoção de emergência quando a antiga primária está indisponível ou a ligação foi interrompida |
Deve ser sempre tentado um takeover normal e reservar BY FORCE apenas para cenários em que a antiga primary não consiga mais participar no HADR.
20. Preocupações operacionais antes do takeover
Antes de efetuar um takeover manual, verifique estes pontos:
| Aspeto | Porque importa |
|---|---|
| Estado HADR | Um takeover limpo funciona melhor quando o par está em PEER |
| Atividade de escrita das aplicações | Trabalho em curso na antiga primary pode ser interrompido pela mudança de papel das bases de dados |
| Ligações de clientes | Os clientes têm de se voltar a ligar à nova primária, a menos que exista uma solução de redirecionamento |
| Modo de sincronização | Em modos menos exigentes, a standby pode estar atrasada em relação à primária no momento da falha |
| Risco de takeover forçado | BY FORCE pode aumentar a exposição à perda de dados se a antiga primária tiver registos de logs para operações committed e que ainda não foram enviados |
21. Validar um takeover manual limpo
Primeiro confirme os papéis atuais das duas bases de dados:
docker compose exec db2pri su - db2inst1 -c "db2pd -db HADRDB -hadr"
docker compose exec db2std su - db2inst1 -c "db2pd -db HADRDB -hadr"Nesta fase deverá ver:
db2pricomo primarydb2stdcomo standby
Agora efetue o takeover a partir da standby:
docker compose exec db2std su - db2inst1 -c \
"db2 takeover hadr on db HADRDB"22. Confirmar a inversão de papéis
Verifique ambos os lados novamente:
docker compose exec db2pri su - db2inst1 -c "db2pd -db HADRDB -hadr"
docker compose exec db2std su - db2inst1 -c "db2pd -db HADRDB -hadr"Agora o resultado esperado será:
db2stdé primarydb2prié standby
Se isso acontecer, o takeover manual funcionou.
23. Validar escritas na nova base de dados primária
Insira uma nova linha na nova base de dados primária, que agora é db2std:
docker compose exec db2std su - db2inst1 -c \
"db2 connect to HADRDB && db2 \"insert into app.orders values (5,650.00)\" && db2 commit && db2 connect reset"Depois valide a partir da nova standby, que agora é db2pri:
docker compose exec db2pri su - db2inst1 -c \
"db2 connect to HADRDB && db2 \"select * from app.orders with ur\" && db2 connect reset"Se a linha estiver visível:
- Os papéis mudaram com sucesso
- O envio do log continuou a funcionar corretamente após o takeover
24. O que este takeover manual não resolve
O takeover manual é importante, mas continua a ser uma operação manual.
Por si só, não fornece:
- Deteção automática de falha da primary
- Decisão automática de promoção da base de dados standby
- Movimentação de endereço IP virtual
- Reconexão automática de aplicações
É aqui que entra um software de gestão de cluster como o Pacemaker ou o TSAMP.
26. Cleanup
Para remover o lab completo, destrua os containers e os volumes Docker:
docker compose down -v27. Resumo
Este é um lab de HADR muito simples:
- Uma base de dados primária
- Uma base de dados de standby
- Sem Pacemaker
- Takeover manual
Apesar de simples, deverá ser útil para perceber a mecânica central da solução antes de acrescentar tópicos mais avançados como peer window, delayed replay e failover gerido por cluster.
Referências
- IBM Docs: High availability disaster recovery (HADR)
- IBM Docs: HADR configuration parameters
- IBM Docs: db2pd command