Sự khác biệt giữa Đọc không lặp lại và Đọc ma là gì?


154

Sự khác biệt giữa đọc không lặp lại và đọc ảo là gì?

Tôi đã đọc bài viết Cách ly (hệ thống cơ sở dữ liệu) từ Wikipedia , nhưng tôi có một vài nghi ngờ. Trong ví dụ dưới đây, điều gì sẽ xảy ra: đọc không lặp lạiđọc ảo ?

Giao dịch A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1
ĐẦU RA:
1----MIKE------29019892---------5000
Giao dịch B
UPDATE USERS SET amount=amount+5000 where ID=1 AND accountno=29019892;
COMMIT;
Giao dịch A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1

Một nghi ngờ khác là, trong ví dụ trên, mức độ cô lập nào nên được sử dụng? Và tại sao?


Câu trả lời:


165

Từ Wikipedia (có ví dụ tuyệt vời và chi tiết cho việc này):

Một lần đọc không lặp lại xảy ra, khi trong quá trình giao dịch, một hàng được lấy hai lần và các giá trị trong hàng khác nhau giữa các lần đọc.

Một lần đọc ảo xảy ra khi trong quá trình giao dịch, hai truy vấn giống hệt nhau được thực thi và tập hợp các hàng được trả về bởi truy vấn thứ hai khác với truy vấn thứ nhất.

Ví dụ đơn giản:

  • Người dùng A chạy cùng một truy vấn hai lần.
  • Ở giữa, Người dùng B chạy một giao dịch và cam kết.
  • Đọc không lặp lại: Hàng A mà người dùng A đã truy vấn có giá trị khác lần thứ hai.
  • Phantom đọc: Tất cả các hàng trong truy vấn có cùng giá trị trước và sau, nhưng các hàng khác nhau đang được chọn (vì B đã xóa hoặc chèn một số). Ví dụ: select sum(x) from table;sẽ trả về một kết quả khác ngay cả khi không có hàng nào bị ảnh hưởng được cập nhật, nếu hàng đã được thêm hoặc xóa.

Trong ví dụ trên, mức cách ly nào sẽ được sử dụng?

Mức độ cô lập bạn cần phụ thuộc vào ứng dụng của bạn. Có một chi phí cao đến mức cô lập "tốt hơn" (chẳng hạn như giảm đồng thời).

Trong ví dụ của bạn, bạn sẽ không có đọc ảo, vì bạn chỉ chọn từ một hàng duy nhất (được xác định bởi khóa chính). Bạn có thể có các lần đọc không lặp lại, vì vậy nếu đó là một vấn đề, bạn có thể muốn có một mức cô lập ngăn chặn điều đó. Trong Oracle, giao dịch A cũng có thể phát hành CHỌN CẬP NHẬT, sau đó giao dịch B không thể thay đổi hàng cho đến khi A hoàn thành.


6
Tôi thực sự không hiểu logic của cú pháp như vậy ... Một lần đọc không lặp lại xảy ra khi lần đọc được lặp lại (và một giá trị khác thu được) ??! ...
serhio

14
@serhio "không lặp lại" đề cập đến thực tế là bạn có thể đọc giá trị một lần và lấy x làm kết quả, sau đó đọc lại và nhận kết quả y, do đó bạn không thể lặp lại (không lặp lại) kết quả tương tự từ hai các truy vấn riêng biệt của cùng một hàng, vì giá trị hàng đó đã được cập nhật ở giữa các lần đọc.
BateTech

@Thilo Bất kỳ ví dụ trường hợp sử dụng thực tế nào trong đó đọc lặp lại có thể tạo ra vấn đề và khi cần thiết?
dùng104309

Điều gì xảy ra nếu PK được sửa đổi trong một giao dịch khác? Điều đó có thể dẫn đến một bóng ma đọc? (Một điều kỳ lạ để làm trong hầu hết các trường hợp, nhưng không phải là không thể.)
jpmc26

1
Cả hai âm thanh đều giống tôi
sn.anurag

125

Một cách đơn giản tôi muốn nghĩ về nó là:

Cả hai lần đọc không lặp lại và ảo đều phải thực hiện với các hoạt động sửa đổi dữ liệu từ một giao dịch khác, được cam kết sau khi giao dịch của bạn bắt đầu và sau đó được đọc bởi giao dịch của bạn.

Các lần đọc không lặp lại là khi giao dịch của bạn đọc các CẬP NHẬT đã cam kết từ một giao dịch khác. Hàng tương tự bây giờ có các giá trị khác với khi giao dịch của bạn bắt đầu.

Phantom đọc tương tự nhưng khi đọc từ cam chèn và / hoặc xóa từ giao dịch khác. Có những hàng hoặc hàng mới đã biến mất kể từ khi bạn bắt đầu giao dịch.

