Transaction Isolation Levels trong DBMS

Please wait 0 seconds...
Scroll Down and click on Go to Link for destination
Congrats! Link is Generated

Transaction Isolation Levels là một chủ đề thực sự hấp dẫn trong DBMS, và để hiểu rõ nó, chúng ta cần bắt đầu từ một câu hỏi cơ bản: điều gì xảy ra khi nhiều người cùng lúc cố gắng làm việc với cùng một dữ liệu?

Hãy tưởng tượng bạn và bạn bè cùng chỉnh sửa một tài liệu Google Docs. Nếu không có cơ chế kiểm soát, các thay đổi có thể xung đột với nhau, tạo ra kết quả không mong muốn. Trong cơ sở dữ liệu, vấn đề này phức tạp hơn nhiều vì chúng ta đang nói về hàng nghìn giao dịch xảy ra đồng thời.

Nền tảng lý thuyết - Tại sao cần Isolation?

Trước khi đi vào chi tiết các mức độ isolation, chúng ta hãy hiểu tại sao vấn đề này lại quan trọng. Khi nhiều transaction chạy đồng thời, chúng có thể can thiệp vào nhau theo những cách không mong muốn. Hãy cùng xem xét một ví dụ đơn giản để minh họa điều này.

Giả sử bạn có một tài khoản ngân hàng với số dư 1000 USD. Đồng thời có hai giao dịch xảy ra: một giao dịch rút 100 USD và một giao dịch khác kiểm tra số dư để quyết định có cho phép rút 500 USD hay không. Nếu không có kiểm soát isolation, giao dịch kiểm tra số dư có thể đọc được số dư ban đầu là 1000 USD và cho phép rút 500 USD, trong khi giao dịch rút 100 USD cũng đang diễn ra. Kết quả cuối cùng, tài khoản của bạn có thể bị rút tổng cộng 600 USD từ số dư 1000 USD, nhưng hệ thống có thể không nhận ra điều này.

Đây chính là lý do tại sao chúng ta cần các mức độ isolation khác nhau - để kiểm soát mức độ "nhìn thấy" các thay đổi chưa hoàn thành của các transaction khác.

Các vấn đề cần giải quyết - Concurrency Problems

Để hiểu rõ các mức độ isolation, chúng ta cần nắm vững ba vấn đề chính mà chúng được thiết kế để giải quyết.

Dirty Read xảy ra khi một transaction đọc dữ liệu đã được thay đổi bởi transaction khác nhưng chưa được commit. Hãy tưởng tượng bạn đang đọc một bản thảo mà tác giả vẫn đang viết và có thể sẽ xóa bỏ. Nếu bạn dựa vào thông tin đó để đưa ra quyết định, bạn có thể sẽ gặp rắc rối khi tác giả quyết định không giữ lại những gì họ đã viết.

Non-repeatable Read xảy ra khi một transaction đọc cùng một dữ liệu hai lần nhưng nhận được kết quả khác nhau vì có transaction khác đã thay đổi dữ liệu đó trong khoảng thời gian giữa hai lần đọc. Điều này giống như việc bạn kiểm tra giá cổ phiếu vào đầu ngày, thực hiện một số tính toán, sau đó kiểm tra lại và thấy giá đã thay đổi, khiến các tính toán trước đó không còn chính xác.

Phantom Read là phiên bản tinh vi hơn, xảy ra khi một transaction thực hiện cùng một truy vấn hai lần nhưng nhận được số lượng records khác nhau vì có transaction khác đã thêm hoặc xóa records phù hợp với điều kiện truy vấn. Hãy tưởng tượng bạn đang đếm số lượng sinh viên trong một lớp học. Bạn đếm được 30 sinh viên, thực hiện một số công việc khác, sau đó đếm lại và thấy có 32 sinh viên vì có 2 sinh viên mới được thêm vào danh sách lớp trong lúc bạn đang làm việc khác.

Read Uncommitted - Mức độ tự do tối đa

Read Uncommitted là mức độ isolation thấp nhất, nơi mà một transaction có thể đọc được tất cả các thay đổi của các transaction khác, kể cả những thay đổi chưa được commit. Điều này giống như việc bạn được phép đọc tất cả các bản thảo đang được viết dở trong một tòa soạn báo, kể cả những bài viết có thể sẽ không bao giờ được xuất bản.

Mức độ này cho phép hiệu suất cao nhất vì không có gì cản trở việc đọc dữ liệu, nhưng nó cũng cho phép tất cả ba vấn đề concurrency xảy ra. Trong thực tế, Read Uncommitted hiếm khi được sử dụng vì rủi ro về tính chính xác của dữ liệu quá cao. Tuy nhiên, nó có thể hữu ích trong một số tình huống đặc biệt như việc tạo ra các báo cáo thống kê tổng quan nơi mà độ chính xác tuyệt đối không quan trọng bằng tốc độ.

Read Committed - Sự cân bằng thực tế

Read Committed là mức độ isolation phổ biến nhất trong nhiều hệ thống database. Ở mức độ này, một transaction chỉ có thể đọc được dữ liệu đã được commit bởi các transaction khác. Điều này giống như việc bạn chỉ được phép đọc những bài báo đã được xuất bản chính thức, chứ không phải các bản thảo đang được viết dở.

