Tại sao truy vấn đó gây ra thời gian chờ khóa?


7

Thỉnh thoảng, tôi tìm thấy rất nhiều lỗi trong nhật ký lỗi PHP của mình:

MYSQL.1213: Deadlock found when trying to get lock; try restarting transactionSQL

Vấn đề vẫn tồn tại trong khoảng 2 hoặc 3 phút. Nhờ stackoverflow , lý do khá dễ tìm:

------------------------
LATEST DETECTED DEADLOCK
------------------------
130320 15:53:37
*** (1) TRANSACTION:
TRANSACTION 0 83395751, ACTIVE 35 sec, process no 26405, OS thread id 140507872417536 starting index read
mysql tables in use 3, locked 3
LOCK WAIT 3 lock struct(s), heap size 1216, 2 row lock(s)
MySQL thread id 1163191, query id 199629038 localhost sosci Updating
UPDATE `database`.`table` SET `invalidate`='2013-03-21 03:53:02' WHERE ((token='C7G8X3HABCDEFGH') AND (invalidate IS NULL)) AND (project=26118) LIMIT 1
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 65548 n bits 192 index `PRIMARY` of table `database`.`table` trx id 0 83395751 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 4; hex 000c2591; asc   % ;; 1: len 6; hex 000004e36ace; asc     j ;; 2: len 7; hex 8000000a830110; asc        ;; 3: len 4; hex 80000001; asc     ;; 4: len 4; hex 80006606; asc   f ;; 5: len 1; hex 07; asc  ;; 6: len 16; hex 32455637363853485447444734584252; asc 2EV768SHTGDG4XBR;; 7: SQL NULL; 8: len 30; hex 3935363436362c656e672c616e6e612e63616d706f7265736940676d6169; asc 956466,eng,anna.camporesi@gmai;...(truncated); 9: SQL NULL; 10: len 8; hex 8000124ef477640e; asc    N wd ;; 11: len 8; hex 8000124ef495e88e; asc    N    ;;

*** (2) TRANSACTION:
TRANSACTION 0 83395676, ACTIVE 37 sec, process no 26405, OS thread id 140507856160512 fetching rows, thread declared inside InnoDB 451
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1216, 53 row lock(s), undo log entries 1
MySQL thread id 1163198, query id 199628885 localhost sosci updating
DELETE FROM `database`.`table` WHERE ((action="limit") AND (info='login') AND (creation < DATE_SUB(NOW(), INTERVAL 10 MINUTE)))
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 65548 n bits 192 index `PRIMARY` of table `database`.`table` trx id 0 83395676 lock_mode X
Record lock, heap no 4 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 4; hex 000c2591; asc   % ;; 1: len 6; hex 000004e36ace; asc     j ;; 2: len 7; hex 8000000a830110; asc        ;; 3: len 4; hex 80000001; asc     ;; 4: len 4; hex 80006606; asc   f ;; 5: len 1; hex 07; asc  ;; 6: len 16; hex 32455637363853485447444734584252; asc 2EV768SHTGDG4XBR;; 7: SQL NULL; 8: len 30; hex 3935363436362c656e672c616e6e612e63616d706f7265736940676d6169; asc 956466,eng,anna.camporesi@gmai;...(truncated); 9: SQL NULL; 10: len 8; hex 8000124ef477640e; asc    N wd ;; 11: len 8; hex 8000124ef495e88e; asc    N    ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 65548 n bits 192 index `PRIMARY` of table `database`.`table` trx id 0 83395676 lock_mode X waiting
Record lock, heap no 117 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 4; hex 000c31d2; asc   1 ;; 1: len 6; hex 000004f884fc; asc       ;; 2: len 7; hex 80000011040110; asc        ;; 3: len 4; hex 80000001; asc     ;; 4: SQL NULL; 5: len 1; hex 06; asc  ;; 6: SQL NULL; 7: len 15; hex 3133322e3139392e3132312e313632; asc 132.199.121.162;; 8: len 5; hex 6c6f67696e; asc login;; 9: len 1; hex 81; asc  ;; 10: len 8; hex 8000124ef49502aa; asc    N    ;; 11: SQL NULL;

*** WE ROLL BACK TRANSACTION (1)

Điều tôi không hiểu là: Tại sao? Bảng bị khóa rất nhỏ, chỉ có 61 mục (khoảng 30 mới và 30 bị xóa mỗi ngày, chỉ số chính tăng tự động là gần 800.000). Không có cột nào đặc biệt lớn.

Tôi sử dụng InnoDB enging cho bảng này (một khóa đề cập đến một bảng khác có khoảng 20.000 mục) và thỉnh thoảng xảy ra sự cố. RAM không phải là một vấn đề. Máy chủ web và máy chủ MySQL chạy trên cùng một máy (ảo) thường không gặp vấn đề về hiệu năng. Các giao dịch khác (có hàng ngàn trong những phút bị khóa) trong các bảng lớn (1-2 mio. Mục nhập) không gây ra bất kỳ rắc rối nào.

