Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
並行性の問題を防げ!実践トランザクション入門
Search
Shoichi Ochi
October 02, 2026
Technology
72
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
並行性の問題を防げ!実践トランザクション入門
PHPカンファレンス愛媛 2026 登壇資料
Shoichi Ochi
October 02, 2026
More Decks by Shoichi Ochi
See All by Shoichi Ochi
ノイジーネイバー問題を解決する 公平なキューイング
occhi
0
230
高速化&コスト半減!? GitHub Actionsの サードパーティマネージドランナーの比較
occhi
1
880
HTTPじゃ遅すぎる! SwitchBotを自作ハブで動かして学ぶBLE通信
occhi
0
2.3k
Other Decks in Technology
See All in Technology
Execution in the Kingdom of Agents: Reflections on Abstraction and Complexity
bcantrill
0
600
OpenClawでAzure DevOpsのWiki更新を自動化する - クラウドAIだけでは届かない場所へ
yutakaosada
0
140
Snowflake Horizon Catalog と Apache Iceberg で作る オープンなデータ基盤
kitagawaz
0
360
Oracle Cloud Infrastructure(OCI):Onboarding Session(はじめてのOCI/Oracle Supportご利⽤ガイド)
oracle4engineer
PRO
3
21k
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
16
120k
AI駆動開発で仕様はどこまで書くべきか? ― 人とAIの責務境界から考える開発プロセスの実践
takahiromatsui
1
270
顧客の成果創出とプロダクトの成長を 両立するためのFDE
sansantech
PRO
0
570
生成AIを使って「人が」考える技術 ― AI時代の人機共想と実践ノウハウ|UNITT AC2026
ishiirikie
0
500
Lambda MicroVMsは常駐サーバーの代わりに なるか? Kiro Crew を動かして検証してみた / Kiro Crew on Lambda MicroVMs
k_adachi_01
2
340
[2026-09-30]ロックンロールは鳴り止まないっ - 信頼性かまってちゃん - 「データ駆動を投げ捨ててまで。」追いかける信頼性改善に向けた取り組みの話
tosite
0
130
私の推しは「聞いてから進む」AIです -AI-DLCに一人でアプリを作らせた話
yama3133
0
150
認知負荷を吸収し、プロダクトをまたぐPR Preview基盤の設計事例
taiki45
2
560
Featured
See All Featured
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
530
Git: the NoSQL Database
bkeepers
PRO
432
67k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
300
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
68
58k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
890
Tell your own story through comics
letsgokoyo
1
1.1k
Ten Tips & Tricks for a 🌱 transition
stuffmc
1
240
Navigating Weather and Climate Data
rabernat
0
540
GitHub's CSS Performance
jonrohan
1033
470k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
960
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
Transcript
並行性の問題を防げ! 実践トランザクション入門 Shoichi Ochi (@occhi) PHPカンファレンス愛媛2026 2026-10-03
自己紹介 おち しょういち 越智 翔一 SmartBank, Inc. Software Engineer 出身:
愛媛県西条市 趣味: 筋トレ @ochi11181101 @sho-work 2
3
トランザクション 4
Introduction 「トランザクション」 複数の読み書きを、 1つの論理的な処理単位と して扱う仕組み。 トランザクション中のすべての読み書きは、 1つ の処理単位として扱われ、オールオアナッシン グの保証を提供してくれる。 つまり、すべて成功するか(
commit)、すべて なかった(rollback)ことにするかしかない。 5
Introduction 「トランザクション」 複数の読み書きを、 1つの論理的な処理単位と して扱う仕組み。 トランザクション中のすべての読み書きは、 1つ の処理単位として扱われ、オールオアナッシン グの保証を提供してくれる。 複数のクエリを、
BEGIN ~ COMMITで囲む つまり、すべて成功するか( commit)、すべて なかった(rollback)ことにするかしかない。 6
今回はそんなトランザクションが、 複数実行された時に起こる問題の話 7
では、実際にどんな問題が起こる?🤔 8
簡単な例を見てみよう!💪💪 9
Introduction 並行性の問題の簡単な例 カウンタの同一レコード更新をしようとする 2つのトランザクションを考える * https://www.oreilly.co.jp/books/9784873118703/ 10
Introduction 並行性の問題の簡単な例 カウンタの同一レコード更新をしようとする 2つのトランザクションを考える BEGIN * https://www.oreilly.co.jp/books/9784873118703/ COMMIT 11
Introduction 並行性の問題の簡単な例 カウンタの同一レコード更新をしようとする 2つのトランザクションを考える BEGIN * https://www.oreilly.co.jp/books/9784873118703/ COMMIT 12
Introduction 並行性の問題の簡単な例 カウンタの同一レコード更新をしようとする 2つのトランザクションを考える Tx A Tx B * https://www.oreilly.co.jp/books/9784873118703/
13
Introduction 並行性の問題の簡単な例 どちらのユーザーも現在のカウンタ +1したい よって、以下のようになっていて欲しい ・ユーザー 1のCOMMIT直後には 43 ・ユーザー 2のCOMMIT直後には
44 * https://www.oreilly.co.jp/books/9784873118703/ 14
Introduction 並行性の問題の簡単な例 1. Tx Aが現在のカウンタを読む( =42) * https://www.oreilly.co.jp/books/9784873118703/ 15
Introduction 並行性の問題の簡単な例 1. Tx Aが現在のカウンタを読む(=42) 2. Tx Bが現在のカウンタを読む( =42) *
https://www.oreilly.co.jp/books/9784873118703/ 16
Introduction 並行性の問題の簡単な例 1. Tx Aが現在のカウンタを読む(=42) 3. カウンタを 42+1し、43でUPDATE 2. Tx
Bが現在のカウンタを読む(=42) * https://www.oreilly.co.jp/books/9784873118703/ 17
Introduction 並行性の問題の簡単な例 1. Tx Aが現在のカウンタを読む(=42) 3. カウンタを42+1し、43でUPDATE 2. Tx Bが現在のカウンタを読む(=42)
* https://www.oreilly.co.jp/books/9784873118703/ 4. カウンタを 42+1し、43でUPDATE 18
Introduction 並行性の問題の簡単な例 最終結果が 44ではなく、 43になってしまった! 😭 3. カウンタを42+1し、43でUPDATE 4. カウンタを
42+1し、43でUPDATE * https://www.oreilly.co.jp/books/9784873118703/ 19
むむむ・・・🤔 2020
どうやって防げばいいんやろか?🤔 2121
今日のトーク 22
今日紹介するトランザクション分離レベルとレース条件 23
今日紹介するトランザクション分離レベルとレース条件 24
今日のトーク 25
1. トランザクション分離レベル 26
トランザクション分離レベル
トランザクション分離レベル 28
分離レベルは「他のTxの変更が、いつから見えるか」の設定 29
他の Tx の変更が見え始めるタイミングは、分離レベルで違う 30
他の Tx の変更が見え始めるタイミングは、分離レベルで違う 31
他の Tx の変更が見え始めるタイミングは、分離レベルで違う 32
トランザクション分離レベル 33
Serializableの実現方法は 3 つある 34
Serializableの実現方法は 3 つあり、どれも見え方が異なる 35
完全な順次実行:そもそも同時に走らせない 36
完全な順次実行:そもそも同時に走らせない 37
Serializableの実現方法は 3 つあり、どれも見え方が異なる 38
ロックには、共有ロックと排他ロックがある 39
2PL:ロックを取って、競合する読み書きを待たせる 40
2PL:ロックを取って、競合する読み書きを待たせる 41
2PL:ロックを取って、競合する読み書きを待たせる 42
2PL:ロックを取って、競合する読み書きを待たせる 43
2PL:ロックを取って、競合する読み書きを待たせる 44
Serializableの実現方法は 3 つあり、どれも見え方が異なる 45
SSI(直列化可能なスナップショット分離):スナップショットから更新されていたらロールバックさせる 46
SSI(直列化可能なスナップショット分離):スナップショットから更新されていたらロールバックさせる 47
SSI(直列化可能なスナップショット分離):スナップショットから更新されていたらロールバックさせる 48
SSI(直列化可能なスナップショット分離):スナップショットから更新されていたらロールバックさせる 49
SSI(直列化可能なスナップショット分離):スナップショットから更新されていたらロールバックさせる 50
今日のトーク 51
2. 並行性の問題 52
並行性の問題の全体像 53
問題ごとに「どのレベルから防げるか」を表に埋めていく 54
同じ 1 行を、並行して読み書きする場合に起こる問題 55
ここからしばらくは、accounts テーブルで考える 56
Dirty Write:未コミットの値を、別のTxが上書きしてしまう 57
Dirty Write:未コミットの値を、別のTxが上書きしてしまう 58
Dirty Write:未コミットの値を、別のTxが上書きしてしまう 59
Dirty Write:未コミットの値を、別のTxが上書きしてしまう 60
Dirty Write:未コミットの値を、別のTxが上書きしてしまう 61
Dirty Write は、どの分離レベルでも防がれる 62
Dirty Write の防ぎ方:書き込む行のロックを COMMIT まで持つ 63
Dirty Read:未コミットの値を読んでしまう 64
Dirty Read:未コミットの値を読んでしまう 65
Dirty Read:未コミットの値を読んでしまう 66
Dirty Read:未コミットの値を読んでしまう 67
Dirty Read:未コミットの値を読んでしまう 68
Dirty Read は Read Uncommitted で起き、Read Committed 以上で防げる 69
Lost Update:古い値を前提に上書きして、更新が消える 70
Lost Update は Snapshot Isolation 以下で起きうる(DB による) https://www.postgresql.org/docs/current/transaction-iso.html 71
複数の行にまたがる整合性が崩れる問題 72
Read Skew:1つのTx内で、異なる時点のコミット済みデータを読んでしまう 73
Read Skew:1つのTx内で、異なる時点のコミット済みデータを読んでしまう 74
Read Skew:1つのTx内で、異なる時点のコミット済みデータを読んでしまう 75
Read Skew:1つのTx内で、異なる時点のコミット済みデータを読んでしまう 76
Read Skew:1つのTx内で、異なる時点のコミット済みデータを読んでしまう 77
Read Skew:1つのTx内で、異なる時点のコミット済みデータを読んでしまう 78
Read Skew は Read Committed 以下で起き、Snapshot Isolation 以上で防げる 79 79
ここからは budgets テーブルで考える 80
部署の予算:どちらも「あと 20 使える」と判断して、合計が上限を超える 81
部署の予算:どちらも「あと 20 使える」と判断して、合計が上限を超える 82
部署の予算:どちらも「あと 20 使える」と判断して、合計が上限を超える 83
部署の予算:どちらも「あと 20 使える」と判断して、合計が上限を超える 84
部署の予算:どちらも「あと 20 使える」と判断して、合計が上限を超える 85
部署の予算:どちらも「あと 20 使える」と判断して、合計が上限を超える 86
更新は消えていない。壊れたのは「読んだ前提」 87
Write Skew は「Observe → Decide → Mutate」の流れで起きる 88
Write Skew は「Observe → Decide → Mutate」の流れで起きる 89
Write Skew は「Observe → Decide → Mutate」の流れで起きる 90
2 つの Tx が同じ古い前提を観測すると、組み合わせた結果として不変条件が壊れる 91
同じ形の問題は、身近にいくつもある 92
会議室予約は bookings テーブルで考える 93
会議室予約:どちらも「重なる予約は 0 件」を見て、同じ時間に予約を入れる 94
会議室予約:どちらも「重なる予約は 0 件」を見て、同じ時間に予約を入れる 95
会議室予約:どちらも「重なる予約は 0 件」を見て、同じ時間に予約を入れる 96
会議室予約:どちらも「重なる予約は 0 件」を見て、同じ時間に予約を入れる 97
会議室予約:どちらも「重なる予約は 0 件」を見て、同じ時間に予約を入れる 98
Write Skew のうち、ロックすべき行がまだ存在しないケース 99
Write Skew は Serializable だけが防ぐ 100
デフォルトの分離レベルでは、どのような問題が起こる? 101
今日のトーク 102
3. 並行性の問題を防ぐトランザクション設計手段 103
デフォルトの分離レベルで残る問題に、自分で対処する 104
Read Skew の対策:一貫したスナップショットで読むか、読む行を変更させない 105
Lost Update の対策:アトミックな更新・悲観ロック・楽観ロック 106
Write Skew の対策:ロックすべき行があるか、まだないか 107
Write Skew の対策:ロックすべき行があるか、まだないか 108
Write Skew の対策:ロックすべき行があるか、まだないか 109
Write Skew の対策:ロックすべき行があるか、まだないか 110
Write Skew の対策:ロックすべき行があるか、まだないか 111
部署の予算は、前提にした行を FOR UPDATE でロックすれば防げる 112
部署の予算は、前提にした行を FOR UPDATE でロックすれば防げる 113
部署の予算は、前提にした行を FOR UPDATE でロックすれば防げる 114
部署の予算は、前提にした行を FOR UPDATE でロックすれば防げる 115
部署の予算は、前提にした行を FOR UPDATE でロックすれば防げる 116
Write Skew の対策:ロックすべき行があるか、まだないか 117
ユーザー名の登録は users テーブルで考える 118
対策①:制約で書けるなら、DB に任せる(ユーザー名の UNIQUE) 119
対策①:制約で書けるなら、DB に任せる(ユーザー名の UNIQUE) 120
対策①:制約で書けるなら、DB に任せる(ユーザー名の UNIQUE) 121
対策①:制約で書けるなら、DB に任せる(ユーザー名の UNIQUE) 122
ロックするテーブルが存在しない例 123
ロックするテーブルが存在しない例 124
ロックするテーブルが存在しない例 125
ロックするテーブルが存在しない例 126
ロックするテーブルが存在しない例 127
対策④:「ない」を、ロックできる行に置き換える(競合の実体化) 128
対策④:「ない」を、ロックできる行に置き換える(競合の実体化) 129
対策④:「ない」を、ロックできる行に置き換える(競合の実体化)
対策④:「ない」を、ロックできる行に置き換える(競合の実体化) 131
対策④:「ない」を、ロックできる行に置き換える(競合の実体化) 132
実体化の対象は、例ごとに「必ずある行」を選ぶ 133
Write Skew の対策は、悲観ロック → Serializable → 競合の実体化 の順に検討する 134
今日のトーク 135
4. デッドロックとその対策 136
デッドロック:お互いが相手のロックを待ち続けて、どちらも進めない 137
デッドロックが起きるメカニズム:2 つの Tx が逆の順番で行をロックする 138
デッドロックが起きるメカニズム:2 つの Tx が逆の順番で行をロックする 139
デッドロックが起きるメカニズム:2 つの Tx が逆の順番で行をロックする 140
デッドロックが起きるメカニズム:2 つの Tx が逆の順番で行をロックする 141
デッドロックが起きるメカニズム:2 つの Tx が逆の順番で行をロックする 142
デッドロックが起きるメカニズム:2 つの Tx が逆の順番で行をロックする 143
デッドロックは「起きにくくする」と「回復可能にする」の両方を設計する 144
回避①:ロックを取る順番をそろえる 145
回避①:ロックを取る順番をそろえる 146
回避①:ロックを取る順番をそろえる 147
回避①:ロックを取る順番をそろえる 148
回避①:ロックを取る順番をそろえる 149
回避①:ロックを取る順番をそろえる 150
回避②:Tx を短く保ち、ロックを持つ時間を減らす 151
回避③:インデックスで、ロックする行を絞る 152
回復:DB がデッドロックを検出した際の挙動 153
回復:失敗した Tx は、BEGIN から全体をリトライする 154
回復:PHP(PDO)でリトライを書いた例 155
まとめ 156
並行性の問題が起こるトランザクションを設計する際の思考順序 157
並行性の問題が起こるトランザクションを設計する際の思考順序 158
並行性の問題が起こるトランザクションを設計する際の思考順序 159
並行性の問題が起こるトランザクションを設計する際の思考順序 160
並行性の問題を防げ! 実践トランザクション入門 Shoichi Ochi (@occhi) PHPカンファレンス愛媛2026 2026-10-03
Appendix - 参考資料 • • • • • • •
• • Designing Data-Intensive Applications(Martin Kleppmann, O'Reilly, 2017) ◦ https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/ データ指向アプリケーションデザイン(オライリー・ジャパン , 2019) ◦ https://www.oreilly.co.jp/books/9784873118703/ PostgreSQL: Transaction Isolation ◦ https://www.postgresql.org/docs/current/transaction-iso.html PostgreSQL: Explicit Locking ◦ https://www.postgresql.org/docs/current/explicit-locking.html PostgreSQL: Serialization Failure Handling ◦ https://www.postgresql.org/docs/current/mvcc-serialization-failure-handling.html MySQL 8.4: Transaction Isolation Levels ◦ https://dev.mysql.com/doc/refman/8.4/en/innodb-transaction-isolation-levels.html MySQL 8.4: InnoDB Locking ◦ https://dev.mysql.com/doc/refman/8.4/en/innodb-locking.html MySQL 8.4: Locking Reads ◦ https://dev.mysql.com/doc/refman/8.4/en/innodb-locking-reads.html MySQL 8.4: Deadlocks in InnoDB ◦ https://dev.mysql.com/doc/refman/8.4/en/innodb-deadlocks.html 162