Bỏ qua điều hướng
Blog

Deadlock cơ sở dữ liệu: đọc vòng chờ trước khi thêm retry

Deadlock cơ sở dữ liệu cần đọc vòng chờ và thứ tự khóa. Phân biệt giao dịch bị hủy với tác động bên ngoài trước khi thiết kế retry.

Chia sẻFacebookLinkedInZalo
deadlock cơ sở dữ liệu: minh họa đồ thị giữ–chờ tài nguyên và thứ tự lấy khóa thống nhất
Nội dung bài viết

Hai giao dịch đều đang chờ, CPU không nhất thiết cao, và một giao dịch bị cơ sở dữ liệu hủy. Thêm retry có thể giúp một lần chạy đi tiếp nhưng chưa giải thích vì sao vòng chờ xuất hiện. Deadlock cơ sở dữ liệu cần được đọc như quan hệ giữ–chờ tài nguyên giữa các giao dịch.

Một vòng chờ khác một truy vấn chậm

Chờ khóa thông thường có thể là A đang sửa một hàng và B đợi A hoàn tất. Deadlock cần một vòng phụ thuộc: A chờ thứ B giữ, trong khi B chờ thứ A giữ. Một truy vấn chậm có thể kéo dài thời gian giữ và làm tranh chấp dễ xuất hiện hơn, nhưng thời gian dài tự nó chưa chứng minh deadlock.

PostgreSQL mô tả deadlock và việc hệ thống hủy một giao dịch liên quan để các giao dịch khác tiếp tục. Không dựa vào việc luôn hủy đúng một giao dịch cụ thể. Khi dùng engine khác, cần đọc đúng tài liệu về phát hiện, lỗi và phạm vi rollback của engine đó.

Vẽ tài nguyên trước khi tranh luận về cấu hình

Ví dụ giả định: giao dịch A giữ hàng R1 rồi muốn sửa R2; giao dịch B giữ R2 rồi muốn sửa R1. Hai mũi tên chờ tạo vòng. Tên R1/R2 chỉ là nhãn minh họa; trong sự cố thật, tài nguyên có thể là hàng, bảng hoặc tài nguyên khác theo kế hoạch thực thi và cơ chế khóa.

Giao dịch A giữ hàng1 chờ hàng2; B giữ hàng2 chờ hàng1
Giao dịch A giữ hàng1 chờ hàng2; B giữ hàng2 chờ hàng1. Sơ đồ biên tập; số liệu hoặc tình huống trong hình là giả định, không phải log hay kết quả khách hàng.

Một sơ đồ có ích ghi giao dịch, tài nguyên đang giữ, tài nguyên muốn lấy và thứ tự câu lệnh. Đừng chỉ chụp màn hình “deadlock detected” rồi nâng timeout. Timeout có thể thay cách lỗi biểu hiện mà không thay vòng chờ. Cần giữ log đã che dữ liệu cùng phiên bản ứng dụng để đối chiếu các đường chạy.

Thứ tự nhất quán giảm một loại vòng chờ

Trong ví dụ trên, nếu cả A và B cùng lấy R1 trước R2, vòng cụ thể đó không còn. Đây là nguyên tắc tài liệu PostgreSQL đề cập cho việc lấy khóa trên nhiều đối tượng. Nhưng một sơ đồ hai hàng không chứng minh toàn hệ thống hết deadlock: trigger, khóa ngầm, câu lệnh khác và đường nghiệp vụ khác vẫn phải được xét.

Đội phát triển cần xác định cách sắp thứ tự trên một tập ID ổn định và kiểm mọi đường sửa cùng tập tài nguyên. Nếu chỉ sửa một endpoint, tác vụ nền vẫn có thể lấy theo thứ tự ngược. Khi nghiệp vụ cho phép, giữ transaction ngắn và tránh chờ người dùng hoặc API ngoài trong lúc đang giữ khóa.

Hai giao dịch cùng lấy hàng1 trước hàng2 để tránh vòng minh họa
Hai giao dịch cùng lấy hàng1 trước hàng2 để tránh vòng minh họa. Sơ đồ biên tập; số liệu hoặc tình huống trong hình là giả định, không phải log hay kết quả khách hàng.

Bản ghi điều tra tối thiểu

Trường Tác dụng
Cửa sổ sự cố và phiên bản Nối đúng đợt phát hành và log
Giao dịch và thứ tự thao tác Thấy đường giữ–chờ
Loại tài nguyên và chế độ khóa Đối chiếu tài liệu engine
Thông báo/mã lỗi nguyên gốc Phân biệt deadlock với timeout khác
Tác động ngoài transaction Biết việc nào không được lặp tùy ý

Log truy vấn có thể chứa dữ liệu riêng. Sổ chia sẻ chỉ cần cấu trúc và nhãn tài nguyên đã ẩn danh, trong khi bằng chứng gốc nằm ở nơi được phân quyền. Không xuất toàn bộ dữ liệu khách để minh họa một vòng hai giao dịch.

Retry chỉ là một nhánh có điều kiện

Nếu engine xác nhận một transaction đã bị hủy do deadlock, ứng dụng có thể cần chạy lại transaction theo hợp đồng và giới hạn đã thống nhất. Không chạy lại riêng câu cuối trong một transaction đã không còn hợp lệ. Cũng không giả định email hoặc lệnh ngoài đã gửi sẽ được cơ sở dữ liệu hoàn tác.

Phải phân biệt lỗi deadlock đã xác nhận với request timeout chưa biết kết quả. Đó là lý do xác minh kết quả sau timeout có owner riêng. Thêm retry chung cho mọi lỗi có thể làm tăng tranh chấp hoặc nhân đôi tác động ngoài phạm vi giao dịch.

Chứng minh thay đổi bằng cùng bài toán

Bộ kiểm nên giữ hai luồng sửa cạnh tranh với dữ liệu giả, xác nhận kết quả nghiệp vụ và log khóa trước/sau. Theo dõi số lỗi, thời gian chờ và kết quả cuối; giảm deadlock nhưng làm request chờ vô hạn không phải cải thiện đủ. Các ca thử phải chạy trong môi trường được phép, không tạo tranh chấp trên production chỉ để lấy ảnh.

If-Match khi hai người cùng sửa bảo vệ phiên bản dữ liệu ở một ranh giới khác, không thay việc phân tích vòng khóa trong DB. Có thể trao đổi phạm vi sửa phần mềm với Onter bằng một đồ thị giữ–chờ và các đường truy vấn đã che dữ liệu. Mục tiêu là sửa nguyên nhân có bằng chứng, không hứa loại mọi deadlock chỉ bằng một tham số.

Tài khoản Onter

Đăng nhập rồi tiếp tục việc đang làm.

Mở trang đăng nhập riêng nếu trình duyệt chưa hiển thị biểu mẫu.

Contact Me on Zalo