最佳实践概述
场景描述
概述:分布式关系型数据库(简称DRDS),是一款分布式关系型数据库。兼容MySQL协议,专注于解决数据库分布式扩展问题,突破传统数据库的容量和性能瓶颈,实现海量数据高并发访问。
典型行业:互联网企业
适配场景:适用于数据规模较大的场景
方案优势
- 自动分库分表
- 读写分离
- 弹性扩容
前提条件
需搭配开通RDS for MySQL和DRDS等产品
资源规划
网络资源规划
Figure 1 网络资源规划
资源类型 配置项 配置明细 说明 区域 区域 西安2 本最佳实践全部资源部署在西安2资源池 专有网络VPC 状态 新购 云上选择专有网络(VPC)以保障安全性。
选择离原系统公网 IP 近的云上区域减少网络延迟。
选择资源丰富、离用户近的区域保障项目顺利实施。
网络规划留足可用 IP 数即可。VPC名 vpc-vsfl 网段 192.168.0.0/16
弹性计算资源规划
Figure 2 弹性计算资源规划
资源类型 配置项 配置明细 说明 ECS-(MySQL 服务器) ECS名称 ecs-bendi 自定义,易理解可识别 规格 通用计算增强型
c3.large.2
2vCPUs
4GiB
本示例中选择的规格。实际选择的规格需要结合业务场景选择,请参考弹性云服务器的实例规格。 操作系统 Windows 2016 - 系统盘 通用型SSD 40GiB -
数据库资源规划
资源类型 配置项 配置明细 说明 RDS RDS实例名 rds-8c73 自定义,易理解可识别 数据库版本 PostgreSQL 12.6 本示例中为单机。实际使用时,为提升业务可靠性,推荐选择主备RDS实例。 实例类型 单机 - 存储类型 SSD - 可用区 可用区1 本示例中未单机,实际业务场景推荐选择主备RDS实例,此时建议将两个实例创建在不同的可用区,提升业务可靠性。 规格 2 vCPUs | 4 GB - DRDS RDS实例名 Drds-53c1 自定义,易理解可识别 数据库版本 DRDS 选择逻辑库总分片数为2,可根据需要按需进行分片 实例类型 双节点 最大可支持32节点 配置 8C16G
方案正文
insert操作
insert写法规范
- 不建议逐条insert,推荐使用insert into values (),()..();语法。
- MySQL的JDBC连接的url中要加rewriteBatchedStatements参数,并保证5.1.13以上版本的驱动,才能实现批量插入。MySQL
JDBC驱动在默认情况下会无视executeBatch()语句,把预计批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,批量插入实际上是单条插入,直接造成较低的性能。只有把rewriteBatchedStatements参数置为true,
驱动才会批量执行SQL。另外这个选项对INSERT/UPDATE/DELETE操作都有效。
- 拆分字段的值:不建议使用函数、表达式、子查询等,推荐使用常量值。
- 普通字段的值:不建议使用子查询,推荐使用常量、函数、表达式。
大批量数据导入
推荐使用loaddata local infile来实现大批量数据导入。
数据迁移场景
建议使用mysqldump导出sql文件,再使用mysql source命令导入。
auto_increment字段
- DRDS使用Sequence来实现auto_increment语义,并保证全局唯一。
- 赋值:若使用auto_increment字段,建议不要在values子句中赋值,否则容易造成主键冲突。如果在values中赋了值,建议使用alter sequence语句更改。
- 步长:auto_increment字段步长建议不要设置成1,会导致性能低下。默认设置成1000。
update与delete操作
普通更新
- 进行update/delete操作时,where条件建议带上拆分字段;
- 无法带上拆分字段的场景,建议控制并发度,控制更新/删除涉及的数据条数。建议先用select查出相应的数据,double check确保数据范围无误后再实行update/delete操作。
拆分字段更新
- 条数限制:DRDS拆分字段更新有数据量限制,一般不能超过10000条数据,数据量越少越好。若超过10000条数据,建议用改重建表的方式来做,或者是拆分成多次update操作来等价实现。
- 操作的时机:建议选择在业务低谷期做。
关联操作
不建议进行表关联更新、表关联删除操作,即不建议进行多张表同时进行update/delete操作。
- 子查询及limit操作
不建议update/delete语句中含有子查询。不建议update/delete语句中含有limit或order by limit语句。
select操作
- Order by 及 Limit函数
- "order by limit offset, count"场景,禁止给offset赋大数值,即禁止深度翻页。
Group by函数
- 不建议select_list部分含有非group by列。
- 不支持不可下推的group_concat聚合函数内含有order by子句。
- 不建议distinct、group by字段多于3项。
- 不建议join、或者子查询操作之后含有group by操作
- 不建议使用count(distinct ),sum(distinct )操作。
Join函数
- select场景,建议join条件是每个表的拆分字段或使用广播表,或者是驱动表是一个小表(inner/left join驱动表是左表,right join驱动表是右表)。
- 不建议两个大表直接进行join操作。
- 不建议join on condition中含有非等值操作。
- 如遇到临时表超限(Temp table limit exceeded)报错,说明JOIN中间数据产生了临时表且超限,建议进行SQL调优。
- 不建议5张表以上进行join操作。
- join查询操作建议不要开启事务。
- 不建议在事务中进行join查询,开启事务会影响DRDS对join算法的选择,无法使用最高效的算法。
子查询
- 不建议子查询包含在OR表达式中,或者是子查询的关联条件包含在OR表达式中
- 不建议使用含有limit的标量子查询,如 select (select x from t2 where t2.id= t.id limit 1),a,b from t。
- 如果子查询和主表都路由到同一分片,建议在SQL前加/+db=xxx/来精准路由。
- 不建议子查询内部含有join语句。
- 不建议写嵌套子查询。
- 不建议ROW表达式跟子查询做比较操作,如 select * from t where (a,b,c)=(select x,y,z from t2 where …)。
- 不建议select_list里面含有超过2个以上的子查询 。
DDL
DDL执行时机
- 对已有表进行DDL操作时建议放在业务低峰期进行。
分片数
- 创建新拆分表时建议结合实际数据量进行合理预估,总分片数满足需求即可。不建议使用超出实际需求的分片数,拆分表分片数并非越多越好
高危DDL
- 进行高危DDL时请仔细校验SQL后谨慎操作,如DROP TABLE, TRUNCATE TABLE等操作。
DDL失败修复
- DDL命令如遇报错,可以使用"check
table 表名"命令对各个分片表结构进行校验,识别出失败的分片进行针对性修复。如ALTER
TABLE命令遭遇失败可以在命令前添加/*+allow_alter_rerun=true/,开启ALTER语句的幂等可重入执行后重试,直到check
table 命令提示各个分片表结构达到一致则可认为执行成功。
MDL锁导致执行DDL报错
- 背景:为保证DDL的可用性,DRDS内部在执行DDL前会检查底层RDS相关表是否存在MDL锁。 若存在MDL锁,,则DDL会提前报错退出。
- 可能出现的问题:若系统中存在慢SQL,执行时间为几分钟不等,那么可能被MDL锁所阻拦,无法执行DDL。
- 解决方案1:在DRDS控制台提高参数“ddl_precheck_mdl_threshold_time”的大小, 如提高到30分钟(1800秒)。
- 解决方案2:执行show
metadata lock查看是否因为持有慢事务的MDL锁阻塞了DDL的执行。若存在阻塞, 可以使用kill physical
threadId@host:port 来关闭底层慢事务。配合/+allow_alter_rerun=true/的hint, 以及check
table来查看和执行,直到DDL彻底执行完。
DDL长时间卡死
- 在业务低峰期执行DDL时如果遇到长时间卡死情况,请另开会话执行xa recover命令查看是否有慢事务存在,如存在慢事务挂起请及时联系值班人员解决。