PostgreSQL笔记20: 实例、集群、模板数据库与表空间 —— 逻辑体系架构深度解析

别再搞混了!5分钟搞懂PostgreSQL的实例、数据库和Schema到底啥关系 本文详细解析了PostgreSQL中实例、数据库和Schema的逻辑结构关系,帮助开发者清晰理解这三者的区别与联系。通过生活场景类比和实战示例,特别针对MySQL转PG的开发者常见误区进行讲解,并分享Schema权限管理的高级技巧,提升数据库设计效率。 阅读详情

纲要

  • Database Cluster(数据库集群)与 Instance(实例)的概念辨析
    • Cluster 的物理存储视角
    • Instance 的运行时视角
  • Database、Schema、Object 的逻辑层级结构
    • 跨数据库访问的限制:dblink 与 postgres_fdw
  • Template Database(模板数据库):template0 与 template1
    • CREATE DATABASE 的复制机制
    • template0 的“原始”用途与编码/区域设置
    • datistemplate 与 datallowconn 标志
  • Tablespace(表空间)
    • CREATE TABLESPACE 与软链接机制
    • pg_default 与 pg_global 默认表空间
    • 冷热分离的存储策略
  • OID(Object Identifier,对象标识符)
    • pg_class 系统表与 regclass 类型
    • oid2name 工具

Database Cluster 与 Instance

在 PostgreSQL 的体系架构中,Database Cluster(数据库集群,SQL 标准中称为 Catalog Cluster)与 Instance(实例)是两个最基础的概念。

Database Cluster 指的是由单个正在运行的数据库服务器实例管理的一组数据库的集合。从文件系统的角度看,一个 Database Cluster 就是一个目录(即 PGDATA 所指向的数据目录),该目录下存放了该集群中所有数据库的全部数据文件。

Instance(实例)则是指正在运行的 postgres 进程及其所管理的内存结构与后台进程。一个 postgres 实例在任何时刻都恰好管理一个 Database Cluster 的数据。在一台物理主机上,可以运行多个 PostgreSQL 实例,只要它们使用不同的数据目录和不同的通信端口即可。

在 PostgreSQL 的官方术语中,“实例”与“数据库集群”在非正式语境下有时会被混用,但严格区分如下:

  • Instance(实例) :运行时的概念,指 postgres 主进程、子进程以及共享内存等运行时资源。
  • Cluster(集群) :存储与数据的概念,指 PGDATA 目录下的全部数据文件与配置文件。

一个 Database Cluster 在初始化(通过 initdb)后,会默认包含三个数据库:postgres、template1 和 template0。postgres 是供工具程序和用户连接的默认数据库。

# 初始化一个数据库集群
initdb -D /usr/local/pgsql/data
# 通过 pg_ctl 启动实例
pg_ctl -D /usr/local/pgsql/data start

Database、Schema 与 Object 的逻辑层级

在一个 Database Cluster 内部,PostgreSQL 的逻辑组织结构为:Cluster → Database → Schema → Object。

  • Database(数据库) :相互隔离的逻辑容器。PostgreSQL 中的各个数据库之间是严格隔离的,默认情况下不支持跨数据库的直接访问。
  • Schema(模式) :数据库内部的命名空间。默认情况下,用户创建的对象(如表、索引、视图、函数、序列、触发器、存储过程等)都位于 public 模式下。
  • Object(对象) :具体的数据库实体,包括 TABLE、INDEX、VIEW、FUNCTION、SEQUENCE、TRIGGER、PROCEDURE 等。

PostgreSQL 的跨数据库访问(Cross-Database Reference)默认不被支持。以下示例展示了尝试跨库查询时的错误:

-- 创建两个数据库
CREATE DATABASE mydb1;
CREATE DATABASE mydb2;

\c mydb1
CREATE TABLE t1 (id int);

-- 尝试跨库查询(会报错)
\c mydb2
SELECT * FROM mydb1.public.t1;
-- ERROR:  cross-database references are not implemented

要实现跨数据库访问,官方提供了两种标准方案:

  1. dblink 模块:基于函数的较老方案,通过 dblink_connect() 建立连接后执行远程查询。
  2. postgres_fdw 模块:基于 SQL/MED(Foreign Data Wrapper)标准的较新方案,语法更透明,性能更优。
-- 使用 postgres_fdw 访问同一集群内的另一个数据库
CREATE EXTENSION postgres_fdw;

CREATE SERVER mydb1_server FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (dbname 'mydb1', host 'localhost', port '5432');

CREATE USER MAPPING FOR CURRENT_USER
SERVER mydb1_server
OPTIONS (user 'postgres');

CREATE FOREIGN TABLE remote_t1 (id int)
SERVER mydb1_server
OPTIONS (schema_name 'public', table_name 't1');

-- 现在可以像访问本地表一样查询远程表
SELECT * FROM remote_t1;

Database Cluster

Database A

Database B

Schema: public

Schema: other

Table

Index

View

Function

Sequence

Trigger

Table

Schema: public

Table

Template Databases(模板数据库)

CREATE DATABASE 命令在 PostgreSQL 中实际上是通过复制一个现有数据库来工作的。默认情况下,它复制名为 template1 的标准系统数据库。

template1

template1 是创建新数据库的默认模板。如果在 template1 中添加了对象(如扩展、函数、表等),这些对象会被自动复制到所有后续创建的用户数据库中。这使得 DBA 可以方便地对所有新数据库进行“站点本地定制”。

template0

template0 是第二个标准系统数据库。它包含的是 PostgreSQL 版本预定义的标准对象,不包含任何用户添加的内容。template0 在数据库集群初始化后不应被修改。

使用 template0 作为模板创建数据库主要有两个场景:

  1. 恢复 pg_dump 转储:确保恢复到一个“原始”状态的数据库中,避免与 template1 中的站点本地对象产生冲突。
  2. 指定不同的编码或区域设置(Locale) :复制 template1 时必须使用与 template1 相同的编码和区域设置,而复制 template0 时可以指定新的编码和区域设置。
-- 使用 template0 创建数据库,并指定不同的编码和排序规则
CREATE DATABASE mydb3
TEMPLATE template0
ENCODING 'UTF8'
LC_COLLATE 'C'
LC_CTYPE 'C';
-- 查看数据库的模板属性
SELECT datname, datistemplate, datallowconn
FROM pg_database;

pg_database 系统表中的两个标志列控制着模板数据库的行为:

  • datistemplate :若为 true,任何具有 CREATEDB 权限的用户都可以克隆该数据库;若为 false,则只有超级用户和数据库所有者可以克隆。
  • datallowconn :若为 false,则不允许对该数据库建立新的连接。template0 通常被标记为 datallowconn = false 以防止被意外修改。
-- 将一个现有数据库标记为模板数据库
UPDATE pg_database SET datistemplate = true WHERE datname = 'my_template_db';

快速克隆数据库

利用模板数据库的特性,可以快速“克隆”(fork)一个现有的数据库:

-- 基于现有的 mydb 快速创建一个新数据库 mydb_clone
CREATE DATABASE mydb_clone TEMPLATE mydb;

目标数据库

模板层

源数据库

CREATE DATABASE ... TEMPLATE mydb

默认

TEMPLATE template0

mydb

template1

template0

新数据库

新数据库
ENCODING=UTF8
LC_COLLATE=C

Tablespace(表空间)

Tablespace(表空间)允许数据库管理员在文件系统中定义存储数据库对象文件的位置。创建表空间后,可以在创建数据库对象时按名称引用。

创建表空间

-- 首先在操作系统中创建空目录
-- mkdir -p /ssd1/postgresql/data
-- chown postgres:postgres /ssd1/postgresql/data

CREATE TABLESPACE fastspace
LOCATION '/ssd1/postgresql/data';

表空间的 LOCATION 必须是一个已存在的、空目录,并且必须由 PostgreSQL 操作系统用户拥有。

默认表空间

数据库集群初始化时会自动创建两个表空间:

表空间用途映射路径
pg_default存储用户数据(非共享对象)$PGDATA/base/
pg_global存储共享系统目录$PGDATA/global/

pg_default 是 template1 和 template0 的默认表空间,因此也是绝大多数新数据库的默认表空间。

表空间的使用

-- 在指定表空间中创建表
CREATE TABLE foo (i int) TABLESPACE fastspace;

-- 在指定表空间中创建索引
CREATE INDEX idx_foo_i ON foo(i) TABLESPACE fastspace;

-- 创建数据库时指定默认表空间
CREATE DATABASE mydb TABLESPACE fastspace;
-- 设置会话级别的默认表空间
SET default_tablespace = fastspace;
CREATE TABLE bar (j int);  -- 自动使用 fastspace

冷热分离策略

表空间的核心应用场景之一是冷热数据分离:

  • 热数据(频繁访问的表和索引)放置在 SSD 上的表空间(如 fastspace)。
  • 冷数据(历史归档表、不常访问的索引)放置在大容量 HDD 上的表空间(如 slowspace)。

表空间的物理存储

PostgreSQL 中的表空间在文件系统层面通过软链接(symlink) 实现。表空间目录下会有一个 PG_<version>_<timestamp> 子目录,其中存储了该表空间中各数据库的 OID 目录。

# 查看表空间的软链接
ls -la $PGDATA/pg_tblspc/
# 示例输出:
# lrwxrwxrwx 1 postgres postgres 25 Jan 15 10:00 16384 -> /ssd1/postgresql/data

表空间的限制

  • 表空间是数据库集群的不可分割的一部分,不能单独备份或迁移到另一个集群。
  • 如果表空间丢失或损坏,整个数据库集群可能无法启动。
  • 表空间的存储容量受限于底层文件系统的容量。

自定义表空间

$PGDATA (数据目录)

pg_global

pg_default

base/

global/

pg_tblspc/

软链接 (OID)

PG__/

数据库 OID 目录/

数据文件

共享系统目录

用户数据

OID(Object Identifier,对象标识符)

OID(Object Identifier,对象标识符)是 PostgreSQL 内部用于标识各种系统表主键的 32 位整数。

在文件系统层面,PostgreSQL 使用 OID 来组织数据文件。$PGDATA/base/ 目录下的数字目录名就是数据库的 OID,而其中的数字文件名则是表或索引的 relfilenode(通常与 OID 一致或相关)。

-- 查询数据库的 OID
SELECT oid, datname FROM pg_database;

-- 查询表的 OID 和 relfilenode
SELECT oid, relname, relfilenode
FROM pg_class
WHERE relname = 'foo';

PostgreSQL 提供了 regclass 别名类型,可以将表名转换为 OID:

-- 使用 regclass 将表名转换为 OID
SELECT 'foo'::regclass::oid;

oid2name 工具

PostgreSQL 提供了 oid2name 命令行工具,用于将 OID 映射为对应的对象名称:

# 查看指定 OID 对应的对象名称
oid2name -d mydb -o 16384

# 列出数据库中所有表及其 OID
oid2name -d mydb -s

API 速览(API Overview)

数据库管理 API

API所属模块方法签名说明
CREATE DATABASEPostgreSQL DDLCREATE DATABASE name [WITH] [TEMPLATE template] [ENCODING encoding] [LC_COLLATE collate] [LC_CTYPE ctype] [TABLESPACE tablespace]创建新数据库,可通过 TEMPLATE 指定模板
DROP DATABASEPostgreSQL DDLDROP DATABASE name删除数据库
ALTER DATABASEPostgreSQL DDLALTER DATABASE name SET parameter = value修改数据库配置

表空间管理 API

API所属模块方法签名说明
CREATE TABLESPACEPostgreSQL DDLCREATE TABLESPACE name LOCATION 'directory'创建表空间
DROP TABLESPACEPostgreSQL DDLDROP TABLESPACE name删除空表空间
SET default_tablespacePostgreSQL GUCSET default_tablespace = 'name'设置会话级默认表空间

系统目录查询 API

API所属模块方法签名说明
pg_database系统表SELECT * FROM pg_database查询所有数据库及其属性(datistemplate、datallowconn)
pg_class系统表SELECT * FROM pg_class查询所有表和索引的元数据(oid、relname、relfilenode)
::regclassPostgreSQL 类型转换'table_name'::regclass将表名转换为 OID
oid2name命令行工具oid2name -d dbname -o oid将 OID 映射为对象名称

跨库访问 API

API所属模块方法签名说明
dblink_connectdblinkdblink_connect(text connstr)建立跨库连接
dblinkdblinkdblink(text connname, text sql)执行远程 SQL 查询
CREATE FOREIGN DATA WRAPPERpostgres_fdwCREATE FOREIGN DATA WRAPPER name创建外部数据包装器
CREATE SERVERpostgres_fdwCREATE SERVER name FOREIGN DATA WRAPPER fdw OPTIONS (...)创建外部服务器
CREATE FOREIGN TABLEpostgres_fdwCREATE FOREIGN TABLE name (...) SERVER server OPTIONS (...)创建外部表映射

Demo 完整示例(Complete Demo)

以下是一个基于 Node.js 和 node-postgres(pg 库)的完整演示,涵盖数据库连接、模板数据库创建、表空间操作和系统目录查询。

# 项目初始化
mkdir pg-demo && cd pg-demo
npm init -y
npm install pg
// index.ts
import { Client, Pool } from 'pg';

// PostgreSQL 连接配置
const config = {
  host: 'localhost',
  port: 5432,
  user: 'postgres',
  password: 'postgres',
  database: 'postgres',
};

// 创建连接池
const pool = new Pool(config);

/**
 * 执行 SQL 查询的辅助函数
 */
async function executeQuery(sql: string, params: any[] = []): Promise<any> {
  const client = await pool.connect();
  try {
    const result = await client.query(sql, params);
    return result.rows;
  } finally {
    client.release();
  }
}

/**
 * 核心 Demo:展示 PostgreSQL 逻辑体系架构的核心操作
 */
async function main() {
  console.log('=== PostgreSQL 逻辑体系架构 Demo ===\n');

  // 1. 查看数据库集群中的数据库列表
  console.log('1. 当前数据库集群中的所有数据库:');
  const dbs = await executeQuery(
    `SELECT oid, datname, datistemplate, datallowconn 
     FROM pg_database 
     ORDER BY datname`
  );
  console.table(dbs);

  // 2. 创建模板数据库
  console.log('\n2. 创建一个自定义模板数据库 (my_template):');
  await executeQuery(`DROP DATABASE IF EXISTS my_template`);
  await executeQuery(`CREATE DATABASE my_template`);
  await executeQuery(`\c my_template`);
  await executeQuery(`CREATE TABLE template_table (id int, name text)`);
  await executeQuery(`INSERT INTO template_table VALUES (1, 'template data')`);
  // 标记为模板数据库
  await executeQuery(
    `UPDATE pg_database SET datistemplate = true WHERE datname = 'my_template'`
  );
  console.log('   ✓ 模板数据库 my_template 创建完成,并标记为 datistemplate = true');

  // 3. 基于模板数据库创建新数据库
  console.log('\n3. 基于 my_template 克隆新数据库 (cloned_db):');
  await executeQuery(`DROP DATABASE IF EXISTS cloned_db`);
  await executeQuery(`CREATE DATABASE cloned_db TEMPLATE my_template`);
  console.log('   ✓ 克隆数据库 cloned_db 创建完成');

  // 4. 验证克隆结果
  console.log('\n4. 验证克隆结果 (查询 cloned_db 中的数据):');
  const rows = await executeQuery(
    `SELECT * FROM cloned_db.public.template_table`
  );
  console.table(rows);

  // 5. 使用 template0 创建指定编码的数据库
  console.log('\n5. 使用 template0 创建指定 LC_COLLATE=C 的数据库 (mydb_c):');
  await executeQuery(`DROP DATABASE IF EXISTS mydb_c`);
  await executeQuery(`
    CREATE DATABASE mydb_c 
    TEMPLATE template0 
    ENCODING 'UTF8' 
    LC_COLLATE 'C' 
    LC_CTYPE 'C'
  `);
  console.log('   ✓ 数据库 mydb_c 创建完成 (LC_COLLATE = C)');

  // 6. 验证排序规则
  console.log('\n6. 验证数据库的排序规则:');
  const collateInfo = await executeQuery(
    `SELECT datname, datcollate, datctype FROM pg_database WHERE datname = 'mydb_c'`
  );
  console.table(collateInfo);

  // 7. 表空间操作
  console.log('\n7. 表空间操作:');
  // 查看现有表空间
  const tablespaces = await executeQuery(
    `SELECT spcname, pg_tablespace_location(oid) as location 
     FROM pg_tablespace`
  );
  console.log('   当前表空间列表:');
  console.table(tablespaces);

  // 8. OID 查询
  console.log('\n8. OID 查询示例:');
  // 切换到 cloned_db 创建测试表
  await executeQuery(`\c cloned_db`);
  await executeQuery(`CREATE TABLE IF NOT EXISTS test_oid (id int)`);
  const oidInfo = await executeQuery(
    `SELECT oid, relname, relfilenode 
     FROM pg_class 
     WHERE relname = 'test_oid'`
  );
  console.table(oidInfo);

  // 使用 regclass 转换
  const regclassResult = await executeQuery(
    `SELECT 'test_oid'::regclass::oid as oid_from_regclass`
  );
  console.log('   通过 regclass 获取 OID:', regclassResult[0]?.oid_from_regclass);

  console.log('\n=== Demo 执行完成 ===');
}

// 执行主函数
main()
  .then(() => process.exit(0))
  .catch((err) => {
    console.error('Demo 执行失败:', err);
    process.exit(1);
  });

运行说明

# 确保 PostgreSQL 已启动
# 方式一:使用 TypeScript(需安装 ts-node)
npx ts-node index.ts

# 方式二:使用 Node.js(将 .ts 改为 .js 或使用编译后的文件)
node index.js

关键技术点总结

  1. 模板数据库克隆:CREATE DATABASE ... TEMPLATE 实现了数据库级别的快速复制。
  2. datistemplate 标志:控制数据库是否可作为模板被克隆。
  3. template0 与编码/区域设置:使用 template0 可以突破 template1 的编码限制。
  4. pg_database 系统表:查询数据库的 OID、模板属性和连接属性。
  5. pg_class 与 regclass:获取表和索引的 OID 及 relfilenode。
  6. 表空间查询:pg_tablespace 系统表与 pg_tablespace_location() 函数。

多语言示例

本节提供与 Node.js Demo 功能等价的 Go、Python 和 Java 实现,涵盖数据库连接、模板数据库克隆、表空间查询和 OID 查询等核心操作。

Go 示例

使用 pgx 驱动(推荐)或 lib/pq。以下基于 pgx/v5。

# 项目初始化
mkdir pg-demo-go && cd pg-demo-go
go mod init pg-demo
go get github.com/jackc/pgx/v5
// main.go
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/jackc/pgx/v5"
)

func main() {
	ctx := context.Background()

	// 连接到 postgres 数据库
	connStr := "postgres://postgres:postgres@localhost:5432/postgres"
	conn, err := pgx.Connect(ctx, connStr)
	if err != nil {
		log.Fatalf("连接失败: %v", err)
	}
	defer conn.Close(ctx)

	fmt.Println("=== PostgreSQL 逻辑体系架构 Demo (Go) ===\n")

	// 1. 查看所有数据库
	fmt.Println("1. 当前数据库集群中的所有数据库:")
	rows, err := conn.Query(ctx, `SELECT oid, datname, datistemplate, datallowconn FROM pg_database ORDER BY datname`)
	if err != nil {
		log.Fatalf("查询失败: %v", err)
	}
	defer rows.Close()
	for rows.Next() {
		var oid uint32
		var datname string
		var datistemplate, datallowconn bool
		if err := rows.Scan(&oid, &datname, &datistemplate, &datallowconn); err != nil {
			log.Fatal(err)
		}
		fmt.Printf("  OID: %d, 名称: %s, 可作模板: %v, 允许连接: %v\n", oid, datname, datistemplate, datallowconn)
	}
	if err = rows.Err(); err != nil {
		log.Fatal(err)
	}

	// 2. 创建自定义模板数据库
	fmt.Println("\n2. 创建自定义模板数据库 (my_template):")
	_, err = conn.Exec(ctx, `DROP DATABASE IF EXISTS my_template`)
	if err != nil {
		log.Fatal(err)
	}
	_, err = conn.Exec(ctx, `CREATE DATABASE my_template`)
	if err != nil {
		log.Fatal(err)
	}
	// 切换到 my_template 创建表
	_, err = conn.Exec(ctx, `\c my_template`) // 注意:pgx 不支持 \c,需要新建连接
	// 改为新建连接
	connTemplate, err := pgx.Connect(ctx, "postgres://postgres:postgres@localhost:5432/my_template")
	if err != nil {
		log.Fatal(err)
	}
	defer connTemplate.Close(ctx)
	_, err = connTemplate.Exec(ctx, `CREATE TABLE template_table (id int, name text)`)
	if err != nil {
		log.Fatal(err)
	}
	_, err = connTemplate.Exec(ctx, `INSERT INTO template_table VALUES (1, 'template data')`)
	if err != nil {
		log.Fatal(err)
	}
	// 标记为模板数据库
	_, err = conn.Exec(ctx, `UPDATE pg_database SET datistemplate = true WHERE datname = 'my_template'`)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("   ✓ 模板数据库 my_template 创建完成")

	// 3. 基于模板克隆
	fmt.Println("\n3. 基于 my_template 克隆新数据库 (cloned_db):")
	_, err = conn.Exec(ctx, `DROP DATABASE IF EXISTS cloned_db`)
	if err != nil {
		log.Fatal(err)
	}
	_, err = conn.Exec(ctx, `CREATE DATABASE cloned_db TEMPLATE my_template`)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("   ✓ 克隆数据库 cloned_db 创建完成")

	// 4. 验证克隆数据
	fmt.Println("\n4. 验证克隆结果:")
	connClone, err := pgx.Connect(ctx, "postgres://postgres:postgres@localhost:5432/cloned_db")
	if err != nil {
		log.Fatal(err)
	}
	defer connClone.Close(ctx)
	var id int
	var name string
	err = connClone.QueryRow(ctx, `SELECT id, name FROM template_table`).Scan(&id, &name)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("   cloned_db 中数据: id=%d, name=%s\n", id, name)

	// 5. 使用 template0 创建指定编码数据库
	fmt.Println("\n5. 使用 template0 创建 LC_COLLATE=C 的数据库 (mydb_c):")
	_, err = conn.Exec(ctx, `DROP DATABASE IF EXISTS mydb_c`)
	if err != nil {
		log.Fatal(err)
	}
	_, err = conn.Exec(ctx, `
		CREATE DATABASE mydb_c
		TEMPLATE template0
		ENCODING 'UTF8'
		LC_COLLATE 'C'
		LC_CTYPE 'C'
	`)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("   ✓ 数据库 mydb_c 创建完成")

	// 6. 查询排序规则
	fmt.Println("\n6. 验证数据库的排序规则:")
	var datcollate, datctype string
	err = conn.QueryRow(ctx, `SELECT datcollate, datctype FROM pg_database WHERE datname = 'mydb_c'`).Scan(&datcollate, &datctype)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("   datcollate: %s, datctype: %s\n", datcollate, datctype)

	// 7. 表空间列表
	fmt.Println("\n7. 当前表空间列表:")
	rowsTS, err := conn.Query(ctx, `SELECT spcname, pg_tablespace_location(oid) FROM pg_tablespace`)
	if err != nil {
		log.Fatal(err)
	}
	defer rowsTS.Close()
	for rowsTS.Next() {
		var spcname string
		var location *string
		if err := rowsTS.Scan(&spcname, &location); err != nil {
			log.Fatal(err)
		}
		loc := "NULL"
		if location != nil {
			loc = *location
		}
		fmt.Printf("   %s -> %s\n", spcname, loc)
	}

	// 8. OID 查询
	fmt.Println("\n8. OID 查询示例:")
	// 在 cloned_db 中建表
	_, err = connClone.Exec(ctx, `CREATE TABLE IF NOT EXISTS test_oid (id int)`)
	if err != nil {
		log.Fatal(err)
	}
	var oidVal uint32
	var relname, relfilenode string
	err = connClone.QueryRow(ctx, `SELECT oid, relname, relfilenode::text FROM pg_class WHERE relname = 'test_oid'`).Scan(&oidVal, &relname, &relfilenode)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("   test_oid: OID=%d, relfilenode=%s\n", oidVal, relfilenode)

	// 使用 regclass
	var oidFromRegclass uint32
	err = connClone.QueryRow(ctx, `SELECT 'test_oid'::regclass::oid`).Scan(&oidFromRegclass)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("   通过 regclass 获取 OID: %d\n", oidFromRegclass)

	fmt.Println("\n=== Demo 执行完成 ===")
}

运行说明:

go run main.go

Python 示例

使用 psycopg2(推荐)或 asyncpg。以下基于 psycopg2。

# 安装依赖
pip install psycopg2-binary
# main.py
import psycopg2
from psycopg2 import sql

