概述
PostgreSQL 中的所有数据都存储在对应的文件中,即我们常见到的文件。这些用来存储数据的文件共同构成了 PostgreSQL 整个数据库集簇,而数据库集簇是对 PostgreSQL 中多个数据库组成的集合的称呼。而在逻辑上,PostgreSQL 所有的数据库都是隶属于某个表空间,并且单个数据库不能跨表空间,而一个表空间中可以存放多个数据库。表空间和数据库的关系属于多对多的关系。那么数据库中的数据是如何存放在数据文件中的呢?接下来一起探究。
理解 oid 和 relfilenode 的关系
在 PostgreSQL 中,oid 全称为 Object identifier,称为对象标识符,在 PostgreSQL 中,用于为每个对象分配的一个内部主键数据类型,其别名为 regclass,并且 oid 可以转换为整数。而 relfilenode 则为 PostgreSQL 数据库中对对象的物理访问信息。relfilenode 关联三个对应的oid,即表空间的oid,数据库的oid和对象的oid。默认,在创建一个对象时,会为该对象使用 oid 映射到 relfilenode 编号。内部采用 RelMapping 的方式进行映射,因此,在 PostgreSQL 中,所有对象的管理通过 oid 来管理内部对象,外部文件却通过 relfilenode 来管理。
postgres=# CREATE TABLE tab_test(id int,name varchar);
CREATE TABLE
postgres=# INSERT INTO tab_test VALUES(1,'PostgreSQL');
INSERT 0 1
postgres=# SELECT relname,oid,relfilenode FROM pg_class WHERE relname = 'tab_test';
relname | oid | relfilenode
----------+-------+-------------
tab_test | 16384 | 16384
(1 row)
通过上面的示例可以观察到创建的新的对象 oid 和 relfilenode 是一样的。其中默认的第一个 oid 为 16384
#define FirstNormalObjectId 16384
那么问题来了,如果在一个并发的多事务环境中,创建的对象会不会有冲突。
--事务1
postgres=# BEGIN;
BEGIN
postgres=*# CREATE TABLE tab_test(id int,name varchar);
CREATE TABLE
postgres=*# SELECT relname,oid,relfilenode FROM pg_class WHERE relname = 'tab_test'; rel