Read Committed ngăn chặn được dirty reads, nhưng vẫn cho phép non-repeatable reads và phantom reads xảy ra. Hãy nghĩ về một ví dụ cụ thể: bạn đang thực hiện một giao dịch để tính tổng số tiền trong tất cả các tài khoản của mình. Trong quá trình tính toán, nếu có giao dịch khác chuyển tiền giữa các tài khoản và commit, bạn có thể đọc được số dư mới của một tài khoản nhưng số dư cũ của tài khoản khác, dẫn đến kết quả không chính xác.

Mặc dù có những hạn chế này, Read Committed cung cấp một sự cân bằng tốt giữa hiệu suất và tính nhất quán, làm cho nó trở thành lựa chọn mặc định cho nhiều ứng dụng thực tế.

Repeatable Read - Tính nhất quán trong phiên làm việc

Repeatable Read đi xa hơn một bước bằng cách đảm bảo rằng nếu một transaction đọc một dữ liệu, mọi lần đọc tiếp theo trong cùng transaction đó sẽ cho ra cùng một kết quả. Điều này giống như việc bạn có một bản sao cố định của tất cả các tài liệu bạn cần trong suốt quá trình làm việc, và không ai có thể thay đổi các tài liệu đó cho đến khi bạn hoàn thành công việc.

Repeatable Read ngăn chặn được dirty reads và non-repeatable reads, nhưng vẫn cho phép phantom reads. Điều này có nghĩa là trong khi các records bạn đã đọc sẽ không thay đổi, các records mới vẫn có thể được thêm vào hoặc xóa đi và xuất hiện trong các truy vấn tiếp theo.

Hãy tưởng tượng bạn đang thực hiện một báo cáo về tất cả các đơn hàng trong tháng. Với Repeatable Read, các đơn hàng bạn đã đọc sẽ không thay đổi thông tin, nhưng các đơn hàng mới vẫn có thể được thêm vào và xuất hiện trong lần truy vấn tiếp theo của bạn.

Serializable - Tính nhất quán tuyệt đối

Serializable là mức độ isolation cao nhất, đảm bảo rằng các transaction được thực hiện như thể chúng chạy tuần tự, từng cái một. Điều này giống như việc bạn có toàn quyền kiểm soát một thư viện và không ai khác được phép vào trong khi bạn đang làm việc.

Serializable ngăn chặn tất cả các vấn đề concurrency, bao gồm cả phantom reads. Tuy nhiên, mức độ isolation này đạt được sự an toàn tuyệt đối bằng cách hy sinh đáng kể hiệu suất. Hệ thống phải sử dụng các cơ chế locking hoặc validation phức tạp để đảm bảo tính serializable.

Trong thực tế, Serializable thường chỉ được sử dụng cho những giao dịch cực kỳ quan trọng nơi mà tính chính xác tuyệt đối quan trọng hơn hiệu suất, chẳng hạn như các giao dịch tài chính lớn hoặc các thao tác audit quan trọng.

Cách thức hoạt động - Mechanisms Behind the Scenes

Để hiểu sâu hơn về isolation levels, chúng ta cần tìm hiểu cách hệ thống database thực hiện chúng. Có hai cơ chế chính: locking và Multi-Version Concurrency Control (MVCC).

Locking mechanism hoạt động bằng cách đặt khóa trên dữ liệu khi có transaction truy cập. Tùy thuộc vào mức độ isolation, các loại khóa khác nhau sẽ được sử dụng. Shared locks cho phép nhiều transaction đọc cùng một dữ liệu, trong khi exclusive locks chỉ cho phép một transaction duy nhất truy cập dữ liệu.

MVCC là một cách tiếp cận tinh vi hơn, trong đó hệ thống duy trì nhiều phiên bản của cùng một dữ liệu. Mỗi transaction sẽ thấy một "snapshot" nhất quán của dữ liệu tại thời điểm transaction bắt đầu. Điều này cho phép các transaction đọc và ghi đồng thời mà không cần sử dụng locks, cải thiện đáng kể hiệu suất.

Lựa chọn Isolation Level - Nghệ thuật của Trade-offs

Việc chọn mức độ isolation phù hợp là một nghệ thuật cân bằng giữa tính nhất quán và hiệu suất. Đây là nơi mà hiểu biết về ứng dụng cụ thể trở nên quan trọng.

Đối với các ứng dụng web thông thường như blog hoặc e-commerce, Read Committed thường là lựa chọn tốt vì nó cung cấp sự cân bằng hợp lý. Đối với các ứng dụng tài chính hoặc những nơi mà tính chính xác dữ liệu là tối quan trọng, bạn có thể cần Repeatable Read hoặc thậm chí Serializable.

Một điều thú vị là bạn có thể thiết lập isolation level ở nhiều mức độ khác nhau: toàn hệ thống, session, hoặc thậm chí từng transaction riêng lẻ. Điều này cho phép bạn tối ưu hóa hiệu suất cho từng loại giao dịch khác nhau trong cùng một ứng dụng.

Bạn có thể thấy rằng transaction isolation levels thực sự là về việc quản lý sự cân bằng giữa tính nhất quán và hiệu suất. Đây là một chủ đề mà ngay cả các database architect giàu kinh nghiệm vẫn phải suy nghĩ cẩn thận. Điều quan trọng là hiểu rõ các trade-offs và chọn mức độ phù hợp với nhu cầu cụ thể của ứng dụng.

Đăng nhận xét

Tham gia cuộc trò chuyện