def main():
    conn = psycopg2.connect(
        host="localhost",
        port=5432,
        user="postgres",
        password="postgres",
        dbname="postgres"
    )
    conn.autocommit = True
    cur = conn.cursor()

    print("=== PostgreSQL 逻辑体系架构 Demo (Python) ===\n")

    # 1. 查看所有数据库
    print("1. 当前数据库集群中的所有数据库:")
    cur.execute("SELECT oid, datname, datistemplate, datallowconn FROM pg_database ORDER BY datname")
    for oid, datname, datistemplate, datallowconn in cur.fetchall():
        print(f"  OID: {oid}, 名称: {datname}, 可作模板: {datistemplate}, 允许连接: {datallowconn}")

    # 2. 创建模板数据库
    print("\n2. 创建自定义模板数据库 (my_template):")
    cur.execute("DROP DATABASE IF EXISTS my_template")
    cur.execute("CREATE DATABASE my_template")
    # 切换到 my_template
    conn_template = psycopg2.connect(
        host="localhost", port=5432, user="postgres", password="postgres", dbname="my_template"
    )
    conn_template.autocommit = True
    cur_t = conn_template.cursor()
    cur_t.execute("CREATE TABLE template_table (id int, name text)")
    cur_t.execute("INSERT INTO template_table VALUES (1, 'template data')")
    cur_t.close()
    conn_template.close()
    # 标记为模板
    cur.execute("UPDATE pg_database SET datistemplate = true WHERE datname = 'my_template'")
    print("   ✓ 模板数据库 my_template 创建完成")

    # 3. 克隆
    print("\n3. 基于 my_template 克隆新数据库 (cloned_db):")
    cur.execute("DROP DATABASE IF EXISTS cloned_db")
    cur.execute("CREATE DATABASE cloned_db TEMPLATE my_template")
    print("   ✓ 克隆数据库 cloned_db 创建完成")

    # 4. 验证
    print("\n4. 验证克隆结果:")
    conn_clone = psycopg2.connect(
        host="localhost", port=5432, user="postgres", password="postgres", dbname="cloned_db"
    )
    conn_clone.autocommit = True
    cur_c = conn_clone.cursor()
    cur_c.execute("SELECT id, name FROM template_table")
    row = cur_c.fetchone()
    print(f"   cloned_db 中数据: id={row[0]}, name={row[1]}")
    cur_c.close()
    conn_clone.close()

    # 5. 使用 template0
    print("\n5. 使用 template0 创建 LC_COLLATE=C 的数据库 (mydb_c):")
    cur.execute("DROP DATABASE IF EXISTS mydb_c")
    cur.execute("""
        CREATE DATABASE mydb_c
        TEMPLATE template0
        ENCODING 'UTF8'
        LC_COLLATE 'C'
        LC_CTYPE 'C'
    """)
    print("   ✓ 数据库 mydb_c 创建完成")

    # 6. 排序规则
    print("\n6. 验证数据库的排序规则:")
    cur.execute("SELECT datcollate, datctype FROM pg_database WHERE datname = 'mydb_c'")
    datcollate, datctype = cur.fetchone()
    print(f"   datcollate: {datcollate}, datctype: {datctype}")

    # 7. 表空间
    print("\n7. 当前表空间列表:")
    cur.execute("SELECT spcname, pg_tablespace_location(oid) FROM pg_tablespace")
    for spcname, location in cur.fetchall():
        loc = location if location else "NULL"
        print(f"   {spcname} -> {loc}")

    # 8. OID
    print("\n8. OID 查询示例:")
    # 在 cloned_db 中操作
    conn_clone2 = psycopg2.connect(
        host="localhost", port=5432, user="postgres", password="postgres", dbname="cloned_db"
    )
    conn_clone2.autocommit = True
    cur_c2 = conn_clone2.cursor()
    cur_c2.execute("CREATE TABLE IF NOT EXISTS test_oid (id int)")
    cur_c2.execute("SELECT oid, relname, relfilenode::text FROM pg_class WHERE relname = 'test_oid'")
    oid_val, relname, relfilenode = cur_c2.fetchone()
    print(f"   test_oid: OID={oid_val}, relfilenode={relfilenode}")
    cur_c2.execute("SELECT 'test_oid'::regclass::oid")
    oid_reg = cur_c2.fetchone()[0]
    print(f"   通过 regclass 获取 OID: {oid_reg}")
    cur_c2.close()
    conn_clone2.close()

    cur.close()
    conn.close()
    print("\n=== Demo 执行完成 ===")

if __name__ == "__main__":
    main()

运行说明:

python main.py

Java 示例

使用 JDBC 驱动(org.postgresql:postgresql)。以下基于 Maven 项目。

# 创建 Maven 项目
mvn archetype:generate -DgroupId=com.example -DartifactId=pg-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
cd pg-demo
# 编辑 pom.xml 添加依赖
# 然后在 src/main/java/com/example/ 下创建 App.java
<!-- pom.xml 依赖片段 -->
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.7.3</version>
</dependency>
// src/main/java/com/example/App.java
package com.example;

import java.sql.*;
import java.util.Properties;

