Máy chủ MySQL phiên bản 5.1.41 với plugin InnoDB được bật. Tôi có ba bảng sau đây cho hóa đơn: hóa đơn, hóa đơn và thành phần hóa đơn. Hóa đơn bảng có khóa chính là invoice_id. Cả invoice_components và invoice_expenses được liên kết với hóa đơn bảng với invoice_id là một ngoại lệ không phải là duy nhất (mỗi hóa đơn có thể có nhiều thành phần và nhiều hơn một chi phí). Cả hai bảng đều có chỉ số BTREE cho khóa ngoại này.InnoDB SELECT ... FOR UPDATE statement khóa tất cả các hàng trong một bảng
tôi có các giao dịch sau:
giao dịch 1
START TRANSACTION;
SELECT * FROM invoices WHERE invoice_id = 18 FOR UPDATE;
SELECT * FROM invoice_components WHERE invoice = 18 FOR UPDATE;
SELECT * FROM invoice_expenses WHERE invoice = 18 FOR UPDATE;
Mọi thứ hoạt động ok cho giao dịch đầu tiên và các hàng được lựa chọn và khóa.
giao dịch 2
START TRANSACTION;
SELECT * FROM invoices WHERE invoice_id = 19 FOR UPDATE;
SELECT * FROM invoice_components WHERE invoice = 19 FOR UPDATE;
SELECT * FROM invoice_expenses WHERE invoice = 19 FOR UPDATE;
Giao dịch thứ hai trả ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
cho truy vấn thứ ba.
Điều tương tự cũng xảy ra khi tôi cố gắng CHỌN ... CẬP NHẬT hóa đơn khác cũng như các thành phần và chi phí của chúng. Dường như giao dịch đầu tiên đã khóa tất cả các hàng trong bảng invoice_expenses. Có ý kiến giải thích tại sao điều này lại xảy ra không?
thông tin bổ sung
Giao dịch 2 bắt đầu sau khi truy vấn thứ ba thực hiện giao dịch 1. Không có người dùng khác, kết nối, giao dịch trên máy chủ.
Sự cố xảy ra ở mức cô lập REPEATABLE READ mặc định. Nó được cố định bằng cách thay đổi sang mức READ COMMITTED. Đây là một giải pháp nhưng nó vẫn không giải thích tại sao vấn đề xảy ra với invoice_expenses và không phải với invoice_components.
bạn có chắc chắn tất cả hồ sơ đã bị khóa không? InnoDB có thể khóa hồ sơ khu phố (khi bạn khóa 18-17 và 19), nhưng không nên khóa hồ sơ mà là xa awat trong btree - vì vậy hãy thử điều này với khoảng cách lớn hơn trong các id? Ngoài ra, mức cô lập của bạn là gì? –
@Darhazer. Cảm ơn. Thay đổi mức cô lập thành READ COMMITTED đã giải quyết được vấn đề. Bạn có thể giải thích những gì đang xảy ra không? Khoảng cách MySQL có khóa bảng invoice_expenses của tôi không? Tại sao điều tương tự lại không xảy ra với invoice_components? Dù bằng cách nào, nếu bạn đăng một câu trả lời tôi sẽ chấp nhận nó. –
Tôi không có câu trả lời tại sao điều này xảy ra trong READEATABLE READ, vì vậy tôi muốn đặt một tiền thưởng vào câu hỏi, hơn là đăng câu trả lời chưa hoàn chỉnh. Đó có phải là những truy vấn duy nhất chạy trong các giao dịch không? Giao dịch thứ hai có bắt đầu sau khi thực hiện truy vấn thứ ba trong giao dịch đầu tiên hay không, hoặc chúng là đồng thời? Tôi sẽ thêm tiền thưởng sau 2 ngày được yêu cầu bởi SO –