乐趣区

关于mysql:mysql分表之后怎么平滑上线

分表的目标

我的项目开发中,咱们的数据库数据越来越大,随之而来的是单个表中数据太多。以至于查问数据变慢,而且因为表的锁机制导致利用操作也受到重大影响,呈现了数据库性能瓶颈。

当呈现这种状况时,咱们能够思考分表,行将单个数据库表进行拆分,拆分成多个数据表,而后用户拜访的时候,依据肯定的算法,让用户拜访不同的表,这样数据扩散到多个数据表中,缩小了单个数据表的拜访压力。晋升了数据库拜访性能。

举个栗子

比方咱们最常见的用户表(user 表)

id user_id 其余字段
主键 id 用户 id 其余字段

咱们个别都会用 user_id 去查问对应的用户信息,然而随着业务的增长,这张表会越来越大,甚至上亿,重大影响了查问性能。
所以咱们就会对这张表进行分表处理,分到多张表减小查问压力

分表策略

以分 10 张表为例 (具体分多少张表 依据理论状况来估算)
首先咱们建 10 张表
user1、user2、user3。。。。。user10

个别状况下,咱们都会用作为索引的字段 (user_id) 进行取模解决。想分多少张表,就依照多少取模,比方这个 case 就是 10

$table_name = $user_id % 10;

依照下面的取模公式

  • user_id 为 1295 的会落在 user5 外面
  • user_id 为 8634 的会落在 user4 外面
  • 。。。。。。。

每次 CURD 依据下面查找表的策略进行就行了,这个问题不大,咱们暂且先不多说。

曾经上线的运行中的表怎么办?

其实下面的办法大家应该都晓得怎么用,然而有个问题,曾经上线了的表怎么办?那张表的数据在线上是始终被查找或者扭转的。如何可能进行平滑的分表,并且让用户无感知呢?

办法 1

间接上线,提前写个脚本,脚本内容是把旧表 (user) 的数据同步到 user1 表到 user10 表,一上线了连忙执行

这种办法显著是行不通的,次要是存在以下问题

  • 如果执行过程中脚本有问题怎么办?代码全副回滚?
  • 脚本把把旧表 (user) 的数据同步到 user1 表到 user10 表,这个脚本得执行多久?如果是 1 个小时,那么这段时间线上和这张表相干的业务都是不失常的

这显然是行不通的,对线上影响很大。

办法 2

先写个同步数据的脚本,脚本内容是把旧表 (user) 的数据同步到 user1 表到 user10 表,脚本同步完了再上线。

这个办法看起来敌对了一些,不过也存在一些问题。

  • 脚本同步完,立刻上线,这两件事之间是有一些时间差的,这个时间差中线上表可能有一些改变,这些改变怎么办?

以上两种办法看起来貌似都行不通,所以看来得来点不一样的了。咱们间接看论断。

步骤 1 上线双写

首先咱们把双写上线了,什么意思呢?比方 user_id=123,对于减少,删除,批改操作来说,咱们既操作 user 表,也操作 user_id=123 对应的 user3 表。

function modify($user_id){  // 蕴含减少,删除,批改操作
  modify_user();  //modify user 表
  $table_name = $user_id % 10;
  modify_user($table_name) //modify 对应的分表
}

因为查问的局部还是在 user 表中查问的,所以下面的操作对线上用户是无任何影响的。

步骤 2 全量同步

写一个全量同步 user 表到 user1-user10 的表,最好找个低峰期执行脚本,以防万一影响 user 表的查问

这一步执行之后,因为咱们之前上线了双写(见步骤 1),所以 user 表和 user1-user10 表之间的数据曾经是完全一致的了。

步骤 3 查问新表数据

将查问的局部改到 user1-user10

因为后面两个步骤咱们曾经保障了 user 表和各个分表之间的数据齐全一致性,所以间接把查问的局部改掉是没有任何问题的

如果依照以上步骤执行,那么对线上的数据是没有任何影响的,而且咱们线上就是这么操作了,通过了屡次实际确保不会出问题,放心使用即可。如果这篇文章帮忙到了你,记得点个赞哦。

退出移动版