public class App {
    public static void main(String[] args) {
        String url = "jdbc:postgresql://localhost:5432/postgres";
        Properties props = new Properties();
        props.setProperty("user", "postgres");
        props.setProperty("password", "postgres");

        try (Connection conn = DriverManager.getConnection(url, props)) {
            conn.setAutoCommit(true);
            System.out.println("=== PostgreSQL 逻辑体系架构 Demo (Java) ===\n");

            // 1. 查看所有数据库
            System.out.println("1. 当前数据库集群中的所有数据库:");
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery(
                         "SELECT oid, datname, datistemplate, datallowconn FROM pg_database ORDER BY datname")) {
                while (rs.next()) {
                    int oid = rs.getInt("oid");
                    String datname = rs.getString("datname");
                    boolean datistemplate = rs.getBoolean("datistemplate");
                    boolean datallowconn = rs.getBoolean("datallowconn");
                    System.out.printf("  OID: %d, 名称: %s, 可作模板: %b, 允许连接: %b%n",
                            oid, datname, datistemplate, datallowconn);
                }
            }

            // 2. 创建模板数据库
            System.out.println("\n2. 创建自定义模板数据库 (my_template):");
            try (Statement stmt = conn.createStatement()) {
                stmt.execute("DROP DATABASE IF EXISTS my_template");
                stmt.execute("CREATE DATABASE my_template");
            }
            // 连接到 my_template
            String urlTemplate = "jdbc:postgresql://localhost:5432/my_template";
            try (Connection connTemplate = DriverManager.getConnection(urlTemplate, props);
                 Statement stmtT = connTemplate.createStatement()) {
                stmtT.execute("CREATE TABLE template_table (id int, name text)");
                stmtT.execute("INSERT INTO template_table VALUES (1, 'template data')");
            }
            // 标记为模板
            try (Statement stmt = conn.createStatement()) {
                stmt.execute("UPDATE pg_database SET datistemplate = true WHERE datname = 'my_template'");
            }
            System.out.println("   ✓ 模板数据库 my_template 创建完成");

            // 3. 克隆
            System.out.println("\n3. 基于 my_template 克隆新数据库 (cloned_db):");
            try (Statement stmt = conn.createStatement()) {
                stmt.execute("DROP DATABASE IF EXISTS cloned_db");
                stmt.execute("CREATE DATABASE cloned_db TEMPLATE my_template");
            }
            System.out.println("   ✓ 克隆数据库 cloned_db 创建完成");

            // 4. 验证
            System.out.println("\n4. 验证克隆结果:");
            String urlClone = "jdbc:postgresql://localhost:5432/cloned_db";
            try (Connection connClone = DriverManager.getConnection(urlClone, props);
                 Statement stmtC = connClone.createStatement();
                 ResultSet rs = stmtC.executeQuery("SELECT id, name FROM template_table")) {
                if (rs.next()) {
                    int id = rs.getInt("id");
                    String name = rs.getString("name");
                    System.out.printf("   cloned_db 中数据: id=%d, name=%s%n", id, name);
                }
            }

            // 5. 使用 template0
            System.out.println("\n5. 使用 template0 创建 LC_COLLATE=C 的数据库 (mydb_c):");
            try (Statement stmt = conn.createStatement()) {
                stmt.execute("DROP DATABASE IF EXISTS mydb_c");
                stmt.execute("CREATE DATABASE mydb_c TEMPLATE template0 ENCODING 'UTF8' LC_COLLATE 'C' LC_CTYPE 'C'");
            }
            System.out.println("   ✓ 数据库 mydb_c 创建完成");

            // 6. 排序规则
            System.out.println("\n6. 验证数据库的排序规则:");
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SELECT datcollate, datctype FROM pg_database WHERE datname = 'mydb_c'")) {
                if (rs.next()) {
                    String datcollate = rs.getString("datcollate");
                    String datctype = rs.getString("datctype");
                    System.out.printf("   datcollate: %s, datctype: %s%n", datcollate, datctype);
                }
            }

            // 7. 表空间
            System.out.println("\n7. 当前表空间列表:");
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SELECT spcname, pg_tablespace_location(oid) FROM pg_tablespace")) {
                while (rs.next()) {
                    String spcname = rs.getString(1);
                    String location = rs.getString(2);
                    String loc = (location == null) ? "NULL" : location;
                    System.out.printf("   %s -> %s%n", spcname, loc);
                }
            }

            // 8. OID
            System.out.println("\n8. OID 查询示例:");
            String urlClone2 = "jdbc:postgresql://localhost:5432/cloned_db";
            try (Connection connClone2 = DriverManager.getConnection(urlClone2, props);
                 Statement stmtC2 = connClone2.createStatement()) {
                stmtC2.execute("CREATE TABLE IF NOT EXISTS test_oid (id int)");
                try (ResultSet rs = stmtC2.executeQuery(
                        "SELECT oid, relname, relfilenode::text FROM pg_class WHERE relname = 'test_oid'")) {
                    if (rs.next()) {
                        int oidVal = rs.getInt("oid");
                        String relname = rs.getString("relname");
                        String relfilenode = rs.getString("relfilenode");
                        System.out.printf("   test_oid: OID=%d, relfilenode=%s%n", oidVal, relfilenode);
                    }
                }
                try (ResultSet rs = stmtC2.executeQuery("SELECT 'test_oid'::regclass::oid")) {
                    if (rs.next()) {
                        int oidReg = rs.getInt(1);
                        System.out.printf("   通过 regclass 获取 OID: %d%n", oidReg);
                    }
                }
            }

            System.out.println("\n=== Demo 执行完成 ===");

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

运行说明:

mvn compile
mvn exec:java -Dexec.mainClass="com.example.App"

多语言示例技术点总结

语言驱动/库连接字符串示例关键特性
Node.jspgpostgres://user:pass@host:port/db基于 Pool 连接池,支持异步/await
Gopgx/v5postgres://user:pass@host:port/db高性能,支持上下文,自动重连
Pythonpsycopg2DSN 或关键字参数成熟稳定,支持 autocommit 和原生 SQL 拼接
JavaJDBC (PostgreSQL 驱动)jdbc:postgresql://host:port/db标准 JDBC API,需手动管理连接

所有示例均实现了以下核心功能:

  • 查询系统目录 pg_database 和 pg_class
  • 创建自定义模板数据库并标记 datistemplate = true
  • 使用 TEMPLATE 子句克隆数据库
  • 使用 template0 创建指定编码和 LC_COLLATE 的数据库
  • 查询表空间及其物理位置
  • 通过 regclass 转换获取 OID
  • 切换数据库连接(通过新建连接模拟 \c)

官方文档与参考链接

官方文档

参考链接

总结

本文深入探讨了 PostgreSQL 逻辑体系架构中的核心概念:

  • Database Cluster(数据库集群) 是存储层面的概念,指 PGDATA 目录下由单个实例管理的所有数据库的集合。
  • Instance(实例) 是运行时的概念,指 postgres 进程及其管理的内存与后台进程。
  • 模板数据库(template1 / template0) 是 CREATE DATABASE 的复制源,template1 支持站点本地定制,template0 提供“原始”环境并支持自定义编码与区域设置。
  • 表空间(Tablespace) 允许 DBA 控制数据库对象的物理存储位置,实现冷热分离与性能优化。
  • OID(对象标识符) 是 PostgreSQL 内部用于标识系统表主键和文件组织的基础机制。
  • 跨数据库访问可通过 dblink 或 postgres_fdw 实现,其中 postgres_fdw 提供了更符合 SQL/MED 标准的语法和更好的性能。
别再搞混了!用大白话图解PostgreSQL的实例、数据库和Schema(附真实项目踩坑经验) 本文通过大白话图解和真实项目案例,详细解析PostgreSQL中实例、数据库和Schema的逻辑结构差异,帮助开发者避免常见误区。文章特别强调schema层级在权限管理和性能优化中的关键作用,并分享从MySQL迁移到PostgreSQL时的最佳实践和踩坑经验。 阅读详情

相关推荐

解密DBeaver与PostgreSQL的‘隐藏数据库’:从配置误区到高效管理

