5. spanserver
(Table A)
spanserver
(Table B)
spanserver
(Table C)
Zone 1
spanserver
(Table A)
spanserver
(Table B)
spanserver
(Table C)
Zone 2
spanserver
(Table A)
spanserver
(Table B)
spanserver
(Table C)
Zone 3
replica replica
Horizontal Consistency
VerticalConsistency
Spannerのチャレンジ
● 同一 Zone の spanserver 間のデータ整合性をどう確保するか?
● Zone 間のデータ整合性をどう確保するか?
9. リードライト・トランザクションにおけるロックの利用
AさんからBさんに50円送金するトランザクション
⇒ 外部からは時刻 t2 にすべての変更がまとめて行われたように見える
A : 100
B : 200
C : 1300
A : 100
B : 200
C : 1300
A : 50
B : 200
C : 1300
共有ロック
排他ロック
Read A = 100 Read B = 200
Write A = 50
Write B = 250
トランザクション開始
この時点では何も
書き込まれない
Commit
A : 50
B : 250
C : 1300
A : 100
B : 200
C : 1300
A : 50
B : 250
C : 1300
トランザクション中に読んだデータが
勝手に書き換えられることを防止
書き換え中の中途半端な状態が
読み取られることを防止
A : 100
B : 200
C : 1300
トランザクション終了
t1 t2
t2
書き込みデータには
Commit時の
タイムスタンプを付与
10. TNX B
TNX A と TNX B が平行に走る例
⇒ TNX B は時刻 t2 以前に開始しているが、そこは関係なくて、外部からは、
TNX B の処理は時刻 t3 にすべてまとめて行われたように見える!!!!
(トランザクション中に読んだデータはすべて共有ロックで守られているので、
どの時刻に読んだと考えても同じ結果になる点に注意)
A : 100
TNX A
B : 200
C : 1300
A : 100
B : 200
C : 1300
共有ロック
排他ロック
Read A = 100 Read B = 200
Write A = 50
Write B = 250
Commit
A : 50
B : 250
C : 1300
t1 t2
A : 50
B : 250
C : 1300
Read C = 1300 Read B = 250 Write B = 350
Write C = 1200
A : 50
B : 350
C : 1200
Commit
A : 50
B : 350
C : 1200
t3
11. TNX A はデータ A を書き換える(t = t2)
TNX B はデータ B を書き換える(t = t3)
この時、さらに別のトランザクションが A と B の値を読み取ると何が見えべきか?
読み取りリクエストを発行した時刻を T として・・・
● 時刻 t1 < T < t2 ⇒ (A, B) = (100, 200)
● 時刻 t2 < T < t3 ⇒ (A, B) = (101, 200)
● 時刻 t3 < T ⇒ (A, B) = (101, 201)
内部的には、「時刻 T 以前のタイムスタンプの中で最新のタイムスタンプのデータ」を spanserver から
取り出すことでこれを実現
⇒ リードオンリー・トランザクションでは、ロックを取得する必要がない!
A : 100 A : 100 A : 101 A : 101
B : 201
A : 101
B : 201B : 200
A : 101
t2
B : 200B : 200
t2 t2
B : 200
t1 t1 t1
t1 t3t1 t1 t1 t1
14. Table A Table B
RDB without read transaction
Write 1
Write 2
Read 1
Read 2
RDB with read transaction
using read-lock mechanism
Table A Table B
Write 1
Write 2
Read 1
read lock
lock release
リードオンリー・トランザクションでもリードロックが発生する
ので性能が上がらない。
NG
15. Table A Table B
Write 1
Write 2
Read
RDB with read transaction
using MVCC (multi version concurrency control)
Write 0
Transaction ID
0
1
2
get ID
read ID=0
read ID=0
トランザクションIDを一元管理する処理がボトルネックになる
16. Table A Table B
Write 1
Write 2
Read
Spanner's approach
Use timestamp as a transaction ID
Write 0 get current time
read time=0
read time=0
Spannerでは、トランザクションIDの代わりにタイムスタンプを使用す
ることで、ボトルネックを排除
time=0
time=1
time=2
18. Truetime APIで t3 > t2 を保証する方法
https://research.google.com/archive/spanner-osdi2012.pptx
19. commit
start
Time range
t=0 t=2
Choose commit timestamp as latest possible time t2=X
Realtime
Time range
t=2 t=4
Write data at t(real) > t2 = X
t(real)=X
Truetime API
⇒ 信頼出来る時刻の範囲 (t_after, t_before) を返すAPI
commit
finish
上記の commit finish 以降、つまり、t(real) > t2 = 2 の瞬間に次のトランザクションの
commit start が発生したとすると、 t3 > t(real) > t2 が保証される
(commit start 〜 commit execute の間は、排他ロックが取得されているので、同じ行を含む他のトランザ
クションの commit start は発行されない。)
排他ロック
取得完了
20. Fluctuations of time drifts from time servers
(excerpt from the research paper)
Hardware maintenance
of two time servers
Network latency
improvement
Truetime APIの精度
Truetime APIが返す時刻 (t_after, t_before) の幅が大きいと commit 処理時の
待ち時間が長くなるので、できるだけ小さい幅で返すことが重要