こわくない同時実行制御

43
こわくない同時実行制御 @Hiraku

description

ゆるかわPHP #2で話しました

Transcript of こわくない同時実行制御

Page 1: こわくない同時実行制御

こわくない同時実行制御@Hiraku

Page 2: こわくない同時実行制御

おことわり

•荒い説明なので突っ込みどころ多いと思います

•「同時実行制御って難しそうだけど面白いな♪」ぐらいになればうれしい

Page 3: こわくない同時実行制御

自己紹介

• @Hiraku (中野拓)

• PHP歴5年+

•使ったことのあるフレームワーク• Zend Framework1• Symfony• Yaf• BEAR.Sunday

• XMLとJSONの相互変換ライブラリ作ってます• https://github.com/hirak/php-XML_Builder

Page 4: こわくない同時実行制御

目次

•同時実行制御とは

•考慮するべき不具合

•解決手法

Page 5: こわくない同時実行制御

同時実行制御Concurrency Control

Page 6: こわくない同時実行制御

同時実行制御とは

•あるデータを、複数の人が同時に扱えるようにすることを考える分野

•例:共有のExcel進捗管理表

さっき僕が追記した内容が上書きされて消えちゃってる

よ!

内容を変更したよー

Page 7: こわくない同時実行制御

同時実行

制御

並列並行

プログラミング

DB

トランザクション

バージョン管理

システム

(git, svn)

Page 8: こわくない同時実行制御

同時実行制御は応用範囲が広い

•並列プログラミング

• DBトランザクション

•バージョン管理システム

•逆に、同時実行制御さえ理解しておけば、上記3つのシステムが理解しやすくなる• イモヅル式!

Page 9: こわくない同時実行制御

教科書

•先述の3つの分野では必ず同時実行制御が必要になる

•どこから勉強しても行き着く

•わたしはSQLから攻めました。いいのがあったら教えてください

• http://www.amazon.co.jp/dp/4798128023

• 資格試験の教科書なんかでも登場するかも…?

Page 10: こわくない同時実行制御

同時実行制御を理解するために

1. 何も制御しなければどんな不具合が起きるのか理解する

2. どうすれば防げるのか理解する

Page 11: こわくない同時実行制御

同時実行制御の失敗で起きる問題整理して名前を付けてくれた人がいるんです

Page 12: こわくない同時実行制御

制御しないと問題が起きる

•具体的な問題って何?• SQLモデルによる定義があります

• http://research.microsoft.com/apps/pubs/default.aspx?id=69541

• 5つに分類• P0 ダーティライト

• P1 ダーティーリード

• P2 ノンリピータブルリード(ファジーリード)

• P3 ファントム

• P4 ロストアップデート

Page 13: こわくない同時実行制御

SQL的考え方で説明します

•一連のまとまった操作=トランザクション(Tx)

•基本的に、自分のTxが変更を行っていないのに、データが勝手に変更されていると、不具合の原因になる

Page 14: こわくない同時実行制御

P0 ダーティライト

• Tx中に他のTxが書き込めちゃう状態• 正しい値が何だったのかわからなくなる

Tx1 Tx2

UPDATE x=1

UPDATE x=2

Datax=0

x=1

x=2

rollback x=??

Page 15: こわくない同時実行制御

P1 ダーティリード

• Tx中の変更が他のTxから読めちゃう状態

Tx1 Tx2

X=1

y = x + 1 (2)

DataX=0, y=0

x=1y=0

x=1y=2

rollback x=0y=??

SELECT x

Page 16: こわくない同時実行制御

P2 ノンリピータブルリード

•他のTxによってデータが勝手に書き換わっていること

Tx1 Tx2

SELECT x

x=1

Datax=0

x=0

x=1

SELECT x x=1

x=0

x=1

SELECTに再現性がない

Page 17: こわくない同時実行制御

P3 ファントム

•他のTxの操作によって謎のデータが突如出現すること• ノンリピータブルリードと対

Tx1 Tx2

SELECT x FROM Data

INSERT

Data(x=0)

(x=0)

(x=0)(x=1)

SELECT x FROM Data (x=0)(x=1)

1件hit

2件hit

SELECTに再現性がない

Page 18: こわくない同時実行制御

P4 ロストアップデート

•同時更新のうち、早かった方の更新が失われてしまう• インクリメントの制御など

Tx1 Tx2

SELECT x SELECT x

Datax=0

x=0

x=1x = x + 1

x=1

手動インクリメントの

ロスト

x=0 x=0

x = x + 1

Page 19: こわくない同時実行制御

SQLの場合

•トランザクション分離レベルで制御できます

分離レベル P0 ダーティライト

P1ダーティリード

P2アンリピータブルリード

P3ファントム

READ

UNCOMMITTED

起きない 発生する 発生する 発生する

READ

COMMITTED

起きない 起きない 発生する 発生する

REPEATABLE

READ

起きない 起きない 起きない 発生する

SERIALIZABLE 起きない 起きない 起きない 起きない

※MySQL InnoDBのデフォルトはREPEATABLE READ

Page 20: こわくない同時実行制御

対処方法色々やり方があります

Page 21: こわくない同時実行制御

基本方針

•競合が起きる条件を崩せば、問題は発生しない• 更新がある

• 複数トランザクションが同時に同じデータを更新する

•この2つの条件をいかにして崩すか。

Page 22: こわくない同時実行制御

対処方法0 書き込まない

•読み込みのみであれば、問題は一切発生しない

