Cấu hình SQL Mode nghiêm ngặt trong MySQL

Khi làm việc với MySQL, sql_mode là một tham số thường bị bỏ qua, mặc định là rỗng. Trong chế độ này, hệ thống cho phép một số thao tác không hợp lệ như chèn dữ liệu sai kiểu, không có kiểm tra đầy đủ. Do đó, trong môi trường sản xuất và ngay cả khi phát triển/thử nghiệm, nên cấu hình sql_mode ở chế độ nghiêm ngặt để phát hiện sớm lỗi và đảm bảo tính toàn vẹn dữ liệu.

Các vấn đề được kiểm soát nhờ thiết lập sql_mode đúng cách

  • Đảm bảo dữ liệu được kiểm tra chặt chẽ theo yêu cầu nghiệp vụ.
  • Khi di chuyển ứng dụng giữa các hệ quản trị CSDL như Oracle và MySQL, dùng sql_mode phù hợp giúp giảm đáng kể sự khác biệt về cú pháp.
  • Tăng tính tương thích khi di chuyển dữ liệu giữa các phiên bản hoặc hệ thống khác nhau.

Các chế độ thường dùng trong sql_mode

  • ONLY_FULL_GROUP_BY
    Yêu cầu tất cả các cột trong mệnh đề SELECT đều phải có mặt trong GROUP BY. Nếu không, truy vấn bị từ chối.
  • NO_AUTO_VALUE_ON_ZERO
    Khi chèn giá trị 0 vào cột AUTO_INCREMENT, mặc định sẽ tạo giá trị tiếp theo. Chế độ này cho phép giá trị 0 được chèn chính xác nếu cần.
  • STRICT_TRANS_TABLES
    Áp dụng kiểm tra nghiêm ngặt với các bảng kiểu MyISAM, InnoDB...: nếu có dữ liệu không hợp lệ trong thao tác INSERT hoặc UPDATE, thao tác sẽ bị hủy ngay.
  • NO_ZERO_IN_DATE
    Ngăn chèn ngày/tháng bằng 0 (ví dụ: 2023-00-15).
  • NO_ZERO_DATE
    Không cho phép chèn ngày tháng không hợp lệ như '0000-00-00'. Thay vì cảnh báo, hệ thống sẽ trả về lỗi.
  • ERROR_FOR_DIVISION_BY_ZERO
    Khi thực hiện phép chia cho 0 trong INSERT/UPDATE, trả về lỗi thay vì NULL nếu không có chế độ này.
  • NO_AUTO_CREATE_USER
    Không cho phép tạo người dùng không có mật khẩu khi dùng lệnh GRANT.
  • NO_ENGINE_SUBSTITUTION
    Nếu storage engine yêu cầu bị vô hiệu hóa hoặc không khả dụng, MySQL sẽ ném lỗi thay vì substitutes bằng engine mặc định.
  • PIPES_AS_CONCAT
    Biến toán tử || thành toán tử nối chuỗi (giống như Oracle và hàm CONCAT()), không còn là phép toán OR.
  • ANSI_QUOTES
    Kích hoạt chế độ mysql không cho phép dùng dấu nháy kép cho chuỗi literal (bắt buộc dùng dấu nháy đơn), thay vào đó dấu nháy kép dùng cho tên định danh (identifiers).

Để compat với ứng dụng gốc từ hệ thống Oracle, bạn có thể xác định sql_mode như sau trong file cấu hình:

[mysqld]
sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,PIPES_AS_CONCAT,ANSI_QUOTES,NO_ENGINE_SUBSTITUTION'

So sánh chế độ mặc định giữa các phiên bản

  • MySQL 5.6: Giá trị mặc định rỗng → chế độ "lỏng lẻo", cho phép dữ liệu sai bị cắt ghép tự động.
  • MySQL 5.7+: Mặc định là STRICT_TRANS_TABLES → chế độ nghiêm ngặt, bắt buộc lỗi phải được báo rõ.

Ví dụ: trong chế độ lỏng lẻo, nếu chèn chuỗi '1234567890abc' vào cột CHAR(10), MySQL sẽ tự động cắt ngắn thành '1234567890' và không báo lỗi — điều này rất nguy hiểm ở môi trường thực tế. Khi dùng chế độ nghiêm ngặt, thao tác trên sẽ bị từ chối.

Lưu ý khi nâng cấp lên chế độ nghiêm ngặt

Nếu NO_ZERO_DATE được bật, dữ liệu có chứa ngày giờ mặc định như '0000-00-00 00:00:00' hoặc '0000-00-00' trên các cột kiểu TIMESTAMP/DATE sẽ bị từ chối và gây lỗi cập nhật. Cần kiểm tra kỹ trước khi áp dụng.

Cách áp dụng cấu hình sql_mode linh hoạt

  1. Chạy ngay tức thì (phiên hiện tại):
    SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
    Lưu ý: Mất hiệu lực sau khi ngắt kết nối.
  2. Áp dụng toàn cục (hiệu lực trong phiên làm việc hiện tại của server):
    SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
    Mất hiệu lực khi restart MySQL.
  3. Thiết lập vĩnh viễn qua file cấu hình:
    Thêm dòng dưới vào file my.cnf hoặc my.ini:
    [mysqld]
    sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
    Sau đó restartMySQL để áp dụng.

Trong môi trường production, phương án kết hợp giữa (2) và (3) là lựa chọn tối ưu: đảm bảo áp dụng ngay mà vẫn duy trì hiệu lực lâu dài.

Thẻ: mysql sql-mode strict-mode database-configuration sql-validation

Đăng vào ngày 24 tháng 6 lúc 23:07