directory search
前言 何为PostgreSQL? PostgreSQL简史 格式约定 更多信息 臭虫汇报指导 I. 教程 章1. 从头开始 1.1. 安装 1.2. 体系基本概念 1.3. 创建一个数据库 1.4. 访问数据库 章2. SQL语言 2.1. 介绍 2.2. 概念 2.3. 创建新表 2.4. 向表中添加行 2.5. 查询一个表 2.6. 表间链接 2.7. 聚集函数 2.8. 更新 2.9. 删除 章3. 高级特性 3.1. 介绍 3.2. 视图 3.3. 外键 3.4. 事务 3.5. 窗口函数 3.6. 继承 3.7. 结论 II. SQL语言 章4. SQL语法 4.1. 词法结构 4.2. 值表达式 4.3. 调用函数 章5. 数据定义 5.1. 表的基本概念 5.2. 缺省值 5.3. 约束 5.4. 系统字段 5.5. 修改表 5.6. 权限 5.7. 模式 5.8. 继承 5.9. 分区 5.10. 其它数据库对象 5.11. 依赖性跟踪 章 6. 数据操作 6.1. 插入数据 6.2. 更新数据 6.3. 删除数据 章7. 查询 7.1. 概述 7.2. 表表达式 7.3. 选择列表 7.4. 组合查询 7.5. 行排序 7.6. LIMIT和OFFSET 7.7. VALUES列表 7.8. WITH的查询(公用表表达式) 章8. 数据类型 8.1. 数值类型 8.2. 货币类型 8.3. 字符类型 8.4. 二进制数据类型 8.5. 日期/时间类型 8.6. 布尔类型 8.7. 枚举类型 8.8. 几何类型 8.9. 网络地址类型 8.10. 位串类型 8.11. 文本搜索类型 8.12. UUID类型 8.13. XML类型 8.14. 数组 8.15. 复合类型 8.16. 对象标识符类型 8.17. 伪类型 章 9. 函数和操作符 9.1. 逻辑操作符 9.2. 比较操作符 9.3. 数学函数和操作符 9.4. 字符串函数和操作符 9.5. 二进制字符串函数和操作符 9.6. 位串函数和操作符 9.7. 模式匹配 9.8. 数据类型格式化函数 9.9. 时间/日期函数和操作符 9.10. 支持枚举函数 9.11. 几何函数和操作符 9.12. 网络地址函数和操作符 9.13. 文本检索函数和操作符 9.14. XML函数 9.15. 序列操作函数 9.16. 条件表达式 9.17. 数组函数和操作符 9.18. 聚合函数 9.19. 窗口函数 9.20. 子查询表达式 9.21. 行和数组比较 9.22. 返回集合的函数 9.23. 系统信息函数 9.24. 系统管理函数 9.25. 触发器函数 章10. 类型转换 10.3. 函数 10.2. 操作符 10.1. 概述 10.4. 值存储 10.5. UNION 章11. 索引 11.1. 介绍 11.2. 索引类型 11.3. 多字段索引 11.4. 索引和ORDER BY 11.5. 组合多个索引 11.6. 唯一索引 11.7. 表达式上的索引 11.8. 部分索引 11.9. 操作类和操作簇 11.10. 检查索引的使用 章12. Full Text Search 12.1. Introduction 12.2. Tables and Indexes 12.3. Controlling Text Search 12.4. Additional Features 12.5. Parsers 12.6. Dictionaries 12.7. Configuration Example 12.8. Testing and Debugging Text Search 12.9. GiST and GIN Index Types 12.10. psql Support 12.11. Limitations 12.12. Migration from Pre-8.3 Text Search 章13. 并发控制 13.1. 介绍 13.2. 事务隔离 13.3. 明确锁定 13.4. 应用层数据完整性检查 13.5. 锁和索引 章14. 性能提升技巧 14.1. 使用EXPLAIN 14.2. 规划器使用的统计信息 14.3. 用明确的JOIN语句控制规划器 14.4. 向数据库中添加记录 14.5. 非持久性设置 III. 服务器管理 章15. 安装指导 15.1. 简版 15.2. 要求 15.3. 获取源码 15.4. 升级 15.5. 安装过程 15.6. 安装后的设置 15.7. 支持的平台 15.8. 特殊平台的要求 章16. Installation from Source Code on Windows 16.1. Building with Visual C++ or the Platform SDK 16.2. Building libpq with Visual C++ or Borland C++ 章17. 服务器安装和操作 17.1. PostgreSQL用户帐户 17.2. 创建数据库集群 17.3. 启动数据库服务器 17.4. 管理内核资源 17.5. 关闭服务 17.6. 防止服务器欺骗 17.7. 加密选项 17.8. 用SSL进行安全的TCP/IP连接 17.9. Secure TCP/IP Connections with SSH Tunnels 章18. 服务器配置 18.1. 设置参数 18.2. 文件位置 18.3. 连接和认证 18.4. 资源消耗 18.5. 预写式日志 18.6. 查询规划 18.7. 错误报告和日志 18.8. 运行时统计 18.9. 自动清理 18.10. 客户端连接缺省 18.12. 版本和平台兼容性 18.11. 锁管理 18.13. 预置选项 18.14. 自定义的选项 18.15. 开发人员选项 18.16. 短选项 章19. 用户认证 19.1. pg_hba.conf 文件 19.2. 用户名映射 19.3. 认证方法 19.4. 用户认证 章20. 数据库角色和权限 20.1. 数据库角色 20.2. 角色属性 20.3. 权限 20.4. 角色成员 20.5. 函数和触发器 章21. 管理数据库 21.1. 概述 21.2. 创建一个数据库 21.3. 临时库 21.4. 数据库配置 21.5. 删除数据库 21.6. 表空间 章22. 本土化 22.1. 区域支持 22.2. 字符集支持 章23. 日常数据库维护工作 23.1. Routine Vacuuming日常清理 23.2. 经常重建索引 23.3. 日志文件维护 章24. 备份和恢复 24.1. SQL转储 24.2. 文件系统级别的备份 24.3. 在线备份以及即时恢复(PITR) 24.4. 版本间迁移 章25. 高可用性与负载均衡,复制 25.1. 不同解决方案的比较 25.2. 日志传送备份服务器 25.3. 失效切换 25.4. 日志传送的替代方法 25.5. 热备 章26. 恢复配置 26.1. 归档恢复设置 26.2. 恢复目标设置 26.3. 备服务器设置 章27. 监控数据库的活动 27.1. 标准Unix工具 27.2. 统计收集器 27.3. 查看锁 27.4. 动态跟踪 章28. 监控磁盘使用情况 28.1. 判断磁盘的使用量 28.2. 磁盘满导致的失效 章29. 可靠性和预写式日志 29.1. 可靠性 29.2. 预写式日志(WAL) 29.3. 异步提交 29.4. WAL配置 29.5. WAL内部 章30. Regression Tests 30.1. Running the Tests 30.2. Test Evaluation 30.3. Variant Comparison Files 30.4. Test Coverage Examination IV. 客户端接口 章31. libpq-C库 31.1. 数据库联接函数 31.2. 连接状态函数 31.3. 命令执行函数 31.4. 异步命令处理 31.5. 取消正在处理的查询 31.6. 捷径接口 31.7. 异步通知 31.8. 与COPY命令相关的函数 31.9. Control Functions 控制函数 31.10. 其他函数 31.11. 注意信息处理 31.12. 事件系统 31.13. 环境变量 31.14. 口令文件 31.15. 连接服务的文件 31.16. LDAP查找连接参数 31.17. SSL支持 31.18. 在多线程程序里的行为 31.19. 制作libpq程序 31.20. 例子程序 章32. 大对象 32.1. 介绍 32.2. 实现特点 32.3. 客户端接口 32.4. 服务器端函数 32.5. 例子程序 章33. ECPG - Embedded SQL in C 33.1. The Concept 33.2. Connecting to the Database Server 33.3. Closing a Connection 33.4. Running SQL Commands 33.5. Choosing a Connection 33.6. Using Host Variables 33.7. Dynamic SQL 33.8. pgtypes library 33.9. Using Descriptor Areas 33.10. Informix compatibility mode 33.11. Error Handling 33.12. Preprocessor directives 33.13. Processing Embedded SQL Programs 33.14. Library Functions 33.15. Internals 章34. 信息模式 34.1. 关于这个模式 34.2. 数据类型 34.3. information_schema_catalog_name 34.4. administrable_role_authorizations 34.5. applicable_roles 34.6. attributes 34.7. check_constraint_routine_usage 34.8. check_constraints 34.9. column_domain_usage 34.10. column_privileges 34.11. column_udt_usage 34.12. 字段 34.13. constraint_column_usage 34.14. constraint_table_usage 34.15. data_type_privileges 34.16. domain_constraints 34.18. domains 34.17. domain_udt_usage 34.19. element_types 34.20. enabled_roles 34.21. foreign_data_wrapper_options 34.22. foreign_data_wrappers 34.23. foreign_server_options 34.24. foreign_servers 34.25. key_column_usage 34.26. parameters 34.27. referential_constraints 34.28. role_column_grants 34.29. role_routine_grants 34.30. role_table_grants 34.31. role_usage_grants 34.32. routine_privileges 34.33. routines 34.34. schemata 34.35. sequences 34.36. sql_features 34.37. sql_implementation_info 34.38. sql_languages 34.39. sql_packages 34.40. sql_parts 34.41. sql_sizing 34.42. sql_sizing_profiles 34.43. table_constraints 34.44. table_privileges 34.45. tables 34.46. triggered_update_columns 34.47. 触发器 34.48. usage_privileges 34.49. user_mapping_options 34.50. user_mappings 34.51. view_column_usage 34.52. view_routine_usage 34.53. view_table_usage 34.54. 视图 V. 服务器端编程 章35. 扩展SQL 35.1. 扩展性是如何实现的 35.2. PostgreSQL类型系统 35.3. User-Defined Functions 35.4. Query Language (SQL) Functions 35.5. Function Overloading 35.6. Function Volatility Categories 35.7. Procedural Language Functions 35.8. Internal Functions 35.9. C-Language Functions 35.10. User-Defined Aggregates 35.11. User-Defined Types 35.12. User-Defined Operators 35.13. Operator Optimization Information 35.14. Interfacing Extensions To Indexes 35.15. 用C++扩展 章36. 触发器 36.1. 触发器行为概述 36.3. 用 C 写触发器 36.2. 数据改变的可视性 36.4. 一个完整的例子 章37. 规则系统 37.1. The Query Tree 37.2. 视图和规则系统 37.3. 在INSERT,UPDATE和DELETE上的规则 37.4. 规则和权限 37.5. 规则和命令状态 37.6. 规则与触发器得比较 章38. Procedural Languages 38.1. Installing Procedural Languages 章39. PL/pgSQL - SQL过程语言 39.1. 概述 39.2. PL/pgSQL的结构 39.3. 声明 39.4. 表达式 39.5. 基本语句 39.6. 控制结构 39.7. 游标 39.8. 错误和消息 39.9. 触发器过程 39.10. PL/pgSQL Under the Hood 39.11. 开发PL/pgSQL的一些提示 39.12. 从OraclePL/SQL 进行移植 章40. PL/Tcl - Tcl Procedural Language 40.1. Overview 40.2. PL/Tcl Functions and Arguments 40.3. Data Values in PL/Tcl 40.4. Global Data in PL/Tcl 40.5. Database Access from PL/Tcl 40.6. Trigger Procedures in PL/Tcl 40.7. Modules and the unknown command 40.8. Tcl Procedure Names 章41. PL/Perl - Perl Procedural Language 41.1. PL/Perl Functions and Arguments 41.2. Data Values in PL/Perl 41.3. Built-in Functions 41.4. Global Values in PL/Perl 41.6. PL/Perl Triggers 41.5. Trusted and Untrusted PL/Perl 41.7. PL/Perl Under the Hood 章42. PL/Python - Python Procedural Language 42.1. Python 2 vs. Python 3 42.2. PL/Python Functions 42.3. Data Values 42.4. Sharing Data 42.5. Anonymous Code Blocks 42.6. Trigger Functions 42.7. Database Access 42.8. Utility Functions 42.9. Environment Variables 章43. Server Programming Interface 43.1. Interface Functions Spi-spi-connect Spi-spi-finish Spi-spi-push Spi-spi-pop Spi-spi-execute Spi-spi-exec Spi-spi-execute-with-args Spi-spi-prepare Spi-spi-prepare-cursor Spi-spi-prepare-params Spi-spi-getargcount Spi-spi-getargtypeid Spi-spi-is-cursor-plan Spi-spi-execute-plan Spi-spi-execute-plan-with-paramlist Spi-spi-execp Spi-spi-cursor-open Spi-spi-cursor-open-with-args Spi-spi-cursor-open-with-paramlist Spi-spi-cursor-find Spi-spi-cursor-fetch Spi-spi-cursor-move Spi-spi-scroll-cursor-fetch Spi-spi-scroll-cursor-move Spi-spi-cursor-close Spi-spi-saveplan 43.2. Interface Support Functions Spi-spi-fname Spi-spi-fnumber Spi-spi-getvalue Spi-spi-getbinval Spi-spi-gettype Spi-spi-gettypeid Spi-spi-getrelname Spi-spi-getnspname 43.3. Memory Management Spi-spi-palloc Spi-realloc Spi-spi-pfree Spi-spi-copytuple Spi-spi-returntuple Spi-spi-modifytuple Spi-spi-freetuple Spi-spi-freetupletable Spi-spi-freeplan 43.4. Visibility of Data Changes 43.5. Examples VI. 参考手册 I. SQL命令 Sql-abort Sql-alteraggregate Sql-alterconversion Sql-alterdatabase Sql-alterdefaultprivileges Sql-alterdomain Sql-alterforeigndatawrapper Sql-alterfunction Sql-altergroup Sql-alterindex Sql-alterlanguage Sql-alterlargeobject Sql-alteroperator Sql-alteropclass Sql-alteropfamily Sql-alterrole Sql-alterschema Sql-altersequence Sql-alterserver Sql-altertable Sql-altertablespace Sql-altertsconfig Sql-altertsdictionary Sql-altertsparser Sql-altertstemplate Sql-altertrigger Sql-altertype Sql-alteruser Sql-alterusermapping Sql-alterview Sql-analyze Sql-begin Sql-checkpoint Sql-close Sql-cluster Sql-comment Sql-commit Sql-commit-prepared Sql-copy Sql-createaggregate Sql-createcast Sql-createconstraint Sql-createconversion Sql-createdatabase Sql-createdomain Sql-createforeigndatawrapper Sql-createfunction Sql-creategroup Sql-createindex Sql-createlanguage Sql-createoperator Sql-createopclass Sql-createopfamily Sql-createrole Sql-createrule Sql-createschema Sql-createsequence Sql-createserver Sql-createtable Sql-createtableas Sql-createtablespace Sql-createtsconfig Sql-createtsdictionary Sql-createtsparser Sql-createtstemplate Sql-createtrigger Sql-createtype Sql-createuser Sql-createusermapping Sql-createview Sql-deallocate Sql-declare Sql-delete Sql-discard Sql-do Sql-dropaggregate Sql-dropcast Sql-dropconversion Sql-dropdatabase Sql-dropdomain Sql-dropforeigndatawrapper Sql-dropfunction Sql-dropgroup Sql-dropindex Sql-droplanguage Sql-dropoperator Sql-dropopclass Sql-dropopfamily Sql-drop-owned Sql-droprole Sql-droprule Sql-dropschema Sql-dropsequence Sql-dropserver Sql-droptable Sql-droptablespace Sql-droptsconfig Sql-droptsdictionary Sql-droptsparser Sql-droptstemplate Sql-droptrigger Sql-droptype Sql-dropuser Sql-dropusermapping Sql-dropview Sql-end Sql-execute Sql-explain Sql-fetch Sql-grant Sql-insert Sql-listen Sql-load Sql-lock Sql-move Sql-notify Sql-prepare Sql-prepare-transaction Sql-reassign-owned Sql-reindex Sql-release-savepoint Sql-reset Sql-revoke Sql-rollback Sql-rollback-prepared Sql-rollback-to Sql-savepoint Sql-select Sql-selectinto Sql-set Sql-set-constraints Sql-set-role Sql-set-session-authorization Sql-set-transaction Sql-show Sql-start-transaction Sql-truncate Sql-unlisten Sql-update Sql-vacuum Sql-values II. 客户端应用程序 App-clusterdb App-createdb App-createlang App-createuser App-dropdb App-droplang App-dropuser App-ecpg App-pgconfig App-pgdump App-pg-dumpall App-pgrestore App-psql App-reindexdb App-vacuumdb III. PostgreSQL服务器应用程序 App-initdb App-pgcontroldata App-pg-ctl App-pgresetxlog App-postgres App-postmaster VII. 内部 章44. PostgreSQL内部概览 44.1. 查询路径 44.2. 连接是如何建立起来的 44.3. 分析器阶段 44.4. ThePostgreSQL规则系统 44.5. 规划器/优化器 44.6. 执行器 章45. 系统表 45.1. 概述 45.2. pg_aggregate 45.3. pg_am 45.4. pg_amop 45.5. pg_amproc 45.6. pg_attrdef 45.7. pg_attribute 45.8. pg_authid 45.9. pg_auth_members 45.10. pg_cast 45.11. pg_class 45.12. pg_constraint 45.13. pg_conversion 45.14. pg_database 45.15. pg_db_role_setting 45.16. pg_default_acl 45.17. pg_depend 45.18. pg_description 45.19. pg_enum 45.20. pg_foreign_data_wrapper 45.21. pg_foreign_server 45.22. pg_index 45.23. pg_inherits 45.24. pg_language 45.25. pg_largeobject 45.26. pg_largeobject_metadata 45.27. pg_namespace 45.28. pg_opclass 45.29. pg_operator 45.30. pg_opfamily 45.31. pg_pltemplate 45.32. pg_proc 45.33. pg_rewrite 45.34. pg_shdepend 45.35. pg_shdescription 45.36. pg_statistic 45.37. pg_tablespace 45.38. pg_trigger 45.39. pg_ts_config 45.40. pg_ts_config_map 45.41. pg_ts_dict 45.42. pg_ts_parser 45.43. pg_ts_template 45.44. pg_type 45.45. pg_user_mapping 45.46. System Views 45.47. pg_cursors 45.48. pg_group 45.49. pg_indexes 45.50. pg_locks 45.51. pg_prepared_statements 45.52. pg_prepared_xacts 45.53. pg_roles 45.54. pg_rules 45.55. pg_settings 45.56. pg_shadow 45.57. pg_stats 45.58. pg_tables 45.59. pg_timezone_abbrevs 45.60. pg_timezone_names 45.61. pg_user 45.62. pg_user_mappings 45.63. pg_views 章46. Frontend/Backend Protocol 46.1. Overview 46.2. Message Flow 46.3. Streaming Replication Protocol 46.4. Message Data Types 46.5. Message Formats 46.6. Error and Notice Message Fields 46.7. Summary of Changes since Protocol 2.0 47. PostgreSQL Coding Conventions 47.1. Formatting 47.2. Reporting Errors Within the Server 47.3. Error Message Style Guide 章48. Native Language Support 48.1. For the Translator 48.2. For the Programmer 章49. Writing A Procedural Language Handler 章50. Genetic Query Optimizer 50.1. Query Handling as a Complex Optimization Problem 50.2. Genetic Algorithms 50.3. Genetic Query Optimization (GEQO) in PostgreSQL 50.4. Further Reading 章51. 索引访问方法接口定义 51.1. 索引的系统表记录 51.2. 索引访问方法函数 51.3. 索引扫描 51.4. 索引锁的考量 51.5. 索引唯一性检查 51.6. 索引开销估计函数 章52. GiST Indexes 52.1. Introduction 52.2. Extensibility 52.3. Implementation 52.4. Examples 52.5. Crash Recovery 章53. GIN Indexes 53.1. Introduction 53.2. Extensibility 53.3. Implementation 53.4. GIN tips and tricks 53.5. Limitations 53.6. Examples 章54. 数据库物理存储 54.1. 数据库文件布局 54.2. TOAST 54.3. 自由空间映射 54.4. 可见映射 54.5. 数据库分页文件 章55. BKI后端接口 55.1. BKI 文件格式 55.2. BKI命令 55.3. 系统初始化的BKI文件的结构 55.4. 例子 章56. 规划器如何使用统计信息 56.1. 行预期的例子 VIII. 附录 A. PostgreSQL错误代码 B. 日期/时间支持 B.1. 日期/时间输入解析 B.2. 日期/时间关键字 B.3. 日期/时间配置文件 B.4. 日期单位的历史 C. SQL关键字 D. SQL Conformance D.1. Supported Features D.2. Unsupported Features E. Release Notes Release-0-01 Release-0-02 Release-0-03 Release-1-0 Release-1-01 Release-1-02 Release-1-09 Release-6-0 Release-6-1 Release-6-1-1 Release-6-2 Release-6-2-1 Release-6-3 Release-6-3-1 Release-6-3-2 Release-6-4 Release-6-4-1 Release-6-4-2 Release-6-5 Release-6-5-1 Release-6-5-2 Release-6-5-3 Release-7-0 Release-7-0-1 Release-7-0-2 Release-7-0-3 Release-7-1 Release-7-1-1 Release-7-1-2 Release-7-1-3 Release-7-2 Release-7-2-1 Release-7-2-2 Release-7-2-3 Release-7-2-4 Release-7-2-5 Release-7-2-6 Release-7-2-7 Release-7-2-8 Release-7-3 Release-7-3-1 Release-7-3-10 Release-7-3-11 Release-7-3-12 Release-7-3-13 Release-7-3-14 Release-7-3-15 Release-7-3-16 Release-7-3-17 Release-7-3-18 Release-7-3-19 Release-7-3-2 Release-7-3-20 Release-7-3-21 Release-7-3-3 Release-7-3-4 Release-7-3-5 Release-7-3-6 Release-7-3-7 Release-7-3-8 Release-7-3-9 Release-7-4 Release-7-4-1 Release-7-4-10 Release-7-4-11 Release-7-4-12 Release-7-4-13 Release-7-4-14 Release-7-4-15 Release-7-4-16 Release-7-4-17 Release-7-4-18 Release-7-4-19 Release-7-4-2 Release-7-4-20 Release-7-4-21 Release-7-4-22 Release-7-4-23 Release-7-4-24 Release-7-4-25 Release-7-4-26 Release-7-4-27 Release-7-4-28 Release-7-4-29 Release-7-4-3 Release-7-4-30 Release-7-4-4 Release-7-4-5 Release-7-4-6 Release-7-4-7 Release-7-4-8 Release-7-4-9 Release-8-0 Release-8-0-1 Release-8-0-10 Release-8-0-11 Release-8-0-12 Release-8-0-13 Release-8-0-14 Release-8-0-15 Release-8-0-16 Release-8-0-17 Release-8-0-18 Release-8-0-19 Release-8-0-2 Release-8-0-20 Release-8-0-21 Release-8-0-22 Release-8-0-23 Release-8-0-24 Release-8-0-25 Release-8-0-26 Release-8-0-3 Release-8-0-4 Release-8-0-5 Release-8-0-6 Release-8-0-7 Release-8-0-8 Release-8-0-9 Release-8-1 Release-8-1-1 Release-8-1-10 Release-8-1-11 Release-8-1-12 Release-8-1-13 Release-8-1-14 Release-8-1-15 Release-8-1-16 Release-8-1-17 Release-8-1-18 Release-8-1-19 Release-8-1-2 Release-8-1-20 Release-8-1-21 Release-8-1-22 Release-8-1-23 Release-8-1-3 Release-8-1-4 Release-8-1-5 Release-8-1-6 Release-8-1-7 Release-8-1-8 Release-8-1-9 Release-8-2 Release-8-2-1 Release-8-2-10 Release-8-2-11 Release-8-2-12 Release-8-2-13 Release-8-2-14 Release-8-2-15 Release-8-2-16 Release-8-2-17 Release-8-2-18 Release-8-2-19 Release-8-2-2 Release-8-2-20 Release-8-2-21 Release-8-2-3 Release-8-2-4 Release-8-2-5 Release-8-2-6 Release-8-2-7 Release-8-2-8 Release-8-2-9 Release-8-3 Release-8-3-1 Release-8-3-10 Release-8-3-11 Release-8-3-12 Release-8-3-13 Release-8-3-14 Release-8-3-15 Release-8-3-2 Release-8-3-3 Release-8-3-4 Release-8-3-5 Release-8-3-6 Release-8-3-7 Release-8-3-8 Release-8-3-9 Release-8-4 Release-8-4-1 Release-8-4-2 Release-8-4-3 Release-8-4-4 Release-8-4-5 Release-8-4-6 Release-8-4-7 Release-8-4-8 Release-9-0 Release-9-0-1 Release-9-0-2 Release-9-0-3 Release-9-0-4 F. 额外提供的模块 F.1. adminpack F.2. auto_explain F.3. btree_gin F.4. btree_gist F.5. chkpass F.6. citext F.7. cube F.8. dblink Contrib-dblink-connect Contrib-dblink-connect-u Contrib-dblink-disconnect Contrib-dblink Contrib-dblink-exec Contrib-dblink-open Contrib-dblink-fetch Contrib-dblink-close Contrib-dblink-get-connections Contrib-dblink-error-message Contrib-dblink-send-query Contrib-dblink-is-busy Contrib-dblink-get-notify Contrib-dblink-get-result Contrib-dblink-cancel-query Contrib-dblink-get-pkey Contrib-dblink-build-sql-insert Contrib-dblink-build-sql-delete Contrib-dblink-build-sql-update F.9. dict_int F.10. dict_xsyn F.11. earthdistance F.12. fuzzystrmatch F.13. hstore F.14. intagg F.15. intarray F.16. isn F.17. lo F.18. ltree F.19. oid2name F.20. pageinspect F.21. passwordcheck F.22. pg_archivecleanup F.23. pgbench F.24. pg_buffercache F.25. pgcrypto F.26. pg_freespacemap F.27. pgrowlocks F.28. pg_standby F.29. pg_stat_statements F.30. pgstattuple F.31. pg_trgm F.32. pg_upgrade F.33. seg F.34. spi F.35. sslinfo F.36. tablefunc F.37. test_parser F.38. tsearch2 F.39. unaccent F.40. uuid-ossp F.41. vacuumlo F.42. xml2 G. 外部项目 G.1. 客户端接口 G.2. 过程语言 G.3. 扩展 H. The Source Code Repository H.1. Getting The Source Via Git I. 文档 I.1. DocBook I.2. 工具集 I.3. 制作文档 I.4. 文档写作 I.5. 风格指导 J. 首字母缩略词 参考书目 Bookindex Index
characters