•何も考えなくてよい。同時に読み込んでOK

•書き込みはバッチ処理に任せるケースも

•もちろん、適用できるケースは限られる

Page 23: こわくない同時実行制御

対処方法1 同時実行しない

•同時実行を一切しなければ、これらの問題は絶対に起きない

•直列化 (Serialization) とも言う

•いったんキューに貯めて、リソースが空くのを待つ

Page 24: こわくない同時実行制御

直列化の問題

•パフォーマンスが落ちる

•スケーラビリティ皆無• 実質ひとつのプロセッサが全作業を行うのと同じ

•これでは実用にならないケースも多い…

Page 25: こわくない同時実行制御

対処方法はここから分岐します

ロックバージョン

管理

Page 26: こわくない同時実行制御

対処方法2-a ロック(Locking)

•悲観的同時実行制御とも呼ばれる

•リソースに鍵をかけて、一度に一人しか触れないようにする• 部分的に直列化

• ロックされていたら、ロックが解除されるまで待つ

•直列化は全リソースをまとめてロックするのと同じ• 適切に使えば問題を完璧に防げる

Page 27: こわくない同時実行制御

個室トイレっぽい

リソース

使用中

or

使っていいよ

使いたいプロセスはアンロック

されるまで待つ

Page 28: こわくない同時実行制御

ロックの粒度

•テーブルロック• (清掃中につきトイレ全体立ち入り禁止)

•行ロック• (個室の使用中・空きの制御)

•読み込みだけなら許可するロック

•読み込みも書き込みも許可しないロック

•大きくロックした方が安全だけど、その分パフォーマンスが劣化する

Page 29: こわくない同時実行制御

ロックの問題

•使いこなすのがむちゃくちゃ難しい• ロックのかけすぎでパフォーマンスが出ない

• アンロック忘れにより破滅

• ロックの順番• デッドロック

• 再利用性の低下

Page 30: こわくない同時実行制御

アンロック忘れ

•ロックしっぱなしにすると、永久に他のトランザクションがそのリソースを扱えなくなる• うっかりミス

• 攻撃

Page 31: こわくない同時実行制御

デッドロック

•ロックの順番を統一していないと発生

•永久にロックが取れない

• 第2回 トランザクションを知ればデータベースがわかる―「データ復旧」「同時実行制御」を行う“不完全な”しくみ(3):DBアタマアカデミー|gihyo.jp … 技術評論社

• http://gihyo.jp/dev/serial/01/db-academy/000203

Page 32: こわくない同時実行制御

ロックは地獄だぜー

•ロックは難しい

•細かく書いていくとたぶん本ができあがる

•扱うにしても、なるべく先人たちの実装を再利用しましょう• DBなら組み込みのトランザクションを使う

• ファイルならgitを使う

•参考:できる!並列・並行プログラミングhttp://www.slideshare.net/pfi/ss-9780450

Page 33: こわくない同時実行制御

対処方法2-b バージョン管理

•楽観的同時実行制御とも呼ばれる

•データにリビジョン番号を振り、改竄を検出できるようにする• データ改竄を検出したらやり直すかマージする

•ロックより簡単

•競合が多いとパフォーマンスが落ちる• リトライしまくるので、ロックより劣化する

Page 34: こわくない同時実行制御

•競合が発覚したら• リトライ

• マージ

リソース

(1) バージョンを取得しておく

(2) バージョンを取得しておく

(3) ver1をベースにして、

データを更新するよー

(4)ver1をベースにして、

データを更新するよー

Ver 1 Ver 2

元にしたデータが

古いよ!

受け入れません

Page 35: こわくない同時実行制御

バージョンの粒度

•テーブル全体のバージョン

•行のバージョン

•ロックの粒度と対比

Page 36: こわくない同時実行制御

STM (Software Transactional Memory)

•バージョン管理方式を使った並行プログラミングの手法

•更新が競合する場合は1からやり直す• 割と単純なモデル

Page 37: こわくない同時実行制御

Git, svn方式

•マージの概念をプラス

•マージもうまくできない場合、最初からやり直す

Page 38: こわくない同時実行制御

実際、同時実行制御とどう付き合っていくか理屈はわかったんだけど

Page 39: こわくない同時実行制御

なるべくなら自分で実装しない

• DBのトランザクションが使えるなら素直にそれを使う

•自前実装はイバラの道

•やるならバージョン管理方式の方がお手軽で楽

Page 40: こわくない同時実行制御

扱うデータの種類を見極める

•例) PHPのセッション• 同時に同じセッションデータを読み書きすることはほとんどない

• 同時実行が起きないので制御を考えなくていい• MemcachedとかのKVSで十分

•データの種類にあった同時実行制御を行えば、パフォーマンスが向上する

•トランザクション分離レベルを操るところからでも

Page 41: こわくない同時実行制御

RESTとトランザクション

• WebAPI作ってますか

• WebAPIで同時実行制御のことを考えていますか

•せっかくMySQLを使っているのに、オレオレWebAPI化によって同時実行制御が破綻しているケースをよく見かける

•条件付き更新に対応しておけば大丈夫

Page 42: こわくない同時実行制御

まとめ

•同時実行制御は難しいですが、色々な分野で登場します• わかると意外と役に立つかも

•我々凡人はなるべく先人たちの実装を使いましょう• Git

• DBのトランザクション

•自前実装する場合は気を付けましょう

Page 43: こわくない同時実行制御

同時実行制御こわくないよ!!