本文深入解析DBeaver连接PostgreSQL时数据库显示不全的问题,揭示工具默认隐藏非默认数据库的设计逻辑,并提供从基础配置到高级管理的全面解决方案。重点介绍'Edit Connection'中的'Show all databases'选项设置,帮助用户高效管理PostgreSQL多数据库环境。

wine的专栏 891

PostgreSQL教程--逻辑结构:实例、数据库、schema、表之间的关系

1 PG的逻辑结构 PG的逻辑结构详见下图: 第一层是实例(Instance)。 第二层是数据库(Database);一个实例下有多个数据库;每个数据库之间是完全独立的。 第三层是Schema;数据库下面有多个Schema;其中“public” 是数据库创建时产生的。 每个Schema下面可以创建表,视图,索引,函数,序列,物化视图,外部表等等。 pg_class记录表和几乎所有具有列或者像表的东西。这包括索引(但还要参见pg_index)、序列(但还要参见pg_sequence)、视图、物化视图、组合

penriver的博客 1万+

若依Vue整合积木报表实战:Token安全校验全流程解析

本文详细解析了在若依Vue后台系统中安全集成积木报表的全流程,重点阐述了Token安全校验的核心机制。通过前端菜单配置、Token传递、后端权限拦截及自定义Token服务实现,构建了一套完整的企业级报表访问安全防线,确保核心业务数据的安全可控。

t8u9v0的博客 579

2.2 数据库方案,及其与实例的区别

1.       数据库方案(Schema)与实例(Instance)之间的区别:方案是指数据库的逻辑设计,实例指的则是某个时刻数据库里的数据, 2.       用编程语言中的概念来理解数据库中的概念:关系——变量,关系方案(Relation Schema)——类型定义,关系实例(Relation Instance)——变量的值。 3.       关系方案由一组属性及其对应的值域组成。

石骞的专栏 2274

Python实战:基于PyG和Stable-Baselines3复现柔性车间调度算法(附数据集)

本文提供了一份基于图神经网络与深度强化学习的柔性车间调度实战指南。通过PyTorch Geometric构建异构图表示车间状态,并利用Stable-Baselines3中的PPO算法训练调度智能体,详细介绍了从环境建模、网络设计到训练评估的完整代码实现,帮助开发者构建可复用的工业级智能调度系统。

ansible6ops的博客 608

RTC 实时时钟实验

如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个TR_CLK 周期中 RTC 产生一个中断(秒中断)。void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data) // 往备份区域写用户数据的函数 (这个函数的第一个参数就是寄存器的标号了,这个是通过宏定义定义的)存储在 RTC_ALR 寄存器中的可编程时间相比较,如果 RTC_CR 控制寄存器中设置了相应允许位,比较匹配时将产生一个闹钟中断。寄存器操作完成,并同步之后,设置秒钟中断。

m0_55996456的博客 1206

oracle几个概念:数据库、实例、用户、schema

Oracle数据库中不能新创建一个schema,要想创建一个schema,只能通过创建一个用户的方法解决,在创建一个用户的同时为这个用户创建一个与用户名同名的schem并作为该用户的缺省shcema。就算没有磁盘存储,数据库实例也能存在。Oracle当中,如果想访问某个服务器,必须要设置TNS,配置客户端到服务器端的连接服务,包括客户端要连接到的服务器和数据库的配置信息。我们访问Oracle都是访问一个实例,但这个实例如果关联了数据库文件,就是可以访问的,如果没有,就会得到实例不可用的错误。...

韦木三 6007

5分钟搞懂SCMA:稀疏码多址接入的核心原理与实战应用

本文深入浅出地解析了SCMA(稀疏码多址接入)的核心原理与实战应用。通过对比传统正交多址技术,阐释了SCMA如何通过非正交叠加和稀疏码本设计,实现远超资源单元数的用户接入,从而有效应对5G海量机器通信(mMTC)的挑战。文章还探讨了其在上行海量连接、免授权接入等场景的应用潜力及工程实现中的关键考量。

zeta9的博客 267

【 PG 入门系列 】PostgreSQL的体系结构(三)

PostgreSQL的体系结构,B站同步教学视频

SUOYUEのBLOG 2638

pytorch多层感知机实现假钞识别(完整项目构建)

目录1 项目构建2 超参数设置 config.py3 数据集预处理 preprocess.py4 数据集类构建 dataset_banknote.py5 模型构建 model.py6 训练trainer.py6.1 查看损失曲线7 在测试集上运行 inference.py 1 项目构建 构建项目文件夹Banknote,以及子文件夹与py文件。 名称 作用 data目录 存放原始数据与预处理后切分为训练集、验证机、测试集的数据 log目录 存放训练过程中保存的指标,如损失、精确度等

Demon_LMMan的博客 2027

SuperMap iDesktop 9D三维倾斜摄影数据处理

OSGB格式的三维倾斜摄影数据进入时空大数据平台之前需要进行数据优化和格式转换

weixin_43204897的博客 1131

Dify-helm项目中PostgreSQL数据库配置的深度解析与解决方案

Dify-helm项目中PostgreSQL数据库配置的深度解析与解决方案 在基于Dify-helm项目部署AI应用时,数据库配置是系统稳定运行的关键环节。近期社区反馈在0.23.0-rc2版本中,当使用外部PostgreSQL数据库时,pluginDaemon组件的DB_DATABASE参数存在配置冲突问题。本文将深入分析该问题的技术背景,并提供专业解决方案。 问题本质分析 该问题的核心在于he...

gitblog_07673的博客 723

如何选择深度强化学习算法:MuZero/SAC/PPO/TD3/DDPG/DQN/等算法

如何选择深度强化学习算法:MuZero/SAC/PPO/TD3/DDPG/DQN/等算法

丨汀、的博客 5224

Teleport Database Access 深入解析:RFD 11 架构、认证、RBAC 与审计实践