Cảm ơn gợi ý của bạn!


"Thời gian chờ khóa" và "bế tắc" là hai điều hoàn toàn khác nhau và bế tắc là về thời gian của các sự kiện từ nhiều hơn một luồng khách, không phải "truy vấn đó". Đó là "truy vấn đó" và ít nhất một truy vấn khác từ một luồng khác và gần như chắc chắn là các truy vấn trước trong cùng một giao dịch. Thật không may, bạn đã không đăng tất cả các đầu ra có liên quan từ SHOW ENGINE INNODB STATUSsự kiện này ... đó sẽ là tất cả mọi thứ từ "DEADLED DETECTED DEADLOCK" xuống thông qua "WE ROLL BACK TRANSACTION ..."
Michael - sqlbot 21/03/13

Cảm ơn bạn đã làm rõ về thời gian chờ và bế tắc. Vì sự bế tắc đồng thời với các lỗi hết thời gian, tôi nghĩ rằng thời gian chờ là do sự bế tắc này gây ra. Xin lỗi vì đã cắt đầu ra, hiện tại tôi chưa quen với thông tin trạng thái MySQL / InnoDb - thông tin còn thiếu đã được bổ sung.
BurninLeo

Câu trả lời:


8

Giao dịch đầu tiên

------------------------
LATEST DETECTED DEADLOCK
------------------------
130320 15:53:37
*** (1) TRANSACTION:
TRANSACTION 0 83395751, ACTIVE 35 sec, process no 26405, OS thread id 140507872417536 starting index read
mysql tables in use 3, locked 3
LOCK WAIT 3 lock struct(s), heap size 1216, 2 row lock(s)
MySQL thread id 1163191, query id 199629038 localhost sosci Updating
UPDATE `database`.`table` SET `invalidate`='2013-03-21 03:53:02' WHERE ((token='C7G8X3HABCDEFGH') AND (invalidate IS NULL)) AND (project=26118) LIMIT 1
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 65548 n bits 192 index `PRIMARY` of table `database`.`table` trx id 0 83395751 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 4; hex 000c2591; asc   % ;; 1: len 6; hex 000004e36ace; asc     j ;; 2: len 7; hex 8000000a830110; asc        ;; 3: len 4; hex 80000001; asc     ;; 4: len 4; hex 80006606; asc   f ;; 5: len 1; hex 07; asc  ;; 6: len 16; hex 32455637363853485447444734584252; asc 2EV768SHTGDG4XBR;; 7: SQL NULL; 8: len 30; hex 3935363436362c656e672c616e6e612e63616d706f7265736940676d6169; asc 956466,eng,anna.camporesi@gmai;...(truncated); 9: SQL NULL; 10: len 8; hex 8000124ef477640e; asc    N wd ;; 11: len 8; hex 8000124ef495e88e; asc    N    ;;

Giao dịch thứ hai

*** (2) TRANSACTION:
TRANSACTION 0 83395676, ACTIVE 37 sec, process no 26405, OS thread id 140507856160512 fetching rows, thread declared inside InnoDB 451
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1216, 53 row lock(s), undo log entries 1
MySQL thread id 1163198, query id 199628885 localhost sosci updating
DELETE FROM `database`.`table` WHERE ((action="limit") AND (info='login') AND (creation < DATE_SUB(NOW(), INTERVAL 10 MINUTE)))
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 65548 n bits 192 index `PRIMARY` of table `database`.`table` trx id 0 83395676 lock_mode X
Record lock, heap no 4 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 4; hex 000c2591; asc   % ;; 1: len 6; hex 000004e36ace; asc     j ;; 2: len 7; hex 8000000a830110; asc        ;; 3: len 4; hex 80000001; asc     ;; 4: len 4; hex 80006606; asc   f ;; 5: len 1; hex 07; asc  ;; 6: len 16; hex 32455637363853485447444734584252; asc 2EV768SHTGDG4XBR;; 7: SQL NULL; 8: len 30; hex 3935363436362c656e672c616e6e612e63616d706f7265736940676d6169; asc 956466,eng,anna.camporesi@gmai;...(truncated); 9: SQL NULL; 10: len 8; hex 8000124ef477640e; asc    N wd ;; 11: len 8; hex 8000124ef495e88e; asc    N    ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 65548 n bits 192 index `PRIMARY` of table `database`.`table` trx id 0 83395676 lock_mode X waiting
Record lock, heap no 117 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 4; hex 000c31d2; asc   1 ;; 1: len 6; hex 000004f884fc; asc       ;; 2: len 7; hex 80000011040110; asc        ;; 3: len 4; hex 80000001; asc     ;; 4: SQL NULL; 5: len 1; hex 06; asc  ;; 6: SQL NULL; 7: len 15; hex 3133322e3139392e3132312e313632; asc 132.199.121.162;; 8: len 5; hex 6c6f67696e; asc login;; 9: len 1; hex 81; asc  ;; 10: len 8; hex 8000124ef49502aa; asc    N    ;; 11: SQL NULL;

*** WE ROLL BACK TRANSACTION (1)

Họ có đặc điểm gì chung ?

Mỗi giao dịch đang cố gắng để có được một khóa độc quyền trên cùng một phần của KHÓA CHÍNH: page no 65548 n bits 192

RECORD LOCKS space id 0 page no 65548 n bits 192 index `PRIMARY` of table `database`.`table` trx id 0 83395751 lock_mode X locks rec but not gap waiting
RECORD LOCKS space id 0 page no 65548 n bits 192 index `PRIMARY` of table `database`.`table` trx id 0 83395676 lock_mode X

Vì vậy, ai đó đã phải quay trở lại. Kết quả: Giao dịch số 1 quay trở lại.

Truy vấn từ Giao dịch số 2 phải thực hiện

DELETE FROM `database`.`table` WHERE ((action="limit") AND (info='login') AND (creation < DATE_SUB(NOW(), INTERVAL 10 MINUTE)))

Đọc nhật ký lỗi của bạn. Ở đâu đó trong đó phải là thông báo rollback và giao dịch số 1 đã được khởi động lại.

Bạn vừa hỏi

Tại sao "tình huống" này chặn quyền truy cập vào bảng (hoặc ít nhất là một số mục) trong hơn một phút? Và tại sao hai giao dịch (đã chết) lại khóa lẫn nhau - thay vì chạy lần lượt từng giao dịch?

Nhìn vào ổ khóa một lần nữa. Mỗi giao dịch được khóa KHÓA CHÍNH. KEY PRIMARY sống trong Chỉ mục được nhóm (Xem bài đăng hay nhất của MyISAM và InnoDB để biết mô tả về Chỉ mục cụm). Một số khóa nhất định sống cùng nhau trên cùng một không gian, trang và bit. Bây giờ hãy xem các truy vấn:

Giao dịch số 1

UPDATE `database`.`table` SET `invalidate`='2013-03-21 03:53:02' WHERE ((token='C7G8X3HABCDEFGH') AND (invalidate IS NULL)) AND (project=26118) LIMIT 1

Giao dịch số 2

DELETE FROM `database`.`table` WHERE ((action="limit") AND (info='login') AND (creation < DATE_SUB(NOW(), INTERVAL 10 MINUTE)))

Nó chỉ xảy ra rằng KHÓA CHÍNH cho các hàng liên quan theo nghĩa đen là bạn cùng phòng. Nó giống như yêu cầu hai vận động viên cử tạ Olympic đi qua cùng một cánh cửa. Điều làm cho nó tồi tệ hơn là truy vấn đầu tiên có thể hơi ngẫu nhiên trong hành vi. Tại sao?

Bạn đang thay thế invalidate(NULL tại thời điểm bạn bắt đầu chạy truy vấn) bằng giá trị datetime thực tế. Nếu có bất kỳ chỉ mục phụ nào (không phải là chỉ mục duy nhất) có invalidatemột trong các cột, thì khóa CHÍNH tương ứng phải được khóa để ổn định cập nhật của khóa phụ. Điều đó diễn ra trong bộ đệm chèn của ibdata1 (Xem Bộ đệm chèn trong Bản đồ của InnoDB )

Bất kỳ thay đổi nào đối với một cột là thành viên của một hoặc nhiều chỉ mục đều yêu cầu khóa KHÓA CHÍNH ở cấp hàng. Thật không may, nhiều ID hàng cùng tồn tại trên cùng một trang với Chỉ mục cụm.

Giao dịch số 1 có 2 khóa. Giao dịch số 2 có 53 khóa. Tại một thời điểm định mệnh, họ muốn khóa cùng một hàng. Thay vì InnoDB thực hiện khóa hàng "thế giới hoàn hảo", lưu ý rằng việc đặt giá trị thời gian chờ dài hơn cho các giao dịch là một tùy chọn. Tất cả các sản phẩm DBMS phải xử lý Độ phân giải bế tắc trên cơ sở LIFO (Lần vào trước, Xuất trước). Đó là lý do tại sao giao dịch số 2 được phép thực hiện mà không bị gián đoạn hoàn toàn.

Giải đáp bí ẩn


Cảm ơn bạn đã giải thích đầu ra! Điều tôi vẫn chưa hiểu: Tại sao "tình huống" này chặn quyền truy cập vào bảng (hoặc ít nhất là đối với một số mục) trong hơn một phút? Và tại sao hai giao dịch (đã chết) lại khóa lẫn nhau - thay vì chạy lần lượt từng giao dịch?
BurninLeo

@Rolando - Bất kỳ ý tưởng làm thế nào để tránh lỗi như vậy. Chúng tôi nhận được những điều này thường xuyên trong cơ sở dữ liệu của chúng tôi, chính xác các lỗi tương tự. Bất kỳ ý tưởng làm thế nào để làm việc xung quanh họ?
Rishav Rastogi
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.