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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Ryohei KOMATSUYAMA
May 15, 2024
Programming
270
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
多重登録を防御するためのノウハウ
2024/05/15【DMM×バイセル】若手エンジニアによる学生向けTech Study Summit
Ryohei KOMATSUYAMA
May 15, 2024
Other Decks in Programming
See All in Programming
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
320
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
9
5.4k
phperだってパンチカードでコーディングしたい
o0h
PRO
0
200
wkhtmltopdfの次どうするか問題2026
willnet
2
1.8k
すこし踏み込む CancellationToken
htkym
2
1.6k
MVNOの申込からeSIM開通までをiOSアプリでつなぐ- 本人確認・MNP・通信事業者基盤をまたぐ実装
satotakeshi
0
540
Verilogで学ぶCPU自作入門.pdf
uyuki234
8
4k
【加筆修正版】Laravel のアプリケーションをどこにデプロイするか #phpcon_ehime
akase244
0
140
パズルゲームの作り方 / how to make puzzle games
kaityo256
PRO
2
270
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
480
Androidだけじゃない、DroidKaigiで広がった私の技術スタック
akkeylab
0
120
速習iPhone Duo対応
yuukiw00w
2
960
Featured
See All Featured
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
320
Heart Work Chapter 1 - Part 1
lfama
PRO
10
36k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
Code Review Best Practice
trishagee
74
20k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
260
Rebuilding a faster, lazier Slack
samanthasiow
85
9.7k
WENDY [Excerpt]
tessaabrams
14
40k
Practical Orchestrator
shlominoach
192
12k
What does AI have to do with Human Rights?
axbom
PRO
1
2.4k
Speed Design
sergeychernyshev
33
2.1k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
530
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
460
Transcript
多重登録を防御するためのノウハウ 2024/05/15 【DMM×バイセル】若手エンジニアによる学生向けTech Study Summit 小松山凌平
👓 小松山 凌平 👶 1998/09/09 生 (2021 年卒) 🏢 開発
1 部 Cosmos 基盤グループ 🧻 BE メインのエンジニア 🏀 NBA 観戦 🧌 Monster Hunter World 🙅 x.com/kmtym_dev zenn.dev/kmtym1998 2 自己紹介
多重登録をデータベースレベルで防御できると安心です API 実装の際の手札を増やしてもらいたいです (PostgreSQL を前提とした話をします) 3 今日のメッセージ
• 多重登録によるトラブル • 多重登録を防ぐためのアプローチ • まとめ 4 話すこと
• 多重登録によるトラブル • 多重登録を防ぐためのアプローチ • まとめ 5 話すこと
• とあるシステムのユーザ管理機能を例にする • ユーザが持つ情報 ◦ ユーザID ◦ 名前 ◦ メールアドレス
◦ ステータス (招待済 / 登録済 / 削除済 の 3 値をとる) • ユーザに関する制約 ◦ "招待済" "登録済" のユーザはメールアドレスが重複しない 6 説明のための例 (要件)
7 説明のための例 (テーブル定義) カラム名 カラムの型 制約 id serial PRIMARY KEY,
NOT NULL name text NOT NULL email text NOT NULL status enum NOT NULL • テーブル名: users • users.status の取り得る値は 'INVITED' / 'REGISTERED' / 'DELETED' の 3 値
8 • 招待者のダブルサブミットによって 招待済ユーザが 2 人できてしまった • 一応重複チェックはしていたつもり ◦ メールアドレスが一致
&& "削除済" でない ユーザがいるか検索 ◦ 検索して見つからなければ新規にレコード作成 • ダブルサブミットによってリクエストが 並列に処理され、ロジックをすり抜けた 多重登録によるトラブル エラーハンドリング等は省略しています
• 多重登録によるトラブル • 多重登録を防ぐためのアプローチ • まとめ 9 話すこと
10 多重登録を防ぐためのアプローチ • トランザクション分離レベルを変更する • テーブルごとロックをかける • 部分インデックスを使ってユニーク制約をつける
• トランザクション分離レベルを変更する • テーブルごとロックをかける • 部分インデックスを使ってユニーク制約をつける 11 多重登録を防ぐためのアプローチ
• 同時に複数のトランザクションが発生したときの挙動を決めるオプション • 標準 SQL で定められているものが以下の 4 つ (下に行くほど分離性が強い) ◦
リードアンコミッティド ◦ リードコミッティド (PostgreSQL のデフォルトはこれ) ◦ リピータブルリード (MySQL のデフォルトはこれ) ◦ シリアライザブル 12 トランザクション分離レベルとは・・・ PostgreSQLでの挙動
• 同時に複数のトランザクションが発生したときの挙動を決めるオプション • 標準 SQL で定められているものが以下の 4 つ (下に行くほど分離性が強い) ◦
リードアンコミッティド ◦ リードコミッティド (PostgreSQL のデフォルトはこれ) ◦ リピータブルリード (MySQL のデフォルトはこれ) ◦ シリアライザブル 13 トランザクション分離レベルとは・・・ PostgreSQLでの挙動
デフォルトの分離レベルがデータベース 単位で決まっている (変更可能) 14 トランザクション分離レベルの指定 トランザクション開始時に個別で設定も可能
シリアライザブル分離レベルは、最も厳しいトランザクションの分離性を提供します。このレベルでは トランザクションが同時にではなく、次から次へと、あたかも順に実行されているように逐次的な トランザクションの実行を全てのコミットされたトランザクションに対しエミュレートします。 PostgreSQL 15.4 文書 - 13.2 トランザクション分離 15
トランザクション分離レベル: シリアライザブル トランザクションの直列性を保証したいときに使う ※ ただし、相対的にパフォーマンスは悪くなる
16 TX開始 重複チェック ユーザ登録 コミット TX開始 重複チェック ユーザ登録 コミット 並列検出🔎
TX開始 重複チェック ユーザ登録 コミット TX開始 重複チェック ロールバック 成功 ✅ 成功 ✅ 重複検出🔎 直列なトランザクション 並列なトランザクション
17 多重登録を防ぐためのアプローチ • トランザクション分離レベルを変更する • テーブルごとロックをかける • 部分インデックスを使ってユニーク制約をつける
• 複数のトランザクションから同時に同じデータを 操作させないようにするための仕組み • トランザクション A がロックをかけているとき、 トランザクション B がロックをかけようとすると
A が解放されるまで B は待たされる • 重複チェックの前にロックをかける 18 テーブルロックとは・・・
19 別のトランザクションはロック解放を待つ TX開始 重複チェック ユーザの登録 コミット 成功 ✅ ロック 重複チェック
TX開始 ロック ロックの解放待ち 重複検出🔎 ※ 分離レベルはリードアンコミッティド・リードコミッティドを使う
20 • トランザクション分離レベルが高すぎると正しく重複チェックできない ◦ 並列して発生したトランザクションで作成されたレコードを読み取る必要がある ◦ リードアンコミッティド・リードコミッティドを使う • デッドロックに気を配る ◦
トランザクションが互いのロック解放を待つ状態となってしまい、いずれの処理も 止まってしまう状態 ◦ ロック時間の上限を設けておくなどして回避する • レコードロックでは重複登録は防げない 注意点
21 多重登録を防ぐためのアプローチ • トランザクション分離レベルを変更する • テーブルごとロックをかける • 部分インデックスを使ってユニーク制約をつける
22 部分インデックスとは・・・ 部分インデックスとは、テーブルの部分集合に構築されるインデックスです。 部分集合は、(部分イン デックスの述語と呼ばれる)条件式で定義されます。 部分インデックスには、その述語を満たすテーブ ル行のみに対するエントリが含まれます。 PostgreSQL 15.4 文書
- 11.8. 部分インデックス 普通のインデックス 部分インデックス ※ サポートがない RDBMS もある
23 部分インデックスのあるテーブルへの INSERT id status email 1 REGISTERED
[email protected]
2
REGISTERED
[email protected]
3 INVITED
[email protected]
4 INVITED
[email protected]
5 DELETED
[email protected]
id status email 1 REGISTERED
[email protected]
2 REGISTERED
[email protected]
3 INVITED
[email protected]
4 INVITED
[email protected]
5 DELETED
[email protected]
インデックスの範囲 インデックスの範囲 普通のインデックス 部分インデックス
インデックスの範囲 24 部分インデックスのあるテーブルへの INSERT id status email 1 REGISTERED
[email protected]
2 REGISTERED
[email protected]
3 INVITED
[email protected]
4 INVITED
[email protected]
5 DELETED
[email protected]
6 INVITED
[email protected]
id status email 1 REGISTERED
[email protected]
2 REGISTERED
[email protected]
3 INVITED
[email protected]
4 INVITED
[email protected]
5 DELETED
[email protected]
6 INVITED
[email protected]
インデックスの範囲 🙅 🙆 普通のインデックス 部分インデックス
25 部分インデックスのパフォーマンス (1)のグラフより、部分インデックスが定義されている条件であれば、通常のインデックスと部分イン デックスで実行速度に差がないことを確認できました。 (2)のグラフより、部分インデックスが定義されていない条件では、当然ですが通常のインデックスの 方が部分インデックスよりも高速に実行されます。 (※ B-Tree インデックスの場合) 株式会社インサイト
TECH BLOG - 部分インデックスの効果を検証(1)
26 話すこと • 多重登録によるトラブル • 多重登録を防ぐためのアプローチ • まとめ
• 忘れがちですが、多重登録はサーバ側で守れると安心です ◦ データベースレベルで防御できると堅牢になります • 重複チェックをするための方法を 3 つ紹介しました ◦ トランザクション分離レベルを上げる方法
◦ テーブルロックを使う方法 ◦ 部分インデックスを使う方法 • 同じような話を記事にしているので良ければご覧ください 27 まとめ
ありがとうございました