Tại sao MySQL lại yêu cầu khóa chia sẻ sau khi đặt mức giao dịch để ĐỌC B UNNG CHỨNG


7

Chạy một công việc xử lý theo nhiều đợt song song về cơ bản đọc một số lượng lớn các hàng để cập nhật một số - ở đây sử dụng mức giao dịch thấp hơn vì tôi biết các giá trị liên quan sẽ không được cập nhật trong khi tác vụ này đang chạy trước khi gọi từng lưu trữ Tôi chạy:

set session transaction isolation level read uncommitted

sau đó gọi Proc được lưu trữ để có một tập hợp con ID để xử lý. SQLFiddle của hoạt động tổng thể: http://sqlfiddle.com/#!9/192d62 (hơi bị chiếm đoạt nhưng giữ nguyên cấu trúc của các truy vấn ban đầu)

Lý do tôi hỏi là sự bế tắc tiếp tục xảy ra và nhìn vào đầu ra Màn hình có một luồng yêu cầu khóa chung trong khi một luồng khác giữ khóa độc quyền trên cùng một không gian (hoặc ngược lại) - không nên đặt mức giao dịch đó ngăn chặn nhu cầu cho một khóa chia sẻ? Có một lý do để có được một khóa chia sẻ ngoài repeatable-read?

Sử dụng InnoDB.

Thông tin khóa có liên quan từ show engine innodb status(được chỉnh sửa để khớp với tên bảng từ SQLFiddle):

*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 481628 page no 24944 n bits 112 index `PRIMARY` of table `events` trx id 27740892 lock mode S locks rec but not gap waiting

*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 481628 page no 24944 n bits 112 index `PRIMARY` of table `events` trx id 27740898 lock_mode X locks rec but not gap waiting

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 481628 page no 25267 n bits 112 index `PRIMARY` of table `events` trx id 27740898 lock_mode X locks rec but not gap waiting

Lưu ý rằng truy vấn 1 và 2 trong SQLFiddle khớp với các mục nhập thứ nhất và thứ hai trong đầu ra của công cụ. Các PRIMARYĐiều quan trọng là duy nhất trong idcột (như có thể thấy trong Fiddle)


Câu trả lời:


1

"Đọc các đoạn, nhưng chỉ cập nhật một vài trong số chúng" ...

SELECT a chunk -- separate transaction, don't care about locking, etc
munch on that chunk to figure out the 'few' ids to update
BEGIN;
    SELECT ... WHERE id IN (list of the few) FOR UPDATE;
    minimal other work
    UPDATE them;
COMMIT;   -- plus checks for deadlocks, etc, and restart the code.

Ý tưởng là rút càng nhiều mã tiêu tốn thời gian ra khỏi giao dịch càng tốt, từ đó giúp giao dịch nhanh hơn, từ đó giảm thiểu khả năng xảy ra xung đột. (Không, có lẽ nó sẽ không loại bỏ tất cả các bế tắc, nhưng nó sẽ giúp ích.)

Một lưu ý khác: Nếu có thể, hãy đi qua bảng theo thứ tự tương tự trong tất cả các luồng. Bế tắc xảy ra khi một chủ đề chơi với id IN (1,2)nhưng một chủ đề khác IN (2,1). Nếu cả hai làm IN (1,2), sau đó bạn nhận được sự chậm trễ, không phải bế tắc.

Một mẹo khác: Làm cho các khối nhỏ hơn.

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.