Maneiras de ter um histórico de alterações nas entradas do banco de dados

21

Quais são as maneiras de permitir o controle de versão das entradas do banco de dados (dados)?

Pense nas habilidades dos sistemas de gerenciamento de conteúdo para reverter as alterações de artigos.

Quais são os seus prós / contras?

Matcauthon
fonte
1
O que exatamente você quer versão? O esquema ou os dados?
tdammers
1
Eu quero versão dos dados. Para ficar no exemplo do cms, digamos as versões dos artigos .
Matcuthon
Você pode querer procurar em Datomic.
dan_waterworth

Respostas:

19

Existem basicamente duas abordagens: uma tabela de auditoria, com todos os valores anteriores armazenados nela, ou inclui uma data de início / término como parte da tabela, e todas as atualizações criam um novo registro ao fechar o antigo.

Atualização: O SQL SERVER 2016 suporta isso como um padrão de design / tipo de tabela - https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables?view=sql-server-2017

jmoreno
fonte
4
Portanto, a primeira abordagem pode ser mais escalável. Como os dados "arquivados" raramente são acessados, o design do banco de dados pode ser otimizado. E a mesa de trabalho fica pequena. Dependendo da complexidade, também deve ser possível salvar apenas diferenças. É aconselhável usar o padrão de lembrança ?
219128 Mathews:
1
Isso dependerá do seu uso, pode ser suficiente usar gatilhos para preencher a (s) tabela (s) e, em seguida, fornecer uma maneira de escolher o que e até que ponto reverter.
jmoreno
Você tem um erro de digitação na sua resposta (o padrão deve ser o padrão)
geocodezip
7

Uma idéia é usar "bancos de dados somente para inserção". A idéia básica é que você nunca exclua ou atualize dados em uma linha .

Cada tabela que precisa ser rastreada terá duas datetimecolunas frome to. Eles começam com o valor NULLem cada um (do início ao fim do tempo). Quando você precisa "alterar" a linha, você adiciona uma nova linha e, ao mesmo tempo, atualiza a tolinha anterior Nowe froma linha na qual está adicionando Now.

Para informações mais detalhadas, consulte:

Essa técnica é chamada AuditTrailpara gerenciar dados herdados, e suas lojas meio que mudam o histórico.

Parece que esta pergunta já foi publicada:

Yusubov
fonte
Infelizmente essa pergunta parece ter sido excluído :(
Douglas Gaskell
Não tem problema, aqui está o link . Outra boa sugestão de design no link
Yusubov
2

Eu acho que você pode usar gatilhos para cada tabela e manter os dados em _history (ou você pode dar qualquer nome) e, em cada inserção, atualização, exclusão na tabela principal, o gatilho será acionado e você poderá salvar os detalhes nesta tabela. também está disponível no banco de dados SQLite, se você estiver usando um.

Esse mecanismo também é útil para grandes projetos. Nesta tabela, você pode registrar informações do usuário que fez as alterações, juntamente com o carimbo de data / hora das alterações. você poderá restaurar sua tabela para qualquer um dos carimbos de data e hora correspondentes aos seus requisitos.

Todo banco de dados tem sua própria maneira de escrever e codificar gatilhos. Se você estiver usando o SQLite, visite SQLite.org para obter a sintaxe. Para outros bancos de dados, você pode visitar seus sites oficiais.

PME
fonte
1

Você provavelmente conhece o mecanismo Sqlite db. O banco de dados inteiro é salvo em um único arquivo. A API também suporta sistemas de arquivos virtuais, portanto, basicamente, você pode organizar o armazenamento em qualquer lugar e com qualquer formato, basta responder às operações de leitura e gravação em desvios de arquivos específicos. As possíveis aplicações para isso podem ser criptografia, compactação e assim por diante. A melhor parte é que a camada de contêiner não deve saber nada sobre bancos de dados, formato de arquivo sql ou sqlite, apenas obedeça aos retornos de chamada xRead e xWrite.

Uma das idéias era implementar o recurso da máquina do tempo. Portanto, qualquer operação do xWrite salva todos os segmentos que seriam substituídos no histórico "desfazer" e o usuário pode escolher uma data no passado para ver o que o banco de dados continha (provavelmente o modo somente leitura). Ainda não tenho exemplo de trabalho (houve uma discussão sobre isso na lista de emails do sqlite), mas provavelmente outros mecanismos fornecem APIs de VFS, portanto, algo semelhante é possível. E uma vez implementado, deve ser compatível com estruturas de banco de dados de qualquer complexidade.

Maksee
fonte
O que você acha que essa abordagem é escalável para projetos maiores?
219128 Mathews:
Eu acho que isso poderia adicionar uma grande sobrecarga de dados para alterações de grandes dados (obviamente, pois todas as alterações devem ser salvas, embora a compactação para a versão mais antiga possa ajudar). Além disso, do ponto de vista do seu esquema, desde que funcione para duas tabelas, funcione para vinte.
275 Maksee
1

O método que usamos para versionar as entradas do banco de dados é usar uma tabela de auditoria. A tabela possui um esquema ao longo das linhas de:

Seq      - Int      ' Unique identifier for this table
Event    - Char     ' Insert / Update / Delete
TblName  - Char     ' Table that had field value changed
FldName  - Char     ' Field that was changed
KeyValue - Char     ' delimited list of values for fields that make up the PK of table changed
UsrId    - Char     ' User who made the change
OldValue - Char     ' Old value (converted to character)
NewValue - Char     ' New value (converted to character)
AddTs    - DateTime ' When the change was made

Em seguida, temos gatilhos na inserção / atualização / exclusão das tabelas que queremos rastrear.

Prós:

  • Todos os dados estão em uma tabela
  • Pode ser configurado para rastrear todos os campos ou campos específicos em uma tabela
  • Fácil de mostrar versionamento em cada campo para uma tabela

Contras:

  • Ter todas as informações de auditoria em uma tabela resulta em um número extremamente grande de registros
  • Muitos gatilhos necessários
briddums
fonte
0

Estou fazendo uma versão disso agora. para cada registro, tenho uma Data Inserida, Data de Modificação e um sinalizador booleano de Registro Ativo. Para a inserção inicial, as datas Inserted e Modified estão definidas como Now () (este exemplo está no Access) e o sinalizador Active record está definido como true. se eu modificar esse registro, copio a coisa toda para um novo registro, alterando os campos que o usuário está alterando, deixo a data de inserção igual ao original e altero a data de modificação para agora (). Em seguida, levanto o sinalizador Active Record do registro original para falsee o novo registro para true. Também tenho um campo para ModifiedRecordsParentID, onde salvo a identidade do registro original.

Então, se eu precisar consultar, posso retornar os registros onde ActiveRecord = truee só obterei as informações mais atualizadas.

Brad
fonte
Não há necessidade da ActiveRecordbandeira. A linha MAX (*) sempre deve ser o registro atual. A restauração para uma versão anterior simplesmente insere a referida linha na tabela novamente.
Invertido
Eu não tinha certeza de como fazer o seleto trabalho, mas agora que você está chamando isso eu estou pensando sobre isso e ter uma idéia, hmmmm
Brad
Normalmente, MAX (nome_da_coluna) seleciona o maior valor na coluna da tabela. Para selecionar a linha inteira, select top 1 order by id descendingbasta fazer um simples .
Invertido
Sim, isso funciona para um registro único e simples, mas minha tabela era uma coleção de registros filhos que precisariam ser selecionados de uma só vez, mas poderiam ter sido modificados individualmente. Apenas um pouco mais complexo.
Brad