基于已有的组件参数对容器化的参数进行校验

MySQL动态参数校验方案

1. 背景与目标

原始提示词

1. 通过比较上层目录template 和 template_oracle下的cn.json、dn.json、gtm.json、lds.json 得到template 文件里 增量 或者 不一样的参数 和 其参数值。targetMysqlParams
1)cluster.json 和 system.json 明确不用考虑。

2.  按照dn、cn、gtm、lds 依次在 template-cr/param_dynamic_cr/mysql/gdbparamdynamic_data.yaml 文件中的参数curMysqlParams查看是否存在第一步的目标参数targetMysqlParams。这些参数的属性是否匹配 -- 这些参数的key,value, file_name, section 都需要匹配。
1)dn下的参数max_table_record_size、innodb_page_size 不再统计范围内
2)   对fileName/section 匹配校验。json文件第一层为文件名,第二次为section
3)如果targetMysqlParams有不存在curMysqlParams的参数,报错 -- 有mysql params 未合入容器化模板中。
4)如果targetMysqlParams都存在于curMysqlParams的参数中,正常退出。

3. 同一个组件的同名参数检测,这个动作应该在 比较后的结果集(targetMysqlParams) 上做,而不是在原始JSON上做。如果出现同名参数,属于异常场景退出。当前容器化不支持。

template/ 目录存放MySQL模式的参数模板JSON文件,template-oracle/ 存放Oracle兼容模式的参数模板。当MySQL模板相对于Oracle基线有新增或变更参数时,这些差异参数(targetMysqlParams)必须已合入容器化动态参数CR模板(param_dynamic_cr/mysql/gdbparamdynamic_data.yaml)。

目标:自动化校验 MySQL模板的增量/差异参数是否已正确合入容器化YAML模板,防止遗漏。

2. 输入文件

类型 文件路径 说明
MySQL模板JSON template/{cn,dn,gtm,lds}.json MySQL模式参数定义
Oracle模板JSON template-oracle/{cn,dn,gtm,lds}.json Oracle兼容模式参数定义(对比基线)
容器化YAML模板 template-cr/param_dynamic_cr/mysql/gdbparamdynamic_data.yaml MySQL模式容器化动态参数CR

明确排除:cluster.json 和 system.json 不参与比较。

3. JSON/YAML 结构约定

JSON 文件结构(template/ 和 template-oracle/)

{ "<fileName>": { "<section>": { "<paramKey>": "<paramValue>", ... } } }
  • 第一层 key = 配置文件名(如 proxy.ini, my.cnf, gtm.ini, lds.ini)
  • 第二层 key = section名(如 GENERAL, SQLEXEC, mysqld, general)
  • 第三层 key = 参数名,value = 参数值

YAML 文件结构(gdbparamdynamic_data.yaml)

spec:
  componentDynamicParams:
    <component>:          # dn / cn / gtm / lds
      paramDetail:
        cluster1:
          <paramKey>:
            fileName: <fileName>
            section: <section>
            paramValue: <value>

4. 算法流程

4.1 第一步:JSON 差异比较 → 得到 targetMysqlParams

目标:找出 template/ 中相对于 template-oracle/ 新增或值不同的参数。

算法:

对于每个组件 component in [dn, cn, gtm, lds]:
    1. 加载 template/{component}.json, 展平为 Map:
       key   = "fileName||section||paramKey"
       value = 字符串化的paramValue
       → templateMap

    2. 加载 template-oracle/{component}.json, 同样展平:
       key   = "fileName||section||paramKey"
       value = 字符串化的paramValue
       → oracleMap

    3. 遍历 templateMap 中每个条目:
       a) 如果 key 不在 oracleMap 中:
          → "增量参数"(MySQL模板独有), 加入 targetMysqlParams
       b) 如果 key 在 oracleMap 中,但 value 不同:
          → "差异参数", 加入 targetMysqlParams

    4. 对于 component == "dn",排除以下参数(不在统计范围内):
       - max_table_record_size
       - innodb_page_size

展平函数 flatten_json(json_obj):

def flatten_json(json_obj):
    """
    输入: {"proxy.ini": {"GENERAL": {"key1": "v1"}, "SQLEXEC": {"key2": "v2"}}}
    输出: {"proxy.ini||GENERAL||key1": "v1", "proxy.ini||SQLEXEC||key2": "v2"}
    """
    result = {}
    for file_name, sections in json_obj.items():
        for section, params in sections.items():
            for param_key, param_value in params.items():
                flat_key = f"{file_name}||{section}||{param_key}"
                result[flat_key] = str(param_value)
    return result

targetMysqlParams 数据结构:

# list of dict
targetMysqlParams = [
    {
        "component": "cn",           # 组件类型
        "fileName": "proxy.ini",     # 配置文件名
        "section": "GENERAL",        # section名
        "paramKey": "oracle_mode_switch",  # 参数名
        "paramValue": "0",           # template中的值
    },
    ...
]

预期当前结果(基于现有数据):

component fileName section paramKey paramValue
cn proxy.ini GENERAL sync_metainfo_to_vengine 0
cn proxy.ini GENERAL sql_mode_proxy default
cn proxy.ini GENERAL oracle_mode_switch 0
cn proxy.ini GENERAL tmp_function_for_future 0
cn proxy.ini GENERAL dictionary_info 0
cn proxy.ini GENERAL ignore_mysql_errno 1060,1061,1091,1507,8157
cn proxy.ini SQLEXEC autocommit 1
dn my.cnf mysqld oracle_mode_switch ALL_OFF
gtm — — — (无差异)
lds — — — (无差异)

说明:

  • gtm.json 两个目录完全一致,无差异参数。
  • lds.json 中 template-oracle 比 template 多 parse_mode 和 sql_mode,但方向是 oracle→template,不属于"template增量",故不纳入。
  • dn.json 中 max_table_record_size 虽然值不同(64K vs 128K),但被排除规则过滤。

4.2 第二步:同名参数检测(在 targetMysqlParams 结果集上)

目标:同一个组件内不允许出现同名参数(当前容器化不支持同名参数跨section区分)。

算法:

对于 targetMysqlParams 按 component 分组:
    统计每个 component 内 paramKey 的出现次数:
        如果任何 paramKey 出现次数 > 1:
            → 报错退出:"{component}组件存在同名参数{paramKey},当前容器化不支持"

注意:此检测在比较后的结果集上做,不在原始JSON上做。JSON中同fileName同section下自然不会有重复key,但跨section的同名参数可能在flat比较中出现。

4.3 第三步:YAML 匹配校验

目标:验证 targetMysqlParams 中每个参数都在容器化YAML模板中存在且属性一致。

算法:

1. 加载 param_dynamic_cr/mysql/gdbparamdynamic_data.yaml
   提取 curMysqlParams:
     对于 component in [dn, cn, gtm, lds]:
         如果 component 在 spec.componentDynamicParams 中:
             提取 paramDetail.cluster1 中的所有参数:
                 key   = paramKey
                 value = {fileName, section, paramValue}
         → curMysqlParams[component] = {paramKey: {fileName, section, paramValue}}

2. 对于 targetMysqlParams 中每个参数:
    令 component, paramKey, paramValue, fileName, section = ...

    a) 如果 component 不在 curMysqlParams 中:
         → 报错: "{component}组件未在容器化模板中找到,参数{paramKey}未合入"

    b) 如果 paramKey 不在 curMysqlParams[component] 中:
         → 报错: "{component}组件的参数{paramKey}({fileName}/{section}={paramValue})未合入容器化模板"

    c) 如果 paramKey 存在,匹配字段:
         令 yaml_entry = curMysqlParams[component][paramKey]
         校验:
           - yaml_entry.paramValue == paramValue (值匹配)
           - yaml_entry.fileName == fileName     (文件名匹配)
           - yaml_entry.section == section       (section匹配)

         如果任一不匹配:
           → 报错: "{component}组件的参数{paramKey}属性不匹配:
                   期望 fileName={fileName}, section={section}, value={paramValue}
                   实际 fileName={yaml.fileName}, section={yaml.section}, value={yaml.paramValue}"

3. 如果所有 targetMysqlParams 都匹配成功:
   → 正常退出(exit 0),输出 "所有MySQL差异参数已合入容器化模板"

匹配规则详解:

校验项 来源(JSON) 来源(YAML) 说明
paramKey 第三层key YAML的key名 参数名
paramValue 第三层value paramValue 值比较前统一转字符串
fileName JSON第一层key fileName 如 proxy.ini, my.cnf
section JSON第二层key section 如 GENERAL, SQLEXEC, mysqld

5. 边界情况处理

场景 处理方式
cluster.json / system.json 不参与比较,直接跳过
gtm.json 两目录一致 targetMysqlParams 为空,跳过后续检查
lds.json template不含oracle独有参数 反向差异不纳入,targetMysqlParams 为空
DN的 max_table_record_size 排除,不纳入 targetMysqlParams
DN的 innodb_page_size 排除(虽仅在cluster.json出现,作为安全兜底)
同组件同名参数(跨section) 在第二步检测并报错
YAML中不存在对应component 报错退出(如gtm/lds未在YAML中定义但有差异参数时)
paramValue类型差异 统一转字符串后比较(JSON中string vs int等)
YAML中component有但target无参数 不报错(YAML可能比差异集有更多参数,正常)

6. 实施文件

修改/创建以下文件:

文件 操作 说明
template-cr/checkMysqlDynamicParam.py 编写 主校验脚本(当前为空占位符)

可复用现有库:

  • template-cr/lib/print_log.py — 日志输出
  • template-cr/lib/read_write_conf.py — JSON/YAML 读写(read_json_with_comment 可处理含 // 注释的JSON)
  • template-cr/lib/config.py — 路径常量和组件名常量

7. 执行方式

cd template-cr
python checkMysqlDynamicParam.py

退出码约定:

  • 0:所有差异参数已合入,校验通过
  • 1:有参数未合入或属性不匹配,校验失败
  • 2:存在同名参数异常,校验失败

8. 校验结果预期(基于当前代码状态)

以当前 template/ 和 template-oracle/ 以及 mysql/gdbparamdynamic_data.yaml 的内容:

targetMysqlParams(第一步):

  • cn: 7个参数
  • dn: 1个参数(oracle_mode_switch)
  • gtm: 0个
  • lds: 0个

同名检测(第二步):

  • cn: 7个参数名均唯一 ✓
  • dn: 1个参数 ✓

YAML匹配(第三步):

  • cn 全部7个参数在YAML中匹配 ✓
  • dn 的 oracle_mode_switch 在YAML中匹配 ✓

预期结果:校验通过,exit 0。

9. 扩展性设计

  • YAML文件路径可通过参数指定,默认读取 param_dynamic_cr/mysql/gdbparamdynamic_data.yaml
  • 排除参数列表(max_table_record_size, innodb_page_size)应可配置
  • 后续如需支持 systemTenant 模式校验,可复用相同逻辑,切换YAML文件路径即可
  • 如果json和yaml有差异,返回所有不匹配的参数
  • 读json的函数,复用from lib.read_write_conf import read_json_with_comment
posted @ 2026-06-18 16:49  静水深耕,云停风驻  阅读(7)  评论(0)    收藏  举报