24.3. 在线备份以及即时恢复(PITR)

在任何时候,PostgreSQL都在集群的数据目录的pg_xlog/子目录里维护着一套预写日志(WAL)。 这些日志记录着每一次对数据库的修改细节。 这些日志存在是为了防止崩溃: 如果系统崩溃,数据库可以通过"重放"上次检查点以来的日志记录以恢复数据库的完整性。 但是,日志的存在让它还可以用于第三种备份数据库的策略: 我们可以组合文件系统备份与WAL文件的备份。 如果需要恢复,我们就恢复文件系统备份,然后重放备份了的WAL文件, 把系统恢复到当前的状态。这个方法对管理员来说,明显比以前的方法更复杂, 但是有非常明显的优势:

  • 在开始的时候我们不需要一个非常完美的一致的文件系统备份。 任何备份内部的不一致都会被日志重放动作修改正确(这个和崩溃恢复时发生的事情没什么区别)。 因此我们不需要文件系统快照的功能,只需要tar或者类似的归档工具。

  • 因为我们可以把无限长的WAL文件序列连接起来, 所以连续的备份简化为连续地对WAL文件归档来实现。 这个功能对大数据库特别有用,因为大数据库的全备份可能并不方便。

  • 没必要重放WAL记录的时候我们必须重放到结尾。 我们可以在任意点停止重放,这样就有一个在任意时间的数据库一致的快照。 因此,这个技术支持即时恢复: 我们可以把数据库恢复到你开始备份以来的任意时刻的状态。

  • 如果我们持续把WAL文件序列填充给其它装载了同样的基础备份文件的机器, 我们就有了一套热备份系统:在任何点我们都可以启动第二台机器, 而它拥有近乎当前的数据库拷贝。