Việc đọc bẩn tương tự như việc đọc không lặp lại và đọc ảo, nhưng liên quan đến việc đọc dữ liệu KHÔNG HOÀN THÀNH và xảy ra khi một CẬP NHẬT, CHERTN hoặc XÓA từ giao dịch khác được đọc và giao dịch khác chưa được cam kết dữ liệu. Nó đang đọc dữ liệu "đang tiến hành", có thể không đầy đủ và có thể không bao giờ thực sự được cam kết.


4
Nó phải làm với mức độ cô lập giao dịch và đồng thời. Sử dụng mức cô lập mặc định, bạn sẽ không bị đọc bẩn và trong hầu hết các trường hợp, bạn muốn tránh đọc bẩn. Có các mức cô lập hoặc gợi ý truy vấn sẽ cho phép đọc bẩn, trong một số trường hợp là sự đánh đổi chấp nhận được để đạt được sự đồng thời cao hơn hoặc là cần thiết do một trường hợp cạnh, chẳng hạn như xử lý sự cố trong giao dịch tiến trình từ một kết nối khác. Thật tốt khi ý tưởng về việc đọc bẩn không vượt qua "bài kiểm tra mùi" đối với bạn, bc như một quy tắc chung, chúng nên được tránh, nhưng có một mục đích.
BateTech

1
@PHPAvenger ở đây là trường hợp sử dụng cho mức cô lập READ UNCOMMITTED: luôn có khả năng gặp phải bế tắc giữa lựa chọn và truy vấn cập nhật (giải thích tại đây ). Nếu truy vấn chọn quá phức tạp để tạo chỉ mục che phủ, để tránh bế tắc, bạn sẽ muốn sử dụng mức cách ly READ UNCOMMITED với nguy cơ gặp phải các lần đọc bẩn, nhưng bạn có thường xuyên quay lại các giao dịch bẩn không? là vĩnh viễn?!
petrica.martinescu

1
@ petrica.martinescu các vấn đề gây ra bởi các lần đọc bẩn KHÔNG chỉ là về việc một giao dịch có được khôi phục hay không. Đọc bẩn có thể trả về kết quả rất không chính xác tùy thuộc vào cách dữ liệu trong các giao dịch đang chờ xử lý đã được sửa đổi. Hãy tưởng tượng một giao dịch thực hiện một loạt các lần xóa, cập nhật và / hoặc chèn. Nếu bạn đọc dữ liệu ở giữa giao dịch đó bằng cách sử dụng "đọc không cam kết", thì nó không đầy đủ. Mức cô lập ảnh chụp nhanh (trong SQL Server) là một cách thay thế tốt hơn để đọc không được cam kết. Một trường hợp sử dụng hợp lệ để đọc mức cô lập không được cam kết trong một hệ thống sản xuất là IMO hiếm.
BateTech ngày

2
@DiponRoy câu hỏi tuyệt vời. Việc khóa được triển khai nếu sử dụng cách ly đọc lặp lại (RR) sẽ ngăn việc xóa xảy ra trên các hàng đã được chọn. Tôi đã thấy các định nghĩa khác nhau về 2 cấp độ iso trong nhiều năm qua, chủ yếu nói rằng bóng ma là một thay đổi trong bộ sưu tập / # hàng được trả về và RR là cùng một hàng được thay đổi. Tôi vừa kiểm tra tài liệu MS SQL đã cập nhật nói rằng việc xóa có thể gây ra không phải RR ( docs.microsoft.com/en-us/sql/odbc/reference/develop-app/, ) vì vậy tôi nghĩ sẽ an toàn khi xóa nhóm loại RR cũng vậy
BateTech

2
@anir có chèn và xóa được bao gồm trong đọc bẩn. Ví dụ: bắt đầu giao dịch, chèn 2 trong số 100 dòng hóa đơn vào kết nối a, bây giờ kết nối b đọc 2 dòng đó trước khi trx được cam kết và trước khi 98 dòng khác được thêm vào và do đó không bao gồm tất cả thông tin cho hóa đơn. Đây sẽ là một bài đọc bẩn liên quan đến một chèn.
BateTech

28

Như đã giải thích trong bài viết này , dị thường Đọc không lặp lại trông như sau:

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

  1. Alice và Bob bắt đầu hai giao dịch cơ sở dữ liệu.
  2. Bob's đọc bản ghi bài đăng và giá trị cột tiêu đề là Giao dịch.
  3. Alice sửa đổi tiêu đề của một bản ghi bài đã cho thành giá trị của ACID.
  4. Alice cam kết giao dịch cơ sở dữ liệu của mình.
  5. Nếu Bob đọc lại hồ sơ bài đăng, anh ta sẽ quan sát một phiên bản khác của hàng này.

Trong bài viết này về Phantom Read , bạn có thể thấy rằng sự bất thường này có thể xảy ra như sau:

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

  1. Alice và Bob bắt đầu hai giao dịch cơ sở dữ liệu.
  2. Bob's đọc tất cả các bản ghi post_comment được liên kết với hàng bài đăng với giá trị định danh là 1.
  3. Alice thêm một bản ghi post_comment mới được liên kết với hàng bài có giá trị định danh là 1.
  4. Alice cam kết giao dịch cơ sở dữ liệu của mình.
  5. Nếu Bob đọc lại các bản ghi post_comment có giá trị cột post_id bằng 1, anh ta sẽ quan sát một phiên bản khác của tập kết quả này.

Vì vậy, trong khi Đọc không lặp lại áp dụng cho một hàng, Phantom Read là về một loạt các bản ghi thỏa mãn một tiêu chí lọc truy vấn nhất định.


3
hình dung tuyệt vời @Vlad
dextermini

23

Đọc hiện tượng

  • Đọc bẩn : đọc dữ liệu UNCOMMITED từ một giao dịch khác
  • Đọc không lặp lại : đọc dữ liệu CAM KẾT từ mộtUPDATEtruy vấn từ một giao dịch khác
  • Phantom đọc : đọc dữ liệu CAM KẾT từ mộtINSERThoặcDELETEtruy vấn từ một giao dịch khác

Lưu ý : XÓA các câu lệnh từ một giao dịch khác, cũng có xác suất rất thấp gây ra các lần đọc Không lặp lại trong một số trường hợp nhất định. Nó xảy ra khi câu lệnh XÓA không may, xóa chính hàng mà giao dịch hiện tại của bạn đang truy vấn. Nhưng đây là một trường hợp hiếm gặp, và rất khó xảy ra trong cơ sở dữ liệu có hàng triệu hàng trong mỗi bảng. Các bảng chứa dữ liệu giao dịch thường có khối lượng dữ liệu cao trong bất kỳ môi trường sản xuất nào.

Ngoài ra, chúng tôi có thể quan sát rằng CẬP NHẬT có thể là một công việc thường xuyên hơn trong hầu hết các trường hợp sử dụng thay vì CHỨNG MINH hoặc XÓA (trong những trường hợp như vậy, nguy cơ đọc không lặp lại vẫn chỉ tồn tại - những trường hợp ảo không thể đọc được trong những trường hợp đó). Đây là lý do tại sao CẬP NHẬT được đối xử khác với CHERTN XÓA và kết quả dị thường cũng được đặt tên khác.

Ngoài ra còn có một chi phí xử lý bổ sung liên quan đến việc xử lý các CHERTN-XÓA, thay vì chỉ xử lý các CẬP NHẬT.


Lợi ích của các mức cô lập khác nhau

  • READ_UNCOMMITTED ngăn chặn không có gì. Đó là mức cô lập bằng không
  • READ_COMMITTED chỉ ngăn chặn một, tức là đọc bẩn
  • REPEATABLE_READ ngăn chặn hai sự bất thường: Đọc bẩn và đọc không lặp lại
  • SERIALIZABLE ngăn chặn cả ba sự bất thường: Đọc bẩn, đọc không lặp lại và đọc Phantom

Vậy thì tại sao không chỉ thiết lập giao dịch SERIALIZABLE mọi lúc? Chà, câu trả lời cho câu hỏi trên là: Cài đặt SERIALIZABLE làm cho các giao dịch rất chậm , điều mà chúng ta lại không muốn.

Trong thực tế, thời gian giao dịch tiêu thụ theo tỷ lệ sau:

SERIALIZABLE > REPEATABLE_READ > READ_COMMITTED > READ_UNCOMMITTED

Vì vậy, cài đặt READ_UNCOMMITTED là nhanh nhất .


Tóm lược

Trên thực tế, chúng ta cần phân tích trường hợp sử dụng và quyết định mức cô lập để chúng ta tối ưu hóa thời gian giao dịch và cũng ngăn ngừa hầu hết các bất thường.

Lưu ý rằng cơ sở dữ liệu theo mặc định có cài đặt REPEATABLE_READ.


1
CẬP NHẬT hoặc XÓA cả hai có thể diễn ra cho các lần đọc Không lặp lại hoặc đó chỉ là CẬP NHẬT?
Dipon Roy

1
CẬP NHẬT hoặc XÓA cả hai có thể diễn ra cho các lần đọc Không lặp lại
niket patel

Trên thực tế, chúng ta có thể tóm tắt rằng trung bình một câu lệnh XÓA ngẫu nhiên được thực hiện bởi một giao dịch khác trên cùng một cơ sở dữ liệu có xác suất rất thấp gây ra các lần đọc không lặp lại cho giao dịch hiện tại. Nhưng cùng một tuyên bố xóa có 100% cơ hội khiến Phantom đọc cho giao dịch hiện tại. Nhìn nó theo cách đó, văn bản của tôi là một chút sai nếu bạn lấy nó từng từ. Nhưng này, tôi cố tình viết nó theo cách này để làm cho mọi người rõ ràng hơn.
Subhadeep Ray

+1 cho một lời giải thích đơn giản và dễ hiểu. Tuy nhiên, tôi nghĩ rằng hầu hết các cơ sở dữ liệu (oracle, mysql) đều có mức cô lập mặc định là Read
Commited

7

Có một sự khác biệt trong việc thực hiện giữa hai mức cách ly này.
Đối với "đọc không lặp lại", khóa hàng là cần thiết.
Đối với "đọc ảo", cần khóa có phạm vi, thậm chí là khóa bảng.
Chúng ta có thể thực hiện hai cấp độ này bằng cách sử dụng giao thức khóa hai pha .


Để thực hiện đọc lặp lại hoặc tuần tự hóa, không cần sử dụng khóa hàng.
a_horse_with_no_name

5

Trong một hệ thống có số lần đọc không lặp lại, kết quả của truy vấn thứ hai của Giao dịch A sẽ phản ánh cập nhật trong Giao dịch B - nó sẽ thấy số tiền mới.

Trong một hệ thống cho phép đọc ảo, nếu Giao dịch B được chèn một hàng mới với ID = 1, Giao dịch A sẽ thấy hàng mới khi truy vấn thứ hai được thực hiện; tức là đọc ảo là một trường hợp đặc biệt của đọc không lặp lại.


Tôi không nghĩ rằng lời giải thích của một bóng ma đọc là chính xác. Bạn có thể nhận được các lần đọc ảo ngay cả khi dữ liệu không cam kết không bao giờ hiển thị. Xem ví dụ trên Wikipedia (được liên kết trong các ý kiến ​​trên).
Thilo

1

Câu trả lời được chấp nhận cho thấy hầu hết tất cả những gì được gọi là sự khác biệt giữa hai thực sự không có ý nghĩa gì cả.

Nếu "một hàng được truy xuất hai lần và các giá trị trong hàng khác nhau giữa các lần đọc", thì chúng không phải là cùng một hàng (không phải là cùng một tuple trong RDB chính xác) và đó thực sự cũng là trường hợp "bộ sưu tập của các hàng được trả về bởi truy vấn thứ hai khác với truy vấn thứ nhất ".

Đối với câu hỏi "mức độ cô lập nào nên được sử dụng", dữ liệu của bạn càng có tầm quan trọng sống còn đối với ai đó, thì ở đâu đó, trường hợp nối tiếp là lựa chọn hợp lý duy nhất của bạn.


0

Tôi nghĩ rằng có một số khác biệt giữa Không thể lặp lại-đọc & đọc ảo.

Không lặp lại có nghĩa là có giao dịch kéo A & B. nếu B có thể nhận thấy sự sửa đổi của A, do đó có thể xảy ra đọc bẩn, vì vậy chúng tôi để B thông báo sửa đổi A sau khi A cam kết.

Có một vấn đề mới: chúng tôi để B chú ý đến việc sửa đổi A sau khi A cam kết, điều đó có nghĩa là A sửa đổi một giá trị của hàng mà B đang giữ, đôi khi B sẽ đọc lại hàng, vì vậy B sẽ nhận được giá trị mới khác với lần đầu tiên chúng tôi nhận được, chúng tôi gọi nó là Không thể lặp lại, để giải quyết vấn đề, chúng tôi để B nhớ điều gì đó (vì tôi không biết điều gì sẽ được ghi nhớ) khi B bắt đầu.

Chúng ta hãy nghĩ về giải pháp mới, chúng ta cũng có thể nhận thấy có vấn đề mới, vì chúng ta để B nhớ điều gì đó, vì vậy bất cứ điều gì xảy ra trong A, B đều không thể bị ảnh hưởng, nhưng nếu B muốn chèn một số dữ liệu vào bảng và B kiểm tra bảng để đảm bảo không có bản ghi, nhưng dữ liệu này đã được A chèn vào, do đó có thể xảy ra một số lỗi. Chúng tôi gọi nó là Phantom-read.


0

đọc không lặp lại là một mức cô lập và đọc ảo (đọc giá trị cam kết của các giao dịch khác) là một khái niệm (loại đọc ví dụ đọc bẩn hoặc đọc ảnh chụp nhanh). Mức cô lập đọc không lặp lại cho phép đọc ảo nhưng không đọc bẩn hoặc đọc ảnh chụp nhanh.

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.