Pergunta

Estamos trabalhando em um projeto no momento e precisamos implementar a exclusão reversível para a maioria dos usuários (funções de usuário).Decidimos adicionar um campo "is_deleted='0'" em cada tabela do banco de dados e defini-lo como '1' se determinadas funções de usuário clicarem em um botão de exclusão em um registro específico.

Para manutenção futura agora, cada consulta SELECT precisará garantir que não inclua registros onde is_deleted='1'.

Existe uma solução melhor para implementar a exclusão reversível?

Atualizar:Devo também observar que temos um banco de dados de auditoria que rastreia alterações (campo, valor antigo, novo valor, hora, usuário, ip) em todas as tabelas/campos no banco de dados do aplicativo.

Foi útil?

Solução

Você poderia realizar todas as suas consultas em uma visualização que contém o WHERE IS_DELETED='0' cláusula.

Outras dicas

Eu me inclinaria para o "jeito Rails" com um deleted_at coluna que contém o data e hora de quando a exclusão ocorreu.Então você obtém alguns metadados gratuitos sobre a exclusão.Para o seu SELECT basta obter linhas WHERE deleted_at IS NULL

Tendo is_deleted coluna é uma abordagem razoavelmente boa.Se estiver no Oracle, para aumentar ainda mais o desempenho, recomendo particionar a tabela criando uma partição de lista em is_deleted coluna.Em seguida, as linhas excluídas e não excluídas estarão fisicamente em partições diferentes, embora para você seja transparente.

Como resultado, se você digitar uma consulta como

SELECT * FROM table_name WHERE is_deleted = 1

então a Oracle executará a 'remoção da partição' e examinará apenas a partição apropriada.Internamente, uma partição é uma tabela diferente, mas é transparente para você como usuário:você poderá selecionar toda a tabela, independentemente de ela estar particionada ou não.Mas a Oracle poderá consultar SOMENTE a partição necessária.Por exemplo, vamos supor que você tenha 1.000 linhas com is_deleted = 0 e 100.000 linhas com is_deleted = 1, e você particiona a tabela em is_deleted.Agora, se você incluir a condição

WHERE ... AND IS_DELETED=0

então o Oracle SÓ verificará a partição com 1000 linhas.Se a tabela não fosse particionada, seria necessário verificar 101.000 linhas (ambas as partições).

se a tabela for grande e o desempenho for um problema, você sempre poderá mover os registros 'excluídos' para outra tabela, que possui informações adicionais como hora da exclusão, quem excluiu o registro, etc.

dessa forma, você não precisa adicionar outra coluna à sua tabela principal

A melhor resposta, infelizmente, depende do que você está tentando realizar com suas exclusões suaves e do banco de dados no qual você está implementando isso.

No SQL Server, a melhor solução seria usar uma coluna delete_on/deleted_at com um tipo SMALLDATETIME ou DATETIME (dependendo da granularidade necessária) e tornar essa coluna anulável.No SQL Server, os dados do cabeçalho da linha contêm uma máscara de bits NULL para cada uma das colunas da tabela, portanto, é um pouco mais rápido executar IS NULL ou IS NOT NULL do que verificar o valor armazenado em uma coluna.

Se você tiver um grande volume de dados, você vai querer particionar seus dados, seja através do próprio banco de dados ou através de duas tabelas separadas (por exemplo,Products e ProductHistory) ou por meio de uma visualização indexada.

Normalmente evito campos de sinalização como is_deleted, is_archive, etc. porque eles carregam apenas um significado.Um campo anulável delete_at, archived_at fornece um nível adicional de significado para você e para quem herda seu aplicativo.E evito campos de bitmask como uma praga, pois eles exigem uma compreensão de como a bitmask foi construída para compreender qualquer significado.

Isso depende de quais informações você precisa e de quais fluxos de trabalho você deseja oferecer suporte.

Você quer ser capaz de:

  • sabe quais informações estavam lá (antes de serem excluídas)?
  • sabe quando foi excluído?
  • sabe quem deletou?
  • sabe em que qualidade eles estavam agindo quando o excluíram?
  • ser capaz de cancelar a exclusão do registro?
  • ser capaz de dizer quando ele foi excluído?
  • etc.

Se o registro foi excluído e não excluído quatro vezes, é suficiente saber que ele está atualmente em um estado não excluído ou você deseja saber o que aconteceu nesse ínterim (incluindo quaisquer edições entre registros sucessivos exclusões!)?

Cuidado com registros excluídos de forma reversível que causam violações de restrição de exclusividade.Se o seu banco de dados tiver colunas com restrições exclusivas, tome cuidado para que os registros anteriores excluídos de forma reversível não impeçam você de recriar o registro.

Pense no ciclo:

  1. criar usuário (login = JOE)
  2. exclusão reversível (definir a coluna excluída como não nula).
  3. (re)criar usuário (login=JOE).ERRO.LOGIN=JOE já está em uso

A segunda criação resulta em uma violação de restrição porque login=JOE já está na linha excluída de forma reversível.

Algumas técnicas:1.Mova o registro excluído para uma nova tabela.2.Faça sua restrição de exclusividade na coluna login e carimbo de data / hora excluído_at

Minha opinião é +1 para mudar para uma nova mesa.É preciso muita disciplina para manter o * e delete_at = null * em todas as suas consultas (para todos os seus desenvolvedores)

Você definitivamente terá um desempenho melhor se mover seus dados excluídos para outra tabela como Jim disse, além de ter registro de quando foram excluídos, por que e por quem.

Adicionando where deleted=0 para todas as suas consultas irá torná-las significativamente mais lentas e dificultar o uso de qualquer um dos índices que você possa ter na mesa.Evite ter “sinalizadores” em suas tabelas sempre que possível.

Algo que eu uso em projetos é uma coluna STATUSUND TINYINT NOT NULL PADRÃO 0 Usando o statusind como uma fase de bits me permite executar o gerenciamento de dados (excluir, arquivar, replicar, restaurar etc.).Usando isso em visualizações, posso fazer a distribuição de dados, publicação, etc. para os aplicativos consumidores.Se o desempenho for uma preocupação em relação às visualizações, use pequenas tabelas de fatos para dar suporte a essas informações, eliminando o fato, eliminando a relação e permitindo exclusões escalonadas.

Escala bem e é centrado em dados, mantendo o volume de dados bem pequeno - fundamental para 350 GB + dbs com preocupações em tempo real.Usar alternativas, tabelas, triggers tem algum overhead que dependendo da necessidade pode ou não funcionar para você.

As auditorias relacionadas à SOX podem exigir mais do que um campo para ajudar no seu caso, mas isso pode ajudar.Aproveitar

você não menciona qual produto, mas o SQL Server 2008 e o postgresql (e outros, tenho certeza) permitem criar índices filtrados, para que você possa criar um índice de cobertura onde is_deleted=0, mitigando alguns dos pontos negativos dessa abordagem específica .

Prefiro manter uma coluna de status, para poder usá-la para várias configurações diferentes, ou seja,publicado, privado, excluído, precisa de aprovação...

use uma visualização, função ou procedimento que verifique is_deleted=0, ou seja,não selecione diretamente na tabela caso a tabela precise ser alterada posteriormente por outros motivos

e indexe a coluna is_deleted para tabelas maiores

como você já tem uma trilha de auditoria, rastrear a data de exclusão é redundante

Crie outro esquema e conceda tudo em seu esquema de dados.Implemente o VPD em seu novo esquema para que toda e qualquer consulta tenha o predicado que permite a seleção da linha não excluída apenas anexada a ela.http://download.oracle.com/docs/cd/E11882_01/server.112/e16508/cmntopc.htm#CNCPT62345

@AdditionalCriteria("this.status <> 'excluído'")

coloque isso em cima da sua @entity

http://wiki.eclipse.org/EclipseLink/Examples/JPA/SoftDelete

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top