直接查 information_schema 是唯一可靠方式,因其提供标准化元数据视图,字段语义明确、顺序可控、结果稳定,避免 show create table 因客户端、版本等差异导致误报。

直接查 INFORMATION_SCHEMA 是唯一可靠方式
用 SHOW CREATE TABLE 输出做字符串 diff 会误报——MySQL 客户端、版本、连接会话都可能导致字段顺序、空格、引号风格不同,但结构实际一致。INFORMATION_SCHEMA 提供标准化元数据视图,字段语义明确、顺序可控、结果稳定。
关键点:
- 必须显式指定
charset='utf8mb4',否则中文注释(COLUMN_COMMENT、TABLE_COMMENT)大概率乱码 -
autocommit=False更安全,避免查询触发隐式事务干扰其他操作 - 库名/表名必须用参数化查询传入,不能字符串拼接,否则下划线或破折号会引发 SQL 注入或语法错误
-
COLUMN_DEFAULT字段要特别处理:MySQL 返回NULL(Python 中为None)表示“无默认值”,而字符串'NULL'才是显式设为 NULL 的默认值,二者语义完全相反
比对必须拆解到字段级,不能靠集合运算
用 set(source_structure) - set(target_structure) 这类做法会丢掉类型、默认值、注释等关键差异,仅能发现字段增删,无法识别 INT → BIGINT 或 NOT NULL → NULL 这类危险变更。
正确做法是把每张表的列转成以 COLUMN_NAME 为 key 的字典,逐字段比对:
-
DATA_TYPE和CHARACTER_MAXIMUM_LENGTH要联合判断(比如VARCHAR(255)和VARCHAR(500)) -
IS_NULLABLE值为'YES'/'NO',不是布尔值 -
COLUMN_COMMENT为空字符串''和None含义不同:前者是显式清空注释,后者是未设置 - 主键、索引、外键不在此表中,需额外查
KEY_COLUMN_USAGE和STATISTICS表
权限和托管环境常导致脚本静默失败
最常见的失败不是代码写错,而是连不上 INFORMATION_SCHEMA —— 它不是普通数据库,而是一个只读元数据视图,某些托管 MySQL(如阿里云 RDS、腾讯云 CDB)默认禁用对其的 SELECT 权限,且不会报错,只会返回空结果集。
排查建议:
- 先手动执行
SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS LIMIT 1,确认能查到数据 - 检查账号是否被授予
SELECT权限在INFORMATION_SCHEMA上(不是仅在目标库) - 若用 mysql-connector-python,加
raise_on_warnings=True参数,避免警告被吞掉 - 连接后立刻查
SELECT DATABASE(), VERSION(),验证连接上下文是否符合预期
输出格式必须兼顾人眼可读与机器可解析
纯文本日志或控制台 print 不适合后续接入 CI/CD 或告警系统。JSON 是最务实的选择,每个字段差异至少包含:
-
"column_name"、"status": "added" | "dropped" | "modified" -
"type_mismatch": true、"nullability_changed": true、"default_changed": true等布尔标记,而不是笼统写“类型不一致” -
"old_default"和"new_default"要区分null(PythonNone)和"NULL"(字符串) - 务必带时间戳、源库 host/port/dbname、目标库 host/port/dbname,否则回溯时根本不知道比的是哪两个快照
真正容易被忽略的是:字段顺序变更本身不改变兼容性,但会影响某些 ORM 映射或导出逻辑;而 ORDINAL_POSITION 差异常被跳过比对,却可能暴露建表脚本不一致的深层问题。











