MySQL(182) 如何进行MySQL的分库分表?

MySQL的分库分表(Sharding)是一种将数据水平拆分为多个库和表的技术,以解决单个数据库性能瓶颈和存储限制。这种技术可以提高数据库的并发处理能力,分散数据存储负载。下面详细介绍如何进行MySQL的分库分表,并结合代码进行说明。

一、分库分表的策略

  1. 水平分表:将一张大表拆分为多张小表。
  2. 水平分库:将一个库的数据拆分到多个库中,每个库包含部分数据。
  3. 垂直分表:将一张大表按列拆分为多张小表(通常不涉及水平分库分表的讨论)。

二、分库分表的实现步骤

1. 设计分库分表策略

常见的分库分表策略有Hash分片、Range分片和List分片。以下以水平分库分表为例,采用Hash分片策略。

假设我们有一个用户表users,需要进行分库分表。

1.1 选择分片键

选择一个确定分片方法的字段,比如用户ID (user_id)。

1.2 确定分片规则

假设我们将数据拆分到4个库中,每个库包含4张表,总共16张表。分片规则可以是:

  • 库编号 = user_id % 4
  • 表编号 = user_id / 4 % 4
1.3 创建数据库和表
sql 复制代码
-- 创建4个数据库
CREATE DATABASE user_db_0;
CREATE DATABASE user_db_1;
CREATE DATABASE user_db_2;
CREATE DATABASE user_db_3;

-- 在每个数据库中创建4张用户表
USE user_db_0;
CREATE TABLE users_0 (user_id INT PRIMARY KEY, user_name VARCHAR(255), ...);
CREATE TABLE users_1 (user_id INT PRIMARY KEY, user_name VARCHAR(255), ...);
CREATE TABLE users_2 (user_id INT PRIMARY KEY, user_name VARCHAR(255), ...);
CREATE TABLE users_3 (user_id INT PRIMARY KEY, user_name VARCHAR(255), ...);

USE user_db_1;
CREATE TABLE users_0 (user_id INT PRIMARY KEY, user_name VARCHAR(255), ...);
CREATE TABLE users_1 (user_id INT PRIMARY KEY, user_name VARCHAR(255), ...);
CREATE TABLE users_2 (user_id INT PRIMARY KEY, user_name VARCHAR(255), ...);
CREATE TABLE users_3 (user_id INT PRIMARY KEY, user_name VARCHAR(255), ...);

-- 重复以上步骤在 user_db_2 和 user_db_3 中创建表

2. 实现数据的插入、查询和管理

2.1 插入数据

根据分片规则插入数据:

python 复制代码
def insert_user(user_id, user_name):
    db_index = user_id % 4
    table_index = (user_id // 4) % 4
    db_name = f"user_db_{db_index}"
    table_name = f"users_{table_index}"

    sql = f"INSERT INTO {db_name}.{table_name} (user_id, user_name) VALUES (%s, %s)"
    # 执行SQL插入操作(使用具体的数据库连接库,比如pymysql)
    cursor.execute(sql, (user_id, user_name))
    connection.commit()

# 示例插入
insert_user(123, 'John Doe')
2.2 查询数据

根据分片规则查询数据:

python 复制代码
def get_user(user_id):
    db_index = user_id % 4
    table_index = (user_id // 4) % 4
    db_name = f"user_db_{db_index}"
    table_name = f"users_{table_index}"

    sql = f"SELECT * FROM {db_name}.{table_name} WHERE user_id = %s"
    # 执行SQL查询操作
    cursor.execute(sql, (user_id,))
    result = cursor.fetchone()
    return result

# 示例查询
user = get_user(123)
print(user)

3. 使用中间件进行分库分表

手动管理分库分表较为复杂,通常使用中间件来简化分库分表的实现。常用的分库分表中间件包括ShardingSphere、Mycat和Vitess等。

3.1 使用ShardingSphere

ShardingSphere是一个开源的分布式数据库中间件,支持分库分表、读写分离和数据加密等功能。

3.1.1 安装ShardingSphere

下载并解压ShardingSphere Proxy:

bash 复制代码
wget https://archive.apache.org/dist/shardingsphere/5.0.0/apache-shardingsphere-5.0.0-shardingsphere-proxy-bin.tar.gz
tar xzf apache-shardingsphere-5.0.0-shardingsphere-proxy-bin.tar.gz
3.1.2 配置ShardingSphere

编辑conf/server.yamlconf/config-sharding.yaml文件。

server.yaml

yaml 复制代码
authentication:
  users:
    root:
      password: root
    sharding:
      password: sharding
props:
  max-connections-size-per-query: 1
  acceptor-size: 16  # The default value is available processors count * 2.
  executor-size: 16  # Infinite by default.
  proxy-frontend-flush-threshold: 128  # The default value is 128.
  proxy-transaction-type: LOCAL
  proxy-opentracing-enabled: false
  proxy-hint-enabled: false
  query-with-cipher-column: true
  sql-show: false
  check-table-metadata-enabled: false

config-sharding.yaml

yaml 复制代码
schemaName: sharding_db

dataSources:
  ds_0:
    url: jdbc:mysql://127.0.0.1:3306/user_db_0?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
  ds_1:
    url: jdbc:mysql://127.0.0.1:3306/user_db_1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
  ds_2:
    url: jdbc:mysql://127.0.0.1:3306/user_db_2?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
  ds_3:
    url: jdbc:mysql://127.0.0.1:3306/user_db_3?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50

shardingRule:
  tables:
    users:
      actualDataNodes: ds_${0..3}.users_${0..3}
      tableStrategy:
        inline:
          shardingColumn: user_id
          algorithmExpression: users_${user_id % 4}
      keyGenerator:
        type: SNOWFLAKE
        column: user_id
  defaultDatabaseStrategy:
    inline:
      shardingColumn: user_id
      algorithmExpression: ds_${user_id % 4}
  defaultTableStrategy:
    none:
3.1.3 启动ShardingSphere
bash 复制代码
sh bin/start.sh

现在,您可以通过连接到ShardingSphere Proxy来进行数据库操作,而不需要手动管理分库分表逻辑:

python 复制代码
# 示例连接
import pymysql

connection = pymysql.connect(
    host='127.0.0.1',
    port=3307,  # ShardingSphere默认监听端口
    user='sharding',
    password='sharding',
    db='sharding_db'
)

cursor = connection.cursor()
cursor.execute("INSERT INTO users (user_id, user_name) VALUES (%s, %s)", (123, 'John Doe'))
connection.commit()

cursor.execute("SELECT * FROM users WHERE user_id = %s", (123,))
result = cursor.fetchone()
print(result)

三、总结

分库分表可以有效地解决单库性能瓶颈问题,提高数据库的扩展性和并发处理能力。我们通过手动分库分表和中间件(如ShardingSphere)两种方式进行了详细说明。

  1. 手动分库分表:适用于简单场景,但需要手动管理分片逻辑和数据分布。
  2. 中间件分库分表:如Sharding
相关推荐
shark_chili2 分钟前
浅谈java内存模
后端
Derek_Smart43 分钟前
Netty 客户端与服务端选型分析:下位机连接场景
spring boot·后端·netty
东阳马生架构1 小时前
Dubbo源码—3.服务引用时执行RPC的流程二
后端
东阳马生架构1 小时前
Dubbo源码—3.服务引用时执行RPC的流程一
后端
姑苏洛言1 小时前
餐饮店数字化转型指南:一个小程序搞定全流程运营
前端·javascript·后端
风象南2 小时前
3s → 30ms!SpringBoot树形结构“开挂”实录:一次查询提速100倍
后端
用户6120414922132 小时前
C语言做的汽车线路模拟查询系统
c语言·后端·设计模式
Victor3563 小时前
MySQL(181)如何在MySQL中管理大数据量的表?
后端
你的人类朋友10 小时前
✨什么是SaaS?什么是多租户?
后端·架构·设计