导读:本期聚焦于芒果创作的《如何在Oracle数据库中用ShardingSphere实现分库分表?》,敬请观看详情。Oracle单表数据量越过千万级后,索引维护、分区管理和SQL优化成本会快速上升,单纯加硬件很难稳定支撑高频写入。ShardingSphere提供了数据库中间层分片能力,但把MySQL上积累的经验直接挪到Oracle,会遇到序列对象、DUAL查询和跨库聚合等差异。文章围绕ShardingSphere-JDBC在Oracle环境下的数据源配置、分片键选择、全局主键生成以及XA分布式事务落地方式展开,给出可运行的YAML和Java示例,并说明绑定表、广播表及读写分离混合使用时的边界与注意事项。同时还会分析分片规则设计中的常见错误,帮助开发者在Oracle上更平稳地完成水平拆分。

把Oracle单库的数据拆散到多个实例和多个表,并不只是改一行连接串那么简单。Oracle的序列、同义词、DUAL查询和MERGE语句都会在分片环境下暴露新问题,而ShardingSphere-JDBC通过标准JDBC入口把这些复杂性收敛在配置和规则层。下面会把重点放在Oracle特有的适配细节上,而不是重复通用分片概念。

如何在Oracle数据库中用ShardingSphere实现分库分表?

一、先确认Oracle是否真的需要分库分表

Oracle本身有RAC、分区表、物化视图和并行查询等能力,很多单库性能问题在用尽这些特性前并不需要引入分片。一般而言,如果单表行数超过5000万、写入TPS接近存储IO瓶颈、维护窗口已经无法完成索引重建或统计信息收集,再考虑水平拆分比较合适。分库分表会牺牲一部分事务一致性和SQL表达能力,不应该把它当作解决慢查询的第一选项。

如果业务确实需要拆分,还要在ShardingSphere-JDBC和ShardingSphere-Proxy之间做选择。JDBC模式以jar包形式嵌入应用,性能损耗小,适合Spring Boot这类服务直接管理数据源;Proxy模式独立部署,适合多语言客户端统一接入,但多一跳网络。对Oracle项目来说,JDBC模式通常更容易和现有连接池、XA事务管理器集成,所以后续配置以ShardingSphere-JDBC为例展开。

二、ShardingSphere分片规则与Oracle物理表准备

分片规则的核心是数据节点和算法。假设把订单表t_order按用户ID分库、按订单ID分表,两个库各放四张物理表,实际SQL会根据分片列自动路由到对应节点。下面的YAML片段配置了两个Oracle数据源,分别指向192.168.10.11和192.168.10.12上的PDB,并将t_order拆成ds0/ds1下的t_order_0到t_order_3。

spring:
  shardingsphere:
    mode:
      type: Standalone
    datasource:
      names: ds0,ds1
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: oracle.jdbc.OracleDriver
        jdbc-url: jdbc:oracle:thin:@//192.168.10.11:1521/ORCLPDB1
        username: sharding_user
        password: sharding_pwd
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: oracle.jdbc.OracleDriver
        jdbc-url: jdbc:oracle:thin:@//192.168.10.12:1521/ORCLPDB1
        username: sharding_user
        password: sharding_pwd
    rules:
      sharding:
        tables:
          t_order:
            actual-data-nodes: ds$->{0..1}.t_order_$->{0..3}
            database-strategy:
              standard:
                sharding-column: user_id
                sharding-algorithm-name: database_inline
            table-strategy:
              standard:
                sharding-column: order_id
                sharding-algorithm-name: table_inline
            key-generate-strategy:
              column: order_id
              key-generator-name: snowflake
        binding-tables:
          - t_order,t_order_item
        broadcast-tables:
          - t_config
        sharding-algorithms:
          database_inline:
            type: INLINE
            props:
              algorithm-expression: ds$->{user_id % 2}
          table_inline:
            type: INLINE
            props:
              algorithm-expression: t_order_$->{order_id % 4}
        key-generators:
          snowflake:
            type: SNOWFLAKE
            props:
              worker-id: 1
    props:
      sql-show: true

这里的actual-data-nodes使用Groovy表达式枚举逻辑库和逻辑表,database-strategy绑定user_id做库路由,table-strategy绑定order_id做表路由。binding-tables声明t_order和t_order_item在同一分片维度下路由,这样关联查询不会跨库;broadcast-tables把t_config全量同步到每个数据源,适合小表。实际建表时需要在每个Oracle实例上手工创建t_order_0到t_order_3,并确保表结构一致,ShardingSphere本身不会自动建表。

应用侧通过JdbcTemplate写入时可以省略主键列,让SNOWFLAKE生成器自动填充order_id。下面的示例插入订单时会根据user_id和生成的order_id完成双层路由,如果打开sql-show就能在日志中看到改写后的实际SQL和命中节点。

@Service
public class OrderService {

    private final JdbcTemplate jdbcTemplate;

    public OrderService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public void createOrder(Long userId, String sku, BigDecimal amount) {
        String sql = "INSERT INTO t_order(user_id, sku, amount, status) VALUES (?, ?, ?, ?)";
        jdbcTemplate.update(sql, userId, sku, amount, 0);
    }
}

三、Oracle序列、DUAL和全局主键的改造

Oracle开发习惯里常用序列加触发器生成主键,分片后如果每个库都建同名序列,多个分片会生成重复ID,最终导致跨库合并数据冲突。ShardingSphere内置的SNOWFLAKE和NANOID生成器可以绕过数据库自增机制,由中间层直接产生全局唯一值。主键列建议改为NUMBER(19)或VARCHAR2(64),避免使用Oracle的IDENTITY列或序列触发器,除非业务能接受每片独立ID再加额外标识位。

DUAL表和rownum分页查询也需要重新审视。单库下写SELECT 1 FROM DUAL没有问题,但要注意ShardingSphere对DUAL路由的处理能力有限,不建议在真实业务SQL里频繁使用DUAL做复杂表达式。分页时Oracle常用ROWNUM或OFFSET FETCH,若分片后需要跨节点聚合排序,必须先把数据拉到合并层再做排序,性能会随分片数量下降。尽量让查询带上分片键,避免触发全库扫描。

SELECT order_id, user_id, sku, amount
FROM t_order
WHERE user_id = 1001
  AND order_id = 9001;

上面这条SQL同时包含库分片键user_id和表分片键order_id,ShardingSphere会把请求精准路由到一个物理节点,不会产生跨库合并。若where条件只带order_id,就会扫描两个库中顺序查找目标表,虽然能定位到单表,但库级还是存在额外连接;若两个分片键都不带,则会把所有物理表都执行一遍后再合并,这在Oracle生产环境应尽量避免。

四、分布式事务与跨库查询的边界

分库后,一笔订单同时写t_order和t_order_item可能落在不同库,需要分布式事务保障一致性。ShardingSphere-JDBC支持XA事务,可以在Spring Boot中集成Atomikos或Narayana作为事务管理器,并通过配置XA数据源类型让ShardingSphere使用XAConnection。Oracle的JDBC驱动对XA支持成熟,但XA提交会引入两阶段锁等待,吞吐量明显低于本地事务,因此不是所有写操作都值得包在XA里。

对于关联查询,优先使用binding-tables让同维度的表提前绑定,避免t_order和t_order_item因为分片键不同而跨库join。broadcast-tables则适合配置、字典这类量少但到处都要用的小表。若业务确实需要跨节点聚合,ShardingSphere会执行多节点查询并在内存合并,支持SUM、COUNT、AVG等聚合,但复杂join、子查询和窗口函数可能受限。Oracle环境建议将跨库聚合放在夜间批处理或异步链路中,并对结果做二次校验。

上线前还应做一轮Oracle特性兼容检查:确认是否存在MERGE INTO、CONNECT BY、MODEL、闪回查询等方言语法;检查表级触发器是否被分片逻辑绕过;确认连接池中隔离级别和readOnly属性不会被分片重写;验证统计信息收集作业能否针对每个物理分片执行。只有把这些细节纳入测试清单,Oracle和ShardingSphere的组合才不至于在上线后频繁返工。

Oracle数据库ShardingSphere分库分表修改时间:2026-09-25 22:14:47

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0925/61879.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。