pg基本知识

pg基本知识.md

目录

  • base: 默认表空间
  • global: 共享系统表目录
  • pg_clog: commit log 目录
  • pg_log: 系统日志目录,查询系统错误时可看,alert日志,慢日志,全量sql都在此
  • pg_stat_tmp: 统计信息的存储目录
  • pg_tblsp: 指向各个用户自建表空间实际目录的链接文件
  • pg_twophase: 两阶段提交功能时分布式事务的存储目录
  • pg_xlog: WAL日志目录

术语

  • relation: 相当于table或index,具体要看情况
  • tuple: 相当于row
  • page: 磁盘中的数据库
  • buffer: 内存中的数据库

初始化

  • initdb -E UTF8 -D $PGDATA -U DB超级用户 --lc-collate=C --lc-ctype=en_US.utf8

基本操作

  • 启动数据库实例
    • postgres -D /home/pgsql/rm-rdszjk_pg10_test/data &
    • pg_ctl start -D /home/pgsql/rm-rdszjk_pg10_test/data
  • 关闭 三种模式
    • smart shutdown:智能关机,不允许有新连接,等已有连接全部结束才关闭
      • pg_ctl stop -D /home/pgsql/rm-rdszjk_pg10_test/data -m smart
      • 发送SIGTERM信号
    • fast shutdown: 快速关闭,不允许有新的连接,并将所有活跃的服务进程发送终止信号让其立刻退出,然后等所有子进程退出后关闭,如果处于备份状态将终止备份,不会丢数据,重启后也不需要重放WAL日志
      • pg_ctl stop -D /home/pgsql/rm-rdszjk_pg10_test/data -m fast
      • 发送SIGINT信号
    • immediate shutdown: 立即关闭模式,主进程想所有子进程发送停止信号,并立刻退出,所有子进程也会立刻退出,下次启动时要重放WAL进行恢复
      • pg_ctl stop -D /home/pgsql/rm-rdszjk_pg10_test/data -m immediate
      • 发送SIGQUIT信号
  • 重启
    • pg_ctl restart -D datadir -m 上述三种模式,还有如下参数,同样适用于启动停止
      • -w: 等待启动完成
      • -t: 等待启动完成的秒数
      • -s: 只打印错误和警告信息,不打印info
      • -l file:把服务器日志输出到file上
      • -o option: 声明直接船体给postgres的选项
      • -p path: 指定postgres的位置,一般跟pg_ctl同目录不需要指定
      • -c: 异常时打coredump
  • 重新读取配置文件
    • pg_ctl reload -D datadir: 比如修改了pg_hba.cong文件,让其生效就用这命令
    • 或者pg_reload_conf()
    • 发送SIGHUP信号
  • 查询数据库实例状态
    • pg_ctl status -D datadir

psql

  • 连接数据库: su 数据库账号下(创建数据默认创建了数据库账号),执行 /u01/pgsql_20190102/bin/psql postgres -p3021
  • \l: 查看数据库,=show databases \l+ 显示数据库详细信息 select datname from pg_catalog.pg_database;
  • \d: 查看表的情况,=show tables 也可用\dn, \d table= show create table, \d 索引名 查看索引情况, \du或dg: 列出所有用户
    • \dn 列出所有schema
  • \du+: 列出所有用户及其用户权限
  • \z: 列出当前库下所有表的权限, \z table_name 列出对象的权限
  • \c: 列出当前库当前用户 \c database: =use database \c database user_name 切换到某个数据库下某个角色
  • \encoding gbk: 指定字符集为gbk
  • \pset 设置输出格式
    • \pset border 0: 输出内容无边框,无任何|
    • \pset border 1: 边框只在内部有,无外边框
    • \pset border 2: 内外都有边框
  • \x: = \G
  • \i filename: 执行filename文件中的sql语句,也可用psql -s filename,在这里也可以用-x来达到\x的目的
  • \echo xxx: 输出信息
  • \password 修改密码
  • ? 帮助命令
  • 命令补全,两个tab
  • 查找某个账号在哪个库下有权限 select *from pg_catalog.pg_database where array_to_string(datacl,’,’) like ‘%pgsql%’;
  • 查找当前库下所有表名 select * from pg_tables;

常用语句

  • 查询语句标记类型: 两种
    • int ‘’
    • ‘’::varchar(32)
  • 查询数组: select * from xxx where phone @> array[‘1234’::varchar(32)]; @>包含的意思 可在phone字段创建GIN索引
  • pg是大小写敏感的数据库,查询时如果想大小写不敏感就用lower()函数,模糊查询时用ILIKE 不区分大小写 like 区分大小写
  • create database
    • create database zjk_db1 with encoding=‘UTF8’ template=‘template1’ owner=‘zjk_test1’; 注意如果字符集不是utf8 要用template0,不然会导致复制错误
    • eg: create database zjk;
  • set time zone ‘PRC’; 有些时候查询时间用的

