CodeGym /Các khóa học /SQL SELF /Các lệnh cơ bản để làm việc với giao dịch: BEGIN

Các lệnh cơ bản để làm việc với giao dịch: BEGIN, COMMIT, ROLLBACK

SQL SELF
Mức độ , Bài học
Có sẵn

Để mọi thay đổi trong database của bạn đều được kiểm soát và thực hiện đúng cách, PostgreSQL dùng khái niệm giao dịch (transaction). Đây là một nhóm các thao tác SQL được thực hiện như một khối duy nhất. Nếu có gì đó sai, bạn cần huỷ các thay đổi. Đó là lúc các lệnh BEGIN, COMMITROLLBACK xuất hiện.

Các lệnh giao dịch không chỉ để cho có — chúng đóng vai trò then chốt trong việc bảo vệ dữ liệu khỏi lỗi và sự cố. Khi bạn thực hiện một loạt thao tác SQL, điều quan trọng là phải chắc chắn mọi thứ đều chạy ổn: nếu một lệnh bị lỗi, database phải quay lại trạng thái ban đầu. Đây là một trong những lý do chính tại sao cần có các lệnh giao dịch — chúng giúp giữ cho dữ liệu luôn nhất quán.

Bên cạnh đó, giao dịch còn đảm bảo tính gọi là "atomicity": hoặc là tất cả thay đổi được áp dụng cùng nhau, hoặc không có gì được áp dụng cả. Cách này loại bỏ trường hợp database bị cập nhật "nửa vời" — ví dụ, tiền đã bị trừ nhưng hàng chưa được thêm vào đơn hàng.

Và tất nhiên, giao dịch còn cho bạn sự linh hoạt. Bạn có thể xây dựng các chuỗi thao tác phức tạp, kiểm soát khi nào xác nhận COMMIT hoặc huỷ ROLLBACK, thậm chí tạo các điểm khôi phục nhỏ với SAVEPOINT. Tất cả điều này làm cho việc làm việc với database không chỉ an toàn mà còn rất chủ động.

Lệnh BEGIN

Lệnh BEGIN báo cho PostgreSQL biết bạn bắt đầu một giao dịch. Sau khi chạy lệnh này, mọi thay đổi bạn thực hiện sẽ ở trạng thái "treo" cho đến khi bạn kết thúc giao dịch bằng COMMIT hoặc huỷ thay đổi bằng ROLLBACK.

Ví dụ kinh điển: giả sử bạn muốn chuyển 100 đơn vị tiền từ một tài khoản sang tài khoản khác. Bạn bắt đầu giao dịch với BEGIN:

BEGIN;
-- Bắt đầu giao dịch
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- Đã giảm số dư ở tài khoản 1
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
-- Đã tăng số dư ở tài khoản 2
Quan trọng:

Khi bạn thực hiện các lệnh trong một giao dịch, người dùng khác của database sẽ không thấy thay đổi của bạn. Chúng chỉ xuất hiện sau khi bạn chạy COMMIT.

Lệnh COMMIT

Lệnh COMMIT kết thúc giao dịch và lưu tất cả thay đổi đã thực hiện vào database. Sau khi chạy lệnh này, các thay đổi sẽ hiển thị cho mọi người dùng.

Ví dụ kết thúc giao dịch:

COMMIT;
-- Tất cả thay đổi trong giao dịch đã được lưu

Bây giờ các thay đổi số dư mà chúng ta làm ở ví dụ trên đã trở thành "vĩnh viễn". Tiền đã được chuyển thành công.

Lệnh ROLLBACK

Nếu trong quá trình thực hiện giao dịch bạn phát hiện lỗi hoặc muốn huỷ thay đổi, bạn có thể dùng lệnh ROLLBACK. Nó sẽ huỷ tất cả thao tác đã thực hiện sau lệnh BEGIN.

Giả sử trong lúc chuyển tiền bạn phát hiện tài khoản không đủ tiền. Khi đó giao dịch sẽ bị huỷ:

BEGIN;
-- Bắt đầu giao dịch
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

