Cơ sở dữ liệu tuân thủ ACID là gì? |
Khi bạn xây dựng và duy trì một ứng dụng, điều cuối cùng mà bạn muốn phải lo lắng chính là tính toàn vẹn dữ liệu; Tính phí sai cho khách hàng hay làm mất dữ liệu của họ có thể gây thảm họa. May mắn thay, các cơ sử dữ liệu mà bạn đang sử dụng - như MySQL và Postgres - sử dụng các biện pháp đặc biệt để đảm bảo điều đó không xảy ra. Nhưng điều gì đang xảy ra đằng sau hậu trường? Hầu hết các cơ sở dữ liệu SQL hiện đại đều sử dụng các tiêu chuẩn giao dịch như ACID để đảm bảo tính toàn vẹn của dữ liệu và ngăn người dùng nhìn thấy dữ liệu sai hoặc lỗi thời, và bài viết này sẽ khám phá cách chúng hoạt động.
Mục lục
Tất cả những điều có thể sai sót trong các giao dịch của bạn
Các nhà khoa học dữ liệu lo lắng về các truy vấn phân tích dài và việc lưu trữ dữ liệu, nhưng đối với các nhà phát triển, cơ sở dữ liệu là tất cả về các giao dịch. Một giao dịch cơ sở dữ liệu là một chuỗi các thao tác cơ sở dữ liệu được nhóm lại một cách logic: chèn một hàng ở đây, cập nhật một bản ghi ở kia, và nhiều thứ khác như vậy. Mã ứng dụng của bạn liên tục thực hiện các giao dịch mỗi khi bạn đăng ký một người dùng mới hoặc người dùng đó cập nhật thông tin tài khoản của mình.
Vấn đề với các giao dịch là chúng có thể đi sai hoàn toàn. Có vô số điều có thể xảy ra khi bạn đang cố gắng ghi vào cơ sở dữ liệu của mình: bạn có thể mất kết nối với một phiên bản từ xa, bạn có thể gặp phải lỗi giá trị, hoặc bất kỳ thứ gì khác có thể xảy ra. Bạn đã từng thấy và đã xử lý nó, và nó có thể gây ra thảm hoạ cho dữ liệu của bạn. Hãy cùng xem một ví dụ nhanh mà một công ty như Amazon có thể gặp phảii:
- Người dùng cập nhật số lượng đặt hàng và nhấp vào "đặt hàng ngay" ->
- Cập nhật số lượng đặt hàng trong bảng đơn hàng chờ
- Thêm hàng vào bảng đơn hàng
- Áp dụng mua hàng vào số dư của người dùng / tính phí thẻ tín dụng
Nếu có điều gì đó xảy ra sai sót trong giữa nhóm các hoạt động này nhưng hệ thống tiếp tục thực thi chúng, người dùng sẽ bị tính phí sai. Và nếu việc tính phí không thành công, họ sẽ nhận được đơn hàng miễn phí. Những loại lỗi dữ liệu này đều có tên gọi và có rất nhiều loại. Một vài ví dụ:
Đọc bẩn (Dirty Reads)
Nếu một giao dịch đang ở giữa việc cập nhật một số dữ liệu và chưa được cam kết (commit), và một giao dịch khác được phép đọc dữ liệu chưa cam kết đó, điều đó rất bẩn và có thể dẫn đến ứng dụng của bạn hiển thị dữ liệu không chính xác đã bị hoàn tác.
Một ví dụ về đọc bẩn có thể là một giao dịch làm mất hiệu lực của mã thông báo đăng nhập khi người dùng thay đổi mật khẩu của họ. Nếu khi giao dịch đầu tiên tải mã thông báo, giao dịch thứ hai đọc mã thông báo đó trước khi giao dịch đầu tiên làm mất hiệu lực của nó, bạn sẽ có một lần đọc bẩn.
Về mặt SQL thực tế, đây là cách một lần đọc bẩn có thể trông như thế này:
### Transaction 1 ###
SELECT user_login_token_id
FROM tokens
UPDATE tokens
SET token_status = "INVALID"
WHERE token_id = user_login_token_id
### Transaction 2 ###
SELECT user_login_token_id
FROM tokens
Đọc không lặp lại (Non-Repeatable Reads)
Nếu bạn có hai lần đọc liên tiếp trong một giao dịch với bản cập nhật đồng thời ở giữa, các lần đọc đó sẽ hiển thị kết quả khác nhau mặc dù chúng là một phần của cùng một giao dịch.
Một ví dụ có thể là hai người viết đang làm việc trên một blog. Người dùng đầu tiên của chúng ta bắt đầu một giao dịch đọc tiêu đề của bài đăng, viết vào bài đăng và sau đó đọc lại tiêu đề của bài đăng đó. Nếu người dùng thứ hai thay đổi tiêu đề của bài đăng đó ở giữa giao dịch của người dùng đầu tiên, người dùng đầu tiên sẽ thấy các giá trị khác nhau cho tiêu đề trên hai lần đọc; hoặc nói cách khác, một lần đọc không lặp lại.
Đây là cách một lần đọc không lặp lại có thể trông như thế này trong SQL:
### Transaction 1 ###
SELECT post_title
FROM posts
SELECT
post_title,
post_content
FROM posts
### Transaction 2 ###
UPDATE posts
SET post_title = "something_new"
WHERE post_title = post_title
Đọc ma (Phantom Reads)
Nếu một giao dịch đọc dữ liệu và sau đó một giao dịch đồng thời chèn dữ liệu mà sẽ được đọc trong giao dịch ban đầu, đó là một lần đọc ma. Hãy sử dụng cùng một ví dụ như một lần đọc không lặp lại: nếu người dùng thứ hai của chúng ta thêm nội dung ở giữa hai lần đọc của người dùng đầu tiên, lần đọc đầu tiên sẽ thiếu dữ liệu xuất hiện trong lần đọc thứ hai (điều này thực sự rất giống với một lần đọc không lặp lại, đó là lý do tại sao ví dụ tương tự hoạt động).
Trong SQL, một lần đọc ma có thể trông như thế này:
### Transaction 1 ###
SELECT post_title
FROM posts
SELECT
post_title,
post_content
FROM posts
### Transaction 2 ###
INSERT INTO posts
VALUES "something_new", ...
Đây là 3 lỗi giao dịch được định nghĩa bởi tiêu chuẩn SQL - ba lỗi lớn, bạn có thể nói như vậy. Rất nhiều lỗi này nghe có vẻ giống nhau và có xu hướng chồng chéo trong thực tế, vì vậy đừng lo lắng về các chi tiết
Bây giờ, câu hỏi quan trọng: làm thế nào để chúng ta tránh những điều này?
ACID, nhưng là loại tốt
Các cơ sở dữ liệu quan hệ phổ biến như MySQL tránh các vấn đề về tính toàn vẹn dữ liệu này bằng cách tuân theo một số nguyên tắc cốt lõi điều chỉnh cách thức hoạt động của các giao dịch. Chúng tuân thủ một tiêu chuẩn giao dịch gọi là ACID. ACID là từ viết tắt của bốn từ khác nhau, nhưng nó thực sự được chia thành hai nguyên tắc cốt lõi: tính đầy đủ và tính đồng thời. Đầu tiên, đây là những gì ACID viết tắt:
- Nguyên tử (Atomicity): quy tắc "tất cả hoặc không có gì" - giao dịch hoặc xảy ra hoàn toàn hoặc không xảy ra.
- Tính nhất quán (Consistency): dữ liệu nhất quán trước và sau một giao dịch mà không có bất kỳ bước nào bị thiếu.
- Cách ly (Isolation): nhiều giao dịch có thể xảy ra đồng thời mà không đọc sai dữ liệu.
- Tính bền vững (Durability): Sự thành công của giao dịch vẫn được đảm bảo ngay cả khi hệ thống gặp sự cố.
Chúng chồng chéo rất nhiều, vì vậy chỉ cần nhớ: mục đích của bất kỳ cơ sở dữ liệu tuân thủ ACID nào là đảm bảo rằng:
- Các giao dịch có thể thất bại mà không làm tổn hại đến tính toàn vẹn dữ liệu.
- Nhiều giao dịch có thể xảy ra đồng thời mà không đọc và ghi sai dữ liệu.
ACID là một tập hợp các thuộc tính, nhưng nó không phải là một quá trình: làm thế nào mà các cơ sở dữ liệu SQL mà chúng ta sử dụng thực sự đạt được sự tuân thủ ACID? Chúng sử dụng một hệ thống gọi là khóa để giữ cho cơ sở dữ liệu tạm dừng trong khi các giao dịch đang xảy ra.
Khóa hoạt động giống như bạn tưởng tượng: khi một giao dịch bắt đầu, công cụ cơ sở dữ liệu khóa dữ liệu mà nó đang làm việc cho đến khi giao dịch hoàn thành (và đôi khi, vượt quá thời gian đó). Bằng cách đó, các giao dịch đồng thời không thể làm việc với dữ liệu đang bị thay đổi bởi giao dịch đầu tiên.
Một khi một giao dịch bắt đầu và có được một khóa, nó có thể hoàn thành thành công và cam kết, hoặc gặp lỗi và hủy bỏ. Nó giống như việc viết trong bảng tính Excel trước khi lưu công việc của bạn - mọi thứ đều được thay đổi, nhưng chỉ nhẹ nhàng, cho đến khi bạn lưu chúng (cam kết) hoặc hoàn nguyên chúng (hủy bỏ). Quay trở lại ví dụ Amazon của chúng tôi: nếu cơ sở dữ liệu của chúng tôi gặp lỗi ngay sau khi cập nhật số lượng đơn hàng của người dùng, giao dịch sẽ bị hủy bỏ và như thể bản cập nhật đó chưa bao giờ xảy ra. Và nếu lỗi xảy ra trong quá trình cập nhật, thẻ tín dụng sẽ không bao giờ bị tính phí. Hoặc là mọi thứ đều xảy ra hoặc không có gì xảy ra, và đó là ACID.
Khái niệm ACID trong NoSQL và hệ thống phân tán
ACID là nền tảng của các CSDL quan hệ đáng tin cậy mà chúng ta quen thuộc ngày nay, nhưng NoSQL đã thay đổi cuộc chơi: nhiều CSDL NoSQL được xây dựng như các hệ thống phân tán và chúng không thể luôn đảm bảo tính nhất quán giao dịch hoàn toàn. Trên thực tế, có một lý thuyết chi phối điều này - được gọi là định lý CAP - rằng trong các hệ thống phân tán, bạn không thể bao giờ có cả tính nhất quán đầy đủ và khả dụng đầy đủ; bạn cần phải chọn một trong hai. Vậy ACID trông như thế nào đối với một thứ gì đó như MongoDB hoặc Cassandra?
Một chuẩn gần đúng mới đã xuất hiện cho các cơ sở dữ liệu NoSQL gọi là BASE (một sự trùng hợp hiếm hoi giữa SQL và những câu chuyện cười về hóa học), và đó là một mô hình nhất quán yếu hoặc mềm dẻo, giảm bớt một số giả định của ACID để đạt được khả năng mở rộng:
- Khả dụng cơ bản (Basic Availability): cơ sở dữ liệu hoạt động cơ bản hầu hết thời gian, mặc dù không hoàn hảo.
- Trạng thái mềm (Soft-State): các nút của cơ sở dữ liệu không nhất thiết phải nhất quán với nhau mọi lúc.
- Nhất quán cuối cùng (Eventual Consistency): dữ liệu cuối cùng sẽ nhất quán trên tất cả các nút, chẳng hạn như theo thời gian đọc.
Theo nhiều cách, đây là điều hoàn toàn ngược lại với ACID và ưu tiên khả dụng hơn là tính nhất quán hoàn hảo; nhưng đó là một phần quan trọng của NoSQL ngay từ đầu. Khi NoSQL trở thành một phần được thiết lập hơn của phát triển ứng dụng (hơn 25% nhà phát triển đang sử dụng MongoDB), hãy mong đợi nhiều tiến bộ hơn trên mặt trận này.
Giải thích
- Định lý CAP: Nguyên lý này cho rằng trong một hệ thống phân tán, không thể đảm bảo đồng thời tính nhất quán, khả dụng và khả năng chịu lỗi phân vùng. Bạn phải chọn hai trong ba.
- Mô hình BASE: Là một sự thay thế cho ACID cho các cơ sở dữ liệu NoSQL, nhấn mạnh khả dụng và nhất quán cuối cùng hơn là các đảm bảo ACID nghiêm ngặt.
- Sự khác biệt: BASE ưu tiên khả dụng và khả năng mở rộng, điều quan trọng đối với nhiều ứng dụng NoSQL, nhưng có thể hy sinh một số mức độ nhất quán dữ liệu
Từ vựng Tiếng Anh mới
Compliant - Tuân thủ
adjective - uk /kəmˈplaɪ.ənt/ us /kəmˈplaɪ.ənt/
Eg.: What is an ACID compliant database?
Catastrophic - Thảm họa
noun - uk /kəˈtæs.trə.fi/ us /kəˈtæs.trə.fi/
>Eg.: Charging a customer the wrong amount or losing their data can be catastrophic.
>Underlying - Cơ bản, cơ sở
adjective - uk /ˌʌn.dəˈlaɪ.ɪŋ/ us /ˌʌn.dɚˈlaɪ.ɪŋ/
Eg.: It can mean disaster for your underlying data.
Invalidate - Làm mất hiệu lực
verb - uk /ɪnˈvæl.ɪ.deɪt/ us /ɪnˈvæl.ə.deɪt/
Eg.: An example of a dirty read could be a transaction that invalidates login tokens when a user changes their password.
Consecutive - Liên tiếp
adjective - uk /kənˈsek.jə.tɪv/ us /kənˈsek.jə.t̬ɪv/
Eg.: If you’ve got two consecutive reads in one transaction with a concurrent update in between, those reads are going to show different results even though they’re part of the same transaction.
Govern - Quản lý
verb - uk /ˈɡʌv.ən/ us /ˈɡʌv.ɚn/
Eg.: Popular relational databases like MySQL avoid these kinds of data integrity issues by following a few core principles that govern how transactions work
Intricacy - Sự phức tạp
noun - uk /ˈɪn.trɪ.kə.si/ us /ˈɪn.trə.kə.si/
Eg.: I enjoyed the film, but I couldn't follow all the intricacies of the plot.