Note: pg_dumppg_dumpall不产生 文件系统级别的备份,而且不能作为在线备份解决方案的一部分。像logical这样的转储, 在重现WAL时不会包含足够的信息。

和简单的文件系统备份技术一样,这个方法只能支持整个数据库集群的恢复, 而不是一个子集。同样,它还要求大量的归档存储:基础备份量可能很大, 而且忙碌的系统将生成许多兆需要备份的的WAL流量。 但是,它仍然时在需要高可靠性的场合下的最好的备份技术。

要想从在线备份中成功恢复(也叫"在线备份"),你需要一套连续的WAL归档文件, 它们最远回朔到你开始备份的时刻。因此,要想开始备份, 你应该在开始第一次基础备份之前根据我们讨论过的归档WAL文件机制设置并测试你的步骤。

24.3.1. 设置WAL归档

抽像来看,一个运行着的PostgreSQL系统生成一个无限长的WAL日志序列。 系统物理上把这个序列分隔成WAL段文件,通常每段16M(在编译PostgreSQL的时候可以改变其大小)。 这些段文件的名字是数值命名的, 这些数值反映他们在抽取出来的WAL序列中的位置。 在不适用WAL归档的时候,系统通常只是创建几个段文件然后"循环"使用它们, 方法是把不再使用的段文件的名字重命名为更高的段编号。 系统假设那些内容比前一次检查点更老的段文件已经没用了,然后就可以循环利用。

