热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

expdp导出表结构_超强技术案例!86万张表迁移的优化历程

本文转载自:华为云社区86万张表迁移的优化历程问题背景:2019年12月份的时候DRS项目组接到了一个线上问题:XX客户将mysql数据库

c13d9e18d3dfa3b9923ce7a46b3ac11a.png

本文转载自:华为云社区

86万张表迁移的优化历程问题背景:2019年12月份的时候DRS项目组接到了一个线上问题:XX客户将mysql数据库从友商迁移至华为云的时候性能很慢,而且出现报错。运维同学定位发现用户的某几个实例存在大约2000个库,86万张表,而出错的原因是查询源库数据库超时。和开发同学联系后得到了第一个解决方案:增大和源库的socketTimeout值,保证查询不超时。然而,运维同学在后续保障的过程中发现……

01

86万张表迁移的优化历程

  • 问题背景

2019年12月份的时候DRS项目组接到了一个线上问题:XX客户将mysql数据库从友商迁移至华为云的时候性能很慢,而且出现报错。运维同学定位发现用户的某几个实例存在大约2000个库,86万张表,而出错的原因是查询源库数据库超时。和开发同学联系后得到了第一个解决方案:增大和源库的socketTimeout值,保证查询不超时。然而,运维同学在后续保障的过程中发现超时问题得以解决但是性能无法保证,而且容易出现OOM问题。客户要求在一天内要完成割接,然而我们目前的迁移时间远超24个小时,由于项目的进度问题,留给DRS的时间只剩一个周末。

02

问题定位过程

  • 问题定位

饭要一口口吃,问题也得一个个定位,回到最初的超时问题,我们首先找到了出现超时的sql语句:

SELECT TRIGGER_NAME FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = '****';

这个sql用于查询每个库下面的所有触发器(其他对象的查询sql也有这个问题),我们发现这个sql执行了超过5分钟,这个结果令我们很意外。因为理论上而言只查询一个库下面的所有触发器,怎么会这么慢呢?explain这个sql我们发现:

aced798bdcff240f9c1f84cbd58a0102.png

Extra中表示Scanned all databases!!!这意味着虽然我们只是在查询一个库下面的触发器,但是其实它会扫描所有库对应的frm文件。DEBUG了一下mysql的源码,我们发现虽然只是查询了一个库下面的trigger,但是由于information_schema.triggers表里面并不是一张物理表,导致每次查询都会去打开所有的frm文件,我们知道frm文件是用来存放mysql元数据信息的物理文件,对于用户这个表数量,可想而知这个会对用户的源库IO造成多大的影响,即使有buffer pool也扛不住这么多表的缓存。更关键的是,用户有2000个库,也就是说单就查询trigger这一个对象,我们就需要耗费2000*5=10000分钟的时间,迁移性能可想而知。

  • 优化思路

有了上面的结果,其实采取的优化方式很简单了。首先,我们根据对象的类型来区分查询所有对象的方式,对于表,我们可以使用逐库查询,因为查询表的操作不会Scanned all databases;对于其他对象,我们使用只查询一次的sql:

SELECT TRIGGER_SCHEMA, TRIGGER_NAME FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA NOT in('mysql','information_schema','sys', 'performance_schema');

这样我们的查询时间大大缩短!

然而,现实是残酷的,虽然我们缩短了从源库查询对象列表的时间,但是导出对象到回放对象的性能还是不够出色,不能满足用户的12小时时间限制,此外偶发的OOM问题也随之没有解决。

03

OOM问题

  • 问题定位

用MAT分析了heap堆存储后发现,heap里面存在大量的DbSqlData类的对象,正是大量的这种对象导致堆内存溢出。结合我们的架构可以发现,我们在导出表结构的时候会先把所有对象结构分类型存储在ehcache中,然后在读取的时候又会把数据按类型导出到内存中。针对用户的场景,我们可以计算出(用户的表结构平均占用堆内存4000Byte)86万张表总共需要3.44G,而我们的永久代内存只配置了2G,OOM问题可想而知。

if [ -z "$REPLICATOR_HEAP_SIZE" ]; then
  REPLICATOR_HEAP_SIZE="-Xms3072m -Xmx3072m -XX:NewRatio=3 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m"
fi

  • 优化思路

其实这一切的问题来源都是因为我们按对象类型对ehcache进行存取,这种方式不是流式进行的,很有可能发生OOM问题。因此,解决的思路就是我们按照单个对象的粒度进行存取,并且使用内存控制的方式控制读到堆内的对象数目,保证流式结构的回放,如何进行流式结构的回放将会在下面介绍。

04

性能问题

  • 问题定位

为了满足客户的迁移时间需求,我们统计了各个阶段DRS内核的工作时间,大致分为下面几个阶段:

bcce95c785b9f5bb55039f545275fbf4.png

这三个阶段的执行顺序是串行执行的,其中查询对象列表花了共计1个小时,导出对象结构共计10个小时,回放共计8个小时,总计19个小时。这个结果远远超出了客户的预期,为了解决这个问题,我们对整个迁移流程进行了重新梳理,发现有以下2个改进点:

1.查询对象列表的同时可以将已查询对象列表的结构导出2.导出对象结构可以由单线程导出演进为多线程并发导出

按照上述优化流程,假定查询对象列表时间为A,单线程导出结构所需时间为B,根据CPU核数/IO线程比我们设定导出结构的线程数为8,在源库性能足够的情形下,查询对象列表+导出对象结构的时间应该等于

CostTime(hour)=max(A, B/8) —— 约等于2

这样我们的总时间为2 + 8 = 10小时,满足客户的需求!

  • 优化思路

有了上面的分析,结合OOM问题和查询时间优化的思路,我们有了以下的设计:

690c6de7aa27ee12058203d601b1d36d.png

上面图略去了数据的回放模型,主要突出了结构的回放,同时在两个store中加入了内存控制,防止出现OOM问题。

05

优化结果

在通宵达旦的开发和验证后,我们终于构建了以上的框架,并且成功将86万张表的总时长优化到了10小时以内,更为可喜的是整个流程中的full gc次数为0,最终客户的需求得以实现,技术人员也从中学习到了新的知识。

  • 思考

优化是无止境的,其实上述的架构还存在优化空间,比如以下的两点:

1.结构的导入和数据的回放可以并行执行,针对用户表多数据少的场景,统计发现表结构的导入花了4个小时而数据的导入也只花了4个小时,这一个阶段可以优化(DRS已经做了这个优化,会在后续的博客中给大家科普实现方式)2.结构的导出和结构回放是否可以并行执行,他们之间的限制关系是什么?

如果有小伙伴对我们的架构有看法也可以积极留言,我们会去认真观摩!

1a83cc049081235ce6290138d5557815.png

↓点击



推荐阅读
  • 如何优化MySQL数据库性能以提升查询效率和系统稳定性 ... [详细]
  • 本文详细介绍了在MySQL中如何高效利用EXPLAIN命令进行查询优化。通过实例解析和步骤说明,文章旨在帮助读者深入理解EXPLAIN命令的工作原理及其在性能调优中的应用,内容通俗易懂且结构清晰,适合各水平的数据库管理员和技术人员参考学习。 ... [详细]
  • PTArchiver工作原理详解与应用分析
    PTArchiver工作原理及其应用分析本文详细解析了PTArchiver的工作机制,探讨了其在数据归档和管理中的应用。PTArchiver通过高效的压缩算法和灵活的存储策略,实现了对大规模数据的高效管理和长期保存。文章还介绍了其在企业级数据备份、历史数据迁移等场景中的实际应用案例,为用户提供了实用的操作建议和技术支持。 ... [详细]
  • 如何在MySQL中选择合适的表空间以优化性能和管理效率
    在MySQL中,合理选择表空间对于提升表的管理和访问性能至关重要。表空间作为MySQL中用于组织和管理数据的一种机制,能够显著影响数据库的运行效率和维护便利性。通过科学地配置和使用表空间,可以优化存储结构,提高查询速度,简化数据管理流程,从而全面提升系统的整体性能。 ... [详细]
  • 包含phppdoerrorcode的词条 ... [详细]
  • Spring Data JdbcTemplate 入门指南
    本文将介绍如何使用 Spring JdbcTemplate 进行数据库操作,包括查询和插入数据。我们将通过一个学生表的示例来演示具体步骤。 ... [详细]
  • 本文介绍了如何使用Flume从Linux文件系统收集日志并存储到HDFS,然后通过MapReduce清洗数据,使用Hive进行数据分析,并最终通过Sqoop将结果导出到MySQL数据库。 ... [详细]
  • 本文介绍了在 MySQL 中如何使用正则表达式来提高查询效率,通过具体示例展示了如何筛选包含中文字符的记录,并详细解释了正则表达式的各种特殊字符和结构。 ... [详细]
  • 本文介绍如何在将数据库从服务器复制到本地时,处理因外键约束导致的数据插入失败问题。 ... [详细]
  • MySQL的查询执行流程涉及多个关键组件,包括连接器、查询缓存、分析器和优化器。在服务层,连接器负责建立与客户端的连接,查询缓存用于存储和检索常用查询结果,以提高性能。分析器则解析SQL语句,生成语法树,而优化器负责选择最优的查询执行计划。这一流程确保了MySQL能够高效地处理各种复杂的查询请求。 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • 本文深入探讨了NoSQL数据库的四大主要类型:键值对存储、文档存储、列式存储和图数据库。NoSQL(Not Only SQL)是指一系列非关系型数据库系统,它们不依赖于固定模式的数据存储方式,能够灵活处理大规模、高并发的数据需求。键值对存储适用于简单的数据结构;文档存储支持复杂的数据对象;列式存储优化了大数据量的读写性能;而图数据库则擅长处理复杂的关系网络。每种类型的NoSQL数据库都有其独特的优势和应用场景,本文将详细分析它们的特点及应用实例。 ... [详细]
  • C盘无法格式化的原因及解决方法
    本文探讨了C盘无法格式化的原因,并提供了详细的解决方案,帮助用户顺利进行系统维护。 ... [详细]
  • SQL 查询实体优化与实战技巧分享 ... [详细]
  • Syncnavigator激活工具及破解方法详解
    本文详细介绍了Syncnavigator激活工具的使用方法及其破解技巧。用户可以通过访问官方网站www.SyncNavigator.CN获取相关资源,并通过客服QQ 1793040获得技术支持和帮助。此外,文章还提供了详细的步骤说明和常见问题解答,以确保用户能够顺利激活并使用Syncnavigator软件。 ... [详细]
author-avatar
福田商务汽车--南宁鑫来
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有