Thiết kế cơ sở dữ liệu để ghi nhật ký kiểm toán


151

Mỗi lần tôi cần thiết kế một cơ sở dữ liệu mới, tôi dành khá nhiều thời gian để suy nghĩ về cách tôi nên thiết lập lược đồ cơ sở dữ liệu để giữ nhật ký kiểm toán các thay đổi.

Một số câu hỏi đã được hỏi ở đây về vấn đề này, nhưng tôi không đồng ý rằng có một cách tiếp cận tốt nhất cho tất cả các kịch bản:

Tôi cũng đã tình cờ thấy bài viết thú vị này về Duy trì Nhật ký Thay đổi Cơ sở dữ liệu cố gắng liệt kê các ưu và nhược điểm của từng phương pháp. Nó được viết rất tốt và có thông tin thú vị, nhưng nó đã khiến cho quyết định của tôi trở nên khó khăn hơn.

Câu hỏi của tôi là: Có một tài liệu tham khảo mà tôi có thể sử dụng, có thể là một cuốn sách hoặc một cái gì đó giống như một cây quyết định mà tôi có thể tham khảo để quyết định tôi nên đi theo cách nào dựa trên một số biến đầu vào, như:

  • Sự trưởng thành của lược đồ cơ sở dữ liệu
  • Làm thế nào các bản ghi sẽ được truy vấn
  • Xác suất cần thiết để tạo lại hồ sơ
  • Điều quan trọng hơn: viết hoặc đọc hiệu suất
  • Bản chất của các giá trị đang được ghi lại (chuỗi, số, đốm)
  • Dung lượng lưu trữ có sẵn

Các cách tiếp cận mà tôi biết là:

1. Thêm cột cho ngày và người dùng được tạo và sửa đổi

Bảng ví dụ:

  • Tôi
  • giá trị_1
  • giá trị_2
  • giá trị_3
  • ngày tạo ra
  • sửa đổi_date
  • được tạo bởi
  • sửa đổi_by

Nhược điểm chính: Chúng tôi mất lịch sử sửa đổi. Không thể phục hồi sau khi cam kết.

2. Chỉ chèn các bảng

Bảng ví dụ :

  • Tôi
  • giá trị_1
  • giá trị_2
  • giá trị_3
  • từ
  • đến
  • đã xóa (Boolean)
  • người sử dụng

Nhược điểm chính: Làm thế nào để giữ khóa nước ngoài cập nhật? Không gian rộng lớn cần thiết

3. Tạo một bảng lịch sử riêng cho mỗi bảng

Ví dụ bảng lịch sử:

  • Tôi
  • giá trị_1
  • giá trị_2
  • giá trị_3
  • giá trị_4
  • người sử dụng
  • đã xóa (Boolean)
  • dấu thời gian

Nhược điểm chính: Cần sao chép tất cả các bảng đã được kiểm toán. Nếu lược đồ thay đổi, nó cũng sẽ cần thiết để di chuyển tất cả các bản ghi.

4. Tạo Bảng lịch sử hợp nhất cho tất cả các bảng

Ví dụ bảng lịch sử:

  • tên bảng
  • cánh đồng
  • người sử dụng
  • giá trị mới
  • đã xóa (Boolean)
  • dấu thời gian

Nhược điểm chính: Tôi có thể tạo lại các bản ghi (rollback) nếu cần dễ dàng không? Cột new_value cần phải là một chuỗi lớn để có thể hỗ trợ tất cả các loại cột khác nhau.



1
và những gì về việc sử dụng một cơ sở dữ liệu lịch sử thay vì các bảng?
Jowen

Có lẽ bạn có thể kiểm tra thiết kế của github.com/airblade/apers_trail
zx1986

Có phải là một ý tưởng tồi để ghi lại tất cả (bắt buộc) các truy vấn được thực hiện như nó là?
Dinushan 17/07/18

Câu trả lời:


87

Một phương pháp được một số nền tảng wiki sử dụng là phân tách dữ liệu nhận dạng và nội dung bạn đang kiểm tra. Nó thêm phức tạp, nhưng bạn kết thúc với một bản kiểm tra các bản ghi đầy đủ, không chỉ là danh sách các trường đã được chỉnh sửa mà sau đó bạn phải kết hợp lại để cung cấp cho người dùng ý tưởng về bản ghi cũ trông như thế nào.

Vì vậy, ví dụ: nếu bạn có một bảng có tên Cơ hội để theo dõi các giao dịch bán hàng, bạn thực sự sẽ tạo hai bảng riêng biệt:

Cơ hội Cơ
hội_Content (hoặc đại loại như thế)

Bảng Cơ hội sẽ có thông tin bạn sử dụng để xác định duy nhất bản ghi và sẽ chứa khóa chính mà bạn tham chiếu cho các mối quan hệ khóa ngoài của mình. Bảng Cơ hội_Content sẽ giữ tất cả các trường mà người dùng của bạn có thể thay đổi và theo đó bạn muốn giữ dấu vết kiểm toán. Mỗi bản ghi trong bảng Nội dung sẽ bao gồm PK riêng và dữ liệu ngày được sửa đổi và ngày sửa đổi. Bảng Cơ hội sẽ bao gồm một tham chiếu đến phiên bản hiện tại cũng như thông tin về thời điểm bản ghi chính ban đầu được tạo và bởi ai.

Đây là một ví dụ đơn giản:

CREATE TABLE dbo.Page(  
    ID int PRIMARY KEY,  
    Name nvarchar(200) NOT NULL,  
    CreatedByName nvarchar(100) NOT NULL, 
    CurrentRevision int NOT NULL, 
    CreatedDateTime datetime NOT NULL

Và nội dung:

CREATE TABLE dbo.PageContent(
    PageID int NOT NULL,
    Revision int NOT NULL,
    Title nvarchar(200) NOT NULL,
    User nvarchar(100) NOT NULL,
    LastModified datetime NOT NULL,
    Comment nvarchar(300) NULL,
    Content nvarchar(max) NOT NULL,
    Description nvarchar(200) NULL

Tôi có thể sẽ biến PK của bảng nội dung thành một khóa nhiều cột từ PageID và Sửa đổi được cung cấp Sửa đổi là một loại danh tính. Bạn sẽ sử dụng cột Sửa đổi làm FK. Sau đó, bạn kéo bản ghi hợp nhất bằng cách THAM GIA như thế này:

SELECT * FROM Page
JOIN PageContent ON CurrentRevision = Revision AND ID = PageID

Có thể có một số lỗi trên đó ... đây là trên đỉnh đầu của tôi. Nó sẽ cung cấp cho bạn một ý tưởng về một mô hình thay thế, mặc dù.


10
Về mặt kiểm toán tiếp cận tốt nhưng để sản xuất sẽ mất rất nhiều thời gian để phát triển một bảng kiểm toán riêng cho từng bảng trong cơ sở dữ liệu, viết các trình kích hoạt cho mỗi bảng để nắm bắt các thay đổi và ghi vào bảng kiểm toán. Hơn nữa, một thách thức lớn trong việc phát triển một báo cáo kiểm toán cho tất cả các bảng vì mỗi bảng kiểm toán có cấu trúc khác nhau.
asim-ishaq

11
Nếu việc viết và duy trì tập lệnh cho mỗi bảng là mối quan tâm đối với một tổ chức có ý định quản lý cơ sở dữ liệu đã được kiểm toán, thì tôi tự nhiên khuyên họ nên thuê một DBA có kinh nghiệm hoặc một kỹ sư phần mềm rất linh hoạt và có kinh nghiệm cao với kinh nghiệm đầy đủ tạo cơ sở dữ liệu được kiểm toán .
Hardryv

1
Có đúng PageContent.PageIDlà FK Page.IDPage.CurrentRevisionFK PageContent.Revisionkhông? Là sự phụ thuộc này thực sự thông tư?

2
Tôi đã bỏ phiếu vì nó không đề cập đến các lựa chọn thay thế được đề cập. Nó đưa ra một tùy chọn khác là giải pháp rất cụ thể cho trường hợp sử dụng rất cụ thể. Nhưng tôi thấy những ưu điểm của thiết kế được đề xuất
Acteon

1
Tôi có thể nghĩ về rất ít lĩnh vực mà tôi có thể nói với sự tự tin sẽ không thay đổi, vì vậy tất cả các bảng "chính" cho mỗi thực thể sẽ chỉ tồn tại id, revision_id; nhiều hơn một bảng ngã ba, thực sự. Điều này cảm thấy một chút mùi với tôi. Điều này có lợi thế gì so với cách tiếp cận 3 trong OP (bảng lịch sử trên mỗi bảng được kiểm toán)?
Kenmore

14

Nếu bạn đang sử dụng SQL Server 2008, có lẽ bạn nên xem xét Thay đổi dữ liệu. Điều này là mới cho năm 2008 và có thể giúp bạn tiết kiệm một lượng công việc đáng kể.


đây là liên kết đến thông tin theo dõi thay đổi SQL 2012. msdn.microsoft.com/en-us/l Library / bb933994.aspx +1 để sử dụng chức năng tích hợp, không có điểm nào phát minh lại bánh xe.
Chris

4
@Chris bạn đã bao giờ sử dụng nó cho mình? Thật vậy, nó theo dõi mọi thứ ... nhưng có thể lấy thông tin hữu ích từ nó là một câu chuyện hoàn toàn khác. Không thể sử dụng bánh xe máy kéo cho xe đạp của tôi.
Jowen

Điều này thực sự sẽ là tuyệt vời. Nhưng nếu bạn chỉ có phiên bản Tiêu chuẩn của SQL Server, như tôi, bạn sẽ không gặp may: "Thay đổi dữ liệu chỉ có sẵn trong các phiên bản Đánh giá Doanh nghiệp , Nhà phát triểnĐánh giá Doanh nghiệp ".
Brad Turek

6

Tôi không biết bất kỳ tài liệu tham khảo nào, nhưng tôi chắc rằng ai đó đã viết một cái gì đó.

Tuy nhiên, nếu mục đích chỉ đơn giản là có một bản ghi về những gì đã xảy ra thì việc sử dụng một bản ghi kiểm toán tiêu biểu nhất thì tại sao không đơn giản là giữ mọi thứ:

timestamp
username
ip_address
procedureName (if called from a stored procedure)
database
table
field
accesstype (insert, delete, modify)
oldvalue
newvalue

Có lẽ điều này được duy trì bởi một kích hoạt.


Tôi không biết bất kỳ cách nào để có được điều đó trong máy chủ cơ sở dữ liệu, nhưng tất nhiên điều đó có thể được thực hiện từ bên ngoài đủ dễ dàng.
wallyk

5
Dường như với tôi rằng đây là mẫu thiết kế giống như tùy chọn thứ 4 được hiển thị trong câu hỏi ban đầu.
givanse

3

Chúng tôi sẽ tạo một cơ sở dữ liệu ví dụ nhỏ cho một ứng dụng viết blog. Cần có hai bảng:

blog: lưu trữ ID bài đăng duy nhất, tiêu đề, nội dung và cờ đã xóa. audit: lưu trữ một tập hợp các thay đổi lịch sử cơ bản với ID hồ sơ, ID bài đăng trên blog, loại thay đổi (MỚI, EDIT hoặc XÓA) và ngày / giờ của thay đổi đó. SQL sau đây tạo blogvà lập chỉ mục cột bị xóa:

CREATE TABLE `blog` (
    `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
    `title` text,
    `content` text,
    `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`),
    KEY `ix_deleted` (`deleted`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='Blog posts';

SQL sau đây tạo auditbảng. Tất cả các cột được lập chỉ mục và khóa ngoại được xác định cho aud.blog_id tham chiếu blog.id. Do đó, khi chúng tôi XÓA vật lý một mục blog, lịch sử kiểm toán đầy đủ cũng bị xóa.

CREATE TABLE `audit` (
    `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
    `blog_id` mediumint(8) unsigned NOT NULL,
    `changetype` enum('NEW','EDIT','DELETE') NOT NULL,
    `changetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `ix_blog_id` (`blog_id`),
    KEY `ix_changetype` (`changetype`),
    KEY `ix_changetime` (`changetime`),
    CONSTRAINT `FK_audit_blog_id` FOREIGN KEY (`blog_id`) REFERENCES `blog` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

2

Tôi nghĩ rằng không có gì giống như một cây quyết định. Vì một số ưu và nhược điểm (hoặc yêu cầu) không thực sự có thể đếm được. Làm thế nào để bạn đo lường trưởng thành chẳng hạn?

Vì vậy, chỉ cần xếp hàng các yêu cầu kinh doanh của bạn để đăng nhập kiểm toán của bạn. Cố gắng dự đoán các yêu cầu này có thể thay đổi như thế nào trong tương lai và tạo ra các yêu cầu kỹ thuật của bạn. Bây giờ bạn có thể so sánh nó với những ưu và nhược điểm và chọn tùy chọn đúng / tốt nhất.

Và hãy yên tâm, không quan trọng bạn quyết định như thế nào, sẽ luôn có người nghĩ rằng bạn đã quyết định sai. Tuy nhiên, bạn đã làm bài tập về nhà và bạn biện minh cho quyết định của mình.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.