Logo
最大兼容模式

最大兼容模式 #

在真实业务系统中,单表操作占据了大量请求。对于这类 SQL,如果已经能够确定访问的数据源,并且不需要改写执行,SphereEx-DBPlusEngine 可以在识别 SQL 关键信息后直接透传执行,减少完整解析、绑定、改写和结果归并带来的额外开销,从而提升性能。

最大兼容模式(Max Compatibility)首先用于提升单表操作的执行性能,其次用于提升 SQL 兼容性。对于包含数据库方言函数、特殊语法、复杂查询结构或历史兼容写法的 SQL,只要底层数据库能够正确执行,且当前规则允许,SphereEx-DBPlusEngine 会尽量保留原始 SQL 下发。

概述 #

最大兼容模式主要解决两类问题:

  1. 提升单表操作性能。

对于不需要复杂规则改写的单表 SQL,SphereEx-DBPlusEngine 在识别 SQL 类型、表名、参数等关键信息后,可以尽量透传到底层数据库执行,减少普通路径中的完整解析、绑定、SQL 改写和结果处理成本。

  1. 提升 SQL 兼容性。

对于底层数据库支持、但 SphereEx-DBPlusEngine 不需要完整理解的方言语法、函数或复杂表达式,可以在规则允许时尽量由底层数据库直接处理,降低业务 SQL 改造成本。

最大兼容模式不是一项独立的数据治理规则,它会和单表、读写分离、数据库发现、数据加密、数据脱敏、数据防篡改、异构双写等规则共同工作。SQL 是否能够使用最大兼容模式,取决于 SQL 本身以及当前启用规则是否允许。

基本概念 #

逻辑 SQL #

逻辑 SQL 是业务应用发送给 SphereEx-DBPlusEngine 的 SQL。

对于符合条件的单表 SQL,原始逻辑 SQL 可以尽量透传到底层数据库执行。

轻量识别 #

最大兼容模式不会完整理解 SQL 的所有语法细节,而是优先识别执行所需的关键信息,例如:

  • SQL 类型,例如 SELECTINSERTUPDATEDELETE
  • SQL 涉及的业务表;
  • 参数占位符数量;
  • 是否包含加锁查询;
  • 是否包含 LAST_INSERT_ID
  • 是否包含 sequence.nextval

这些信息用于快速判断 SQL 是否满足最大兼容模式的执行条件:例如是否属于可处理的 SQL 类型、是否能够定位到目标表和数据源、参数数量是否匹配、是否存在加锁查询、序列等会影响路由或规则判断的特征。只有当 SQL 本身和当前启用的规则都允许时,SphereEx-DBPlusEngine 才会尽量跳过普通路径中的完整解析、绑定和改写,将原始 SQL 下发到底层数据库执行。

内核执行 #

如果 SQL 或规则不适合最大兼容模式,SphereEx-DBPlusEngine 会回到内核执行流程,继续完成 SQL 解析、绑定、路由、改写和结果处理。

单表元数据懒加载 #

单表元数据懒加载是指:没有在启动阶段预加载的单表,在运行时被 SQL 访问并确实需要表结构时,再按需加载表元数据。

最大兼容模式本身不等于“永不加载元数据”。当 SQL 回退内核执行路径,或者 SQL 需要展开 *表别名.* 时,仍可能读取表结构,加载表元数据。

适用场景 #

最大兼容模式适用于以下场景:

  • 单表 SELECTINSERTUPDATEDELETE 操作,不需要加密、脱敏、防篡改等列级改写;
  • SQL 可以确定访问的数据源,适合尽量透传执行;
  • SQL 能够被底层数据库直接执行;
  • SQL 能够识别出业务表;
  • 当前启用的规则都允许该 SQL 使用最大兼容模式;
  • 读写分离、数据库发现等场景中,需要根据 SQL 类型和少量特征完成判断;
  • SQL 中包含底层数据库支持的方言语法、函数或复杂表达式,希望尽量由底层数据库处理。

常见示例:

-- 假设 t_profile 是单表
SELECT id, user_id, note FROM t_profile WHERE user_id = ?

使用限制 #

以下场景通常不会使用最大兼容路径,或者会回退到普通内核执行路径:

  • SQL 命中加密表,需要对逻辑列、密文列、明文列或辅助查询列进行改写;
  • SQL 命中脱敏表,需要对返回结果进行脱敏处理;
  • SQL 命中防篡改表,需要维护或校验摘要列;
  • 异构双写中的 INSERT
  • 异构双写中包含 SQL 翻译参数列;
  • 异构双写中包含 sequence.nextval
  • SQL 无法识别出明确的业务表;
  • SQL 需要依赖完整语义处理才能保证规则正确生效。

使用最大兼容模式时,不应把它理解为绕过数据治理规则。只要 SQL 命中需要规则改写或规则保护的表,SphereEx-DBPlusEngine 仍会优先保证规则正确性。

原理介绍 #

最大兼容模式的核心原则是:在规则可判断、路由可确定、数据治理语义不受影响的前提下,优先让符合条件的单表 SQL 透传执行,并尽量将复杂 SQL 交给底层数据库处理。

执行流程 #

最大兼容模式处理 SQL 的过程如下:

  1. 应用发送 SQL 到 SphereEx-DBPlusEngine。
  2. SphereEx-DBPlusEngine 判断是否开启最大兼容模式。
  3. 识别 SQL 类型、表名、参数占位符和特殊执行特征。
  4. 检查当前启用的规则是否允许该 SQL 使用最大兼容模式。
  5. 如果允许,则尽量保留原始 SQL 完成路由和执行。
  6. 如果不允许,则回到普通内核 SQL 处理路径。