在归档WAL数据的时候,我们希望在每个段文件填充满之后捕获之, 并且把这些数据在段文件被循环利用之前保存在某处。 根据应用以及可用的硬件的不同,我们可以有许多不同的方法"把数据保存在某处": 我们可以把段文件拷贝到一个NFS挂载的目录,把它们放到另外一台机器上, 或者把它们写入磁带机里(需要保证你有办法把文件恢复为原名), 或者把它们打成包,烧录到CD里,或者是其它的什么方法。 为了给数据库管理员提供最大可能性的灵活性,PostgreSQL试图不对如何归档做任何假设。 取而代之的是, PostgreSQL 让管理员声明一个shell命令执行来拷贝一个完整的段文件到它需要去的地方。 该命令可以简单得就是一个cp,或者它可以调用一个复杂的shell脚本, 这些都由管理员决定。

为了使WAL归档,设置wal_level对archive(或hot_standby) 配置参数,archive_mode为on 所使用的shell命令由配置参数archive_command声明, 它实际上总是放在postgresql.conf文件里的。 在archive_command里,任何%p都被要归档文件的绝对路径代替, 而任何%f只是被文件名代替。(路径名关系到当前的工作目录,例如,集群的数据目录)。 如果你需要在命令里嵌入一个真正的%字符,最简单的有用命令类似下面这样:

