暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

数据库中断和连接问题的故障排除方法

原创 Tom 2022-11-15
1244

介绍

疑似数据库中断对每个人来说都是一件压力大的事件。用户变得沮丧并担心他们的数据可能会丢失,开发人员争先恐后地寻找原因,公司利益相关者分分钟计算可能导致收入损失的时间。

在发生中断时让您的数据库恢复健康状态是首要任务。然而,在如此压力大的事件中,甚至很难推断出问题可能是什么。本文旨在帮助指导您了解数据库可能出现故障的一些最常见原因,以及您可以采取哪些措施来修复它。

本文涵盖了处理数据库中断时需要注意的各个方面,包括:


问题潜在问题动作
数据库似乎不接受连接数据库用户凭据问题、连接字符串问题、达到连接限制检查数据库服务器日志以确定原因
网络通信似乎受损VPC 和防火墙问题、应用程序和数据库之间的延迟和超时检查防火墙规则,查找延迟和超时,检查耗尽的连接限制
数据库服务器或应用程序服务器崩溃导致数据库服务器和应用程序服务器达到资源限制的潜在数据量问题查找大量返回数据,优化查询,添加索引
数据库服务器已启动但应用程序未显示数据最近可能对代码进行更改,包括架构更改、未应用的迁移、格式错误的查询检查源代码控制历史以查找最近的更改并在必要时恢复


阅读本文的最佳时间是在数据库出现故障之前很久。如果您的数据库已经关闭,那么现在是第二好的时间。

数据库连接问题

来自应用程序日志的线索

如果您的数据库出现故障,您的应用程序日志可能会让您深入了解接受请求或连接到数据库的任何问题。因为应用程序服务器同时处理客户端请求和对数据库的请求,所以如果数据库出现问题,它通常会记录错误。


应用服务器是否成功处理连接?

公开 API 并通过查询数据库为请求提供服务的应用服务器有两种连接:

  • 用户请求应用服务器暴露的API
  • 应用服务器请求数据库

调试中断时,请记住两种连接的问题都可能导致中断。

应用程序服务器框架通常带有内置记录器。一旦服务器启动,通常的做法是记录服务器可以接受连接。

例如,看看这个日志行:


{"level":30,"time":1617808854673,"pid":96741,"hostname":"do-server-1","msg":"Server listening at http://0.0.0.0:8000"}


日志显示服务器已启动并接受端口 8000 的连接。但这不足以确定服务器启动后是否发生错误。

下一步是查看最近的日志并检查对服务器的最近请求的 HTTP 状态代码。通常请求日志如下所示:


{"level":30,"time":1617809865718,"pid":97326,"hostname":"do-server-1","reqId":5,"req":{"method":"POST","url":"/graphql","hostname":"0.0.0.0:3000","remoteAddress":"127.0.0.1","remotePort":53540},"msg":"incoming request"}

{"level":30,"time":1617809865719,"pid":97326,"hostname":"do-server-1","reqId":5,"res":{"statusCode":200},"responseTime":1.1810400485992432,"msg":"request completed"}


每个传入请求日志都包含时间戳、URL 和有关请求的其他信息。第一个日志表示请求进入,而第二个日志显示请求成功,HTTP 状态代码为 200。

最近有数据库错误吗?

由于您正在尝试调试与数据库相关的问题,因此您应该专门查找失败的请求。您可以通过过滤响应状态代码为 5xx(例如 500,表示服务器错误)的请求来找到这些请求。

如果您注意到多个请求都带有 500 状态代码,请查找这些请求的开始点并检查是否有任何其他记录的错误。

如果数据库已关闭或数据库的凭据错误,您可以看到已记录。例如:


Can't reach database server at `db-postgresql-563564.b.db.ondigitalocean.com`:`5432`


上面的日志表明您的应用程序服务器无法访问数据库。在这种情况下,请检查应用程序服务器中的数据库 URL。


数据库问题排查

现在您知道您的应用程序服务器正在运行但无法访问数据库,下一步就是确定原因。最好通过消除问题的潜在来源来解决这个问题。

如果您为数据库使用托管服务,请先检查您的云提供商的状态页面。大多数云提供商都提供了一种方法来检查其基础设施是否正常运行,例如Digital Ocean、Google Cloud Platform和AWS。

一旦排除了云平台的任何问题,接下来要检查的是数据库实例的日志或状态。

托管数据库日志

如果您使用的托管数据库提供程序似乎可以运行,则下一步将是检查特定数据库实例的日志。

