@Alpacadh
2022-09-18T17:05:52.000000Z
字数 1640
阅读 234
分库分表
mysql
1、简介
- DB中的业务表数据量大了之后,无论是CRUD读写性能,还是日常维护变更,都是一件极其耗费资源的事情。即便正确设置了索引,仍然无法掩盖因为数据量过大从而导致的数据库性能下降的事实。此时对数据库及表进行 水平拆分 (sharding,即分库分表 ),将原本一张表维护的海量数据分配给 N 个子表进行存储和维护,就是一种简单有效的优化办法。
- 分库分表一般分为垂直分库分表、水平分库分表。
- 垂直分库分表主要为更偏向于业务拆分。
- 分库:将相互之间可以明确划分领域边界的库表拆分到多个数据库中,从而分散数据存储和读取的压力,降低数据层面的耦合程度。
- 分表:是指根据数据表不同列的实际应用场景,将部分列拆分出来,改变原来的表结构。往往可以结合实际查询场景、冷热数据列拆分、大字段独立存储等方式拆分表结构。
- 水平分库分表主要分为三个:只分表、只分库、分库分表。
- 只分表:将db库中的user表拆分为2个分表,user_0和user_1,这两个表还位于同一个库中。
- 只分库:将db库拆分为db_0和db_1两个库,同时在db_0和db_1库中各自新建一个user表,db_0.user表和db_1.user表中各自只存原来的db.user表中的部分数据。
- 分库分表:将db库拆分为db_0和db_1两个库,db_0中包含user_0、user_1两个分表,db_1中包含user_2、user_3两个分表。
2、拆分原因
为什么要拆分成分库分表,这样的好处是什么?
- 分库往往部署在多套集群中,也就意味着降低了单个集群的负载压力,提升整体的读写性能。
分表提高数据操作的效率。举个例子说明,比如user表中现在有4000w条数据,此时我们需要在这个表中增加(insert)一条新的数据,insert完毕后,数据库会针对这张表重新建立索引,4000w行数据建立索引的系统开销还是不容忽视的。
假如我们将这个大表分成4个分表,从user_0到user_3,4000w行数据平均下来,每个子表里只有1000W行数据,对1000W行的表中insert数据,建立索引的时间就会下降,从而提高了DB的运行时效率,进而提高并发量。
除了提高写的效率,更重要的是提高读效率,提高查询的性能。当然分表的好处还不止这些,还有诸如减少写操作时锁范围等,都会带来很多明显的优点。
分库分表好处怎么多为啥不都采用分库分表?
目标分库分表遇到的困难主要为如下几个原因:
- 对于开发人员而言,虽然分库分表,但还是希望能和单库单表那样的去简单地操作数据库,包括查询与DML操作。
- 在分库分表后,我们不能再使用mysql的自增主键。因为在插入记录的时候,不同的库生成的记录的自增id会出现冲突。因此需要有一个全局的id生成器。
- 分布式事务是分库分表绕不过去的一个坎,因为涉及到了同时更新多个数据库,如何保证要么同时成功,要么同时失败。关于分布式事务,mysql支持XA事务,但是效率较低。柔性事务是目前比较主流的方案,柔性事务包括:最大努力通知型、可靠消息最终一致性方案以及TCC两阶段提交。但是无论XA事务还是柔性事务,实现起来都是非常复杂的。一般采用柔性事务解决。
动态扩容指的是增加分库分表的数量。
例如原来的user表拆分到2个库的4张表上。现在我们希望将分库的数量变为4个,分表的数量变为8个。这种情况下一般要伴随着数据迁移。例如在4张表的情况下,id为7的记录,7%4=3,因此这条记录位于user_3这张表上。但是现在分表的数量变为了8个,而7%8=7,而user_7这张表上根本就没有id=7的这条记录,因此如果不进行数据迁移的话,就会出现记录找不到的情况。数据库中间件团体也有方法来解决。
对于新的应用,如果预估到未来数据量比较大,可以提前进行分库分表。但是对于一些老的应用,单表数据量已经比较大了,这个时候就涉及到数据迁移的过程。**数据库中间件团队提供了一些工具来帮助业务方进行数据迁移
**
3、拆分依据