管理内存用量的最佳实践

本页面介绍了如何为 Cloud SQL 实例配置内存用量。

简介

创建 Cloud SQL 实例时,您可以为该实例选择内存量。随着 PostgreSQL 数据库的工作负载增加,实例的内存用量也会增加。消耗大量内存的实例可能会造成性能瓶颈,有时可能导致内存不足问题。

当 Cloud SQL 实例由于需求增加而耗尽内存时,可能会导致数据库停机。因此,请务必正确配置实例内存以及与内存相关的数据库标志,并监控内存用量,以确保实例运行状况良好。

PostgreSQL 内存大致由两部分组成:

  • 全局内存:所有进程共享此内存以执行查询;例如 shared_buffersmax_connections
  • 本地内存:这是分配给每个连接的专用内存;例如,work_memmaintenance_work_memtemp_buffers

如需了解其他配置注意事项,请参阅一般最佳实践操作指南

内存用量和标志

每当 Cloud SQL 实例的内存用量较高时,可能需要解决以下问题:

  • 哪个查询或进程使用的内存较高?
  • 内存设置是否足以满足数据库活动?
  • 如何更改内存设置?

当 PostgreSQL 数据库运行时,大多数内存用量发生在以下几个方面:

  • 共享缓冲区:这是 PostgreSQL 分配的共享内存,用于保存 readwrite 操作的表数据。对于 read 操作,从磁盘请求的所有数据首先会提取到 RAM,然后再提供给客户端。类似地,在 PostgreSQL 中,请求数据时(例如 SELECT * from emp),它首先从磁盘提取到 shared_buffers 进行缓存,然后再提供给客户端。write 操作也会发生相同的情况。

    共享缓冲区也是所有进程和连接的共享内存区域,用于数据缓存、连接缓存和数据操纵语言 (DML) 操作等数据库活动。此区域可分配的最大值由 shared_buffers 标志指定,默认值为相应实例内存的 33%。shared_buffers 的值越高,内存中缓存的数据量越大。

  • 查询工作内存:运行查询时,PostgreSQL 会为每个操作(例如排序和哈希处理)分配本地内存。在写入临时磁盘文件之前,它可以为查询的每个操作分配的最大值由 work_mem 标志配置,默认值为 4 MB。work_mem 的值越高,内存中可以排序的数据量就越大。
  • 维护工作内存:某些维护操作(例如 VACUUMCREATE INDEXALTER TABLEADD FOREIGN KEY)需要 PostgreSQL 分配单独的本地内存。 这些操作使用的后端进程的最大数量可通过 maintenance_work_mem 标志配置,默认值为 64 MB。请注意,autovacuum 工作器也会使用维护工作内存,并且最大值可以被 autovacuum_work_mem 标志替换。maintenance_work_mem 的值越高,VACUUM 操作的执行速度越快。
  • 临时缓冲区:在数据库会话中使用临时表时,PostgreSQL 会分配临时缓冲区来保存会话局部临时表。最大值可通过 temp_buffers 标志指定,默认值为 8 MB。
  • 数据库连接:当客户端连接到数据库时,PostgreSQL 会创建一个后端进程来传送客户端会话。除了用于运行查询的内存之外,PostgreSQL 还会分配额外的内存来维护系统目录缓存和准备好的查询计划等信息。max_connections 标志可以配置数据库服务器允许的最大并发连接数。每个空闲连接使用大约 2 MB 到 3 MB 的共享内存。 如果 max_connections 的值较高,则实例可以建立更多连接,但会占用更多内存。

如需查看 PostgreSQL 中内存组件的完整列表,请参阅 PostgreSQL 文档。如需更改或修改本部分中列出的标志,请参阅配置数据库标志

监控内存用量

定期在 Cloud Monitoring监控实例的内存,并确保其不超过内存容量上限。一种良好的做法是在 Cloud Monitoring 中设置提醒,以便在内存用量超过容量上限的 90% 并持续 6 小时的情况下发出提醒。当您的内存用量持续接近容量上限时,此提醒可以向您发出警告。

此外,请监控内存不足的突发事件。为此,请为 Cloud Monitoring 中的 server process .* was terminated by signal 9: Killed 消息设置基于日志的指标,以统计内存不足事件,然后在每次发生此类事件时发出提醒。

如果您的实例在运行时持续超出内存容量上限的 90% 或发生内存不足事件,您可以增加实例的内存。或者,您可以通过限制数据库连接数或降低数据库标志(例如 shared_bufferswork_memmax_connections)的值来减少内存用量。降低这些标志的值可能会限制实例的性能。

内存不足

如果内存不足,无法处理数据库工作负载,作为最后的补救手段,底层 Linux 操作系统会使用 out-of-memory (OOM) killer 来结束进程以释放内存。Cloud SQL 经过配置,因此 OOM killer 仅针对 PostgreSQL 工作器进程。在这种情况下,postmaster 进程会被保留,因此只需结束所有现有数据库连接并运行恢复来保护数据库的完整性。如果发生这种情况,可能会出现服务中断和数据库停机的问题。PostgreSQL 数据库日志中会显示如下消息:

2021-10-24 23:34:22.265 UTC [7]: [663-1] db=,user= LOG: server process (PID 1255039) was terminated by signal 9: Killed
2021-10-24 23:34:22.265 UTC [7]: [664-1] db=,user= DETAIL: Failed process was running: SELECT * FROM tab ORDER BY col
2021-10-24 23:34:22.277 UTC [7]: [665-1] db=,user= LOG: terminating any other active server processes
2021-10-24 23:34:22.278 UTC [1255458]: [1-1] db=postgres,user=postgres WARNING: terminating connection because of crash of another server process
2021-10-24 23:34:22.278 UTC [1255458]: [2-1] db=postgres,user=postgres DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
2021-10-24 23:34:22.278 UTC [1255458]: [3-1] db=postgres,user=postgres HINT: In a moment you should be able to reconnect to the database and repeat your command.
2021-10-24 23:34:22.278 UTC [1255458]: [4-1] db=postgres,user=postgres CONTEXT: while updating tuple (27,18) in relation "tab"
...
2021-10-24 23:34:22.558 UTC [1255477]: [1-1] db=postgres,user=postgres FATAL: the database system is in recovery mode
...
2021-10-24 23:34:25.579 UTC [7]: [666-1] db=,user= LOG: all server processes terminated; reinitializing
...
2021-10-24 23:34:25.691 UTC [1255482]: [1-1] db=,user= LOG: database system was interrupted; last known up at 2021-10-24 23:31:53 UTC
2021-10-24 23:34:25.776 UTC [1255482]: [2-1] db=,user= LOG: database system was not properly shut down; automatic recovery in progress
2021-10-24 23:34:25.789 UTC [1255482]: [3-1] db=,user= LOG: redo starts at 227/AB359400
2021-10-24 23:34:38.957 UTC [1255482]: [4-1] db=,user= LOG: redo done at 229/4621F508
2021-10-24 23:34:38.959 UTC [1255482]: [5-1] db=,user= LOG: last completed transaction was at log time 2021-10-24 23:34:18.5535+00
2021-10-24 23:34:39.290 UTC [7]: [667-1] db=,user= LOG: database system is ready to accept connections

后续步骤