SlideShare una empresa de Scribd logo
1 de 19
Descargar para leer sin conexión
なかったらINSERTしたい
し、あるならロック取りたい
やん?
第2回 DevOps勉強会
ichirin2501
1
似たネタで乗っかることにしました
2
想定する状況(MySQL)
• ユーザーアクションでINSERTしたいんだよね
• 既にデータがあるなら排他制御しつつ参照して

処理したいんだよね
=> 罠がある(InnoDB, REPEATABLE-READ)
なぜだめなのか、に焦点をあてて話したいと思います
用意したコードはてきとーなので注意
3
よくある1
$dbh->do( BEGIN );
$row = $dbh->do( SELECT FOR UPDATE );
if (! $row) {
$dbh->do( INSERT );
}
4
だめな理由
• 空打ちロックはギャップロックになる
• ギャップロックされた空間のINSERTは

全てブロックされる
• そしてギャップロック同士はブロックされない
5
ギャップロックって?
インデックスの 間をロックすること
5
6
10
id (pk)
[-inf, 5)
[7, 10)
[11, +inf]
6
ギャップロックされた

空間のINSERTは止まる
5
6
10
id (pk)
tx A tx B
SELECT * FROM t 

WHERE id = 4 FOR UPDATE
BEGIN BEGIN
INSERT INTO t (id)
VALUES (1);
ブロックされる
id=2,3,4も同様にブロック

id=7とかはブロックされない
7
ギャップロック同士は

ブロックしない
5
6
10
id (pk)
tx A tx B
SELECT * FROM t 

WHERE id = 4 FOR UPDATE
BEGIN BEGIN
SELECT * FROM t 

WHERE id = 3 FOR UPDATE
INSERT INTO t (id) VALUES(4)
INSERT INTO t (id) VALUES(3)
同じギャップ空間だけど止まらない
Deadlock Error
8
ちなみに
5
6
10
id (pk)
tx A tx B
BEGIN BEGIN
INSERT INTO t (id) VALUES(4)
INSERT INTO t (id) VALUES(3)
これはデッドロックにならない
9
よくある2 - とりあえず挿入
$dbh->do( BEGIN );
$row;
try {
$dbh->do( INSERT );
} catch {
$row = $dbh->do( SELECT FOR UPDATE );
};
10
だめな理由
• INSERTでDuplicate-Entryになったら、

共有ロックになる
• 共有 -> 排他ロックはデッドロックの原因となり、

Dup -> FOR-UPDATEの 間に刺さる
• Dupでもロックを取るので大量発行してると

ロック待ちで詰む
11
共有 -> 排他ロック
5
6
10
id (pk)
tx A tx B
SELECT * FROM t 

WHERE id = 5 FOR UPDATE
BEGIN BEGIN
INSERT INTO t (id) VALUES (5)
SELECT * FROM t 

WHERE id = 5 FOR UPDATE
Deadlock Error
Err: Duplicate Entry…
12
だったらIGNORE?
$dbh->do( BEGIN );
$res = $dbh->do( INSERT IGNORE );
if (!$res) {
$row = $dbh->do( SELECT FOR UPDATE );
};
マサカリ投げていく所存
無視しても共有ロックは取られる
13
よくある3 - ロックなし参照
$dbh->do( BEGIN );
$row = $dbh->do( SELECT );
if (! $row) {
$dbh->do( INSERT );
} else {
$row = $dbh->do( SELECT FOR UPDATE );
}
14
あまりよくない理由
• SELECTからINSERTまでの 間でDuplicateEntry
• 最初のSELECT文で全体のスナップショットが取ら
れるため、排他制御としては不十分な状態になる
15
面倒だけど無難な解決案
• Duplicate-EntryになったらRollbackして

リトライする
16
バッドノウハウのご紹介
$dbh->do( BEGIN );
$dbh->do( INSERT ON DUPLICATE KEY UPDATE );
$row = $dbh->do( SELECT FOR UPDATE );
ON DUPLICATE KEY UPDATEで
無意味な更新をするのがミソ

(name = name みたいな
17
解決されること
• INSERTでもUPDATEでも排他ロックになるため、

共有 -> 排他ロックのデッドロックが発生しない
• トランザクション開始直後に打てばスナップショッ
トによるバグ埋め込みが発生しない
18
そんな感じで、

ロックと仲良くしよう!
19

Más contenido relacionado

La actualidad más candente

La actualidad más candente (20)

SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
 
エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織
 
やはりお前らのMVCは間違っている
やはりお前らのMVCは間違っているやはりお前らのMVCは間違っている
やはりお前らのMVCは間違っている
 
外部キー制約に伴うロックの小話
外部キー制約に伴うロックの小話外部キー制約に伴うロックの小話
外部キー制約に伴うロックの小話
 
ふつうのRailsアプリケーション開発
ふつうのRailsアプリケーション開発ふつうのRailsアプリケーション開発
ふつうのRailsアプリケーション開発
 
深い親子関係のテーブル設計
深い親子関係のテーブル設計深い親子関係のテーブル設計
深い親子関係のテーブル設計
 
トランザクションの設計と進化
トランザクションの設計と進化トランザクションの設計と進化
トランザクションの設計と進化
 
強いて言えば「集約どう実装するのかな、を考える」な話
強いて言えば「集約どう実装するのかな、を考える」な話強いて言えば「集約どう実装するのかな、を考える」な話
強いて言えば「集約どう実装するのかな、を考える」な話
 
マルチテナントのアプリケーション実装〜実践編〜
マルチテナントのアプリケーション実装〜実践編〜マルチテナントのアプリケーション実装〜実践編〜
マルチテナントのアプリケーション実装〜実践編〜
 
イミュータブルデータモデルの極意
イミュータブルデータモデルの極意イミュータブルデータモデルの極意
イミュータブルデータモデルの極意
 
さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)
 