与各类规则的关系 #

不同规则对最大兼容模式的要求不同:

规则行为说明
单表一般允许使用最大兼容模式。符合条件时,可以尽量透传执行以减少普通路径开销。
读写分离一般允许使用最大兼容模式,根据 SQL 类型、加锁查询等信息判断主库或从库。
数据库发现一般允许使用最大兼容模式,由高可用规则决定可用数据源。
数据加密SQL 未命中加密表时可以使用;命中加密表时通常需要普通路径进行列改写。
数据脱敏SQL 未命中脱敏表时可以使用;命中脱敏表时通常需要普通路径进行结果处理。
数据防篡改SQL 未命中防篡改表时可以使用;命中防篡改表时通常需要普通路径维护摘要列。
异构双写普通查询可以使用;INSERT、包含 SQL 翻译参数列或包含序列时不使用。

操作指南 #

开启最大兼容模式 #

在 YAML 配置中设置:

props:
  max-compatibility-enabled: true

也可以通过 DistSQL 动态开启:

SET DIST VARIABLE max_compatibility_enabled = true;

开启后可以通过以下 DistSQL 查看配置:

SHOW DIST VARIABLE WHERE name = max_compatibility_enabled;

配置单表 #

如果希望启动时加载并管理全部单表,可以配置:

rules:
  - !SINGLE
    tables:
      - "*.*"

| 配置方式 | 行为 | | tables: "*.*" | 启动阶段扫描并加载全部单表。 |

如果期望启动阶段不加载所有单表元数据,仅在运行阶段需要时才加载,则不需要配置单表规则,或者单表规则里只配置您需要启动阶段加载的单表。

配置示例 #

单表查询 #

适用于单数据源或单表查询,希望减少普通解析和改写开销,并尽量保留原始 SQL 的场景。

databaseName: demo_db

dataSources:
  ds_0:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbcUrl: jdbc:mysql://127.0.0.1:3306/demo_ds?serverTimezone=UTC&useSSL=false
    username: root
    password: root

rules:
  - !SINGLE
    defaultDataSource: ds_0

props:
  sql-show: true
  max-compatibility-enabled: true

业务 SQL 示例:

SELECT id, user_id, note FROM t_profile WHERE user_id = ?

该 SQL 不包含 *,也没有命中需要列级改写的规则,适合通过最大兼容模式透传执行,以减少普通路径开销。

单表与加密表混合查询 #

以下示例中,t_profile 为单表,t_user 为加密规则表。

databaseName: demo_db

dataSources:
  ds_0:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbcUrl: jdbc:mysql://127.0.0.1:3306/demo_ds?serverTimezone=UTC&useSSL=false
    username: root
    password: root

rules:
  - !SINGLE
    defaultDataSource: ds_0
  - !ENCRYPT
    encryptors:
      aes_encryptor:
        type: AES
        props:
          aes-key-value: 123456abc
    tables:
      t_user:
        columns:
          user_name:
            plain:
              name: user_name
              queryWithPlain: true
            cipher:
              name: user_name_cipher
              encryptorName: aes_encryptor

props:
  sql-show: true
  max-compatibility-enabled: true

业务 SQL 示例:

SELECT p.*, u.user_name
FROM t_profile p
JOIN t_user u ON p.user_id = u.user_id
WHERE p.user_id = ?

该 SQL 命中加密表 t_user,通常需要普通路径处理加密列。如果同时包含 p.*,普通路径需要读取 t_profile 的列信息,因此可能触发单表元数据懒加载。 如果单纯的单表查询,不涉及加密表,即使当前配置包含加密规则,也可以走最大兼容模式。

异构双写查询 #

异构双写场景下,普通查询可以使用最大兼容模式。例如:

SELECT id, user_id, note FROM t_dw_seq_single WHERE id = ?

如果 SQL 包含序列,例如 Oracle 中常见的 sequence.nextval

SELECT order_seq.nextval AS generated_id, p.* FROM t_dw_seq_single p WHERE p.id = ?

需要注意:

  • 包含序列时,异构双写不会使用最大兼容路径;
  • 上例中真正容易触发单表元数据加载的是 p.*,因为普通路径需要展开表的所有列;
  • 不能简单理解为“有序列就一定加载元数据”。

如果希望减少运行时元数据加载,建议显式写出业务列:

SELECT order_seq.nextval AS generated_id, p.id, p.user_id, p.note
FROM t_dw_seq_single p
WHERE p.id = ?

常见问题 #

开启最大兼容模式后,SQL 一定原样下发吗? #

不一定。只有 SQL 类型、涉及表和当前规则都满足条件时,才会尽量原样下发。 命中加密表、脱敏表、防篡改表,或异构双写中的 INSERT、序列等场景时,可能回到内核执行路径。

最大兼容模式会绕过加密、脱敏或防篡改规则吗? #

不会。最大兼容模式会先判断当前规则是否允许该 SQL 使用最大兼容路径。只要 SQL 需要规则改写或规则保护,就会回到普通内核执行路径处理。

如何减少运行时单表元数据加载? #

  • 不配置 !SINGLE tables: "*.*",避免把启动预加载误判为运行时加载;
  • 在高频 SQL 中避免使用 *表别名.*
  • 对需要稳定低延迟的单表,使用 !SINGLE tables 显式加载;
  • 通过 sql-show 观察 actual SQL 是否出现列展开。