Con trỏ và phân vùng trong mysql

  • Cursor (con trỏ) giúp duyệt từng dòng dữ liệu để xử lý phức tạp trong thủ tục và giao dịch.
  • Partition (phân vùng) giúp quản lý dữ liệu lớn hiệu quả trong lưu trữ và tối ưu hệ thống.

Ta cùng đi từng phần một, kèm ví dụ nghiệp vụ Kho bạc Nhà nước, để cô có thể đưa trực tiếp vào giáo trình.

🧭 I. CON TRỎ (CURSOR) TRONG MYSQL

1️⃣ Khái niệm

  • Cursor (con trỏ)vùng nhớ tạm trong thủ tục (stored procedure) cho phép duyệt từng bản ghi trong tập kết quả của một truy vấn.
  • Cursor giống như “ngón tay chỉ” qua từng dòng của bảng dữ liệu để xử lý logic phức tạp mà lệnh SQL đơn không thực hiện được.

👉 MySQL chỉ hỗ trợ read-only, non-scrollable cursor (nghĩa là đọc tuần tự, không quay lại dòng trước).

2️⃣ Cấu trúc hoạt động của Cursor

Một con trỏ trong MySQL có 4 bước chính:

Bước Câu lệnh Chức năng
1 DECLARE cursor_name CURSOR FOR SELECT... Khai báo con trỏ
2 OPEN cursor_name; Mở con trỏ
3 FETCH cursor_name INTO variable_list; Lấy từng dòng dữ liệu
4 CLOSE cursor_name; Đóng con trỏ, giải phóng bộ nhớ

3️⃣ Ví dụ minh hoạ: Cập nhật phí giao dịch hàng loạt

Tình huống thực tế Kho bạc:
Hàng ngày cần duyệt qua từng giao dịch để tính và cập nhật phí dựa theo loại nghiệp vụ (chuyển khoản, thu ngân sách, hoàn thu…).

🔧 Tạo dữ liệu mẫu:

CREATE TABLE giao_dich (
  id INT AUTO_INCREMENT PRIMARY KEY,
  so_tk VARCHAR(20),
  loai_giao_dich VARCHAR(50),
  so_tien DECIMAL(18,2),
  phi DECIMAL(18,2)
);

INSERT INTO giao_dich (so_tk, loai_giao_dich, so_tien)
VALUES 
('KB001','Chuyển khoản',2000000),
('KB002','Thu ngân sách',10000000),
('KB003','Rút tiền',3000000);

🧮 Thủ tục sử dụng CURSOR:

DELIMITER //
CREATE PROCEDURE cap_nhat_phi()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE p_id INT;
  DECLARE p_loai VARCHAR(50);
  DECLARE p_so_tien DECIMAL(18,2);
  DECLARE cur CURSOR FOR 
      SELECT id, loai_giao_dich, so_tien FROM giao_dich;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur;
  read_loop: LOOP
    FETCH cur INTO p_id, p_loai, p_so_tien;
    IF done THEN
      LEAVE read_loop;
    END IF;

    IF p_loai = 'Chuyển khoản' THEN
      UPDATE giao_dich SET phi = p_so_tien * 0.005 WHERE id = p_id;
    ELSEIF p_loai = 'Rút tiền' THEN
      UPDATE giao_dich SET phi = p_so_tien * 0.01 WHERE id = p_id;
    ELSE
      UPDATE giao_dich SET phi = 0 WHERE id = p_id;
    END IF;
  END LOOP;
  CLOSE cur;
END //
DELIMITER ;

Gọi thử:

CALL cap_nhat_phi();
SELECT * FROM giao_dich;

👉 Ứng dụng thực tế:

  • Duyệt kiểm tra chênh lệch dữ liệu.
  • Ghi log lỗi dòng theo điều kiện đặc biệt.
  • Tự động hiệu chỉnh dữ liệu định kỳ.

🧩 II. PHÂN VÙNG (PARTITION) TRONG MYSQL

1️⃣ Khái niệm

  • Partition (phân vùng)cách chia logic một bảng lớn thành nhiều phần nhỏ hơn (partition), nhưng MySQL vẫn coi đó là một bảng duy nhất khi truy vấn.
  • Mỗi partition có thể lưu ở file vật lý khác nhau, giúp:
    • Truy xuất nhanh hơn (đọc ít dữ liệu hơn),
    • Quản lý dễ hơn (xóa dữ liệu cũ theo phân vùng),
    • Tối ưu backup và phục hồi.

2️⃣ Các kiểu phân vùng trong MySQL

Kiểu Partition Mô tả Ví dụ
RANGE Chia theo giá trị trong khoảng Theo năm, tháng, ngày
LIST Chia theo danh sách cụ thể Mã chi nhánh
HASH Chia ngẫu nhiên theo công thức Sử dụng cho cân tải
KEY Dựa vào khóa chính Dành cho dữ liệu có ID lớn

3️⃣ Ví dụ nghiệp vụ: Phân vùng bảng giao dịch theo năm

Tình huống thực tế Kho bạc:
Dữ liệu giao dịch từ năm 2019 đến 2025, cần chia partition theo năm để tối ưu truy vấn và backup.

🔧 Tạo bảng phân vùng:

CREATE TABLE giao_dich_partition (
  id INT AUTO_INCREMENT PRIMARY KEY,
  so_tk VARCHAR(20),
  loai_giao_dich VARCHAR(50),
  so_tien DECIMAL(18,2),
  ngay_giao_dich DATE
)
PARTITION BY RANGE (YEAR(ngay_giao_dich)) (
  PARTITION p2019 VALUES LESS THAN (2020),
  PARTITION p2020 VALUES LESS THAN (2021),
  PARTITION p2021 VALUES LESS THAN (2022),
  PARTITION p2022 VALUES LESS THAN (2023),
  PARTITION p2023 VALUES LESS THAN (2024),
  PARTITION pmax VALUES LESS THAN MAXVALUE
);

👉 Khi chèn dữ liệu:

INSERT INTO giao_dich_partition VALUES
(NULL,'KB001','Chuyển khoản',2000000,'2022-05-10'),
(NULL,'KB002','Rút tiền',1500000,'2024-01-12');

MySQL tự động phân vào partition p2022p2023.

4️⃣ Kiểm tra thông tin phân vùng

SELECT TABLE_NAME, PARTITION_NAME, TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME = 'giao_dich_partition';

5️⃣ Xóa hoặc thêm partition mới

ALTER TABLE giao_dich_partition
ADD PARTITION (PARTITION p2025 VALUES LESS THAN (2026));

6️⃣ Ứng dụng thực tế

Nhiệm vụ Kho bạc Cách áp dụng Partition
Dữ liệu giao dịch theo năm RANGE (YEAR)
Dữ liệu theo đơn vị địa phương (KBNN) LIST (Mã chi nhánh)
Cân bằng tải truy vấn HASH (ID giao dịch)
Xóa dữ liệu cũ nhanh chóng ALTER TABLE ... DROP PARTITION

🧮 III. KẾT HỢP CON TRỎ + PHÂN VÙNG TRONG QUẢN TRỊ

Cô có thể kết hợp cả hai kỹ thuật để tự động quản lý dữ liệu lớn.
Ví dụ: Mỗi tháng, con trỏ duyệt qua từng partition → tính tổng, lưu log, xoá dữ liệu cũ.

⚙️ Mẫu thủ tục quản lý phân vùng:

DELIMITER //
CREATE PROCEDURE tong_hop_theo_partition()
BEGIN
  DECLARE done INT DEFAULT 0;
  DECLARE p_name VARCHAR(64);
  DECLARE cur CURSOR FOR
    SELECT PARTITION_NAME FROM INFORMATION_SCHEMA.PARTITIONS
    WHERE TABLE_NAME = 'giao_dich_partition' AND PARTITION_NAME IS NOT NULL;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

  OPEN cur;
  read_loop: LOOP
    FETCH cur INTO p_name;
    IF done THEN LEAVE read_loop; END IF;
    SET @sql = CONCAT('SELECT "', p_name, '" AS partition_name, SUM(so_tien) AS tong_tien FROM giao_dich_partition PARTITION(', p_name, ');');
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
  END LOOP;
  CLOSE cur;
END //
DELIMITER ;

👉 Gọi:

CALL tong_hop_theo_partition();

→ Cho phép tự động thống kê dữ liệu từng năm.

🧭 IV. TÓM TẮT & SO SÁNH

Nội dung Cursor Partition
Mục đích Xử lý từng dòng dữ liệu tuần tự Quản lý dữ liệu lớn theo nhóm
Phạm vi Trong thủ tục (procedural) Trong cấu trúc bảng (structural)
Ứng dụng Tự động hoá cập nhật, kiểm tra logic Tối ưu lưu trữ, backup, phân tích
Hạn chế Tốc độ chậm nếu duyệt lớn Không hỗ trợ FULLTEXT, FK phức tạp
Công cụ hỗ trợ Stored Procedure Workbench, CLI, Information_Schema

🏦 Ví dụ nghiệp vụ tổng hợp Kho bạc Nhà nước

Tình huống:
Mỗi quý, hệ thống Kho bạc phải:

  • Duyệt qua từng partition theo năm.
  • Tính tổng số giao dịch, tổng phí, và lưu kết quả.
  • Ghi log bằng trigger khi phát hiện phân vùng vượt 2 triệu bản ghi.

→ Kết hợp:

  • Cursor để duyệt phân vùng,
  • Procedure để tổng hợp dữ liệu,
  • Trigger để giám sát,
  • Transaction để rollback nếu lỗi tính toán.

 

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *