目录
一、什么时候分库分表
- 单表数据过大:当单表的数据量达到1000W或100G以后;
- 对一个很大的表进行DDL修改时,MySQL会锁住全表,这个时间会很长影响业务;
- 大表会经常访问与更新,就更有可能出现锁等待;
二、分库分表--水平分,垂直分
1、水平分库
例如:一个数据库有5000万的数据,单库带动不起来,分为两个库,一个库3000万,一个库2000万;
概念:以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库中。
结果:
每个库的结构都一样;
每个库的数据都不一样,没有交集;
所有库的并集是全量数据;
2、水平分表
概念:以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表中。
结果:
每个表的结构都一样;
每个表的数据都不一样,没有交集;
所有表的并集是全量数据;
3、垂直分库
例如:人员信息表字段多达50多个,把基础的人员信息例如生日性别身份证号不会变动的10个字段设计成【人员-基础】表,剩余的部门信息入职日期岗位等40个字段设计成【人员-扩展】表;
概念:以表为依据,按照业务归属不同,将不同的表拆分到不同的库中。
结果:
每个库的结构都不一样;
每个库的数据也不一样,没有交集;
所有库的并集是全量数据;
4、垂直分表
概念:以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。
结果:
每个表的结构都不一样;
每个表的数据也不一样,一般来说,每个表的字段至少有一列交集,一般是主键,用于关联数据;
所有表的并集是全量数据;
三、分库分表--存在的问题
- 事务一致性
方法一:分布式事务,例如:XA协议,两段式提交;
方法二:最终一致性,例如:事务补偿(事后检查补救措施);
- 跨表跨库 join,order,分页,函数
方法一:字段冗余(适用于依赖字段比较少);
方法二:全局表,也可看做是"数据字典表",将这类表在每个数据库中都保存一份;
方法三:数据组装(从库一种查询id,然后根据id从库二查询出其他数据,然后组装);
- 全局主键 id 避免重复
方法一:唯一索引 = 自增id + 字段
方法二:创建保存时在应用服务器生成 uuid , 然后分布分配到不同的表和库进行存储(uuid长,耗存储);
方法三:其他类似于uudi生成的算法生成全局ID,eg:Twitter的snowflake算法,美团点评的Leaf算法;
四、支持分库分表中间件
站在巨人的肩膀上能省力很多,目前分库分表已经有一些较为成熟的开源解决方案: