pg_wal中文件的名称中的logseq和实际文件中的logseq不匹配

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:pg_wal中文件的名称中的logseq和实际文件中的logseq不匹配

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

一个朋友由于某种原因给我发了一个pg_wal里面的wal文件,让我帮忙分析下故障原因,我打开文件之后发现文件编号小的修改时间比编号大的文件修改时间要新
pg_wal


wal日志文件命名规则:
我们看到的wal日志是这样的:0000000100004D6E000000CF
其中前8位:00000001表示timeline
中间8位:00004D6E表示logid
最后8位:000000CF表示logseg
在上述截图中,可以看到logseq为CF的文件比D0的要新很多,这个初步给人感觉不太正常.使用pg_waldump分别对其进行dump操作
pg_waldump1

[postgres@xifenfei bin]$ pg_waldump /data/wal/0000000100004D6E000000D0|head -10
pg_waldump: fatal: could not find a valid record after 4D6E/D0000000

这样可以看出来CF的wal文件可以正常dump出来,但是D0的文件dump报pg_waldump: fatal: could not find a valid record after类似异常.通过od命令分别对两个文件进行分析

[postgres@xifenfei bin]$ od -x /data/wal/0000000100004D6E000000CF|head -1
0000000 d101 0006 0001 0000 0000 cf00 4d6e 0000
[postgres@xifenfei bin]$ od -x /data/wal/0000000100004D6E000000D0|head -1
0000000 d101 0007 0001 0000 0000 9400 4d6e 0000

从第8个字节到第12个字节结束为logseq的值,这里明显可以看出来D0文件的logseq值和实际文件中的不一致.尝试把D0修改为94之后即可正常的pg_waldump进行分析
pg_waldump2


通过这里可以的出来一个结论,pg_wal中文件的名称中的logseq和实际文件中的logseq不匹配.出现这种问题的本质是由于pg_wal中的wal日志是相当oracle的redo,是通过类似重命名机制(看到有文档介绍是说硬链接指向旧文件然后删除旧文件)引起的问题.

pg创建gbk字符集库

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:pg创建gbk字符集库

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

记录下,Postgres库创建中文字符集

postgres=# CREATE DATABASE mydb_gbk
postgres-#     ENCODING 'EUC_CN'
postgres-#     LC_COLLATE 'zh_CN' 
postgres-#     LC_CTYPE 'zh_CN'
postgres-#     TEMPLATE template0;
CREATE DATABASE
postgres=# \l
                                                 List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    | ICU Locale | Locale Provider |   Access privileges   
-----------+----------+----------+-------------+-------------+------------+-----------------+-----------------------
 mydb_gbk  | postgres | EUC_CN   | zh_CN       | zh_CN       |            | libc            | 
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | =c/postgres          +
           |          |          |             |             |            |                 | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | =c/postgres          +
           |          |          |             |             |            |                 | postgres=CTc/postgres
(4 rows)

前提系统必须支持zh_CN语言包,检查命令为:

[root@xifenfei yum.repos.d]# locale -a |grep zh_CN
zh_CN
zh_CN.gb18030
zh_CN.gbk
zh_CN.utf8

如果没有使用yum以下命令安装

yum groupinstall "fonts"
yum install glibc-langpack-zh.x86_64

PostgreSQL运行日志管理

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:PostgreSQL运行日志管理

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

PostgreSQL目前配置中,不直接记录日志文件,这样的情况给数据库后期出现问题(特别是无法正常启动的情况)分析带来很大麻烦,不知道具体问题所在,建议在PG安装完成之后,启用日志功能,便于数据库运行状态检查和错误跟踪,主要日志参数涉及以下配置

log_destination = 'stderr'              # Valid values are combinations of
                                        # stderr, csvlog, jsonlog, syslog, and
                                        # eventlog, depending on platform.
                                        # csvlog and jsonlog require
                                        # logging_collector to be on.

# This is used when logging to stderr:
logging_collector = on          # Enable capturing of stderr, jsonlog,
                                        # and csvlog into log files. Required
                                        # to be on for csvlogs and jsonlogs.
                                        # (change requires restart)
//是否将日志重定向至文件中,默认是off。

# These are only used if logging_collector is on:
log_directory = 'pg_log'                   # directory where log files are written,
                                        # can be absolute or relative to PGDATA