索引

  • 查看索引信息: \d+ 索引名
  • 创建索引: pg有多种索引,B-tree索引(mysql类似),Hash索引(处理简单的等值查询不会记WAL日志,很少用),GiST, SP-GiST, GIN(反转索引,包含多个键的值,如数组)
    • create index idx_xxx on table_name(column) : 创建Btree
    • create index idx_xx on table_name usinng gin(column) : GIN索引
    • 创建索引是锁写的,只读,不是online DDL,要用online需要使用concurrently,并行,创建索引的执行时间也会变长
    • create index concurrently idx_xxx on table_name(column)
    • 函数索引: create index idx_xxx on table_name (lower(column_name)),为lower函数在column_name列上创建函数索引,不创建索引因为使用了函数所以走不到column_name上的索引,创建了函数索引后执行where lower(note)=‘a’ 时就能走到索引了
    • 部分索引: create index idx_xxx on table_name (column_name) where not (column_name > xx and column_name < xx),按照条件筛选的部分内容创建上索引
  • 重建索引: 重建索引不支持从currently,但是支持同一个字段建立多个索引,可以先用concurrently创建一个新的索引,再删除老的索引
    • alter index idx_xxx rename to new_xxx : 改索引名
    • alter index idx_xxx set tablespace tablespace_name :更改到其他白哦空间
    • alter index idx_xxx set (storage_parameter=value) :修改索引的填充因子
    • alter index idx_xxx reset (storage_parameter[,…]) :重指填充因子
  • 删除索引
    • drop index idx_xxx
    • drop index if exists idx_xxx :存在删除,不存在也不报错
    • 默认是restrict的,也就是有外部依赖索引时删除索引会失败,cascade表示强制把外部依赖也删除,比如外键约束
    • drop index idx_xxx cascade

用户权限相关

  • database -> schema -> table 分层关系
    • 每个schema总是属于一个数据库的,schema对象: 表、视图、函数,mysql中的database对应的是pgsql中的schema,所以pg中没有对数据库的
    • pg没有create table这种DDL权限控制,只有对schema的create权限,但是数据库默认会有public的schema,拥有create权限,所以如果不收回任何用户在public schema下都有create权限,一般是要revoke create on schema public form public
    • 每个数据库都有个默认的public schema, schema是相对数据库来说的,schema下又有很多表,默认创建的表是在public 下
    • 可以同时给数据库下某个schema下的所有表赋权,但是不能给库下所有schema的下的所有表赋权
  • 权限分层
    • 管理用户特殊属性的权限,如超级管理员,创建数据库,创建用户,login的权限
    • 数据库中创建模式的权限
    • 模式中创建数据库对象的权限,如创建表,创建索引
    • 查询表,DML等权限
    • 操作表中某些字段的权限
  • 权限分为两类
    • 创建用户就指定的权限,修改此权限需要用alter role的方式来修改: alter role role_name option(具体的权限)
      • 超级用户的权限
      • 创建数据库的权限
      • 是否允许login的权限
    • 剩余的权限是用grant和revoke来管理的: grant xxx on table to role_name
      • 数据库中创建模式(schema)
      • 允许在指定的数据库中创建临时表
      • 连接某个数据库
      • 在模式中创建数据库对象,如创建表,视图,函数
      • 在表中做DML或查询
      • 在表的具体列上做DML
      • 对序列进行查询
      • 在声明表上创建触发器
      • 可以把表索引等建到指定的表空间
  • 创建用户和角色: pg用户user和角色role一样,只是创建user默认会有login的权限,role默认没有,其他都一样
    • create role/user name option(具体权限)
      • superuser|nosuperuser:是否是超级用户,只有超级用户才能创建超级用户
      • createdb|nocreatedb: 是否有create database的权限
      • createrole|nocreaterole: 是否有创建其他角色的权限
      • createuser|nocreateuser: 是否有创建其他用户的权限
      • inherit|noinherit: 如果创建的用户又某个角色的权限,若指定inherit,则表示用户自动拥有相应角色的权限
      • login|nologin: 是否有login的权限,可以临时禁止用户的login的权限
      • connection limit connlimit:指定该用户可以使用的并发连接数量,-1表示不限制
      • [ENCRYPTED|UNENCRYPTED] PASSWORD ‘XXX’: 控制存储在系统表里的密码是否加密
      • valid until ‘timestamp’: 密码失效时间,不指定永远有效
      • in role role_name: 指定用户成为哪些角色的成员,不能把新角色添加未管理员,必须用grant命令来做
      • role role_name: role_name将成为这个新建角色的成员
      • admin role_name: role_name将有这个新建角色的with admin option权限
      • eg: create user replicator replication login encrypted password ‘replicator’;
      • eg2: create user user_name with priv password ‘xxx’
      • eg3: create role role_name with priv password ‘xxxx’ in role role_name1 相当于用了grant role_name1 to role_name
  • 修改用户和角色权限: alter role role_name option(与上面个创建时的option一样) 修改创建数据库时候的权限
    • eg修改密码: alter role role_name with password ‘xxx’
    • eg修改权限: alter role role_name with priv password ‘xxx’
  • 删除用户: drop user user_name
  • grant权限 grant 具体权限 on table|sequence|database|foreign data wrapper|foreign server|function|language|large object|schema [xxx_name] to [role_name]
    • grant两个作用 1.让某个用户拥有某个角色的权限 2.让某个用户拥有操作哪些对象(数据库/table/schema/…)的权限
    • 具体权限包含 多个权限逗号隔开
      • SELECT|INSERT|UPDATE|DELETE|TRUNCATE|CREATE|ALL PRIVILEGES|USAGE
      • EXECUTE: 函数上的唯一权限
      • CONNECT: 允许连接到指定的数据库
      • TRIGGET: 允许指定的表上创建触发器
      • REFERENCES: 创建外键约束,将该权限赋给一个表的所有列或者特定列
    • eg: grant all on database db_name to role_name 操作对象的权限
    • eg: grant select(字段名字) on table table_name to role_name select table_name表中某个字段的权限
    • eg: grant role_name to new_role_name with xxx 操作用户 前提是先创建用户
    • eg: grant select on all tables in sechma public to user_name 把public模式下所有表的select权限赋给user_name,只是存量表,增量的需要用下面的sql
    • alter default privileges in schema public grant select on tables to user_name public下新建的增量表也会授权
  • revoke权限 revoke 权限 on table/database… table_name from role_name
  • 查看用户权限
    • 查看所有账号: select *from pg_user; select *from pg_roles; \du+ 可以查看member of(属于哪个账号) 和description
    • 查某个账号有哪些权限 下面sql只能查询这个账号在当前库下有哪些表的权限,不能查其他库中表中的权限
      • select * from information_schema.table_privileges where grantee=‘pgsql’; 只有grant表权限的账号才会有
      • 如果没有代表这个账号没有这个库下所有表的权限
    • \z table_name: table上有哪些用户权限 等于 select relacl from pg_class where relname=‘table_name’;
      • r – SELECT (“read”)
      • w – UPDATE (“write”)
      • a – INSERT (“append”)
      • d – DELETE
      • D – TRUNCATE
      • x – REFERENCES
      • t – TRIGGER
      • X – EXECUTE
      • U – USAGE
      • C – CREATE
      • c – CONNECT
      • T – TEMPORARY
      • arwdDxt – ALL PRIVILEGES (for tables, varies for other objects)
        • – grant option for preceding privilege
    • 查看账号有哪些数据库的权限
      • select datname from pg_catalog.pg_database where array_to_string(datacl,’,’) like ‘%pgsql%’;

