MySQL中CHARACTER SET=与CONVERT TO CHARACTER SET的区别
两类MySQL表字符集修改语句的核心区别
两个语句的核心差异和配套的ALGORITHM、LOCK参数无关,本质是作用范围、是否改动存量数据的区别:
ALTER TABLE tbl_name CHARACTER SET = charset_name只修改表级默认字符集的元数据,完全不碰存量数据
这个操作仅更新数据字典里记录的表默认字符集属性,只对后续在这张表新增的、未显式指定字符集的字符串类型列(char/varchar/text等)生效。表里已经存在的所有字符串列,会保留建列时设置/继承的字符集属性,列里存的所有存量行数据不会做任何编码转换,执行速度极快,不需要拷贝表数据。踩坑提示:不少开发者误以为执行完这个语句就完成了全表字符集切换,实际上存量列仍保留原字符集,后续跨字符集列做关联、写入数据时很容易触发乱码,排查成本很高。
ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name是真正的全表字符集转换
这个操作会完成两层修改:一是把表的默认字符集改成目标值;二是遍历表内所有已存在的字符串类型列,将列的字符集属性修改为目标值,同时把所有存量行的字符串数据按照字符集映射规则重新编码、重写存储。因为需要全表扫描、重写全量数据,所以必须拷贝整表数据,无法走原地修改逻辑。
举个直观的场景示例:假设现有表t1,默认字符集为latin1,表内已有name varchar(20)列(建列时未指定字符集,继承当时的表默认值latin1):
- 执行不带
CONVERT TO的改字符集语句将表字符集改为utf8mb4后:- 表默认字符集更新为
utf8mb4 - 已存在的
name列字符集仍为latin1,存量数据无任何改动 - 后续新增的字符串列如果不显式指定字符集,默认使用
utf8mb4
- 表默认字符集更新为
- 执行带
CONVERT TO的改字符集语句将表字符集改为utf8mb4后:- 表默认字符集更新为
utf8mb4 - 已存在的
name列字符集改为utf8mb4,存量的latin1编码数据全部转码为utf8mb4后重写存储 - 后续新增的字符串列如果不显式指定字符集,默认使用
utf8mb4
- 表默认字符集更新为
内容的提问来源于stack exchange,提问作者callum
相关产品推荐
相关产品推荐

