MathJax

MathJax-2

MathJax-3

Google Code Prettify

置頂入手筆記

EnterproseDB Quickstart — 快速入門筆記

由於考慮採用 EnterpriseDB 或是直接用 PostgreSQL 的人,通常需要一些入手的資料。這邊紀錄便提供相關快速上手的簡單筆記 ~ 這篇筆記以 資料庫安裝完畢後的快速使用 為目標,基本紀錄登入使用的範例:

2016年11月10日 星期四

同一個 Postgres Cluster 的不同資料庫之間的資料怎麼溝通?

在同一個 PostgreSQL Instance(或稱作一個 PostgreSQL Cluster)裡面,不同的 Database 間要交換資料,這看起來是個小小問題,但其實只能走連線交換資料的方式,沒有想像中的直覺。

PostgreSQL 提供以下兩種方式進行:
1. 用 Postgres_FDW 存取外部表
2. 用 DBLink 連到其他資料庫

其中的 postgres_fdw 在最近發展功能越來越豐富,因此一般建議使用 Postgres_FDW 去進行不同 Database 之間,資料的交換。

以下簡單示範在 EDB 公司的 PostgreSQL 9.5 企業版中使用 postgres_fdw 進行存取。
來源的 database 是 edb,以及裡面的範例資料 Schema;然後在另外一個 database,postgres 建立外部表。


以下即操作步驟

先確認 edb 裡面的範例表

bash-4.1$ psql -U enterprisedb -d edb
Password: 
psql.bin (9.5.3.8)
Type "help" for help.


edb=# \d
               List of relations
 Schema |    Name    |   Type   |    Owner     
--------+------------+----------+--------------
 public | dept       | table    | enterprisedb
 public | emp        | table    | enterprisedb
 public | jobhist    | table    | enterprisedb
 public | next_empno | sequence | enterprisedb
 public | salesemp   | view     | enterprisedb


登入啟用套件,然後設置一個存放外部表的 Schema

edb=# \c postgres
You are now connected to database "postgres" as user "enterprisedb".
postgres=# CREATE EXTENSION postgres_fdw;
CREATE EXTENSION
postgres=# CREATE SCHEMA edb_sample_tabs;
CREATE SCHEMA


設置存取資訊:分成資料庫連線資訊,以及帳號密碼資訊。注意一點,在此 CREATE SERVER 中連線資訊不指定 host IP,便會走本地的 Unix Socket,這會比走網路協定要快的多。

postgres=# CREATE SERVER local_edb
            FOREIGN DATA WRAPPER postgres_fdw
            OPTIONS (dbname 'edb');
CREATE SERVER
postgres=# CREATE USER MAPPING FOR CURRENT_USER
            SERVER local_edb
            OPTIONS (user 'enterprisedb', password 'password');
CREATE USER MAPPING

最後,就可以匯入表格資訊
postgres=# IMPORT FOREIGN SCHEMA public
            FROM SERVER local_edb
            INTO edb_sample_tabs;
ImMPORT FOREIGN SCHEMA
postgres=# SET search_path TO edb_sample_tabs;
SET
postgres=# \d
                     List of relations
     Schema      |   Name   |     Type      |    Owner     
-----------------+----------+---------------+--------------
 edb_sample_tabs | dept     | foreign table | enterprisedb
 edb_sample_tabs | emp      | foreign table | enterprisedb
 edb_sample_tabs | jobhist  | foreign table | enterprisedb
 edb_sample_tabs | salesemp | foreign table | enterprisedb



上面使用的 Foreign Schema 是 PostgreSQL 9.5 版才引入的功能,這功能讓外部表的匯入更為簡易,不用輸入完整表格 DDL 也能夠進行,還能指定/排除特定表格作匯入,是一個不錯的功能。

僅匯入 emp 表格:

postgres=# IMPORT FOREIGN SCHEMA public
            LIMIT TO (emp)
            FROM SERVER local_edb
            INTO edb_sample_tabs;

排除 emp 表格之外的都匯入
postgres=# IMPORT FOREIGN SCHEMA public
            EXCLUDE (emp)
            FROM SERVER local_edb
            INTO edb_sample_tabs;

換作是匯入外部表的語法,則需要指名 DDL;不過好處是,能夠自選要提供的欄位,不用讓「全部」欄位都出現在外部表裡面
postgres=# CREATE FOREIGN TABLE scm.foreign_emp(
              empno numeric,
              ename varchar(10)
              ) SERVER local_edb
              OPTIONS (schema_name 'public', table_name 'emp');



以上所作的簡單示範,是直接用 Super User 進行;若是要給予一般帳戶存取表格,只需要處理相關外部表的 GRANT 即可。而要給予建立外部表的能力,則需要賦予帳戶 FOREIGN DATA WRAPPER 的 USAGE 權限才行。至於啟用任何一種 Foreign Data Wrapper 套件(例如,CREATE EXTENSION postgres_fdw)則需要先以 Super User 建立才行。範例請參考下述示範。




接著,以下示範的是,允許一個 Non-SuperUser 的帳號(在此為一個 Database Owner)在某個資料庫可以建立 Foreign Server、外部表;然後允許其他普通帳戶可以存取該表格。

prod=# \c
You are now connected to database "prod" as user "enterprisedb".
prod=# CREATE EXTENSION postgres_fdw;
CREATE EXTENSION
prod=# grant all on FOREIGN DATA WRAPPER postgres_fdw TO prod; 
GRANT

prod=# -- 離開 Super User,換成 database owner
prod=# \c prod prod
Password for user prod: 
You are now connected to database "prod" as user "prod".
prod=> -- 先建立一個 Non-Public Schema
prod=> CREATE SCHEMA scm;
prod=>
prod=> -- 建立 prod 這個帳號專屬的外部表
prod=> -- 注意的是,USER MAPPING 指定的對象要指派給需要用的帳號
prod=> -- 在此設定開放給大眾帳號存取
prod=> CREATE SERVER local_edb FOREIGN DATA WRAPPER postgres_fdw OPTIONS (dbname 'edb');
CREATE SERVER
prod=> CREATE USER MAPPING
  FOR PUBLIC
  SERVER local_edb
  OPTIONS (user 'enterprisedb', password 'edb');
CREATE USER MAPPING
prod=> IMPORT FOREIGN SCHEMA public
  LIMIT TO (emp)
  FROM SERVER local_edb
  INTO scm;
IMPORT FOREIGN SCHEMA
prod=> select * from scm.emp limit 1;
 empno | ename |  job  | mgr  |      hiredate      |  sal   | comm | deptno 
-------+-------+-------+------+--------------------+--------+------+--------
  7369 | SMITH | CLERK | 7902 | 17-DEC-80 00:00:00 | 800.00 |      |     20
(1 row)
prod=>
prod=>
prod=> -- 接著,授予某個普通帳號 normaluser 存取外部表的權限
prod=> -- 要賦予的權限,只要使該帳號能存取表格就夠了,用法與一般表一樣
prod=> grant usage on SCHEMA scm to dever1;
GRANT
prod=> grant SELECT on scm.emp to dever1;
GRANT

prod=> -- 換成普通帳號 normaluser 登入
prod=> \c prod normaluser
Password for user normaluser:
You are now connected to database "prod" as user "normaluser".
prod=> select * from scm.emp limit 1;
 empno | ename |  job  | mgr  |      hiredate      |  sal   | comm | deptno 
-------+-------+-------+------+--------------------+--------+------+--------
  7369 | SMITH | CLERK | 7902 | 17-DEC-80 00:00:00 | 800.00 |      |     20
(1 row)
prod=>
prod=> -- 值得提的一點是,連線資訊正常帳號看不到
prod=> \deu+
        List of user mappings
  Server   | User name | FDW Options 
-----------+-----------+-------------
 local_edb | public    | 
(1 row)
prod=>

prod=> -- 然而,如果 prod 帳號授予 normaluser 相關權限,normaluser 就會得知密碼了
prod=# \c prod prod
Password for user prod: 
You are now connected to database "prod" as user "prod".
prod=> grant usage on FOREIGN SERVER local_edb TO dever1;
GRANT
prod=> \c prod normaluser
Password for user normaluser:
You are now connected to database "prod" as user "normaluser".
prod=> \deu+
                      List of user mappings
  Server   | User name |               FDW Options               
-----------+-----------+-----------------------------------------
 local_edb | public    | ("user" 'enterprisedb', password 'edb')
(1 row)



最後小結
  • 在一個 Database 啟用 Foreign Data Wrapper:
    • 需要由 Super User 啟用
  • 允許一個帳戶(通常是 Database Owner)能建立 FDW,並且其他帳戶看不到他存儲的帳號密碼資訊:
    • 由 Super User 允許該帳戶(Database Owner)使用 Foreign Data Wrapper 套件的使用權限
    • 建立外部表的連線資訊、登入帳密,還有外部表
    • 登入帳密設置(CREATE USER MAPPING)要指定會用到的帳號,請參考 PostgreSQL: Documentation : CREATE USER MAPPING
    • 規劃上,可以透過 GROUP ROLE 作權限配置
  • 允許一個普通帳號存取某個不屬於他的外部表:
    • 把外部表當作普通表格,由外部表的建立者賦予普通帳號相關的表葛存取權限
    • 連線資訊,對於一般帳號,是看不到的
    • 要是賦予了某帳號對 Foreign Server 有 Usage 權限,這個帳號就會不小心看到帳密了 ...

最後提醒:在 PostgreSQL 裡面,Database 是各自物件獨立的邏輯個體,Schema 類似一種 Name Space 的想法。所以就算是待在同一個 Instance 裡面的不同 Database,並不能像不同 Schema 一樣,「直接」的相互存取。


參考資料:
A look at Foreign Data Wrappers Craig Kerstiens
還有更多,可以直接搜尋,或參考之前發布的文章

沒有留言:

張貼留言