诊断Java代码中常见的数据库性能热点问题(5)

发表于:2016-05-04来源:infoq作者:Andreas Grabner and点击数: 标签:数据库
进行大量更新操作的批处理作业的执行需要一段时间才能完成,尤其对于包含大量行的表来说更为明显。如果整张表因此被锁住,那么其他需要对这张表、

  进行大量更新操作的批处理作业的执行需要一段时间才能完成,尤其对于包含大量行的表来说更为明显。如果整张表因此被锁住,那么其他需要对这张表、哪怕只是对其中某些行进行更新的请求都必须等待锁被释放。你应考虑在没有其他用户在线的时间段运行这些作业,或实现某种不同的加锁逻辑,实现对单个行的加锁、更新以及释放操作。

  检查点3:数据库实例的运行状态

  在本文中,我着重分析的数据库性能问题多数与数据库服务器本身是否缓慢是无关的,而主要是由使用了糟糕的数据库访问模式(N+1次查询问题、未经预处理的语句等等)的应用程序代码、或是配置错误(低效的连接池访问、数据驱动问题)所导致的问题。

  但是,如果我们完全忽略了数据库本身,那也是不明智的。因此,我总是会对关键的数据库性能指标进行检查。大多数数据库都会通过特殊的系统表提供丰富的性能信息,比如Oracle就会提供某些v$表以及视图,以访问关键的数据库性能指标(会话、等待时间、解析时间、执行时间等等),或是表锁以及运行时间较慢的SQL等信息,这些信息来自于使用这个共享的数据库实例的各个应用程序。

  我在进行数据库健康检查时通常会观察两个仪表板,你可以在此看到来自于这些性能表中的指标数据:

  (点击放大图像)

  观察数据库是处于健康状态,还是由于共享该数据库实例的应用产生过多的负载而产生了影响。

  (点击放大图像)

  通过表锁等信息,判断是否有某个正在执行中的SQL语句对服务器乃至你的应用造成了负面影响

  在持续集成流程中对数据库指标进行自动检测

  在我为你介绍分析关键数据库指标以及用例的一些新点子之前,我希望首先能够弥补一个缺失的主题,而这一点是我们都应当考虑到的,那就是自动化!

  我建议你不要手动地执行这些检查步骤,而是通过持续集成工具检查这些指标,将这一步骤与单元测试、集成测试、REST API或其他类型的功能性测试等步骤结合在一起。如果你已经设计出一套测试用例集,用于检查各种REST API或新特性的功能,那么为什么不在每次构建的测试执行期间去捕获这些指标呢?这种方式可以带来以下益处:

  让代码评审过程专注于这些指标,而不是翻来覆去地阅读每一行代码

  如果某个代码签入导致了这种问题,则发出通知

  下面这幅屏幕截图展示了每次构建与每次测试时对这些指标的追踪,并在其表现异常时发出警告。你可以将这些指标集成在你的构建管道中,并且当某个代码变更造成影响时通过通知信息了解情况,随后立即修复这一问题,避免当代码发布到生产环境时产生系统崩溃的情况。

  (点击放大图像)

  在你的持续集成流程中加入这些指标,并对指标的变化进行观察,以自动地找出各种糟糕的数据库访问模式!

  性能问题远不止数据库

  在本文中,我们专注的是数据库方面的热点问题。但在我的工作过程中,我也在其他领域发现许多类型的性能问题。在2015年,我参与了一个将一体性应用迁移为(微)服务的项目,在其中发现了一个巨大的峰值问题。该问题类似于我们已分析过的某些模式,例如N+1次查询问题,原因在于某个用例会数百次调用某个后端服务。大多数情况下,这种问题都是由糟糕的接口设计而造成的,并且没有考虑到某个原本在本地调用的方法在Docker容器或云计算环境中被执行时会发生什么。网络问题会突然间出现,包括通过网络传输的信息以及新的连接池(意味着你需要考虑线程与套接字),这些问题是你必须处理的。不过,这方面的内容已经超出了本文的范围,请关注我们的后续文章。“愿指标与你同在” :-)

原文转自:http://www.infoq.com/cn/articles/Diagnosing-Common-Java-Database-Performance-Hotspots