//日志文件目录,默认是PGDATA的相对路径,即PGDATA的相对路径,即{PGDATA}/pg_log,也可以改为绝对路径。
//日志文件可能会非常多,建议将日志重定向到其他目录或分区。
//将此配置修改其他目录时,必须先创建此目录,并修改权限,使得postgres用户对该目录有写权限。

log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # log file name pattern,
                                        # can include strftime() escapes
log_file_mode = 0600                    # creation mode for log files,
                                        # begin with 0 to use octal notation
log_rotation_age = 1d                   # Automatic rotation of logfiles will
                                        # happen after that time.  0 disables.
log_rotation_size = 10MB                # Automatic rotation of logfiles will
                                        # happen after that much log output.
                                        # 0 disables.
#log_truncate_on_rotation = off         # If on, an existing log file with the
                                        # same name as the new log file will be
                                        # truncated rather than appended to.
                                        # But such truncation only occurs on
                                        # time-driven rotation, not on restarts
                                        # or size-driven rotation.  Default is
                                        # off, meaning append to existing files
                                        # in all cases.
//当日志文件已存在时,该配置如果为off,新生成的日志将在文件尾部追加,如果为on,则会覆盖原来的日志。

上述配置得到的结果如下

[postgres@xifenfei pg_log]$ pwd
/data/pg/15/data/pg_log
[postgres@xifenfei pg_log]$ ls -l
total 4
-rw------- 1 postgres postgres 1263 Apr  3 22:37 postgresql-2025-04-03_223117.log

pglog


Navicat连接postgresql时出现column “datlastsysoid” does not exist错误解决

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:Navicat连接postgresql时出现column “datlastsysoid” does not exist错误解决

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

使用Navicat Premium 15访问PostgreSQL 16版本的库,报如下错误

ERROR:  column "datlastsysoid" does not exist
LINE 1: SELECT DISTINCT datlastsysoid FROM pg_database;

QQ20250308-105201
QQ20250308-105222


登录pg库查看

postgres=# SELECT DISTINCT datlastsysoid FROM pg_database;
2025-03-07 22:09:03.569 EST [62553] ERROR:  column "datlastsysoid" does not exist at character 17
2025-03-07 22:09:03.569 EST [62553] STATEMENT:  SELECT DISTINCT datlastsysoid FROM pg_database;
ERROR:  column "datlastsysoid" does not exist
LINE 1: SELECT DISTINCT datlastsysoid FROM pg_database;
                        ^
postgres=# \d pg_database;
               Table "pg_catalog.pg_database"
     Column     |   Type    | Collation | Nullable | Default 
----------------+-----------+-----------+----------+---------
 oid            | oid       |           | not null | 
 datname        | name      |           | not null | 
 datdba         | oid       |           | not null | 
 encoding       | integer   |           | not null | 
 datlocprovider | "char"    |           | not null | 
 datistemplate  | boolean   |           | not null | 
 datallowconn   | boolean   |           | not null | 
 datconnlimit   | integer   |           | not null | 
 datfrozenxid   | xid       |           | not null | 
 datminmxid     | xid       |           | not null | 
 dattablespace  | oid       |           | not null | 
 datcollate     | text      | C         | not null | 
 datctype       | text      | C         | not null | 
 daticulocale   | text      | C         |          | 
 daticurules    | text      | C         |          | 
 datcollversion | text      | C         |          | 
 datacl         | aclitem[] |           |          | 
Indexes:
    "pg_database_oid_index" PRIMARY KEY, btree (oid), tablespace "pg_global"
    "pg_database_datname_index" UNIQUE CONSTRAINT, btree (datname), tablespace "pg_global"
Tablespace: "pg_global"

确认没有了datlastsysoid列,通过查看文档确认从Postgres 15版本开始 pg_database表中删除了 datlastsysoid,但是可以通过查询dattablespace替代,使用二进制工具修改libcc.dll文件中的SELECT DISTINCT datlastsysoid部分语句为:SELECT DISTINCT dattablespace
QQ20250308-105427
QQ20250308-105455


然后重新启动Navicat,访问pg库正常
QQ20250308-111555

当然这个问题如果使用高版本的Navicat或者访问低版本的PostgreSQL库不会出现

PostgreSQL部分主要字典信息

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:PostgreSQL部分主要字典信息

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

一、pg_class:

该系统表记录了数据表、索引(仍然需要参阅pg_index)、序列、视图、复合类型和一些特殊关系类型的元数据。注意:不是所有字段对所有对象类型都有意义。