archive_command = 'cp -i %p /mnt/server/archivedir/%f </dev/null'  # Unix
archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"'  # Windows

它将把 WAL 段拷贝到/mnt/server/archivedir目录。 (这个只是一个例子,并非我们建议的方法,可能不能在所有系统上都正确运行。) 在%p%f的参数更换之后, 实际执行的命令可能就像:

cp -i pg_xlog/00000001000000A900000065 /mnt/server/archivedir/00000001000000A900000065 </dev/null

一个相似的命令会在每一个新文件归档时产生。

归档命令将在运行PostgreSQL服务器的同一个用户的权限下执行 因此被归档的WAL文件实际上包含你的数据库里的所有东西, 所以你应该确保自己的归档数据不会被别人窥探; 比如,归档到一个没有组或者全局读权限的目录里。

有一点很重要:当且仅当归档命令成功时,它才返回零。 在得到一个零值结果之后,PostgreSQL将假设该文件已经成功归档, 因此它稍后将被删除或者被新的数据覆盖。 但是,一个非零值告诉PostgreSQL该文件没有被归档; 因此它会周期性的重试直到成功。

归档命令通常应该设计成拒绝覆盖已经存在的归档文件。 这是一个非常重要的安全特性, 可以在管理员操作失误(比如把两个不同的服务器的输出发送到同一个归档目录)的时候保证归档的完整性。 我们建议你首先要测试你准备使用到归档命令,以保证它确实不会覆盖现有的文件, 并且在这种情况下返回非零状态。在许多Unix平台,cp -i 会引起复制并在覆盖文件之前提醒,< /dev/null提示(覆盖)失败。 如果你的平台不支持这种操作,你可以增加一个命令测试存在的归档文件。 比如,类似下面的东西:

archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'

在几乎所有的Unix变种上都工作正确。

在设置归档环境的时候,请考虑一下如果归档命令失败会发生什么情况, 因为有些方面要求操作者的干涉,或者是归档空间不够了。 比如,如果你往磁带机上写,但是没有自动换带机,那么就有可能发生这种情况; 如果磁带满了,那就除非换磁带,否则啥事也做不了。 你应该确保任何的错误条件或者人为的操作请求会被合理的记录以确保问题会被快速合理地解决。 否则pg_xlog/目录会不停地填充WAL段文件,直到问题解决。 (如果文件系统被pg_xlog/填满,PostgreSQL会 做一个PANIC关闭,没有提交的事务都将丢失,将保持脱机状态,直到你释放一些空间数据库。)

归档命令的速度并不要紧,只要它能跟上你的服务器生成WAL数据的平均速度即可。 即使归档进程落在了后面一点,正常的操作也会继续进行。 如果归档进程慢很多,就会增加灾难发生时的数据丢失量。 同时也意味着pg_xlog/目录包含大量未归档的日志段文件,并且可能最后超出了磁盘空间。 我们建议你监控归档进程,确保它是按照你的意识运转的。

在写自己的归档命令的时候, 你应该假设被归档的文件最多64个字符长并且可以包含ASCII字母、数字、点的任意组合。 我们不必要记住原始的全路径(%p),但是有必要记住文件名(%f).

请注意尽管WAL归档允许你恢复任何对PostgreSQL数据库的修改, 在最初的基础备份之后,它还是不会恢复对配置文件的修改 (postgresql.conf,pg_hba.conf,pg_ident.conf), 因为这些文件都是手工编辑的,而不是通过SQL操作来编辑的。 所以你可能会需要把你的配置文件放在一个日常文件系统备份过程即可处理到的地方。 参阅Section 18.2获取如何重定位配置文件的知识。

因为归档命令仅在已经完成的WAL段上调用, 因此,如果你的服务器只产生很小的WAL流量或段之间的间隔很长, 那么在事务完成之后与其被安全归档之间就会存在很长的延时。 为了限制未归档数据的最长期限, 可以设置archive_timeout强制服务器在切换 WAL 段之间的时间间隔。 需要注意的是,由于强制切换而提早结束的已归档文件的大小与完整的归档文件相同。 因此将 archive_timeout设为一个很小的值是不明智的,它将很快耗尽归档空间。 将archive_timeout设置为60秒左右通常是比较合理的。

同样,如果你想确保刚刚完成的事务被立即归档, 那么也可以通过pg_switch_xlog手动强制切换段文件。 其它与WAL管理相关的工具函数在Table 9-56中列出。

wal_levelminimal时一些SQL命令将被优化用以避免WAL日志, 就像Section 14.4.7里描述的。如果归档和流复制在执行这些语句之一时被开启, WAL可能不会为存档恢复包含足够的信息。(崩溃恢复不受影响)。由于这个原因,wal_level 只能在服务器开始运行的时候被改变。然而,archive_command可以被重载配置文件改变。 如果你暂时停止归档,一个方法是把archive_command设置成空字符('')。 这将导致WAL文件在pg_xlog/里的积累,直到重新建立正在工作的archive_command

24.3.2. 进行一次基础备份

进行基础备份的过程相当简单:

  1. 确保WAL归档打开并且可以运转。

  2. 以数据库超级用户身份连接到数据库,发出命令:

    SELECT pg_start_backup('label');

    这里的label是任意你想使用的这次备份操作的唯一标识 (一个好习惯是使用备份转储文件的放置地全路径)。 pg_start_backup创建文件backup label, 叫做backup label,你备份的信息在集群目录里,包括开始时间和标签字符串。

    至于你连接到集群中的那个数据库没什么关系。 你可以忽略函数返回的结果;但是如果它报告错误,那么在继续之前先处理它。

    缺省时,pg_start_backup结束需要很长时间。这是因为它执行了一个检查点,并且 I/O所需的检查点将分散在一段重要的时间,默认情况下是你设置的inter-checkpoint间隔的一半 (配置参数请参阅checkpoint_completion_target). 这通常是你所想要的,因为这将影响查询处理。如果你想快速的启动备份,使用:

    SELECT pg_start_backup('label', true);

    这将促使设置检查点越快越好。

  3. 执行备份,使用任何方便的文件系统工具, 比如tarcpio 。 (不是pg_dumppg_dumpall) 这些操作过程中既不需要关闭数据库,也不需要关闭数据库的操作。

  4. 再次以数据库超级用户身份连接数据库,然后发出命令:

    SELECT pg_stop_backup();

    这将中止备份模式并自动切换到下一个WAL段。 自动切换是为了在备份间隔中写入的最后一个WAL段文件可以立即为下次备份作好准备。

  5. 只要在备份过程中使用的WAL段文件作为正常数据库活动的一部分备份完毕,你的备份工作就完成了。 由pg_stop_backup的结果标识的文件是完成备份的最后一个段,这个段需要形成一套完整的备份文件。 如果archive_mode 是不可用的,pg_stop_backup不会返回,直到最后完成一段。 因为你已经配置了archive_command,所以这些文件的归档将自动发生。 在大多数情况下,这个动作非常迅速,但是我们仍然建议你监视归档系统以确保备份成功。 如果由于归档命令失败归档进程已经落后,它会一直尝试直到成功完成和完成备份。 如果你希望用时间限制statement_timeout的执行,给statement_timeout设置适当的值。

有些工具在拷贝文件的时候,如果其正拷贝的文件改变了,就会发出警告或者错误信息。 在进行一个活跃数据库的基础备份的时候,这种情况是正常的,不是错误; 因此你必须能够区别这种报怨和真正的错误。 比如,有些版本的rsync会给"vanished source files"(消失的源文件)发出独立的退出码, 你可以写一个驱动脚本接受这样的退出码,把它当作非错误类型。 还有,当复制tar的时候文件被截断,有些版本的GNU tar返回一个错误代码与致命的错误区分。 幸运的是,如果文件在备份时被改变GNU tar版本1.16后来退出显示1,而2表示别的错误。

我们不需要太关心在pg_start_backup和开始实际备份之间的时间开销, 也不需要太关心备份结束和pg_stop_backup之间的时间;几分钟的延迟没什么害处。 然而,如果在关闭full_page_writes的情况下运行服务器, 你必须注意在pg_start_backuppg_stop_backup之间执行的 DROP 命令, 因为full_page_writes在备份模式中仍然有效。 你必须确保这些操作是按顺序执行的而不是重叠执行的,否则备份可能是无效的。

要保证你的备份转储包括所有数据库集群目录里的文件(比如/usr/local/pgsql/dataa)。 如果你在使用并未放置在这个目录里的表空间,也要小心地包含它们, 并且要确保你的备份转储归档符号连接是符号连接,否则,恢复会把你的表空间搞乱。

不过,你可以在备份转储文件里省略集群目录下的pg_xlog/子目录。 这个略微调整的动作是值得的,因为它减少了恢复时候的错误。 如果pg_xlog/是一个指向集群目录之外的符号连接, 那么这件事情很容易处理,出于性能考虑的时候经常这么做。

要使用这个备份,你需要保存所有备份开始以及之后的WAL段文件。 为了帮助你实现这个任务,pg_stop_backup函数创建一个备份历史文件,它马上存储到WAL归档区域。 这个文件的名字是以你在使用备份的时候需要的第一个WAL段文件的名字命名的。 比如,如果开始WAL文件是0000000100001234000055CD , 那么备份历史文件将命名为类似0000000100001234000055CD.007C9330.backup这样的东西。 这个文件名的第二部分表示在该WAL文件里面的准确位置,通常可以被忽略。 一旦你安全地把这些日志段文件归了档, 那么你就可以删除所有那些数值名字在这个文件前面的归档的WAL段。 文件系统备份不再需要它们了。当然,你应当保留几套备份以绝对确保可以恢复先前的数据。

备份历史文件只是一个小的文本文件。 它包含你给予pg_start_backup的标签字符串,以及备份的起始时间和终止时间。 如果你使用这个标签来表示转储文件放在哪里, 则在需要的时候,归档的历史文件就足够告诉你转储文件存放在哪里了

因为你必须保留直到最后一次基础备份的所有归档的WAL文件, 那么两次基础备份之间的间隔通常是根据你想在归档WAL文件上花多少存储空间来定的。 你还应该考虑你准备在恢复上花多少时间。 如果需要恢复的话,系统将需要重放所有那些段,而如果最后一次基础备份以来, 时间已经很长了,那么那些动作可能会花掉好些时间。

还有一件事值得一提,那就是pg_start_backup函数在数据库集群目录里创建了一个叫backup_label的文件, 它被pg_stop_backup删除。这个文件当然也会作为备份转储文件的一部分归档。 这个备份标签文件包含你给予pg_start_backup的标签字符串, 以及pg_start_backup运行的时刻,以及起始WAL文件的名字。 如果有混淆, 那么我们可以看看备份转储文件里面然后判断转储文件来自那个备份会话。

我们还可以在服务器停止的时候制作一个备份转储。 在这种条件下,很明显你不能使用pg_start_backuppg_stop_backup, 并且因此你必须靠自己的手段来跟踪备份转储文件都是那些,以及相关的WAL文件最远走到哪里。 通常使用上面的在线备份步骤更好些。

24.3.3. 从在线备份中恢复

好,最糟糕的事情发生了,现在你需要从备份中恢复。下面是步骤:

  1. 停止服务器,如果它还在运行的话。

  2. 如果你还有足够的空间,把整个集群数据目录和所有表空间拷贝到一个临时位置, 以防万一你之后还需要它们。 请注意这个预防措施要求你在系统里有足够的剩余空间来现有库的保持两份拷贝。 如果你没有足够的空间,那么你至少需要把集群数据目录的pg_xlog子目录的内容拷贝到安全的地方, 因为它们可能包含系统宕掉的时候还没有归档的日志。

  3. 然后清理掉所有在该集群数据目录里的现存文件, 以及所有你使用的表空间里根目录下的现存文件。

  4. 从你的备份转储中恢复数据库文件。 要小心用正确的所有者(数据库系统用户,而不是root)和权限恢复它们。 如果你使用了表空间,你可能需要核实在pg_tblspc/ 里的符号连接都得到正确恢复。

  5. 删除任何目前还在pg_xlog/里的文件 这些文件来自备份转储,因此它们可能比目前的老。 如果你就根本没有归档pg_xlog/,那么用适当的权限重建, 如果你之前已经以那样的方法设置了它,注意确保你重建就像符号链接一样。

  6. 如果你有在步骤2里面保存的WAL段文件,那么把它们拷贝到pg_xlog/ 。 最好是拷贝它们,而不是把它们移动回来,这样即使发生了糟糕的事情, 你需要重启的时候,你也依然拥有未修改的文件。

  7. 在集群数据目录里创建一个恢复命令文件recovery.conf(参阅Chapter 26)。 你可能还需要临时修改pg_hba.conf以避免普通用户连接, 直到你确信恢复已经正常了为止。

  8. 启动服务器。服务器将进入恢复模式并且继续读取它需要的WAL归档文件。 在遇见外部错误的应当中止恢复过程,然后重新启动服务器, 这样它会自动继续进行恢复工作。 在恢复过程完成后, 服务器将把recovery.conf改名为recovery.done以避免不小心因后面的崩溃再次进入恢复模式, 然后开始正常的数据库操作。

  9. 检查数据库的内容以确保你已经恢复到你期望的位置。 如果还没有,回到步骤 1 。 如果全部正常,则恢复pg_hba.conf成正常状态以允许普通用户登录。

所有这些操作的关键是设置一个恢复命令文件,这个文件描述你希望如何恢复以及恢复应该走到哪里。 你可以使用recovery.conf.sample(通常安装在安装目录的share/子目录里)作为原型。 你必须在recovery.conf.sample 里面声明的一个东西是restore_command,它告诉系统如何拿回归档的WAL文件段。 类似archive_command,这个是一个脚本命令字符串。它可以包含%f, 这个变量会被需要的日志文件名替换,以及%p,它会被要拷贝去的日志文件的绝对路径代替。 如果需要在命令里替换真正的%字符,那么就双写(%%)。最简单的有用命令是类似下面的东西:

restore_command = 'cp /mnt/server/archivedir/%f %p'

这个命令将把以前归档的WAL段从/mnt/server/archivedir目录拷贝过来。 你当然可以使用某些更复杂的东西,甚至是一个要求操作者挂载合适的磁带的shell脚本。

重要的一点是:该命令在失败的时候返回非零值。 如果日志文件没有出现在规档中,那么该系统将询问该命令; 在问到的时候,它必须返回非零。这个不是错误条件。 不是所有请求的文件会变成WAL段文件;你也可以期望要求以.backup.history 为后缀的文件。还要注意%p路径的基础名将和%f不一样;不要认为它们是可以互换的。

在归档中找不到的WAL段将被认为在pg_xlog/里; 这样就允许使用最近没有归档的段。 但是在归档中的段将比pg_xlog/中的优先。 在检索归档文件的时候,系统将不会覆盖现有的pg_xlog/内容。

通常,恢复将处理所有可用的WAL段,因此将把数据库恢复到当前时间(或者是在所给出的可用WAL段数的情况下,我们能走到的最近的地方)。 因此,一个正常的恢复会以"file not found"信息结尾,错误信息的确切文本取决于你对restore_command的选择。 你也可以在开始恢复命名像00000001.history的文件时看到一个错误信息。 这也是正常的,不表明在这个简单的恢复情况中有问题;更多内容请参考Section 24.3.4。

但是如果你想恢复到某些以前的时刻点(比如,在菜鸟DBA删除你的主要事务表之前), 那么只需要在recovery.conf里声明要求的停止点。 你可以通过日期/时间来声明,也可以通过特定事务ID的结束来声明这个停止点, 我们叫做"恢复目标"。 目前,只有日期/时间选项比较有用, 因为我们没有工具来帮助你精确地标识应该使用哪个事务ID 。

Note: 请注意停止点必须在备份的终止时间之后(也就是pg_stop_backup的时间)。 你无法使用一个基础备份恢复到备份正在进行中的某个时刻。 要想恢复到该时刻,你必须回到你以前的基础备份,然后从那个位置向前滚动。

如果在恢复过程中发现在WAL数据中存在错误,那么恢复将在错误的地方停止, 并且不会启动服务器。在这种情况下,可以指定一个位于错误点之前的"恢复目标", 然后从起始点开始重新运行恢复进程,这样恢复就可以正常完成。 如果由于外部原因(系统崩溃、无法读取WAL归档)导致恢复失败, 那么可以简单的重新启动恢复过程即可,它将从上次失败的地方继续。 重新启动恢复过程与检查点的操作非常类似: 服务器周期性的强制将其状态记录到磁盘上并更新pg_control文件以标识已经处理的WAL数据不需要被再次扫描。

24.3.4. 时间线

能够把数据库恢复到以前的某个时间点的能力导致了一些类似科幻小说里的时间跟踪和并行宇宙这样的复杂情况。 例如,在数据库最初的历史里,可能你在周二下午5:15删除掉了一个非常关键的表。 然后有条不紊地拿出备份,恢复到周二晚上5:14的即时备份。 在这个数据库宇宙的历史里,你从来没有删除过那个表。 但是假如你后来认识到这么干是错误的,并且想回到最初的历史中的周三早上的某一点。 你没法这么干,因为在数据库运行的时候,它覆盖了一些WAL段文件的序列, 这些序列就在你希望回去的区间里。 因此,为了避免这些,你的确需要区分在你从那些原始数据库历史生成的WAL中完成即时恢复之后生成的WAL序列。

