2012-01-13 35 views
25

Theo tài liệu MySql, MySql hỗ trợ nhiều khóa chi tiết (MGL).Hành vi của MySQL 'chọn để cập nhật'

trường hợp-1

Khai trương terminal-1:

// kết nối với mysql

mysql> start transaction; 
Query OK, 0 rows affected (0.00 sec) 

mysql> select id, status from tracking_number limit 5 for update; 
+----+--------+ 
| id | status | 
+----+--------+ 
| 1 |  0 | 
| 2 |  0 | 
| 3 |  0 | 
| 4 |  0 | 
| 5 |  0 | 
+----+--------+ 
5 rows in set (0.00 sec) 
mysql> 

trái nó mở ra và mở thiết bị đầu cuối-2:

// kết nối với mysql

mysql> start transaction; 
Query OK, 0 rows affected (0.00 sec) 

mysql> select id, status from tracking_number limit 5 for update; 

<!-- Hangs here. and after some time it says--> 
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 

Mặc dù có rất nhiều hàng để truy xuất, T2 đợi cho đến khi t1 hoàn tất.

trường hợp-2

Left terminal-1 như is.Now trong thiết bị đầu cuối-2:

mysql> start transaction; 
Query OK, 0 rows affected (0.00 sec) 

<!-- case 2.1 --> 
mysql> select id, status from tracking_number where id=1; 
+----+--------+ 
| id | status | 
+----+--------+ 
| 1 |  0 | 
+----+--------+ 
1 row in set (0.00 sec) 

mysql> select id, status from tracking_number where id=2; 
+----+--------+ 
| id | status | 
+----+--------+ 
| 2 |  0 | 
+----+--------+ 
1 row in set (0.00 sec) 

<!-- case 2.2 --> 
mysql> select * from tracking_number where id=2 for update; 
<!-- Hangs here. and after some time --> 
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 
  1. Nhưng tại sao trong trường hợp 1, T2 chờ đợi cùng một bộ hàng mà T1 đã bị khóa?

  2. Điều đó có nghĩa là truy vấn chọn không bị chặn (ngay cả với thông số giới hạn. Tôi cũng đã thử với phạm vi khác) cũng chặn toàn bộ bảng?

  3. Có cách nào để cho phép giao dịch khóa độc lập mà không chỉ định trường của bản ghi (tức là, không sử dụng trong đó trường = giá trị)?
  4. Nói chung (hoặc theo khóa đồng thời Java), viết khóa là độc quyền và không đọc được. Trong trường hợp 2.1, mặc dù các bản ghi trong chế độ ghi khóa, T2 có thể đọc các bản ghi giống nhau như thế nào? Kể từ khi điều này được cho phép những gì là điểm trong khóa nó?
  5. Trường hợp 2.2 được hiểu.

Khai trương một nhà ga và một giao dịch:

mysql> update tracking_number set status=4 where status=0 limit 5; 
Query OK, 5 rows affected (0.00 sec) 
Rows matched: 5 Changed: 5 Warnings: 0 

trái nó ở đó và mở một thiết bị đầu cuối và giao dịch:

mysql> update tracking_number set status=5 where status=0 limit 5; 

T2 đã không thành công cho đến khi tôi cam kết (hoặc rollback) T1.

  1. Tại sao lại có hành vi này?

Trả lời

22

Hãy để tôi đi qua trường hợp của bạn và giải thích cách những ổ khóa làm việc:

1 trường hợp

T1 muốn cập nhật một số hàng trong bảng thử nghiệm của bạn. Giao dịch này đặt IX khóa trên tất cả các bảng và X khóa trên 5 hàng đầu tiên.

T2 muốn cập nhật một số hàng trong bảng thử nghiệm của bạn.Giao dịch này đặt IX (vì IX tương thích với IX) khóa trên tất cả các bảng và cố gắng đầu tiên 5 hàng nhưng nó không thể làm điều đó bởi vì X không tương thích với X

Vì vậy, chúng tôi là tốt.

2,1 trường hợp

T1 muốn cập nhật một số hàng trong bảng thử nghiệm của bạn. Giao dịch này đặt IX khóa trên tất cả các bảng và X khóa trên 5 hàng đầu tiên.

T2 muốn chọn một số hàng từ bảng thử nghiệm của bạn. Và nó không đặt bất kỳ ổ khóa (vì InnoDB cung cấp không khóa đọc)

2,1 trường hợp

T1 muốn cập nhật một số hàng trong bảng thử nghiệm của bạn. Giao dịch này đặt IX khóa trên tất cả các bảng và X khóa trên 5 hàng đầu tiên.

T2 muốn cập nhật (chọn để cập nhật) một số hàng từ bảng thử nghiệm của bạn. Đặt IS trên toàn bộ bảng và cố gắng để có được S khóa trên hàng và không thành công vì X và S không tương thích.


Cũng luôn luôn nhận thức được mức độ cô lập: mức độ khác nhau gây ra cơ chế khác nhau để giải phóng/thu khóa

Hy vọng nó giúp

+0

Cảm ơn @ravnur. Có cách nào để cho phép các giao dịch khóa độc lập mà không chỉ định trường của bản ghi (tức là, không sử dụng trường = giá trị)? –

+1

độc lập = đồng thời? Nếu "có" không có cách nào để làm điều đó ngoại trừ việc đặt mức cô lập thành "DIRTY READS" (tốt hơn bạn không nên thử tùy chọn này). Nếu câu trả lời của bạn là "không" hơn bạn có thể thử 'LOCK TABLE' hoặc thiết lập mức cô lập là" SERIALIZABLE "(nhưng tôi cho rằng câu trả lời của bạn phải là" có "). – ravnur

+0

Câu trả lời của tôi là "có". cảm ơn bạn đã làm rõ. –

Các vấn đề liên quan