Điều này xuất phát từ câu hỏi liên quan này , nơi tôi muốn biết làm thế nào để buộc hai giao dịch xảy ra tuần tự trong một trường hợp tầm thường (trong đó cả hai chỉ hoạt động trên một hàng duy nhất). Tôi nhận được câu trả lời sử dụng SELECT ... FOR UPDATE
như là dòng đầu tiên của cả hai giao dịch, nhưng điều này dẫn đến một vấn đề: Nếu giao dịch đầu tiên không bao giờ được cam kết hoặc quay trở lại, thì giao dịch thứ hai sẽ bị chặn vô thời hạn. Các innodb_lock_wait_timeout
biến đặt số giây sau đó khách hàng cố gắng để thực hiện giao dịch thứ hai sẽ được thông báo "Xin lỗi, hãy thử lại" ... nhưng như xa như tôi có thể nói, họ sẽ phải cố gắng một lần nữa cho đến khi máy chủ khởi động lại tiếp theo. Vì thế:
- Chắc chắn phải có một cách để buộc một
ROLLBACK
nếu một giao dịch được thực hiện mãi mãi? Tôi phải sử dụng một daemon để giết các giao dịch như vậy, và nếu vậy, một daemon như vậy sẽ trông như thế nào? - Nếu một kết nối bị giết bởi
wait_timeout
hoặcinteractive_timeout
giữa giao dịch, giao dịch có bị khôi phục không? Có cách nào để kiểm tra điều này từ bàn điều khiển không?
Làm rõ : innodb_lock_wait_timeout
đặt số giây mà giao dịch sẽ đợi khóa được phát hành trước khi từ bỏ; những gì tôi muốn là một cách buộc một khóa được phát hành.
Cập nhật 1 : Đây là một ví dụ đơn giản cho thấy tại sao innodb_lock_wait_timeout
không đủ để đảm bảo rằng giao dịch thứ hai không bị chặn bởi giao dịch thứ nhất:
START TRANSACTION;
SELECT SLEEP(55);
COMMIT;
Với cài đặt mặc định là innodb_lock_wait_timeout = 50
, giao dịch này hoàn thành không có lỗi sau 55 giây. Và nếu bạn thêm một dòng UPDATE
trước SLEEP
dòng, sau đó bắt đầu một giao dịch thứ hai từ một khách hàng khác cố gắng thực SELECT ... FOR UPDATE
hiện cùng một hàng, đó là giao dịch thứ hai hết thời gian, không phải là giao dịch ngủ quên.
Những gì tôi đang tìm kiếm là một cách để chấm dứt tình trạng uể oải của giao dịch này.
Cập nhật 2 : Đáp lại những lo ngại của hobodave về mức độ thực tế của ví dụ trên, đây là một kịch bản thay thế: Một DBA kết nối với một máy chủ trực tiếp và chạy
START TRANSACTION
SELECT ... FOR UPDATE
trong đó dòng thứ hai khóa một hàng mà ứng dụng thường ghi vào. Sau đó, DBA bị gián đoạn và bỏ đi, quên kết thúc giao dịch. Ứng dụng sẽ dừng lại cho đến khi hàng được mở khóa. Tôi muốn giảm thiểu thời gian ứng dụng bị kẹt do lỗi này.
ROLLBACK
giao dịch đầu tiên nếu mất hơn n
vài giây để hoàn thành. Có cách nào để làm như vậy?
MYSQL
không có cấu hình để ngăn chặn tình huống này. Bởi vì nó không được chấp nhận khi treo máy chủ do khách hàng thiếu trách nhiệm. Tôi không thấy khó khăn gì để hiểu câu hỏi của bạn, nó cũng rất phù hợp.