函数

  • select pg_backend_pid():查看当前连接的pid,因为每个连接是一个进程的,所以当前连接的pid直接可见
  • select pg_cancel_backend(pid int) : 取消某个用户进程
  • select pg_reload_conf() 重载postgresql.conf中的配置文件,生效的都是无需重启的参数
  • select version() 查看版本 show server_version; 纯数字的
  • select pg_postmaster_start_time() 查看启动时间
  • select pg_conf_load_time() 产看最后load配置文件时间
  • show timezone 显示数据库时区
  • select user 查看当前用户名
  • select catalog/current_databases() 查看当前连接的数据库
  • select pg_xlogfile_name(pg_current_xlog_location()) 查看当前正在写的WAL select pg_walfile_name(pg_current_wal_lsn());
  • select pg_current_xlog_location() pg10改为 pg_current_wal_lsn()
  • SELECT pg_xlog_location_diff(pg_current_xlog_insert_location(),pg_current_xlog_location()) 查看WAL的buffer还有多少数据没写磁盘
  • select pg_is_in_recovery() 查看当前数据库是正常状态还是hot standby状态
  • select pg_rotate_logfile() 切换log日志文件到下一个,flush log相当于
  • select pg_switch_xlog() 切换WAL日志文件 select pg_switch_wal()
  • checkpoint 手工产生一次checkpoint
  • select pg_postmaster_start_time(); 查看启动时间
  • pg_encoding_to_char(encoding) pg中的字符转换为UTF8那种类型
  • select pg_switch_xlog(); 手动切换xlog

系统表

  • select *from pg_locks: 查看锁的情况
  • select *from pg_stat_activity: 查看系统服务进程,可查看运行较久的sql进程
  • select *from pg_statistic: 产看统计数据
  • select *from pg_settiongs limit 1: 参数的详细说明

参数

  • 参数分类: 修改立即生效,修改执行reload生效,修改重启生效
  • 参数操作
    • 好看参数: show xxxx; eg: show rds_force_trans_ro_non_sup
    • 修改参数: alter system set xxx=xxx
    • reload参数: select pg_reload_conf() pg_ctrl reload -D/u01/pgxxx/data
    • 针对某个角色/database设置参数: alter role set xxx=xxx, alter database set xxx=xxx
    • 查看参数如何生效: 方式 select context from pg_settings where name=‘xxx’
      • context七中类型
        • postmaster 重启
        • superuser-backend superuser修改后的新连接生效
        • user 单个会话用户可以在任意时间做修改,只会影响该会话
        • internal 编译期间的设置,只有重新编译才能生效。
        • backend reload 后的新连接生效
        • sighup pg_ctl reload 生效
        • superuser 这类参数可以由超级用户使用set修改。参数设置后只会影响超级用户自身的session配置,不会影响其他用户。
  • wal_level: 枚举类型,决定wal日志中的信息量
    • minimal:仅写入北葵或者突发关机时所需的信息
    • archive: 想用WAL做归档要使用 9.6前
    • hot_standby: 如果要搭建hot_standby备库要使用,一般实在流复制的时候使用到, 9.6前
    • replica:9.6中新增,相当于是archive和hot_standby的合并
    • logical: 主要用于logical decoding场景
    • 在写入频繁的场景中,会产生大量的WAL日志,而且WAL日志量会远远超过实际更新的数据量。叫做“WAL写放大”。造成WAL写放大的主要原因有2点
      • 1、在checkpoint之后第一次修改页面,需要在WAL中输出整个page,即全页写(full page writes)。全页写的目的是防止在意外宕机时出现的数据块部分写导致数据库无法恢复。
      • 2、更新记录时如果新记录位置(ctid)发生变更,索引记录也要相应变更,这个变更也要记入WAL。更严重的是索引记录的变更又有可能导致索引页的全页写,进一步加剧了WAL写放大。
  • fsync: on/off: 是否使用fsync()系统调用,把文件系统中的脏页刷新到磁盘上,确保数据库宕机时数据不丢失(未刷盘相当于wal中的数据少了,导致无法恢复数据,比如未提交的无法回滚造成数据不一致)
  • synchronous_commit: on ,off、local、remote_write、remote_apply: 递交事务是否需要等到把WAL刷到磁盘再返回commit结果,设置为off如果宕机可能导致数据丢失
    • on当没有同步备库时,wal真正写入磁盘才返回commit成功
    • on当有同步备库时(设置了synchronous_standby_names)必须要等事务日志刷新到本地磁盘,并且还要等远程备库也提交到磁盘才能返回客户端已经提交
      • 提交到磁盘是指收到数据刷新到磁盘文件(relaylog),不是指落库,允许备库应用日志慢
      • 所以测试时候 select pg_wal_replay_pause(); 是没用的,需要关库
    • off写到缓存中就会向客户端返回提交成功。
      • 延迟写入磁盘的时间为最大3倍的wal_writer_delay参数的(默认200ms)的时间,关闭synchronous_commit会造成最多600ms的事务丢失,但对高并发的小事务系统来说,性能来说提升较大。
    • remote_write:当事务提交时,不仅要把wal刷新到磁盘,还需要等wal日志发送到备库操作系统(但不用等备库刷新到磁盘)。
      • 如果备库此时发生实例中断不会有数据丢失,因为数据还在操作系统上,而如果操作系统故障,则此部分wal日志还没有来得及写入磁盘就会丢失,备库启动后还需要想主库索取wal日志
    • local:当事务提交时,仅写入本地磁盘即可返回客户端事务提交成功,而不管是否有同步备库。
    • 可以局部设置set local synchronous_commit to off; 局部事务科备库异步方式同步,重要事务同步方式
  • wal_buffers: wal的缓冲区大小,最小为32kb
  • wal_writer_delay: wal writer进程的sleep时间,默认200ms
  • wal_sync_method: wal写入磁盘的控制方式
  • log_min_messages: 设置log级别
  • log_mim_duration_statement: 慢日志设置时间,超过这个时间就把sql记录到日志中
  • log_staement: 设置是否记录sql,可设置ddl dml等
  • debug_print_xxx: 设置sql执行计划等打印到日志中
  • 流复制相关参数 (重启生效)
    • listen_addresses=’*’ 监听地址
    • max_wal_senders=x 最大wal日志发送线程数
    • wal_level=hot_standby hot_standby
  • 设置只读的参数: rds_force_trans_ro_non_sup=‘on’ (reload生效) 也可以设置recovery配置文件让其成为只读(重启生效)

配置文件

  • postgresql.conf: 数据库实例的主配置文件,基本上所有的配置参数都在此
  • pg_hdb.conf: 认证配置文件,比如允许哪些ip的主机访问数据库,认证方式之类的,如果选择了一条记录且认证失败不会再考虑后面的记录 修改reoad生效
    • 格式
      • local [auth-option] unix 套接字
      • host [auth-option] tcp/ip 包括ssl或者非ssl
      • hostssl [auth-option] tcp/ip的ssl连接
      • hostnossl [auth-option] tcp/ip的非ssl
      • host [auth-option]
      • hostssl [auth-option]
      • hostnossl [auth-option]
    • 关键字及解释
      • dbname: 数据库名,如果为all表示所有数据库,如果replication表示允许流复制连接
      • user: 用户名,all表示任意用户
      • ip/masklen: 允许哪些ip访问,1.1.1.1/32 表示完全匹配1.1.1.1, 1.1.1.0/24表示前缀未1.1.1的ip, 0.0.0.0/0任何ip
      • auth-method: 验证方式 trust reject,md5,ident
        • trust: 无条件允许,不需要口令和任何认证
        • reject: 无条件的拒绝,可以组织一个主机连接
        • md5: 用户提供md5的口令认证
        • password: 未加密的口令
        • ident: 允许客户端上特定操作系统用户连接到数据库
      • auth-option: 认证选项
  • pg_ident.conf: "ident"认证方式的用户映射文件
  • recovery.conf: 恢复配置,修改了这个文件需要重启实例生效
    • 归档恢复: standby从归档日志(备份)文件中恢复standby数据库时需要配置
      • restore_command: standby如何获取WAL日志文件,通常是配置一个拷贝命令,从备份目录拷贝到xlog目录
        • cp " + self.clone_path +"/%f %p
      • archive_cleanup_command: 清理standby数据库机器上不需要的WAL日志文件
      • recovery_end_command: 恢复完成后可以执行一个命令
      • recovery_target_time: 目标,应用到哪里结束
      • 如何查看归档恢复成功
        • 成功后 select pg_is_wal_replay_paused(); 会变为true
        • 主动执行select pg_wal_replay_resume(); 后会跳出恢复状态,数据库变为主库
    • recovery target配置: standby恢复到一个指定的点后就停止
    • standby server配置: 就是备库
      • standby_mod: standby为on
      • primary_conninfo: 流复制参数
      • primary_slot_name: 指定复制槽,9.4才有的
      • trigger_file: 指定基金或standby的触发文件,standby发现此文件存在时就会把standby库激活为主库,不配置此项的话可以使用 gp_ctl promote来激活standby数据库
      • recovery_min_apply_delay: 指定备库延迟主库一段时间,防止主库误操作数据丢失等用途

log

  • WAL: write ahead log: 预写式日志,也被称为xlog
    • 作用: 在修改数据前把修改操作记录到磁盘中,后续实际更新数据时不需要实时地把数据持久化到文件中了(可以在内存buffer里),这样如果突然down机,内存buffer里的还没刷新到磁盘中的实际数据就丢失了,重启后通过读取WAL日志重新执行一遍就好了,具体的还要看刷WAL有没有参数控制,如果WAL的刷盘也有缓冲区,那WAL也是有可能丢失的
    • WalWriter进程专门负责写WAL日志,保存在pg_xlog中,每个文件默认16M
    • 会被循环使用,较早时间的WAL日志会被覆盖,所以PgArch(归档)进程会法则把WAL日志备份出来,增量备份就是备份的WAL日志
    • 只有在启动数据库时,机器实时检查点(check_point)时才会清理log
      • 启动startup进程时,自动清理当前时间线以前的XLOG文件,因为数据库启动需要recovery的数据是最后一次检查点之后的数据,之前的数据就认为没用了,所以可以清理(这是在不考虑归档和流复制的情况下)
    • 数据库CRASH后,是从最后一次完成的检查点(不是时间线)开始恢复的,所以只需要那次检查点开始之后的XLOG即可
      • 检查点的值可以通过pg_controldata $PGDATA 查到
        Latest checkpoint location:           1/E000028  
        Prior checkpoint location:            1/D18C068  
        Latest checkpoint's REDO location:    1/E000028  
        Latest checkpoint's REDO WAL file:    00000001000000010000000E  
      
        表示00000001000000010000000E之前的xlog文件可以删除  
      
    • 数据的最大log量就是 max_wal_size/16MB + wal_keep_segments
    • log大于max_wal_size后会强行进行check_point,进行check_point时候会调用清理log进程
    • 当日志量在[min_wal_size, max_wal_size] 时候check_point时间完全是checkpoint_timeout 时间确定 也叫 lazy check_point
    • 日志不会少于min_wal_size 最少会保留这些循环使用
    • select * from pg_ls_waldir() order by name; 类似于 show binary logs
    • 归档 archive_status目录下会有一个跟pg_wal目录里相同名字当时后缀是.ready或者.done的文件 这个文件称为归档日志
      • archive_mode=on 归档开关 archive_command=xxx 归档命令
      • 比如你配置了archive_mode=on,但是没有配置archive_command,那么xlog文件会一直堆积(xlog写完后,会写.ready,但是由于没有配置archive_command,也就是说不会触发归档命令,所以一直都不会写.done) 这就是为什么日志备份需要备份后把文件改为.done
    • 手动清理wal 要注意,检查是否有 select * from pg_replication_slots 消费log的地方,检查是否备份
      • pg_controldata $PGDATA 找到那个file之前的可以清理
      • pg_archivecleanup -d $PGDATA/pg_xlog 00000001000000010000000E 清理掉指定文件之前的log
    • pg_receivewal -h%s -p%s -U%s -D%s 从一个库向另一个库拉wal log
      • export PGPASSWORD=jFDx86dX;/u01/pgsql/bin/pg_receivewal -h192.168.4.155 -p5432 -Ureplicator -D /u01/pg5432 &
  • clog: commit log, 在pg_clog子目录中, 记录事务状态的log
    • 事务状态
      • TRANSACTION_STATUS_IN_PROGRESS=0X00: 表示事务正在进行中
      • TRANSACTION_STATUS_COMMITTED=0X01: 表示事务已提交
      • TRANSACTION_STATUS_ABORTED=0X02: 表示事务已回滚
      • TRANSACTION_STATUS_SUB_COMMITTED=0X03: 表示子事务已提交
    • 事务ID: xid,32位数字,从3开始,到最大后再从3循环
  • pg_receivewal
    • pg_receivexlog会扫描整个-D选项指定的目录,将扫描到的每个文件名,去掉其timeline部分,转换为64为整数。选取其中对应整数最大的文件,按如下方式选择开始下载的文件:如果这个文件是以.partial为后缀的,则重新下载此文件和后续文件;如果该文件不带.partial后缀,是一个完整的日志文件,则从此文件的下一个文件(文件名加1)开始下载
    • pg_receivexlog已经下载了我们需要的文件后,并不会自动停止,我们也没有办法指定它下载到哪个文件结束。唯一的办法是通过Ctl-C命令向它发送SIGINT信号来结束它。类似的,可以直接向它的进程发生kill命令
    • 注意,pg_receivexlog只在成功传输完一个xlog文件后,才检查是否收到了SIGINT信号,因此你只可能在一个文件接收完成后正常结束pg_receivexlog运行。其实更暴力的办法是直接kill -9 也是可以的

进程

  • Postmaster: 整个数据库实例的总控制进程,负责启动和关闭数据库实例,是一个指向pstgres的链接,pg_ctl也是通过运行postgres来启动的,只是做了些包装
  • SysLogger(系统日志)进程: 收集系统日志的
  • BgWriter(后台写)进程: 共享内存中的脏页刷新到磁盘
  • WalWriter(预写式日志写)进程: 写WAL日志的
  • PgArch(归档)进程: 备份Wal日志的,防止循环覆盖
  • AutoVacuum(自动清理)进程: pg中数据删除和更新不会直接修改数据,而是新增一条,或者把要删除的行标记为删除,在没有并发的其他事物读这些旧数据时此进程负责说清楚掉这些数据
  • PgStat(统计数据收集)进程: 采集数据的,正在pg_statistic中有记录

常用运维操作

  • 取消一个运行时间久的SQL
    • select pid,usename,query_start,query from pg_stat_activity 查找运行时间久的sql
    • select pg_cancel_backend() 取消这个sql 如果取消不了就用 pg_terminate_backend()
  • kill session: select pg_terminate_backend(pid)
    • kill排除某些用户的session: select pg_terminate_backend(pid) from pg_stat_activity where username not in (%s);
  • switch xlog: select * from pg_switch_xlog();

MVCC 多版本并发控制

  • 实现MVCC的方法
    • 写新数据时把旧数据移到一个单独的地方,如回滚段中,其他人读数据时从回滚段中把旧数据读出来: mysql(innodb) 和 Oracle
    • 写新数据时,旧数据不删除,而是心插入一条,把旧数据标记一下 postgres
      • 这样带来一个问题就是旧数据回收,由vaccum进程来回收存储空间,autovacuum设置是自动回收空间,也可以关闭,在低峰期手工操作

序列

  • pg有单独的序列sequence,mysql的序列是绑定在一张表的字段上的,自增列,只能用于表中的其中一个字段,pg没有任何限制
  • 创建序列 create temporary|temp sequence name [increment by xxx][minvalue xxx|no minvalue][maxvalue xxx|no maxvaluue] …

咨询锁,类似于zk中的分布式锁服务,谁拿到锁谁是master的场景

checkpoint

checkpoint是事务中的点,在产生检查点时,所有脏数据页都会刷新到磁盘并在日志中写入一条特殊的检查点记录,确保在之前的所有信息都落盘,在发生崩溃后,恢复过程会查找最后一个检查点记录,然后重做这个检查点之后的数据,从而把数据库恢复到正常情况下。检查点说白了就是数据刷脏后的一个点记录,用来记录之前的数据都落盘了,之前的日志可以删了,下次从这里开始恢复

  • 参数 下面两个参数是或的关系
    • checkpoint_segments: 每写完几个WAL日志文件创建一个检查点 默认3
    • checkpoint_timeout: 每过多少秒创建一个检查点 默认300s
  • 也可以用checkpoint命令手动创建检查点,命令就是 CHECKPOINT;
  • 顾名思义对性能有影响,刷的快性能慢,刷的慢数据有问题

主备

  • warm standby server: 只接收同步数据,不能提供只读服务的,比如备份数据库
  • hot standby server: 既同步数据,又可做只读,slave,9.x才有的功能
  • PITR: Point-in-Time Recovery, 基于时间点的备份,简单的cp数据库文件到另一台机器,这叫基础备份。后续通过WAL日志的备份与基础备份构成完整的备份,不停的重放WAL日志就就可以把数据推到备份结束后的任意一个时间点,这就是PITR
  • 将WAL日志传送到另一个机器的方法有两种
    • WAL日志归档: 配置将WAL复制到某个地方,由两个参数控制
      • archive_mode=on 表示打开归档
      • archive_command=‘cp %p /backup/pgarch/%f’ %p WAL全路径,%f去掉全路径的WAL文件名,配置主备同步就用scp命令就好了
      • 这样主备复制延迟一个WAL文件,所以不适合主备同步
    • 流复制: 9.0开始提供的一种新的传递WAL日志的方法,只要产生日志就传到备库,其中包括同步模式9.1之后和异步模式,9.2后增加了级联复制
      • 手动创建流复制的方法: /u01/ppas1000_20190101/bin/pg_receivewal -h11.239.188.71 -p3004 -Ureplicator -D/home/pgsql/downloads/3020’
  • 创建standby步骤
    • 生成基础备份,把基础备份拷贝到备机上,配置recovery.conf把备库启动在standby模式下
    • 生成基础备份步骤,pg_basebackup命令行工具完成了整个步骤9.1版本开始提供的
      • 超级用户执行 select pg_start_backup(‘lable’)
      • 执行备份 可以压缩如tar
      • 超级用户执行 select pg_stop_backup() 终止备份模式并自动切换到下一个WAL段
      • 拷贝备份过程中产生的增量WAL文件
  • pg_basebackup使用
    • 使用replication协议连接到数据库实例上,所以pg_hba.conf中要允许热;replication连接
    • pg_basebackup option
      • -D directory --pgdata=directory 设置备份到哪个目录,为-表示输出到标准输出以便用管道与其他工具配合
      • -F format --format=format 指定输出格式,format=p/plain(原样输出) t/tar(压缩为tar)
      • -z --gzip,与tar连用,压缩用的
      • -Z level --compress=level gzip的压缩级别,1-9的数字
      • -x --xlog 备份时同时备份WAL,需要设置wal_keep_segments参数以保证备份过程中WAL日志不会被覆盖
      • -X f/s --xlog-method=fetch/stream -X f与-x相同意义,s表示备份开始很厚启动另一个流复制连接组库接受WAL日志,避免了覆盖问题,但是需要与主库建立两个连季节,需要主库的max_wal_senders参数>=2
      • -c fast|spread --checkpoint=fast|spread 设置checkpoint的模式是fast还是会spread
      • -l label --lable=label 指定备份的一个标识,便于维护,基础备份pg_start_backup参数中的label,在backup_lable文件中记录
      • -P --progress 允许在备份过程中实时地打印备份的进度,不是百分百精确因为备份过程中还有写入
      • -R 产生recovery.conf文件,设置为备库需要摄者这个文几件的,意思是备份完就可以直接修改这个文件启动为备库了
      • -h host --host=host -p port --port=port
      • -s interval --status-interval=interval: 多长时间向服务器反馈状态,如果配置了流复制超时就需要设置次参数,不然流复制就超时了
      • -U username --username=username
      • -w --no-password 不提示输入密码 -W --password 强制输入密码
    • eg: pg_basebackup -h xxx -u xx -F p -P -x -R -D /hoame/xxx/xxx -l backup_xxx
  • 9.2后有级联复制,从备库备份注意事项
  • 搭建异步复制的hot_standby
    • 主库配置三个参数
    • 在standby机器上生成基础备份 pg_basebackup -h xx -U xx -F p -P -x -R -D xxx -l xx
    • 备库上检查recovery.conf文件
      • standby_mode=‘on’
      • primary_conninfo=‘host=10.125.51.225 port=3006 user=replicator password=YUT0hCmiBe27Joxy sslmode=prefer sslcompression=1 krbsrvname=postgres application_name=standby1’
      • recovery_target_timeline=‘latest’
      • trigger_file=’/home/pgsql/rm-rdszjk_pg10_test/postgresql.trigger’
    • 修改standby的postgresql.conf 文件中的hot_standby=on
    • 启动standby
  • 同步复制standby (一般是一主多备,防止一个备挂了影响主库)
    • 主库要配置参数synchronous_standby_names 指定standby的名称,这个名称就是standby中recovery.conf文件中primary_conninfo中设置的application_name,主库设置次参数需要reload配置,参数中的顺序决定了谁默认是同步谁是异步,当第一个同步有问题时会自动切换为第二个
    • 如果备库有问题,影响到主库只会影响写不会影响读
  • 流复制监控
    • select *from pg_stat_replication 主库上 select * from pg_replication_slots; 这个是查看有没有消费log的地方
      • sent_location: 发送WAL位置
      • write_location: standby写WAL日志的位置
      • flush_location: standby写WAL日志刷新到磁盘的位置
      • replay_location: standby重放WAL日志位置
      • 延迟存在的点,1.主库实际WAL位置和发送位置延迟,2.发送位置和重放位置延迟
    • 查看备库落后主库多少字节的WAL 只能主库上查询
      • pg9: select pg_xlog_location_diff(pg_current_xlog_location(),replay_location) from pg_stat_replication
      • pg10: select pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn) from pg_stat_replication
      • 将WAL位置转换为偏移量,select * from pg_xlogfile_name_offset(‘位置十六进制’)
    • 备库上查看位置
      • select pg_is_wal_replay_paused(); 查看wal应用是否暂停了 这个只能在备库上执行
      • select pg_last_xlog_receive_location() select pg_last_wal_receive_lsn() 查看wal接收到的位点
      • select pg_last_xlog_replay_location() select pg_last_wal_replay_lsn() 查看wal应用到的位点
      • select pg_last_xact_replay_timestamp() select pg_last_xact_replay_timestamp() 应用wal最后一个事务执行的时间,这个参数不可以作为延迟时间,因为是执行时间,只能看最后同步时间
    • 备库上操作主备
      • select pg_wal_replay_pause(); 暂停wal的应用 等于stop slave sql_thread
      • select pg_is_wal_replay_paused(); 查看是否返回t,t证明暂停了
      • select pg_wal_replay_resume(); 恢复复制 等于start slave sql_thread
      • select pg_is_wal_replay_paused(); 查看是否返回f,f证明恢复了
    • 查看当前的xlog:
      • pg9: select pg_xlogfile_name(pg_current_xlog_location()); select pg_walfile_name(pg_current_wal_location())
      • pg10:
    • 主库查看同步状态
      pg9  没用的,备库pg_stat_replication中没记录,所以下面语句只能在主库执行才有记录
       select client_addr, application_name,
       case pg_is_in_recovery() when true then
            pg_xlog_location_diff(pg_last_xlog_replay_location(), flush_location)
       else
            pg_xlog_location_diff(pg_current_xlog_location(), flush_location)
       end
       from pg_stat_replication;
      
    pg10
      select client_addr, application_name,
      case pg_is_in_recovery() when true then
           pg_wal_lsn_diff(pg_last_wal_replay_lsn(), flush_lsn)
      else
           pg_wal_lsn_diff(pg_current_wal_lsn(), flush_lsn)
      end
      from pg_stat_replication;
    
      select client_addr, application_name, sync_state, state,
        pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn)) as sent_delay,      
        pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), write_lsn)) as write_delay,   
        pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), flush_lsn)) as flush_delay,   
        pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)) as replay_delay   
      from pg_stat_replication;  
      pg_size_pretty 自动把数字转换为了KB MB  需要自己做判断
      sent_lsn:  发送到备库的上个事务日志位置
      write_lsn: 发送到备库并写入到磁盘的上个事务日志位置
      flush_lsn: 发送备库并写入磁盘且刷新到磁盘的上个事务日志位置
      replay_lsn: 备库上应用到数据库的上个事务日志位置
     ```
    
  • 查看备库状态
    • select pg_is_in_recovery() : 如果当前是备库返回true,主库返回false
    • 不登录数据库可以用pg_controldata来判断,pg_controldata -D xxx |grep cluster, 主库 in production 备库 in archive recovery
  • 激活备库为主库
    • 1.通过备库recovery.conf中的trigger文件
    • 2.pg_ctrl promote -D datadir 此时备库中recovery.conf会变为recovery.done
  • 主库降级为备库
    • 修改recovery.conf 设置host和port 重启
    • 如果发现new timeline 2 forked off current database system timeline 1 before current recovery point 说明时间线不同了需要修复时间线
      • 先停止服务
      • pg_rewind /u01/pgsql/bin/pg_rewind --target-pgdata=/u01/pg3306/data --source-server=‘host=10.125.50.199 port=3306 user=pgsql dbname=postgres password=pgsql’
      • 执行pg_rewind需要wal_log_hints 设置成 on 或者 PG 在初始化时开启 checksums 功能
  • 流复制注意事项
    • wal_keep_segments: 主库的wal日志会回卷覆盖,默认这个参数为0,就是不特意保存wal,当打开流复制时一定要设置这个参数,防止主备延迟日志覆盖导致备库永远跟不上主库,这个值是个数字,表是保留多少个wal,每个wal默认16M,所以16*wal_keep_segments就是日志最大占用磁盘空间
    • vacuum_defer_cleanup_age: 主库的清理进程vacuum会定时清理那些旧版本(删除标记变更标记)的数据,因为他知道这些数据主库已经不需要了,但是不知道备库还需不需要,可以设置这个参数代表延迟多少个事务清理,让主库延迟清理
  • 注意
    • pg变更参数会检查主备参数一致性(max_connections, max_worker_processes, max_prepared_transactions),如果备库的比主库小,则备库拉不起来

pg_waldump 解析log

Usage:
  pg_waldump [OPTION]... [STARTSEG [ENDSEG]]

STARTSEG    从指定的日志段文件开始读取。这也隐含地决定了要搜索文件的路径以及 要使用的时间线。
ENDSEG      在读取指定的日志段文件后停止。
Options:
  -b, --bkp-details      输出有关备份块的细节。
  -e, --end=RECPTR       在指定的日志位置停止读取,而不是一直读取到日志流的末尾。
  -f, --follow           在到达可用 WAL 的末尾之后,保持每秒轮询一次是否有新的 WAL 出现。
  -n, --limit=N          显示指定数量的记录,然后停止。
  -p, --path=PATH        要在哪个目录中寻找日志段文件。默认是在当前目录的pg_xlog 子目录中搜索。
  -r, --rmgr=RMGR        只显示由指定资源管理器生成的记录。如果把list作为资源管理器名称 传递给这个选项,则打印出可用资源管理器名称的列表然后退出。
  -s, --start=RECPTR     要从哪个日志位置开始读取。默认是从找到的最早的文件的第一个可用日志记录开始。
  -t, --timeline=TLI     要从哪个时间线读取日志记录。默认是使用startseg(如果指定) 中的值,否则默认为 1
  -V, --version          打印pg_xlogdump版本并且退出。
  -x, --xid=XID         只显示用给定事务 ID 标记的记录。
  -z, --stats[=record]   显示概括统计信息(记录的数量和尺寸以及全页镜像)而不是显示 每个记录。可以选择针对每个记录生成统计信息,而不是针对每个 资源管理器生成。
  -?, --help             show this help, then exit
  • 查看log的第一个 Transaction 时间 /u01/pgsql/bin/pg_waldump …/00000002000000070000002C -r Transaction|head -n 1
  • 查看log的最后一个Transaction时间 /u01/pgsql/bin/pg_waldump …/00000002000000070000002C -r Transaction|tail -n 1

注意

  • pg主备切换后,新主库会出现一个.partial的wal日志,是因为主备切换要变更时间线,那个未完成的log会变为.partial,然后把.partial的内容全部拷贝到新时间线的log中,如果此时使用pg_receivewal传日志会因为遇到.partial而报错, clone实例影响较大,此时需要等待备份上传后,使用备份中的log,备份也会上传.partial的日志,下载完备份日志会删掉所有.partial,所以不妨碍

压测

yum install -y postgresql-contrib 安装pgbench包

第三方软件

  • pgbouncer: 连接池,防止每个连接pg都创建进程耗费资源
  • bucardo: 双向同步软件,可实现双master
  • PL/Proxy: 实现分库分表的,水平拆分中间件
  • Postgres-XC: 基于postgresql数据库实现的真正的数据水平拆分的分布式数据库

pg引号处理

‘’’
su - pgsql -c “/u01/pgsql/bin/psql -p3306 postgres -c ‘create user zjk with rds_superuser replication login password ‘’‘123’’’;’”

你可能感兴趣的:(postgresql)