Quản lý giao dịch trong MongoDB
- 15-07-2026
- Toanngo92
- 0 Comments
Mục lục
Mục tiêu bài học
- Hiểu giao dịch (transaction) trong MongoDB và bốn thuộc tính ACID.
- Phân biệt Core API và Callback API khi làm việc với transaction.
- Nhận biết hai nhãn lỗi transaction quan trọng trong MongoDB.
- Biết cách tạo session, bắt đầu, commit và abort một transaction.
- Thực hiện transaction trên một hoặc nhiều document, nhiều collection.
Hãy hình dung quy trình đặt hàng trên một website thương mại điện tử: hệ thống tính tổng tiền, nhận thông tin thanh toán, gửi yêu cầu đến cổng thanh toán và chỉ tạo đơn hàng khi giao dịch được chấp thuận. Các bước này phải được xem là một đơn vị công việc duy nhất. Nếu thanh toán thất bại nhưng đơn hàng vẫn được tạo, hoặc tiền đã bị trừ nhưng đơn hàng không tồn tại, dữ liệu sẽ rơi vào trạng thái không nhất quán.
Một tập hợp thao tác được thực hiện như một đơn vị duy nhất được gọi là transaction. Bài viết này trình bày cách MongoDB quản lý transaction, session, commit, rollback và transaction trên nhiều document.
1. Transaction trong MongoDB là gì?
Transaction là một nhóm thao tác cơ sở dữ liệu được thực thi như một đơn vị công việc duy nhất. Hoặc toàn bộ thao tác thành công, hoặc không thao tác nào được áp dụng. Khi một thao tác trong transaction thất bại, các thay đổi trước đó của transaction phải được hoàn tác để cơ sở dữ liệu trở về trạng thái ban đầu.
MongoDB hỗ trợ transaction trên một document và transaction trên nhiều document. Với thao tác chỉ tác động đến một document, MongoDB vốn đã bảo đảm tính nguyên tử ở cấp document. Transaction nhiều document được dùng khi một quy trình nghiệp vụ cần cập nhật đồng thời nhiều document hoặc nhiều collection.
1.1 Bốn thuộc tính ACID

- Atomicity – Tính nguyên tử: tất cả thao tác trong transaction cùng thành công hoặc cùng bị hủy. Ví dụ, khi chuyển tiền từ tài khoản A sang B, nếu thao tác cộng tiền vào B thất bại thì khoản tiền đã trừ ở A phải được hoàn lại.
- Consistency – Tính nhất quán: transaction chỉ được chấp nhận khi kết quả tuân thủ các quy tắc và ràng buộc của dữ liệu.
- Isolation – Tính cô lập: các transaction chạy đồng thời không được nhìn thấy trạng thái trung gian hoặc làm ảnh hưởng sai lệch kết quả của nhau.
- Durability – Tính bền vững: sau khi commit thành công, thay đổi được lưu bền vững và không bị mất do sự cố nguồn điện hoặc phần cứng.
Một transaction kết thúc bằng commit hoặc abort/rollback. Commit làm cho thay đổi trở nên bền vững và có thể quan sát từ bên ngoài transaction. Abort loại bỏ toàn bộ thay đổi do transaction tạo ra.
1.2 Transaction và replica set
Transaction nhiều document được hỗ trợ trên replica set và sharded cluster, không dùng trên một triển khai standalone. Replica set gồm nhiều tiến trình mongod duy trì các bản sao dữ liệu giống nhau, giúp transaction có thể được commit hoặc rollback một cách nhất quán và tăng tính sẵn sàng của dữ liệu.
2. API transaction trong MongoDB
MongoDB cung cấp hai cách chính để triển khai transaction:
| API | Đặc điểm |
|---|---|
| Core API | Lập trình viên gọi rõ ràng các hàm bắt đầu, commit hoặc abort transaction. API không tự xử lý lỗi mặc định, nhưng cho phép tùy biến đầy đủ chiến lược xử lý lỗi. |
| Callback API | Thực thi các thao tác trong một callback, tự commit hoặc abort và tích hợp cơ chế thử lại cho các nhãn lỗi transaction được MongoDB hỗ trợ. |
Core API phù hợp khi bạn cần kiểm soát chi tiết vòng đời transaction. Callback API, thường được driver cung cấp qua hàm như withTransaction(), giúp giảm mã lặp và xử lý retry an toàn hơn.
3. Xử lý lỗi transaction
Xử lý lỗi là phần bắt buộc của transaction. Nếu chỉ bắt lỗi chung mà không xác định đúng loại lỗi, ứng dụng có thể thử lại một thao tác không an toàn hoặc ghi nhận kết quả sai. Hai nhãn lỗi quan trọng là:
| Nhãn lỗi | Ý nghĩa và cách xử lý |
|---|---|
TransientTransactionError | Đã xảy ra lỗi tạm thời, chẳng hạn lỗi mạng hoặc xung đột giữa các transaction cùng sửa một document. Cần thử lại toàn bộ transaction, không chỉ một thao tác ghi riêng lẻ. |
UnknownTransactionCommitResult | Client không xác định được kết quả commit, thường do mất kết nối khi commit. Có thể thử lại thao tác commit cho đến khi nhận được kết quả xác định. |
Không nên tự động thử lại mọi lỗi theo cùng một cách. Việc retry phải dựa trên nhãn lỗi do MongoDB driver trả về.
4. Session và các phương thức transaction
Session là nhóm logic của các thao tác đọc và ghi cần thực thi tuần tự. Một session có thể chứa nhiều transaction, nhưng tại một thời điểm chỉ có một transaction đang hoạt động. Nếu session kết thúc trước khi transaction hoàn tất, transaction sẽ bị hủy.
4.1 Bắt đầu transaction
session.startTransaction({
readConcern: { level: "snapshot" },
writeConcern: { w: "majority" }
})
readConcern quyết định mức nhất quán khi đọc dữ liệu. Giá trị snapshot cung cấp một ảnh chụp nhất quán của dữ liệu cho transaction. writeConcern quy định mức xác nhận thao tác ghi; w: "majority" yêu cầu đa số thành viên lưu trữ dữ liệu của replica set xác nhận.
4.2 Commit và abort
session.commitTransaction()
// Hoặc hoàn tác toàn bộ transaction
session.abortTransaction()
commitTransaction() lưu vĩnh viễn các thay đổi và làm chúng hiển thị cho các session khác. abortTransaction() loại bỏ các thay đổi chưa commit.
5. Thực hành tạo và commit một transaction
Ví dụ sử dụng replica set ba thành viên và database Employee có collection EmpDetail. Đầu tiên, tạo unique index để không có hai nhân viên trùng Emp_ID:
use Employee
db.EmpDetail.createIndex(
{ Emp_ID: 1 },
{ unique: true }
)
Trên primary, tạo session và bắt đầu transaction:
var session = db.getMongo().startSession()
session.startTransaction({
readConcern: { level: "snapshot" },
writeConcern: { w: "majority" }
})
var empdetail = session
.getDatabase("Employee")
.getCollection("EmpDetail")
Chèn một document mới thông qua collection gắn với session:
empdetail.insertOne({
Emp_ID: 102,
Emp_Name: "John Edward",
Gender: "Male",
Designation: "Software Engineer"
})
Trong chính transaction, thao tác có thể đọc được document vừa chèn. Tuy nhiên, session khác và secondary chưa nhìn thấy thay đổi vì transaction chưa được commit.
empdetail.find()
session.commitTransaction()
session.endSession()

Sau khi commit, document có Emp_ID: 102 trở nên hiển thị trên secondary sau khi replication hoàn tất. Khi cần đọc trực tiếp từ secondary trong môi trường thực hành, hãy cấu hình read preference phù hợp với phiên bản mongosh đang sử dụng.
6. Abort transaction và hoàn tác thay đổi
Trong ví dụ tiếp theo, transaction cập nhật chức danh của nhân viên 105 và xóa nhân viên 103:
var session = db.getMongo().startSession()
session.startTransaction({
readConcern: { level: "snapshot" },
writeConcern: { w: "majority" }
})
var empdetail = session
.getDatabase("Employee")
.getCollection("EmpDetail")
empdetail.updateOne(
{ Emp_ID: 105 },
{ $set: { Designation: "Project Lead" } }
)
empdetail.deleteOne({ Emp_ID: 103 })
Nếu người dùng nhận ra đã xóa nhầm document 103 thay vì document 102, toàn bộ transaction phải được hủy:
session.abortTransaction()
session.endSession()
db.EmpDetail.find()

Cả thao tác update lẫn delete đều bị hoàn tác. MongoDB mặc định hủy transaction chạy quá thời gian giới hạn của hệ thống; giá trị thường gặp là 60 giây và có thể được cấu hình bởi quản trị viên.
7. Transaction trên nhiều document và nhiều collection
Giả sử chức danh của nhân viên được lưu đồng thời trong EmpDetail và DesignationDetail. Khi đổi chức danh từ Accountant thành Finance Executive, hai collection phải được cập nhật cùng một transaction để tránh dữ liệu không đồng bộ.
var session = db.getMongo().startSession()
session.startTransaction({
readConcern: { level: "snapshot" },
writeConcern: { w: "majority" }
})
var employeeDb = session.getDatabase("Employee")
var empdetail = employeeDb.getCollection("EmpDetail")
var designation = employeeDb.getCollection("DesignationDetail")
empdetail.updateOne(
{ Emp_ID: 105 },
{ $set: { Designation: "Finance Executive" } }
)
designation.updateOne(
{ Designation_ID: 10003 },
{ $set: { Designation_Title: "Finance Executive" } }
)
session.commitTransaction()
session.endSession()

Nếu một trong hai lệnh update thất bại, transaction có thể bị abort để không collection nào lưu trạng thái dở dang. Đây là tình huống điển hình cho transaction nhiều document.
8. Tổng kết
- Transaction là một đơn vị công việc logic gồm một hoặc nhiều thao tác.
- Bốn thuộc tính ACID bảo vệ tính toàn vẹn và nhất quán của dữ liệu.
- MongoDB cung cấp Core API và Callback API để triển khai transaction.
TransientTransactionErroryêu cầu thử lại toàn bộ transaction;UnknownTransactionCommitResultthường yêu cầu thử lại commit.- Session cung cấp các phương thức bắt đầu, commit và abort transaction.
- Transaction nhiều document giúp cập nhật nhất quán dữ liệu trên nhiều document hoặc collection.
Bài tập
- Triển khai replica set ba thành viên theo kiến trúc Primary–Secondary–Secondary.
- Tạo database
Inventoryvà collectionsales_invent. - Chèn một số document sản phẩm và tạo unique index cho trường
cust_id. - Bắt đầu transaction để cập nhật sản phẩm của khách hàng 1007 thành
Dairy product, đồng thời xóa document của khách hàng 1002. - Commit transaction và kiểm tra hai thay đổi trên các secondary.
- Tạo transaction khác, chèn khách hàng 1009, sau đó abort và xác nhận document không xuất hiện trên secondary.
