用于实现 Azure Database for MySQL 灵活服务器的最佳性能的最佳做法

了解在使用 Azure Database for MySQL 灵活服务器时如何获得最佳性能。 在向平台添加新功能时,我们将继续优化本部分中的建议。

物理邻近性

请确保在同一区域中部署应用程序和数据库。 在开始任何性能基准测试运行之前执行的快速检查是使用简单的 SELECT 1 查询确定客户端和数据库之间的网络延迟。

当 Web 应用程序及其关联的数据库等资源在不同的区域中运行时,这些资源之间的通信延迟可能会增加。 将应用程序和数据库置于不同区域的另一个可能的副作用与出站数据传输成本有关。

为了在成本优化部署中提高应用程序的性能和可靠性,强烈建议 Web 应用程序服务和 Azure Database for MySQL 灵活服务器资源驻留在同一区域和可用性区域中。 这种共置状态最适合对延迟敏感的应用程序,并且它还提供最佳吞吐量,因为资源是紧密配对的。

加速网络

如果你使用的是 Azure 虚拟机、Azure Kubernetes 或应用服务,请对应用程序服务器使用加速网络。 使用加速网络可以实现对 VM 的单根 I/O 虚拟化 (SR-IOV),大幅提升其网络性能。 这种高性能路径会绕过数据路径中的主机,降低延迟、抖动,以及受支持 VM 类型上的最苛刻网络工作负荷的 CPU 利用率。

连接效率

建立新的连接始终是一项昂贵而耗时的任务。 当某个应用程序请求数据库连接时,它会优先分配现有的空闲数据库连接,而不是创建新的连接。 以下是一些用于良好连接做法的选项:

  • ProxySQL:使用 ProxySQL(提供内置连接池)并将工作负载负载均衡到多个只读副本,如应用程序代码更改所需要的那样。

  • Heimdall 数据代理:此外,还可以使用 Heimdall 数据代理,这是一个与供应商无关的专用代理解决方案。 它支持查询缓存和读/写拆分以及复制滞后检测。 还可以参考如何使用 Heimdall 代理加速 MySQL 性能

  • 持久或长期连接:如果应用程序具有短期事务或查询,执行时间通常 < 5-10 ms,则使用持久连接替换短期连接。 将短期连接替换为持久性连接只需对代码进行轻微的更改,但在许多典型的应用方案中,这种做法可以大幅提高性能。 请确保设置事务完成时超时或关闭连接。

  • 副本:如果使用副本,请使用 ProxySQL 在主服务器和可读辅助副本服务器之间进行负载均衡。 了解如何设置 ProxySQL

连接池

连接池是一种机制,用于管理数据库连接的创建和分配,避免数据库连接激增。 如果应用程序在相对较短的时间内打开了许多连接,并且连接的生存期较短,可以考虑使用连接池。 例如,每秒可能发生数百或数千次这些类型的连接,而且与总的连接生存期相比,建立和关闭这些连接所需的时间明显增多。

如果应用程序的开发框架不支持连接池,请在应用程序与数据库服务器之间改用连接代理(例如 ProxySQL 或 Heimdall 代理)。

处理连接缩放

为满足波动的需求,缩放 Web 应用程序的一种常见方法是添加和删除应用程序服务器。 每个应用程序服务器都可以将连接池与数据库配合使用。 这种方法导致数据库服务器上的连接总数与应用程序服务器的数量成正比增长。 例如,如果一个数据库服务器有 10 个应用程序服务器,并且每个服务器针对 100 个数据库连接进行配置,这将提供 1,000 个数据库连接。 如果应用程序工作负载因用户活动增加或处于高峰时段而缩放,如果再增加 50 个应用程序服务器,数据库连接总共将达到 6,000 个。 通常,在由应用程序服务器生成其中大多数连接后,这些连接将处于空闲状态。 由于空闲连接使用资源(内存和 CPU)以保持打开状态,因此数据库可伸缩性可能会受到影响。

