ALTER TABLE MODIFY COLUMN 可能丢失数据,取决于新旧类型兼容性:缩容、降精度或跨大类转换易导致截断、报错或边界值;扩容安全;改名须用 CHANGE COLUMN;含 TEXT/BLOB 需先设 ROW_FORMAT=DYNAMIC;大表修改建议用 pt-online-schema-change。

ALTER TABLE MODIFY COLUMN 会丢失数据吗
直接用 MODIFY COLUMN 改字段类型,是否丢数据,取决于新旧类型的兼容性。比如从 VARCHAR(255) 缩成 VARCHAR(10),超长值会被截断;从 INT 改成 TINYINT,超出 -128~127 范围的值会变成边界值或报错(取决于 SQL mode)。不是所有修改都安全,尤其涉及长度缩减、精度降低或类型跨大类(如字符串→数字)时。
- 改宽不丢数据(
VARCHAR(10) → VARCHAR(200)) - 改窄大概率丢数据(
TEXT → VARCHAR(100),超长部分被截) -
DECIMAL(10,2) → DECIMAL(5,2):整数位不够时,插入会报错或四舍五入(看版本和 sql_mode) - 必须先查当前数据分布:
SELECT MIN(col), MAX(col), COUNT(*) FROM tbl WHERE col IS NOT NULL;
用 CHANGE COLUMN 还是 MODIFY COLUMN
CHANGE COLUMN 和 MODIFY COLUMN 都能改类型,但语义不同:CHANGE 必须写两次字段名(旧名 新名),哪怕不改名也得重复;MODIFY 只写一次,更简洁。两者在纯类型变更时行为一致,但 CHANGE 允许同时改名+改类型,MODIFY 不允许改名。
- 只改类型、不改名 → 优先用
MODIFY COLUMN(少写、不易错) - 要改名又改类型 → 必须用
CHANGE COLUMN old_name new_name new_type - 误写
CHANGE col col INT是合法的,但多打一个col容易手滑漏掉,引发语法错误
修改 TEXT/BLOB 字段类型要加 ROW_FORMAT=DYNAMIC
MySQL 5.7+ 中,如果表用的是 COMPACT 或 REDUNDANT 行格式,直接对含 TEXT 或 BLOB 的字段执行 MODIFY,可能报错:ERROR 1118 (42000): Row size too large。这是因为老行格式对单行总长有限制,而 TEXT 实际存储在行外,但元信息仍占空间。
一鱼CMS一鱼CMS(APHPCMS)轻量级10秒快速建表一键CRUD生成企业网站,采用PearAdmin和Layui2.9.16。(原YiYuAdmin升级进化版本),超简单模板制作。CMS特色字段预设:表字段预先配置好,新增模型时直接选择生成表。模型字段:可导出,导入,设为预设字段,修改和删除时自动更新表字段。模型字段:结合Layui表可设置查询,表头属性,表头模板。模型字段:可设置表单类型,
- 先确认当前行格式:
SHOW TABLE STATUS LIKE 'tbl_name';看Row_format列 - 若为
Compact,建议先改行格式:ALTER TABLE tbl_name ROW_FORMAT=DYNAMIC; - 再执行字段修改,否则可能卡住或失败
-
DYNAMIC是 InnoDB 默认(8.0+),但老表迁移后未必自动更新
在线修改字段类型真的“在线”吗
MySQL 5.6+ 支持部分 ALTER TABLE 操作的“在线”能力(即不锁表),但改字段类型是否真正不锁,要看具体操作和版本。例如 MODIFY COLUMN 改 VARCHAR 长度,在 5.7+ 中如果是扩大且字符集不变,通常可 ALGORITHM=INPLACE;但缩容、改类型(如 VARCHAR → TEXT)、或涉及全文索引时,大概率触发 COPY 算法,锁表 + 全量复制。
- 加
ALGORITHM=INPLACE, LOCK=NONE强制指定,但 MySQL 会校验是否支持,不支持则报错 - 生产环境务必先在从库或测试库验证耗时与锁表现:
SHOW PROCESSLIST;观察状态 - 大表(千万级+)改类型前,用
pt-online-schema-change更稳妥
SELECT ... LIMIT 5 看真实数据样例,还有那个容易被忽略的 sql_mode 设置——它会影响截断、零日期等行为的报错/警告策略。









