Kiến trúc hai cơ sở dữ liệu: Hoạt động và lịch sử


8

Tôi nghĩ về một cấu trúc cơ sở dữ liệu không phổ biến và tự hỏi nếu có ai đã nhìn thấy nó được sử dụng trước đây. Về cơ bản, nó sử dụng 2 cơ sở dữ liệu:

  • Cơ sở dữ liệu đầu tiên chỉ giữ dữ liệu hiện tại hợp lệ
  • Cơ sở dữ liệu thứ hai chứa lịch sử của tất cả mọi thứ đã được nhập, cập nhật hoặc xóa trong cơ sở dữ liệu đầu tiên

Kịch bản

Tôi đang làm việc trong một dự án mà tôi bắt buộc phải ghi nhật ký mọi thứ xảy ra và dữ liệu thay đổi thường xuyên.

Ví dụ (không phải thực tế)

Bạn phải làm thiết kế cơ sở dữ liệu cho một giải bóng đá. Trong giải đấu này có người chơi và đội. Các cầu thủ thường chuyển đội.

  • Yêu cầu đầu tiên : Cơ sở dữ liệu phải chứa thông tin cần thiết để chơi trận đấu tiếp theo. Điều này có nghĩa là một danh sách của mỗi người chơi, đội và đội hiện tại mỗi đội.
  • Yêu cầu thứ hai : Cơ sở dữ liệu phải giữ các giá trị lịch sử mà chúng ta sẽ sử dụng để tạo số liệu thống kê. Điều này có nghĩa là danh sách tất cả các cầu thủ đã từng là một phần của đội hoặc danh sách tất cả các đội mà một cầu thủ đã tham gia.

Vấn đề

Hai yêu cầu này là trái ngược nhau. Tôi đã cố gắng làm mọi thứ trong cùng một cơ sở dữ liệu nhưng nó không có ý nghĩa gì. Yêu cầu đầu tiên chỉ quan tâm đến "chơi trận tiếp theo" trong khi yêu cầu thứ hai chỉ quan tâm đến "tạo số liệu thống kê".

Để làm mọi thứ trong cùng một cơ sở dữ liệu, tôi đã sử dụng một loại cơ sở dữ liệu "chỉ chèn" bằng cách xóa phần mềm rõ ràng để xóa / cập nhật thông tin ...

Ban đầu có vẻ như là một nhiệm vụ dễ dàng, việc nắm giữ một danh sách các cầu thủ, đội và đội hiện tại của mỗi người chơi, đột nhiên trở nên khó khăn hơn rất nhiều. Logic ứng dụng cần thiết để chơi trận đấu tiếp theo đã đủ phức tạp nhưng giờ đây cơ sở dữ liệu có thiết kế rất không hữu ích khi ứng dụng được yêu cầu thêm "bị xóa" kiểm tra trên mỗi truy vấn duy nhất để chơi trận đấu tiếp theo.

Bạn có muốn trở thành huấn luyện viên đó hét lên "tất cả các cầu thủ trong đội, đến với tôi" và sau đó 2000 cầu thủ đến với bạn. Tại thời điểm đó, bạn có thể sẽ hét lên "tất cả những người chơi không bị xóa trong đội, hãy đến với tôi" (trong khi thề về thiết kế ngu ngốc này).

Kết luận của tôi

Tôi đã tự hỏi tại sao bạn cần phải đặt mọi thứ trong cùng một cơ sở dữ liệu. Xóa mềm không chỉ làm một công việc kém khi ghi nhật ký mọi thứ trừ khi bạn thêm nhiều cột (time_created, who_created_it, time_delatted, who_delatted_it) mà còn làm phức tạp mọi thứ. Nó làm phức tạp thiết kế cơ sở dữ liệu và nó làm phức tạp thiết kế ứng dụng.

