Một lần truyền giữa các cơ sở dữ liệu chết khi VPN ngắt, và «chạy lại đi» không phải là kế hoạch khôi phục. Việc trích xuất từ nguồn có thể đã hoàn tất, đích có thể đã commit, hoặc phản hồi có thể chỉ đơn giản bị mất trên đường trở về. Ba trạng thái đó cần những hành động khác nhau, và một ứng dụng khách chỉ biết «lỗi» không thể phân biệt chúng.

Cách sửa là mang tính kiến trúc: cấp cho mỗi lần chạy một danh tính lô bền vững, và để cơ sở dữ liệu trả lời câu hỏi thay vì để ứng dụng khách đoán.

Cơ sở dữ liệu thực sự bảo đảm điều gì

SQL Server và Oracle đều cung cấp tính nguyên tử bên trong một giao dịch. Không cái nào cung cấp tính nguyên tử xuyên qua cả hai. Một kết nối bị mất không làm hỏng cơ sở dữ liệu và cũng không buộc phải hoàn tác thủ công, vì máy chủ tự giải quyết giao dịch của mình mà không cần bạn. Thứ bị phá vỡ là hiểu biết của bên gọi về kết quả.

Commit riêng có nghĩa là commit riêng. Một VPN mang cả hai kết nối không hợp nhất hai commit thành một đơn vị công việc.

Commit mà bạn chưa bao giờ nghe tới

Một chế độ lỗi trừng phạt logic thử lại ngây thơ: máy chủ commit, và xác nhận không bao giờ đến được bên gọi. Oracle ghi nhận điều này là vấn đề kết quả không xác định và cung cấp Transaction Guard cho nó trong tài liệu giao dịch. Lỗi truyền thông không phải là bằng chứng rằng một commit đã gửi bị thất bại, và coi đó là bằng chứng chính là cách một lô bị đăng hai lần. Sự khác biệt này quan trọng nhất trên đường thử lại, nơi người vận hành chỉ có một thông báo lỗi và không có tín hiệu nào khác để hành động.

Vì vậy bước khôi phục phải đọc kết quả từ đích thay vì suy ra từ văn bản lỗi.

Cấp cho bản truyền một danh tính lô

Mỗi lần chạy nhận một ID lô bất biến, và đích ghi lại những gì nó đã làm với ID đó. Vòng đời gồm bốn bước, và nó trông giống nhau bất kể nhà cung cấp nào:

  1. Trích xuất một lô nguồn đã được nhận diện và bất biến với lược đồ và ranh giới được ghi lại.
  2. Truyền nó vào vùng chuẩn bị của đích và phát hiện nội dung không đầy đủ hoặc xung đột trước khi tuyên bố sẵn sàng.
  3. Áp dụng nó theo các quy tắc duy nhất hoặc khóa của chính đích và ghi lại việc hoàn thành trong cùng giao dịch cục bộ.
  4. Đối soát kết quả bền vững qua giao thức được hỗ trợ trước khi xác nhận hoặc thử lại.

Các lần thử lại dùng cùng ID. Một ID mới cho mỗi lần thử sẽ phá hỏng việc ngăn trùng lặp mà bạn vừa xây dựng, điều nghe có vẻ hiển nhiên cho đến khi một lớp bọc thử lại tự động tạo ra một cái.

ID cũng cho bạn một thứ để đối soát sau này, rất lâu sau khi tiến trình khách biến mất.

Nhận lô, rồi áp dụng

Bước áp dụng phải nhận ID lô, thực hiện các thay đổi nghiệp vụ và ghi lại việc hoàn thành trong một giao dịch cục bộ. Làm việc kiểm tra và chèn như hai câu lệnh riêng rẽ sẽ đưa trở lại cuộc đua mà bạn đang cố loại bỏ. Nếu hai công nhân cạnh tranh, đúng một yêu cầu thắng và người kia được thông báo.

Thiếu bản ghi hoàn thành không phải là bằng chứng rằng một giao dịch đang chạy sẽ không bao giờ commit. Việc nhận lô phải tuần tự hóa các lần thử cạnh tranh, hoặc giao thức phải đọc kết quả bền vững trước khi quyết định bất cứ điều gì.

Dùng cơ chế được cơ sở dữ liệu hỗ trợ cho việc tuần tự hóa đó thay vì một vòng lặp kiểm-tra-rồi-lặp-lại trong mã ứng dụng.

Điều thiết kế vẫn chưa thể hứa

Việc chuẩn bị làm cho công việc có thể khởi động lại và giảm phụ thuộc vào một phiên dài. Nó không tạo ra một commit nguyên tử duy nhất xuyên qua SQL Server, Oracle và bất kỳ tác dụng phụ bên ngoài nào mà công việc thực hiện. Nếu nghiệp vụ thực sự cần điều đó, hãy thiết kế và đủ điều kiện một giao dịch phân tán được hỗ trợ hoặc một quy trình đối soát, bao gồm ai sở hữu công việc có kết quả chưa chắc chắn. Bất cứ điều gì yếu hơn thế đều thuộc về một runbook đối soát, không phải mã truyền.

Chấp nhận gián đoạn ở ba nơi: trong khi truyền, trong khi áp dụng, và sau commit nhưng trước xác nhận. Sau đó kiểm tra kết quả nghiệp vụ thay vì thông điệp của khách, và để sổ lô nói xem công việc chưa hoàn thành, đã commit hay vẫn chưa được giải quyết.

Bài viết liên quan