Câu lệnh COMMITROLLBACK trong MySQL là hai phần quan trọng của việc quản lý giao dịch (transactions). Chúng giúp kiểm soát và đảm bảo tính nhất quán của dữ liệu trong quá trình thực hiện các thao tác với cơ sở dữ liệu.

Giao dịch là một đơn vị công việc bao gồm một hoặc nhiều lệnh SQL thực hiện cùng nhau. Một giao dịch thường được sử dụng khi bạn cần đảm bảo rằng tất cả các lệnh SQL trong giao dịch phải thành công hoàn toàn hoặc bị hủy bỏ nếu có lỗi xảy ra.

1. Câu lệnh COMMIT

  • COMMIT được sử dụng để xác nhận và lưu các thay đổi dữ liệu thực hiện trong quá trình giao dịch.
  • Sau khi thực hiện COMMIT, mọi thay đổi trong giao dịch sẽ được lưu vĩnh viễn vào cơ sở dữ liệu và không thể hoàn tác.

Cú pháp:

COMMIT;

Ví dụ cơ bản:

Giả sử bạn có bảng employees và bạn muốn thêm một nhân viên mới. Bạn có thể thực hiện thêm dữ liệu trong một giao dịch, và sau đó sử dụng COMMIT để lưu lại thay đổi.

START TRANSACTION;

INSERT INTO employees (id, name, department)
VALUES (1, 'John Doe', 'HR');

COMMIT;

Sau khi câu lệnh COMMIT được thực thi, bản ghi mới sẽ được lưu vĩnh viễn trong bảng employees.

Ví dụ nâng cao:

Giả sử bạn thực hiện nhiều thay đổi cùng lúc trên nhiều bảng và muốn chắc chắn rằng tất cả các thay đổi này đều được lưu lại nếu không có lỗi nào xảy ra.

START TRANSACTION;

UPDATE employees SET department = 'IT' WHERE id = 1;
UPDATE salaries SET amount = 5000 WHERE employee_id = 1;

COMMIT;

Nếu cả hai câu lệnh UPDATE thành công, giao dịch sẽ được xác nhận và lưu bằng câu lệnh COMMIT. Nếu xảy ra lỗi trước khi COMMIT, bạn có thể sử dụng ROLLBACK để hoàn tác toàn bộ thay đổi.


2. Câu lệnh ROLLBACK

  • ROLLBACK được sử dụng để hoàn tác tất cả các thay đổi đã thực hiện trong một giao dịch nếu xảy ra lỗi hoặc bạn muốn quay lại trạng thái trước khi bắt đầu giao dịch.
  • Sau khi thực hiện ROLLBACK, mọi thay đổi dữ liệu trong giao dịch sẽ không được lưu vào cơ sở dữ liệu.

Cú pháp:

ROLLBACK;

Ví dụ cơ bản:

Giả sử bạn bắt đầu một giao dịch để thêm một nhân viên mới, nhưng sau đó bạn nhận ra rằng có lỗi trong quá trình thêm dữ liệu, và bạn không muốn lưu các thay đổi này.

START TRANSACTION;

INSERT INTO employees (id, name, department)
VALUES (2, 'Jane Smith', 'Finance');

-- Nhận thấy có lỗi, bạn thực hiện ROLLBACK
ROLLBACK;

Khi ROLLBACK được thực hiện, bản ghi của Jane Smith sẽ không được thêm vào bảng employees.

Ví dụ nâng cao:

Bạn có thể sử dụng ROLLBACK trong trường hợp nhiều câu lệnh SQL được thực hiện, và bạn muốn đảm bảo rằng chỉ khi mọi câu lệnh thành công thì thay đổi mới được lưu. Nếu một trong những câu lệnh không thành công, bạn có thể quay lại trạng thái ban đầu của cơ sở dữ liệu.

START TRANSACTION;

UPDATE employees SET department = 'Marketing' WHERE id = 2;
UPDATE salaries SET amount = 6000 WHERE employee_id = 2;

