Temos uma tabela que serve como tabela de trilha de auditoria para um aplicativo. Vamos chamá-lo ProductAudit
e vamos chamar a tabela de dados para esta tabela de auditoria Products
. ProductsAudit
foi poluído com cerca de 150 milhões de linhas devido a um bug. Existem cerca de 2 milhões de linhas válidas que precisam permanecer.
Então, para limpeza, eu quero:
- criar uma nova tabela,
ProductAudit_TEMP
- copiar mais de 2 milhões de linhas boas
- mesa suspensa
ProductAudit
- renomear
ProductAudit_TEMP
paraProductAudit
.
Isso será muito mais rápido do que excluir os 150 milhões de linhas inválidas - mesmo em lotes.
Minha pergunta é, a tabela Products
possui gatilhos INSERT, UPDATE e DELETE, que gravam na tabela ProductAudit
. Meu plano quebrará os gatilhos? Terei todos os usuários fora do sistema e até mesmo desabilitarei os gatilhos por segurança ao realizar a limpeza.
EDITAR:
Só para esclarecer, ProductAudit
não tem gatilhos, Products
tem. ProductAudit
está sendo preenchido pelos gatilhos INSERT, UPDATE e DELETE que pertencem à tabela Products
.
Como @AaronBertrand apontou em seu comentário, os objetos são anexados a outros objetos por object_id , não por object name . Dito isto, existe uma maneira de mover dados de uma tabela para outra sem a necessidade de usar
sp_rename
.Como o código de exemplo é a maneira mais limpa de mostrar como algo funciona, criei o código de teste a seguir para ilustrar como usar
ALTER TABLE ... SWITCH
a sintaxe para habilitar a migração de dados.Primeiro, criaremos uma tabela
Product
e "existente"ProductAudit
, com um gatilho naProduct
tabela, que insere linhas naProductAudit
tabela:Aqui, vamos inserir 100.000 linhas na
Product
tabela:Resultados das
SELECT
consultas acima:Isso criará uma tabela "temporária" para conter as linhas que queremos reter:
Este código "migra" os dados da tabela existente para a nova tabela, mantendo os triggers presentes na tabela original, sem recriá-los. A
ALTER TABLE ... SWITCH
sintaxe é uma operação somente de metadados que é extremamente rápida, tornando essa uma ótima maneira de migrar dados. O código abaixo define o nível de isolamento da transação para bloquear as tabelas envolvidas para impedir que outros processos insiram ou atualizem dados em qualquer uma das tabelas envolvidas.Resultados:
Aqui, inseriremos outras 10 linhas na
dbo.Product
tabela para provar que o gatilho ainda funciona:Resultados:
Se o acionador estiver na tabela Produtos e estiver gravando na tabela ProductAudit, tudo bem, desde que exista uma tabela chamada ProductAudit no momento em que o acionador for executado.
O truque é garantir que você não tenha linhas de auditoria sendo gravadas pelo gatilho depois de achar que já moveu todas as linhas boas de ProductAudit para ProductAudit_TEMP. A maneira simples de garantir que isso não aconteça seria definir o banco de dados para algo como o modo RESTRICTED_USER e garantir que ninguém mais possa se conectar. Se você precisar fazer isso sem desativar completamente o aplicativo, talvez seja necessário fazer tudo em uma transação envolvendo algumas dicas TABLOCK, XLOCK, HOLDLOCK ou modificar temporariamente o gatilho para gravar diretamente em ProductAudit_TEMP.