2.MySql读写分离及分库分表

主从复制

  • 主从复制

  • 主从复制是指将主数据库的DDL和DML操作通过二进制日志传到从数据库上,然后在从数据库上对这些日志进行重新执行,从而使从数据库和主数据库的数据保持一致。

  • 主要涉及三个线程:binlog 线程、I/O 线程和 SQL 线程。

    • binlog 线程(主库) :负责将主服务器上的数据更改写入二进制日志(Binary log)中。
    • I/O 线程(从库) :负责从主服务器上读取二进制日志,并写入从服务器的中继日志(Relay log)。
    • SQL 线程(从库) :负责读取中继日志,解析出主服务器已经执行的数据更改并在从服务器中重放(Replay)。

读写分离

  • 主服务器处理写操作以及实时性要求比较高的读操作,而从服务器处理读操作。
    读写分离能提高性能的原因在于:
    • 主从服务器负责各自的读和写,极大程度缓解了锁的争用;
    • 从服务器可以使用 MyISAM,提升查询性能以及节约系统开销;
    • 增加冗余,提高可用性。
      读写分离常用代理方式来实现,代理服务器接收应用层传来的读写请求,然后决定转发到哪个服务器。

分区表

分区表的底层原理

​ 分区表由多个相关的底层表实现,这个底层表也是由句柄对象标识,我们可以直接访问各个分区。存储引擎管理分区的各个底层表和管理普通表一样(所有的底层表都必须使用相同的存储引擎),分区表的索引只是在各个底层表上各自加上一个完全相同的索引。从存储引擎的角度来看,底层表和普通表没有任何不同,存储引擎也无须知道这是一个普通表还是一个分区表的一部分。
​ 分区表的操作按照以下的操作逻辑进行:

  • select查询
    ​ 当查询一个分区表的时候,分区层先打开并锁住所有的底层表,优化器先判断是否可以过滤部分分区,然后再调用对应的存储引擎接口访问各个分区的数据
  • insert操作
    ​ 当写入一条记录的时候,分区层先打开并锁住所有的底层表,然后确定哪个分区接受这条记录,再将记录写入对应底层表
  • delete操作
    ​ 当删除一条记录时,分区层先打开并锁住所有的底层表,然后确定数据对应的分区,最后对相应底层表进行删除操作
  • update操作
    ​ 当更新一条记录时,分区层先打开并锁住所有的底层表,mysql先确定需要更新的记录再哪个分区,然后取出数据并更新,再判断更新后的数据应该再哪个分区,最后对底层表进行写入操作,并对源数据所在的底层表进行删除操作
    ​ 有些操作时支持过滤的,例如,当删除一条记录时,MySQL需要先找到这条记录,如果where条件恰好和分区表达式匹配,就可以将所有不包含这条记录的分区都过滤掉,这对update同样有效。如果是insert操作,则本身就是只命中一个分区,其他分区都会被过滤掉。mysql先确定这条记录属于哪个分区,再将记录写入对应得曾分区表,无须对任何其他分区进行操作
    ​ 虽然每个操作都会“先打开并锁住所有的底层表”,但这并不是说分区表在处理过程中是锁住全表的,如果存储引擎能够自己实现行级锁,例如innodb,则会在分区层释放对应表锁。
  • 分区类型

分库分表

  • 需要进行分库分表的情况
    • 大量请求阻塞:在高并发场景下,大量请求都需要操作数据库,导致连接数不够了,请求处于阻塞状态。
    • SQL 操作变慢:如果数据库中存在一张上亿数据量的表,一条 SQL 没有命中索引会全表扫描,这个查询耗时会非常久。
    • 存储出现问题:业务量剧增,单库数据量越来越大,给存储造成巨大压力。
    • 业界一般认为超过500万就需要做分表操作

分库

  • 按业务分库
  • 按表分库

分表

MySql内部分表方案

  • 对id进行Hash

水平拆分

  • 按月分表
  • 按天份表
水平拆分的问题
  • 分布式全局唯一ID
  • 分片键选择
    • 选择分片键时,需要先统计该表上的所有的 SQL,尽量选择使用频率且唯一值多的字段作为分片键,既能做到数据均匀分布,又能快速定位到数据位置,例如user_id,order_id等。
  • 数据扩容
    • 举个例子,目前交易数据库 trade 中的订单表 orders 已经做了水平分库(位于两个不同RDS实例上),这时发现两个 RDS 写入性能还是不够,需要再扩容一个RDS,同时将 orders 从原来的 20 个子表扩容到 40个(user_id % 40),这就需要迁移数据来实现数据重平衡,既要停机迁移数据,又要修改代码,有点出力不讨好的感觉啦。
  • 跨库Join
  • 跨库排序分页

垂直拆分

  • 按照冷热字符进行垂直拆分
垂直拆分的问题
  • 跨库Join问题
    • 全局表
    • 数据同步
  • 分布式事务问题
    • 本地消息表
      • 消息生产方:需要额外建一个消息表,并记录消息发送状态,消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后消息会经过 MQ 发送到消息的消费方,如果消息发送失败,会进行重试发送。
      • 消息消费方:需要处理这个消息,并完成自己的业务逻辑,此时如果本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。

数据库设计

  • 需求分析
  • 构建E-R图
  • 数据库三范式 外键
  • CDM(概念数据模型)->LDM(逻辑数据模型)->PDM(物理数据模型)->Database
  • 数据库选型
    • 数据库方面主要包括数据存储,检索,安全,读写分离,分库分表,数据归档,接入数据仓库都要进行确认

2.MySql读写分离及分库分表
https://x-leonidas.github.io/2025/10/26/05数据库/MySQL/2.MySql读写分离及分库分表/
作者
听风
发布于
2025年10月26日
更新于
2025年6月30日
许可协议