
# 实例使用规范
#### **数据库连接**
RDS for PostgreSQL是进程架构，每个客户端连接都对应一个后端服务进程。
- 根据业务的复杂度，合理配置"max_connections"，例如，参考pgtune：
  - WEB应用："max_connections"配置为 200
  
  - OLTP应用："max_connections"配置为 300
  
  - 数据仓库："max_connections"配置为 40
  
  - 桌面应用："max_connections"配置为 20
  
  - 混合应用："max_connections"配置为 100
   
- 根据业务需要限制单个用户的最大连接数。
  ```
  ALTER ROLE xxx CONNECTION LIMIT xxx;
  ```
  
- 保持合理的活跃连接数，建议活跃连接数为CPU数量的2\~3倍。
- 避免长事务，长事务会阻塞autovacuum等，导致出现性能问题。
- 避免空闲长连接，长连接的缓存可能较大，导致内存不足，建议通过配置idle_session_timeout和idle_in_transaction_session_timeout参数等方式，定期释放长连接。
- 检查应用程序框架，避免应用程序自动begin事务，但不做任何操作。
 
#### **只读实例**
- 避免长事务，长事务容易导致查询冲突，影响回放。
- 对实时性有要求的实例，建议配置"hot_standby_feedback"，同时根据业务设置"max_standby_streaming_delay"为合理的值。
- 监控长事务、长连接和复制延迟，出现问题及时处理。
- 只读实例为单节点，不提供高可用能力，连接只读实例的应用程序应该具备切换到其他节点的能力。
 
#### **可靠性、可用性**
- 生产数据库的实例类型务必选择主备类型。
- 生产数据库的CPU、内存、磁盘要有一定的冗余，正常使用保持在85%以下，防止出现OOM、磁盘满等异常问题。
- 将主、备机部署在不同可用区内，增加可用性。
- 将周期性备份设置到业务低峰期，并且不要关闭全量备份。
- 建议将主备的复制模式设置为"异步"，防止备机故障阻塞主机业务。
- 业务上需要关注临时文件大小与生成速率指标。若临时文件生成过多，会对性能产生影响，并且会拖慢数据库启动，造成业务不可用。
- 业务上应避免在单个实例创建大量对象。一般而言单个实例表个数不宜超过2万，单个数据库中表个数不宜超过4千。防止在数据库启动时，由于扫描表文件耗时过久，导致业务不可用。
 
#### **逻辑复制**
- 创建的逻辑复制槽名需要在40个字节长度以下，否则可能导致全量备份失败。
- 使用逻辑复制时，注意删除不再使用的复制槽，防止数据库膨胀。
- 使用普通逻辑复制槽时，注意主备倒换（规格变更、小版本升级或主机故障等场景可能发生主备倒换）后复制槽会丢失，需要再次创建复制槽。
- RDS for PostgreSQL 12.6及以上的小版本、13和14的所有小版本使用具备故障转移功能复制槽，避免主备倒换或数据库重启后复制槽丢失。
- 使用逻辑复制时，业务尽量避免长事务，废弃的两阶段事务需要及时提交，防止WAL日志积压，占用过高磁盘空间。
- 使用逻辑复制时，尽量避免大量使用子事务（事务内使用savepoint、exception等），防止造成过高的内存占用。
- 使用DRS等服务进行数据同步、迁移时，对于长期无业务的库，建议删除其中包含的逻辑复制槽，或添加心跳表来定期推进复制槽位点，避免WAL日志积压。
 
#### **数据库年龄**
- 数据库年龄的概念：
  - 数据库年龄是PostgreSQL特有的概念，指的是数据库中最旧和最新两个事务ID的差值。
  
  - 由于RDS for PostgreSQL的MVCC机制，数据库年龄上限为20亿，当年龄耗尽，数据库会强制关闭，只能联系技术支持来执行清理操作。
  
  - 可以通过以下SQL查看当前数据库年龄： **select datname, age(datfrozenxid) from pg_database;**
    
   
- 建议通过"db_max_age"CES指标来监控数据库年龄，告警阈值设置为10亿。
 
#### **稳定性**
- 对于两阶段提交的事务，要及时提交或回滚，防止导致数据库膨胀。
- 选择业务低峰期变更表结构，如添加字段，索引操作。
- 业务高峰期创建索引时，建议使用CONCURRENTLY语法，并行创建索引，不堵塞表的DML。
- 业务高峰期修改表结构，要提前进行测试，防止表的REWRITE。
- DDL操作需要设置锁等待超时时间，防止阻塞相关表的操作。
- 单个数据库库容量超过2T，需要考虑分库。
- 频繁访问的表，单表记录超过2000万，或超过10GB，需要考虑分表或创建分区。
- PostgreSQL的备库、只读库单进程回放WAL日志，最大回放速度为50 MB/s\~70 MB/s，因此需要控制主库数据写入压力在50 MB/s以下，避免备机、只读复制异常。
 
#### **日常运维**
- 在实例管理界面下载慢SQL，及时关注并解决性能问题。
- 定期关注数据库的资源使用情况，若业务压力存在较大波动，建议配置资源告警，必要时扩充规格。业务写入压力过大会导致数据库重启恢复过程缓慢，影响业务可用性。
- 删除和修改记录时，需要先执行SELECT，确认无误才能提交执行。
- 大批量删除数据和更新数据时，建议分批次操作，不建议在一个事务中完成。
- 大批量数据删除、更新后，应对被操作表执行VACUUM。
- 关注可用复制槽数以及创建的复制槽，请始终保持至少有一个空余的复制槽可供数据库备份使用，否则数据库备份会失败。
- 及时清理不再使用的复制槽，防止复制槽阻塞日志回收。
- DDL操作之前务必要经过审视，并且选择在低峰期执行，DDL操作以及类似的可能获取锁的操作，（例如VACUUM FULL、CREATE INDEX等）建议设置锁等待，用于防止阻塞所有与该DDL锁对象相关的查询。
  ```
  begin;
  SET local lock_timeout = '10s';  
  -- DDL query;  
  commit;
  ```
  
- 不要使用不记录日志的表（UNLOGGED TABLE），因为在以下场景该表的数据会丢失：
  - 数据库异常（如OOM、底层故障等）
  
  - 主备倒换
  
  - 规格变更
  
  - 小版本升级和大版本升级
  
  - 备份恢复
   
- 尽量避免对系统表做vacuum full操作，若有必要建议使用vacuum；否则执行vacuum full，并重启数据库后，可能导致数据库长时间无法连接。
- EXPLAIN ANALYZE语句的工作方式类似于EXPLAIN，主要区别在于EXPLAIN ANALYZE会实际执行SQL。如果SQL涉及数据变更（UPDATE、INSERT或DELETE），建议在事务中执行EXPLAIN ANALYZE，查看完成后再进行事务回滚。
 
#### **监控告警**
- 建议开启RDS for PostgreSQL云监控功能，对实例的运行状态进行日常监控，详见[支持的监控指标](https://support.huaweicloud.com/usermanual-rds-pg/rds_pg_06_0001.html)。
- 可以根据业务情况配置监控指标阈值，比如CPU、内存、磁盘空间、长事务等。
 
#### **安全**
- 尽量避免数据库被公网访问，公网连接时必须绑定弹性公网IP，设置合适的白名单。
- 尽量使用SSL连接，保证连接的安全性。
 