Ngoài ra, tôi nhận được 2 yêu cầu này như là một phần của một ứng dụng duy nhất không thể tách rời nhưng tôi vẫn nghĩ: đây là 2 ứng dụng hoàn toàn khác biệt. Tại sao tôi lại cố gắng làm mọi thứ cùng nhau.

Đó là khi tôi nghĩ về việc chia đôi cơ sở dữ liệu. Một cơ sở dữ liệu hoạt động chỉ được sử dụng để chơi trận đấu tiếp theo và chỉ chứa thông tin hiện tại hợp lệ và cơ sở dữ liệu lịch sử chứa tất cả thông tin từng tồn tại, khi nó được tạo, xóa và ai đã làm điều đó.

Mục tiêu là giữ cho cơ sở dữ liệu đầu tiên (hoạt động) và ứng dụng đơn giản nhất có thể trong khi có càng nhiều thông tin càng tốt trong cơ sở dữ liệu thứ hai (lịch sử).

Câu hỏi

  • Bạn đã thấy thiết kế đó trước đây? Nó có tên không?
  • Có bất kỳ cạm bẫy rõ ràng mà tôi đang thiếu?



EDIT 2015/03/2016

Kiến trúc hiện tại

Về cơ bản, bạn có thể nghĩ về toàn bộ kiến ​​trúc như một quá trình gồm 2 bước.

Bước 1 :

  • Ứng dụng đang chạy và người dùng đang thực hiện một số hành động
  • Mỗi khi một sự kiện xảy ra, nó sẽ được ghi lại tự động (giải pháp kiểm toán) trong một bảng sự kiện
  • Sau đó, hàng đúng, trong cơ sở dữ liệu hoạt động được cập nhật

Bước 2 :

  • Một công việc đọc phần chèn mới nhất trong bảng sự kiện và chèn dữ liệu mới này vào cơ sở dữ liệu lịch sử.
  • Người dùng truy vấn cơ sở dữ liệu lịch sử để lấy thông tin mà họ cần.

Chỉ cần từ bảng sự kiện, bạn có thể xây dựng lại thông tin đến bất kỳ thời điểm nào. Vấn đề là bảng sự kiện này không dễ truy vấn. Đây là nơi cơ sở dữ liệu lịch sử khởi động; để trình bày dữ liệu theo cách dễ dàng truy xuất chính xác những gì chúng ta muốn.

Các vấn đề khác khi đặt mọi thứ vào cùng một bảng

Tôi đã bày tỏ mối quan tâm của mình về sự phức tạp thêm của việc kiểm tra "bị xóa" trên mỗi truy vấn. Nhưng có một vấn đề khác: tính toàn vẹn .

Tôi sử dụng nhiều khóa ngoại và ràng buộc để đảm bảo rằng tại bất kỳ thời điểm nào, dữ liệu trong cơ sở dữ liệu của tôi là hợp lệ.

Hãy xem xét một ví dụ:

Hạn chế: Chỉ có thể có một thủ môn mỗi đội.

Thật dễ dàng để thêm một chỉ mục duy nhất để kiểm tra nếu chỉ có một người giữ mục tiêu cho mỗi đội. Nhưng sau đó những gì xảy ra khi bạn thay đổi thủ môn. Bạn vẫn cần lưu giữ thông tin về người trước nhưng hiện tại bạn có 2 người giữ mục tiêu trong cùng một đội, một người hoạt động và một người không hoạt động, điều này mâu thuẫn với sự ràng buộc của bạn.

Chắc chắn thật dễ dàng để thêm một kiểm tra vào ràng buộc của bạn, nhưng đó là một điều khác để quản lý và suy nghĩ.


Hãy xem kích thước thay đổi từ từ cho một số cách tiếp cận tiêu chuẩn
Turch

1
Đáng kiểm tra: tìm nguồn cung ứng sự kiện . Một trong những bảng của bạn là nhật ký các sự kiện, cung cấp một bản kiểm toán hoàn chỉnh; một phần của nó có thể được lưu trữ sau này. Một bảng khác là trạng thái tóm tắt hiện tại được tạo bằng cách áp dụng các thay đổi từ mọi sự kiện. Nó có thể chứa các điểm kiểm tra trước đó để cho phép khôi phục chỉ từ một phần của luồng sự kiện.
9000

Câu trả lời:


7

Nó xảy ra khá thường xuyên, mặc dù lịch sử (đôi khi được gọi là hồ sơ kiểm toán) được lưu trong cùng một bảng hoặc trong một bảng riêng biệt trong cùng một cơ sở dữ liệu.

Ví dụ, tôi đã từng làm việc với một hệ thống trong đó mọi cập nhật cho bảng sẽ được triển khai dưới dạng chèn, bản ghi 'hiện tại' cũ sẽ có một cờ được đặt trên đó nói rằng đó là bản ghi lịch sử và dấu thời gian khi được cập nhật viết vào một cột.

Hôm nay tôi làm việc trên một hệ thống trong đó mọi thay đổi được ghi vào bảng kiểm toán chuyên dụng và sau đó cập nhật xảy ra trên bảng.

Cái sau có khả năng mở rộng hơn, nhưng không dễ thực hiện theo cách chung chung.

Cách dễ nhất để đạt được mục tiêu của bạn là làm cho các truy vấn trở nên đơn giản và không yêu cầu thêm cờ 'là hiện tại' là chỉ cho phép đọc các truy vấn thông qua chế độ xem hoặc thủ tục được lưu trữ. Sau đó, bạn thực hiện cuộc gọi để nói "lấy tất cả người chơi" và Proc được lưu trữ sẽ chỉ trả lại những người chơi hiện tại (bạn có thể thực hiện quy trình thứ 2 để trả lại người chơi có nhiều quyền kiểm soát hơn những người chơi được trả lại). Điều này hoạt động tốt cho văn bản quá. Một thủ tục được lưu trữ để cập nhật trình phát sau đó có thể viết bất kỳ chi tiết lịch sử nào là cần thiết và cập nhật trình phát - mà không cần khách hàng biết cơ chế lịch sử là gì. Vì lý do này, các thủ tục được lưu trữ tốt hơn một khung nhìn chỉ trả về các trình phát hiện tại, vì nó giữ cho toàn bộ cơ chế truy cập DB giống nhau để đọc và viết - mọi thứ đều diễn ra theo chiều hướng.


Hiện tại, tôi thích cái sau. Nó có vẻ không phải là một vấn đề lớn để chạy tất cả các truy vấn của bạn thông qua các thủ tục hoặc chế độ xem được lưu trữ nhưng nó lại thêm khá nhiều phức tạp để duy trì tất cả các truy vấn đó. Xem và lưu trữ thủ tục cũng giới thiệu rất nhiều hạn chế. blog.sqlauthority.com/2010/10/03/ Chồng stackoverflow.com/questions/921190/iêu
Gudradain

1
Hạn chế là tốt, nó giống như nói "các biến cục bộ trong các đối tượng giới hạn tôi sử dụng toàn cầu". Hạn chế bề mặt truy cập dữ liệu của bạn có nghĩa là nó an toàn hơn và bạn phải thiết kế tốt hơn. Đây là những điều tốt. Các liên kết: lượt xem bị giới hạn, chúng không được thiết kế để trở thành bảng thay thế. Một sproc bạn không thể tham gia có nghĩa là bạn cần một sproc khác. Viết SQL của bạn bằng sprocs không tệ hơn viết SQL bằng mã phía máy khách, bạn duy trì điều đó hoàn toàn tốt để bạn có thể duy trì mã sproc của mình một cách dễ dàng.
gbjbaanb

1
@Gudradain Tôi với gbjbaanb. Dựa vào sự căm ghét các thực hành máy chủ tốt của khách hàng trên một bài đăng blog kém bằng văn bản đề cập đến một RDBMS và một liên kết không liên quan đến một câu hỏi về lỗi tràn ngăn xếp trong đó ai đó đang cố gắng làm điều gì đó không tự nhiên bằng thủ tục được lưu trữ và không thể. Về cơ bản, bạn đọc qua các khung nhìn và viết thông qua các procs được lưu trữ. Có, bạn phải có quy trình kiểm soát và phát hành phiên bản - nhưng dù sao bạn cũng cần điều đó.
đánh dấu

@mcottle Việc chuyển qua chế độ xem và sproc dường như không thực tế khi bạn có một dự án đã sử dụng ORM và lớp truy cập dữ liệu. Ngoài ra, nếu bạn đặt mọi thứ vào cơ sở dữ liệu, thì việc đóng gói logic chương trình sẽ rất kém. Thông thường, bạn có nhiều ứng dụng sử dụng cùng một cơ sở dữ liệu. Không có nghĩa là tất cả các thủ tục được lưu trữ liên quan đến nhiều ứng dụng khác nhau ở cùng một nơi. Nếu tôi phải thực hiện phương pháp thêm "bị xóa" này ở mọi nơi, tôi sẽ thực hiện nó trong lớp truy cập dữ liệu của mình (trong ứng dụng của mình).
Gudradain 17/03/2015

@Gudradain có, "nhiều ứng dụng khác nhau" đang vui vẻ sử dụng cùng một bảng và dữ liệu. Hãy nghĩ về một sproc như một dạng bảng khác chứ không phải logic máy khách dán vào lớp DB. Bạn vẫn có thể gọi chúng qua ORM của mình và nếu bạn thực sự muốn sử dụng nhiều ứng dụng khác nhau, bạn sử dụng các lược đồ để cách ly chúng - làm cho ứng dụng DB của bạn trở nên đặc biệt tốt cho bảo mật và bảo trì (vì 1 ứng dụng có thể thay đổi API dữ liệu mà không ảnh hưởng đến các ứng dụng khác). Sprocs thực hành tốt nhất, mã khách hàng có thể quên thêm "bị xóa", sproc đảm bảo nó.
gbjbaanb

4

Bằng cách chia cơ sở dữ liệu thành hai cơ sở dữ liệu, bạn sẽ mất tất cả các lợi ích của các tham chiếu quan hệ và kiểm tra tính toàn vẹn tham chiếu. Tôi chưa bao giờ thử một điều như vậy, nhưng tôi đoán là nó sẽ trở thành một cơn ác mộng lớn.

Tôi tin rằng toàn bộ tập dữ liệu mô tả một hệ thống nhất định thuộc về một cơ sở dữ liệu. Các vấn đề về sự thuận tiện trong việc truy cập dữ liệu hầu như không bao giờ là lý do chính đáng để đưa ra quyết định tổ chức dữ liệu.

Các vấn đề về sự thuận tiện trong việc truy cập dữ liệu của bạn nên được xử lý bằng cách sử dụng bất kỳ tính năng tiện lợi nào được cung cấp bởi RDBMS của bạn.

Vì vậy, thay vì có cơ sở dữ liệu 'hiện tại' và cơ sở dữ liệu 'lịch sử', bạn chỉ nên có một cơ sở dữ liệu và tất cả các bảng trong đó phải được thêm tiền tố vào 'history'. Sau đó, bạn nên tạo một tập hợp các khung nhìn, một cho mỗi bảng mà bạn muốn xem là 'hiện tại' và để mỗi chế độ xem lọc ra các hàng lịch sử mà bạn không muốn xem và chỉ để các chế độ hiện tại đi qua.

Đây là một giải pháp phù hợp cho vấn đề của bạn vì nó sử dụng tính năng tiện lợi của RDBMS để giải quyết mối quan tâm tiện lợi của lập trình viên, giữ nguyên thiết kế cơ sở dữ liệu.

Một ví dụ về một vấn đề bạn có khả năng gặp phải (quá lâu cho một nhận xét)

Giả sử bạn đang xem một màn hình hiển thị cho bạn thông tin hiện tại về một đội, giả sử team.id = 10, team.name = "Manchester United" và bạn nhấp vào nút có nội dung "hiển thị lịch sử". Tại thời điểm đó, bạn sẽ muốn chuyển sang một màn hình hiển thị thông tin lịch sử về cùng một đội. Vì vậy, bạn sẽ lấy id của 10 mà bạn biết rằng trong cơ sở dữ liệu "hiện tại" là viết tắt của "Manchester United", và bạn sẽ phải hy vọngsố id này là 10 cũng là viết tắt của "Manchester United" trong cơ sở dữ liệu lịch sử. Không có quy tắc toàn vẹn tham chiếu nào thực thi rằng id đề cập đến cùng một thực thể trong cả hai cơ sở dữ liệu, vì vậy, về cơ bản, bạn sẽ có hai bộ dữ liệu tách rời hoàn toàn với các kết nối ngầm chỉ được biết đến, được tôn vinh và hứa sẽ được duy trì bởi, mã bên ngoài cơ sở dữ liệu.

Và tất nhiên, điều này không chỉ đúng với các bảng lớn, như bảng "Đội", mà ngay cả đối với bảng nhỏ nhất mà bạn sẽ có ở bên cạnh, như "Vị trí cầu thủ: Tiền đạo, Tiền vệ, Thủ môn, v.v."

Đạt được tính lịch sử trong cùng một cơ sở dữ liệu

Có nhiều phương pháp khác nhau để duy trì tính lịch sử, và mặc dù chúng nằm ngoài phạm vi của câu hỏi này, về cơ bản, điều mà cạm bẫy mà ý tưởng đặc biệt này của bạn có thể có, đây là một ý tưởng:

Bạn có thể duy trì một bảng nhật ký chứa một mục nhập cho mỗi thay đổi từng được thực hiện cho cơ sở dữ liệu. Bằng cách này, tất cả các bảng "hiện tại" có thể được xóa hoàn toàn dữ liệu và được xây dựng lại hoàn toàn bằng cách phát lại các thay đổi đã ghi. Tất nhiên, nếu bạn có thể xây dựng lại các bảng "hiện tại" bằng cách phát lại các thay đổi từ đầu đến giờ, thì bạn cũng có thể xây dựng một tập hợp các bảng tạm thời để có được chế độ xem cơ sở dữ liệu theo tọa độ thời gian cụ thể bằng cách phát lại những thay đổi từ đầu thời gian cho đến khi phối hợp thời gian cụ thể đó.

Điều này được gọi là "Tìm nguồn sự kiện" (Bài viết của Martin Fowler.)


Bạn có nghĩa là tài liệu tham khảo quan hệ và tính toàn vẹn tham chiếu giữa 2 cơ sở dữ liệu hoặc trong một cơ sở dữ liệu? Tôi sử dụng khóa ngoại và ràng buộc ở mọi nơi mà nó bị chiếm dụng bởi vì chỉ có dữ liệu tôn trọng các ràng buộc này mới được chèn vào cơ sở dữ liệu.
Gudradain

Theo tôi biết, bạn chỉ có thể có quan hệ trong một cơ sở dữ liệu duy nhất. Có thể tồn tại các RDBMS cho phép quan hệ trên cơ sở dữ liệu, nhưng điều đó không được các sản phẩm khác mong đợi và theo ý kiến ​​khiêm tốn của tôi, cũng không bị phụ thuộc ngay cả với sản phẩm quảng cáo tính năng như vậy.
Mike Nakis

Vì vậy, bằng cách chia cơ sở dữ liệu trong hai cơ sở dữ liệu, bạn sẽ có thể có quan hệ trong từng cơ sở dữ liệu riêng biệt, nhưng không phải trên hai cơ sở dữ liệu. Mà có thể đánh vần thảm họa.
Mike Nakis

1
Dữ liệu trong cơ sở dữ liệu lịch sử chỉ đến từ cơ sở dữ liệu hoạt động và không có cập nhật / xóa nào trên cơ sở dữ liệu đó. Theo quan điểm của tôi, cơ sở dữ liệu này thậm chí không cần bất kỳ mối quan hệ hoặc ràng buộc nào. Nó chỉ đơn giản là giữ dữ liệu trong cơ sở dữ liệu hoạt động tại một số điểm. Không có thao tác hoặc bất cứ điều gì để kiểm tra dữ liệu đó. Điều duy nhất quan trọng là: nó đã tồn tại trong cơ sở dữ liệu khác (có / không). Tôi không thấy vấn đề gì với điều đó ...
Gudradain

Vì điều này sẽ quá dài cho một bình luận, tôi đã thêm nó như là một sửa đổi cho câu trả lời của tôi.
Mike Nakis

2

Trước tiên , cơ sở mã của bạn đã cung cấp một sự phân tách rõ ràng các mối quan tâm trong đó logic nghiệp vụ (chọn người chơi để chơi trong trận đấu tiếp theo) được phân biệt với logic truy cập cơ sở dữ liệu của bạn (một lớp chỉ đơn giản là kết nối với cơ sở dữ liệu và ánh xạ cấu trúc dữ liệu của bạn vào hàng cơ sở dữ liệu và ngược lại)? Câu trả lời cho điều này sẽ giúp ích rất nhiều cho việc giải thích lý do tại sao bạn phải đối phó với điều này:

Nó làm phức tạp thiết kế cơ sở dữ liệu và nó làm phức tạp thiết kế ứng dụng.

Hiện nay...

Logic ứng dụng cần thiết để chơi trận đấu tiếp theo đã đủ phức tạp nhưng giờ đây cơ sở dữ liệu có thiết kế rất không hữu ích khi ứng dụng được yêu cầu thêm "bị xóa" kiểm tra trên mỗi truy vấn duy nhất để chơi trận đấu tiếp theo.

Giả sử bạn đang nói về RDBMS, bạn vẫn có thể có một cơ sở dữ liệu bitemporal rằng chụp tất cả các dữ liệu quá khứ có hiệu lực, hiện tại và có thể trong tương lai, sau đó sử dụng một truy cập cơ sở dữ liệu khuôn khổ thư viện / ORM mạnh mẽ, đủ để xử lý logic cơ sở dữ liệu truy vấn cho bạn. Bạn thậm chí có thể sử dụng chế độ xem cơ sở dữ liệu để hỗ trợ cho lựa chọn của bạn. Sau đó, các phần logic nghiệp vụ trong mã của bạn không cần phải biết các trường tạm thời bên dưới, điều này sẽ loại bỏ vấn đề bạn mô tả ở trên.

Ví dụ: thay vì phải mã hóa truy vấn SQL trong ứng dụng của bạn:

SELECT * FROM team_players WHERE team_id = ? AND valid_from >= ? AND valid_to <= ? AND ...

(sử dụng ?như các ràng buộc tham số)

Thư viện truy cập cơ sở dữ liệu giả định có thể cho phép bạn truy vấn dưới dạng (mã giả):

dbConnection.select(Table.TEAM_PLAYERS).match(Field.TEAM_ID, <value>).during(Season.NOW)

Hoặc sử dụng phương pháp xem cơ sở dữ liệu:

-- Using MySQL dialect for illustration
CREATE VIEW seasonal_players AS SELECT * FROM team_players 
    WHERE valid_from >= ... AND valid_to <= ... AND ...

Sau đó, bạn có thể truy vấn người chơi trong khoảng thời gian đó là:

SELECT * FROM seasonal_players WHERE team_id = ?

Quay lại mô hình cơ sở dữ liệu được đề xuất của bạn , bạn dự định xử lý việc xóa dữ liệu lịch sử khỏi cơ sở dữ liệu hoạt động của bạn như thế nào? Bạn chỉ đơn giản là INSERThai hàng tương tự vào cơ sở dữ liệu lịch sử và hoạt động của mình, sau đó chạy một DELETEcơ sở dữ liệu hoạt động bất cứ khi nào có hành động người dùng để xóa dữ liệu lịch sử?


Suy nghĩ lớn

Nếu bạn đang nói về xử lý dữ liệu quy mô lớn trong đó 'cơ sở dữ liệu' của bạn là một giải pháp phân cụm / xử lý luồng cơ sở dữ liệu phân tán được thu nhỏ, cách tiếp cận của bạn sẽ nghe có vẻ mơ hồ (có thể chỉ trên một số thuật ngữ được xác định) với Lambda Kiến trúc , trong đó dữ liệu 'lịch sử' (tức là thời gian thực) của bạn được xử lý riêng lẻ để thực hiện loại thống kê bạn đang tìm kiếm và dữ liệu 'hoạt động' (tức là truyền phát thời gian thực) của bạn vẫn có thể truy vấn một giới hạn được xác định trước trước khi xử lý hàng loạt vẫn tồn tại chúng. Tuy nhiên, nền tảng của phương pháp này được thúc đẩy nhiều hơn bởi những ưu điểm hạn chế của việc triển khai Dữ liệu lớn hiện tại, hơn là đơn giản hóa logic ứng dụng của một người.


chỉnh sửa (sau khi chỉnh sửa của OP)

Tôi nên trả lời điều này sớm hơn, nhưng dù sao đi nữa:

Ngoài ra, tôi nhận được 2 yêu cầu này như là một phần của một ứng dụng duy nhất không thể tách rời nhưng tôi vẫn nghĩ: đây là 2 ứng dụng hoàn toàn khác biệt. Tại sao tôi lại cố gắng làm mọi thứ cùng nhau.

Điều đó nói chung bởi vì người dùng cuối có xu hướng suy nghĩ về các tính năng, không phải số lượng cơ sở dữ liệu cần thiết .

Bạn cũng đề cập rằng:

Bước 1:

  • Mỗi khi một sự kiện xảy ra, nó sẽ được ghi lại tự động (giải pháp kiểm toán) trong một bảng sự kiện.
  • Sau đó, hàng chính xác, trong cơ sở dữ liệu hoạt động được cập nhật.

Bước 2:

  • Một công việc đọc phần chèn mới nhất trong bảng sự kiện và chèn dữ liệu mới này vào cơ sở dữ liệu lịch sử.

Tuyệt quá! Vì vậy, bây giờ bạn có một bảng sự kiện, mà tôi đoán thực sự là khái niệm tìm nguồn cung ứng sự kiện được đề cập bởi các câu trả lời khác. Tuy nhiên, cái gì đọc bảng sự kiện của bạn và cập nhật hàng đúng trong cơ sở dữ liệu hoạt động ? Có phải giống như công việc đọc sự kiện cuối cùng và chèn nó vào cơ sở dữ liệu lịch sử ?

Thêm một điểm liên quan đến ví dụ ràng buộc của bạn:

Tôi sử dụng nhiều khóa ngoại và ràng buộc để đảm bảo rằng tại bất kỳ thời điểm nào, dữ liệu trong cơ sở dữ liệu của tôi là hợp lệ.

Hãy xem xét một ví dụ:

Hạn chế: Chỉ có thể có một thủ môn mỗi đội. ( hoạt động trên sân trong một trò chơi, chỉ là một ghi chú bên lề )

Là " bất kỳ thời điểm nào " đề cập đến thời gian hợp lệ hoặc thời gian giao dịch ?

Điều gì xảy ra khi chúng ta có một thủ môn mới thứ ba? Bạn có tạo một ràng buộc duy nhất trên các trường tạm thời trong cơ sở dữ liệu lịch sử để giữ dữ liệu cho hai thủ môn "cũ" hợp lệ không?


Trước khi chèn / cập nhật / xóa bất cứ thứ gì, tôi tạo một sự kiện chứa tất cả thông tin cần thiết để xây dựng lại dữ liệu tại thời điểm này sau đó tôi chỉ cần cập nhật cơ sở dữ liệu hoạt động. Sau đó, tôi thêm thông tin sự kiện vào cơ sở dữ liệu lịch sử. Quá trình này chủ yếu là tự động và bạn hầu như không có gì để duy trì.
Gudradain

1
Các sự kiện được tạo bởi các kích hoạt trực tiếp trên các bảng. Sự kiện được lưu và hàng được tạo / cập nhật / xóa hoặc không có gì xảy ra. Vì vậy, nó xảy ra cùng một lúc. Bằng cách này, nó đảm bảo rằng sự kiện được tạo và nó đảm bảo rằng sự kiện đó đang cố gắng làm điều gì đó hợp lệ như được chỉ định bởi mối quan hệ và ràng buộc trên cơ sở dữ liệu hoạt động.
Gudradain

1

Điều này thực sự tương tự như cách các giao dịch cơ sở dữ liệu thường được thực hiện, ngoại trừ dữ liệu lịch sử thường bị vứt đi sau khi được ghi vào cơ sở dữ liệu hoạt động. Mẫu lập trình gần nhất tôi có thể nghĩ đến là tìm nguồn cung ứng sự kiện .

Tôi nghĩ rằng việc tách hai cơ sở dữ liệu này là một động thái đúng đắn. Cụ thể hơn, tôi sẽ xem cơ sở dữ liệu "hoạt động" như một bộ đệm, vì dữ liệu lịch sử sẽ đủ để xây dựng lại cơ sở dữ liệu hoạt động bất cứ lúc nào. Tùy thuộc vào bản chất của ứng dụng và yêu cầu hiệu năng của bạn, có thể không cần thiết duy trì bộ đệm này dưới dạng cơ sở dữ liệu riêng nếu việc tái cấu trúc trạng thái hiện tại từ dữ liệu lịch sử trong bộ nhớ mỗi khi chương trình được khởi động là hợp lý.

Theo như những cạm bẫy, vấn đề chính bạn có thể gặp phải là nếu bạn cần bất kỳ loại đồng thời nào (trong cùng một chương trình hoặc có nhiều khách hàng sử dụng cơ sở dữ liệu cùng một lúc). Trong trường hợp đó, bạn sẽ muốn đảm bảo rằng các sửa đổi đối với cơ sở dữ liệu lịch sử và hoạt động được thực hiện nguyên tử. Trong trường hợp đồng thời trong cùng một chương trình, đặt cược tốt nhất của bạn có lẽ là một loại cơ chế khóa. Đối với nhiều khách hàng tương tác với cùng một cơ sở dữ liệu, cách dễ nhất là giữ cả hai dưới dạng bảng trong cùng một cơ sở dữ liệu và sử dụng các giao dịch để giữ cho cơ sở dữ liệu nhất quán.


1
Tìm nguồn cung ứng sự kiện thực sự khá gần với những gì tôi hiện có. Một dấu vết kiểm toán được tạo tự động từ mỗi lần chèn / cập nhật / xóa có thể so sánh với danh sách các sự kiện.
Gudradain

0

Hỗ trợ phiên bản dữ liệu trong cơ sở dữ liệu là một chủ đề được thiết lập tốt và một số DBMS hỗ trợ tính năng này. Tôi nhớ rằng MariaDB hỗ trợ phiên bản dữ liệu ( https://mariadb.com/resource/blog/automatic-data-versioning-in-mariadb-server-10-3/ ) và một tìm kiếm nhanh đã khai quật được thứ gì đó gọi là OrpheusDB ( https: / /medium.com/data-people/painless-data-versioning-for-collaborative-data-science-90cf3a2e279d )

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.