- 最新动态
- 功能总览
-
服务公告
- 漏洞公告
-
产品公告
- 【停售公告】华为云云数据库RDS for PostgreSQL 12版本于2025年5月1日00:00(北京时间)停售通知
- 【下线公告】华为云云数据库RDS for PostgreSQL 10、11版本于2024年11月1日00:00(北京时间)下线通知
- 【停售公告】华为云云数据库RDS for MySQL 5.6版本于2024年7月1日00:00(北京时间)停售通知
- 【停售公告】华为云云数据库RDS for PostgreSQL 10、11版本于2024年7月1日00:00(北京时间)停售通知
- 【下线公告】华为云云数据库RDS for PostgreSQL 9.5、9.6版本于2024年7月1日00:00(北京时间)下线通知
- RDS for MySQL产品公告
- 【通知】2024年5月28日起RDS for MySQL内存加速特性开放公测
- 历史公告
- 产品发布说明
- 产品介绍
- 计费说明
- 快速入门
- 内核介绍
-
用户指南
- RDS for MySQL用户指南
- RDS for MariaDB用户指南
- RDS for PostgreSQL用户指南
- RDS for SQL Server用户指南
-
最佳实践
- RDS最佳实践汇总
- RDS for MySQL
- RDS for PostgreSQL
-
RDS for SQL Server
- 恢复备份文件到RDS for SQL Server实例的版本限制
- 使用导入导出功能将ECS上的SQL Server数据库迁移到RDS for SQL Server
- 修改RDS for SQL Server实例的参数
- RDS SQL Server支持DMV动态管理视图
- 使用导入导出功能将本地SQL Server数据库迁移到RDS for SQL Server
- 在rdsuser主账号下创建子账号
- RDS for SQL Server如何实现异地容灾
- 创建tempdb临时数据文件
- Microsoft SQL Server发布与订阅
- RDS for SQL Server添加c#CLR程序集的使用方法
- RDS for SQL Server添加链接服务器
- RDS for SQL Server 如何将线下SSRS报表服务部署上云
- RDS for SQL Server收缩数据库
- 使用DAS在RDS for SQL Server主备实例上分别创建和配置Agent Job和Dblink
- 创建实例定期维护job
- 使用扩展事件
- 性能白皮书
-
API参考
- 使用前必读
- API概览
- 如何调用API
- API v3.1(推荐)
-
API v3(推荐)
- 查询API版本
- 查询数据库引擎的版本
- 查询数据库规格
- 查询数据库磁盘类型
- 获取磁盘空间使用量
-
实例管理
- 创建数据库实例
- 创建数据库实例(v5接口)
- 按需转包周期
- 停止实例
- 批量停止实例
- 开启实例
- 修改实例名称
- 修改实例备注
- 申请内网域名
- 修改内网域名
- 查询实例域名
- 查询实例IPv6域名
- 获取实例的复制状态
- 查询数据库可变更规格接口
- 变更数据库实例的规格
- 扩容数据库实例的磁盘空间
- 设置自动扩容策略
- 查询自动扩容策略
- 单机转主备实例
- 重启数据库实例
- 删除数据库实例
- 查询数据库实例列表
- 绑定和解绑弹性公网IP
- 切换主备实例的倒换策略
- 手动倒换主备
- 更改主备实例的数据同步方式
- 设置实例读写状态
- 迁移主备实例的备机
- 设置可维护时间段
- 升级内核小版本
- 设置实例内核小版本自动升级策略(PostgreSQL)
- 查询实例内核小版本自动升级策略(PostgreSQL)
- 设置秒级监控策略
- 查询秒级监控策略
- 开启实例TDE(SQL Server)
- 查询实例TDE状态(SQL Server)
- 解除节点只读状态
- 灾备实例
- 数据库安全性
- 备份与恢复
- 大版本升级
- 获取日志信息
- 实例诊断
- SQL限流(PostgreSQL)
- 数据库代理(MySQL)
- 管理数据库和用户(MySQL)
- 管理数据库和用户(PostgreSQL)
- 管理数据库和用户(SQL Server)
- 参数管理
- 插件管理(PostgreSQL)
- 配置只读延迟库(PostgreSQL)
- 回收站
- 标签管理
- 配额管理
- 获取任务信息
- 历史API
- 权限和授权项
- 附录
- SDK参考
- 场景代码示例
-
常见问题
-
产品咨询
- 使用RDS要注意些什么
- RDS实例是否会受其他用户实例的影响
- 不同RDS实例的CPU和内存是否共享
- 创建RDS实例需要多长时间
- 为何使用了RDS后网站登录较慢
- 为什么新购买实例比规格变更实例价格便宜
- 主备同步存在多长时间的延迟
- 多台弹性云服务器是否可以使用同一个RDS数据库
- RDS购买磁盘加密后,备份文件会加密吗
- 什么是RDS实例可用性
- 云数据库RDS支持跨AZ高可用吗
- RDS是否支持主备实例变更为单机实例
- RDS for MySQL与TaurusDB的区别
- 为什么无法找到云数据库RDS实例
- 云数据库RDS是否支持CloudPond
- RDS for MySQL实例支持哪些加密函数
- RDS for MySQL是否兼容MariaDB
- RDS for MySQL是否支持TokuDB
- RDS for MySQL开启GTID后有哪些限制
- RDS for MySQL是否有单表尺寸限制
- 登录RDS实例时能使用加密密码认证吗
- RDS实例内网IP和私有IP的区别
- 找不到我的RDS资源怎么办
- 资源冻结/释放/停止/删除/退订
- 资源及磁盘管理
-
数据库连接
- RDS实例连接失败怎么办
- RDS数据库连接数满的排查思路
- RDS数据库实例支持的最大数据连接数是多少
- 内网方式下ECS无法连接RDS实例的原因
- 客户端问题导致连接RDS实例失败
- 服务端问题导致连接RDS实例失败
- 应用程序是否需要支持自动重连RDS数据库
- RDS绑定公网IP后无法ping通的解决方案
- RDS跨地域内网能访问吗
- 为什么RDS实例重置密码后新密码没有生效
- 可以访问RDS备实例吗
- 如何查看RDS for MySQL数据库的连接情况
- 连接RDS for SQL Server数据库时,连接超时是否会自动退出
- RDS for SQL Server连接不上的判断方法
- 外部服务器能否访问RDS数据库
- ECS内网访问RDS,是否受带宽限制
- Navicat如何配置SSL CA证书
- 如何安装SQL Server Management Studio
- 数据库迁移
-
数据库权限
- RDS的root账号为什么没有super权限
- RDS ManageAccess权限和DAS权限有什么区别
- 本地客户端连接RDS实例后如何查看已授权的数据库
- 使用DAS登录RDS数据库是否有人数限制,密码多次输入错误有无锁死机制
- RDS for MySQL是否支持多账号
- 普通用户在postgres数据库下创建对象失败
- 删除RDS for PostgreSQL数据库中的角色失败
- RDS for PostgreSQL数据迁移过程中由于权限问题导致迁移报错
- 如何给RDS for PostgreSQL数据库中的用户赋予REPLICATION权限
- 更改云数据库 RDS for PostgreSQL数据库中表的OWNER报错
- RDS for SQL Server 2017 企业版主备实例的登录名权限如何同步到只读实例
- RDS for SQL Server中主实例的账号删除重建后,权限是否会自动同步
- 数据库存储
- 数据库基本使用
- 备份与恢复
- 只读实例和读写分离
- 数据库监控
- 扩容及规格变更
-
数据库参数修改
- RDS是否支持使用SQL命令修改全局参数
- 如何修改RDS实例的时区
- 如何设置RDS for MySQL 8.0字符集的编码格式
- 如何设置RDS for MySQL的表名是否区分大小写
- 如何设置RDS for MySQL实例开启查询缓存
- 如何设置RDS for MySQL实例的密码过期策略
- 如何修改RDS for MySQL实例的事务隔离等级
- 如何确保RDS for MySQL数据库字符集正确
- 如何使用utf8mb4字符集存储emoji表情到RDS for MySQL实例
- RDS for PostgreSQL的哪些参数设置不合理会导致数据库不可用
- 如何设置RDS for PostgreSQL实例的临时文件磁盘占用上限
- 如何设置RDS for PostgreSQL实例支持test_decoding插件
- 如何在RDS for SQL Server数据库添加ndf文件的路径
- 如何修改RDS for SQL Server字符集的排序规则
- 日志管理
- 网络安全
- 版本升级
- RDS API&SDK等开发者相关
-
产品咨询
-
故障排除
-
RDS for MySQL
- 备份恢复
- 主备复制
- 参数类
-
性能资源类
- CPU使用率高问题排查与优化
- 内存使用超限风险与优化
- 磁盘性能带宽超上限
- 联合索引设置不当导致慢SQL
- 数据库磁盘满导致被设置read_only
- Binlog未清理导致磁盘占用高
- 业务死锁导致响应变慢
- MySQL只读实例磁盘占用远超主实例
- RDS for MySQL CPU升高定位思路
- 冷热数据问题导致sql执行速度慢
- CPU/内存配置与TPS和QPS性能相关的问题
- 表碎片率过高可能导致的问题
- 复杂查询造成磁盘满
- 怎么解决查询运行缓慢的问题
- 长事务导致规格变更或小版本升级失败
- RDS for MySQL数据库报错Native error 1461的解决方案
- RDS for MySQL增加表字段后出现运行卡顿现象
- 长事务导致UNDO增多引起磁盘空间满
- RDS for MySQL如何定位一直存在的长事务告警
- RDS for MySQL部分SQL的commit时间偶现从几毫秒陡增到几百毫秒
- 本地SSD盘规格降配选不到资源
- ibdata1为什么会变大
-
SQL类
- RDS for MySQL执行SQL报错无法识别双引号
- 更新emoji表情数据报错Error 1366
- 索引长度限制导致修改varchar长度失败
- 建表时timestamp字段默认值无效
- 自增属性AUTO_INCREMENT为什么未在表结构中显示
- 存储过程和相关表字符集不一致导致执行缓慢
- RDS MySQL报错ERROR [1412]的解决方法
- 创建二级索引报错Too many keys specified
- 存在外键的表删除问题
- distinct与group by优化
- 字符集和字符序的默认选择方式
- MySQL创建用户提示服务器错误
- delete大表数据后,再次查询同一张表时出现慢SQL
- 设置事件定时器后未生效
- 为什么有时候用浮点数做等值比较查不到数据
- 开通数据库代理后有大量select请求分发到主节点
- 执行RENAME USER失败的解决方法
- 有外键的表无法删除报错ERROR[1451]的解决方案
- 表字段类型转换失败的解决方法
- RDS for MySQL创建表失败报错Row size too large的解决方案
- RDS for MySQL数据库报错ERROR [1412]的解决方案
- 外键使用不规范导致实例重启失败或执行表操作报错ERROR 1146: Table 'xxx' doesn't exist
- RDS for MySQL在分页查询时报错:Out of sort memory, consider increasing server sort buffer size
- RDS for MySQL创建用户报错:Operation CREATE USER failed
- RDS for MySQL使用grant授权all privileges报语法错误
- RDS for MySQL 5.6版本实例创建表报错
- 无主键表添加自增主键后导致主备节点查询数据不一致
- RDS for MySQL插入数据提示Data too long for column
-
连接类
- 连接数据库报错Access denied
- mariadb-connector SSL方式连接数据库失败
- RDS for MySQL建立连接慢导致客户端超时报connection established slowly
- root账号的ssl_type修改为ANY后无法登录
- 通过DAS登录实例报错Client does not support authentication protocol requested by server
- 通过DAS授权或取消授权时报错Your password does not satisfy the current policy requirements
- 客户端TLS版本与RDS for MySQL不一致导致SSL连接失败
- 使用root账号连接数据库失败
- RDS for MySQL客户端连接实例后会自动断开
- RDS for MySQL实例无法访问
- RDS for MySQL数据库修改authentication_string字段为显示密码后无法登录
- RDS for MySQL升级版本后,导致现有配置无法正常连接到MySQL-server
- 客户端超时参数设置不当导致连接超时退出
- RDS for MySQL在启用了SSL验证连接功能后,导致代码(php/java/python)等连接数据库失败
- istio-citadel证书机制导致每隔45天出现断连
- 数据库版本升级后Navicat客户端登录实例报错1251
-
其他使用问题
- 慢日志显示SQL语句扫描行数为0
- SQL诊断结果中记录的行数远小于慢日志中的扫描行数
- RDS for MySQL慢日志里面有毫秒级别的SQL
- 查看RDS存储空间使用量
- 错误日志报错The table is full
- 审计日志上传策略说明
- 自增字段取值
- 表的自增AUTO_INCREMENT初值与步长
- 表的自增AUTO_INCREMENT超过数据中该字段的最大值加1
- 自增字段值跳变的原因
- 修改表的自增AUTO_INCREMENT值
- 自增主键达到上限,无法插入数据
- 空用户的危害
- pt-osc工具连接RDS for MySQL主备实例卡住
- 购买RDS实例支付报错:Policy doesn't allow bss:order:update to be performed
- RDS for MySQL是否可以修改数据库名称
- 购买RDS实例报错:无IAM的agency相关权限
- RDS for PostgreSQL
- RDS for SQL Server
-
RDS for MySQL
- 视频帮助
- 文档下载
- 通用参考
链接复制成功!
AutoVacuum介绍和调优
vacuum可以理解为清理,是维护高效健康的PostgreSQL数据库的必要步骤,autovacuum是自动化执行vacuum的进程。如果autovacuum的参数配置得和业务比较契合,通常就不用考虑vacuum相关的事宜,数据库会自动替您做好这些事。
本文介绍vacuum的作用,autovacuum和vacuum的关系,autovacuum的参数调优建议,并提供autovacuum常见问题的解答。
为什么要做vacuum
PostgreSQL使用多版本并发控制(MVCC)来保证数据在高并发环境中保持一致和可访问性,每个事务在它开始的时间点都在其自己的数据库快照上运行,这就意味着无法立即删除过时的数据。当进行UPDATE和DELETE操作时,PostgreSQL数据库会为其他正在运行的事务保留旧版本的元组,修改数据库的每个语句都会生成一个事务ID(xid);PostgreSQL UPDATE可以看成是先DELETE然后INSERT。这就会导致数据库出现两个主要问题:事务ID回卷和表膨胀。
事务ID回卷
PostgreSQL会为事务分配一个事务ID,这个事务ID并不是无限大的,PostgreSQL使用一个32位的整数作为事务ID的值,其使用1到2^31轮转的方式来处理无限多的事务,也就是说,当事务ID到达2^31(2147483648)的时候,它将为接下来的事务继续分配1到2^31的事务ID,这种轮转事务ID的方法就是事务ID回卷。
当前的事务ID只能看到其之前的事务ID提交信息,如果当前一个事务ID是100, 当该事务ID达到最大值2^31之后会进行轮转,这样从101到2^31对于当该事务ID来说都是之后的事务ID,此时该事务ID不能看到100以后的所有事务,这样就会导致数据库数据丢失,会造成数据库的不可信。
vacuum freeze可以用来防止事务ID回卷,其意味着覆盖事务ID到frozen事务ID,上面的例子,当前的事务ID100是经历过回卷的,但是使用vacuum freeze将表中对应元组的xmax的值设置为2,那这样所有的事务都能看到该元组。
vacuum freeze同时也会清理死元组。
表膨胀
由于MVCC机制,PostgreSQL的DELETE操作并不会真正删除元组,而是将其标记为已删除状态,这些被标记为删除的元组称为死元组(dead tuples),UPDATE也是同理,可以看成是先DELETE然后再INSERT;由于DELETE并不是真正的删除数据,死元组依旧占用磁盘空间,就会出现虽然查询表数据很少,但是磁盘占用空间很大,这样就会形成表膨胀。
vacuum可以用来解决表膨胀的问题,vacuum会清理死元组,但是并不会重新组织活元组在表上的存储位置,其会维护表的空闲空间映射(FSM)以供接下来的元组INSERT操作从而避免占用更多的空间。
vacuum full则更干脆一些,会对原表进行重建,但是vacuum full会对表进行锁定,在执行vacuum full期间无法对表进行读写操作。同时,如果表的数据量太大,在使用vacuum full时执行时间会很长,请在业务低峰期进行操作。
Autovacuum
Autovacuum是一个能够自动执行vacuum和analyze命令的守护进程,其能够检查数据库中臃肿的表,并回收空间用以重用。autovacuum守护进程被设计成两个进程,autovacuum launcher和autovacuum worker。
autovacuum launcher是在autovacuum参数设置为on时postmaster启动的进程,autovacuum launcher进程用来调度autovacuum worker进程对表进行vacuum操作;autovacuum worker是实际执行vacuum操作的进程,它按照launcher进程的计划连接到数据库并选择某个表执行vacuum操作。
触发autovacuum的条件
当死元组的数量超过一定的值的时候,即死元组数量达到阈值就会触发autovacuum,具体的阈值计算公式如下:
以触发vacuum为例,其中autovacuum_vacuum_scale_factor和autovacuum_vacuum_threshold是PostgreSQL的两个参数。
- number_of_live_tuples是pg_class系统表的“reltuples”字段,可以使用select reltuples from pg_class where relname = '$TBL_NAME'获取。
- 死元组number_of_dead_tuples可以使用select n_dead_tup from pg_stat_user_tables where relname = '$TBL_NAME'获取。
- n_mod_since_analyze是自从上一次auto analyze以来被修改过的元组数量,包括INSERT、UPDATE、DELETE等。
当autovacuum_vacuum_scale_factor为0.2,autovacuum_vacuum_threshold为50,这个表中存活元组数量为2000的时候,能够计算得到的阈值为2000*0.2 + 50 = 450,当number_of_dead_tuples超过450就会触发自动清理。
number_of_dead_tuples > autovacuum_vacuum_scale_factor * number_of_live_tuples + autovacuum_vacuum_threshold
触发auto analyze的条件则是:
n_mod_since_analyze > autovacuum_analyze_threshold + autovacuum_analyze_scale_factor * number_of_live_tuples
当autovacuum_analyze_scale_factor为0.2,autovacuum_analyze_threshold为50,表中存活元组数量为2000的时候,计算阈值为2000 * 0.2 + 5 = 450,当n_mod_since_analyze超过450就会触发auto analyze。
可以通过如下查询来看元组信息和上一次进行autovacuum的时间:
SELECT relname AS tablename, n_live_tup AS livetuples, n_dead_tup AS deadtuples, last_autovacuum, last_autoanalyze FROM pg_stat_user_tables;
系统视图pg_stat_progress_vacuum可以被用来跟踪vacuum的实时状态,由于vacuum full是重写表,所以不会被记录到这个视图中。关于这个视图的详细信息可以查阅官方文档。
当表的年龄大于autovacuum_freeze_max_age时(云上默认是4亿),autovacuum进程会自动对表进行freeze。
数据库年龄一旦超过20亿,数据库会宕机不可用,则不会再接受新事物写入。需要单用户模式执行vacuum full才能修复。
查看数据库年龄:
SELECT datname, age(datfrozenxid) FROM pg_database WHERE datname <> 'template1' AND datname <> 'template0' ORDER BY age DESC;
查看年龄大的5张表:
SELECT relname, relfrozenxid, age(relfrozenxid) aa FROM pg_class WHERE relfrozenxid != 0 ORDER BY aa DESC LIMIT 5;
autovacuum的相关参数
可以通过查询pg_settings系统表来查看autovacuum参数:
select category, name,setting,unit,source,min_val,max_val from pg_settings where category = 'Autovacuum' ; category | name | setting | unit | source | min_val | max_val ------------+-------------------------------------+-----------+------+---------+---------+------------ Autovacuum | autovacuum | on | | default | | Autovacuum | autovacuum_analyze_scale_factor | 0.1 | | default | 0 | 100 Autovacuum | autovacuum_analyze_threshold | 50 | | default | 0 | 2147483647 Autovacuum | autovacuum_freeze_max_age | 200000000 | | default | 100000 | 2000000000 Autovacuum | autovacuum_max_workers | 3 | | default | 1 | 262143 Autovacuum | autovacuum_multixact_freeze_max_age | 400000000 | | default | 10000 | 2000000000 Autovacuum | autovacuum_naptime | 60 | s | default | 1 | 2147483 Autovacuum | autovacuum_vacuum_cost_delay | 2 | ms | default | -1 | 100 Autovacuum | autovacuum_vacuum_cost_limit | -1 | | default | -1 | 10000 Autovacuum | autovacuum_vacuum_scale_factor | 0.2 | | default | 0 | 100 Autovacuum | autovacuum_vacuum_threshold | 50 | | default | 0 | 2147483647
autovacuum的工作量取决于两个参数:
- autovacuum_vacuum_cost_limit是自动清理一次性完成的工作量。
- autovacuum_vacuum_cost_delay是自动清理在达到autovacuum_vacuum_cost_limit参数指定的开销后休眠的毫秒数。
autovacuum常见问题
- 长事务/事务未提交影响autovacuum正常工作
由于MVCC机制,长事务/事务未提交不允许autovacuum清理死元组,如果当前事务在执行删除或更新操作之前拍摄的数据快照,那autovacuum会跳过这些死元组;出现autovacuum不能正常工作的时候应优先排查idle in transaction中的会话。
可以通过如下SQL查询autovacuum进程的锁信息:
select locktype, relation::regclass, pid, mode, granted from pg_locks where pid in($autovacuum_pid);
可以通过如下SQL查询长事务以及等待事件信息:
select pid,wait_event_type,wait_event,state,backend_start,xact_start,query_start,state_change, query from pg_stat_activity where state not in ('idle', 'active');
确认后通过如下SQL杀死该事务:
select pg_terminate_backend(pid);
- 废弃的复制槽影响autovacuum正常工作
复制槽中存储着备机追上主机需要的信息,如果备机宕机或者严重落后于主机,将无法清理在主节点上复制槽中的列。
可以通过如下SQL查询包含旧事务的复制槽:
SELECT slot_name, slot_type, database, xmin, catalog_xmin FROM pg_replication_slots ORDER BY age(xmin), age(catalog_xmin) DESC;
使用pg_drop_replication_slot()删除废弃的复制槽。
- autovacuum时占用资源高,或者经常导致中断
这时一般是由于autovacuum执行次数过于频繁,需要调整参数降低其执行次数:
- 适当增大autovacuum_vacuum_cost_delay和减少autovacuum_vacuum_cost_limit的值。
- 减少autovacuum_max_workers的数量。
如果业务量比较大,可以做定时任务在业务低峰期进行清理,也可以设置定时任务为特殊的表单独设置autovacuum参数。
- 表膨胀的速度加快
在autovacuum正常运行的情况下,如果业务量增加,可能在短时间内产生大量死元组,导致autovacuum跟不上节奏,会导致查询性能下降;可通过修改autovacuum的相关参数进行优化:
- 适量降低autovacuum_vacuum_cost_delay,适量增加autovacuum_vacuum_cost_limit。
- 适量增大autovacuum_max_workers增加并行。
- autovacuum执行卡住或执行很慢
如果autovacuum执行卡住或执行很慢,尝试手动执行vacuum。
- 通过SQL查询autovacuum运行情况,找到autovacuum的PID:
SELECT datname, usename, pid, now() - xact_start AS runtime, query FROM pg_stat_activity WHERE upper(query) LIKE '%VACUUM%' ORDER BY xact_start;
- 多次执行以下命令,判断autovacuum是否正常运行:
SELECT pg_terminate_backend($PID);
确认autovacuum正常运行后,对需要清理的表手动执行vacuum freeze终止autovacuum进程:
verbose选项可选。vacuum freeze verbose $TBL_NAME;
- 通过SQL查询autovacuum运行情况,找到autovacuum的PID: