深入学习MySQL(七):高可用架构与分库分表

内容分享6个月前发布
12 0 0

随着业务规模增长,单机MySQL面临性能瓶颈和单点故障风险。本文将深入讲解MySQL高可用架构方案和分库分表策略,协助你构建可扩展的数据库架构。

高可用架构概述

高可用的目标

指标

说明

目标值

可用性

系统正常运行时间占比

99.99%(年停机<53分钟)

RTO

恢复时间目标

< 30秒

RPO

数据恢复点目标

0(零数据丢失)

常见高可用方案对比

方案

复杂度

数据一致性

故障切换

适用场景

主从复制

低

最终一致

手动

读多写少

MHA

中

最终一致

自动

通用场景

MGR

中

强一致

自动

金融级场景

MySQL Cluster

高

强一致

自动

超高可用

Galera Cluster

中

强一致

自动

多主写入

MHA高可用架构

MHA简介

MHA(Master High Availability)是一款开源的MySQL高可用解决方案,由日本DeNA公司开发。它能在主库故障时自动完成故障检测和主从切换,一般能在10-30秒内完成切换。

MHA架构

                    ┌─────────────────┐
                    │   MHA Manager   │
                    │  (监控和管理)    │
                    └────────┬────────┘
                             │ 监控
           ┌─────────────────┼─────────────────┐
           │                 │                 │
           ▼                 ▼                 ▼
    ┌────────────┐    ┌────────────┐    ┌────────────┐
    │   Master   │    │   Slave1   │    │   Slave2   │
    │ (MHA Node) │    │ (MHA Node) │    │ (MHA Node) │
    └────────────┘    └────────────┘    └────────────┘
           │                 ▲                 ▲
           └─────────────────┴─────────────────┘
                      主从复制

MHA组件

  • MHA Manager:管理节点,负责监控主库状态、执行故障切换
  • MHA Node:数据节点,部署在每台MySQL服务器上

MHA安装配置

1. 安装MHA Node(所有MySQL节点)

# 安装依赖
yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager

# 下载并安装MHA Node
wget https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58.tar.gz
tar -xzf mha4mysql-node-0.58.tar.gz
cd mha4mysql-node-0.58
perl Makefile.PL
make && make install

2. 安装MHA Manager(管理节点)

# 安装依赖
yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes

# 下载并安装MHA Manager
wget https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-manager-0.58.tar.gz
tar -xzf mha4mysql-manager-0.58.tar.gz
cd mha4mysql-manager-0.58
perl Makefile.PL
make && make install

3. 配置SSH免密登录

# 在Manager节点生成密钥
ssh-keygen -t rsa

# 分发公钥到所有节点
ssh-copy-id root@192.168.1.100  # Master
ssh-copy-id root@192.168.1.101  # Slave1
ssh-copy-id root@192.168.1.102  # Slave2

4. 创建MHA配置文件

# /etc/mha/app1.cnf

[server default]
# MySQL复制用户
user=root
password=root123
repl_user=repl
repl_password=Repl@123456

# SSH用户
ssh_user=root

# MHA工作目录
manager_workdir=/var/log/mha/app1
manager_log=/var/log/mha/app1/manager.log
remote_workdir=/var/log/mha/app1

# 故障切换脚本
master_ip_failover_script=/usr/local/bin/master_ip_failover
master_ip_online_change_script=/usr/local/bin/master_ip_online_change

# 检测间隔
ping_interval=1

[server1]
hostname=192.168.1.100
port=3306
candidate_master=1

[server2]
hostname=192.168.1.101
port=3306
candidate_master=1

[server3]
hostname=192.168.1.102
port=3306
no_master=1

5. VIP切换脚本

#!/usr/bin/env perl
# /usr/local/bin/master_ip_failover

use strict;
use warnings FATAL => 'all';
use Getopt::Long;

my (
    $command, $ssh_user, $orig_master_host, $orig_master_ip,
    $orig_master_port, $new_master_host, $new_master_ip, $new_master_port
);

my $vip = '192.168.1.200';
my $interface = 'eth0';
my $key = '1';

GetOptions(
    'command=s'          => $command,
    'ssh_user=s'         => $ssh_user,
    'orig_master_host=s' => $orig_master_host,
    'orig_master_ip=s'   => $orig_master_ip,
    'orig_master_port=i' => $orig_master_port,
    'new_master_host=s'  => $new_master_host,
    'new_master_ip=s'    => $new_master_ip,
    'new_master_port=i'  => $new_master_port,
);

