Spring Boot 数据持久化:MyBatis-Plus 分库分表实战指南

在分布式系统开发中,随着业务规模的扩大,单库单表的架构往往会面临性能瓶颈------数据量激增导致查询缓慢、写入耗时变长,甚至出现表锁阻塞等问题。MyBatis-Plus(简称MP)作为MyBatis的增强工具,不仅简化了CRUD操作,还能与分库分表中间件无缝集成,轻松解决数据量大的存储难题。本文将从分库分表的核心概念入手,结合Spring Boot实战,通过详细的示例代码讲解MyBatis-Plus实现分库分表的完整流程,并补充相关拓展知识点,帮助开发者快速上手。

一、分库分表核心概念:为什么需要它?

在讲解实操前,我们先明确分库分表的核心逻辑------本质是"拆分"与"路由":通过将海量数据拆分到多个数据库或数据表中,降低单库单表的数据量,从而提升读写性能;同时通过中间件实现数据的自动路由,让开发者像操作单库单表一样操作拆分后的数据源。

1.1 分库 vs 分表

  • 分表:将一张大表拆分为多张结构相同的小表,所有表仍存储在同一个数据库中。核心解决"单表数据量过大"的问题,比如将一张1000万行的用户表拆分为10张100万行的小表。

  • 分库:将一个数据库拆分为多个数据库,每个数据库存储部分数据。核心解决"单库压力过大"的问题,比如将用户数据按地域拆分为北京库、上海库、广州库,分别存储对应区域的用户信息。

1.2 拆分方式:水平 vs 垂直

水平拆分(横向拆分)

按"数据行"拆分,拆分后每张表/每个库的结构完全相同,数据按规则分布。比如:

  • 用户表按user_id取模拆分:user_id%2=0存user_0表,user_id%2=1存user_1表

  • 订单表按创建时间拆分:2024年1月数据存order_202401表,2月数据存order_202402表

适用场景:数据量巨大,且查询多基于拆分字段(如user_id、时间)。

垂直拆分(纵向拆分)

按"数据列"拆分,拆分后每张表/每个库的结构不同,存储不同维度的字段。比如:

  • 用户表拆分为user_base(存储id、姓名、手机号等核心字段)和user_extend(存储头像、简介、地址等扩展字段)

  • 数据库按业务拆分:用户库(存储用户信息)、订单库(存储订单信息)、商品库(存储商品信息)

适用场景:表字段过多,或不同字段的查询频率差异大(如核心字段高频查询,扩展字段低频查询)。

核心原则:拆分后尽量避免跨库跨表查询(如联合查询多个拆分表),否则会降低性能。若必须跨查询,需通过中间件或业务逻辑优化。

二、实战准备:技术栈与环境搭建

本文采用"Spring Boot + MyBatis-Plus + Sharding-JDBC"实现分库分表------Sharding-JDBC是阿里开源的轻量级分库分表中间件,无需额外部署独立服务,可直接集成到应用中,支持所有基于JDBC的ORM框架(包括MyBatis-Plus)。

2.1 技术栈版本

技术 版本 说明
Spring Boot 2.7.10 稳定版,适配大多数中间件
MyBatis-Plus 3.5.3.1 支持Sharding-JDBC的增强功能
Sharding-JDBC 4.1.1 轻量级分库分表中间件
MySQL 8.0.x 关系型数据库(示例用)
Lombok 1.18.24 简化实体类代码(可选)

2.2 依赖引入(pom.xml)

在Spring Boot项目中引入核心依赖,重点是MyBatis-Plus Starter和Sharding-JDBC Starter:

xml 复制代码
<!-- Spring Boot 核心依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- MyBatis-Plus Starter -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>

<!-- Sharding-JDBC Starter(分库分表核心) -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>

<!-- MySQL 驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

<!-- Lombok(简化代码) -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

<!-- 测试依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
    

2.3 数据库准备

本文将演示3个核心场景:水平分表、垂直分表、水平分库。提前创建对应的数据库和表:

  1. 水平分表场景:1个数据库(sharding_db),2张用户表(t_user_0、t_user_1),结构完全相同。

  2. 垂直分表场景:1个数据库(sharding_db),2张用户相关表(t_user_base、t_user_extend),结构不同。

  3. 水平分库场景:2个数据库(sharding_db_0、sharding_db_1),每个库各1张订单表(t_order),结构完全相同。

创建SQL示例(以MySQL为例):

sql 复制代码
-- 1. 水平分表:创建数据库sharding_db
CREATE DATABASE IF NOT EXISTS sharding_db CHARACTER SET utf8mb4;
USE sharding_db;

-- 水平分表:t_user_0 和 t_user_1(结构相同)
CREATE TABLE IF NOT EXISTS t_user_0 (
    id BIGINT NOT NULL COMMENT '用户ID',
    username VARCHAR(50) NOT NULL COMMENT '用户名',
    age INT NOT NULL COMMENT '年龄',
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS t_user_1 LIKE t_user_0;

-- 垂直分表:t_user_base(核心字段)和 t_user_extend(扩展字段)
CREATE TABLE IF NOT EXISTS t_user_base (
    id BIGINT NOT NULL COMMENT '用户ID',
    username VARCHAR(50) NOT NULL COMMENT '用户名',
    phone VARCHAR(20) NOT NULL COMMENT '手机号',
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS t_user_extend (
    id BIGINT NOT NULL COMMENT '用户ID(与t_user_base关联)',
    avatar VARCHAR(255) COMMENT '头像地址',
    address VARCHAR(255) COMMENT '详细地址',
    update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 2. 水平分库:创建2个数据库sharding_db_0、sharding_db_1
CREATE DATABASE IF NOT EXISTS sharding_db_0 CHARACTER SET utf8mb4;
CREATE DATABASE IF NOT EXISTS sharding_db_1 CHARACTER SET utf8mb4;

-- 每个库创建t_order表(结构相同)
USE sharding_db_0;
CREATE TABLE IF NOT EXISTS t_order (
    id BIGINT NOT NULL COMMENT '订单ID',
    user_id BIGINT NOT NULL COMMENT '用户ID',
    order_no VARCHAR(50) NOT NULL COMMENT '订单编号',
    amount DECIMAL(10,2) NOT NULL COMMENT '订单金额',
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

USE sharding_db_1;
CREATE TABLE IF NOT EXISTS t_order LIKE sharding_db_0.t_order;
    

三、核心实战:MyBatis-Plus 分库分表示例

Sharding-JDBC的核心配置是"数据源配置"和"分片规则配置"------通过配置告诉中间件:数据拆分到哪些库/表?按什么规则路由?下面结合3个场景逐一演示。

场景1:水平分表(按用户ID取模拆分)

需求:将用户数据按user_id取模拆分到t_user_0和t_user_1表(user_id%2=0→t_user_0,user_id%2=1→t_user_1),使用MyBatis-Plus实现CRUD操作。

3.1.1 配置文件(application.yml)

yaml 复制代码
spring:
  # Sharding-JDBC 配置
  shardingsphere:
    # 数据源配置(水平分表仅1个数据源)
    datasources:
      # 数据源名称(自定义)
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
        username: root
        password: root123456
    # 分片规则配置
    sharding:
      # 表分片规则(重点)
      tables:
        # 逻辑表名(自定义,对应MP实体类的表名)
        t_user:
          # 数据节点:格式为 数据源名称.真实表名,多个表用逗号分隔
          actual-data-nodes: ds0.t_user_$->{0..1}
          # 表分片策略(按user_id取模)
          table-strategy:
            inline:
              # 分片键(即按哪个字段拆分)
              sharding-column: id
              # 分片表达式(user_id%2得到0或1,对应t_user_0和t_user_1)
              algorithm-expression: t_user_$->{id % 2}
      # 主键生成策略(可选,MP也可配置)
      key-generators:
        t_user_key:
          type: SNOWFLAKE
          props:
            worker-id: 123
    # 打印SQL(开发环境开启,便于调试)
    props:
      sql:
        show: true
# MyBatis-Plus 配置
mybatis-plus:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.sharding.entity
  configuration:
    map-underscore-to-camel-case: true # 下划线转驼峰
  global-config:
    db-config:
      id-type: ASSIGN_ID # 主键生成策略(雪花算法,与Sharding-JDBC一致)
    

3.1.2 实体类(User.java)

java 复制代码
package com.example.sharding.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;

@Data
@TableName("t_user") // 对应Sharding-JDBC配置的逻辑表名
public class User {
    private Long id; // 分片键(用户ID)
    private String username;
    private Integer age;
    private LocalDateTime createTime; // 对应数据库的create_time(下划线转驼峰)
}
    

3.1.3 Mapper接口(UserMapper.java)

MyBatis-Plus的BaseMapper已提供CRUD方法,直接继承即可:

java 复制代码
package com.example.sharding.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.sharding.entity.User;
import org.springframework.stereotype.Repository;

@Repository
public interface UserMapper extends BaseMapper<User> {
}
    

3.1.4 测试类(UserMapperTest.java)

通过测试验证数据是否按规则路由到对应表:

java 复制代码
package com.example.sharding.mapper;

import com.example.sharding.entity.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
import java.util.List;

@SpringBootTest
public class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    // 测试新增:验证按id取模拆分
    @Test
    public void testInsert() {
        // id=1(1%2=1→t_user_1)
        User user1 = new User();
        user1.setId(1L);
        user1.setUsername("张三");
        user1.setAge(25);
        user1.setCreateTime(LocalDateTime.now());
        userMapper.insert(user1);

        // id=2(2%2=0→t_user_0)
        User user2 = new User();
        user2.setId(2L);
        user2.setUsername("李四");
        user2.setAge(30);
        user2.setCreateTime(LocalDateTime.now());
        userMapper.insert(user2);

        System.out.println("新增成功,可去数据库查看t_user_0和t_user_1表数据");
    }

    // 测试查询:验证自动路由到对应表
    @Test
    public void testSelect() {
        // 查询id=1的用户(应从t_user_1查询)
        User user1 = userMapper.selectById(1L);
        System.out.println("id=1的用户:" + user1);

        // 查询所有用户(自动聚合t_user_0和t_user_1的数据)
        List<User> userList = userMapper.selectList(null);
        System.out.println("所有用户:" + userList);
    }
}
    

3.1.5 测试结果说明

  • 执行testInsert后,id=1的用户会插入到t_user_1表,id=2的用户会插入到t_user_0表。

  • 执行testSelect时,selectById(1L)会自动路由到t_user_1表查询;selectList(null)会自动查询t_user_0和t_user_1表,将结果聚合后返回。

场景2:垂直分表(按字段维度拆分)

需求:将用户数据拆分为核心字段(t_user_base)和扩展字段(t_user_extend),通过MyBatis-Plus实现关联查询和分别插入。

3.2.1 配置文件(application.yml)

垂直分表无需复杂的分片规则,只需配置数据源,MP通过不同的实体类和Mapper对应不同的表:

yaml 复制代码
spring:
  shardingsphere:
    datasources:
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
        username: root
        password: root123456
    # 垂直分表无需表分片规则(直接操作真实表)
    props:
      sql:
        show: true
# MyBatis-Plus 配置(不变)
mybatis-plus:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.sharding.entity
  configuration:
    map-underscore-to-camel-case: true
  global-config:
    db-config:
      id-type: ASSIGN_ID
    

3.2.2 实体类(UserBase.java + UserExtend.java)

java 复制代码
// UserBase.java(对应t_user_base表,核心字段)
package com.example.sharding.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;

@Data
@TableName("t_user_base") // 对应真实表名
public class UserBase {
    private Long id; // 关联键
    private String username;
    private String phone;
    private LocalDateTime createTime;
}

// UserExtend.java(对应t_user_extend表,扩展字段)
package com.example.sharding.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;

@Data
@TableName("t_user_extend") // 对应真实表名
public class UserExtend {
    private Long id; // 与UserBase的id关联
    private String avatar;
    private String address;
    private LocalDateTime updateTime;
}
   

3.2.3 Mapper接口(UserBaseMapper.java + UserExtendMapper.java)

java 复制代码
package com.example.sharding.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.sharding.entity.UserBase;
import org.springframework.stereotype.Repository;

@Repository
public interface UserBaseMapper extends BaseMapper<UserBase> {
}

package com.example.sharding.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.sharding.entity.UserExtend;
import org.springframework.stereotype.Repository;

@Repository
public interface UserExtendMapper extends BaseMapper<UserExtend> {
}
    

3.2.4 关联查询(自定义XML)

垂直分表的关联查询需通过XML自定义SQL(关联t_user_base和t_user_extend),创建UserMapper.xml:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.sharding.mapper.UserBaseMapper"&gt;
    <!-- 关联查询用户完整信息(核心字段+扩展字段) -->
    <select id="selectUserFullInfo" resultType="java.util.Map">
        SELECT 
            ub.id, ub.username, ub.phone, ub.create_time,
            ue.avatar, ue.address, ue.update_time
        FROM t_user_base ub
        LEFT JOIN t_user_extend ue ON ub.id = ue.id
        WHERE ub.id = #{id}
    </select>
</mapper>
    

在UserBaseMapper中添加方法:

java 复制代码
Map<String, Object> selectUserFullInfo(Long id);

3.2.5 测试类

java 复制代码
package com.example.sharding.mapper;

import com.example.sharding.entity.UserBase;
import com.example.sharding.entity.UserExtend;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
import java.util.Map;

@SpringBootTest
public class UserVerticalShardingTest {

    @Autowired
    private UserBaseMapper userBaseMapper;

    @Autowired
    private UserExtendMapper userExtendMapper;

    // 测试分别插入核心字段和扩展字段
    @Test
    public void testInsertVertical() {
        // 插入核心字段(t_user_base)
        UserBase userBase = new UserBase();
        userBase.setId(3L);
        userBase.setUsername("王五");
        userBase.setPhone("13800138000");
        userBase.setCreateTime(LocalDateTime.now());
        userBaseMapper.insert(userBase);

        // 插入扩展字段(t_user_extend)
        UserExtend userExtend = new UserExtend();
        userExtend.setId(3L); // 与userBase的id关联
        userExtend.setAvatar("https://xxx.com/avatar/3.jpg");
        userExtend.setAddress("北京市海淀区");
        userExtendMapper.insert(userExtend);

        System.out.println("垂直分表插入成功");
    }

    // 测试关联查询完整信息
    @Test
    public void testSelectFullInfo() {
        Map<String, Object> userInfo = userBaseMapper.selectUserFullInfo(3L);
        System.out.println("用户完整信息:" + userInfo);
    }
}
    

场景3:水平分库(按用户ID取模拆分数据库)

需求:将订单数据按user_id取模拆分到sharding_db_0和sharding_db_1(user_id%2=0→sharding_db_0,user_id%2=1→sharding_db_1),每个库中的订单表为t_order。

3.3.1 配置文件(application.yml)

水平分库需配置多个数据源,并指定数据库分片规则和表分片规则(本例表不分片,仅库分片):

yaml 复制代码
spring:
  shardingsphere:
    # 多数据源配置(sharding_db_0和sharding_db_1)
    datasources:
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_db_0?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
        username: root
        password: root123456
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_db_1?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
        username: root
        password: root123456
    # 分片规则配置(库分片+表分片)
    sharding:
      # 数据库分片规则(按user_id取模)
      default-database-strategy:
        inline:
          sharding-column: user_id # 库分片键(用户ID)
          algorithm-expression: ds$->{user_id % 2} # 分片表达式(user_id%2=0→ds0,1→ds1)
      # 表分片规则(本例表不分片,仅指定真实表名)
      tables:
        t_order:
          actual-data-nodes: ds$->{0..1}.t_order # 数据节点:ds0.t_order 和 ds1.t_order
      # 主键生成策略
      key-generators:
        t_order_key:
          type: SNOWFLAKE
          props:
            worker-id: 123
    props:
      sql:
        show: true
# MyBatis-Plus 配置(不变)
mybatis-plus:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.sharding.entity
  configuration:
    map-underscore-to-camel-case: true
  global-config:
    db-config:
      id-type: ASSIGN_ID

3.3.2 实体类(Order.java)

java 复制代码
package com.example.sharding.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;

@Data
@TableName("t_order") // 对应真实表名(每个库都有t_order表)
public class Order {
    private Long id; // 订单ID
    private Long userId; // 库分片键(用户ID)
    private String orderNo;
    private BigDecimal amount;
    private LocalDateTime createTime;
}
    

3.3.3 Mapper接口(OrderMapper.java)

java 复制代码
package com.example.sharding.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.sharding.entity.Order;
import org.springframework.stereotype.Repository;

@Repository
public interface OrderMapper extends BaseMapper<Order> {
}
    

3.3.4 测试类

java 复制代码
package com.example.sharding.mapper;

import com.example.sharding.entity.Order;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

@SpringBootTest
public class OrderMapperTest {

    @Autowired
    private OrderMapper orderMapper;

    // 测试新增订单:验证按userId分库
    @Test
    public void testInsertOrder() {
        // userId=1(1%2=1→ds1→sharding_db_1库)
        Order order1 = new Order();
        order1.setId(1001L);
        order1.setUserId(1L);
        order1.setOrderNo("ORDER20240501001");
        order1.setAmount(new BigDecimal("99.99"));
        order1.setCreateTime(LocalDateTime.now());
        orderMapper.insert(order1);

        // userId=2(2%2=0→ds0→sharding_db_0库)
        Order order2 = new Order();
        order2.setId(1002L);
        order2.setUserId(2L);
        order2.setOrderNo("ORDER20240501002");
        order2.setAmount(new BigDecimal("199.99"));
        order2.setCreateTime(LocalDateTime.now());
        orderMapper.insert(order2);

        System.out.println("水平分库新增订单成功,可去sharding_db_0和sharding_db_1库查看t_order表");
    }

    // 测试查询订单:验证自动路由到对应库
    @Test
    public void testSelectOrder() {
        // 查询userId=1的订单(应从sharding_db_1库查询)
        List<Order> orderList1 = orderMapper.selectList(
            Wrappers.<Order>lambdaQuery().eq(Order::getUserId, 1L)
        );
        System.out.println("userId=1的订单:" + orderList1);

        // 查询userId=2的订单(应从sharding_db_0库查询)
        List<Order> orderList2 = orderMapper.selectList(
            Wrappers.<Order>lambdaQuery().eq(Order::getUserId, 2L)
        );
        System.out.println("userId=2的订单:" + orderList2);
    }
}
    

四、拓展知识点:分库分表进阶技巧

4.1 分片键选择技巧

  • 优先选择高频查询字段:比如订单表常用userId查询,用userId作为分片键,避免跨库查询。

  • 避免热点数据集中:比如按时间分片时,若某时间段数据量激增(如电商大促),会导致单库/单表压力过大,可结合其他字段(如userId)复合分片。

  • 尽量使用整数类型:整数类型的分片键(如id、userId)取模效率高于字符串类型(如订单号)。

4.2 分库分表后的事务处理

分库分表后,单库事务仍可用Spring的@Transactional,但跨库事务会失效。解决方案:

  • 柔性事务:使用Seata、Hmily等分布式事务框架,支持TCC、SAGA等模式。

  • 业务优化:尽量避免跨库事务,通过"最终一致性"替代强一致性(如用消息队列异步补偿)。

4.3 MyBatis-Plus 高级特性适配

  • 分页插件:分库分表场景下,MP的分页插件需结合Sharding-JDBC使用,配置方式不变,Sharding-JDBC会自动处理跨表分页。

  • 条件构造器:支持所有MP的条件构造器(如lambdaQuery、eq、like等),Sharding-JDBC会自动将条件转换为跨库/跨表查询。

  • 逻辑删除:配置方式与单库单表一致,需确保所有拆分表都添加逻辑删除字段(如is_deleted)。

4.4 分库分表中间件对比

中间件 优点 缺点 适用场景
Sharding-JDBC 轻量级、无独立部署、适配所有JDBC框架、性能好 不支持读写分离自动切换(需额外配置)、动态扩容复杂 中小型分布式系统、对性能要求高的场景
MyCat 支持读写分离、动态扩容、功能强大 需独立部署、性能略低于Sharding-JDBC、配置复杂 大型分布式系统、需要丰富分库分表功能的场景
Sharding-Proxy 支持多语言、动态扩容、统一管理分片规则 需独立部署、性能有损耗(代理层) 多语言开发、需要统一管理分片规则的场景

五、总结

本文通过Spring Boot + MyBatis-Plus + Sharding-JDBC实现了水平分表、垂直分表、水平分库三个核心场景的实战,详细讲解了配置流程、示例代码和测试验证。分库分表的核心是"合理拆分"与"自动路由",开发者需根据业务场景选择合适的拆分方式和分片键,同时注意事务处理、热点数据等问题。

MyBatis-Plus的增强功能(如BaseMapper、条件构造器)与Sharding-JDBC无缝集成,大大降低了分库分表的开发成本。在实际项目中,还需结合业务需求选择合适的中间件,并做好性能监控和动态扩容方案,确保系统稳定运行。

相关推荐
无名-CODING2 小时前
SQL 注入指南
sql·mybatis
悟能不能悟2 小时前
springboot全局异常
大数据·hive·spring boot
ConardLi2 小时前
AI:我裂开了!现在的大模型评测究竟有多变态?
前端·人工智能·后端
Victor3563 小时前
Hibernate(2)Hibernate的核心组件有哪些?
后端
Victor3563 小时前
Hibernate(1)什么是Hibernate?
后端
+VX:Fegn08953 小时前
计算机毕业设计|基于springboot + vue宠物寄养系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计·宠物
一 乐3 小时前
校园实验室|基于springboot + vue校园实验室管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
Lisonseekpan3 小时前
Spring Boot Email 邮件发送完全指南
java·spring boot·后端·log4j
sheji34163 小时前
【开题答辩全过程】以 基于Springboot的体检中心信息管理系统设计与实现为例,包含答辩的问题和答案
java·spring boot·后端