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

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.jsonsystem.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_modesql_mode,但方向是 oracle→template,不属于"template增量",故不纳入。
  • dn.jsonmax_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  静水深耕,云停风驻  阅读(3)  评论(0)    收藏  举报