在创建 MySQL 8.0 实例时,如何一次性指定字符集、排序规则与 SQL 模式?
解读
国内面试官问这道题,表面看是“怎么填参数”,实则考察三层能力:
- 是否理解 Cloud SQL 与自建 MySQL 在初始化阶段的差异——Cloud SQL 不允许直接修改 my.cnf,必须通过 官方暴露的 flag 列表 完成;
- 是否熟悉 MySQL 8.0 默认行为(utf8mb4、utf8mb4_0900_ai_ci、STRICT_TRANS_TABLES 等)与 国内合规要求(GB18030、大小写敏感、NO_ZERO_DATE 等)之间的冲突;
- 是否具备 “一次交付、后续免运维” 的云原生思维:用 Terraform + 变量文件 把字符集、排序规则、SQL 模式、备份窗口、高可用策略一并固化,避免人工在控制台“点选”带来的漂移风险。
如果仅回答“在创建页下拉框选一下”,会被视为“只用过控制台”的初级水平;必须给出 gcloud 命令 + Terraform 代码 + 可灰度验证的方案,才能拿到高分。
知识点
-
Cloud SQL 初始化三要素
- 字符集:由
character_set_server控制,MySQL 8.0 默认 utf8mb4,国内业务若需 GB18030 必须显式指定。 - 排序规则:由
collation_server控制,决定大小写敏感、重音规则;国内常见utf8mb4_0900_as_cs(敏感)或utf8mb4_general_ci(不敏感)。 - SQL 模式:由
sql_mode控制,Cloud SQL 用 逗号分隔的字符串 传入,顺序无关,但 NO_AUTO_VALUE_ON_ZERO、STRICT_TRANS_TABLES、NO_ZERO_DATE、NO_ENGINE_SUBSTITUTION 是金融级标配。
- 字符集:由
-
Cloud SQL 的“允许 Flag”白名单
并非所有 my.cnf 参数都能改,必须通过gcloud sql flags list --database-version=MYSQL_8_0确认;若参数不在白名单,只能提 支持工单 或改用 Cloud SQL Enterprise Plus(可开自定义参数组)。 -
一次性注入的三种姿势
- gcloud CLI:
--database-flags支持键值对,一次最多 20 个,用^(Windows)或\(Linux)换行续行; - Terraform:
google_sql_database_instance的settings.database_flags块,可变量化,方便多环境复用; - Cloud SQL Admin API:
instances.insert的settings.databaseFlags[]数组,适合 CI/CD 自动触发。
- gcloud CLI:
-
国内网络合规细节
若通过 Private Service Connect 内网接入,需提前在 vpc-peering 中放通servicenetworking.googleapis.com的 /24 前缀,否则创建实例会卡在“分配 IP”阶段,被误判为“参数无效”。
答案
步骤一:确认白名单
gcloud sql flags list --database-version=MYSQL_8_0 \
--filter="name=(character_set_server,collation_server,sql_mode)" \
--format="value(name)"
预期输出三行,证明均可改。
步骤二:gcloud 一次性创建(Linux 续行)
gcloud sql instances create prod-mysql80 \
--database-version=MYSQL_8_0 \
--tier=db-n1-standard-2 \
--region=asia-east2 \
--root-password='${ROOT_PW}' \
--database-flags \
character_set_server=utf8mb4,\
collation_server=utf8mb4_0900_as_cs,\
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY'
注意:
sql_mode的值用 单引号包裹,内部逗号 不能有空格,否则会被拆成多个 flag 导致报错;- 若需 GB18030,把
character_set_server=gb18030和collation_server=gb18030_chinese_ci替换即可,但需先确认业务驱动支持该字符集。
步骤三:Terraform 模板(production/variables.tf)
variable "sql_mode" {
default = "STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY"
}
variable "character_set" { default = "utf8mb4" }
variable "collation" { default = "utf8mb4_0900_as_cs" }
production/main.tf
resource "google_sql_database_instance" "mysql80" {
name = "prod-mysql80"
database_version = "MYSQL_8_0"
region = "asia-east2"
settings {
tier = "db-n1-standard-2"
database_flags {
name = "character_set_server"
value = var.character_set
}
database_flags {
name = "collation_server"
value = var.collation
}
database_flags {
name = "sql_mode"
value = var.sql_mode
}
backup_configuration {
enabled = true
start_time = "03:00"
point_in_time_recovery_enabled = true
}
ip_configuration {
ipv4_enabled = false
private_network = google_compute_network.vpc.id
}
}
}
执行
terraform plan -out=tfplan
terraform apply tfplan
即可 一次性 完成实例创建、参数注入、备份策略与内网接入,后续 零人工点选。
验证
gcloud sql connect prod-mysql80 --user=root <<EOF
SHOW VARIABLES LIKE 'character_set_server';
SHOW VARIABLES LIKE 'collation_server';
SELECT @@sql_mode;
EOF
三行输出与预期完全一致,即交付完成。
拓展思考
-
灰度变更
若实例已上线,修改sql_mode会 立即重启示例,导致主库闪断;国内金融场景可先用 只读实例 验证新 SQL 模式是否击穿业务,再采用 蓝绿发布:- 新建 Cloud SQL 蓝实例(带新 flag);
- 用 Database Migration Service 做 最小停机迁移(<30 s);
- 切换 Private DNS A 记录,实现业务无感。
-
参数漂移审计
国内等保 2.0 要求 “配置基线可核查”,可在 Cloud Asset Inventory 中创建 策略监控:gcloud asset feeds create mysql80-drift \ --asset-types="sqladmin.googleapis.com/Instance" \ --content-type="resource" \ --feed-output-config="pubsubTopic=projects/${PROJECT}/topics/sql-drift"一旦有人控制台手动改 flag,Pub/Sub 触发 Cloud Function 自动回滚 Terraform 状态,确保 “代码即真相”。
-
Serverless 场景
若业务使用 Cloud Run 全托管模式,建议把上述 Terraform 模块封装成 Google Cloud Blueprints,通过 Cloud Deploy 流水线 一键拉起 “Cloud Run + Cloud SQL + Secret Manager” 组合,字符集、SQL 模式、连接池大小 全部变量化,让开发同学 只改 yaml 不碰控制台,符合国内 “研发不碰生产” 的合规红线。