exit &main();

sub main {
    if ($command eq "stop" || $command eq "stopssh") {
        # 停止VIP
        my $exit_code = 1;
        eval {
            &stop_vip();
            $exit_code = 0;
        };
        if ($@) {
            warn "Got Error: $@
";
            exit $exit_code;
        }
        exit $exit_code;
    }
    elsif ($command eq "start") {
        # 启动VIP
        my $exit_code = 10;
        eval {
            &start_vip();
            $exit_code = 0;
        };
        if ($@) {
            warn $@;
            exit $exit_code;
        }
        exit $exit_code;
    }
    elsif ($command eq "status") {
        exit 0;
    }
    else {
        &usage();
        exit 1;
    }
}

sub start_vip() {
    `ssh $ssh_user@$new_master_host "ip addr add $vip/24 dev $interface"`;
    `ssh $ssh_user@$new_master_host "arping -c 3 -I $interface $vip"`;
}

sub stop_vip() {
    `ssh $ssh_user@$orig_master_host "ip addr del $vip/24 dev $interface"`;
}

sub usage {
    print "Usage: master_ip_failover --command=start|stop|stopssh|status
";
}

6. 检查和启动MHA

# 检查SSH连接
masterha_check_ssh --conf=/etc/mha/app1.cnf

# 检查复制状态
masterha_check_repl --conf=/etc/mha/app1.cnf

# 启动MHA Manager
nohup masterha_manager --conf=/etc/mha/app1.cnf 
    --remove_dead_master_conf 
    --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

# 检查MHA状态
masterha_check_status --conf=/etc/mha/app1.cnf

MHA故障切换流程

  1. 检测主库故障:Manager通过ping_interval检测主库状态
  2. 确认主库宕机:多次检测失败后确认主库故障
  3. 选择新主库:根据配置和数据最新程度选择候选主库
  4. 补齐差异日志:从各从库收集差异binlog,补齐新主库
  5. 切换VIP:执行master_ip_failover脚本切换VIP
  6. 重新配置从库:将其他从库指向新主库

MySQL Group Replication (MGR)

MGR简介

MySQL Group Replication是MySQL 5.7.17引入的官方高可用方案,基于Paxos协议实现分布式一致性。

MGR特点

  • 多主/单主模式:支持单主(推荐)和多主模式
  • 自动故障检测:基于组成员协议自动检测故障节点
  • 自动故障切换:单主模式下自动选举新主库
  • 强一致性:基于Paxos协议保证数据一致性

MGR架构

单主模式:
┌─────────────────────────────────────────────────┐
│                Group Replication                 │
│  ┌─────────┐   ┌─────────┐   ┌─────────┐       │
│  │ Primary │   │Secondary│   │Secondary│       │
│  │  (R/W)  │   │  (R/O)  │   │  (R/O)  │       │
│  └────┬────┘   └────┬────┘   └────┬────┘       │
│       │             │             │             │
│       └─────────────┼─────────────┘             │
│                     │                           │
│           Group Communication                   │
│              (Paxos协议)                        │
└─────────────────────────────────────────────────┘

MGR配置

1. 准备工作

所有节点配置my.cnf:

[mysqld]
# 基础配置
server_id = 1  # 每个节点不同
gtid_mode = ON
enforce_gtid_consistency = ON
log_bin = mysql-bin
binlog_format = ROW
log_slave_updates = ON
binlog_checksum = NONE
master_info_repository = TABLE
relay_log_info_repository = TABLE

# MGR配置
plugin_load_add = 'group_replication.so'
transaction_write_set_extraction = XXHASH64
group_replication_group_name = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
group_replication_start_on_boot = OFF
group_replication_local_address = "192.168.1.100:33061"
group_replication_group_seeds = "192.168.1.100:33061,192.168.1.101:33061,192.168.1.102:33061"
group_replication_bootstrap_group = OFF

# 单主模式(推荐)
group_replication_single_primary_mode = ON
group_replication_enforce_update_everywhere_checks = OFF

2. 创建复制用户

-- 在所有节点执行
SET SQL_LOG_BIN = 0;

CREATE USER 'repl'@'%' IDENTIFIED BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
GRANT BACKUP_ADMIN ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;

SET SQL_LOG_BIN = 1;

