管理数据库与数据库实例数据库(Database)数据库实例(Instance)管理数据库和模版数据库模版template0template1管理数据库实例:命令pg_ctl管理数据库的扩展访问外部的数据源file_fdw:访问外部的文件系统postgres_fdw:访问外部的文件系统oracle_fdw:访问外部的文件系统
管理数据库与数据库实例
数据库(Database)
它是数据的 “存储结构”,可以理解为 “装数据的容器”。
逻辑存储结构:我们在 SQL 里直接打交道的对象,比如数据库集群、库、表空间、表、索引等,是 “用户视角” 的数据组织方式。
物理存储结构:真正存在磁盘上的文件,比如数据文件、日志文件,是 “底层视角” 的实现方式。
核心关系:数据库系统会通过逻辑结构,来管理和组织物理上的文件,让你不用直接操作磁盘。
数据库实例(Instance)
它是数据库运行时的 “进程 + 内存结构”,是让数据库能干活的 “引擎”。
由内存(比如共享缓冲区、日志缓冲区)和后台进程组成。
你平时启动
pg_ctl start,启动的就是这个实例;实例没起来,就算磁盘上有数据文件,也没法访问。
PostgreSQL 场景下的补充
在你用的 PostgreSQL 里,这两个概念非常好理解:
你用
pg_ctl start启动的,就是 PostgreSQL 实例(进程 + 内存)。你用
CREATE DATABASE scott;创建的,就是 数据库对象,它最终会在数据目录下生成对应的物理文件。
PostgreSQL / MySQL:1 个实例,N 个数据库
关系:1 个数据库实例(进程 + 内存),可以管理 N 个独立的数据库。
理解:
你启动一次
pg_ctl start或mysqld,就启动了一个实例。在这个实例里,你可以
CREATE DATABASE scott;创建多个数据库,它们共享同一个实例的进程和内存。
Oracle(非 RAC):1 个实例,1 个数据库
关系:1 个实例,对应 1 个数据库。
理解:Oracle 的传统架构里,一个实例只能挂载一个数据库。要多库就得启动多个实例。
Oracle RAC:N 个实例,1 个数据库
关系:多个实例(节点),同时挂载同一个数据库,实现高可用和负载均衡。
理解:
这是 Oracle 的集群架构,多个服务器上的实例,同时访问同一份数据文件。
好处是一个节点挂了,其他节点还能继续提供服务。
管理数据库和模版
管理数据库和模版1、管理数据库 (1)创建数据库 create database mypgsql; select datname from pg_database; (2)修改数据库实例配置 (*)执行SQL命令 set (*)配置文件:postgresql.conf (*)执行shell命令 (3)删除数据库 drop database mypgsql;2、数据库模版:template0、template1
修改数据库实例配置 (*)执行SQL命令set(会话级修改)只对当前会话生效,断开连接后恢复默认。 示例:修改当前会话的工作内存postgres=# show work_mem ; work_mem ---------- 4MB(1 row)postgres=# set work_mem = '64MB';SETpostgres=# show work_mem ; work_mem ---------- 64MB(1 row) (*)配置文件:postgresql.conf(全局永久修改)修改配置文件后需要重启数据库服务才能生效。# 示例:修改最大连接数max_connections =200[postgres@pg15 ~]$ cd training/pgsql/data/[postgres@pg15 data]$ vim postgresql.conf找到max_connections =修改成200#重启数据库[postgres@pg15 pgsql]$ pg_ctl-D data -l logfile restartwaiting for server to shut down.... doneserver stoppedwaiting for server to start.... doneserver started[postgres@pg15 pgsql]$ pg_ctl-D data statuspg_ctl: server is running (PID: 90154)/home/postgres/training/pgsql/bin/postgres "-D""data"[postgres@pg15 pgsql]$ (*)执行shell命令[postgres@pg15 pgsql]$ bin/pg_ctl -D data/ -l logfile stopwaiting for server to shut down.... doneserver stopped[postgres@pg15 pgsql]$ bin/postgres -cwork_mem='8MB'2026-05-1716:40:12.518 CST [112438] LOG: starting PostgreSQL 15.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit2026-05-1716:40:12.520 CST [112438] LOG: listening on IPv6 address "::1", port 54322026-05-1716:40:12.520 CST [112438] LOG: listening on IPv4 address "127.0.0.1", port 54322026-05-1716:40:12.522 CST [112438] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432"2026-05-1716:40:12.524 CST [112446] LOG: database system was shut down at 2026-05-1716:39:07 CST2026-05-1716:40:12.525 CST [112438] LOG: database system is ready to accept connections#因为你这里按Ctrl+c数据库会直接不启动所以重新开个链接查看[root@pg15 ~]# su - postgres 上一次登录:日 5月 1710:12:15 CST 2026pts/0 上[postgres@pg15 ~]$ cd training/pgsql/[postgres@pg15 pgsql]$ cd bin/[postgres@pg15 bin]$ psqlpsql (15.3)Type "help"for help.postgres=# show work_mem; work_mem ---------- 8MB(1 row)postgres=# 修改成功
数据库模版
当我们创建启动一个数据库集群系统默认会有两个数据库模版 template0、template1这是标准的数据库对象
[postgres@pg15 pgsql]$ bin/pg_ctl -D data/ -l logfile startpg_ctl: another server might be running; trying to start server anywaywaiting for server to start.... doneserver started[postgres@pg15 pgsql]$ bin/pg_ctl -D data/ -l logfile statuspg_ctl: server is running (PID: 3637)/home/postgres/training/pgsql/bin/postgres "-D""data"[postgres@pg15 pgsql]$ bin/psql psql (15.3)Type "help"for help.postgres=# select datname from pg_database; datname ----------- postgres scott template1 template0(4 rows)
template0
template0:当数据库集群被初始化成功后,不应该修改它保存的是pg数据库预定义的数据库对象
template1
template1: 跟template0保存的对象是一样的,当创建一个自定义数据库的时候实际上它是复制一个template1的模版。
select datname,datistemplate,datallowconn from pg_database;datname:数据库名称datistemplate:是否为模板库(t= 是,f= 否)datallowconn:是否允许连接(t= 是,f= 否)
执行结果里:
template1:datistemplate = t、datallowconn = t→ 可修改、可连接、默认模板template0:datistemplate = t、datallowconn = f→ 纯净模板、不可连接
#datistemplate表示是不是一个数据库模版,datallowconn表示是否允许建立连接postgres=# select datname,datistemplate,datallowconn from pg_database; datname | datistemplate | datallowconn -----------+---------------+-------------- postgres | f | t scott | f | t template1 | t是模版数据库 | t template0 | t是模版数据库 | f 不允许建立连接 (4 rows)
| 特性 | template1 | template0 |
|---|---|---|
| 是否可修改 | ✅ 可修改 | ❌ 不可修改(初始化后不应改动) |
| 创建新库时默认模板 | ✅ 是(CREATE DATABASE 默认复制它) | ❌ 不是,需手动指定 |
| 是否允许连接 | ✅ 允许(datallowconn = t) | ❌ 不允许(datallowconn = f) |
| 用途 | 作为默认模板,可自定义公共对象 | 纯净备份模板,恢复 / 创建干净库时用 |
一句话总结
template1是可定制的默认模板,改它 = 给所有新库加 “公共配置”。template0是只读的纯净备份,用来救急和创建干净库。
管理数据库实例:命令pg_ctl
[postgres@pg15 pgsql]$ bin/pg_ctl --helppg_ctl is a utility to initialize, start, stop, or control a PostgreSQL server.Usage: pg_ctl init[db] [-D DATADIR] [-s] [-o OPTIONS] pg_ctl start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s] [-o OPTIONS] [-p PATH] [-c] pg_ctl stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s] pg_ctl restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s] [-o OPTIONS] [-c] pg_ctl reload [-D DATADIR] [-s] pg_ctl status [-D DATADIR] pg_ctl promote [-D DATADIR] [-W] [-t SECS] [-s] pg_ctl logrotate [-D DATADIR] [-s] pg_ctl kill SIGNALNAME PIDCommon options:-D, --pgdata=DATADIR location of the database storage area-s, --silent only print errors, no informational messages-t, --timeout=SECS seconds to wait when using -w option-V, --version output version information, thenexit-w, --wait wait until operation completes (default)-W, --no-waitdo not wait until operation completes-?, --help show this help, thenexitIf the -D option is omitted, the environment variable PGDATA is used.Options forstart or restart:-c, --core-files allow postgres to produce core files-l, --log=FILENAME write (or append) server log to FILENAME-o, --options=OPTIONS command line options to pass to postgres (PostgreSQL server executable) or initdb-p PATH-TO-POSTGRES normally not necessaryOptions forstop or restart:-m, --mode=MODE MODE can be "smart", "fast", or "immediate"Shutdown modes are: smart quit after all clients have disconnected fast quit directly, with proper shutdown (default) immediate quit without complete shutdown; will lead to recovery on restartAllowed signal names forkill: ABRT HUP INT KILL QUIT TERM USR1 USR2Report bugs to <pgsql-bugs@lists.postgresql.org>.PostgreSQL home page: <https://www.postgresql.org/>
Usage: pg_ctl init[db] [-D DATADIR] [-s] [-o OPTIONS] pg_ctl start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s] [-o OPTIONS] [-p PATH] [-c] pg_ctl stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s] pg_ctl restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s] [-o OPTIONS] [-c] pg_ctl reload [-D DATADIR] [-s] pg_ctl status [-D DATADIR] pg_ctl promote [-D DATADIR] [-W] [-t SECS] [-s] pg_ctl logrotate [-D DATADIR] [-s] pg_ctl kill SIGNALNAME PID
初始化数据库(第一次用才执行)
pg_ctl initdb -D data= 建一个空的数据库环境(删数据、重装时用)
1. pg_ctl start
作用:启动数据库
pg_ctl start -D data -l logfile2. pg_ctl stop
作用:停止数据库
pg_ctl stop -D data3. pg_ctl restart
作用:重启数据库(先停再起)
pg_ctl restart -D data4. pg_ctl reload
作用:重新加载配置文件(不重启)
5. pg_ctl status
作用:看数据库有没有运行
pg_ctl status -D data6. 其他(你暂时不用记)
promote:主从切换用logrotate:日志切割kill:强制杀进程
最重要的 2 个参数(必须懂)
-D DATADIR
数据目录在哪里
你永远写:
-D data-l FILENAME
日志写在哪里
你永远写:
-l logfile4 条常用命令
pg_ctl initdb -D data # 初始化(删数据才用)pg_ctl start -D data -l logfile # 启动pg_ctl stop -D data # 停止pg_ctl status -D data # 看状态
一句话终极总结
pg_ctl = PG 开关命令 -D 表示数据目录 start 启动 stop 停止 status 看状态
管理数据库的扩展
访问外部的数据源
file_fdw:访问外部的文件系统
编译和安装file_fdw
[postgres@pg15 ~]$ cd tools/postgresql-15.3/contrib/file_fdw/[postgres@pg15 file_fdw]$ make``````[postgres@pg15 file_fdw]$ make install``````
修改配置文件
[postgres@pg15 ~]$ cd training/pgsql/data/[postgres@pg15 data]$ vim postgresql.conf 用下面命令在vim找到这个参数/shared_preload 添加以下内容shared_preload_libraries ='file_fdw'保存退出
启动数据库实例
[postgres@pg15 data]$ cd ..[postgres@pg15 pgsql]$ bin/pg_ctl -D data/ -l logfile startwaiting for server to start.... doneserver started[postgres@pg15 pgsql]$ bin/pg_ctl -D data/ -l logfile statuspg_ctl: server is running (PID: 123146)/home/postgres/training/pgsql/bin/postgres "-D""data"
创建扩展插件
[postgres@pg15 pgsql]$ bin/psql psql (15.3)Type "help"for help.postgres=# create extension file_fdw;CREATE EXTENSIONpostgres=# select * from pg_extension; oid | extname | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition -------+----------+----------+--------------+----------------+------------+-----------+--------------13673 | plpgsql | 10 | 11 | f | 1.0 | | 16399 | file_fdw | 10 | 2200 | t | 1.0 | | (2 rows)postgres=# \x #输入一次 \x → 开启(竖着展示,一行一个字段)Expanded display is on.postgres=# \x #再输入一次 \x → 关闭(横着展示,表格形式) Expanded display is off.postgres=# \xExpanded display is on.postgres=# select * from pg_extension; #查看数据库安装了哪些扩展插件-[ RECORD 1 ]--+---------oid | 13673extname | plpgsql #系统自带的函数语言(必须有,删不掉)extowner | 10extnamespace | 11extrelocatable | fextversion | 1.0extconfig | extcondition | -[ RECORD 2 ]--+---------oid | 16399extname | file_fdw #用来读取外部文件的插件extowner | 10extnamespace | 2200extrelocatable | textversion | 1.0extconfig | extcondition |
做完以上内容就是安装成功了file_fdw
file_fdw:访问外部的文件系统
postgres=# create server service_file foreign data wrapper file_fdw;CREATE SERVERpostgres=# create foreign table ft_emppostgres-# (empno int,postgres(# ename varchar(10),postgres(# job varchar(10),postgres(# mgr int,postgres(# hiredate varchar(100),postgres(# sal int,postgres(# comn int,postgres(# deptno int)postgres-# server service_file optionspostgres-# (filename '/home/postgres/training/pgsql/emp.csv',format 'csv');CREATE FOREIGN TABLEpostgres=# select * from ft_emp;ERROR: invalid input syntax for type integer: "empno"CONTEXT: COPY ft_emp, line 1, column empno: "empno"#发现报错现在的外部表没告诉 PostgreSQL:CSV 第一行是表头,不是数据!#所以它把 empno 这个文字当成数字往里插,直接报错#排错先删掉旧的外部表postgres=# drop foreign table ft_emp;DROP FOREIGN TABLE#重新创建带header正确版本postgres=# create foreign table ft_emppostgres-# (empno int,postgres(# ename varchar(10),postgres(# job varchar(10),postgres(# mgr int,postgres(# hiredate varchar(100),postgres(# sal int,postgres(# comm int,postgres(# deptno int)postgres-# server service_file optionspostgres-# (postgres(# filename '/home/postgres/training/pgsql/emp.csv',postgres(# format 'csv',postgres(# header 'true' #添加这一行,header 'true'= 跳过 CSV 第一行的表头postgres(# );postgres-# \xExpanded display is off.ostgres=# select * from ft_emp; empno | ename | job | mgr | hiredate | sal | comm | deptno -------+--------+-----------+------+------------+------+------+--------7369 | SMITH | CLERK | 7902 | 1980/12/17 | 800 | | 207499 | ALLEN | SALESMAN | 7698 | 1981/2/20 | 1600 | 300 | 307521 | WARD | SALESMAN | 7698 | 1981/2/22 | 1250 | 500 | 307566 | JONES | MANAGER | 7839 | 1981/4/2 | 2975 | | 207654 | MARTIN | SALESMAN | 7698 | 1981/9/28 | 1250 | 1400 | 307698 | BLAKE | MANAGER | 7839 | 1981/5/1 | 2850 | | 307782 | CLARK | MANAGER | 7839 | 1981/6/9 | 2450 | | 107788 | SCOTT | ANALYST | 7566 | 1987/4/19 | 3000 | | 207839 | KING | PRESIDENT | | 1981/11/17 | 5000 | | 107844 | TURNER | SALESMAN | 7698 | 1981/9/8 | 1500 | 0 | 307876 | ADAMS | CLERK | 7788 | 1987/5/23 | 1100 | | 207900 | JAMES | CLERK | 7698 | 1981/12/3 | 950 | | 307902 | FORD | ANALYST | 7566 | 1981/12/3 | 3000 | | 207934 | MILLER | CLERK | 7782 | 1982/1/23 | 1300 | | 10(14 rows)postgres=#
postgres_fdw:访问外部的文件系统
通过使用 file_fdw 扩展使得 PostgreSQL 能够访问外部文件系统中的数据文件,同样通过使用 postgres_fdw 扩展可以使得 PostgreSQL 能够访问外部远端的 PostgreSQL 数据库中的数据。下面通过具体的步骤操作来演示如何使用 postgres_fdw 扩展。
编译和安装postgres_fdw修改配置文件和上面file_fdw一致请参考上面这部分
#只是在修改配置文件的时候在后面添加插件名字用,隔开shared_preload_libraries ='file_fdw,postgres_fdw'
重启数据库实例
[postgres@pg15 pgsql]$ bin/pg_ctl -D data/ -l logfile restartwaiting for server to shut down.... doneserver stoppedwaiting for server to start.... doneserver started[postgres@pg15 pgsql]$ bin/pg_ctl -D data/ -l logfile statuspg_ctl: server is running (PID: 115560)/home/postgres/training/pgsql/bin/postgres "-D""data"
到这里postgres_fdw这个扩展插件就编译安装好了
postgres_fdw:访问外部的文件系统
#创建 postgres_fdw 扩展postgres=# create extension postgres_fdw;CREATE EXTENSIONpostgres=# \xExpanded display is on.postgres=# select * from pg_extension;-[ RECORD 1 ]--+-------------oid | 13673extname | plpgsqlextowner | 10extnamespace | 11extrelocatable | fextversion | 1.0extconfig | extcondition | -[ RECORD 2 ]--+-------------oid | 16399extname | file_fdwextowner | 10extnamespace | 2200extrelocatable | textversion | 1.0extconfig | extcondition | -[ RECORD 3 ]--+-------------oid | 16410extname | postgres_fdwextowner | 10extnamespace | 2200extrelocatable | textversion | 1.1extconfig | extcondition |#创建远程服务器postgres=# create server foreign_server foreign data wrapper postgres_fdwpostgres-# options (host 'localhost',port '5432',dbname 'scott');CREATE SERVER#创建用户映射create user mapping for postgresserver foreign_serveroptions (user 'postgres', password '你的postgres密码');postgres=# create user mapping for postgrespostgres-# server foreign_serverpostgres-# options (user 'postgres', password '你的postgres密码');CREATE USER MAPPING#创建远程外部表postgres=# create foreign table ft_dept (postgres(# deptno int,postgres(# dname varchar(14),postgres(# loc varchar(13)postgres(# )postgres-# server foreign_serverpostgres-# options (schema_name 'public', table_name 'dept');CREATE FOREIGN TABLEpostgres=# \xExpanded display is off.#然后查询postgres=# select * from ft_dept; deptno | dname | loc --------+------------+----------10 | ACCOUNTING | NEW YORK20 | RESEARCH | DALLAS30 | SALES | CHICAGO40 | OPERATIONS | BOSTON(4 rows)#远程的外部表内容有更新也会同步到外部表里面[postgres@pg15 pgsql]$ bin/psql psql (15.3)Type "help"for help.postgres=# \c scott You are now connected to database "scott" as user "postgres".scott=# insert into dept values(50,'HR','WuHan');INSERT 01scott=# select * from dept; deptno | dname | loc --------+------------+----------10 | ACCOUNTING | NEW YORK20 | RESEARCH | DALLAS30 | SALES | CHICAGO40 | OPERATIONS | BOSTON50 | HR | WuHan(5 rows)#去查询外部表postgres-# server foreign_serverpostgres-# options (schema_name 'public', table_name 'dept');CREATE FOREIGN TABLEpostgres=# \xExpanded display is off.postgres=# select * from ft_dept; deptno | dname | loc --------+------------+----------10 | ACCOUNTING | NEW YORK20 | RESEARCH | DALLAS30 | SALES | CHICAGO40 | OPERATIONS | BOSTON(4 rows)postgres=# select * from ft_dept; deptno | dname | loc --------+------------+----------10 | ACCOUNTING | NEW YORK20 | RESEARCH | DALLAS30 | SALES | CHICAGO40 | OPERATIONS | BOSTON50 | HR | WuHan(5 rows)postgres=#
oracle_fdw:访问外部的文件系统
使用 Oracle 数据库扩展 oracle_fdw
使用oracle_fdw:访问外部的文件系统需要有orcal环境我会发orcal安装教程具体安装看后面更新的文章
与 file_fdw 和 postgres_fdw 扩展类似,oracle_fdw 也是 PostgreSQL 数据库支持的外部扩展。通过使用 oracle_fdw 扩展可以读取到 Oracle 数据库中的数据。它是一种非常方便且常见的 PostgreSQL 与 Oracle 的同步数据的方法。
oracle_fdw 扩展需要依赖 Oracle 的 Instance Client 环境。
Oracle Instant Client 的组件包下载地址:https://www.oracle.com/cn/database/technologies/instant-client/linux-x86-64-downloads.html
| 文件名 | 作用 | 必须下载吗? |
|---|---|---|
instantclient-basic-linuxx64.zip | 基础运行库,oracle_fdw 必须依赖 | ✅ 必须 |
instantclient-sqlplus-linuxx64.zip | 提供 sqlplus 命令行工具,方便你直接连 Oracle | ⭕ 推荐 |
instantclient-sdk-linuxx64.zip | 开发头文件,oracle_fdw 编译必须依赖 | ✅ 必须 |
[postgres@pg15 ~]$ cd tools/instantclient/[postgres@pg15 instantclient]$ lsinstantclient-basic-linux.x64-19.31.0.0.0dbru.zip instantclient-sdk-linux.x64-19.31.0.0.0dbru.zip instantclient-sqlplus-linux.x64-19.31.0.0.0dbru.zip-- 分别解压三个安装包unzip instantclient-basic-linux.x64-19.31.0.0.0dbru.zip unzip instantclient-basic-linux.x64-19.31.0.0.0dbru.zip unzip instantclient-sqlplus-linux.x64-19.31.0.0.0dbru.zip -- 改个文件名方便辨认[postgres@pg15 instantclient]$ lsinstantclient_19_31 instantclient-basic-linux.x64-19.31.0.0.0dbru.zip instantclient-sdk-linux.x64-19.31.0.0.0dbru.zip instantclient-sqlplus-linux.x64-19.31.0.0.0dbru.zip META-INF[postgres@pg15 instantclient]$ mv instantclient_19_31 instantclient[postgres@pg15 instantclient]$ lsinstantclient instantclient-basic-linux.x64-19.31.0.0.0dbru.zip instantclient-sdk-linux.x64-19.31.0.0.0dbru.zip instantclient-sqlplus-linux.x64-19.31.0.0.0dbru.zip META-INF-- 设置orcal环境变量[postgres@pg15 instantclient]$ vi ~/.bash_profile #添加以下内容exportORACLE_HOME=/home/postgres/tools/instantclient/instantclientexportOCI_LIB_DIR=$ORACLE_HOMEexportOCI_INC_DIR=$ORACLE_HOME/sdk/includeexportLD_LIBRARY_PATH=$ORACLE_HOME:$LD_LIBRARY_PATH[postgres@pg15 instantclient]$ source ~/.bash_profile [postgres@pg15 instantclient]$ echo$ORACLE_HOME/home/postgres/tools/instantclient/instantclient-- 下载 oracle_fdw 源码[postgres@pg15 instantclient]$ cd ..wget https://github.com/laurenz/oracle_fdw/archive/refs/tags/ORACLE_FDW_2_6_0.tar.gz[postgres@pg15 tools]$ lsinstantclient ORACLE_FDW_2_6_0.tar.gz postgresql-15.3 postgresql-15.3.tar.gz-- 解压设置pg_config的环境变量并编译安装[postgres@pg15 tools]$ tar-zxvf ORACLE_FDW_2_6_0.tar.gz [postgres@pg15 oracle_fdw-ORACLE_FDW_2_6_0]$ exportPATH=/home/postgres/training/pgsql/bin:$PATH[postgres@pg15 oracle_fdw-ORACLE_FDW_2_6_0]$ which pg_config ~/training/pgsql/bin/pg_config--能输出 /home/postgres/training/pgsql/bin/pg_config,就说明环境已经完全配置好了,直接 make 即可[postgres@pg15 oracle_fdw-ORACLE_FDW_2_6_0]$ make[postgres@pg15 oracle_fdw-ORACLE_FDW_2_6_0]$ make install
使用root用户添加oracle依赖的库信息,添加完成后切换回postgres用户
为什么要做这一步?
oracle_fdw 运行时需要依赖 Oracle 客户端的 .so 库文件,通过 ldconfig 可以让系统全局识别这些库,避免在 PostgreSQL 运行时出现 error while loading shared libraries 这类错误。
[postgres@pg15 oracle_fdw-ORACLE_FDW_2_6_0]$ su- root[root@pg15 ~]# echo "/home/postgres/tools/instantclient/instantclient" > /etc/ld.so.conf.d/oracle.conf[root@pg15 ~]# ldconfig[root@pg15 ~]# su - postgres Last login: Thu May 2112:57:45 CST 2026 on pts/0[postgres@pg15 ~]$
启动数据库创建扩展
[postgres@pg15 ~]$ cd training/pgsql/[postgres@pg15 pgsql]$ bin/pg_ctl -D data/ -l logfile startwaiting for server to start.... doneserver started-- 创建扩展[postgres@pg15 pgsql]$ bin/psql psql (15.3)Type "help"for help.postgres=# create extension oracle_fdw;CREATE EXTENSIONpostgres=# \dx List of installed extensions Name | Version | Schema | Description --------------+---------+------------+---------------------------------------------------- file_fdw | 1.0 | public | foreign-data wrapper for flat file access oracle_fdw | 1.2 | public | foreign data wrapper for Oracle access plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language postgres_fdw | 1.1 | public | foreign-data wrapper for remote PostgreSQL servers(4 rows)
创建基于 oracle_fdw的外部数据库服务
-- 切换orcal账户看一下1521端口是不是正常监听和启动[root@pg15 ~]# su - oracle 上一次登录:四 5月 2113:37:30 CST 2026pts/4 上[oracle@pg15 ~]$ lsnrctl status如果看到 The listener supports no services 或者命令报错,说明监听没起来-- 就用下面命令启动监听[oracle@pg15 ~]$ lsnrctlstart-- 检查端口[oracle@pg15 ~]$ netstat-tlnp | grep1521(Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.)tcp6 00 :::1521 :::* LISTEN 96638/tnslsnr-- 切换postgres账户创建基于 oracle_fdw的外部数据库服务su- postgres[postgres@pg15 ~]$ cd training/pgsql/[postgres@pg15 pgsql]$ bin/psql psql (15.3)Type "help"for help.postgres=# create server oracle_serverpostgres-# foreign data wrapper oracle_fdwpostgres-# options (dbserver '//192.168.10.139:1521/orcl');CREATE SERVERpostgres=# \xExpanded display is on.postgres=# \des+List of foreign servers-[ RECORD 1 ]--------+------------------------------------------------Name | foreign_serverOwner | postgresForeign-data wrapper | postgres_fdwAccess privileges | Type | Version | FDW options | (host 'localhost', port '5432', dbname 'scott')Description | -[ RECORD 2 ]--------+------------------------------------------------Name | oracle_serverOwner | postgresForeign-data wrapper | oracle_fdwAccess privileges | Type | Version | FDW options | (dbserver '//192.168.10.139:1521/orcl')Description | -[ RECORD 3 ]--------+------------------------------------------------Name | service_fileOwner | postgresForeign-data wrapper | file_fdwAccess privileges | Type | Version | FDW options | Description | postgres=#
创建postgreSQL与Oracle之间的用户映射
postgres=# create user mapping for postgrespostgres-# server oracle_serverpostgres-# options (user 'scott', password 'tiger');CREATE USER MAPPING
在pgsql数据库中创建外部表访问orcal中的数据
postgres=# create foreign table oracle_emp(postgres(# empno numeric(4,0) options (key 'true') not null,postgres(# ename varchar(10),postgres(# job varchar(9),postgres(# mgr numeric(4,0),postgres(# hiredate timestamp,postgres(# sal numeric(7,2),postgres(# comm numeric(7,2),postgres(# deptno numeric(2,0)postgres(# ) server oracle_serverpostgres-# options (schema 'SCOTT', table 'EMP');CREATE FOREIGN TABLE-- 需要注意这里SCOTT和EMP需要大写-- 然后我们发现可以直接通过外部表访问oracle数据postgres=# select * from oracle_emp;-[ RECORD 1 ]-----------------empno | 7369ename | SMITHjob | CLERKmgr | 7902hiredate | 1980-12-1700:00:00sal | 800.00comm | deptno | 20-[ RECORD 2 ]-----------------empno | 7499ename | ALLENjob | SALESMANmgr | 7698hiredate | 1981-02-2000:00:00sal | 1600.00comm | 300.00deptno | 30-[ RECORD 3 ]-----------------empno | 7521ename | WARDjob | SALESMANmgr | 7698hiredate | 1981-02-2200:00:00sal | 1250.00comm | 500.00deptno | 30postgres=# -- 下面为orcal用户查看oracle表发现和数据和上面外部访问一样[oracle@pg15 ~]$ sqlplus / as sysdbaSQL*Plus: Release 19.0.0.0.0 - Production on Thu May 2115:46:20 2026Version 19.3.0.0.0Copyright (c) 1982, 2019, Oracle. All rights reserved.Connected to:Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - ProductionVersion 19.3.0.0.0SQL> conn scott/tigerConnected.SQL> select * from emp; EMPNO ENAME JOB MGR HIREDATE SAL COMM-------------------------------------------------------------------- DEPTNO----------7369 SMITH CLERK 790217-DEC-80800207499 ALLEN SALESMAN 769820-FEB-811600300307521 WARD SALESMAN 769822-FEB-81125050030SQL>
还有一种自导导入也可以通过在pgsql数据库访问orcal中的数据
| 特性 | 自动导入 IMPORT FOREIGN SCHEMA | 手动创建 CREATE FOREIGN TABLE |
|---|---|---|
| 创建方式 | 一条命令自动生成 | 逐张表、逐列手动定义 |
| Schema / 表名 | 完全继承 Oracle 的 schema 和表名 | 可以自定义 PG 里的表名(比如 oracle_emp) |
| 字段定义 | 自动按 Oracle 字段类型映射 | 必须手动写清每一列的 PG 数据类型 |
| 主键 / 索引 | 自动识别 Oracle 主键 | 需手动通过 options (key 'true') 指定主键 |
| 适用场景 | 快速迁移、一次性导入整个 schema | 只需要访问少数几张表,或需要自定义表结构 |
| 优缺点 | 快、省事,但灵活性低 | 灵活可控,但写起来麻烦,容易写错字段类型 |
自动把 Oracle 里的 把 Oracle scott 用户下的所有表全部导入 PG
import foreign schema scott from server oracle_server into public;--- 执行完,直接查select * from emp;
我这里就不演示了因为我pgsql里面有emp这个表自动导入命令它会试图在 PG 里再创建一张叫 emp、dept 的外部表表名重复 → 直接报错,创建失败!
总结
无论哪种方式,数据都不存在 PostgreSQL 里,外部表只是一个「代理」,查询时 PG 会把请求转发给 Oracle,再把结果返回给你。所以 Oracle 里的数据变了,PG 里查出来的结果也会跟着变
夜雨聆风