名字 类型 引用 描述
relname name 数据类型名字。
relnamespace oid pg_namespace.oid 包含这个对象的名字空间(模式)的OI。
reltype oid pg_type.oid 对应这个表的行类型的数据类型。
relowner oid pg_authid.oid 对象的所有者。
relam oid pg_am.oid 对于索引对象,表示该索引的类型(B-tree,hash)。
relfilenode oid 对象存储在磁盘上的文件名,如果没有则为0。
reltablespace oid pg_tablespace.oid 对象所在的表空间。如果为零,则表示使用该数据库的缺省表空间。(如果对象在磁盘上没有文件,这个字段就没有什么意义)
relpages int4 该数据表或索引所占用的磁盘页面数量,查询规划器会借助该值选择最优路径。
reltuples float4 表中行的数量,该值只是被规划器使用的一个估计值。
reltoastrelid oid pg_class.oid 与此表关联的TOAST表的OID,如果没有为0。TOAST表在一个从属表里”离线”存储大字段。
reltoastidxid oid pg_class.oid 如果是TOAST表,该字段为它索引的OID,如果不是TOAST表则为0。
relhasindex bool 如果这是一个数据表而且至少有(或者最近有过)一个索引,则为真。它是由CREATE INDEX设置的,但DROP INDEX不会立即将它清除。如果VACUUM发现一个表没有索引,那么它清理 relhasindex。
relisshared bool 如果该表在整个集群中由所有数据库共享,则为真。
relkind char r = 普通表,i = 索引,S = 序列,v = 视图, c = 复合类型,s = 特殊,t = TOAST表
relnatts int2 数据表中用户字段的数量(除了系统字段以外,如oid)。在pg_attribute里肯定有相同数目的数据行。见pg_attribute.attnum.
relchecks int2 表中检查约束的数量,参阅pg_constraint表。
reltriggers int2 表中触发器的数量;参阅pg_trigger表。
relhasoids bool 如果我们为对象中的每行都生成一个OID,则为真。
relhaspkey bool 如果该表存在主键,则为真。
relhasrules bool 如表有规则就为真;参阅pg_rewrite表。
relhassubclass bool 如果该表有子表,则为真。
relacl aclitem[] 访问权限。

二、pg_attribute:

该系统表存储所有表(包括系统表,如pg_class)的字段信息。数据库中的每个表的每个字段在pg_attribute表中都有一行记录。

名字 类型 引用 描述
attrelid oid pg_class.oid 此字段所属的表。
attname name 字段名。
atttypid oid pg_type.oid 字段的数据类型。
attstattarget int4 attstattarget控制ANALYZE为这个字段设置的统计细节的级别。零值表示不收集统计信息,负数表示使用系统缺省的统计对象。正数值的确切信息是和数据类型相关的。
attlen int2 该字段所属类型的长度。(pg_type.typlen的拷贝)
attnum int2 字段的编号,普通字段是从1开始计数的。系统字段,如oid,是任意的负数。
attndims int4 如果该字段是数组,该值表示数组的维数,否则是0。
attcacheoff int4 在磁盘上总是-1,但是如果装载入内存中的行描述器中, 它可能会被更新为缓冲在行中字段的偏移量。
atttypmod int4 表示数据表在创建时提供的类型相关的数据(比如,varchar字段的最大长度)。其值对那些不需要atttypmod的类型而言通常为-1。
attbyval bool pg_type.typbyval字段值的拷贝。
attstorage char pg_type.typstorage字段值的拷贝。
attalign char pg_type.typalign字段值的拷贝。
attnotnull bool 如果该字段带有非空约束,则为真,否则为假。
atthasdef bool 该字段是否存在缺省值,此时它对应pg_attrdef表里实际定义此值的记录。
attisdropped bool 该字段是否已经被删除。如果被删除,该字段在物理上仍然存在表中,但会被分析器忽略,因此不能再通过SQL访问。
attislocal bool 该字段是否局部定义在对象中的。
attinhcount int4 该字段所拥有的直接祖先的个数。如果一个字段的祖先个数非零,那么它就不能被删除或重命名。

三、pg_attrdef:

该系统表主要存储字段默认值,字段中的主要信息存放在pg_attribute系统表中。注意:只有明确声明了缺省值的字段在该表中才会有记录。

