云服务器内容精选

  • 备份恢复 业务高峰时执行备份可能会备份失败,建议手动备份选择在业务低峰期间,自动备份建议根据业务需要自定义备份时间段(默认自动备份时间段为01:00-02:00 (GMT+08:00))。 实例写入业务较多时,建议备份策略设置成每天做一次自动备份。 建议根据业务需要设置备份保留天数(默认保留7天)。 建议根据业务需要设置Binlog本地保留时长(默认为0,表示Binlog备份完成后本地日志会被删除)。 使用表级时间点恢复功能时,建议提前确认所选时间点之前是否有对无主键大表的删除操作,如果有该操作,恢复完成时间不易评估。 创建实例前建议根据需要选择存储类型。 删除实例后,自动备份的全量备份和Binlog备份也会删除,对数据有需要时,建议删除前进行手动全量备份。 建议自定义回收站策略,防止误删实例无法恢复。
  • 数据库实例 数据库实例类型选择 表1 数据库实例类型选择 实例类型 说明 高可用 一主一备的经典高可用架构。适用于大中型企业的生产数据库,覆盖互联网、物联网、零售电商、物流、游戏等行业应用。 备节点提高了实例的可靠性,创建主节点的过程中,同步创建备节点,备节点创建成功后,支持开放可读能力。 当主节点故障后,会发生主备切换,数据库客户端会发生短暂中断,数据库客户端需要支持重新连接。 单机 采用单个数据库节点部署架构,只包含一个节点,但具有高性价比。 适用于个人学习、微型网站以及中小企业的开发测试环境。 单机出现故障后,无法保障及时恢复。 只读 只读实例为单机版只读实例。 购买只读实例时,注意表库名的大小写敏感要与主实例保持一致。 当只读实例与主数据库之间复制异常后,需要较长时间重建和恢复(取决于数据量)。 只读实例创建完成后,可通过time_zone参数修改时区。要求只读实例的时区和主实例一致,否则会导致数据同步异常。 实例性能规格选择 支持独享型实例规格,完全独享的CPU和内存,性能长期稳定,不会因为物理机上其它实例的行为而受到影响,适用于对性能稳定性要求较高的应用场景。
  • SQL设计 查询时指定返回需要的字段,不要返回用不到的字段。 查询或比较字段是否为NULL时,只能使用IS NULL或IS NOT NULL条件。 查询条件中,尽量使用NOT EXISTS替代NOT IN。 聚合数据时,尽量使用UNION ALL代替UNION。 删除数据时,尽量使用TRUNCATE代替全表DELETE。 分批提交大事务中对数据的修改,防止事务提交或回滚时压力集中。 创建函数时,应该定义函数易变性分类为对它们合法的分类中最严格的种类,而不是选择默认的VOLATILE。VOLATILE类函数调用并发过高可能导致新连接无法接入。
  • 索引设计规范 使用逻辑复制时,对需要进行逻辑复制的表设计主键或者唯一键。 使用外键时,一定要设置外键被删除或更新的动作,例如ON DELETE CASCADE。 在使用频繁(如查询、排序)的字段上创建索引。 对于固定条件的查询,建议创建并使用部分索引。 对于经常使用表达式作为查询条件的查询,建议创建并使用表达式索引。 索引也会占用存储,单表索引数量不宜太多,比如单列索引个数小于5,复合索引个数小于3。
  • 备份恢复 业务高峰时执行备份可能会备份失败,建议手动备份选择在业务低峰期间,自动备份建议根据业务需要自定义备份时间段。 实例写入业务较多时,建议备份策略设置成每天做一次自动备份。 建议根据业务需要设置备份保留天数(默认保留7天)。 建议根据业务需要设置Binlog本地保留时长(默认为0,表示Binlog备份完成后本地日志会被删除)。 使用表级时间点恢复功能时,建议提前确认所选时间点之前是否有对无主键大表的删除操作,如果有该操作,恢复完成时间不易评估。 创建实例前建议根据需要选择存储类型,本地盘SSD实例不支持备份恢复到已有实例和当前实例。 删除实例后,自动备份的全量备份和Binlog备份也会删除,对数据有需要时,建议删除前进行手动全量备份。 建议自定义回收站策略,防止误删实例无法恢复。
  • 数据库实例 数据库实例类型选择 主备 一主一备的经典高可用架构。适用于大中型企业的生产数据库,覆盖互联网、物联网、零售电商、物流、游戏等行业应用。 备机提高了实例的可靠性,创建主机的过程中,同步创建备机,备机创建成功后,用户不可见。 当主节点故障后,会发生主备切换,数据库客户端会发生短暂中断,数据库客户端需要支持重新连接。 单机 采用单个数据库节点部署架构,与主流的主备实例相比,它只包含一个节点,但具有高性价比。 适用于个人学习、微型网站以及中小企业的开发测试环境。 单机版出现故障后,无法保障及时恢复。 只读 只读实例分为单机版只读实例和高可用只读实例。 单机版只读实例: 推荐开启数据库代理功能,并购买单机版只读实例。当单个只读故障后,数据库代理可以将流量分担到其它只读节点。 高可用只读实例: 当只读实例所在物理机故障后,备用只读实例自动顶替。 购买只读实例时,注意表库名的大小写敏感要与主实例保持一致。 推荐用法: 主实例下包含2个及以下只读实例时,高可用只读作用比较好。 2个以上只读实例,建议开启数据库代理,获得更好的性价比。 当只读实例与主数据库之间复制异常后,单机版和高可用版只读都需要较长时间重建和恢复(取决于数据量)。 只读实例创建完成后,可通过time_zone参数修改时区。要求只读实例的时区和主实例一致,否则会导致数据同步异常。 实例性能规格选择 独享型 完全独享的CPU和内存,性能长期稳定,不会因为物理机上其它实例的行为而受到影响,适用于对性能稳定性要求较高的应用场景。 通用型 与同一物理机上的其他通用型规格实例共享CPU资源,通过资源复用换取CPU使用率最大化,性价比较高,适用于对性能稳定性要求较低的应用场景。 惠选型 完全独享的CPU和内存,性能长期稳定,不会因为物理机上其它实例的行为而受到影响,适用于对性能稳定性要求较高的应用场景,与独享型相比在价格方面有一定优惠。
  • 日常运维 在实例管理界面下载慢SQL,及时关注并解决性能问题。 定期关注数据库的资源使用情况,若业务压力存在较大波动,建议配置资源告警,必要时扩充规格。业务写入压力过大会导致数据库重启恢复过程缓慢,影响业务可用性。 删除和修改记录时,需要先执行SELECT,确认无误才能提交执行。 大批量数据删除、更新后,应对被操作表执行VACUUM。 关注可用复制槽数以及创建的复制槽,请始终保持至少有一个空余的复制槽可供数据库备份使用,否则数据库备份会失败。 及时清理不再使用的复制槽,防止复制槽阻塞日志回收。 不要使用不记录日志的表(UN LOG GED TABLE),因为该表的数据会在数据库异常(如OOM、底层故障等)或发生主备倒换后丢失。 尽量避免对系统表做vacuum full操作,若有必要建议使用vacuum;否则执行vacuum full,并重启数据库后,可能导致数据库长时间无法连接。
  • 逻辑复制 创建的逻辑复制槽名需要在40个字节长度以下,否则可能导致全量备份失败。 使用逻辑复制时,注意删除不再使用的复制槽,防止数据库膨胀。 使用普通逻辑复制槽时,注意主备倒换(规格变更、小版本升级或主机故障等场景可能发生主备倒换)后复制槽会丢失,需要再次创建复制槽。 RDS for PostgreSQL 12.6及以上的小版本、13和14的所有小版本使用具备故障转移功能复制槽,避免主备倒换或数据库重启后复制槽丢失。 使用逻辑复制时,业务尽量避免长事务,废弃的两阶段事务需要及时提交,防止WAL日志积压,占用过高磁盘空间。 使用逻辑复制时,尽量避免大量使用子事务(事务内使用savepoint、exception等),防止造成过高的内存占用。 使用DRS等服务进行数据同步、迁移时,对于长期无业务的库,建议删除其中包含的逻辑复制槽,或添加心跳表来定期推进复制槽位点,避免WAL日志积压。
  • 数据库连接 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事务,但不做任何操作。
  • 稳定性 对于两阶段提交的事务,要及时提交或回滚,防止导致数据库膨胀。 选择业务低峰期变更表结构,如添加字段,索引操作。 业务高峰期创建索引时,建议使用CONCURRENTLY语法,并行创建索引,不堵塞表的DML。 业务高峰期修改表结构,要提前进行测试,防止表的REWRITE。 DDL操作需要设置锁等待超时时间,防止阻塞相关表的操作。 单个数据库库容量超过2T,需要考虑分库。 频繁访问的表,单表记录过2000万,或超过10GB,需要考虑分表或创建分区。 PostgreSQL的备库、只读库单进程回放WAL日志,最大回放速度为50 MB/s~70 MB/s,因此需要控制主库数据写入压力在50 MB/s以下,避免备机、只读复制异常。
  • 可靠性、可用性 生产数据库的实例类型务必选择主备类型。 生产数据库的CPU、内存、磁盘要有一定的冗余,正常使用保持在85%以下,防止出现OOM、磁盘满等异常问题。 将主、备机部署在不同可用区内,增加可用性。 将周期性备份设置到业务低峰期,并且不要关闭全量备份。 建议将主备的复制模式设置为“异步”,防止备机故障阻塞主机业务。 业务上需要关注临时文件大小与生成速率指标。若临时文件生成过多,会对性能产生影响,并且会拖慢数据库启动,造成业务不可用。 业务上应避免在单个实例创建大量对象。一般而言单个实例表个数不宜超过2万,单个数据库中表个数不宜超过4千。防止在数据库启动时,由于扫描表文件耗时过久,导致业务不可用。
  • 数据库年龄 数据库年龄的概念: 数据库年龄是PostgreSQL特有的概念,指的是数据库中最旧和最新两个事务ID的差值。 由于RDS for PostgreSQL的MVCC机制,数据库年龄最大为20亿,当年龄耗尽,数据库会强制关闭,只能联系技术支持来执行清理操作。 可以通过以下SQL查看当前数据库年龄: select datname, age(datfrozenxid) from pg_database; 建议通过“db_max_age” CES 指标来监控数据库年龄,告警阈值设置为10亿。
  • 数据库命名规范 所有的数据库对象名称(包括库名、表名、列名等)建议以小写字母命名,每个单词之间用下划线分割。 所有的数据库对象名称禁止使用RDS for MariaDB保留关键字。 数据库对象的命名要能做到见名知意,并且不超过32个字符。 数据库中用到的临时表以“tmp”为前缀并以日期为后缀。 数据库中用到的备份表以“bak”为前缀并以日期为后缀。 在不同的库或表中,要保证所有存储相同数据的列名和列类型必须一致。
  • 数据库索引设计规范 限制每张表上的索引数量,建议单张表索引不超过5个。索引并不是越多越好,索引可以提高查询的效率,但会降低写数据的效率。有时不恰当的索引还会降低查询的效率。 禁止给表中的每一列都建立单独的索引。设计良好的联合索引比每一列上的单独索引效率要高出很多。 每个InnoDB表强烈建议有一个主键,且不使用更新频繁的列作为主键,不使用多列主键,不使用UUID、MD5、字符串列作为主键。最好选择值的顺序是连续增长的列作为主键,所以建议选择使用自增ID列作为主键。 建议在下面的列上建立索引: 在SELECT,UPDATE,DELETE语句的WHERE从句上的列。 在ORDER BY,GROUP BY,DISTINCT上的列。 多表JOIN的关联列。 索引列顺序: 区分度最高的列放在联合索引的最左侧。区分度=列中不同值的数量/列的总行数。 尽量把字段长度小的列放在联合索引的最左侧。因为字段长度越小,一页能存储的数据量越大,IO性能也就越好。 使用最频繁的列放到联合索引的左侧。这样可以比较少的建立一些索引。 避免冗余的索引,例如:primary key(id),index(id),unique index(id) 避免重复的索引,例如:index(a,b,c),index(a,b),index(a),由于RDS for MariaDB查询优化器无法确定使用哪个索引,所以重复的和冗余的索引会降低查询效率。 在VARCHAR字段上建立索引时,需指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。 一般对字符串类型数据,长度为20的索引,区分度会高达90%以上,可以使用 count(distinct left(列名, 索引长度))/count(*) 的区分度来确定。 对于频繁查询优先考虑使用覆盖索引。 覆盖索引指包含了所有查询字段的索引,不仅仅是WHERE从句GROUP BY从句中的列,也包含SELECT查询的列组合,避免InnoDB表进行索引的二次查询。 外键约束: 建立外键关系的对应列的字符集必须保持一致或者存在外键关系的子表父表的字符集保持一致。
  • 数据库字段设计规范 优先为表中的每一列选择符合存储需要的最小的数据类型。优先考虑数字类型,其次为日期或二进制类型,最后是字符类型。列的字段类型越大,建立索引占据的空间就越大,导致一个页中的索引越少,造成IO次数增加,从而影响性能。 整数型选择能符合需求的最短列类型,如果为非负数,声明需是无符号(UNSIGNED)类型。 每个字段尽可能具有NOT NULL属性。 避免使用ENUM类型,可以用TINYINT类型替换。修改ENUM值需要使用ALTER语句,ENUM类型的ORDER BY操作效率低,需要额外操作。 如果定义了禁止ENUM的枚举值是数值,可使用其他数据类型(如CHAR类型)。 实数类型使用DECIMAL,禁止使用FLOAT和DOUBLE类型。FLOAT和DOUBLE在存储的时候,存在精度损失的问题,很可能在值的比较时,得到错误的结果。 使用DATETIME、TIMESTAMP类型来存储时间,禁止使用字符串替代。 使用数字类型INT UNSIGNED存储IP地址,用INET_ATON、INET_NTOA可以在IP地址和数字类型之间转换。 VARCHAR类型的长度应该尽可能短。VARCHAR类型虽然在硬盘上是动态长度的,但是在内存中占用的空间是固定的最大长度。 使用VARBINARY存储大小写敏感的变长字符串,VARBINARY默认区分⼤小写,没有字符集概念,速度快。