狠狠撸

狠狠撸Share a Scribd company logo
PostgreSQLのリカバリ超入門
Version 2.0
See also http://www.interdb.jp/pg/
2015.3.09
鈴木啓修
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 2
改訂履歴
●
2014.5.31 ver1.1
●
2015.3.09 ver2.0 LSNの説明追加+ FPW(Full-Page-Writes)の説明を修正
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 3
PostgreSQLのリカバリ超入門
目的
●
リカバリの原理を25分?30分で紹介
– リカバリ(recovery)=サーバクラッシュ後の復旧プロセス
– 物理バックアップと密接な関係
種本(ネタ元)
こちら 
講師
●
勉強会主催者の一人、種本の著者
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 4
PostgreSQLのリカバリ超入門
i. データベースとテーブル
ii. データ操作
iii. WAL(Write Ahead Logging)
iv. CHECKPOINT
v.Full-Page-Writes
vi. オンラインバックアップ
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 5
/
$PG_DATA/
base/
1/
(template0)
12891/
(templete1)
12896/
(postgres)
16384/
(sampledb)
18740
(sampletbl)
Database Cluster
pg_xlog/ global/ .......
postgresql.conf
i. データベースとテーブル
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 6
/
$PG_DATA/
base/
1/
(template0)
12891/
(templete1)
12896/
(postgres)
16384/
(sampledb)
18740
(sampletbl)
Database Cluster
pg_xlog/ global/ .......
postgresql.conf
データベースとテーブル
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 7
/
$PG_DATA/
base/
1/
(template0)
12891/
(templete1)
12896/
(postgres)
16384/
(sampledb)
18740
(sampletbl)
Database Cluster
pg_xlog/ global/ .......
postgresql.conf
データベースとテーブル
XLogRecPtr TimeLineID pd_lower
pd_special
pd_pagesize_
version
pd_prune
_xid
1
Tuple 1
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 8
8192[byte]
XLogRecPtr TimeLineID pd_lower pd_upper
pd_special
pd_pagesize_
version
pd_prune
_xid
1
Tuple 1
Heap Tuples
(record data)
Header Info
Line Pointer
TABLE = FILE
1行のデータ
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 9
8192[byte]
XLogRecPtr TimeLineID pd_lower pd_upper
pd_special
pd_pagesize_
version
pd_prune
_xid
1 2
Tuple 1
Tuple 2
INSERT
PostgreSQLはデータを追加していきます。
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 10
8192[byte]
XLogRecPtr TimeLineID pd_lower pd_upper
pd_special
pd_pagesize_
version
pd_prune
_xid
1 2
Tuple 1 AAAAAAAAAAAAABBBBBBBBBBBB
Tuple 2 BBB
INSERT
sampledb=# SELECT *
FROM sampletbl;
id | data
----+------------
1 | AAAAAAAAAA
2 | BBBBBBBBBB
(2 rows)
PostgreSQLはデータを追加していきます。
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 11
8192[byte]
XLogRecPtr TimeLineID pd_lower pd_upper
pd_special
pd_pagesize_
version
pd_prune
_xid
1 2
Tuple 1 AAAAAAAAAAAAABBBBBBBBBBBB
Tuple 2 BBB
INSERT
$ od -c data/base/16384/18740
0000000 0 0 0 0 324 V 022 002 001 0 0 0 0 260 037
0000020 0 004 0 0 0 0 330 237 N 0 260 237 N 0
*
0017660 4 * 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0017700 002 0 002 0 002 t 030 0 002 0 0 0 027 B B B
0017720 B B B B B B B 0 3 * 0 0 0 0 0 0
0017740 0 0 0 0 0 0 0 0 001 0 002 0 002 t 030 0
0017760 001 0 0 0 027 A A A A A A A A A A 0
0020000
PostgreSQLはデータを追加していきます。
sampledb=# SELECT *
FROM sampletbl;
id | data
----+------------
1 | AAAAAAAAAA
2 | BBBBBBBBBB
(2 rows)
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 12
8192[byte]
XLogRecPtr TimeLineID pd_lower pd_upper
pd_special
pd_pagesize_
version
pd_prune
_xid
1 2
Tuple 1
Tuple 2
3
Tuple 3
UPDATE
PostgreSQLはUPDATEでも追加します
MVCC (多版型同時実行制御)の一種
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 13
8192[byte]
XLogRecPtr TimeLineID pd_lower pd_upper
pd_special
pd_pagesize_
version
pd_prune
_xid
1 2
Tuple 1 AAAAAAAAAAAA
Tuple 2 BBB
3
Tuple 3 CCCCCCC
BBBBBBBBB
CCCCCC
UPDATE
PostgreSQLはUPDATEでも追加します
MVCC (多版型同時実行制御)の一種
sampledb=# UPDATE sampletbl
SET data='CCCCCCCCCC'
WHERE id = 1;
sampledb=# SELECT *
FROM sampletbl;
id | data
----+------------
2 | BBBBBBBBBB
1 | CCCCCCCCC
(2 rows)
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 14
8192[byte]
XLogRecPtr TimeLineID pd_lower pd_upper
pd_special
pd_pagesize_
version
pd_prune
_xid
1 2
Tuple 1
Tuple 2
3
Tuple 3
データが増えたら
8192[byte]
XLogRecPtr TimeLineID pd_lower pd_upper
pd_special
pd_pagesize_
version
pd_prune
_xid
1
Tuple 4
ブロック追加
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 15
ここまでのまとめ
●
1テーブル = 1ファイル
●
ファイルは8[kbyte]単位
足りなくなったら8[kbyte]づつ追加
●
データをどんどん、追加していく
INSERTだけでなく、 UPDATEも
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 16
ii. データ操作
ブロック (block)
or
ページ (page) 
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 17
データ操作
begin;
UPDATE ...;
(共有)メモリに読み込んで操作する
ページ (page)
ブロック (block)
or
ページ (page) 
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 18
データ操作
(共有)メモリに読み込んで操作する
begin;
UPDATE ...;
commit;
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 19
データ操作
(共有)メモリに読み込んで操作する
begin;
...;
commit;
HDDに書き込むのは高コストなので
なるべく
メモリ上で操作
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 20
データ操作
(共有)メモリに読み込んで操作する
begin;
...;
commit;
HDDに書き込むのは高コストなので
なるべく
メモリ上で操作
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 21
データ操作
(共有)メモリに読み込んで操作する
begin;
...;
commit;
HDDに書き込むのは高コストなので
なるべく
メモリ上で操作
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 22
データ操作
OS or Postgres
クラッシュ
(共有)メモリに読み込んで操作する
HDDに書き込むのは高コストなので
なるべく
メモリ上で操作
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 23
OS or Postgres
クラッシュ
データ操作
まずい!
更新データが消えた
Orz
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 24
iii. WAL (Write Ahead Logging)
耐障害性を高める
先に変化分だけHDDに書いて(logging)
ページ本体は後からHDDに書く
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 25
WAL (Write Ahead Logging)
●
論理的に超長いファイルを想定
WAL つづく
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 26
WAL (Write Ahead Logging)
●
論理的に超長いファイルを想定
●
物理的には16[Mbyte]のファイルの集合
WAL
1つのWALセグメント
16[Mbyte]
1つのWALセグメント
16[Mbyte]
つづく
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 27
WAL (Write Ahead Logging)
●
論理的に超長いファイルを想定
●
物理的には16[Mbyte]のファイルの集合
WAL
1つのWALセグメント
16[Mbyte]
1つのWALセグメント
16[Mbyte]
つづく
単調増加の番地(LSN=Log Sequential Number)がある
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 28
WAL (Write Ahead Logging)
●
論理的に超長いファイルを想定
●
物理的には16[Mbyte]のファイルの集合
●
差分データをWALセグメントに書く
WAL
1つのWALセグメント
16[Mbyte]
1つのWALセグメント
16[Mbyte]
つづく
単調増加の番地(LSN=Log Sequential Number)がある
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 29
WAL (Write Ahead Logging)
●
論理的に超長いファイルを想定
●
物理的には16[Mbyte]のファイルの集合
●
差分データをWALセグメントに書く
差分データ≒ (追加したデータ) ≒ (基本情報)+(更新データ)
基本情報=誤り訂正符号, INSERTかUPDATEかなど
WAL
1つのWALセグメント
16[Mbyte]
1つのWALセグメント
16[Mbyte]
つづく
単調増加の番地(LSN=Log Sequential Number)がある
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 30
$PG_DATA/
base/
1/
(template0)
12891/
(templete1)
12896/
(postgres)
16384/
(sampledb)
18740
pg_xlog/ global/ .......
WAL
順次書き込む
WALセグメントの実体はここ↓
# ls -la
total 131084
drwx------ 3 postgres postgres 4096 Apr 23 19:16 .
drwx------ 16 postgres postgres 4096 Apr 21 03:30 ..
-rw------- 1 postgres postgres 16777216 Apr 26 12:41 00000001000000000000000C
-rw------- 1 postgres postgres 16777216 Apr 23 19:02 00000001000000000000000D
-rw------- 1 postgres postgres 16777216 Apr 23 19:03 00000001000000000000000E
-rw------- 1 postgres postgres 16777216 Apr 23 19:03 00000001000000000000000F
-rw------- 1 postgres postgres 16777216 Apr 23 19:05 000000010000000000000010
-rw------- 1 postgres postgres 16777216 Apr 23 19:06 000000010000000000000011
-rw------- 1 postgres postgres 16777216 Apr 23 19:04 000000010000000000000012
-rw------- 1 postgres postgres 16777216 Apr 23 19:06 000000010000000000000013
drwx------ 2 postgres postgres 4096 Apr 23 19:16 archive_status
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 31
FAQ: HDD上のWALに書いたら
遅いんじゃないの?
HDDに分散して配置された
8[kbyte]のblockを書く
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 32
FAQ: HDD上のWALに書いたら
遅いんじゃないの?
WAL
HDDに分散して配置された
8[kbyte]のblockを書く
16[Mbyte]のWALセグメントに
必要な分だけ、シーケンシャルに書く
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 33
FAQ: HDD上のWALに書いたら
遅いんじゃないの?
HDDに分散して配置された
8[kbyte]のblockを書く
16[Mbyte]のWALセグメントに
必要な分だけ、シーケンシャルに書く
頑健性と性能を総合評価
WAL
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 34
FAQ: HDD上のWALに書いたら
遅いんじゃないの?
HDDに分散して配置された
8[kbyte]のblockを書く
16[Mbyte]のWALセグメントに
必要な分だけ、シーケンシャルに書く
WAL
SSDとかRAIDとか
FileSystemのブロックサイズとか
面倒な話は忘れるように
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 35
ということで
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 36
データ操作
(WALあり)
WAL
begin;
UPDATE ...;
LSN_1
これから書き込む
番地はLSN_1
LSN_0
LSN_0
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 37
データ操作
(WALあり)
WAL
begin;
UPDATE ...;
LSN_1
LSN_0
LSN_0
直前に書き込んだ
番地LSN_0は
headerに保存
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 38
データ操作
(WALあり)
WAL
begin;
UPDATE ...;
LSN_1
LSN_0
LSN_0
直前に書き込んだ
番地LSN_0は
headerに保存
理由はすぐに説明するので
ここでは”そういうもの”と...
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 39
データ操作
(WALあり)
WAL
begin;
UPDATE ...;
commit;
同期書き込み
commit時に
LSN_0
LSN_0
LSN_1
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 40
データ操作
(WALあり)
WAL
begin;
UPDATE ...;
commit;
LSN_0からLSN_1に書き換え
LSN_0
LSN_1
LSN_1
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 41
データ操作
(WALあり)
WAL
begin;
...
LSN_1 < LSN_2
LSN_0
LSN_1 LSN_1
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 42
データ操作
(WALあり)
WAL
begin;
...
commit;
同期書き込み
commit時に
LSN_1
LSN_0
LSN_1 LSN_2
LSN_2
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 43
データ操作
(WALあり)
WAL
begin;
...
commit;
同期書き込み
LSN_1 LSN_2
LSN_0
LSN_1 LSN_2LSN_1 LSN_3
LSN_3
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 44
データ操作
(WALあり)
WAL
begin;
...
commit;
同期書き込み
LSN_1 LSN_2 LSN_3
LSN_0
LSN_0 LSN_2 LSN_3 LSN_4
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 45
データ操作
(WALあり)
WAL
OS or Postgres
クラッシュ
LSN_1 LSN_2 LSN_3 LSN_4
LSN_0
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 46
リカバリ
サーバを再起動
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_0
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 47
リカバリ
リカバリ-フェーズ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_0
LSN_0
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 48
リカバリ
リカバリ-フェーズ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_0
LSN_0
ページのLSN(LSN_0)と
WALデータのLSN(LSN_1)を比較
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 49
リカバリ
リカバリ-フェーズ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_0
LSN_1
ページのLSN(LSN_0) < WALデータのLSN(LSN_1)
なのでREDOする
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 50
リカバリ
リカバリ-フェーズ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_0
LSN_1
ページのLSN < WALデータのLSN  ならばREDO
ページのLSN >= WALデータのLSN  ならば何もしない
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 51
リカバリ
リカバリ-フェーズ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_0
LSN_1 LSN_1
LSN_1 < LSN_2なのでREDO
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 52
リカバリ
リカバリ-フェーズ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_0
LSN_1 LSN_2
LSN_1 < LSN_2なのでREDO
そして
LSN_1からLSN_2に書き換え
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 53
リカバリ
リカバリ-フェーズ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_0
LSN_1 LSN_2 LSN_3
LSN_2 < LSN_3なのでREDO
そして
LSN_2からLSN_3に書き換え
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 54
リカバリ
リカバリ-フェーズ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_0
LSN_1 LSN_2 LSN_3 LSN_4
LSN_3 < LSN_4なのでREDO
そして
LSN_3からLSN_4に書き換え
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 55
リカバリ完了
稼働-フェーズへ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_4
LSN_4
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 56
リカバリ完了
WAL
トランザクションの実行記録なので
Transaction LOG
再実行してリカバリするから
REDO LOG
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 57
ちょっと待てよ?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 58
Question.
”どこから”
リカバリを
始めるんだ?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 59
Answer.
CHECKPOINTの
開始点から
(REDO point)
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 60
iv. CHECKPOINT
周期的にメモリ上のデータをHDDに書き込む
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 61
CHECKPOINT
そもそも
メモリ上の(更新された)ページは
周期的に
HDDに書き込まなければ
ならない
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 62
CHECKPOINT
●
周期的(default:5min)にメモリ上の(更新された)ペー
ジをHDDに書き込む
●
CHECKPOINTの開始直後の位置=REDO point
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 63
CHECKPOINT
●
周期的(default:5min)にメモリ上の(更新された)ペー
ジをHDDに書き込む
●
CHECKPOINTの開始直後の位置=REDO point
CHECKPOINTが完了すれば
(少なくとも)REDO point以前のデータはHDDに反映されてる。
→ REDO point以前のことは気にしなくてよい
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 64
CHECKPOINT
●
周期的(default:5min)にメモリ上の(更新された)ペー
ジをHDDに書き込む
●
CHECKPOINTの開始直後の位置=REDO point
CHECKPOINTが完了すれば
(少なくとも)REDO point以前のデータはHDDに反映されてる。
→ REDO point以前のことは気にしなくてよい
●
Fuzzy CHECKPOINT
●
LOCK不要
– CHECKPOINT実行中も更新可能
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 65
Fuzzy CHECKPOINT
WAL
begin;
UPDATE ...;
commit;
同期書き込み
LSN_1
LSN_0
LSN_1
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 66
Fuzzy CHECKPOINT
WAL
CHECKPOINT
開始
LSN_1
LSN_0
LSN_1
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 67
Fuzzy CHECKPOINT
WAL
REDO point
CHECKPOINT開始直後
のWALの書き込み位置
CHECKPOINT
開始
LSN_1
LSN_0
LSN_1
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 68
Fuzzy CHECKPOINT
WAL
REDO point
CHECKPOINT開始直後
のWALの書き込み位置
CHECKPOINT
開始
ちょっとややこしいやり方でちょっとややこしいやり方で
HDDHDDののpg_controlpg_control
に記録。に記録。
今回は説明略今回は説明略
詳細は種本で詳細は種本で (^_^;(^_^;
ちょっとややこしいやり方でちょっとややこしいやり方で
HDDHDDののpg_controlpg_control
に記録。に記録。
今回は説明略今回は説明略
詳細は種本で詳細は種本で (^_^;(^_^;LSN_1
LSN_0
LSN_1
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 69
Fuzzy CHECKPOINT
WAL
REDO point
CHECKPOINT開始直後
のWALの書き込み位置
CHECKPOINT完了までに
(更新された)ページを必ずHDDに書き込む
CHECKPOINT
開始
何時、書き込まれるかは分からない
LSN_1
LSN_0
LSN_1
LSN_1
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 70
Fuzzy CHECKPOINT
WAL
CHECKPOINT
実行中
OR
LSN_1
LSN_1 LSN_2
LSN_2
LSN_1 LSN_2
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 71
Fuzzy CHECKPOINT
WAL
CHECKPOINT
完了
OR OR
CHECKPOINT実行中も
更新可能
LSN_1
LSN_1
LSN_2
LSN_2 LSN_3
LSN_3
LSN_1 LSN_2 LSN_3
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 72
Fuzzy CHECKPOINT
WAL
CHECKPOINT
完了
OR OR
CHECKPOINT実行中も
更新可能
LSN_1
LSN_1
LSN_2
LSN_2 LSN_3
LSN_3
LSN_1 LSN_2 LSN_3
そのかわり
どのタイミングで
HDDに書き込まれるか
分からない
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 73
Fuzzy CHECKPOINT
WAL
OR OR
LSN_1
LSN_1
LSN_2
LSN_2 LSN_3
LSN_3
LSN_1 LSN_2 LSN_3
LSN_4
LSN_4
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 74
Fuzzy CHECKPOINT
WAL
OR OR
LSN_1 LSN_2 LSN_3
LSN_1 LSN_2 LSN_3
LSN_4
LSN_4OS or Postgres
クラッシュ
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 75
リカバリ
WAL
リカバリは
REDO point
から
OR OR
LSN_1 LSN_2 LSN_3 LSN_4
LSN_1 LSN_2 LSN_3
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 76
リカバリ
WAL
リカバリは
REDO point
から
OR OR
LSN_1 LSN_2 LSN_3 LSN_4
? ページの状態は
直前のCHECKPOINTの
タイミング次第
LSN_1 LSN_2 LSN_3
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 77
リカバリ
WAL
リカバリは
REDO point
から
LSN_1 LSN_2 LSN_3 LSN_4
ページの状態は
直前のCHECKPOINTの
タイミング次第
今回はLSN_2 のときに
書き込まれたと仮定
LSN_2
LSN_2
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 78
リカバリ
WAL
リカバリは
REDO point
から
LSN_1 LSN_2 LSN_3 LSN_4
LSN_2 LSN_2
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 79
リカバリ
WAL
リカバリは
REDO point
から
LSN_1 LSN_2 LSN_3 LSN_4
LSN_2 LSN_2
LSNが同じなので
REDOしない
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 80
リカバリ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_2 LSN_2
LSNが同じなので
REDOしない
REDOしたらマズい!
(普通の)WALデータの
REDO操作は
“ベキ等でない”から
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 81
リカバリ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_2 LSN_2 LSN2 < LSN_3
なので
REDOする
LSN_2
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 82
リカバリ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_2 LSN2 < LSN_3
なので
REDOする
LSN_2 LSN_2
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 83
リカバリ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_2 LSN2 < LSN_3
なので
REDOする
そして
LSN_3書き換え
LSN_2 LSN_3
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 84
リカバリ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_2
同様に
REDOして
LSN書き換え
LSN_2 LSN_3 LSN_4
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 85
リカバリ完了
稼働-フェーズへ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_2 LSN_2 LSN_3 LSN_4
LSN_4
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 86
リカバリ完了
稼働-フェーズへ
WAL
(原理的には)
CHECKPOINT間の変更分だけ
書き込めるWALセグメントがあればよい
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 87
ちょいと脇道へ
初見時は
vi.オンラインバックアップ
まで飛ばしてもOK
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 88
v. Full-Page-Writes
●
WALでリカバリ可能
●
全ページ正常で、常に完璧にREDOできることが前提
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 89
v. Full-Page-Writes
●
WALでリカバリ可能
●
全ページ正常で、常に完璧にREDOできることが前提
– もしもページが壊れたら?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 90
v. Full-Page-Writes
●
WALでリカバリ可能
●
全ページ正常で、常に完璧にREDOできることが前提
– もしもページが壊れたら?
●
こんなこともあろうかと
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 91
v. Full-Page-Writes
●
WALでリカバリ可能
●
全ページ正常で、常に完璧にREDOできることが前提
– もしもページが壊れたら?
●
こんなこともあろうかと Full-Page-Writes
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 92
v. Full-Page-Writes
●
WALでリカバリ可能
●
全ページ正常で、常に完璧にREDOできることが前提
– もしもページが壊れたら?
●
こんなこともあろうかと Full-Page-Writes
●
Full-Page-Writes:
– Checkpoint直後は(差分でなく)ページ全体をWALに
書き込む
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 93
v. Full-Page-Writes
●
WALでリカバリ可能
●
全ページ正常で、常に完璧にREDOできることが前提
– もしもページが壊れたら?
●
こんなこともあろうかと Full-Page-Writes
●
Full-Page-Writes:
– Checkpoint直後は(差分でなく)ページ全体をWALに
書き込む
– PostgreSQLはデフォルトで有効
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 94
v. Full-Page-Writes
●
WALでリカバリ可能
●
全ページ正常で、常に完璧にREDOできることが前提
– もしもページが壊れたら?
●
こんなこともあろうかと Full-Page-Writes
●
Full-Page-Writes:
– Checkpoint直後は(差分でなく)ページ全体をWALに
書き込む
– PostgreSQLはデフォルトで有効
●
実例で機能を確認!
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 95
Full-Page-Writes
WAL
begin;
UPDATE ...;
commit;
同期書き込み
LSN_1
LSN_0
LSN_1
Full-Page-Writesの威力を示すため、
クリティカルなトラブルを起こしてみる
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 96
Full-Page-Writes
WAL
CHECKPOINT
開始
LSN_1
LSN_0
LSN_1
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 97
Full-Page-Writes
WAL
CHECKPOINT
実行中
OR
LSN_1
LSN_1 LSN_2
LSN_2
LSN_1 LSN_2
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 98
Full-Page-Writes
WAL
CHECKPOINT
実行中
OR
LSN_1
LSN_1 LSN_2
LSN_2
LSN_1 LSN_2
Checkpoint直後は
ページデータ全体
を書き込む
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 99
Full-Page-Writes
WAL
CHECKPOINT
実行中
OR
LSN_1
LSN_1 LSN_2
LSN_2
LSN_1 LSN_2
Checkpoint直後は
ページデータ全体
を書き込む
バックアップブロック
(BackupBlock)
と呼びます
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 100
Full-Page-Writes
WAL
CHECKPOINT
実行中
OR
LSN_1
LSN_1 LSN_2
LSN_2
LSN_1 LSN_2
OR
LSN_3
LSN_3
LSN_3
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 101
Full-Page-Writes
WAL
OR
LSN_1
LSN_1 LSN_2
LSN_2
LSN_1 LSN_2
OR
LSN_3
LSN_3
LSN_3
LSN_4
LSN_4
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 102
Full-Page-Writes
WAL
LSN_1
LSN_1 LSN_2
LSN_2
LSN_3
LSN_3 LSN_4
LSN_4
LSN_4
BackgroundWriterが
このページを....
Full-Page-Writesの威力を示すため
クリティカルなトラブルを起こしてみる
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 103
Full-Page-Writes
WAL
LSN_1 LSN_2 LSN_3 LSN_4
BackgroundWriterが
このページを
書いてる最中に
クラッシュ!!!
OS or Postgres
クラッシュ
Full-Page-Writesの威力を示すため、
クリティカルなトラブルを起こしてみる
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 104
Full-Page-Writes
WAL
LSN_1 LSN_2 LSN_3 LSN_4
BackgroundWriterが
このページを
書いてる最中に
クラッシュ!!!
OS or Postgres
クラッシュ
データ書き込み中にクラッシュ
したので、
データがおかしい orz
Full-Page-Writesの威力を示すため、
クリティカルなトラブルを起こしてみる
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 105
こんな状態でリカバリーできるの?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 106
できるんです
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 107
リカバリ
WAL
リカバリは
REDO point
から
LSN_1 LSN_2 LSN_3 LSN_4
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 108
リカバリ
WAL
リカバリは
REDO point
から
LSN_1 LSN_2 LSN_3 LSN_4
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 109
リカバリ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
バックアップブロックだから
LSNに関わらず上書きする
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 110
リカバリ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_2
データロストした
ページが直ったぞ!!!
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 111
リカバリ
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_2
データロストした
ページが直ったぞ!!!
Full-Page-Writes
スゲー
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 112
リカバリ完了
あとは、粛々とリカバリを続ける也
WAL
LSN_1 LSN_2 LSN_3 LSN_4
LSN_3 LSN_4
LSN_4
LSN_2
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 113
というわけで、
Full-Page-Writesで
(各checkpoint直後に)バックアップブロックを
書き込んでおけば
かなり頑健になる
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 114
さて、
最後のトピック
vi. オンラインバックアップについて
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 115
CHECKPOINTを実行しておけば
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 116
CHECKPOINTを実行しておけば
WALを使って
リカバリできる
(HDDが正常であれば)
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 117
CHECKPOINTを実行しておけば
HDD上に最新データがなくても
WALを使って
リカバリできる
(HDDが正常であれば)
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 118
もしかして?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 119
うまいことやれば、
オンラインバックアップ
できる?
稼働中に
データを
バックアップ
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 120
はい、できます。
稼働中に
データを
バックアップ
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 121
PostgreSQLはLockなしで
オンラインバックアップできます(論理も物理も)。
稼働中に
データを
バックアップ
論理:INSERT文のリスト, CSV, etc..
物理:ファイルそのもの
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 122
v. オンラインバックアップ
WAL
DBMSを稼働したまま
物理バックアップをつくる
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 123
オンラインバックアップ
(1) CHECKPOINTから始める
WAL
オンラインバックアップ
開始
最初に
CHECKPOINT
実行
backup_label
CHECKPOINTの情報などが書き込まれている。
後からREDOpointを知るために使う。
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 124
オンラインバックアップ
(2) テーブルファイル をCOPY
WAL
オンラインバックアップ
開始
テーブルファイルを
コピー
最初に
CHECKPOINT
実行
コピーに時間がかかっても大丈夫
backup_label
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 125
オンラインバックアップ
FILE COPY
0:00
0:00
0:00
0:00copy
実際のデータベースには
多数のテーブル(FILE)があり、巨大なものもある。
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 126
オンラインバックアップ
FILE COPY
1:00
1:00
1:00
1:00
0:00
copyに1時間
実際のデータベースには
多数のテーブル(FILE)があり、巨大なものもある。
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 127
オンラインバックアップ
FILE COPY
1:01
1:01
1:01
1:00
0:00
1:01今、copy終了
実際のデータベースには
多数のテーブル(FILE)があり、巨大なものもある。
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 128
オンラインバックアップ
FILE COPY
1:01
1:01
1:01
1:00
0:00
1:01
時間差
Snapshot
じゃないけど
OK
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 129
オンラインバックアップ
(3) COPY中もデータ操作可能
WAL
オンラインバックアップ
開始
テーブルファイルを
コピー
(backup_labelも)
最初に
CHECKPOINT
実行
コピーに時間がかかっても大丈夫
OR OR OR
backup_label
backup_label
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 130
オンラインバックアップ
(4) 最後に WALをCOPY
WAL
WAL
WALを
コピー
OR OR OR
backup_label
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 131
オンラインバックアップ
(4) 最後に WALをCOPY
WAL
WAL
WALを
コピー
OR OR OR
backup_label
注意:pg_xlog/以下のWALセグメントは短時間で消されるので、
 アーカイブログ(Archiving Logging)の設定をして
 別のディレクトリに保存し、それらもCOPYしませう
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 132
バックアップデータからDB起動
初期状態
WAL
OR OR OR
backup_label
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 133
バックアップデータからDB起動
リカバリ-フェーズ
WAL
?
OR OR OR
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 134
バックアップデータからDB起動
リカバリ-フェーズ
WAL
?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 135
バックアップデータからDB起動
リカバリ-フェーズ
WAL
?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 136
バックアップデータからDB起動
リカバリ-フェーズ
WAL
?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 137
リカバリ-フェーズ完了 → 稼働!
稼働-フェーズ
WAL
?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 138
まとめ
リカバリの原理は単純にして巧妙
WALにREDOログ(CHECKPOINT直後はページ)を書く
– もう、ジムグレイのトランザクション本:9?11章がスラスラ分かる!はず
実際に使うには
利点だけでなく、短所や限界も把握しませう
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 139
Appendix 1
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 140
今回、省略したこと
WALの書き込みタイミングは3種類
1. COMMITと同時(今回説明)
2. 大量更新でWALバッファがあふれたとき
3. 周期的にWAL writerが書き込む
変更されたページ(dirtyページ)の書き込みタイミングは3種類
1. CHECKPOINT(今回説明)
① CHECKPOINTERが周期的に実行(今回説明)
② CHECKPOINTコマンド実行時
③ WALバッファへの書き込みがcheckpoint_segmentsを超えたとき
④ pg_start_backup()関数実行時
⑤ PostgreSQL正常終了時
2. 共有メモリが一杯で、ページを入れ替えるとき
3. バックグランドライタが少しづつ書き込む
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 141
Appendix 2
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 142
1: 更新がなかったら?
WAL
これはどうなる?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 143
1: 更新がなかったら?
WAL
CHECKPOINT
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 144
2: CHECKPOINTが失敗したら?
WAL
CHECKPOINT
実行中
OS or Postgres
クラッシュ
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 145
2: CHECKPOINTが失敗したら?
一つ前のREDO pointからリカバリ
WAL
CHECKPOINT
失敗
OS or Postgres
クラッシュ
CHECKPOINT
成功
?
OROR
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 146
2: CHECKPOINTが失敗したら?
一つ前のREDO pointからリカバリ
WAL
CHECKPOINT
成功
CHECKPOINT
失敗
?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 147
2: CHECKPOINTが失敗したら?
一つ前のREDO pointからリカバリ
WAL
CHECKPOINT
成功
CHECKPOINT
失敗
?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 148
2: CHECKPOINTが失敗したら?
一つ前のREDO pointからリカバリ
WAL
CHECKPOINT
成功
CHECKPOINT
失敗
?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 149
2: CHECKPOINTが失敗したら?
一つ前のREDO pointからリカバリ
WAL
CHECKPOINT
成功
CHECKPOINT
失敗
?
2014/5/31 29回jpug_study 鈴木啓修@interdb.jp 150
2: CHECKPOINTが失敗したら?
一つ前のREDO pointからリカバリ
WAL
CHECKPOINT
成功
CHECKPOINT
失敗
?

More Related Content

笔辞蝉迟驳谤别厂蚕尝のリカバリ超入门(もしくは奥础尝、颁贬贰颁碍笔翱滨狈罢、オンラインバックアップの仕组み)