Sự khác biệt giữa đọc và đọc


245

Tôi nghĩ rằng các mức cô lập ở trên là như nhau. Ai đó có thể vui lòng mô tả với một số ví dụ tốt đẹp sự khác biệt chính là gì?


3
Bạn nên mở rộng câu hỏi và thêm các thẻ cho "mức độ cô lập" mà bạn đang đề cập đến (Java, v.v.). "Mức cô lập" là một thuật ngữ hơi mơ hồ và rõ ràng bạn đang yêu cầu một câu trả lời cho một môi trường cụ thể.
jesup

Câu trả lời:


564

Đọc cam kết là một mức cô lập đảm bảo rằng mọi dữ liệu đã đọc được cam kết tại thời điểm này được đọc. Nó chỉ đơn giản là hạn chế người đọc nhìn thấy bất kỳ đọc trung gian, không cam kết, 'bẩn'. Không có gì hứa hẹn rằng nếu giao dịch phát hành lại việc đọc, sẽ tìm thấy cùng một dữ liệu, dữ liệu có thể tự do thay đổi sau khi được đọc.

Đọc lặp lại là mức cô lập cao hơn, ngoài các đảm bảo của mức đã đọc cam kết, nó cũng đảm bảo rằng mọi dữ liệu đọc không thể thay đổi , nếu giao dịch đọc lại cùng một dữ liệu, nó sẽ tìm thấy dữ liệu đã đọc trước đó, không thay đổi , và có sẵn để đọc.

Mức cô lập tiếp theo, tuần tự hóa, đảm bảo thậm chí còn mạnh mẽ hơn: ngoài tất cả mọi thứ đảm bảo đọc lặp lại, nó cũng đảm bảo rằng không có dữ liệu mới nào có thể được nhìn thấy bằng lần đọc tiếp theo.

Giả sử bạn có một bảng T có cột C có một hàng trong đó, giả sử nó có giá trị '1'. Và xem xét bạn có một nhiệm vụ đơn giản như sau:

BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;

Đó là một nhiệm vụ đơn giản phát hành hai lần đọc từ bảng T, với độ trễ là 1 phút giữa chúng.

  • trong READ CAM KẾT, CHỌN thứ hai có thể trả về bất kỳ dữ liệu nào . Một giao dịch đồng thời có thể cập nhật hồ sơ, xóa nó, chèn hồ sơ mới. Lựa chọn thứ hai sẽ luôn nhìn thấy dữ liệu mới .
  • trong REPEATABLE READ, CHỌN thứ hai được đảm bảo hiển thị ít nhất các hàng được trả về từ CHỌN đầu tiên không thay đổi . Các hàng mới có thể được thêm bởi một giao dịch đồng thời trong một phút đó, nhưng các hàng hiện tại không thể bị xóa hoặc thay đổi.
  • trong SERIALIZABLE đọc lựa chọn thứ hai được đảm bảo để xem chính xác các hàng giống như hàng đầu tiên. Không có hàng nào có thể thay đổi, cũng không bị xóa, cũng không thể chèn các hàng mới bằng một giao dịch đồng thời.

Nếu bạn tuân theo logic ở trên, bạn có thể nhanh chóng nhận ra rằng các giao dịch SERIALIZABLE, trong khi chúng có thể giúp bạn dễ dàng hơn, luôn chặn hoàn toàn mọi hoạt động đồng thời có thể, vì chúng yêu cầu không ai có thể sửa đổi, xóa cũng như chèn bất kỳ hàng nào. Mức cô lập giao dịch mặc định của System.Transactionsphạm vi .Net là tuần tự hóa và điều này thường giải thích hiệu suất kinh khủng dẫn đến kết quả.

Và cuối cùng, cũng có mức cô lập SNAPSHOT. Mức cô lập SNAPSHOT thực hiện các đảm bảo tương tự như tuần tự hóa, nhưng không phải bằng cách yêu cầu rằng không có giao dịch đồng thời nào có thể sửa đổi dữ liệu. Thay vào đó, nó buộc mọi người đọc phải xem phiên bản thế giới của riêng mình (đó là 'ảnh chụp nhanh'). Điều này làm cho nó rất dễ dàng để lập trình cũng như rất có thể mở rộng vì nó không chặn các cập nhật đồng thời. Tuy nhiên, lợi ích đó đi kèm với một mức giá: tiêu thụ tài nguyên máy chủ thêm.

Bổ sung đọc:


24
Tôi nghĩ có một lỗi ở trên đối với ĐỌC REPEATABLE: Bạn nói rằng các hàng hiện tại không thể bị xóa hoặc thay đổi, nhưng tôi nghĩ chúng có thể bị xóa hoặc thay đổi vì đọc lặp lại chỉ đơn giản là đọc "ảnh chụp" chứ không phải dữ liệu thực tế. Từ các tài liệu dev.mysql.com/doc/refman/5.0/en/ từ : "Tất cả các lần đọc nhất quán trong cùng một giao dịch đều đọc ảnh chụp nhanh được thiết lập bởi lần đọc đầu tiên."
Derek Litz

2
@Derek Litz Tôi nói đúng rằng bạn đang nói: Dữ liệu CÓ THỂ / CÓ THỂ được thay đổi từ bên thứ ba, trong khi giao dịch đang diễn ra, nhưng các lần đọc vẫn sẽ thấy dữ liệu gốc 'cũ' như thể thay đổi chưa được thực hiện nơi (ảnh chụp nhanh).
Chương trình

5
@Thân cây ngô. Có, đọc Phantom có ​​thể xảy ra từ việc xóa (hoặc chèn). Có, đọc ảo có thể xảy ra trong cách ly đọc lặp lại (chỉ từ các phần chèn). Không, Phantom đọc từ xóa không thể xảy ra trong cách ly đọc lặp lại. Kiểm tra nó Những gì tôi đang nói không mâu thuẫn với tài liệu bạn đã trích dẫn.
AndyBrown

4
@Cornstalks NP. Tôi chỉ đề cập đến nó bởi vì tôi không chắc chắn 100% về bản thân mình và phải lặn sâu để chắc chắn ai đúng! Và tôi không muốn những độc giả tương lai bị đánh lừa. Giữ lại các ý kiến, có lẽ tốt nhất để giữ như đề xuất. Tôi chắc rằng bất cứ ai khác quan tâm đến mức độ chi tiết tốt đó sẽ đủ đặc biệt để đọc tất cả các bình luận !!
AndyBrown

12
Cảm ơn vì đã không xóa bình luận của bạn. Các cuộc thảo luận giúp kết nối nhiều dấu chấm hơn.
Josh

68

Đọc lặp lại

Trạng thái của cơ sở dữ liệu được duy trì từ khi bắt đầu giao dịch. Nếu bạn truy xuất một giá trị trong session1, sau đó cập nhật giá trị đó trong session2, lấy lại nó trong session1 sẽ trả về kết quả tương tự. Đọc được lặp lại.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Aaron

Đọc cam kết

Trong bối cảnh giao dịch, bạn sẽ luôn lấy giá trị được cam kết gần đây nhất. Nếu bạn truy xuất một giá trị trong session1, hãy cập nhật nó trong session2, sau đó lấy nó trong session1again, bạn sẽ nhận được giá trị như được sửa đổi trong session2. Nó đọc hàng cam kết cuối cùng.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Bob

Có ý nghĩa?


Tôi đã thử Đọc lặp lại trong SQL Server 2008 với "đặt mức đọc lặp lại mức cô lập". Tạo hai cửa sổ truy vấn sql. Nhưng không hoạt động. Tại sao?
Aditya Bokade

1
Tại sao phiên thứ hai1 vẫn đọc Aaron? Giao dịch của session2 chưa kết thúc và được cam kết? Tôi biết điều này cũ, nhưng có lẽ ai đó có thể làm sáng tỏ.
Sonny Childs

9
Tôi nghĩ rằng Đọc lặp lại sẽ chặn phiên thứ hai cho đến khi phiên đầu tiên được cam kết. Vì vậy, ví dụ là sai.
Nighon

4
Trong trường hợp Đọc lặp lại, khi phiên 1 đọc hàng, nó sẽ đặt khóa chung, điều này sẽ không cho phép bất kỳ khóa Độc quyền nào (đến phiên 2) để cập nhật, do đó dữ liệu không thể được cập nhật.
Taher

Tôi nghĩ rằng máy chủ SQL và MySQL hoạt động khác nhau khi cập nhật các hàng được chia sẻ giữa hai giao dịch
user2488286

23

Đơn giản chỉ là câu trả lời theo cách đọc và hiểu của tôi đối với chủ đề này và câu trả lời @ remus-rusanu dựa trên kịch bản đơn giản này:

Có hai quy trình A và B. Quy trình B đang đọc Bảng X Quy trình A đang viết trong bảng X Quy trình B đang đọc lại Bảng X.

  • ReadUncommned : Quá trình B có thể đọc dữ liệu không được cam kết từ quy trình A và nó có thể thấy các hàng khác nhau dựa trên văn bản B. Không có khóa
  • ReadCommned : Quá trình B có thể đọc CHỈ dữ liệu đã cam kết từ quy trình A và nó có thể thấy các hàng khác nhau chỉ dựa trên văn bản B CAMNG CHỈ. chúng ta có thể gọi nó là Khóa đơn giản không?
  • Lặp lạiRead : Quá trình B sẽ đọc cùng một dữ liệu (hàng) cho dù Quy trình A đang làm gì. Nhưng quá trình A có thể thay đổi các hàng khác. Chặn cấp độ hàng
  • Nối tiếp : Quá trình B sẽ đọc các hàng giống như trước và Quy trình A không thể đọc hoặc ghi trong bảng. Khối cấp bảng
  • Ảnh chụp nhanh : mọi quy trình đều có bản sao riêng và họ đang làm việc với nó. Mỗi người có một quan điểm riêng.

15

Câu hỏi cũ đã có câu trả lời được chấp nhận, nhưng tôi muốn nghĩ về hai mức cô lập này về cách chúng thay đổi hành vi khóa trong SQL Server. Điều này có thể hữu ích cho những người đang gỡ lỗi bế tắc như tôi.

ĐỌC CAM KẾT (mặc định)

Các khóa được chia sẻ được lấy trong SELECT và sau đó được giải phóng khi câu lệnh SELECT hoàn thành . Đây là cách hệ thống có thể đảm bảo rằng không có dữ liệu bẩn đọc dữ liệu không được cam kết. Các giao dịch khác vẫn có thể thay đổi các hàng bên dưới sau khi CHỌN của bạn hoàn thành và trước khi giao dịch của bạn hoàn tất.

ĐỌC

Khóa chia sẻ được lấy trong CHỌN và sau đó chỉ được phát hành sau khi giao dịch hoàn tất . Đây là cách hệ thống có thể đảm bảo rằng các giá trị bạn đọc sẽ không thay đổi trong quá trình giao dịch (vì chúng vẫn bị khóa cho đến khi giao dịch kết thúc).


13

Cố gắng giải thích nghi ngờ này bằng các sơ đồ đơn giản.

Đọc cam kết: Ở đây trong mức cô lập này, Giao dịch T1 sẽ được đọc giá trị cập nhật của X được giao dịch bởi Giao dịch T2.

Đọc cam kết

Đọc lại: Trong mức cô lập này, Giao dịch T1 sẽ không xem xét các thay đổi được cam kết bởi Giao dịch T2.

nhập mô tả hình ảnh ở đây


1

Tôi nghĩ rằng hình ảnh này cũng có thể hữu ích, nó giúp tôi làm tài liệu tham khảo khi tôi muốn nhanh chóng ghi nhớ sự khác biệt giữa các mức độ cô lập (nhờ kudvenkat trên youtube)

nhập mô tả hình ảnh ở đây


0

Xin lưu ý rằng, việc lặp lại trong lần đọc lặp lại liên quan đến một tuple, nhưng không phải cho toàn bộ bảng. Trong các mức cô lập ANSC, có thể xảy ra dị thường đọc ảo , có nghĩa là đọc một bảng có cùng mệnh đề hai lần có thể trả về các tập kết quả khác nhau trả về khác nhau. Theo nghĩa đen, nó không lặp lại .


-1

Quan sát của tôi về giải pháp được chấp nhận ban đầu.

Trong RR (mysql mặc định) - Nếu một tx được mở và CHỌN đã được kích hoạt, một tx khác KHÔNG thể xóa bất kỳ hàng nào thuộc tập kết quả READ trước đó cho đến khi tx trước đó được thực hiện (trên thực tế, câu lệnh xóa trong tx mới sẽ bị treo) , tuy nhiên tx tiếp theo có thể xóa tất cả các hàng khỏi bảng mà không gặp sự cố nào. Btw, một READ tiếp theo trong tx trước đó vẫn sẽ thấy dữ liệu cũ cho đến khi nó được cam kết.


2
Bạn có thể muốn đặt nó trong phần bình luận để người trả lời được thông báo. Bằng cách đó, anh ta sẽ có thể đáp ứng các quan sát của bạn và sửa chữa nếu được yêu cầu.
RBT
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.