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
相关推荐
Emrys_2 分钟前
Java 动态代理详解:从原理到实战
java·后端
倔强的石头6 分钟前
java程序员如何搭建C++windows开发环境搭建(三)
c++·后端
灵魂猎手10 分钟前
12. 告别 MyBatis IN 语句的 foreach 模板:自定义扩展 让 SQL 编写效率翻倍
java·后端·源码
JarvanMo27 分钟前
跨平台开发的隐性成本
前端·后端
风象南1 小时前
SpringBoot 程序 CPU 飙升排查:自制「方法级采样火焰图」
spring boot·后端
用户6120414922131 小时前
springboot+vue3做的图书管理与借阅系统
vue.js·spring boot·后端
IT_陈寒1 小时前
Python数据处理太慢?这5个Pandas优化技巧让速度提升300%!
前端·人工智能·后端
技术小泽1 小时前
Kafka架构以及组件讲解
后端·性能优化
Victor3562 小时前
Redis(28)Redis的持久化文件可以跨平台使用吗?
后端
Victor3562 小时前
Redis(29)如何手动触发Redis的RDB快照?
后端