初心者向けMongoDBのキホン!
初心者向けMongoDBのキホン!初心者向けMongoDBのキホン!
初心者向けMongoDBのキホン!
 
TLS, HTTP/2演習
TLS, HTTP/2演習TLS, HTTP/2演習
TLS, HTTP/2演習
 
マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!
 
やってはいけない空振りDelete
やってはいけない空振りDeleteやってはいけない空振りDelete
やってはいけない空振りDelete
 

Similar a なかったらINSERTしたいし、あるならロック取りたいやん?

PerlとSQLのいろいろ
PerlとSQLのいろいろPerlとSQLのいろいろ
PerlとSQLのいろいろ
Takuya Tsuchida
 
Glass fishで作ったアプリをweblogicに移植してみた
Glass fishで作ったアプリをweblogicに移植してみたGlass fishで作ったアプリをweblogicに移植してみた
Glass fishで作ったアプリをweblogicに移植してみた
Satoshi Kubo
 
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
Yoshiyuki Asaba
 
[OLD/STALE] Redis cluster (japanese)
[OLD/STALE] Redis cluster (japanese)[OLD/STALE] Redis cluster (japanese)
[OLD/STALE] Redis cluster (japanese)
Shunichi Shinohara
 
20130611 java concurrencyinpracticech7
20130611 java concurrencyinpracticech720130611 java concurrencyinpracticech7
20130611 java concurrencyinpracticech7
Toshiaki Toyama
 

Similar a なかったらINSERTしたいし、あるならロック取りたいやん? (20)

PerlとSQLのいろいろ
PerlとSQLのいろいろPerlとSQLのいろいろ
PerlとSQLのいろいろ
 
Wtm
WtmWtm
Wtm
 
大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック
大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック
大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック
 
SmartNews TechNight Vol5 : SmartNews AdServer 解体新書 / ポストモーテム
SmartNews TechNight Vol5 : SmartNews AdServer 解体新書 / ポストモーテムSmartNews TechNight Vol5 : SmartNews AdServer 解体新書 / ポストモーテム
SmartNews TechNight Vol5 : SmartNews AdServer 解体新書 / ポストモーテム
 
Glass fishで作ったアプリをweblogicに移植してみた
Glass fishで作ったアプリをweblogicに移植してみたGlass fishで作ったアプリをweblogicに移植してみた
Glass fishで作ったアプリをweblogicに移植してみた
 
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
位置情報を使ったサービス「スマポ」をPostgreSQLで作ってみた db tech showcase 2013 Tokyo
 
SQL Server のロック概要
SQL Server のロック概要SQL Server のロック概要
SQL Server のロック概要
 
使ってみた!ioMemoryで実現する噂のAtomic write!
使ってみた!ioMemoryで実現する噂のAtomic write!使ってみた!ioMemoryで実現する噂のAtomic write!
使ってみた!ioMemoryで実現する噂のAtomic write!
 
[OLD/STALE] Redis cluster (japanese)
[OLD/STALE] Redis cluster (japanese)[OLD/STALE] Redis cluster (japanese)
[OLD/STALE] Redis cluster (japanese)
 
What is doobie? - database access for scala -
What is doobie? - database access for scala -What is doobie? - database access for scala -
What is doobie? - database access for scala -
 
スレッドダンプの読み方
スレッドダンプの読み方スレッドダンプの読み方
スレッドダンプの読み方
 
MySQLトラブル解析入門
MySQLトラブル解析入門MySQLトラブル解析入門
MySQLトラブル解析入門
 
20100717tobesetu
20100717tobesetu20100717tobesetu
20100717tobesetu
 
20130611 java concurrencyinpracticech7
20130611 java concurrencyinpracticech720130611 java concurrencyinpracticech7
20130611 java concurrencyinpracticech7
 
MySQL at Yahoo! JAPAN #dbts2018
MySQL at Yahoo! JAPAN #dbts2018MySQL at Yahoo! JAPAN #dbts2018
MySQL at Yahoo! JAPAN #dbts2018
 
EmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とEmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤と
 
EmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とEmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤と
 
Gorinphp0729
Gorinphp0729Gorinphp0729
Gorinphp0729
 
Gorinphp0729
Gorinphp0729Gorinphp0729
Gorinphp0729
 
MySQL Cluster 7.4で楽しむスケールアウト @DB Tech Showcase 2015/06
MySQL Cluster 7.4で楽しむスケールアウト @DB Tech Showcase 2015/06MySQL Cluster 7.4で楽しむスケールアウト @DB Tech Showcase 2015/06
MySQL Cluster 7.4で楽しむスケールアウト @DB Tech Showcase 2015/06
 

なかったらINSERTしたいし、あるならロック取りたいやん?