-- Giả sử lệnh thứ hai thất bại, bạn có thể hoàn tác cả hai thay đổi
ROLLBACK;

Khi ROLLBACK được gọi, mọi thay đổi từ lệnh UPDATE đầu tiên cũng sẽ bị hủy bỏ, và cơ sở dữ liệu sẽ quay trở lại trạng thái trước khi giao dịch bắt đầu.


3. Sử dụng SAVEPOINT trong giao dịch

MySQL cũng hỗ trợ SAVEPOINT giúp bạn đánh dấu một điểm trong giao dịch để có thể ROLLBACK tới điểm đó thay vì hoàn tác toàn bộ giao dịch.

Cú pháp:

  • Tạo SAVEPOINT:
SAVEPOINT savepoint_name;

  • Quay lại SAVEPOINT:
ROLLBACK TO SAVEPOINT savepoint_name;

  • Xóa SAVEPOINT:
RELEASE SAVEPOINT savepoint_name;

Ví dụ:

Giả sử bạn thực hiện nhiều thay đổi trong một giao dịch và tạo một điểm SAVEPOINT giữa quá trình.

START TRANSACTION;

UPDATE employees SET department = 'Sales' WHERE id = 1;
SAVEPOINT sp1;

UPDATE employees SET department = 'HR' WHERE id = 2;

-- Nếu có lỗi xảy ra, bạn có thể quay lại savepoint sp1
ROLLBACK TO SAVEPOINT sp1;

-- Xác nhận thay đổi cho giao dịch sau rollback
COMMIT;

Trong ví dụ này, nếu có lỗi trong lệnh UPDATE thứ hai, bạn có thể quay lại SAVEPOINT sp1 để hoàn tác chỉ lệnh đó mà không cần hoàn tác lệnh UPDATE đầu tiên.


4. Chế độ tự động COMMIT

Trong MySQL, theo mặc định, chế độ tự động COMMIT (AUTOCOMMIT) được bật, nghĩa là mỗi câu lệnh SQL được thực hiện sẽ được lưu ngay lập tức. Để làm việc với giao dịch, bạn cần tắt chế độ AUTOCOMMIT.

Tắt AUTOCOMMIT:

SET AUTOCOMMIT = 0;

Bật lại AUTOCOMMIT:

SET AUTOCOMMIT = 1;


5. Kết hợp COMMIT, ROLLBACK, và SAVEPOINT trong các giao dịch phức tạp

Khi làm việc với các hệ thống lớn, đặc biệt là khi có nhiều giao dịch và dữ liệu phức tạp, việc kết hợp COMMIT, ROLLBACK, và SAVEPOINT rất hữu ích để đảm bảo tính nhất quán và khả năng kiểm soát khi thực hiện các thao tác trên cơ sở dữ liệu.

Ví dụ nâng cao:

START TRANSACTION;

INSERT INTO orders (order_id, customer_id, order_date) VALUES (101, 1, NOW());
SAVEPOINT sp_order;

INSERT INTO order_items (order_id, product_id, quantity) VALUES (101, 200, 2);
SAVEPOINT sp_items;

UPDATE inventory SET stock = stock - 2 WHERE product_id = 200;

-- Nếu xảy ra lỗi, bạn có thể quay lại điểm lưu lệnh order_items
ROLLBACK TO SAVEPOINT sp_items;

-- Xác nhận thay đổi sau khi rollback
COMMIT;

Trong ví dụ này, nếu có lỗi xảy ra trong lệnh UPDATE cho inventory, bạn có thể ROLLBACK trở lại SAVEPOINT sp_items, hủy bỏ thay đổi trong order_items nhưng vẫn giữ nguyên các thay đổi trong orders.


Kết luận:

  • COMMIT: Xác nhận và lưu lại các thay đổi trong giao dịch.
  • ROLLBACK: Hoàn tác tất cả các thay đổi đã thực hiện trong giao dịch.
  • SAVEPOINT: Tạo điểm lưu trong giao dịch để có thể quay lại mà không cần hoàn tác toàn bộ giao dịch.