-- 配置复制通道
CHANGE REPLICATION SOURCE TO 
    SOURCE_USER = 'repl',
    SOURCE_PASSWORD = 'Repl@123456'
    FOR CHANNEL 'group_replication_recovery';

3. 启动MGR集群

-- 在第一个节点(引导节点)
SET GLOBAL group_replication_bootstrap_group = ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group = OFF;

-- 在其他节点
START GROUP_REPLICATION;

4. 查看集群状态

-- 查看组成员
SELECT * FROM performance_schema.replication_group_members;

+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
| group_replication_applier | 3a3b3c3d-1111-2222-3333-444444444444 | node1       |        3306 | ONLINE       | PRIMARY     | 8.0.32         | XCom                       |
| group_replication_applier | 4a4b4c4d-1111-2222-3333-444444444444 | node2       |        3306 | ONLINE       | SECONDARY   | 8.0.32         | XCom                       |
| group_replication_applier | 5a5b5c5d-1111-2222-3333-444444444444 | node3       |        3306 | ONLINE       | SECONDARY   | 8.0.32         | XCom                       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+

-- 查看主节点
SELECT MEMBER_HOST, MEMBER_PORT 
FROM performance_schema.replication_group_members 
WHERE MEMBER_ROLE = 'PRIMARY';

MGR与MySQL Router

MySQL Router可以与MGR配合实现自动故障切换。

# 初始化Router配置
mysqlrouter --bootstrap root@192.168.1.100:3306 
    --user=mysqlrouter 
    --directory=/etc/mysqlrouter

# 启动Router
mysqlrouter -c /etc/mysqlrouter/mysqlrouter.conf &

生成的配置文件:

[routing:primary]
bind_address = 0.0.0.0
bind_port = 6446
destinations = metadata-cache://mycluster/?role=PRIMARY
routing_strategy = first-available
protocol = classic

[routing:secondary]
bind_address = 0.0.0.0
bind_port = 6447
destinations = metadata-cache://mycluster/?role=SECONDARY
routing_strategy = round-robin-with-fallback
protocol = classic

分库分表

为什么需要分库分表

问题

表现

解决方案

单表数据量过大

查询慢、索引效率低

分表

单库写入瓶颈

TPS上限、连接数限制

分库

单机存储上限

磁盘空间不足

分库

单机内存限制

Buffer Pool不足

分库

分库分表策略

垂直拆分

按业务模块拆分数据库或表。

垂直分库:
┌──────────────────────────────────────────────────┐
│                    单体数据库                      │
│  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐   │
│  │ 用户表  │ │ 订单表  │ │ 商品表  │ │ 库存表  │   │
│  └────────┘ └────────┘ └────────┘ └────────┘   │
└──────────────────────────────────────────────────┘
                        ↓ 垂直拆分
┌────────────┐ ┌────────────┐ ┌────────────────────┐
│  用户库     │ │  订单库     │ │     商品库         │
│ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐┌────────┐│
│ │ 用户表  │ │ │ │ 订单表  │ │ │ │ 商品表  ││ 库存表  ││
│ └────────┘ │ │ └────────┘ │ │ └────────┘└────────┘│
└────────────┘ └────────────┘ └────────────────────┘

垂直分表:
┌─────────────────────────────────────┐
│              用户表                  │
│ id, name, age, avatar, bio, ...    │
└─────────────────────────────────────┘
                  ↓ 垂直拆分
┌─────────────────┐  ┌─────────────────┐
│    用户基础表     │  │   用户扩展表     │
│ id, name, age   │  │ id, avatar, bio │
└─────────────────┘  └─────────────────┘

水平拆分

按数据行拆分到多个库或表。

水平分表:
┌─────────────────────────────────────┐
│           订单表(1000万行)          │
└─────────────────────────────────────┘
                  ↓ 水平拆分
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│  order_0    │ │  order_1    │ │  order_2    │ │  order_3    │
│ (250万行)   │ │ (250万行)   │ │ (250万行)   │ │ (250万行)   │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘

水平分库:
┌─────────────────────────────────────┐
│              单库                    │
│         订单表(1000万行)            │
└─────────────────────────────────────┘
                  ↓ 水平拆分
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│    db_0     │ │    db_1     │ │    db_2     │ │    db_3     │
│ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │
│ │ order_0 │ │ │ │ order_1 │ │ │ │ order_2 │ │ │ │ order_3 │ │
│ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘

分片键选择

分片键(Sharding Key)是决定数据路由的关键字段。

选择原则

  1. 高频查询条件:分片键应该是查询中最常用的条件
  2. 数据分布均匀:避免数据倾斜
  3. 避免跨分片查询:尽量让相关数据在同一分片
  4. 不可变:分片键值不应该被修改

常见分片策略

1. 取模分片

// 根据用户ID取模
int shardIndex = userId % shardCount;
String tableName = "order_" + shardIndex;

2. 范围分片

// 根据时间范围
if (orderTime.getYear() == 2023) {
    tableName = "order_2023";
} else if (orderTime.getYear() == 2024) {
    tableName = "order_2024";
}

3. 哈希分片

// 一致性哈希
int hash = consistentHash(userId);
int shardIndex = hash % shardCount;

4. 复合分片

// 先按用户分库,再按订单ID分表
int dbIndex = userId % dbCount;
int tableIndex = orderId % tableCount;
String dataSource = "db_" + dbIndex;
String tableName = "order_" + tableIndex;

ShardingSphere实战

ShardingSphere简介

Apache ShardingSphere是一套开源的分布式数据库中间件,包含:

  • ShardingSphere-JDBC:轻量级Java框架,以jar包形式提供
  • ShardingSphere-Proxy:透明化数据库代理,支持任何语言

ShardingSphere-JDBC配置

1. 添加依赖

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.4.0</version>
</dependency>

2. 分库分表配置

spring:
  shardingsphere:
    # 数据源配置
    datasource:
      names: ds0,ds1
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://192.168.1.100:3306/mydb_0?useSSL=false
        username: root
        password: root123
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://192.168.1.101:3306/mydb_1?useSSL=false
        username: root
        password: root123
    
    # 分片规则
    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
          
          # 订单明细表分片规则
          t_order_item:
            actual-data-nodes: ds$->{0..1}.t_order_item_$->{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
        
        # 绑定表(关联查询优化)
        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
    
    # 显示SQL
    props:
      sql-show: true

3. 实体类和Mapper

@Data
@TableName("t_order")
public class Order {
    @TableId(type = IdType.ASSIGN_ID)
    private Long orderId;
    private Long userId;
    private BigDecimal amount;
    private Integer status;
    private LocalDateTime createTime;
}

@Mapper
public interface OrderMapper extends BaseMapper<Order> {
    
    @Select("SELECT * FROM t_order WHERE user_id = #{userId} ORDER BY create_time DESC")
    List<Order> findByUserId(@Param("userId") Long userId);
}

4. 使用示例

@Service
public class OrderService {
    
    @Autowired
    private OrderMapper orderMapper;
    
    // 插入数据(自动路由到对应分片)
    public void createOrder(Order order) {
        orderMapper.insert(order);
    }
    
    // 根据分片键查询(准确路由)
    public List<Order> getOrdersByUserId(Long userId) {
        return orderMapper.findByUserId(userId);
    }
    
    // 跨分片查询(全分片扫描,性能较差)
    public List<Order> getOrdersByStatus(Integer status) {
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getStatus, status);
        return orderMapper.selectList(wrapper);
    }
}

自定义分片算法

1. 实现分片算法接口

public class OrderTableShardingAlgorithm implements StandardShardingAlgorithm<Long> {
    
    @Override
    public String doSharding(Collection<String> availableTargetNames, 
                             PreciseShardingValue<Long> shardingValue) {
        // 准确分片
        Long orderId = shardingValue.getValue();
        String suffix = String.valueOf(orderId % 4);
        
        for (String tableName : availableTargetNames) {
            if (tableName.endsWith(suffix)) {
                return tableName;
            }
        }
        throw new IllegalArgumentException("No target table found");
    }
    
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames,
                                         RangeShardingValue<Long> shardingValue) {
        // 范围分片
        Range<Long> range = shardingValue.getValueRange();
        List<String> result = new ArrayList<>();
        
        for (String tableName : availableTargetNames) {
            // 简化处理:范围查询返回所有表
            result.add(tableName);
        }
        return result;
    }
    
    @Override
    public String getType() {
        return "ORDER_TABLE";
    }
    
    @Override
    public void init(Properties props) {
    }
}

2. 注册自定义算法

# 在 META-INF/services/org.apache.shardingsphere.sharding.spi.ShardingAlgorithm 文件中添加
com.example.sharding.OrderTableShardingAlgorithm

