Mối quan hệ giữa các mức cách ly giao dịch với các khóa trên bàn


105

Tôi đã đọc về 4 cấp độ cô lập:

Isolation Level       Dirty Read    Nonrepeatable Read  Phantom Read  
READ UNCOMMITTED      Permitted       Permitted           Permitted
READ COMMITTED              --        Permitted           Permitted
REPEATABLE READ             --             --             Permitted
SERIALIZABLE                --             --              --

Tôi muốn hiểu khóa mà mỗi cách ly giao dịch diễn ra trên bảng

READ UNCOMMITTED - no lock on table
READ COMMITTED - lock on committed data
REPEATABLE READ - lock on block of sql(which is selected by using select query)
SERIALIZABLE - lock on full table(on which Select query is fired)

dưới đây là ba hiện tượng có thể xảy ra trong giao dịch Cô lập
Dirty Read - không khóa
Không thể lặp lại Đọc - không đọc bẩn khi khóa dữ liệu đã cam kết
Phantom Read - khóa trên khối sql (được chọn bằng cách sử dụng truy vấn chọn)

Tôi muốn hiểu nơi chúng tôi xác định các mức cách ly này: chỉ ở mức jdbc / hibernate hoặc trong DB cũng vậy

Tái bút: Tôi đã xem qua các liên kết trong các cấp độ Cô lập trong oracle , nhưng chúng trông vụng về và nói trên cơ sở dữ liệu cụ thể


3
Điều này hoàn toàn phụ thuộc vào cơ sở dữ liệu. Cơ sở dữ liệu khác nhau có thể sử dụng các thuật toán khác nhau cho các mức cách ly. Một số có thể sử dụng MVCC (không có khóa đối với các truy vấn được chọn), một số sử dụng khóa 2 giai đoạn nghiêm ngặt (khóa chia sẻ và khóa riêng).
trà brb

Câu trả lời:


157

Tôi muốn hiểu khóa mà mỗi cách ly giao dịch diễn ra trên bảng

Ví dụ, bạn có 3 tiến trình đồng thời A, B và C. A bắt đầu một giao dịch, ghi dữ liệu và cam kết / khôi phục (tùy thuộc vào kết quả). B chỉ thực hiện một SELECTcâu lệnh để đọc dữ liệu. C đọc và cập nhật dữ liệu. Tất cả quá trình này hoạt động trên cùng một bảng T.

  • ĐỌC KHÔNG ĐƯỢC ĐỀ XUẤT - không có khóa trên bàn. Bạn có thể đọc dữ liệu trong bảng trong khi viết trên đó. Điều này có nghĩa là A ghi dữ liệu (không được cam kết) và B có thể đọc dữ liệu không được cam kết này và sử dụng nó (cho bất kỳ mục đích nào). Nếu A thực hiện khôi phục dữ liệu, B vẫn đọc và sử dụng dữ liệu đó. Đây là cách nhanh nhất nhưng không an toàn nhất để làm việc với dữ liệu vì có thể dẫn đến lỗ hổng dữ liệu trong các bảng không liên quan đến vật lý (vâng, hai bảng có thể liên quan về mặt logic nhưng không liên quan về mặt vật lý trong các ứng dụng trong thế giới thực = \).
  • ĐỌC CAM KẾT - khóa dữ liệu đã cam kết. Bạn có thể đọc dữ liệu chỉ được cam kết. Điều này có nghĩa là A ghi dữ liệu và B không thể đọc dữ liệu được lưu bởi A cho đến khi A thực hiện một cam kết. Vấn đề ở đây là C có thể cập nhật dữ liệu đã được đọc và sử dụng trên máy khách B và B sẽ không có dữ liệu cập nhật.
  • REPEATABLE READ - khóa trên một khối SQL (được chọn bằng cách sử dụng truy vấn chọn). Điều này có nghĩa là B đọc dữ liệu trong một số điều kiện WHERE aField > 10 AND aField < 20, tức là , A chèn dữ liệu có aFieldgiá trị từ 10 đến 20, sau đó B đọc lại dữ liệu và nhận được kết quả khác.
  • SERIALIZABLE - khóa trên một bảng đầy đủ (trên đó truy vấn Chọn được kích hoạt). Điều này có nghĩa là, B đọc dữ liệu và không có giao dịch nào khác có thể sửa đổi dữ liệu trên bảng. Đây là cách an toàn nhất nhưng chậm nhất để làm việc với dữ liệu. Ngoài ra, vì một thao tác đọc đơn giản sẽ khóa bảng , điều này có thể dẫn đến các vấn đề nặng nề trong sản xuất: hãy tưởng tượng rằng bảng T là một bảng Hóa đơn, người dùng X muốn biết hóa đơn trong ngày và người dùng Y muốn tạo một hóa đơn mới, vì vậy trong khi X thực hiện việc đọc hóa đơn, Y không thể thêm hóa đơn mới (và khi liên quan đến tiền, mọi người thực sự phát điên, đặc biệt là các ông chủ).

Tôi muốn hiểu nơi chúng tôi xác định các mức cách ly này: chỉ ở mức JDBC / hibernate hoặc trong DB cũng có

Sử dụng JDBC, bạn xác định nó bằng cách sử dụng Connection#setTransactionIsolation.

Sử dụng Hibernate:

<property name="hibernate.connection.isolation">2</property>

Ở đâu

  • 1: ĐỌC KHÔNG ĐƯỢC ĐỀ NGHỊ
  • 2: ĐỌC ĐƯỢC CAM KẾT
  • 4: ĐỌC CÓ THỂ LẶP LẠI
  • 8: HỢP LỆ

Cấu hình Hibernate được lấy từ đây (xin lỗi, nó bằng tiếng Tây Ban Nha).

Nhân tiện, bạn cũng có thể đặt mức cô lập trên RDBMS:

và tiếp tục ...


docs.oracle.com/cd/B12037_01/server.101/b10743/consist.htm Chỉ để thêm cho Oracle: Người ta có thể đặt mức cô lập của một giao dịch bằng cách sử dụng một trong các câu lệnh sau khi bắt đầu giao dịch: SET TRANSACTION ISOLATION CẤP ĐỘ ĐỌC ĐƯỢC CAM KẾT; THIẾT LẬP MỨC ĐỘ CỰC KỲ GIAO DỊCH CÓ THỂ XÁC NHẬN ĐƯỢC; ĐẶT GIAO DỊCH CHỈ ĐỌC;
Người học

2
Hơn nữa, để tiết kiệm mạng và chi phí xử lý khi bắt đầu mỗi giao dịch bằng câu lệnh SET TRANSACTION, bạn có thể sử dụng câu lệnh ALTER SESSION để đặt mức cách ly giao dịch cho tất cả các giao dịch tiếp theo: ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE; ALTER SESSION SET ISOLATION_LEVEL READ ĐÃ CAM KẾT;
Người học

12
Về REPEATABLE READ - Tôi nghĩ một ví dụ tốt hơn để chứng minh điều đó như sau: B bắt đầu một giao dịch, đọc dữ liệu trên khối của sql WHERE aField> 10 VÀ aField <20, dữ liệu đó bị khóa cho đến khi giao dịch kết thúc. A cố gắng cập nhật dữ liệu đó nhưng phải đợi vì bị khóa. Bây giờ khi B đọc lại dữ liệu đó trong cùng một giao dịch, nó được đảm bảo đọc cùng một dữ liệu, vì nó đã bị khóa. Sửa cho tôi nếu tôi sai.
BornToCode

1
@LuiggiMendoza Theo khái niệm chung, các mức độ cô lập chỉ là về Đọc bẩn , Đọc không lặp lạiHàng Phantom . Khóa (S2PL) hoặc MVCC là các triển khai cho các nhà cung cấp khác nhau.
trà brb

4
@LuiggiMendoza - Tôi không chính xác, nó phải như thế này - dữ liệu mà B đọc không bị thay đổi, nhưng các lựa chọn do B thực hiện có thể trả về nhiều hàng hơn. Đó là bởi vì A không thể sửa đổi các hàng mà B đã đọc , cho đến khi A giải phóng chúng. Tuy nhiên, A có thể chèn các hàng mới thỏa mãn điều kiện where (và do đó, lần sau A thực hiện một lựa chọn, nó sẽ nhận được một kết quả khác với nhiều hàng hơn - đọc ảo).
BornToCode

9

Như brb tea nói, phụ thuộc vào việc triển khai cơ sở dữ liệu và thuật toán mà họ sử dụng: MVCC hoặc Two Phase Lock.

CUBRID (RDBMS mã nguồn mở) giải thích ý tưởng của hai thuật toán này:

  • Khóa hai pha (2PL)

Đầu tiên là khi giao dịch T2 cố gắng thay đổi bản ghi A, nó biết rằng giao dịch T1 đã thay đổi bản ghi A và đợi cho đến khi giao dịch T1 hoàn thành vì giao dịch T2 không thể biết liệu giao dịch T1 sẽ được cam kết hay cuộn trở lại. Phương pháp này được gọi là khóa hai pha (2PL).

  • Kiểm soát đồng thời nhiều phiên bản (MVCC)

Phương thức còn lại là cho phép mỗi giao dịch T1 và T2 có phiên bản thay đổi của riêng chúng. Ngay cả khi giao dịch T1 đã thay đổi bản ghi A từ 1 thành 2, giao dịch T1 vẫn giữ nguyên giá trị ban đầu là 1 và ghi rằng phiên bản giao dịch T1 của bản ghi A là 2. Sau đó, giao dịch T2 sau thay đổi bản ghi A. từ 1 đến 3, không phải từ 2 đến 4 và viết rằng phiên bản giao dịch T2 của bản ghi A là 3.

Khi giao dịch T1 được quay trở lại, không có vấn đề gì nếu phiên bản giao dịch 2, T1, không được áp dụng cho bản ghi A. Sau đó, nếu giao dịch T2 được cam kết, phiên bản giao dịch 3, T2, sẽ được áp dụng cho bản ghi A. Nếu giao dịch T1 được cam kết trước giao dịch T2, bản ghi A được thay đổi thành 2 và sau đó thành 3 tại thời điểm thực hiện giao dịch T2. Trạng thái cơ sở dữ liệu cuối cùng giống với trạng thái thực hiện từng giao dịch một cách độc lập, không có bất kỳ ảnh hưởng nào đến các giao dịch khác. Do đó, nó thỏa mãn thuộc tính ACID. Phương pháp này được gọi là điều khiển đồng thời nhiều phiên bản (MVCC).

MVCC cho phép sửa đổi đồng thời với chi phí tăng thêm chi phí trong bộ nhớ (vì nó phải duy trì các phiên bản khác nhau của cùng một dữ liệu) và tính toán (ở cấp REPETEABLE_READ, bạn không thể mất cập nhật nên nó phải kiểm tra các phiên bản của dữ liệu, chẳng hạn như Hiberate với Khóa Optimistick ).

Trong 2PL Mức cách ly giao dịch kiểm soát những điều sau :

  • Khóa có được sử dụng khi dữ liệu được đọc hay không và loại khóa được yêu cầu.

  • Khóa đọc được giữ trong bao lâu.

  • Liệu một hoạt động đọc tham chiếu đến các hàng được sửa đổi bởi một giao dịch khác:

    • Chặn cho đến khi khóa riêng trên hàng được giải phóng.

    • Truy xuất phiên bản đã cam kết của hàng tồn tại tại thời điểm bắt đầu sao kê hoặc giao dịch.

    • Đọc sửa đổi dữ liệu không cam kết.

Việc chọn mức cách ly giao dịch không ảnh hưởng đến các khóa có được để bảo vệ các sửa đổi dữ liệu. Một giao dịch luôn có một khóa độc quyền đối với bất kỳ dữ liệu nào mà nó sửa đổi và giữ khóa đó cho đến khi giao dịch hoàn tất, bất kể mức độ cách ly được đặt cho giao dịch đó là gì. Đối với hoạt động đọc, các mức cách ly giao dịch chủ yếu xác định mức độ bảo vệ khỏi tác động của các sửa đổi được thực hiện bởi các giao dịch khác.

Mức cô lập thấp hơn sẽ làm tăng khả năng nhiều người dùng truy cập dữ liệu cùng một lúc, nhưng làm tăng số lượng các tác động đồng thời , chẳng hạn như đọc bẩn hoặc cập nhật bị mất mà người dùng có thể gặp phải.