除了吞吐量和查询统计数据等一些指标外,大多数云平台都提供了一种查看数据库日志的方法。日志的布局和详细程度因云提供商而异。但是,大多数云提供商都提供了足够的详细信息来帮助您搜索问题。

每个云提供商也有不同的方式来访问数据库日志。大多数使日志可以从部署管理页面轻松访问。

例如,DigitalOcean 提供了一个名为“日志和查询”的选项卡,可直接从部署管理菜单访问。

此部分包含几种不同类型的日志记录信息,包括一般的“最近日志”部分。您可能会发现连接到数据库的问题或可能发生的其他问题的迹象。

DigitalOcean 最近的日志部分

网络问题

与网络相关的问题可能会导致您的数据库不可用或似乎已关闭。在由客户端层、应用程序层(后端)和数据层(数据库)组成的三层应用程序中,三层之间可能会出现网络问题。

与网络相关的问题包括:

  • VPC 和防火墙策略问题
  • 应用程序和数据库之间的延迟和超时

当您的数据库出现故障或无响应,并且您怀疑这可能与网络问题有关时,最好首先确定流量是否被防火墙策略阻止或是否存在实际网络问题。

注意:以下建议基于可能不适用于您的体系结构的假设。因此,建议在调试数据库问题时了解故障模式及其原因。

专有网络

在云平台上配置数据库等云资源时,它们被隔离在一个虚拟私有云(VPC)中。实际上,VPC 充当您的应用程序资源的专用网络,并与公共 Internet 隔离。如果您的数据库和应用程序不在同一个 VPC(或同一个云)中,您通常需要配置 VPC 的防火墙规则以允许应用程序的 IP 访问数据库。

防火墙规则

当您将应用程序和数据库部署到不同的云平台或不同的VPC时,您需要配置防火墙以允许应用程序访问数据库。

虽然某些防火墙策略使用黑洞策略静默丢弃不允许的流量,但其他防火墙策略会发送拒绝的响应,这可以帮助您确定防火墙是否对连接中断负责。同样,如果您遇到“无路由到主机”类型的错误,则可能意味着网段已关闭或路由逻辑不正确。

此外,如果您的应用程序的 IP 是动态的,它可以随时更改。当应用程序的 IP 更改时,它可能无法连接到数据库,直到防火墙更新为允许新的 IP 访问。

防火墙规则补救措施

通常最好将应用程序和数据库部署在同一个 VPC 和同一个区域中,以便两者通过私有网络进行通信。它还可以防止公共网络可能出现的瓶颈。但是,如果这不可能,则有几种可能的修复方法。

第一种方法是为您的应用程序使用专用 IP,并添加允许从该 IP 访问的防火墙规则。此方法可确保您无需更新防火墙规则,因为 IP 保持不变。

如果由于云平台限制或部署方法(例如无服务器)而无法使用专用 IP ,请考虑通过公共网络启用对数据库的访问。虽然这种方法降低了数据库的安全性,但它确保您的应用程序不会突然停机,直到您在应用程序的 IP 更改时更新防火墙规则。此外,您的数据库的身份验证机制仍然是主要的防线。

请注意,不建议从公共互联网打开到您的数据库的连接。在可能的情况下,我们建议将连接限制为特定 IP 地址或使用 VPC 对等技术。

延迟和超时

当应用程序和数据库之间的地理和网络距离很远时,增加的请求延迟和超时错误可能是一个问题。在这种情况下,可能需要增加应用程序中的数据库连接超时以避免超时错误。

ORM和查询构建器持有一个数据库连接池。这些连接通常有一个连接超时配置,控制在建立连接时等待多长时间才会超时。

建议设置初始基线超时值并对应用程序进行负载测试以查看其执行情况。根据负载测试失败请求的数量,您可能需要调整超时并重试,直到您确信超时不是问题的原因。如果您的连接超时配置太低,您将面临这些超时导致请求失败的风险。

耗尽的连接限制

基于连接的数据库(如MySQL和PostgreSQL )的另一个常见挑战是您可以快速耗尽数据库的连接限制。面向连接的数据库对打开的数据库连接数施加了限制。

当您使用传统的长时间运行的流程模型部署您的应用程序时,您可以在池中较少的数据库连接上多路复用许多传入请求。例如,单个服务器实例可能处理 100 个并发 HTTP 请求,池中有 20 个数据库连接。

然而,在无服务器函数上,每个函数实例一次只能处理 1 个 HTTP 请求。因为每个传入请求都需要至少一个到数据库的连接,所以您无法多路复用数据库连接。

鉴于此,建议使用数据库连接限制,然后以不耗尽数据库连接限制的方式在连接到它的服务器实例之间分配这些限制。例如,假设您的数据库的连接限制为 20。如果您有两个应用程序服务器实例,您可能希望将每个服务器实例的连接池设置为最多 10 个连接。

对于无服务器部署,请考虑运行一个外部连接池程序,如 PgBouncer——一个额外的基础设施组件,用于保持与数据库的连接并多路复用来自无服务器功能的传入数据库查询。

数据量问题

随着应用程序的增长,该应用程序的数据量很可能也会增长。性能和数据库正常运行时间的一个关键考虑因素是为满足给定请求而处理的数据量。当总数据量较小时,为应用程序编写的低效查询可能会变成瓶颈,从而降低性能并在数据增长时导致中断。

大数据量可能会在三个位置产生影响:

  • 数据库服务器
  • 应用服务器
  • 客户端

数据库服务器

当从应用程序服务器进行数据库查询时,数据库服务器的职责是检索请求的数据并将其发送回应用程序服务器。为此,数据库服务器必须首先将检索到的数据扫描到自己的内存中。当数据量较小时,将数据扫描到内存并转发到应用服务器的过程是微不足道的。但是,如果从查询返回大量数据,配置不足的数据库服务器可能会在负载下崩溃。

当随着数据大小的增长,最初使用较小的总数据库大小就足够的查询没有得到充分优化时,通常会出现这种情况。

考虑一个应用程序需要为用户显示联系人列表的场景。提供此数据的典型数据库查询可能会选择该用户范围内的数据。


SELECT * from contacts WHERE userId = 123;


根据应用程序的需要,应用程序服务器可能除了将结果转发给客户端之外不需要做任何进一步的事情。此查询不太可能导致数据量问题。

WHERE但是,请考虑如果上述查询中没有子句会发生什么情况。


SELECT * from contacts;


相反,如果查询要求数据库中的所有联系人,然后应用服务器负责userId在将结果转发给客户端之前过滤列表,那么数据量的差异可能是天文数字。

由于总体数据量相对较小,这种不充分的查询可能不会被发现。随着数据量的增长,性能下降可能会变得很明显,但可能不会完全破坏应用程序。然而,当发生这种情况时,数据库服务器的负载将超出其可能配置的范围。随着数据量继续进一步增长,可能会达到数据库服务器不再能够处理负载的临界点。

应用服务器

就像数据库服务器没有无限容量来处理大量数据一样,应用程序服务器也是如此。与数据库服务器相比,您对应用服务器的容量和大小有更多的控制权,但增加应用服务器的容量可能是不必要的。

从数据库服务器返回的大量数据需要时间和资源在应用服务器上进行处理。如果应用服务器正在响应来自客户端应用程序的请求,则应用服务器的长时间等待可能会产生问题。许多云托管提供商会在几分钟后强制执行请求超时。Web 浏览器将在请求处于“待定”状态几分钟后自动重试请求,从而进一步增加系统压力。

客户端

客户端应用程序可能最容易受到大数据量引起的瓶颈的影响。与您可以增加容量的应用程序服务器和数据库服务器不同,在浏览器或移动设备上运行的客户端应用程序会受到浏览器、操作系统或两者的限制。

向客户端应用程序发送大量数据会导致处理延迟,并可能严重降低响应能力。一旦达到给定的数据大小,浏览器可能会完全无响应并最终崩溃。

如果非常大的数据量从数据库一直转发到客户端,那么每一步都会感觉到性能下降。这三连胜将导致加载时间过长,并可能在这些点中的任何一个点出现可感知的中断。使问题更加复杂的是,在存在瓶颈的地方进行故障排除可能会变得困难。

数据大小补救措施

由数据量问题引起的性能下降和中断的修复几乎总是限制从数据库服务器返回的数据量。这样做可以缓解数据库服务器、应用程序服务器和客户端的问题。

WHERE带子句的范围数据

在上面的虚构查询示例中,查询了数据库的整个联系人表。这意味着数据库服务器需要在筛选出所需结果之前将整个表扫描到内存中,这会给数据库服务器和应用程序服务器带来巨大的负载。

首先寻找撒得太宽的查询。这些查询很可能需要很长时间才能在数据库服务器上进行处理。查看长时间运行的查询的日志可以指示发生这种情况的位置。与其返回许多结果然后使用应用程序代码过滤它们,不如构造您的查询以返回真正需要的结果子集。在 SQL 中,使用WHERE子句来具体说明您实际需要的数据。

LIMIT使用and对数据进行分页OFFSET

如果客户端应用程序确实需要大量数据,建议引入分页。