其他潜在的挑战涉及处理与数据库服务器的连接总数。 这是由连接到数据库服务器的应用程序服务器数量决定的,每个服务器都创建了自己的连接集。 在这些场景中,请考虑调整应用程序服务器上的连接池。 尝试将每个池中的连接数减少到可接受的最小值,以确保数据库服务器端的连接没有膨胀现象。 将此操作视为抵消应用程序服务器缩放的影响的短期补救措施,而不是解决应用程序增长的永久解决方案。

作为长期解决方案,在数据库服务器和应用程序服务器之间引入连接代理,例如 ProxySQL 或 Heimdall 代理。 这很有帮助,因为代理将:

  • 使用固定数量的连接建立与数据库服务器的连接。
  • 接受应用程序连接,并充当潜在连接风暴的缓冲区。

代理还可以提供其他功能,例如查询缓存、连接缓冲、查询重写/路由和负载均衡。 为了提高可伸缩性,请考虑使用多个代理实例。

用于容错和快速恢复的连接处理

在设计用于容错和快速恢复的应用程序和环境时,请考虑在数据库环境中,可能会遇到连接中断或硬件故障。 此外,请记住需要执行以下操作:缩放实例大小、修补和执行手动故障转移。

例如,请考虑以下场景:数据库服务器在一分钟内完成了故障转移,但由于一些情况,例如 DNS TTL 在应用程序端太长等,应用程序还会停机几分钟。 在这些情况下,只需减少 TTL 值即可更快地恢复,或者,集成应用程序与数据库服务器之间的连接代理可以帮助处理此类故障。

分区

当生产工作负载使用极其庞大的表时,分区是提高数据库性能和方便维护的好方法。 通过分区,可以更轻松地管理大型表,此方法可以添加和删除分区以有效地管理大型表。 分区还可以通过缓解内部结构争用(每个表或每个索引的内部锁,例如,InnoDB 中的 btr_search_latch)来帮助扩展引擎。

例如,通过添加五个分区,实质上将具有大量活动的大型表分解为五个更小、更有效的表。 这主要有助于主操作是表上的主键查找的情况,这样查询就可以利用“分区修剪”。 但是,在表扫描方面,分区也会有所帮助。

虽然分区具有它的优势,但它也有一些限制,例如缺少对已分区表中的外键的支持、缺少查询缓存等。有关这些限制的完整列表,请参阅 MySQL 参考手册中的有关分区的限制和局限一章。

分离读取和写入

大多数应用程序主要是从数据库读取,只有一小部分的交互涉及写入。 为连接池计算的主数据库的活动连接数可能包括读取流量。 将尽可能多的查询卸载到只读副本,减少对主可写实例的访问,会增加应用程序服务器执行的总体数据库活动量,而不会增加主数据库上的负载。 如果你还没有访问只读副本(至少在报表等长时间运行的查询中),应考虑立即将报告或分析移到只读副本。

对只读副本的更广泛使用可能需要更仔细的考虑,因为由于复制的异步性,复制略微滞后于主要副本。 找出尽可能多的应用程序的区域,这些区域可以随次要代码更改从副本读取一起提供。 还应在与缓存相关的较高级别应用此方法,从专用缓存层(例如 Azure Cache for Redis)提供更多只读或缓慢更改的内容。

写入缩放和分片

随着时间的推移,应用程序不断发展,并且增加了新功能。 出于方便或一般的做法,表会添加到主数据库。 为了处理数据库上不断增长的流量负载,请确定可轻松移动到单独的数据库的应用程序区域,并考虑水平分片或垂直拆分数据库。

水平分片数据库的工作原理是,在不同的数据库中创建应用程序架构的多个副本,并根据客户 ID、地理位置或一些其他每客户或租户属性分离客户和所有相关数据。 这非常适用于 SaaS 或 B2C 应用程序,在这些应用程序中,单个客户很小,而应用程序的负载来自数百万客户的总使用量。 不过,对于 B2B 应用程序来说,这就比较困难了,因为客户的规模不同,个别大型客户可能会主导特定分片的流量负载。

通过在功能上分片数据库来垂直拆分负载,将单独的应用程序域(或微服务)移动到它们自己的数据库。 这会将负载从主数据库分发到单独的每服务数据库。 简单的示例包括日志记录表或站点配置信息,这些信息不需要与高负载订单表位于同一数据库中。 更复杂的示例包括将客户和帐户域与订单或履行域分开。 在某些情况下,这可能需要更改应用程序,例如,修改电子邮件或后台作业队列,使它们成为独立的且不依赖联接回客户或订单表。 可以使用 Azure Database for MySQL 灵活服务器只读副本将现有表和数据移动到新的主数据库,提升副本并将应用程序的各个部分指向新创建的可写数据库。 新创建的数据库需要使用连接池来限制访问,优化查询,并像原来的主数据库一样用自己的副本分散负载。

数据导入配置

  • 在开始数据导入操作之前,可以暂时将实例缩放到较高的 SKU 大小,然后在导入成功时将其纵向缩减。
  • 通过使用将本地 MySQL 迁移到 Azure Database for MySQL 进行联机或脱机迁移,可以以最少的故障时间导入数据。

Azure Database for MySQL 灵活服务器内存建议

Azure Database for MySQL 灵活服务器性能最佳做法是分配足够的 RAM,使工作集几乎完全驻留在内存中。

  • 使用 Azure Database for MySQL 灵活服务器的指标检查使用的内存百分比是否达到限制
  • 设置针对这类值的警报,确保当服务器达到限制时,你可以立即执行操作来修复它。 根据定义的限制,检查是否将数据库 SKU 纵向扩展为更高的计算大小或更好的定价层,从而显著提高性能。
  • 进行纵向扩展,直到缩放操作后性能值不再急剧下降。 有关监视 DB 实例的指标的信息,请参阅 Azure Database for MySQL 灵活服务器 DB 指标

使用 InnoDB 缓冲池预热

重启 Azure Database for MySQL 灵活服务器实例后,驻留在存储中的数据页将在查询表时加载,这会导致第一次执行查询时延迟增加和性能下降。 对于延迟敏感型工作负载,这可能是不可接受的。

利用 InnoDB 缓冲池预热,可以通过在重启之前重新加载缓冲池中的磁盘页来缩短预热时间,而不必等待 DML 或 SELECT 操作访问相应的行。

通过配置 InnoDB 缓冲池服务器参数,可以减少重启 Azure Database for MySQL 灵活服务器实例后的预热时间,这是一种性能优势。 InnoDB 会在服务器关闭时为每个缓冲池保存一定百分比的最近使用的页面,并在服务器启动时还原这些页面。

还需要注意的是,性能的提高是以服务器启动时间的延长为代价的。 启用此参数后,预计服务器启动和重启时间会增加,具体取决于服务器上预配的 IOPS。

我们建议测试和监视重启时间,以确保启动/重启性能是可接受的,因为在此期间服务器不可用。 当预配的 IOPS 小于 1000(或换句话说,当预配的存储小于 335GB)时,不建议使用此参数。

要在服务器关闭时保存缓冲池的状态,请将服务器参数 innodb_buffer_pool_dump_at_shutdown 设置为 ON。 同样,将服务器参数 innodb_buffer_pool_load_at_startup 设置为 ON 以在服务器启动时还原缓冲池状态。 可以通过降低和微调服务器参数 innodb_buffer_pool_dump_pct 的值来控制对启动/重启时间的影响。 默认情况下,此参数设置为 25

注意

仅存储容量最大达 16 TB 的常规用途存储服务器才支持 InnoDB 缓冲池预热参数。 有关详细信息,请参阅 Azure Database for MySQL 灵活服务器存储选项