名字 类型 引用 描述
adrelid oid pg_class.oid 这个字段所属的表
adnum int2 pg_attribute.attnum 字段编号,其规则等同于pg_attribute.attnum
adbin text 字段缺省值的内部表现形式。
adsrc text 缺省值的人可读的表现形式。

四、pg_constraint:

该系统表存储PostgreSQL中表对象的检查约束、主键、唯一约束和外键约束。

名字 类型 引用 描述
conname name 约束名字(不一定是唯一的)。
connamespace oid pg_namespace.oid 包含这个约束的名字空间(模式)的OID。
contype char c = 检查约束, f = 外键约束, p = 主键约束, u = 唯一约束
condeferrable bool 该约束是否可以推迟。
condeferred bool 缺省时这个约束是否是推迟的?
conrelid oid pg_class.oid 该约束所在的表,如果不是表约束则为0。
contypid oid pg_type.oid 该约束所在的域,如果不是域约束则为0。
confrelid oid pg_class.oid 如果为外键,则指向参照的表,否则为0。
confupdtype char 外键更新动作代码。
confdeltype char 外键删除动作代码。
confmatchtype char 外键匹配类型。
conkey int2[] pg_attribute.attnum 如果是表约束,则是约束控制的字段列表。
confkey int2[] pg_attribute.attnum 如果是外键,则是参照字段的列表。
conbin text 如果是检查约束,则表示表达式的内部形式。
consrc text 如果是检查约束,则是表达式的人可读的形式。

五、pg_tablespace:

该系统表存储表空间的信息。注意:表可以放在特定的表空间里,以帮助管理磁盘布局和解决IO瓶颈。

名字 类型 引用 描述
spcname name 表空间名称。
spcowner oid pg_authid.oid 表空间的所有者,通常是创建它的角色。
spclocation text 表空间的位置(目录路径)。
spcacl aclitem[] 访问权限。

六、pg_namespace:

该系统表存储名字空间(模式)。

名字 类型 引用 描述
nspname name 名字空间(模式)的名称。
nspowner oid pg_authid.oid 名字空间(模式)的所有者
nspacl aclitem[] 访问权限。

七、pg_database:

该系统表存储数据库的信息。和大多数系统表不同的是,在一个集群里该表是所有数据库共享的,即每个集群只有一份pg_database拷贝,而不是每个数据库一份。

名字 类型 引用 描述
datname name 数据库名称。
datdba oid pg_authid.oid 数据库所有者,通常为创建该数据库的角色。
encoding int4 数据库的字符编码方式。
datistemplate bool 如果为真,此数据库可以用于CREATE DATABASE TEMPLATE子句,把新数据库创建为此数据库的克隆。
datallowconn bool 如果为假,则没有人可以联接到这个数据库。
datlastsysoid oid 数据库里最后一个系统OID,此值对pg_dump特别有用。
datvacuumxid xid
datfrozenxid xid
dattablespace text pg_tablespace.oid 该数据库的缺省表空间。在这个数据库里,所有pg_class.reltablespace为零的表都将保存在这个表空间里,特别要指出的是,所有非共享的系统表也都存放在这里。
datconfig text[] 运行时配置变量的会话缺省值。
datacl aclitem[] 访问权限。

八、pg_index:

该系统表存储关于索引的一部分信息。其它的信息大多数存储在pg_class。

名字 类型 引用 描述
indexrelid oid pg_class.oid 该索引在pg_class里的记录的OID。
indrelid oid pg_class.oid 索引所在表在pg_class里的记录的OID。
indnatts int2 索引中的字段数量(拷贝的pg_class.relnatts)。
indisunique bool 如果为真,该索引是唯一索引。
indisprimary bool 如果为真,该索引为该表的主键。
indisclustered bool 如果为真,那么该表在这个索引上建了簇。
indkey int2vector pg_attribute.attnum 该数组的元素数量为indnatts,数组元素值表示建立这个索引时所依赖的字段编号,如1 3,表示第一个字段和第三个字段构成这个索引的键值。如果为0,则表示是表达式索引,而不是基于简单字段的索引。
indclass oidvector pg_opclass.oid 对于构成索引键值的每个字段,这个字段都包含一个指向所使用的操作符表的OID。
indexprs text 表达式树用于那些非简单字段引用的索引属性。它是一个列表,在indkey里面的每个零条目一个元素。如果所有索引属性都是简单的引用,则为空。
indpred text 部分索引断言的表达式树。如果不是部分索引, 则是空字串。