分页是一种设计模式,它限制在给定时间查询和返回的记录总数。如果用户想查看更多记录,他们必须明确请求。

这种设计模式通常使用LIMITandOFFSET子句来实现。通过选择跳过一定数量的记录并限制返回结果的数量,客户端和应用服务器可以实现分页体验。

第一页的查询可能如下所示:


SELECT * from contacts WHERE userId = 123 LIMIT 25 OFFSET 0;


然后,对第二页的查询只需将 的值设置LIMITOFFSET获取下一个“页面”的值。


SELECT * from contacts WHERE userId = 123 LIMIT 25 OFFSET 25;


排查数据量问题

大多数数据库都提供可帮助解决数据量问题的工具。特别是,许多数据库提供了一个EXPLAIN命令,该命令将显示查询的执行计划并提供对任何相关问题的洞察力。

例如,在 PostgreSQL 中,该EXPLAIN命令显示正在考虑的语句的查询计划,并将显示估计的执行成本。这是对运行查询所需时间的估计。

此信息有助于缩小导致瓶颈的特定表或查询语句的范围。

除了手动调用EXPLAIN命令之外,许多云数据库提供商还提供了一种方法来自动可视化导致问题的查询。此信息通常可以在云提供商的“慢速查询”视图中找到。检查您的数据库提供商的慢速查询部分,找出哪些查询可能会对您的应用程序产生不利影响。

添加索引

与大数据量相关的问题通常可以使用索引来修复。

数据库表的索引可以像书中的索引一样概念化。如果您要在一本书中查找有关特定主题的信息,则需要花很长时间通读整本书才能找到它。相反,您可以查阅索引以查找感兴趣的特定主题。如果存在,它将指向书中讨论该主题的特定页面。

同样的概念也适用于数据库索引。根据常见的访问模式向数据库表添加索引可以实现快速查找。

例如,如果您有一个用户数据库表,其中包含一列 foremail并且查询该表以根据他们的电子邮件查找用户,则可以根据该列为该表创建索引有助于提高性能email。如果没有索引,将扫描整个表以通过电子邮件地址查找用户。如果表非常大,这会产生严重的性能问题。但是,如果为该列创建了索引,查找将很快,因为搜索特定电子邮件将立即指向所需的确切行。

向数据库添加索引需要计划和考虑,并且应该在数据库导致应用程序中断之前完成。但是,如果您可以找到导致中断的一个或多个特定查询,则添加索引以立即缓解压力会很有帮助。

中断代码更改

可疑的数据库中断可能会追溯到最近对客户端或服务器代码所做的重大更改。在这些情况下,很可能不是数据库本身遇到了中断,而是用于检索数据、处理数据并将其返回给客户端的代码可能已经损坏。

可能导致中断的代码更改通常分为三类:

  • 数据库查询
  • 服务器代码
  • 客户端代码

数据库查询

对数据库查询的更改,即使很小,也会影响应用程序。如果使用原始SQL,查询语句可能在最近的代码更改中变得无效。如果查询本身仍然有效,则它可能已更改为返回不再可由应用程序的其他部分处理的结果。

检查源代码控制更改以查找最近对数据库访问的更改(SQL 语句或 ORM 使用)。尝试隔离与受影响的应用程序特定区域相关的查询。

如果没有迹象表明数据库访问发生了变化,则另一种可能是数据库架构已更改,但尚未运行迁移。查找可能仍需要应用于生产数据库的任何最新迁移。

客户端和服务器代码

对客户端或服务器中的应用程序代码进行代码更改,即使很小,也可能造成看起来像数据库中断的情况。有许多具体问题可能是问题的根源,但一些示例包括:

  • 客户端可能正在调用不再存在的服务器端点
  • 服务器端点更改了有效负载或查询参数的验证规则
  • 服务器正在尝试从返回的数据访问属性,这些数据因最近的架构更改而变得无效

结论

无论根本原因如何,数据库中断都可能是压力非常大的事件。在匆忙尝试让应用程序恢复运行时,可能很难正确推断出数据库问题可能源自何处。

每次数据库中断都是独一无二的,并且没有一种万能的解决方案。但是,精通可能出现的问题及其相关解决方案可以帮助您更有效地确定问题的原因并减少恢复和运行所需的时间。

与解决大多数问题一样,最好在问题发生之前熟悉潜在的解决方案。我们希望本指南能帮助您实现这一目标。


原文作者:Ryan Chenkie、Daniel Norman

原文标题:Troubleshooting database outages and connection issues

原文链接:https://www.prisma.io/dataguide/managing-databases/database-troubleshooting


「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论