Teleport Database Access 是 Teleport 中用于为数据库提供安全访问通道的核心特性,它通过反向隧道、mTLS 认证与 RBAC 模型,让用户使用熟悉的数据库客户端(如 `psql`、`mysql`、`pgAdmin`)安全地访问数据库,同时将每一次连接与查询记录进审计日志。本文以仓库中 [rfd/0011-database-access.md](https://lin

gitblog_00176的博客 1110

华为 MetaERP 财务模块的核心业务对象,按子模块与架构维度分类,以表格呈现,适配架构设计与实施落地

华为MetaERP财务模块基于4A架构(业务/应用/数据/技术)与TOGAF框架,实现业财一体化与全球合规。业务架构涵盖组织模型与核心流程,应用架构支撑财务操作,数据架构确保数据一致性,技术架构提供高性能技术底座。模块覆盖总账、应收应付、资产等子模块,支持多组织、多币种、多准则核算,通过实时会计引擎实现"交易即核算"。4A架构与TOGAF框架对应,实现业务能力、应用组件、数据模型与技术栈的深度融合,为华为全球化财务核算提供核心支撑。

金牌架构师 444

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

ECC database-reviewer 深度解析:PostgreSQL 查询优化、Schema 设计、安全与性能审查实战指南

本文围绕 ECC(Everything Claude Code,Agent 编排与开发插件仓库)中 [database-reviewer Agent 定义](https://link.gitcode.com/i/5f281835c9480735b787d1c205285fef)展开,讲解一名面向 PostgreSQL 与 Supabase 场景的数据库专家 Agent 如何从查询性能、Schema

gitblog_00170的博客 393

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

为什么我说PostgreSQL是Agent Database的最佳选择

本文将深度解析 PostgreSQL 胜出的 5 个底层逻辑,以及在实际落地中如何避开那些"看起来很美"的选型陷阱。

Database_Cool_的博客 640

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

在 OpenShift 上部署 Patroni PostgreSQL 高可用集群:基于模板的动态 UID/GID 适配实战

本篇技术指南围绕 Patroni 项目仓库中的 [OpenShift 示例配置](https://link.gitcode.com/i/b546af38b5c520ee1cf9db706dd698fb) 展开,系统讲解如何在 OpenShift 的 `restricted` SCC(Security Context Constraints)约束下部署一套三副本的 PostgreSQL 高可用集群。

gitblog_00402的博客 1032

Teleport 数据库按需用户自动配置(RFD 113)深度解析:PostgreSQL 动态数据库用户方案

> 本文基于 [rfd/0113-automatic-database-users.md](https://link.gitcode.com/i/3a1705ce64736098ad5d54f488798052) 展开,并结合仓库中 [lib/srv/db](https://link.gitcode.com/i/14d3f77c8a0661aa7f310f1fe2840f26) 的数据库服务实现源

gitblog_00001的博客 913

DBX Database Recipe 模板详解:为 90+ 数据库构建可复现的 Docker 测试环境

DBX 内置一套 `deploy/database` 测试环境体系:每个数据库产品以「版本化 Recipe」(recipe.json + compose.yaml + init/)的形式,把镜像、端口、凭据、冒烟验证和交互式入口固化成可一键启动的环境。本文以 [RECIPE_TEMPLATE.md](https://link.gitcode.com/i/66ecc324f1fa69c5f19fd7

gitblog_00506的博客 391

Ubuntu 20.04 PostgreSQL安装与连接全链路解析

PostgreSQL是一种开源关系型数据库管理系统,其核心原理在于ACID事务保障、MVCC并发控制与基于角色的访问控制机制。在Linux发行版中,Ubuntu 20.04因采用systemd服务管理、postgresql-common配置框架及默认peer认证策略,形成了区别于CentOS或Docker环境的独特部署逻辑。该版本的技术价值体现在系统级集成稳定性、安全基线预置(如默认禁用远程TCP、强制peer本地认证)以及配置双轨制(/etc/主导生效、/var/lib/承载数据)。典型应用场景包括Spr

weixin_30596023的博客 408

Ory Kratos 数据库自动迁移深度解析:如何同时支持 PostgreSQL、MySQL 与 CockroachDB

**Ory Kratos** 是一款云原生的无头身份认证与身份管理系统,其数据库层通过一套**自动迁移机制**,让同一份迁移代码同时兼容 **PostgreSQL、MySQL、CockroachDB**(以及 SQLite、YugabyteDB),实现零人工干预的建库与升级。本文将带你完整看懂这套机制的工作原理。 ## 一、先看全景:迁移体系放在哪里 Kratos 的多数据库支持由两部分协作完

gitblog_00431的博客 403

PostgreSQL 工程化部署深度解析

本文档是PostgreSQL工程化部署的深度解析,主要包含以下核心内容: 架构设计:采用Docker容器化部署,实现数据与计算分离,确保容器可销毁重建而不丢失数据。 部署全流程解析: 从环境准备(Docker验证、国内镜像源配置) 到Compose声明式部署(详解docker-compose.yml每个配置项) 再到连接验证与管理维护 关键设计理念: 声明式配置管理 最小权限原则(非root运行) 完善的监控与健康检查机制 完整的备份恢复方案 深度技术解析: 逐行拆解所有配置命令和参数 阐明每个操作的技术原

A1063348628的博客 465

数据库教程FGMT50‑PostgreSQL体系结构深入与源码解析

本文深入解析 PostgreSQL 体系结构,涵盖逻辑存储、物理文件布局、进程模型与内存机制,结合两台8CPU/64GB主机实操环境,系统讲解集群初始化、源码编译调试、gdb跟踪initdb与启动流程。通过理论与实战结合,帮助DBA、运维及架构师掌握底层运行机制,具备源码级问题定位能力,提升故障诊断与性能调优水平。

风哥oracle/mysql/pg技术教程 265

CodeIgniter 数据库驱动参考:CI_DB_driver 核心 API 全解析

本文是 CodeIgniter 数据库层基类 `CI_DB_driver` 的完整参考指南,覆盖连接建立、查询执行、事务管理、转义安全、元数据获取、查询缓存等全部核心 API。无论你是要排查数据库连接问题、手动编写原生 SQL,还是想深入理解 Query Builder 的底层运作,本文都能为你提供可直接对照源码的方法签名、返回类型与实战用法。读完本文,你将能熟练运用这套平台无关的数据库接口,在不

gitblog_00280的博客 1014

remix/data-table-postgres:基于 pg 的 PostgreSQL 驱动与 SQL 编译实现深度解析

`data-table-postgres` 是 Remix 全栈框架中 [`data-table`](https://link.gitcode.com/i/460e4b39b5bfc0d4f115e01f963c1762) 的 PostgreSQL 数据库驱动实现,底层由 `pg` 连接池驱动,是 `remix` 包导出路径 `remix/data-table/postgres` 的映射目标(见

gitblog_00920的博客 1034
上一篇: PostgreSQL笔记19:进程与内存架构精解
下一篇: PostgreSQL笔记21: 文件系统、Buffer I/O与数据页底层结构解析
Wang's Blog
博客等级 码龄12年 7438粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值