Transactions & ACID là gì?

Trong Backend, một request gửi đến API có thể yêu cầu hệ thống thực hiện nhiều thao tác trên database. Chẳng hạn, khi khách hàng đặt hàng, hệ thống có thể cần tạo đơn hàng, lưu chi tiết đơn hàng và cập nhật số lượng tồn kho.

Nếu một thao tác thất bại sau khi những thao tác trước đó đã thành công, dữ liệu có thể rơi vào trạng thái không nhất quán. Để xử lý vấn đề này, database cung cấp cơ chế Transaction (giao dịch).

ACID là tập hợp bốn thuộc tính quan trọng mô tả các bảo đảm của transaction, giúp các thao tác trên database được thực hiện một cách đáng tin cậy.

1. Transaction là gì?

Transaction (giao dịch) là một nhóm thao tác trên database được xem như một đơn vị xử lý. Các thao tác này được quản lý theo một quy tắc thống nhất: hoặc những thay đổi được xác nhận thành công, hoặc những thay đổi chưa được xác nhận sẽ được hoàn tác khi transaction thất bại.

Ví dụ, trong một hệ thống quản lý bán hàng, khi khách hàng đặt một sản phẩm, hệ thống có thể cần thực hiện các thao tác sau:

  1. Tạo đơn hàng trong bảng orders.
  2. Lưu các sản phẩm thuộc đơn hàng trong bảng order_items.
  3. Cập nhật số lượng tồn kho trong bảng products.

Các thao tác này có quan hệ với nhau vì chúng cùng phục vụ một nghiệp vụ: đặt hàng.

Nếu hệ thống tạo đơn hàng thành công nhưng gặp lỗi khi cập nhật tồn kho, việc chỉ giữ lại những thay đổi đã thực hiện có thể khiến dữ liệu không phản ánh đúng trạng thái của nghiệp vụ. Transaction giúp quản lý các thay đổi đó như một đơn vị xử lý.

COMMIT và ROLLBACK

Hai thao tác quan trọng khi làm việc với transaction là:

  • COMMIT: Xác nhận các thay đổi của transaction.
  • ROLLBACK: Hoàn tác các thay đổi chưa được xác nhận của transaction.

Ví dụ, khi tạo đơn hàng, nếu tất cả thao tác cần thiết đều thành công, hệ thống có thể commit transaction. Nếu xảy ra lỗi trước khi commit, hệ thống có thể rollback để hoàn tác những thay đổi thuộc transaction đó.

Trong SQL, một transaction cơ bản có thể được viết như sau:

BEGIN;

INSERT INTO orders (customer_id, status)
VALUES (1, 'pending');

UPDATE products
SET stock = stock - 1
WHERE id = 10 AND stock > 0;

COMMIT;

Đây là ví dụ minh họa cơ chế transaction. Trong ứng dụng thực tế, hệ thống còn cần kiểm tra số lượng bản ghi được cập nhật, xử lý trường hợp sản phẩm hết hàng và chỉ commit khi toàn bộ điều kiện nghiệp vụ được đáp ứng. Nếu có lỗi, ứng dụng cần rollback thay vì commit các thay đổi dở dang.

2. ACID là gì?

ACID là viết tắt của bốn thuộc tính:

  • Atomicity: Tính nguyên tử.
  • Consistency: Tính nhất quán.
  • Isolation: Tính cô lập.
  • Durability: Tính bền vững.

Bốn thuộc tính này giúp giải thích cách database quản lý transaction, duy trì các ràng buộc dữ liệu và xử lý những tình huống có thể xảy ra khi nhiều thao tác hoặc nhiều request diễn ra đồng thời.

2.1. Atomicity — Tính nguyên tử

Atomicity có nghĩa là transaction được xử lý như một đơn vị: các thay đổi được xác nhận cùng nhau, hoặc được hoàn tác khi transaction thất bại.

Ví dụ, khi đặt hàng, hệ thống cần tạo đơn hàng và trừ tồn kho. Nếu thao tác tạo đơn hàng đã thực hiện nhưng một thao tác bắt buộc khác thất bại, transaction có thể được rollback để không giữ lại phần thay đổi dở dang.

Atomicity giúp tránh tình trạng một nghiệp vụ chỉ được thực hiện một phần trong database.

2.2. Consistency — Tính nhất quán

Consistency có nghĩa là một transaction khi hoàn tất phải đưa database từ trạng thái hợp lệ sang một trạng thái hợp lệ khác, theo các ràng buộc và quy tắc đã được xác định.

Ví dụ, nếu hệ thống quy định số lượng tồn kho không được âm, thao tác đặt hàng cần bảo đảm quy tắc này không bị vi phạm.

Database có thể hỗ trợ bằng các ràng buộc như:

  • NOT NULL: không cho phép giá trị NULL tại cột được quy định.
  • UNIQUE: bảo đảm giá trị hoặc tổ hợp giá trị được ràng buộc là duy nhất.
  • FOREIGN KEY: bảo đảm tính hợp lệ của mối quan hệ tham chiếu giữa các bảng.
  • CHECK: kiểm tra điều kiện đối với giá trị dữ liệu.

Tuy nhiên, transaction không tự động hiểu mọi quy tắc nghiệp vụ. Lập trình viên cần xác định và triển khai các điều kiện phù hợp trong database hoặc ứng dụng.

2.3. Isolation — Tính cô lập

Isolation liên quan đến cách database xử lý nhiều transaction diễn ra đồng thời.

Ví dụ, kho chỉ còn một sản phẩm nhưng hai khách hàng gửi request đặt hàng gần như cùng lúc. Nếu cả hai request đều đọc được số lượng tồn kho là một rồi cùng tiếp tục xử lý mà không có cơ chế kiểm soát phù hợp, hệ thống có thể nhận nhiều đơn hàng hơn số lượng hàng thực tế.

Database sử dụng các cơ chế như khóa dữ liệu (locking), MVCC và các mức cô lập transaction để kiểm soát những tương tác này.

Mức cô lập càng cao thường cung cấp những bảo đảm mạnh hơn về tính nhất quán khi xử lý đồng thời, nhưng cũng có thể làm giảm khả năng xử lý song song hoặc tăng nguy cơ phải thử lại transaction. Vì vậy, việc lựa chọn isolation level cần phù hợp với yêu cầu của nghiệp vụ.

2.4. Durability — Tính bền vững

Durability có nghĩa là khi transaction đã commit thành công, các thay đổi phải được lưu giữ theo những bảo đảm về độ bền mà database cung cấp.

Ví dụ, sau khi đơn hàng đã được xác nhận và transaction commit thành công, việc server khởi động lại không nên khiến đơn hàng đã commit biến mất.

Database thường sử dụng các cơ chế ghi log và khôi phục dữ liệu để thực hiện bảo đảm này. Mức độ bảo vệ thực tế còn phụ thuộc vào cấu hình, hệ thống lưu trữ và các cơ chế dự phòng được triển khai.

3. Transaction và ACID liên quan với nhau như thế nào?

Transaction là cơ chế để nhóm các thao tác database thành một đơn vị xử lý. ACID mô tả bốn thuộc tính quan trọng của cách xử lý đó.

Thuộc tính Ý nghĩa Ví dụ trong hệ thống đặt hàng
Atomicity Xác nhận hoặc hoàn tác các thay đổi của transaction Không giữ lại đơn hàng dở dang khi thao tác bắt buộc thất bại
Consistency Duy trì các ràng buộc dữ liệu đã xác định Tồn kho không âm nếu hệ thống có quy tắc này
Isolation Kiểm soát tương tác giữa các transaction đồng thời Hai khách hàng không cùng mua vượt số lượng hàng có sẵn
Durability Giữ lại các thay đổi đã commit theo cam kết của database Đơn hàng đã commit vẫn tồn tại sau khi server khởi động lại

Cần lưu ý rằng ACID không phải là bốn câu lệnh SQL. Đây là các thuộc tính và bảo đảm của transaction; còn việc đạt được chúng phụ thuộc vào database, cách cấu hình và cách lập trình viên triển khai nghiệp vụ.

4. Vì sao Backend Developer cần hiểu Transaction & ACID?

Trong Backend, một API có thể thực hiện nhiều thao tác database để hoàn thành một nghiệp vụ. Việc hiểu transaction giúp lập trình viên xác định những thao tác nào cần được xử lý cùng nhau và cách ứng dụng phản ứng khi có lỗi.

Một số trường hợp thường cần xem xét transaction:

  • Tạo đơn hàng và cập nhật tồn kho.
  • Chuyển tiền giữa hai tài khoản.
  • Tạo hóa đơn và các dòng chi tiết hóa đơn.
  • Cập nhật nhiều bảng có quan hệ với nhau.
  • Xử lý nhiều request có khả năng thay đổi cùng một dữ liệu.

Khi thiết kế API, lập trình viên không chỉ cần quan tâm đến việc trả về HTTP Status Code phù hợp mà còn phải bảo đảm những thay đổi dữ liệu phía sau request được xử lý đúng. Chẳng hạn, trả về 201 Created không có nhiều ý nghĩa nếu đơn hàng đã được tạo nhưng các thay đổi bắt buộc khác lại thất bại.

Transaction cũng không thay thế việc thiết kế database tốt. Các khóa chính, khóa ngoại, ràng buộc dữ liệu và quy tắc nghiệp vụ vẫn cần được xác định rõ ràng.

5. Kết luận

Transaction giúp nhóm các thao tác database thành một đơn vị xử lý có kiểm soát. ACID mô tả bốn thuộc tính quan trọng giúp bảo đảm tính nguyên tử, tính nhất quán, tính cô lập và tính bền vững của các thay đổi dữ liệu.

Đối với Backend Developer, hiểu Transaction & ACID là bước chuyển từ việc biết cách truy vấn và thiết kế database sang hiểu cách duy trì tính đúng đắn của dữ liệu khi hệ thống xử lý nghiệp vụ thực tế, đặc biệt khi xảy ra lỗi hoặc nhiều request diễn ra đồng thời.

Nguồn tham khảo

Bài viết khác

locking & dead lock (Transaction)

1. Locking là gì? Locking (cơ chế khóa) là cơ chế database sử dụng để kiểm soát việc nhiều transaction cùng truy cập hoặc thay đổi dữ liệu, nhằm tránh những xung đột có thể làm sai lệch kết quả. Trong một ứng dụng có nhiều user, nhiều request có thể đồng thời thao tác […]

Eloquent ORM

1. Eloquent ORM là gì? Eloquent ORM là ORM được tích hợp sẵn trong Laravel, sử dụng mô hình Active Record để tương tác với database. Eloquent cho phép developer làm việc với dữ liệu thông qua các Model trong PHP thay vì phải viết SQL thủ công cho mọi thao tác. Mỗi model thường […]

ORM

ORM là gì? (Object-Relational Mapping) Trong quá trình phát triển Backend, ứng dụng thường xuyên cần tương tác với database để lưu trữ, truy vấn, cập nhật và xóa dữ liệu. Một cách phổ biến để thực hiện những thao tác này là viết SQL trực tiếp. Tuy nhiên, khi dự án phát triển, việc […]

UAT(Kiểm thử chấp nhận người dùng)

UAT là gì? Trong toàn bộ Vòng đời phát triển phần mềm (SDLC), sau khi trải qua hàng loạt các cấp độ kiểm thử kỹ thuật nội bộ như Unit Testing, Integration Testing, System Testing, sản phẩm phần mềm vẫn chưa thể chính thức phát hành. Bước đệm cuối cùng và mang tính chất quyết […]

N+1 Query Problem

N+1 Query Problem là gì? Trong quá trình phát triển Backend, ứng dụng thường cần truy xuất dữ liệu từ database để trả về cho client. Một API có thể cần lấy danh sách đơn hàng cùng thông tin khách hàng tương ứng. Tuy nhiên, nếu ứng dụng truy vấn dữ liệu liên quan riêng […]

ORM – Object-Relational Mapping Fundamentals

1. ORM là gì? ORM (Object-Relational Mapping) là kỹ thuật ánh xạ giữa các đối tượng trong chương trình và dữ liệu được lưu trữ trong cơ sở dữ liệu quan hệ. Trong ứng dụng backend, dữ liệu thường được biểu diễn bằng struct hoặc object trong code, trong khi database lưu dữ liệu dưới […]

Leave a Reply

Your email address will not be published. Required fields are marked *