Việc sử dụng giao dịch, COMMIT, và ROLLBACK rất quan trọng trong các ứng dụng thực tế, giúp bảo đảm dữ liệu không bị hỏng hoặc mất mát khi xảy ra lỗi.

Dưới đây là một số ví dụ nâng cao về việc sử dụng COMMIT, ROLLBACK, và SAVEPOINT trong MySQL, bao gồm các trường hợp phức tạp hơn và các tình huống thực tế khi làm việc với giao dịch (transactions).


6. Giao dịch với SAVEPOINT trong nhiều bảng

Trong các ứng dụng phức tạp, bạn có thể thao tác trên nhiều bảng cùng lúc. Sử dụng SAVEPOINT giúp bạn kiểm soát linh hoạt việc quay lại một điểm nhất định trong giao dịch nếu có lỗi xảy ra.

Ví dụ:

Giả sử bạn đang quản lý một hệ thống đặt hàng. Khi khách hàng đặt hàng, bạn cần cập nhật nhiều bảng bao gồm orders, order_items, và inventory. Nếu có bất kỳ lỗi nào xảy ra, bạn muốn quay lại trạng thái trước đó mà không cần hủy bỏ toàn bộ giao dịch.

START TRANSACTION;

-- Bước 1: Thêm đơn hàng mới
INSERT INTO orders (order_id, customer_id, order_date)
VALUES (102, 3, NOW());
SAVEPOINT sp_order;

-- Bước 2: Thêm các mục vào đơn hàng
INSERT INTO order_items (order_id, product_id, quantity)
VALUES (102, 201, 3);
SAVEPOINT sp_items;

-- Bước 3: Cập nhật tồn kho sản phẩm
UPDATE inventory
SET stock = stock - 3
WHERE product_id = 201;

-- Giả sử có lỗi xảy ra ở đây: không đủ tồn kho
-- Bạn có thể quay lại điểm savepoint sp_items
ROLLBACK TO SAVEPOINT sp_items;

-- Tiếp tục cập nhật các mục đơn hàng khác
INSERT INTO order_items (order_id, product_id, quantity)
VALUES (102, 202, 2);

-- Xác nhận toàn bộ giao dịch
COMMIT;

Giải thích:

  • Sau khi thêm đơn hàng mới và cập nhật các mục đơn hàng, một lỗi xảy ra khi cập nhật tồn kho.
  • Chúng ta sử dụng ROLLBACK TO SAVEPOINT sp_items để quay lại trước khi cập nhật tồn kho nhưng giữ lại đơn hàng đã thêm.
  • Tiếp tục thêm các mục khác vào đơn hàng và sau đó COMMIT để lưu lại tất cả các thay đổi.

7. Sử dụng ROLLBACK có điều kiện trong giao dịch phức tạp

Trong nhiều tình huống, bạn có thể sử dụng IF để kiểm tra điều kiện và quyết định xem có nên COMMIT hay ROLLBACK giao dịch. Điều này đặc biệt hữu ích khi bạn thực hiện nhiều thao tác trên các bảng khác nhau và muốn chắc chắn rằng tất cả thao tác đều thành công.

Ví dụ:

Giả sử bạn đang quản lý tài khoản ngân hàng và thực hiện giao dịch chuyển tiền giữa các tài khoản. Bạn muốn đảm bảo rằng cả hai tài khoản đều được cập nhật thành công trước khi xác nhận giao dịch.

 

START TRANSACTION;
-- Trừ tiền từ tài khoản gửi
UPDATE accounts
SET balance = balance - 500
WHERE account_id = 101;
-- Kiểm tra nếu số dư âm
IF (SELECT balance FROM accounts WHERE account_id = 101) < 0 THEN
    ROLLBACK;
ELSE
    -- Thêm tiền vào tài khoản nhận
    UPDATE accounts
    SET balance = balance + 500
    WHERE account_id = 202;
    -- Kiểm tra nếu giao dịch thành công
    IF ROW_COUNT() > 0 THEN
        COMMIT;
    ELSE
        ROLLBACK;
    END IF;
END IF;

Giải thích:

  • Tài khoản gửi (account_id = 101) được cập nhật trừ 500 đơn vị.
  • Sử dụng điều kiện để kiểm tra nếu số dư của tài khoản gửi bị âm, thì thực hiện ROLLBACK.
  • Nếu mọi thứ ổn, cập nhật tài khoản nhận và kiểm tra nếu lệnh UPDATE thành công, sau đó COMMIT hoặc ROLLBACK tùy tình huống.

8. Kết hợp SAVEPOINTROLLBACK trong vòng lặp

Trong các tình huống phức tạp, bạn có thể cần thực hiện nhiều giao dịch lặp lại và đảm bảo rằng nếu có lỗi trong bất kỳ bước nào, hệ thống có thể quay lại một điểm an toàn và tiếp tục thực hiện các thao tác còn lại.

Ví dụ:

Giả sử bạn có một danh sách các giao dịch thanh toán và muốn xử lý từng giao dịch một. Nếu một giao dịch thất bại, bạn sẽ hoàn tác giao dịch đó nhưng tiếp tục xử lý các giao dịch khác.

START TRANSACTION;

-- Giả sử bạn có 5 giao dịch thanh toán cần xử lý
SET @transactions = (SELECT id FROM payments WHERE status = 'pending' LIMIT 5);

-- Duyệt qua từng giao dịch
FOR EACH @transaction IN @transactions DO
    SAVEPOINT sp_payment;

    -- Cập nhật trạng thái thanh toán
    UPDATE payments
    SET status = 'processed'
    WHERE id = @transaction;

    -- Giả sử có lỗi trong quá trình cập nhật
    IF ROW_COUNT() = 0 THEN
        -- Nếu có lỗi, quay lại điểm SAVEPOINT
        ROLLBACK TO SAVEPOINT sp_payment;
    END IF;

    -- Tiếp tục xử lý các giao dịch khác
END FOR;

-- Cuối cùng xác nhận toàn bộ giao dịch
COMMIT;

Giải thích:

  • Một danh sách các giao dịch đang chờ xử lý được duyệt qua.
  • Mỗi lần xử lý một giao dịch, một SAVEPOINT được tạo.
  • Nếu có bất kỳ lỗi nào xảy ra (sử dụng IF để kiểm tra), giao dịch đó sẽ được hoàn tác bằng cách quay lại SAVEPOINT.
  • Sau khi xử lý hết các giao dịch, COMMIT toàn bộ thay đổi.

9. Sử dụng SAVEPOINT để xử lý từng phần của giao dịch lớn

Trong những hệ thống giao dịch lớn, đôi khi bạn cần xử lý một phần dữ liệu và tạo các điểm dừng trong quá trình. Sử dụng SAVEPOINT cho phép bạn xử lý từng phần dữ liệu mà không làm hỏng toàn bộ giao dịch nếu một phần nhỏ gặp lỗi.

Ví dụ:

Giả sử bạn đang nhập dữ liệu từ một file CSV lớn vào bảng products. Bạn muốn chia nhỏ giao dịch thành từng phần và xử lý từng phần một. Nếu có lỗi trong một phần, bạn hoàn tác chỉ phần đó và tiếp tục xử lý phần khác.

START TRANSACTION;

-- Chúng ta giả định mỗi lần nhập 100 dòng từ file CSV
LOAD DATA INFILE '/path/to/csvfile.csv'
INTO TABLE products
FIELDS TERMINATED BY ','
LINES TERMINATED BY 'n'
(@row)
SET 
    product_id = @row[1],
    product_name = @row[2],
    price = @row[3];

-- Tạo một savepoint để kiểm soát từng phần
SAVEPOINT sp_batch1;

-- Giả sử có lỗi xảy ra khi nhập 100 dòng đầu tiên
IF ERROR THEN
    ROLLBACK TO SAVEPOINT sp_batch1;
END IF;

-- Tiếp tục xử lý các phần khác của file CSV

-- Cuối cùng, commit toàn bộ giao dịch
COMMIT;

Giải thích:

  • Dữ liệu từ file CSV được nhập vào bảng products.
  • SAVEPOINT sp_batch1 được tạo sau khi nhập mỗi lô 100 dòng.
  • Nếu có lỗi trong quá trình nhập dữ liệu, bạn có thể ROLLBACK TO SAVEPOINT để hoàn tác các thay đổi của phần dữ liệu đó mà không cần hủy bỏ toàn bộ giao dịch.

10. Sử dụng SAVEPOINTROLLBACK để cập nhật bảng có quan hệ phức tạp

Khi làm việc với các bảng có quan hệ phức tạp, bạn có thể sử dụng SAVEPOINT để quản lý các cập nhật liên quan đến nhiều bảng một cách linh hoạt hơn.

Ví dụ:

Giả sử bạn đang quản lý một hệ thống quản lý nhân sự và muốn cập nhật thông tin nhân viên cùng với bảng departments có quan hệ khóa ngoại với employees. Nếu có lỗi khi cập nhật departments, bạn cần hoàn tác các thay đổi nhưng vẫn giữ nguyên các thay đổi của bảng employees.

START TRANSACTION;

-- Bước 1: Cập nhật thông tin nhân viên
UPDATE employees
SET name = 'Alice', department_id = 5
WHERE employee_id = 123;
SAVEPOINT sp_employee;

-- Bước 2: Cập nhật bảng departments
UPDATE departments
SET department_name = 'IT'
WHERE department_id = 5;

-- Nếu cập nhật departments gặp lỗi, quay lại điểm savepoint sp_employee
IF ERROR THEN
    ROLLBACK TO SAVEPOINT sp_employee;
END IF;

-- Nếu không có lỗi, commit toàn bộ giao dịch
COMMIT;

Giải thích:

  • Cập nhật bảng employees và tạo một SAVEPOINT.
  • Sau đó cập nhật bảng departments. Nếu có lỗi xảy ra trong quá trình cập nhật bảng departments, bạn có thể hoàn tác chỉ phần thay đổi liên quan đến bảng departments mà không ảnh hưởng đến thay đổi đã thực hiện trong bảng employees.

Dưới đây là thêm các ví dụ nâng cao về việc sử dụng COMMIT, ROLLBACK, và SAVEPOINT trong MySQL, mở rộng thêm các tình huống thực tế và phức tạp:

11. Quản lý Giao dịch Phân Tán (Distributed Transactions)

Khi làm việc với nhiều cơ sở dữ liệu hoặc nhiều bảng trong các cơ sở dữ liệu khác nhau, bạn có thể cần quản lý giao dịch phân tán. SAVEPOINT giúp bạn xử lý các phần của giao dịch trên các cơ sở dữ liệu khác nhau và đảm bảo tính nhất quán của dữ liệu.

Ví dụ:

Giả sử bạn đang thực hiện giao dịch trên hai cơ sở dữ liệu khác nhau, một là cơ sở dữ liệu chính (main_db) và một là cơ sở dữ liệu phụ (secondary_db). Bạn muốn đảm bảo rằng cả hai cơ sở dữ liệu đều được cập nhật hoặc không thay đổi nếu có lỗi xảy ra.

-- Bắt đầu giao dịch với cơ sở dữ liệu chính
USE main_db;
START TRANSACTION;

-- Thực hiện thay đổi trên cơ sở dữ liệu chính
INSERT INTO orders (order_id, customer_id, order_date)
VALUES (103, 4, NOW());
SAVEPOINT sp_main;

-- Thực hiện thay đổi trên cơ sở dữ liệu phụ
USE secondary_db;
START TRANSACTION;

-- Thực hiện thay đổi trên cơ sở dữ liệu phụ
INSERT INTO inventory (product_id, quantity)
VALUES (303, 10);
SAVEPOINT sp_secondary;

-- Nếu có lỗi trong cơ sở dữ liệu phụ
IF ERROR THEN
    -- Hoàn tác thay đổi trên cơ sở dữ liệu phụ
    ROLLBACK TO SAVEPOINT sp_secondary;
    -- Hoàn tác thay đổi trên cơ sở dữ liệu chính
    USE main_db;
    ROLLBACK TO SAVEPOINT sp_main;
ELSE
    -- Xác nhận thay đổi trên cơ sở dữ liệu phụ
    COMMIT;
    -- Xác nhận thay đổi trên cơ sở dữ liệu chính
    USE main_db;
    COMMIT;
END IF;

Giải thích:

  • Bắt đầu giao dịch trên cơ sở dữ liệu chính và phụ.
  • Thực hiện thay đổi trên cả hai cơ sở dữ liệu và tạo các SAVEPOINT cho từng cơ sở dữ liệu.
  • Nếu có lỗi xảy ra, hoàn tác thay đổi trên cả hai cơ sở dữ liệu và quay lại trạng thái an toàn. Nếu không có lỗi, xác nhận thay đổi trên cả hai cơ sở dữ liệu.

12. Giao dịch với Lệnh LOCK

Trong các tình huống phức tạp, bạn có thể cần phải sử dụng LOCK để khóa các bảng hoặc hàng trong khi thực hiện giao dịch. Điều này giúp bạn tránh xung đột giữa các giao dịch đồng thời.

Ví dụ:

Giả sử bạn cần thực hiện một giao dịch chuyển tiền giữa các tài khoản và muốn đảm bảo rằng không có giao dịch khác can thiệp vào các tài khoản trong suốt quá trình này.

START TRANSACTION;

-- Khóa bảng accounts để ngăn các giao dịch khác truy cập đồng thời
LOCK TABLES accounts WRITE;

-- Trừ tiền từ tài khoản gửi
UPDATE accounts
SET balance = balance - 500
WHERE account_id = 101;

-- Thêm tiền vào tài khoản nhận
UPDATE accounts
SET balance = balance + 500
WHERE account_id = 202;

-- Xác nhận thay đổi và mở khóa bảng
COMMIT;
UNLOCK TABLES;

Giải thích:

  • Sử dụng LOCK TABLES để khóa bảng accounts trong khi thực hiện giao dịch, đảm bảo rằng không có giao dịch khác can thiệp vào.
  • Thực hiện các cập nhật và sau đó COMMIT để lưu lại thay đổi.
  • Sử dụng UNLOCK TABLES để mở khóa bảng sau khi giao dịch hoàn tất.

13. Xử lý Lỗi Ngoại Lệ (Exception Handling) với Giao Dịch

Trong các ứng dụng phức tạp, việc xử lý lỗi ngoại lệ giúp bạn quản lý giao dịch một cách an toàn và hiệu quả. Điều này có thể được thực hiện trong các ứng dụng client-side hoặc server-side.

Ví dụ (client-side):

<?php
// Kết nối đến cơ sở dữ liệu
$mysqli = new mysqli("localhost", "user", "password", "database");

// Bắt đầu giao dịch
$mysqli->begin_transaction();

try {
    // Thực hiện một số câu lệnh SQL
    $mysqli->query("UPDATE accounts SET balance = balance - 500 WHERE account_id = 101");
    $mysqli->query("UPDATE accounts SET balance = balance + 500 WHERE account_id = 202");

    // Xác nhận giao dịch
    $mysqli->commit();
} catch (Exception $e) {
    // Nếu có lỗi, hoàn tác giao dịch
    $mysqli->rollback();
    echo "Error: " . $e->getMessage();
}

// Đóng kết nối
$mysqli->close();
?>

Giải thích:

  • Sử dụng phương pháp begin_transaction() để bắt đầu giao dịch.
  • Thực hiện các câu lệnh SQL và commit giao dịch nếu mọi thứ thành công.
  • Nếu có lỗi xảy ra, thực hiện rollback để hoàn tác các thay đổi và xử lý ngoại lệ.

14. Giao dịch với Ghi Đè (Overriding) và SAVEPOINT

Khi làm việc với các giao dịch phức tạp, bạn có thể cần ghi đè các SAVEPOINT trong một giao dịch dài.

Ví dụ:

Giả sử bạn đang thực hiện giao dịch dài với nhiều bước và muốn ghi đè các SAVEPOINT sau mỗi bước quan trọng.

START TRANSACTION;

-- Bước 1: Cập nhật thông tin khách hàng
UPDATE customers
SET address = '123 New St'
WHERE customer_id = 10;
SAVEPOINT sp_step1;

-- Bước 2: Thực hiện thay đổi liên quan đến đơn hàng
UPDATE orders
SET status = 'shipped'
WHERE order_id = 1001;
SAVEPOINT sp_step2;

-- Nếu có lỗi ở bước 2, quay lại bước 1
IF ERROR THEN
    ROLLBACK TO SAVEPOINT sp_step1;
ELSE
    -- Nếu không có lỗi, tiếp tục và ghi đè savepoint
    SAVEPOINT sp_step3;
    -- Tiếp tục với các bước tiếp theo
    -- ...

    -- Xác nhận toàn bộ giao dịch
    COMMIT;
END IF;

Giải thích:

  • Sử dụng SAVEPOINT sau mỗi bước quan trọng trong giao dịch dài.
  • Nếu có lỗi ở một bước, quay lại SAVEPOINT gần nhất và ghi đè các điểm lưu trước đó.
  • Nếu không có lỗi, tiếp tục với các bước tiếp theo và xác nhận toàn bộ giao dịch.

15. Quản lý Giao Dịch với ROLLBACKSAVEPOINT trong Vòng Lặp

Khi làm việc với các giao dịch lặp lại, việc sử dụng SAVEPOINT giúp quản lý các thay đổi nhỏ mà không cần hoàn tác toàn bộ giao dịch nếu một phần nhỏ thất bại.

Ví dụ:

Giả sử bạn đang xử lý một loạt các bản ghi và muốn đảm bảo rằng nếu một bản ghi thất bại, các bản ghi khác vẫn được xử lý.

START TRANSACTION;

-- Lặp qua từng bản ghi và thực hiện các thay đổi
FOR EACH record IN records DO
    SAVEPOINT sp_record;

    -- Cập nhật bản ghi
    UPDATE my_table
    SET field = 'value'
    WHERE id = record.id;

    -- Nếu có lỗi, hoàn tác thay đổi cho bản ghi đó
    IF ERROR THEN
        ROLLBACK TO SAVEPOINT sp_record;
    END IF;

    -- Tiếp tục với bản ghi tiếp theo
END FOR;

-- Xác nhận toàn bộ giao dịch nếu tất cả các bản ghi được xử lý thành công
COMMIT;

Giải thích:

  • Trong vòng lặp, sử dụng SAVEPOINT để đánh dấu mỗi bản ghi.
  • Nếu có lỗi xảy ra trong khi cập nhật một bản ghi, hoàn tác chỉ thay đổi của bản ghi đó mà không ảnh hưởng đến các bản ghi khác.
  • Xác nhận giao dịch nếu tất cả các bản ghi được xử lý thành công.

Những ví dụ trên mở rộng các tình huống phức tạp hơn mà bạn có thể gặp phải khi làm việc với giao dịch trong MySQL. Việc hiểu rõ cách sử dụng COMMIT, ROLLBACK, và SAVEPOINT giúp bạn quản lý dữ liệu một cách hiệu quả và đảm bảo tính nhất quán trong các ứng dụng thực tế.