Ví dụ cụ thể về mối quan hệ giữa khóa và mức cách ly trong SQL Server (sử dụng 2PL ngoại trừ trên READ_COMMITED với READ_COMMITTED_SNAPSHOT = ON)

  • READ_UNCOMMITED: không phát hành khóa dùng chung để ngăn các giao dịch khác sửa đổi dữ liệu được đọc bởi giao dịch hiện tại. READ UNCOMMITTED giao dịch cũng không bị chặn bởi các khóa độc quyền sẽ ngăn giao dịch hiện tại đọc các hàng đã được sửa đổi nhưng không được cam kết bởi các giao dịch khác. [...]

  • READ_COMMITED:

    • Nếu READ_COMMITTED_SNAPSHOT được đặt thành TẮT (mặc định): sử dụng khóa chia sẻ để ngăn các giao dịch khác sửa đổi hàng trong khi giao dịch hiện tại đang chạy thao tác đọc. Các khóa chia sẻ cũng chặn câu lệnh đọc các hàng được sửa đổi bởi các giao dịch khác cho đến khi giao dịch khác được hoàn thành. [...] Khóa hàng được giải phóng trước khi hàng tiếp theo được xử lý. [...]
    • Nếu READ_COMMITTED_SNAPSHOT được đặt thành BẬT, Công cụ cơ sở dữ liệu sử dụng lập phiên bản hàng để trình bày từng câu lệnh với ảnh chụp nhanh dữ liệu nhất quán về giao dịch như nó tồn tại ở đầu câu lệnh. Khóa không được sử dụng để bảo vệ dữ liệu khỏi các cập nhật bởi các giao dịch khác.
  • REPETEABLE_READ: Các khóa dùng chung được đặt trên tất cả dữ liệu được đọc bởi mỗi câu lệnh trong giao dịch và được giữ cho đến khi giao dịch hoàn tất.

  • SERIALIZABLE: Khóa phạm vi được đặt trong phạm vi giá trị khóa phù hợp với điều kiện tìm kiếm của mỗi câu lệnh được thực hiện trong một giao dịch. [...] Các khóa phạm vi được giữ cho đến khi giao dịch hoàn tất.


5

Các khóa luôn được thực hiện ở cấp DB: -

Tài liệu chính thức của Oracle: - Để tránh xung đột trong quá trình giao dịch, DBMS sử dụng các khóa, cơ chế để chặn quyền truy cập của người khác vào dữ liệu đang được giao dịch truy cập. (Lưu ý rằng trong chế độ tự động cam kết, trong đó mỗi câu lệnh là một giao dịch, các khóa chỉ được giữ cho một câu lệnh.) Sau khi khóa được thiết lập, khóa vẫn có hiệu lực cho đến khi giao dịch được cam kết hoặc khôi phục lại. Ví dụ, một DBMS có thể khóa một hàng của bảng cho đến khi các cập nhật cho nó được cam kết. Tác dụng của khóa này là ngăn người dùng đọc sai, tức là đọc một giá trị trước khi nó được thực hiện vĩnh viễn. (Việc truy cập một giá trị đã cập nhật mà chưa được cam kết được coi là đọc bẩn vì giá trị đó có thể được khôi phục về giá trị trước đó của nó. Nếu bạn đọc một giá trị sau đó được khôi phục lại, bạn sẽ đọc một giá trị không hợp lệ. )

Cách thiết lập khóa được xác định bởi mức được gọi là mức cô lập giao dịch, có thể bao gồm từ hoàn toàn không hỗ trợ giao dịch đến hỗ trợ giao dịch thực thi các quy tắc truy cập rất nghiêm ngặt.

Một ví dụ về mức cách ly giao dịch là TRANSACTION_READ_COMMITTED, mức này sẽ không cho phép một giá trị được truy cập cho đến khi nó được cam kết. Nói cách khác, nếu mức cách ly giao dịch được đặt thành TRANSACTION_READ_COMMITTED, thì DBMS sẽ không cho phép các lần đọc bẩn xảy ra. Giao diện Kết nối bao gồm năm giá trị đại diện cho các mức cách ly giao dịch mà bạn có thể sử dụng trong JDBC.

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.