- Tác giả

- Name
- Nguyễn Đức Xinh
- Ngày xuất bản
- Ngày xuất bản
MySQL INFORMATION_SCHEMA: Công Cụ Không Thể Thiếu Khi Audit Database
Khi làm việc với MySQL, chúng ta thường sử dụng các câu lệnh như:
SHOW DATABASES;
SHOW TABLES;
SHOW COLUMNS FROM users;
SHOW CREATE TABLE users;
SHOW INDEX FROM users;
Những câu lệnh này rất tiện khi kiểm tra nhanh một table.
Tuy nhiên, khi cần investigate một database lớn, tìm kiếm trên hàng trăm table, kiểm tra relationship, foreign key, index, charset/collation, thống kê số lượng record hoặc audit schema, INFORMATION_SCHEMA trở thành một công cụ cực kỳ hữu ích.
INFORMATION_SCHEMA là một metadata database được MySQL cung cấp, chứa thông tin mô tả về database, table, column, index, constraint, privilege, partition...
Nói đơn giản:
Data nằm trong table của application. Metadata về những table đó nằm trong
INFORMATION_SCHEMA.
INFORMATION_SCHEMA là gì?
INFORMATION_SCHEMA là một database đặc biệt của MySQL, cung cấp thông tin siêu dữ liệu (metadata) về cấu trúc của cơ sở dữ liệu
Ví dụ:
SELECT *
FROM INFORMATION_SCHEMA.TABLES;
hoặc:
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS;
Các bảng trong INFORMATION_SCHEMA không phải là application tables thông thường.
Chúng cung cấp thông tin về cấu trúc database.
Một số bảng quan trọng:
| INFORMATION_SCHEMA | Dùng để |
|---|---|
SCHEMATA |
Database / schema |
TABLES |
Table và thông tin table |
COLUMNS |
Column / field |
STATISTICS |
Index |
KEY_COLUMN_USAGE |
Key và constraint |
TABLE_CONSTRAINTS |
Constraint |
REFERENTIAL_CONSTRAINTS |
Foreign key relationship |
VIEWS |
View |
ROUTINES |
Procedure / Function |
TRIGGERS |
Trigger |
PARTITIONS |
Partition |
Trong thực tế, 5 nhóm thường dùng nhất là:
SCHEMATA
TABLES
COLUMNS
STATISTICS
KEY_COLUMN_USAGE
Xem danh sách Database
Có thể sử dụng:
SHOW DATABASES;
Nhưng nếu muốn query metadata:
SELECT
SCHEMA_NAME
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME LIKE '%app%';
ORDER BY SCHEMA_NAME;
Xem danh sách Table
SHOW TABLES;
Nhưng với INFORMATION_SCHEMA:
SELECT
TABLE_NAME,
TABLE_TYPE,
ENGINE,
TABLE_ROWS,
DATA_LENGTH,
INDEX_LENGTH,
CREATE_TIME,
UPDATE_TIME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE()
ORDER BY TABLE_NAME;
INFORMATION_SCHEMA.TABLESchứa khá nhiều thông tin hữu ích như: table type, storage engine, estimated row count, data size, index size,..TABLE_SCHEMA = DATABASE()để chỉ lấy table của database hiện tại, bạn có thể chỉ định database cụ thể.
Lưu ý:
- Đối với InnoDB,
TABLE_ROWSthường là Approximate/ estimated row count chứ không phải absolute count. Nếu cần số lượng chính xác bạn cần dùngSELECT COUNT(*) FROM users;Tuy nhiên,COUNT(*)trên table rất lớn có thể tốn resource và thời gian.
Tìm Table có nhiều record nhất
SELECT
TABLE_NAME,
TABLE_ROWS
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE()
ORDER BY TABLE_ROWS DESC
LIMIT 20;
Rất hữu ích khi cần:
- tìm table lớn
- migration planning
- backup analysis
- performance investigation
- data cleanup
- estimate migration time
Xem Columns
Đây là một trong những tác vụ phổ biến nhất.
SELECT
TABLE_NAME,
ORDINAL_POSITION,
COLUMN_NAME,
DATA_TYPE,
COLUMN_TYPE,
IS_NULLABLE,
COLUMN_DEFAULT,
CHARACTER_SET_NAME,
COLLATION_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND COLUMN_NAME LIKE '%flag%'
ORDER BY
TABLE_NAME,
ORDINAL_POSITION;
Thêm COLUMN_NAME LIKE '%flag%' để tìm tất cả field có tên chứa flag:
Đây là kỹ thuật rất hữu ích khi:
- legacy investigation
- migration
- tìm field liên quan đến status
- tìm soft delete
- tìm flag logic
- mapping database cũ → database mới
Ngoài ra có thể tìm column theo: DATA_TYPE, CHARACTER_MAXIMUM_LENGTH
Charset và Collation
Đây là một trong những use case rất quan trọng khi làm việc với Japanese data.
SELECT
TABLE_NAME,
COLUMN_NAME,
DATA_TYPE,
CHARACTER_SET_NAME,
COLLATION_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
-- Điều kiện hữu ích để kiểm tra COLLATION
-- AND DATA_TYPE IN ('varchar', 'char', 'text') AND COLLATION_NAME <> 'utf8mb4_general_ci';
ORDER BY TABLE_NAME, ORDINAL_POSITION;
Điều này đặc biệt hữu ích khi investigate:
- Japanese text
- kana
- full-width / half-width
- dakuten / handakuten
- string comparison
- JOIN không match như mong đợi
- migration giữa database
- collation conflict
Ví dụ một JOIN có thể gặp vấn đề khi hai column sử dụng collation khác nhau:
utf8mb4_unicode_ci
VS
utf8mb4_general_ci
Kiểm tra Charset / Collation của Table
Không chỉ column, có thể kiểm tra default charset/collation của table:
SELECT
TABLE_NAME,
TABLE_COLLATION
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE()
ORDER BY TABLE_NAME;
Tìm Table có Foreign Key tới một Table
Đây là một trong những use case cực kỳ hữu ích.
Ví dụ muốn biết:
Table nào đang reference
users?
SELECT
TABLE_NAME,
COLUMN_NAME,
CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE()
AND REFERENCED_TABLE_NAME = 'users';
Kết quả có thể như:
orders user_id fk_orders_user
comments user_id fk_comments_user
user_roles user_id fk_user_roles_user
Từ đó có thể biết:
users
├── orders
├── comments
└── user_roles
Foreign Key
muốn biết:
ordersđang reference những table nào?
SELECT
TABLE_NAME,
COLUMN_NAME,
CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'orders'
AND REFERENCED_TABLE_NAME IS NOT NULL;
Ví dụ:
orders.user_id
→ users.id
orders.shop_id
→ shops.id
Table nào đang reference users?
SELECT
TABLE_NAME,
COLUMN_NAME,
CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE()
AND REFERENCED_TABLE_NAME = 'users';
Đây là query rất hữu ích khi cần biết impact/dependency trước khi thay đổi hoặc xoá một table.
Tìm toàn bộ Foreign Key Relationship
SELECT
TABLE_NAME,
COLUMN_NAME,
CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE()
AND REFERENCED_TABLE_NAME IS NOT NULL
ORDER BY
TABLE_NAME,
COLUMN_NAME;
Đây gần như là một database relationship map dạng text.
Rất hữu ích khi:
- đọc legacy database
- migration
- reverse engineering
- tìm dependency
- chuẩn bị DROP table
- phân tích impact khi thay đổi column
Primary Key
Có thể dùng để kiểm tra nhanh cấu trúc Primary Key của toàn database.
SELECT
TABLE_NAME,
COLUMN_NAME,
CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE()
AND CONSTRAINT_NAME = 'PRIMARY'
ORDER BY TABLE_NAME, ORDINAL_POSITION;
Tìm Table không có Primary Key: Đây là một query rất hữu ích trong database audit.
SELECT
t.TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES t
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
ON tc.TABLE_SCHEMA = t.TABLE_SCHEMA
AND tc.TABLE_NAME = t.TABLE_NAME
AND tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
WHERE t.TABLE_SCHEMA = DATABASE()
AND t.TABLE_TYPE = 'BASE TABLE'
AND tc.TABLE_NAME IS NULL
ORDER BY t.TABLE_NAME;
Index
Một trong những metadata quan trọng nhất là:
INFORMATION_SCHEMA.STATISTICS
Xem tất cả index hoặc index của 1 table :
SELECT
TABLE_NAME,
INDEX_NAME,
COLUMN_NAME,
NON_UNIQUE,
SEQ_IN_INDEX,
INDEX_TYPE
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
-- AND TABLE_NAME = 'orders'
---- Tìm Index chứa một Column, hữu ích khi muốn biết Field này đang được index ở những table nào?
ORDER BY
TABLE_NAME,
INDEX_NAME,
SEQ_IN_INDEX;
NON_UNIQUE = 0: nghĩa là index không cho phép duplicate values.COLUMN_NAME = 'user_id';: Ví dụ tìm tất cả index cóuser_id:
Table Size
Có thể estimate kích thước data và index:
SELECT
TABLE_NAME,
ROUND(DATA_LENGTH / 1024 / 1024, 2) AS DATA_MB,
ROUND(INDEX_LENGTH / 1024 / 1024, 2) AS INDEX_MB,
ROUND(
(DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024,
2
) AS TOTAL_MB
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE()
ORDER BY TOTAL_MB DESC
Rất hữu ích khi:
- migration
- backup
- RDS sizing
- disk planning
- performance investigation
View / Procedure / Function / Trigger
Tìm View
SELECT
TABLE_NAME,
VIEW_DEFINITION
FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_SCHEMA = DATABASE()
ORDER BY TABLE_NAME;
Stored Procedure / Function
SELECT
ROUTINE_NAME,
ROUTINE_TYPE,
DATA_TYPE
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_SCHEMA = DATABASE()
-- -- Có thể tìm riêng procedure:
-- WHERE ROUTINE_TYPE = 'PROCEDURE';
-- -- Có thể tìm riêng function:
-- WHERE ROUTINE_TYPE = 'FUNCTION';
ORDER BY ROUTINE_TYPE, ROUTINE_NAME;
Tìm Trigger
SELECT
TRIGGER_NAME,
EVENT_OBJECT_TABLE,
EVENT_MANIPULATION,
ACTION_TIMING
FROM INFORMATION_SCHEMA.TRIGGERS
WHERE TRIGGER_SCHEMA = DATABASE()
ORDER BY EVENT_OBJECT_TABLE;
Kiểm tra Partition
Nếu database sử dụng partition:
SELECT
TABLE_NAME,
PARTITION_NAME,
PARTITION_METHOD,
PARTITION_EXPRESSION,
TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA = DATABASE()
AND PARTITION_NAME IS NOT NULL
ORDER BY TABLE_NAME, PARTITION_ORDINAL_POSITION;
Phát hiện Column cùng tên nhưng khác Data Type
Đây là một kỹ thuật khá hữu ích khi audit legacy database.
Ví dụ:
SELECT
COLUMN_NAME,
DATA_TYPE,
COLUMN_TYPE,
COUNT(*) AS CNT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
GROUP BY
COLUMN_NAME,
DATA_TYPE,
COLUMN_TYPE
ORDER BY
COLUMN_NAME,
CNT DESC;
Ví dụ phát hiện:
update_userid
varchar(20)
varchar(50)
int
bigint
Điều này có thể là dấu hiệu database chưa được standardize.
Tìm Column có cùng tên nhưng khác Collation
Đặc biệt hữu ích với Japanese system:
SELECT
COLUMN_NAME,
CHARACTER_SET_NAME,
COLLATION_NAME,
COUNT(*) AS CNT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND CHARACTER_SET_NAME IS NOT NULL
GROUP BY
COLUMN_NAME,
CHARACTER_SET_NAME,
COLLATION_NAME
ORDER BY COLUMN_NAME;
Có thể phát hiện:
name
├── utf8mb4_unicode_ci
└── utf8mb4_general_ci
Đây là dấu hiệu cần review nếu những column này thường xuyên được JOIN hoặc compare với nhau.
INFORMATION_SCHEMA vs SHOW
Hai cách tiếp cận đều hữu ích.
SHOW
SHOW TABLES;
SHOW COLUMNS FROM users;
SHOW INDEX FROM users;
SHOW CREATE TABLE users;
Phù hợp khi:
- kiểm tra nhanh
- làm việc thủ công
- debug một table cụ thể
INFORMATION_SCHEMA
SELECT ...
FROM INFORMATION_SCHEMA.TABLES;
SELECT ...
FROM INFORMATION_SCHEMA.COLUMNS;
SELECT ...
FROM INFORMATION_SCHEMA.STATISTICS;
Phù hợp khi:
- cần search toàn database
- cần filter
- cần JOIN metadata
- cần report
- cần audit
- cần automation
- cần migration analysis
Kết luận
INFORMATION_SCHEMA đặc biệt hữu ích khi không biết chính xác database đang được thiết kế như thế nào.
Thay vì mở từng table và kiểm tra thủ công, chúng ta có thể query metadata để trả lời nhanh các câu hỏi như:
Có những table nào?
Table này có những column nào?
Field này xuất hiện ở những table nào?
Table nào đang reference table này?
Column này có index không?
Database đang dùng charset/collation nào?
Table nào lớn nhất?
Table nào không có Primary Key?
Đặc biệt trong legacy investigation, database migration, schema audit và performance investigation, INFORMATION_SCHEMA gần như là một trong những công cụ đầu tiên nên sử dụng.
