本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
降低负载
缩短响应时间并增加关键工作流程的可用资源可能需要清除无关的负载。本节介绍的许多解决方案都是权衡决策。它们对应用程序有影响,必须仔细考虑。在以下情况下,考虑使用这些解决方案:
-
您已在使用最大大小的实例,尤其是对于主可写数据库实例。
-
作为最后的手段,在短期内提供足够的空间来实施其他更改。
即时更改包括:
-
将非关键读取流量从主数据库实例中移出。
-
存档或清除旧数据。
-
移除引用完整性。
-
禁用二进制日志(如果正在使用)。
-
推迟非关键提取、转换、加载(ETL)流程。
-
暂停或降级非必要的应用程序功能。
在采取这些行动之前,请根据长期业务目标和风险对其进行评估。
分离读写工作负载
运行由 MySQL 提供支持的应用程序时,一种常见的技术是将读取操作从写入器(主)数据库实例卸载到一个或多个只读数据库副本上。通过卸载读取,您可以减少主数据库实例的总体负载,并为写入操作留出空间。确保仅将不依赖于副本即时read-after-write一致性的读取作为目标。更有效的方法是将所有读取流量转移到副本,并计划 read-after-write在复制延迟时重试。可以卸载一些独立的读取工作负载,如报告服务。其他读取操作需要在应用程序级别进行更改,在此级别发布读取的上下文是众所周知的。
另一种方法是实现数据库代理解决方案,作为应用程序和数据库之间的中介,它可以提供读写分离和查询路由的功能,而无需应用程序感知。ProxySQL
存档或清除旧数据
另一种提高数据库性能的方法是将历史数据卸载到另一个表、数据库或 Amazon Simple Storage Service(Amazon S3)。许多数据库保留了应用程序整个历史记录中的所有内联数据。在正常情况下,在典型的面向用户的应用程序中,这将使用户能够查看其所有历史订单。当需求激增时,应用程序上的许多活跃用户可能是新用户,或专注于下新订单。如果历史数据联机驻留在包含数十亿行的单个表中,情况会更加复杂。该表可能还有较大的索引。表数据和索引都存储在树结构中。在表中拥有更多条目需要树上的更多级别,这需要更多的 I/O 操作才能访问这些行。这会增加查找单个记录的访问时间。更重要的是,它会导致索引中大量不需要的部分驻留在数据库页面缓存(InnoDB 缓冲池)中。
将旧数据存档到单独的表、单独的数据库或 Amazon S3 可以减少最终用户的访问时间,释放宝贵的缓存,提高整体应用程序性能。在事件发生之前存档旧数据(例如,仅保留 30 或 90 天)会限制关键表上的表和索引的大小。这一更改要求对应用程序进行修改,以便仅针对明确要求查看历史数据的一小部分用户,从二级位置查询旧数据。
推迟非关键 ETL 过程
在超大规模条件下,从主数据库系统中提取 ETL 过程可能会给高事务性和并发工作负载带来稳定性风险。ETL 过程具有以下特点:
-
长时间运行的事务
-
宽锁
-
CPU、内存和 I/O 消耗
-
与服务于关键最终用户路径的事务性工作负载争用。
可变或不可预测的 ETL 过程,例如,INSERT INTO ... SELECT FROM ...;) 之类的查询会增加负载和争用的总体可变性,从而增加稳定性风险。
在可能的情况下,推迟或减少 ETL 过程的运行频率,尤其是在它们不提供关键功能的情况下。对于关键 ETL 过程,对其进行修改,使其在有界限的工作单元中运行,例如,处理固定行数的批处理(例如,使用 LIMIT 子句),使用单独的事务,或在较长时间内拉取少量数据以减少数据库实例的峰值资源需求。
关闭不太重要的应用程序功能
在处理激增的请求时,适度降低用户体验或删除非核心功能,可以为关键功能节省数据库资源。这可能需要稍微改变客户体验,但不同的流程总比站点崩溃要好。也许可以暂时禁用总是进行数据库调用的站点首页上的个性化设置。或者,您可以在选择产品时停止向老客户提供定制优惠。暂时关闭功能可以使页面无需访问数据库即可被缓存或传送。
其他示例包括具有轮询机制的前端,用于检查需要数据库调用的数据更改。减少轮询频率将立即减少数据库调用。如果用户界面需要分页,或为用户提供检索排序结果集的选项,而这些结果集又离最前面的结果较远,那么数据库调用的开销就会逐渐增加。限制结果集中的页数,以保护数据库免受开销最大的数据库调用。在应用程序层中使用功能标志,使运营团队能够随着应用程序或数据库负载的增加而关闭或降级功能。