3. 使用自定义算法

spring:
  shardingsphere:
    rules:
      sharding:
        sharding-algorithms:
          order-table-algorithm:
            type: ORDER_TABLE

分布式主键

雪花算法(Snowflake)

spring:
  shardingsphere:
    rules:
      sharding:
        key-generators:
          snowflake:
            type: SNOWFLAKE
            props:
              worker-id: 1
              max-vibration-offset: 1

UUID

spring:
  shardingsphere:
    rules:
      sharding:
        key-generators:
          uuid:
            type: UUID

自定义主键生成器

public class CustomKeyGenerator implements KeyGenerateAlgorithm {
    
    private AtomicLong counter = new AtomicLong(0);
    
    @Override
    public Comparable<?> generateKey() {
        // 自定义主键生成逻辑
        return System.currentTimeMillis() * 10000 + counter.incrementAndGet() % 10000;
    }
    
    @Override
    public String getType() {
        return "CUSTOM";
    }
    
    @Override
    public void init(Properties props) {
    }
}

分布式事务

Seata AT模式

spring:
  shardingsphere:
    rules:
      transaction:
        default-type: XA
        provider-type: Atomikos

使用示例

@Service
public class OrderService {
    
    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private InventoryMapper inventoryMapper;
    
    @ShardingTransactionType(TransactionType.XA)
    @Transactional
    public void createOrderWithInventory(Order order, Long productId) {
        // 创建订单(可能在ds0)
        orderMapper.insert(order);
        
        // 扣减库存(可能在ds1)
        inventoryMapper.decrease(productId, 1);
    }
}

分库分表最佳实践

容量规划

指标

提议值

说明

单表行数

< 1000万

超过后查询性能下降

单表大小

< 10GB

便于备份和迁移

单库表数

< 500

避免元数据过多

分片数量

2的幂次

便于扩容

扩容方案

翻倍扩容

扩容前:4个分片
user_id % 4 = 0 → shard_0
user_id % 4 = 1 → shard_1
user_id % 4 = 2 → shard_2
user_id % 4 = 3 → shard_3

扩容后:8个分片
user_id % 8 = 0 → shard_0 (原shard_0的一半数据)
user_id % 8 = 4 → shard_4 (原shard_0的另一半数据)
...

扩容步骤

  1. 准备新分片:创建新的数据库实例
  2. 数据迁移:使用工具迁移数据到新分片
  3. 双写验证:新旧分片同时写入,验证一致性
  4. 切换路由:更新分片规则
  5. 清理旧数据:删除已迁移的数据

常见问题

问题一:跨分片查询

// 不推荐:跨分片查询
SELECT * FROM t_order WHERE status = 1;

// 推荐:带分片键查询
SELECT * FROM t_order WHERE user_id = 123 AND status = 1;

问题二:跨分片JOIN

// 不推荐:跨分片JOIN
SELECT o.*, i.* FROM t_order o 
JOIN t_order_item i ON o.order_id = i.order_id;

// 推荐:使用绑定表
binding-tables:
  - t_order,t_order_item

问题三:跨分片排序分页

// 问题:跨分片分页效率低
SELECT * FROM t_order ORDER BY create_time LIMIT 10000, 10;

// 优化1:使用游标分页
SELECT * FROM t_order WHERE create_time > '2024-01-01' 
ORDER BY create_time LIMIT 10;

// 优化2:二次查询
// 第一次:各分片查询ID
// 第二次:根据ID准确查询

问题四:全局唯一ID

// 使用雪花算法
@TableId(type = IdType.ASSIGN_ID)
private Long id;

// 或使用分布式ID服务
private Long id = idGenerator.nextId();

总结

本文详细介绍了MySQL高可用架构和分库分表方案:

  1. MHA:成熟的主从高可用方案,自动故障切换
  2. MGR:MySQL官方高可用方案,基于Paxos协议
  3. 分库分表:解决单机性能瓶颈的有效手段
  4. ShardingSphere:功能强劲的分库分表中间件

选择提议:

  • 中小规模:MHA + 读写分离
  • 金融级场景:MGR + MySQL Router
  • 大规模数据:ShardingSphere分库分表

下一篇我们将介绍MySQL性能调优与运维实战。

深入学习MySQL(七):高可用架构与分库分表

© 版权声明

相关文章

暂无评论

none
暂无评论...