MySQL 分库分表

对于使用 MySQL 作为数据库管理系统的应用来说,当数据量达到一定规模时,单库单表的架构会面临性能瓶颈,如查询缓慢、写入性能下降等问题。为了解决这些问题,可以使用分库分表技术。

二、为什么需要分库分表

2.1 单库单表的局限性

数据量过大:随着业务的发展,单表的数据量可能会达到数十亿甚至更多,这会导致索引变得庞大,查询时的磁盘 I/O 开销增加,从而影响查询性能。

并发压力:大量的并发读写请求会使数据库服务器的 CPU、内存和磁盘 I/O 资源达到瓶颈,导致响应时间变长,甚至出现数据库崩溃的情况。

2.2 分库分表的好处

提升性能:通过将数据分散到多个数据库和表中,可以减少单个数据库和表的数据量,从而提高查询和写入的性能。

增强扩展性:分库分表可以方便地增加数据库服务器和表的数量,以应对不断增长的数据量和并发请求。

三、分库分表的原理

3.1 分库

分库是将一个数据库中的数据分散到多个数据库中。可以按照业务功能、数据类型等进行划分。例如,将用户相关的数据存放在一个数据库中,将订单相关的数据存放在另一个数据库中。

3.2 分表

分表是将一个表中的数据分散到多个表中。常见的分表方式有水平分表和垂直分表。

水平分表:将表按照行进行划分,将不同行的数据存储到不同的表中。例如,按照用户 ID 的哈希值将用户数据分散到多个表中。

垂直分表:将表按照列进行划分,将不同列的数据存储到不同的表中。例如,将一个包含用户基本信息和详细信息的表拆分成两个表,一个存储基本信息,另一个存储详细信息。

四、常见的分库分表实现方式

4.1 客户端分片

客户端分片是指在应用程序端实现分库分表的逻辑。应用程序根据规则将数据路由到不同的数据库和表中。

实现思路

  1. 数据路由规则设计:确定如何将数据映射到不同的数据库和表,常见的规则有哈希取模、范围划分等。

  2. 数据库连接管理:使用数据库连接池来管理与各个数据库的连接,提高连接的复用性和性能。

  3. SQL 语句生成:根据数据路由结果,生成对应的 SQL 语句,将数据插入到正确的数据库和表中。

    #include <iostream>
    #include <string>
    #include <vector>
    #include <mysql_driver.h>
    #include <mysql_connection.h>
    #include <cppconn/statement.h>
    #include <cppconn/prepared_statement.h>
    #include <cppconn/resultset.h>
    #include <cppconn/exception.h>
    #include <functional>

    // 哈希函数
    int hashFunction(int key, int numShards) {
    return std::hash<int>()(key) % numShards;
    }

    // 数据库连接信息
    struct DatabaseInfo {
    std::string host;
    std::string user;
    std::string password;
    std::string database;
    };

    // 分库分表管理器
    class ShardingManager {
    public:
    ShardingManager(const std::vector<DatabaseInfo>& dbs, int numTablesPerDb)
    : databases(dbs), numTablesPerDb(numTablesPerDb) {
    driver = get_mysql_driver_instance();
    }

    复制代码
     // 插入数据
     void insertData(int id, const std::string& name) {
         int dbIndex = hashFunction(id, databases.size());
         int tableIndex = hashFunction(id, numTablesPerDb);
         std::string tableName = "table_" + std::to_string(tableIndex);
    
         try {
             sql::Connection* con = driver->connect(databases[dbIndex].host, databases[dbIndex].user, databases[dbIndex].password);
             con->setSchema(databases[dbIndex].database);
    
             std::string sql = "INSERT INTO " + tableName + " (id, name) VALUES (?, ?)";
             sql::PreparedStatement* pstmt = con->prepareStatement(sql);
             pstmt->setInt(1, id);
             pstmt->setString(2, name);
             pstmt->execute();
    
             delete pstmt;
             delete con;
         } catch (sql::SQLException& e) {
             std::cerr << "SQLException: " << e.what() << std::endl;
         }
     }

    private:
    std::vector<DatabaseInfo> databases;
    int numTablesPerDb;
    sql::mysql::MySQL_Driver* driver;
    };

    int main() {
    // 数据库连接信息
    std::vector<DatabaseInfo> dbs = {
    {"localhost", "user1", "password1", "db1"},
    {"localhost", "user2", "password2", "db2"}
    };

    复制代码
     // 每个数据库中的表数量
     int numTablesPerDb = 2;
    
     // 创建分库分表管理器
     ShardingManager shardingManager(dbs, numTablesPerDb);
    
     // 插入数据
     shardingManager.insertData(1, "John");
     shardingManager.insertData(2, "Jane");
    
     return 0;

    }

4.2 中间件分片

中间件分片是指在应用程序和数据库之间引入一个中间件,由中间件来实现分库分表的逻辑。常见的 MySQL 分库分表中间件有 MyCAT、ShardingSphere 等。

MyCAT 示例

MyCAT 是一个开源的 MySQL 中间件,它可以将多个 MySQL 数据库和表进行逻辑上的整合,为应用程序提供统一的访问接口。

五、分库分表的应用场景

5.1 电商系统

在电商系统中,订单数据和用户数据量非常大。可以将订单数据按照订单创建时间进行水平分表,将用户数据按照用户 ID 进行水平分表。同时,可以将订单数据和用户数据分别存储在不同的数据库中,以提高性能和扩展性。

5.2 社交系统

在社交系统中,用户的动态数据和好友关系数据量也很大。可以将用户动态数据按照用户 ID 进行水平分表,将好友关系数据按照用户 ID 进行垂直分表。

六、分库分表的注意事项

6.1 事务处理

分库分表后,跨数据库和表的事务处理变得更加复杂。可以使用分布式事务解决方案,如两阶段提交、TCC(Try-Confirm-Cancel)等。

6.2 数据迁移

在进行分库分表时,需要将原有的数据迁移到新的数据库和表中。数据迁移过程中需要注意数据的一致性和完整性。

6.3 全局唯一 ID

分库分表后,需要确保生成的 ID 在所有数据库和表中是唯一的。可以使用 UUID、数据库自增 ID、分布式 ID 生成器(如 Snowflake)等方式。

相关推荐
zc.z40 分钟前
Tomcat线程池、业务线程池与数据库连接池的层级约束关系解析及配置优化
服务器·数据库·tomcat
Aplis43 分钟前
ETCD学习之路
数据库·学习·etcd
拷斤锟44 分钟前
使用Excel解析从OData API获取到的JSON数据
数据库·json·excel
翔云1234561 小时前
MySQL 高并发下如何保证事务提交的绝对顺序?
数据库·mysql
正在走向自律1 小时前
X2Doris是SelectDB可视化数据迁移工具,安装与部署&使用手册,轻松进行大数据迁移
数据库·数据迁移·selectdb·x2doris·数据库迁移工具
tuokuac1 小时前
SQL中的LEFT JOIN
数据库·sql
tuokuac1 小时前
SQL中的GROUP BY用法
数据库·sql
爱吃小土豆豆豆豆2 小时前
登录校验一
java·大数据·数据库
Albert Tan2 小时前
Oracle EBS 缺少adcfgclone.pl文件
数据库·oracle