-- Ôi, lỗi: không đủ tiền.
ROLLBACK;
-- Tất cả thay đổi đã bị huỷ, database trở về trạng thái ban đầu

Sau lệnh ROLLBACK, không có thay đổi nào trong database được lưu lại. Điều này rất tiện để tránh lỗi.

Ví dụ đầy đủ: chuyển tiền giữa các tài khoản

Hãy gom mọi thứ lại. Đây là ví dụ đầy đủ về một giao dịch — có kiểm tra số dư, chuyển tiền và khả năng huỷ nếu có lỗi:

BEGIN;
-- Bắt đầu giao dịch

-- Kiểm tra số dư tài khoản
SELECT balance INTO current_balance FROM accounts WHERE account_id = 1;

-- Kiểm tra có đủ tiền không
IF current_balance >= 100 THEN
    -- Nếu đủ tiền, thực hiện chuyển khoản
    UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
    UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
    COMMIT;
    -- Xác nhận thay đổi
ELSE
    -- Nếu không đủ tiền, huỷ giao dịch
    ROLLBACK;
END IF;

Ví dụ này cho thấy các lệnh giao dịch phối hợp với nhau để ngăn dữ liệu bị không nhất quán.

Quan trọng

IF THEN ELSE END IF — đây là các thao tác của stored procedure, chúng ta sẽ học kỹ hơn ở các level sau nhé :P

Đặc điểm của chế độ autocommit

Trong PostgreSQL mặc định bật chế độ autocommit, nên nếu bạn chạy lệnh ngoài giao dịch rõ ràng, chúng sẽ được lưu ngay vào database. Ví dụ:

UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- Thay đổi được lưu ngay, không cần COMMIT

Nếu bạn muốn tự kiểm soát giao dịch, nên luôn dùng BEGIN để bắt đầu giao dịch một cách rõ ràng.

Bạn có thể tắt autocommit cho session hiện tại bằng lệnh:

SET AUTOCOMMIT TO OFF;

Nhớ nhé: nếu autocommit bị tắt, bạn sẽ phải kết thúc mỗi session bằng lệnh COMMIT hoặc ROLLBACK.

Các lỗi phổ biến khi làm việc với giao dịch

Quên COMMIT. Nếu bạn quên chạy COMMIT, các thay đổi của bạn sẽ chưa hoàn thành và sẽ bị mất sau khi session kết thúc.

Khoá (lock). Khi giao dịch chưa kết thúc, các tài nguyên mà nó dùng có thể bị khoá. Điều này có thể gây ra vấn đề khi nhiều người cùng truy cập dữ liệu.

ROLLBACK dư thừa. Đôi khi dev quá cẩn thận và huỷ giao dịch mà không cần thiết. Điều này dẫn đến việc tính toán lại và tăng tải cho database.

Giao dịch bị treo. Nếu bạn bắt đầu giao dịch nhưng quên kết thúc nó (không COMMIT cũng không ROLLBACK), session có thể bị treo và khoá tài nguyên của database.

Ứng dụng thực tế

Khi phỏng vấn vị trí dev hoặc DBA (quản trị database), bạn có thể bị hỏi về cách triển khai giao dịch trong PostgreSQL. Hiểu các lệnh BEGIN, COMMITROLLBACK cho thấy bạn biết cách làm việc với dữ liệu an toàn và hiệu quả.

Trong thực tế, giao dịch đặc biệt hữu ích để xây dựng các hệ thống đáng tin cậy, ví dụ như xử lý đơn hàng cho shop online hoặc tính điểm thưởng trong chương trình khách hàng thân thiết.

Bây giờ bạn đã hiểu các lệnh giao dịch cơ bản, chúng ta có thể đi tiếp và đào sâu vào các chủ đề thú vị như dùng SAVEPOINT và làm việc với các mức isolation. PostgreSQL — đúng là biển kiến thức, nên hãy chuẩn bị tinh thần nhé.

2
Nhiệm vụ
SQL SELF, mức độ, bài học
Đã khóa
Giao dịch đơn giản với commit
Giao dịch đơn giản với commit
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION