MathJax

MathJax-2

MathJax-3

Google Code Prettify

置頂入手筆記

EnterproseDB Quickstart — 快速入門筆記

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

2016年5月10日 星期二

Point-in-Time Recovery 操作筆記

環境:既有運作的一個 PostgreSQL instance,其資料夾位在/home/aaa/pgsql/9.5/data/,沒有 tablespace,資料庫的 superuser 為 aaa。
WAL archived 目錄亦放置於同一台主機上/home/aaa/pgsql/wals 裡面。
以下備份操作都在同一主機上進行備份與還原。


1. 在 postgresql.conf 編輯:

[aaa@localhost ~]$ vim /home/aaa/pgsql/9.5/data/postgresql.conf

wal_level = archive    # hot_standby、logical 也可以
archive_mode = on
archive_command = 'cp %p /home/aaa/pgsql/wals/%f'
max_wal_senders = 1    # 允許用 pg_basebackup 連入資料庫

2. 在 pg_hba.conf 編輯,允許待會全備份的連線

[aaa@localhost ~]$ vim /home/aaa/pgsql/9.5/data/pg_hba.conf

host    replication     aaa             127.0.0.1/32            trust

3. 重新啟動資料庫

[aaa@localhost ~]$ pg_ctl -D /home/aaa/pgsql/9.5/data/ restart

4. 使用 pg_basebackup 指令進行資料庫全備份,弄成壓縮檔

[aaa@localhost ~]$ mkdir /home/aaa/pgsql/total/
[aaa@localhost ~]$ pg_basebackup -p 5432 -Ft -z \
> -D /home/aaa/pgsql/total/
NOTICE:  pg_stop_backup complete, all required WAL segments have been archived

5. 資料庫繼續進行服務:插入一些資料進去,停頓三十秒,並紀錄時間,如此重複三次。

[aaa@localhost ~]$ psql -p 5432 -d postgres -c "BEGIN;CREATE TABLE \
> dummy1 AS SELECT * FROM pg_class;COMMIT; \
> SELECT pg_sleep(30);SELECT now();"
             now            
-------------------------------
2016-05-10 16:10:01.719448+08
(1 row)

[aaa@localhost ~]$ psql -p 5432 -d postgres -c "BEGIN;CREATE TABLE \
> dummy2 AS SELECT * FROM pg_class;COMMIT; \
> SELECT pg_sleep(30);SELECT now();"
             now            
-------------------------------
2016-05-10 16:11:57.732774+08
(1 row)

[aaa@localhost ~]$ psql -p 5432 -d postgres -c "BEGIN;CREATE TABLE \
> dummy3 AS SELECT * FROM pg_class;COMMIT; \
> SELECT pg_sleep(30);SELECT now();"
             now            
-------------------------------
2016-05-10 16:14:14.526662+08
(1 row)

6. 模擬資料庫發生異常。使用 pg_ctl 的 immediate mode 會造成關檔不完全,用此進行模擬:


[aaa@localhost ~]$ psql -p 5432 postgres\ > -c "BEGIN;SELECT \
> pg_sleep(3);CREATE TABLE \
> dummy4 AS SELECT * FROM \
> pg_class; SELECT \
> pg_sleep(30);SELECT now(); \
> Commit;"
WARNING:  terminating connection because of crash of another server process
DETAIL:  The postmaster has commanded this server process to roll back the current transaction
 and exit, because another server process exited abnormally and possibly corrupted shared memory.
HINT:  In a moment you should be able to reconnect to the database and repeat your command.
server closed the connection unexpectedly
       This probably means the server terminated abnormally
       before or while processing the request.
connection to server was lost
[aaa@localhost ~]$ # 左方過個四~五秒再執行強至關閉指令
[aaa@localhost ~]$ 
[aaa@localhost ~]$ pg_ctl -D \
> /home/aaa/pgsql/9.5/data/ \
> -m immediate stop
waiting for server to shut down.... done
server stopped



目前資料庫的 instance 已經有部份損毀。利用既有的內容完成回復作業

7. 先將突然中止的 /home/aaa/pgsql/9.5/data/ 重新命名,留作備用;接著解壓縮全備份

[aaa@localhost ~]$ mv /home/aaa/pgsql/9.5/data/ \
> /home/aaa/pgsql/9.5/data.crashed
[aaa@localhost ~]$ mkdir /home/aaa/pgsql/9.5/data/
[aaa@localhost ~]$ chmod 700 /home/aaa/pgsql/9.5/data/
[aaa@localhost ~]$ tar zxf /home/aaa/pgsql/total/base.tar.gz \
> -C /home/aaa/pgsql/9.5/data/

8. 移除目前 /home/aaa/pgsql/9.5/data/ 中被一併打包的 pg_xlog/ 內容以及運作標記的 lock

[aaa@localhost ~]$ rm /home/aaa/pgsql/9.5/data/postmaster.*
[aaa@localhost ~]$ rm /home/aaa/pgsql/9.5/data/pg_xlog/*

9. 將/home/aaa/pgsql/9.5/data.crashed/ 裡面的 pg_xlog/ 內容放到等著回復的/home/aaa/pgsql/9.5/data/pg_xlog/裡面

[aaa@localhost ~]$ cp -rp /home/aaa/pgsql/9.5/data.crashed/pg_xlog/* \
/home/aaa/pgsql/9.5/data/pg_xlog/

10. 設置 recovery.conf,指定回復到先前 dummy2 表格建立後,dummy3 建立之前

[aaa@localhost ~]$ vim /home/aaa/pgsql/9.5/data/recovery.conf

restore_command = 'cp /home/cchsu/pgsql/wala95/%f %p'
recovery_target_time = '2016-05-10 16:11:59'

11. 啟動資料庫,並同時觀察狀況

[aaa@localhost ~]$ pg_ctl -D \
> /home/cchsu/pgsql/95stdby2/ \
> start
server starting
bash-4.3$ LOG:  redirecting log output to logging collector process
HINT:  Future log output will appear in directory "pg_log".
[aaa@localhost ~]$ tail -f \
> /home/aaa/pgsql/9.5/data/ \ > pg_log/postgresql-2016-05- \
10_170312.log
LOG:  starting point-in-time recovery to 2016-05-10 16:11:59+08
LOG:  restored log file "00000004.history" from archive
LOG:  restored log file "000000040000000000000028" from archive
LOG:  redo starts at 0/28000060
LOG:  consistent recovery state reached at 0/28000130
LOG:  database system is ready to accept read only connections
LOG:  restored log file "000000040000000000000029" from archive
LOG:  recovery stopping before commit of transaction 1449, time 2016-05-10 16:12:31.941565+08
LOG:  recovery has paused
HINT:  Execute pg_xlog_replay_resume() to continue.


12. 進入資料庫看

postgres=# select tablename from pg_tables
postgres-#  where schemaname = 'public'
postgres-#  order by tablename;
     tablename   
-------------------
 dummy1
 dummy2
(2 rows)
postgres=# select pg_is_in_recovery();
 pg_is_in_recovery
-------------------
 t
(1 row)

由此確定資料庫僅回復到所指定的位置了

13. 確定回復目前狀態,正常啟用

postgres=# SELECT pg_xlog_replay_resume();
 pg_xlog_replay_resume
-----------------------
(1 row)

postgres=# select pg_is_in_recovery();
 pg_is_in_recovery
-------------------
 f
(1 row)


參考資料:



PostgreSQL Point-in-time Recovery (Incremental Backup)

Point In Time Recovery From Backup using PostgreSQL Continuous Archving - Zetetic

PostgreSQL Point-in-time Recovery (using WAL) | Madilator

Point in time recovery: PITR using pg_basebackup with PostgreSQL 9.2

The Scale-Out Blog: Simple HA with PostgreSQL Point-In-Time Recovery

The Internals of PostgreSQL : Chapter 9 Write Ahead Log (WAL)

select * from depesz; » Blog Archive » Write Ahead Log + Understanding postgresql.conf: checkpoint_segments, checkpoint_timeout, checkpoint_warning

Korry Douglas-PostgreSQL - The Comprehensive Guide

2016年5月8日 星期日

PostgreSQL 9.x 連到 Greenplum

Greenplum 基於 PostgreSQL 8.x,照理說要很像 PostgreSQL;那麼兩類資料庫要跨接時,能怎麼做?目前我找到的方式,有使用 DBLink,或是用 postgres_fdw 這個 Foreign Data Wrapper 套件。

使用 DBLink 連到 Greenplum,找到的都是實驗性質的使用。所以在此我用 Foreign Data Wrapper 接到 Greenplum。

Foreign Data Wrapper 是一個 PostgreSQL 的擴充套件(Extension),所以要使用  Foreign Data Wrapper,要先在所連線的資料庫裡面建立 Extension。例如,以下在 postgres 下為例:

postgres=# CREATE EXTENSION postgres_fdw;

若想要之後每次都產生 database 時,都自動加上這個套件的話,則將該套件建立到 template1:

[postgres ~]$ psql -d template1 -c 'create extension postgres_fdw;'

接著便開始要進行設定。

連線設定,要先使用 CREATE SERVER 指令,使用連線字串設定方式設定連線到 Greenplum 的資訊。在此 Greenplum 的 入口 IP (Master Instance)為 192.168.238.152,port 為 5432:
postgres=# CREATE SERVER gp_db
postgres-# FOREIGN DATA WRAPPER postgres_fdw
postgres-# OPTIONS (host '192.168.238.152', port '5432', dbname 'fdwtest');
CREATE SERVER

接著設定登入帳密:值得注意的是,一般帳密都是設在連線字串裡面,不過 Foreign Data Wrapper 則是另外用 CREATE USER MAPPING 指令設定的:

postgres=# CREATE USER MAPPING FOR user4gpfdw SERVER gp_db
postgres-# OPTIONS (user 'fdwuser',password 'fdwuser');
CREATE USER MAPPING

到目前為止,Foreign Data Wrapper 的資訊已經建立完畢了。

再來便是要在 Greenplum 上面建立一個可以連線的測試資料表格。
在 Greenplum 上:

gpadmin=# \c fdwtest brandon
You are now connected to database "test" as user "brandon".
fdwtest=# SET search_path TO testing;
SET
fdwtest=# CREATE TABLE productest
fdwtest-# (name VARCHAR(40), prod_id INTEGER)
fdwtest-# DISTRIBUTED BY (prod_id);
CREATE TABLE

接著,回到 PostgreSQL 上,建立一個上面已經存在於 Greenplum 上的資料表:

postgres=# CREATE FOREIGN TABLE foreigntab(
postgres(# name TEXT,
postgres(# id INTEGER)
postgres-# SERVER gp_db
postgres-# OPTIONS (schema_name 'testing', table_name 'productest');
CREATE FOREIGN TABLE

可以在 Greenplum 上檢查一下連線資訊:

gpadmin=# SELECT datname,usename,client_addr,application_name
gpadmin=#  FROM pg_stat_activity;
  datname | usename |  client_addr   | application_name
 ---------+---------+----------------+------------------
  gpadmin | brandon |                | psql
  fdwtest | fdwuser | 192.168.62.178 | postgres_fdw
  fdwtest | brandon | 192.168.62.178 | psql
(3 rows)

以上可見 postgres_fdw 連線進入的資訊,表示 postgres_fdw 有成功連線到 Greenplum 。

使用會發現,要直接輸入資料,會出現下列錯誤:
Greenplum Database does not support REPEATABLE READ transactions

所以要指定 transaction level,再輸入資料,才能避免上述錯誤:
postgres=# START TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION
Time: 0.331 ms

postgres*=# INSERT INTO foreigntab VALUES ('rastberry',101);
INSERT 0 1

Time: 220.690 ms
postgres*=# -- 這時資料輸入進去了。 
postgres*=# -- 從 PostgreSQL裡面檢查一下資料
postgres*=# SELECT * FROM foreigntab;
    name   | prod_id 
-----------+---------
 grava     |     100
 pen       |       1
 rastberry |     101
 pencil    |       2
(4 rows)

Time: 169.112 ms
postgres*=# END;
COMMIT

Time: 110.171 ms

要透過 postgres_fdw 存取 Greenplum 上的資料,都需要向上面所示,使用 SERIALIZABLE 的交易等級才行。

現在到 Greenplum 上直接檢查,也會看到剛剛從 PostgreSQL 輸入進來的資料:

gpadmin=# SELECT * FROM productest;
    name   | prod_id 
-----------+---------
 pen       |       1
 pencil    |       2
 grava     |     100
 rastberry |     101
(4 rows)


[Update 20190325] 如果要用 IMPORT FOREIGN SCHEMA 簡化匯入外部表的方式,也需要指定 isolation level。跟上面一樣,CREATE SERVER 以及 CREATE USER MAPPING 不用包在這個 Transaction 裡面(這邊延續上面的環境~)
postgres=# CREATE SCHEMA gptables;
CREATE SCHEMA
postgres=# BEGIN;
BEGIN
postgres=# SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET
postgres=# IMPORT FOREIGN SCHEMA testing LIMIT TO (productest) FROM SERVER gp_db INTO gptables;
IMPORT FOREIGN SCHEMA
postgres=# COMMIT;
COMMIT
postgres=# 



參考資料:

這是一個 postgres_fdw 的操作介紹
A look at Foreign Data Wrappers Craig Kerstiens 
以下是此次實作中,用到的 Greenplum 資料
What are the Table Distribution Policy in Greenplum - A Web Portal for Greenplum Database Professionals!
SET TRANSACTION | Pivotal Greenplum Database Docs