为了处理这些问题,PostgreSQL有个叫时间线的概念。 当归档恢复完成时,那么就创建一个新的时间线, 以表示在该次恢复之后生成的WAL记录。不过,如果恢复动作一直处理到WAL结尾, 就不会开始一个新的时间线而只是扩展现有个那个。 时间线ID号是WAL段文件名的一部分,因此新的时间线并不会覆盖以前的时间线生成的WAL数据。 实际上我们可以归档许多不同的时间线。 虽然这些看起来像没用的特性,但它却可能常常是救命稻草。 考虑一下你并不很确信应该恢复到那个时刻的情况, 这个时候你不得不做好几次试验性即时恢复然后从中找到旧历史中最好的分支。 如果没有时间线,那么这个过程可能很快就会导致无法管理的混乱。 有了时间线,你可以恢复到任意以前的状态,包括恢复到你后来放弃的时间线分支的状态。

每当创建一个新的时间线的时候,PostgreSQL都创建一个"时间线历史"文件, 它显示自己从哪个时间线分出来,以及何时分出来的。 这些历史文件是在从包含多个时间线的归档中进行恢复时, 允许系统选取正确WAL段文件的必要文件。因此,它们像WAL段文件一样归档到WAL归档里。 历史文件只是很小的文本文件(不像段文件很大),所以独立地保存他们代价很小,也值得做。 如果你喜欢,你可以在历史文件里加入注释,记录自己为什么设置这个时间线以及如何设置的等信息。 这样的注释会在你有厚厚一堆不同的时间线需要选择和分析的时候特别有价值。

恢复的缺省的行为是沿着与基础备份的同一个时间线恢复。 如果你想恢复到某些子时间线,也就是,你想回到某些本身就是在开始恢复之后发生的状态。 你需要在recovery.conf里声明目标时间线ID。 你无法恢复到比基础备份更早的时间线分支。

24.3.5. 提示和范例

这里给出了一些提示配置连续归档。

24.3.5.1. 独立的热备份

PostgreSQL的备份设备产生独立的热备份是可能的。那些不能用在时间点 恢复中的备份,通常比pg_dump备份和存储要快。(他们也比pg_dump转储大, 所以在一些情况中,速度的优势可能被否定。)

为独立热备份做准备,把wal_level设置成archive(或者hot_standby), 把archive_mode设置成on,和设置archive_commandswitch file 存在时执行归档。例如:

archive_command = 'test ! -f /var/lib/pgsql/backup_in_progress || cp -i %p /var/lib/pgsql/archive/%f < /dev/null'

/var/lib/pgsql/backup_in_progress存在时这个命令将执行归档,否则不返回零退出状态(允许PostgreSQL 回收没用的WAL文件)。

有了这个准备,备份可以使用脚本,就像下面的例子:

touch /var/lib/pgsql/backup_in_progress
psql -c "select pg_start_backup('hot_backup');"
tar -cf /var/lib/pgsql/backup.tar /var/lib/pgsql/data/
psql -c "select pg_stop_backup();"
rm /var/lib/pgsql/backup_in_progress
tar -rf /var/lib/pgsql/backup.tar /var/lib/pgsql/archive/

交换文件/var/lib/pgsql/backup_in_progress首先被创建,使WAL 文件的归档完成。备份之后交换文件被删除,归档WAL文件,然后添加到备份,这样 基础备份和所有必需的WAL文件都是相同tar文件的一部分。请记得 给你的备份脚本添加错误处理。

如果归档存储容量是一个问题,用pg_compresslog,http://pglesslog.projects.postgresql.org, 去删除不必要的full_page_writes和从WAL文件里延伸的目录空间。 你可以用gzip进一步压缩gzip的输出:

archive_command = 'pg_compresslog %p - | gzip > /var/lib/pgsql/archive/%f'

在恢复时你将会用到gunzippg_decompresslog

restore_command = 'gunzip < /mnt/server/archivedir/%f | pg_decompresslog - %p'

24.3.5.2. archive_command scripts archive_command脚本

很多人选择用脚本去定义他们的archive_command,以至于他们的postgresql.conf、 输入看起来非常简单:

archive_command = 'local_backup_script.sh'

使用一个分开的脚本文件时可取的,在归档进程中你可以在任何时间用多于一个单一的命令。 这使得所有的复杂性在脚本里被管理,那些复杂性可以用流行的脚本语言编写,就像bashperl。 脚本写给stderr的任何信息会出现在数据库服务器的日志里,允许复杂的配置,如果他们不容易被诊断。

可能在一个脚本解决需求的例子包括:

  • 复制数据,以确保异地数据存储

  • 配置WAL文件,使他们每隔三小时转换一次而不是一小时转换一次。

  • 其他备份和恢复软件接口

  • 接口监控软件报告错误

24.3.6. 警告

目前,在线备份技术还有几个局限。它们可能在将来的版本中修补:

  • 在Hash索引上的操作目前没有使用WAL记录日志, 所以重放就不会更新这些索引类型。 这将意味着任何新的插入都将会被索引忽略,更新的行会消失,删除行仍将保留指针。 也就是说,如果你用hash索引修改一个表,你将会在备用服务器上得到一个不正确的查询结果。 当恢复完成后,在恢复操作之后,建议你手动REINDEX每一个这样的索引。

  • 如果在进行数据库备份的时候发出一个CREATE DATABASE命令, 然后在这个过程中CREATE DATABASE命令拷贝的模板数据库被修改了, 那么用这个备份进行恢复的数据库很有可能导致这些修改也传播到新创建的数据库中去。 这个行为当然是不愿意看到的。 为了避免这个风险,最好在进行数据库备份的时候不要修改任何模板数据库。

  • CREATE TABLESPACE命令是用文本的绝对路径记录WAL日志的, 因此会以相同的绝对路径重新创建。 如果日志是在另外一台机器上重放,那么这个行为可能不是我们想要的。 即使在同一台机器,但是在一个新的数据目录里重放日志,都很可能是危险的: 重放仍将会覆盖原来的表空间的内容。 为了避免这类的潜在问题,最好的方法是在创建或者删除表空间之后进行一次新的基础备份。

还要注意,缺省的WAL格式体积相当大,因为它包含许多磁盘页快照。 这些磁盘页快照是设计来支持崩溃恢复的,因为我们可能需要修补部分写入的磁盘页。 根据你的系统硬件和软件的不同,这种部分写入的危险可能是微乎其微的。 这种情况下,你可以通过使用full_page_writes关闭磁盘页面快照, 从而大大减少归档日志的总尺寸(在你这么做之前,阅读Chapter 29里面的注意和警告)。 关闭页面快照并不阻止日志使用PITR操作。 一个将来需要开发的功能是在full_page_writes打开的时候, 通过删除不需要的磁盘页拷贝来压缩归档的 WAL 数据。 同时,管理员可以通过尽量合理地增加检查点的时间间隔来减少包含在WAL里的页面快照。

Previous article: Next article: