IT

데이터베이스에서 레코드를 버전 관리하는 방법

lottoking 2020. 6. 5. 08:13
반응형

데이터베이스에서 레코드를 버전 관리하는 방법


데이터베이스에 레코드가 있고 관리자 및 일반 사용자 모두 업데이트를 수행 할 수 있다고 가정 해 봅시다.

누구든지이 테이블의 모든 변경 사항을 버전 관리하는 방법에 대한 좋은 접근 방식 / 아키텍처를 제안 할 수 있으므로 레코드를 이전 개정으로 롤백 할 수 있습니다.


FOO관리자와 사용자가 업데이트 할 수 있는 테이블이 있다고 가정 합니다. 대부분의 경우 FOO 테이블에 대해 쿼리를 작성할 수 있습니다. 행복한 날들.

그런 다음 FOO_HISTORY테이블을 만듭니다 . 여기에는 FOO테이블 의 모든 열이 있습니다 . 기본 키는 FOO와 RevisionNumber 열을 더한 것과 같습니다. 에서 외래 키 FOO_HISTORYFOO있습니다. UserId 및 RevisionDate와 같이 개정과 관련된 열을 추가 할 수도 있습니다. 모든 *_HISTORY테이블에서 (즉, Oracle 시퀀스 또는 이와 동등한) 계속해서 수정 번호를 채 웁니다 . 1 초에 한 번만 변경되는 것에 의존하지 마십시오 (즉 RevisionDate, 기본 키에 넣지 마십시오 ).

이제 업데이트 할 때마다 업데이트 FOO직전에 이전 값을에 삽입합니다 FOO_HISTORY. 프로그래머가 실수로이 단계를 놓칠 수 없도록 설계의 일부 기본 수준에서이 작업을 수행합니다.

행을 삭제하려면 FOO몇 가지 선택 사항이 있습니다. 캐스케이드 및 모든 히스토리를 삭제하거나 삭제 된 것으로 플래그 FOO를 지정 하여 논리적 삭제를 수행하십시오 .

이 솔루션은 현재 값에 관심이 많고 때때로 이력에만 관심이있는 경우에 좋습니다. 항상 기록이 필요한 경우 효과적인 시작 및 종료 날짜를 입력하고 모든 레코드를 FOO자체적으로 보관할 수 있습니다. 그런 다음 모든 쿼리는 해당 날짜를 확인해야합니다.


누군가가 질문 / 답변을 편집 할 때 StackOverflow 가하는 것처럼 데이터베이스 레코드의 내용을 버전 화하려고한다고 생각합니다. 개정 시작을 사용하는 일부 데이터베이스 모델을 살펴 보는 것이 좋습니다 .

가장 좋은 예는 Wikipedia 엔진 인 MediaWiki입니다. 여기 에서 데이터베이스 다이어그램 , 특히 개정 테이블을 비교하십시오 .

사용중인 기술에 따라 좋은 diff / merge 알고리즘을 찾아야합니다.

.NET 용인 경우이 질문을 확인하십시오 .


BI 세계에서는 버전을 지정할 테이블에 startDate 및 endDate를 추가하여이 작업을 수행 할 수 있습니다. 첫 번째 레코드를 테이블에 삽입하면 startDate가 채워지지만 endDate는 널입니다. 두 번째 레코드를 삽입하면 첫 번째 레코드의 endDate도 두 번째 레코드의 startDate로 업데이트합니다.

현재 레코드를 보려면 endDate가 널인 레코드를 선택하십시오.

이를 유형 2 느리게 변화하는 차원 이라고도합니다 . TupleVersioning 도 참조하십시오


SQL 2008로 업그레이드하십시오.

SQL 2008에서 SQL 변경 추적을 사용해보십시오. 타임 스탬프 및 삭제 표시 열 해킹 대신이 새로운 기능을 사용하여 데이터베이스의 데이터 변경 내용을 추적 할 수 있습니다.

MSDN SQL 2008 변경 내용 추적


이 문제에 대한 좋은 해결책 중 하나는 임시 데이터베이스 를 사용하는 것 입니다. 많은 데이터베이스 공급 업체가이 기능을 기본 제공 또는 확장을 통해 제공합니다. PostgreSQL과 함께 임시 테이블 확장을 성공적으로 사용 했지만 다른 확장도 있습니다. 데이터베이스에서 레코드를 업데이트 할 때마다 데이터베이스는 해당 레코드의 이전 버전도 보유합니다.


두 가지 옵션 :

  1. 히스토리 테이블 보유-원본이 업데이트 될 때마다 이전 데이터를이 히스토리 테이블에 삽입하십시오.
  2. 감사 테이블-수정 전과 후 값을 감사 테이블의 수정 된 열에 대해서만 업데이트 대상 및시기와 같은 기타 정보와 함께 저장합니다.

SQL 트리거를 통해 SQL 테이블에 대한 감사를 수행 할 수 있습니다. 트리거에서 2 개의 특수 테이블 ( 삽입 및 삭제 )에 액세스 할 수 있습니다 . 이 테이블에는 테이블이 업데이트 될 때마다 삽입되거나 삭제 된 정확한 행이 포함됩니다. 트리거 SQL에서 이러한 수정 된 행을 가져 와서 감사 테이블에 삽입 할 수 있습니다. 이 접근 방식은 감사가 프로그래머에게 투명하다는 것을 의미합니다. 그들의 노력이나 구현 지식이 필요하지 않습니다.

이 접근 방식의 추가 이점은 데이터 액세스 DLL 또는 수동 SQL 쿼리를 통해 SQL 작업이 수행되었는지 여부에 관계없이 감사가 발생한다는 것입니다. 감사는 서버 자체에서 수행됩니다.


어떤 데이터베이스를 말하지 않고 게시 태그에 표시되지 않습니다. Oracle의 경우 Designer에 기본 제공되는 접근 방식 : 저널 테이블 사용을 권장 할 수 있습니다 . 다른 데이터베이스를위한 것이라면 기본적으로 같은 방법을 권장합니다 ...

다른 DB에서 복제하려는 경우 또는 이해하기를 원하는 경우 테이블에 대해 동일한 필드 스펙을 가진 일반 데이터베이스 테이블 만 생성되는 새도우 테이블이 있다는 것이 작동 방식 , 일부 추가 필드 : 마지막으로 수행 한 작업 (문자열, 삽입의 경우 "INS", 업데이트의 경우 "UPD", 삭제의 경우 "DEL"), 작업이 발생한 날짜 시간 및 수행 한 사용자 ID 그것.

트리거를 통해 테이블의 행에 대한 모든 조치는 저널 테이블에 새 값, 수행 된 조치,시기 및 사용자에 의해 새 행을 삽입합니다. 적어도 지난 몇 개월 동안은 행을 삭제하지 마십시오. 예, 수백만 행이 쉽게 커지지 만 저널링이 시작되거나 이전 저널 행이 마지막으로 삭제 된 언제 마지막으로 변경했는지 누가 언제라도 모든 레코드 의 값을 쉽게 추적 할 수 있습니다 .

Oracle에서는 필요한 모든 것이 SQL 코드로 자동 생성되므로 컴파일 / 실행 만하면됩니다. 기본 CRUD 응용 프로그램 (실제로는 "R")과 함께 검사합니다.


나는 또한 같은 일을하고 있습니다. 수업 계획을위한 데이터베이스를 만들고 있습니다. 이러한 계획에는 원자 변경 버전 관리 유연성이 필요합니다. 다시 말해, 수업 계획에 대한 각 변경 사항은 아무리 작아도 허용되어야하지만 이전 버전도 그대로 유지해야합니다. 이렇게하면 수업 제작자는 수업 계획을 사용하는 동안 수업 계획을 편집 할 수 있습니다.

그것이 작동하는 방식은 일단 학생이 수업을 마치면 그 결과가 완성 된 버전에 첨부되는 것입니다. 변경하면 결과는 항상 버전을 가리 킵니다.

이런 방식으로 수업 조건을 삭제하거나 이동해도 결과는 변경되지 않습니다.

현재이 작업을 수행하는 방법은 하나의 테이블에서 모든 데이터를 처리하는 것입니다. 일반적으로 하나의 id 필드 만 가지고 있지만이 시스템에서는 id와 sub_id를 사용하고 있습니다. sub_id는 항상 업데이트 및 삭제를 통해 행과 함께 유지됩니다. ID는 자동 증분됩니다. 수업 계획 소프트웨어는 최신 sub_id에 연결됩니다. 학생 결과가 ID에 연결됩니다. 또한 변경 사항이 발생한 시점을 추적하기위한 타임 스탬프도 포함 ​​시켰지만 버전 관리를 처리 할 필요는 없습니다.

테스트 한 후에 변경할 수있는 한 가지는 앞서 언급 한 endDate null 아이디어를 사용할 수 있다는 것입니다. 내 시스템에서 최신 버전을 찾으려면 max (id)를 찾아야합니다. 다른 시스템은 endDate = null을 찾습니다. 혜택에 다른 날짜 필드가 있는지 확실하지 않습니다.

내 두 센트


While @WW. answer is a good answer another way is to make a version column and keep all your versions in the same table.

For one table approach you either:

  • Use a flag to indicate the latest ala Word Press
  • OR do a nasty greater than version outer join.

An example SQL of the outer join method using revision numbers is:

SELECT tc.*
FROM text_content tc
LEFT OUTER JOIN text_content mc ON tc.path = mc.path
AND mc.revision > tc.revision
WHERE mc.revision is NULL 
AND tc.path = '/stuff' -- path in this case is our natural id.

The bad news is the above requires an outer join and outer joins can be slow. The good news is that creating new entries is theoretically cheaper because you can do it in one write operation with out transactions (assuming your database is atomic).

An example making a new revision for '/stuff' might be:

INSERT INTO text_content (id, path, data, revision, revision_comment, enabled, create_time, update_time)
(
SELECT
(md5(random()::text)) -- {id}
, tc.path
, 'NEW' -- {data}
, (tc.revision + 1)
, 'UPDATE' -- {comment}
, 't' -- {enabled}
, tc.create_time
, now() 
FROM text_content tc
LEFT OUTER JOIN text_content mc ON tc.path = mc.path
AND mc.revision > tc.revision
WHERE mc.revision is NULL 
AND tc.path = '/stuff' -- {path}
)

We insert by using the old data. This is particularly useful if say you only wanted to update one column and avoid optimistic locking and or transactions.

The flag approach and history table approach requires two rows to be inserted/updated.

The other advantage with the outer join revision number approach is that you can always refactor to the multiple table approach later with triggers because your trigger should essentially to do something like the above.


Alok suggested Audit table above, I would like explain it in my post.

I adopted this schema-less, single table design on my project.

Schema:

  • id - INTEGER AUTO INCREMENT
  • username - STRING
  • tablename - STRING
  • oldvalue - TEXT / JSON
  • newvalue - TEXT / JSON
  • createdon - DATETIME

이 테이블은 각 테이블에 대한 히스토리 레코드를 한 번에 한 레코드에 보유 할 수 있으며 완전한 오브젝트 히스토리는 한 레코드에 보유 할 수 있습니다. 이 테이블은 데이터가 변경되는 트리거 / 후크를 사용하여 채워질 수 있으며 대상 행의 이전 및 새 값 스냅 샷을 저장합니다.

이 디자인의 장점 :

  • 히스토리 관리를 위해 관리 할 테이블 수가 적습니다.
  • 각 행의 이전 및 새 상태에 대한 전체 스냅 샷을 저장합니다.
  • 각 테이블을 쉽게 검색 할 수 있습니다.
  • 테이블별로 파티션을 만들 수 있습니다.
  • 테이블 당 데이터 보존 정책을 정의 할 수 있습니다.

이 디자인과 단점 :

  • 시스템이 자주 변경되는 경우 데이터 크기가 클 수 있습니다.

참고 URL : https://stackoverflow.com/questions/323065/how-to-version-control-a-record-in-a-database

반응형