
SEATA Sharding-JDBC 分库分表分布式事务完整实战原理场景代码优缺点一、业务背景在海量数据高并发微服务场景中单库单表会出现数据量大、查询慢、写入瓶颈、索引失效等问题行业普遍采用Sharding-JDBC做分库分表、读写分离解决存储与性能瓶颈。但分库分表后会引入新的核心问题跨分片分布式事务。Sharding-JDBC 仅负责 SQL 路由、分片规则、多数据源管理不具备分布式事务一致性能力。当一次业务操作涉及多个分库、多个分片表写入/更新时本地事务只能保证单库一致性必然出现部分分片成功、部分分片失败的数据脏写问题。因此生产环境必须引入SEATA AT 模式结合 Sharding-JDBC解决分库分表场景下的跨分片分布式事务一致性问题实现分表扩容事务可控的高可用架构。二、核心适用场景SEATA Sharding-JDBC 组合方案并非所有项目都需要使用精准适配以下业务场景海量数据业务订单、支付、流水、用户行为数据单表数据量突破千万/亿级需要水平分表扩容高并发写入场景秒杀、下单、流水记录单库写入压力过大需要分库分担IO压力跨分片事务场景一次业务操作需要同时修改多个分片数据必须保证多分片同时成功/同时回滚高性能、低侵入诉求不想使用TCC硬编码事务希望通过框架自动实现分布式事务读写分离分库分表混合架构多数据源、多分片复杂架构下的数据一致性保障。不适用场景数据量小、并发低、单库完全够用的项目过度架构增加维护成本金融级强一致性核心账务优先Sharding-TCC模式。三、整合核心原理3.1 组件分工Sharding-JDBCJDBC层中间件负责拦截SQL、根据分片算法路由至对应分库分表、管理多数据源、合并查询结果SEATA AT模式负责跨分片分布式事务管控一阶段记录undo镜像、二阶段统一提交/回滚保证多分片数据最终一致。3.2 关键整合机制核心难点原生 SEATA 会通过DataSourceProxy代理数据源实现事务管控Sharding-JDBC 内部拥有自己的数据源分片代理逻辑。两者直接整合会出现数据源代理冲突、事务失效。标准解决方案SEATA 嵌套代理 Sharding 数据源执行链路业务SQL → SEATA数据源代理 → Sharding-JDBC分片路由 → 真实分库数据源 → 执行SQL并生成undo镜像3.3 分片事务执行流程TM开启全局事务业务方法添加GlobalTransactional生成全局XIDSQL分片路由Sharding-JDBC 根据分片键路由到一个或多个分片库表一阶段预提交所有分片分支执行SQLSEATA 生成每个分片的undo_log镜像本地事务提交、释放锁二阶段统一处理全局成功批量删除所有分片undo_log事务正常结束全局异常根据各分片undo镜像反向回滚所有分片数据保证多分片数据一致。四、方案优缺点分析4.1 核心优点零代码侵入基于SEATA AT模式无需手动编写Try/Confirm/Cancel仅注解开启事务适配快速开发解决分片事务痛点彻底解决跨库、跨分片部分成功、部分失败的数据一致性问题高性能高并发一阶段提交、短事务、无长锁相比XA、TCC性能更高适配海量分片场景架构解耦分片扩容由Sharding管控事务一致性由SEATA管控职责清晰、扩展灵活兼容主流架构完美适配SpringCloud、MyBatis、MyBatis-Plus生态。4.2 现存缺点与生产局限存在脏读风险AT模式一阶段释锁高并发跨分片场景存在短暂脏读、数据覆盖风险极端场景会触发镜像校验失败、事务重试卡死不支持强隔离级别无法做到串行化隔离金融核心账务场景不适用整合配置复杂多数据源、分片规则、事务分组配置不当极易出现事务不生效、代理冲突大事务风险放大跨多分片大事务一旦超时会出现多分片事务状态割裂修复成本极高undo日志膨胀分片越多事务日志越多增加数据库存储与清理压力。五、入门实战SEATA Sharding-JDBC 完整整合案例5.0 整合核心常用注解及适配业务场景SEATA 结合 Sharding-JDBC 实现跨分片分布式事务核心依靠两类注解实现事务管控与业务适配不同注解对应不同分片业务场景是入门开发与生产落地的核心重点下面结合分库分表场景逐一说明。5.0.1 GlobalTransactionalSEATA 全局事务注解注解作用开启跨库、跨分片全局分布式事务是 SEATASharding-JDBC 整合的核心注解。可统一管控多个分片数据源的分支事务保证所有分片数据要么全部提交、要么全部回滚彻底解决分库分表「部分分片成功、部分分片失败」的一致性问题。核心属性适配分片场景rollbackFor Exception.class捕获所有业务异常任意分片报错触发全分片回滚适配跨多分片复杂业务timeout自定义全局事务超时时间解决跨多库分片事务耗时过长导致的强制回滚失效问题propagation支持事务传播配置适配多服务嵌套分片事务场景。贴合使用场景一次业务操作路由多个分库、多个分片表的读写场景如用户下单根据user_id分库、order_id分表单次下单跨分片写入跨分片数据联动更新场景如下单同步扣减分片库存、生成分片流水记录高并发分片写入场景需要严格保证多分片数据一致性禁止脏数据残留。5.0.2 TransactionalSpring本地事务注解注解作用在 SEATASharding 整合架构中仅用于单分片本地事务兜底负责单个数据源内部的SQL事务控制不具备跨分片事务能力必须配合 GlobalTransactional 使用。贴合使用场景单个分片内多条SQL批量执行保证单库数据本地一致性作为全局事务的分支兜底辅助SEATA完成单分片事务提交与回滚。重要规范分库分表跨分片事务必须以 GlobalTransactional 为入口仅使用 Transactional 会导致跨分片事务完全失效。5.0.3 注解组合使用规范生产标准分片分布式事务标准写法入口方法加 GlobalTransactional分支业务方法加 Transactional形成「全局事务统筹本地事务兜底」的双层事务架构。5.1 项目依赖5.1 项目依赖核心引入Sharding-JDBC分片依赖、SEATA事务依赖版本适配SpringCloud Alibaba生态。!-- sharding-jdbc 分库分表核心依赖 -- dependency groupIdorg.apache.shardingsphere/groupId artifactIdsharding-jdbc-spring-boot-starter/artifactId version4.1.1/version /dependency !-- seata 分布式事务 -- dependency groupIdio.seata/groupId artifactIdseata-spring-boot-starter/artifactId version1.5.2/version /dependency5.2 数据库准备模拟分库场景创建2个分库order_db_0、order_db_1每个库包含订单分片表t_order_0 ~ t_order_1所有分片库必须初始化undo_log表。CREATE TABLE IF NOT EXISTS undo_log ( id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 自增主键, branch_id BIGINT(20) NOT NULL COMMENT 分支事务ID, xid VARCHAR(128) NOT NULL COMMENT 全局事务ID, context VARCHAR(128) NOT NULL COMMENT 上下文, rollback_info LONGBLOB NOT NULL COMMENT 回滚镜像信息, log_status INT(11) NOT NULL COMMENT 0正常1已回滚, log_created DATETIME NOT NULL, log_modified DATETIME NOT NULL, PRIMARY KEY (id), UNIQUE KEY ux_undo_log (xid,branch_id) ) ENGINEInnoDB DEFAULT CHARSETutf8 COMMENTSEATA事务回滚日志表;5.3 核心差异化配置整合专属与单独使用差异对比SEATA、Sharding-JDBC单独使用时无需特殊适配但二者整合场景存在数据源代理、事务托管冲突必须添加专属差异化配置也是整合事务生效的核心关键仅列举差异配置常规分片、SEATA基础配置不再赘述。# SEATA Sharding 整合差异化专属配置 spring: shardingsphere: # 核心差异1关闭Sharding原生事务避免与SEATA事务冲突 # 单独用Sharding默认LOCAL整合SEATA必须改为NONE交由SEATA统一托管 transaction: type: NONE # 其余常规分片规则、数据源配置、SEATA注册配置与单独使用保持一致无需改动配套Java差异化配置唯一代码差异单独使用 Sharding/SEATA 无需手动代理数据源整合场景必须手动用 SEATA 数据源代理包裹 Sharding 数据源解决多层代理冲突否则跨分片事务完全不生效。Configuration public class SeataShardingConfig { Bean Primary public DataSource dataSource(ShardingDataSource shardingDataSource) { // 整合专属差异SEATA嵌套代理Sharding数据源 return new DataSourceProxy(shardingDataSource); } }全局事务模式兜底差异生产环境统一兜底配置spring.shardingsphere.transaction.typeBASE适配SEATA AT模式禁止XA/LOCAL模式混用规避事务协议冲突。重点关闭Sharding自带事务、适配SEATA事务代理保证分布式事务生效。spring: # 关闭sharding默认本地事务交给seata托管 shardingsphere: props: sql-show: true allow-range-query-without-sharding-key: true # 关闭sharding原生事务 transaction: type: NONE # 分库分表规则配置 datasource: names: ds0,ds1 ds0: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/order_db_0?useSSLfalseserverTimezoneGMT%2B8 username: root password: 123456 ds1: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/order_db_1?useSSLfalseserverTimezoneGMT%2B8 username: root password: 123456 sharding: tables: t_order: actual-data-nodes: ds$-{0..1}.t_order_$-{0..1} database-strategy: inline: sharding-column: user_id algorithm-expression: ds$-{user_id % 2} table-strategy: inline: sharding-column: order_id algorithm-expression: t_order_$-{order_id % 2} # SEATA 分布式事务配置 seata: enabled: true tx-service-group: default_tx_group service: vgroup-mapping: default_tx_group: default registry: type: nacos nacos: server-addr: 127.0.0.1:8848 config: type: nacos nacos: server-addr: 127.0.0.1:8848手动注入SEATA代理数据源覆盖Sharding默认数据源解决事务不生效、代理冲突核心问题。Configuration public class SeataShardingConfig { Bean Primary public DataSource dataSource(ShardingDataSource shardingDataSource) { // SEATA代理Sharding数据源实现分片事务管控 return new DataSourceProxy(shardingDataSource); } }5.5 业务实战代码跨分片分布式事务模拟一次下单跨分片写入手动制造异常测试多分片事务一致性。Service public class OrderServiceImpl implements OrderService { Resource private OrderMapper orderMapper; // 开启跨分片分布式事务 Override GlobalTransactional(rollbackFor Exception.class) public void createOrder(Order order) { // 1.插入订单自动根据分片键路由至不同分库分表 orderMapper.insert(order); // 2.模拟业务异常触发全分片回滚 int i 1 / 0; } }5.6 效果验证正常无异常所有分片数据写入成功undo_log自动清除代码抛出异常所有已写入的分片数据全部回滚无任何脏数据残留彻底解决原生Sharding-JDBC跨分片部分成功、部分失败的事务问题。5.7 分片场景注解搭配高频坑点汇总生产致命问题SEATA Sharding-JDBC 整合架构中注解使用不规范是跨分片事务失效、脏读、回滚重试卡死、数据不一致的第一大成因。下面汇总生产 7 类最高频、最隐蔽的注解搭配错误明确错误场景、故障原理与标准规范。5.7.1 坑点一只写 GlobalTransactional不加 ShardingSphereTransactionType(BASE)错误场景跨多分库、多分片业务仅使用 SEATA 全局事务注解未手动指定 Sharding 事务类型。故障原理Sharding-JDBC 默认自带本地事务管控若未强制指定BASE适配 SEATA AT 模式分片底层会走原生本地事务逻辑。跨分片出现异常时Sharding 本地事务无法联动 SEATA 全局事务部分分片本地提交成功、SEATA 全局回滚指令无法覆盖分片数据最终导致分库数据回滚失效、分片数据不一致。正确规范SEATA AT 整合分片场景统一配置spring.shardingsphere.transaction.typeBASE全局适配 SEATA 事务托管杜绝原生事务冲突。5.7.2 坑点二GlobalLock 缺少 Transactional / for update错误场景分片高并发读写场景仅使用 SEATA 全局锁注解GlobalLock未搭配本地事务或行锁。故障原理GlobalLock 仅控制全局分布式锁不替代本地事务与数据库行锁。缺少本地事务包裹时数据库语句自动提交、锁瞬间释放全局锁约束失效。高并发下依然存在跨分片脏读、数据覆盖问题最终触发 SEATAundo 镜像校验失败、事务无限重试卡死。正确规范GlobalLock 必须嵌套 Transactional 本地事务热点数据查询更新搭配 for update 行锁双重杜绝脏读。5.7.3 坑点三分片场景 GlobalLock lockKey 未携带分片字段错误场景跨库分表场景全局锁 lockKey 仅使用业务ID未携带分片字段user_id/分库标识。故障原理Sharding 分片数据分散在不同库、不同表中若锁 Key 不携带分片字段锁作用域会错乱。不同分片的不同业务数据会共用同一把锁或本该互斥的分片数据无法加锁跨分片互相脏读、数据覆盖引发回滚校验失败。正确规范分片场景 lockKey 必须包含「分片键唯一业务ID」保证锁粒度精准绑定单分片单行数据隔离跨分片并发读写。5.7.4 坑点四DDL 语句放在 GlobalTransactional 方法内错误场景全局事务方法中执行建表、改表、加索引等 DDL 语句。故障原理MySQL 对 DDL 语句会强制触发自动提交本地事务会直接打断 SEATA 一阶段镜像生成流程导致当前分支 undo 日志丢失、无回滚快照。全局事务异常时SEATA 无数据可还原事务回滚彻底失效产生永久性分片脏数据。正确规范所有 DDL 语句禁止纳入 SEATA 全局事务单独执行、避开事务切面。5.7.5 坑点五遗漏内层 Transactional 本地事务错误场景外层仅添加 GlobalTransactional内层分片业务方法无任何本地事务注解。故障原理SEATA 分支 RM 生成 undo_log 镜像的前置条件是本地事务上下文生效。内层无 Transactional 时分片 SQL 自动提交、无法被 SEATA 切面拦截RM 分支无 undo 快照生成。二阶段全局回滚时无镜像可还原直接回滚失败。正确规范严格遵循「外层 GlobalTransactional 内层分片业务 Transactional」双层事务规范。5.7.6 坑点六混用 XA 与 BASE 事务类型错误场景项目同时存在 XA、BASE 两种事务模式或分片配置与 SEATA 模式不匹配。故障原理XA 强一致性事务与 BASE 最终一致性事务的分支注册、日志机制、锁机制完全不兼容。混用后事务协议冲突SEATA TC 无法正常识别、注册分片分支事务导致全局事务创建失败、分片事务不生效、提交回滚异常。正确规范一个项目统一一种事务模式分片整合 SEATA AT 必须固定 typeBASE禁止多模式混用。5.7.7 坑点七单纯依赖 GlobalTransactional完全放弃 Sharding 事务管控错误场景认为开启 SEATA 全局事务即可随意关闭、修改 Sharding 事务配置。故障原理Sharding-JDBC 承担多分片 SQL 路由、多数据源调度若完全取消 Sharding 事务适配分片多数据源执行时序错乱SEATA 无法统一接管多分片分支出现部分分片未纳入全局事务、回滚遗漏的问题。正确规范必须配置spring.shardingsphere.transaction.typeBASE适配 SEATA不关闭分片事务适配能力实现框架分层托管。六、生产踩坑与解决方案6.1 坑点1整合后分布式事务不生效原因Sharding-JDBC原生事务与SEATA数据源代理冲突未关闭Sharding默认事务。解决配置spring.shardingsphere.transaction.typeNONE强制交给SEATA托管。6.2 坑点2跨分片回滚触发data validation failed原因高并发下多分片数据被外部线程篡改镜像校验失败。解决热点分片数据增加分布式锁、禁止并发修改核心业务拆分小事务。6.3 坑点3多分片大事务超时回滚失败原因跨多库多分片事务耗时过长TC强制终止分片状态割裂。解决禁止大事务、拆分分片业务调优SEATA超时时间增加定时对账兜底。七、全文总结Sharding-JDBC 解决了海量数据的存储扩容、读写性能问题但缺失分布式事务能力SEATA AT 模式解决了跨分片数据一致性问题。两者结合是目前互联网海量数据高并发项目的标准生产架构。该方案具备零侵入、高性能、易扩展的优势适配绝大多数电商、流水、账单、用户数据业务但存在AT模式天生的隔离性缺陷金融级强一致场景需要升级为Sharding SEATA TCC模式。同时生产必须遵循小事务规范、配合兜底对账保证分片事务百分百可靠。