Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

『歩いておトク』の不具合事例から学ぶトランザクションの落とし穴

571 views

Published on

DeNA TechCon 2018の登壇資料です。

Published in: Technology
  • Be the first to comment

  • Be the first to like this

『歩いておトク』の不具合事例から学ぶトランザクションの落とし穴

  1. 1. 『歩いておトク』の不具合事例から学ぶ トランザクションの落とし穴 DeNAライフサイエンス 馬場 南実
  2. 2. 自己紹介 • 馬場 南実 - 2017年 新卒入社 - DeNAライフサイエンス 所属 - 歩いておトク - iOS/Android エンジニア 2
  3. 3. 『歩いておトク』の紹介 • ドコモヘルスケア社と協業 • 計測された歩数に応じて・・・ - dポイントがもらえる! - バーチャル旅行が進む! 3
  4. 4. 『歩いておトク』の紹介 • ドコモヘルスケア社と協業 • 計測された歩数に応じて・・・ - dポイントがもらえる! - バーチャル旅行が進む! 4 『歩いておトク』で発生した 歩数データに関する不具合を通して トランザクションに関する学びを得た話
  5. 5. 利用者毎の歩数データの更新 • クライアントから定期的に歩数送信され、データベースに保存 - 保存されている歩数より大きい場合のみ、データ更新 5 5000歩 送信 10:30 更新! 0歩 5000歩 2000歩 送信 10:30 更新しない 5000歩 5000歩 5010歩 送信 10:35 更新! 5000歩 5010歩
  6. 6. 今回発生した不具合 • 連続した歩数送信時に、不適切な更新が発生してしまった • 次の歩数送信まで歩数が違う値になり、アプリ上の表示に違和感 6 5000歩 送信 10:30 更新! 0歩 5000歩 2000歩 送信 10:30 更新! 0歩 2000歩 5010歩 送信 10:35 更新! 5000歩 5010歩
  7. 7. 今回発生した不具合 • 連続した歩数送信時に、不適切な更新が発生してしまった • 次の歩数送信まで歩数が違う値になり、アプリ上の表示に違和感 7 5000歩 送信 10:30 更新! 0歩 5000歩 2000歩 送信 10:30 更新! 0歩 2000歩 5010歩 送信 10:35 更新! 5000歩 5010歩 まずは、正しく動作していた時の 実装から紹介していきます
  8. 8. 歩数更新の実装 🙆 • 今からご紹介する実装は、擬似的なコードです • クライアントから、定期的に歩数送信が行われる 8 クライアント
  9. 9. 歩数更新の実装 🙆 • その時サーバーでは、以下のような処理が行われる 9 サーバー
  10. 10. 歩数更新のデータ操作 🙆 • その時MySQLでは、以下のようなSQL文が実行される 10 MySQL
  11. 11. 複数送信時のデータ操作の流れ 🙆 11 5000歩 送信 2000歩 送信 トランザクション開始 歩数取得&ロック開始 歩数更新 ロック&トランザクション終了 0歩 5000歩 トランザクション開始 歩数取得&ロック開始 0歩 5000歩 ロック待ち 更新後の値を取得 ロック&トランザクション終了
  12. 12. 複数送信時のデータ操作の流れ 🙆 12 5000歩 送信 2000歩 送信 トランザクション開始 歩数取得&ロック開始 歩数更新 ロック&トランザクション終了 0歩 5000歩 トランザクション開始 歩数取得&ロック開始 0歩 5000歩 ロック待ち 更新後の値を取得 ロック&トランザクション終了 つづいて、不具合が発生していた時の 実装を紹介します
  13. 13. 歩数更新の実装 🙅 • 関係ないテーブルからデータを取得する、たった1行を追加 13 サーバー
  14. 14. 歩数更新のデータ操作 🙅 • トランザクション開始とロック開始の間に 一つ処理が入ってしまっている・・・ • これこそが不具合の原因!! 14 MySQL
  15. 15. 複数送信時のデータ操作の流れ 🙅 15 5000歩 送信 2000歩 送信 トランザクション開始 歩数取得&ロック開始 歩数更新 ロック&トランザクション終了 0歩 5000歩 トランザクション開始 歩数取得&ロック開始 ロック&トランザクション終了 0歩 0歩 ロック待ち メッセージ取得 メッセージ取得 歩数更新 2000歩 更新前の 歩数を 取得 不適切な更新
  16. 16. 今回ハマった落とし穴 • トランザクションの分離性 - 1つ目のSQLが実行されたタイミングで データベースの状態が切り取られる - それ以降、別のトランザクションで更新されたデータは読み込めない - データを取得するタイミングによって、結果が 変わってしまうことを防ぐため - トランザクション分離レベルによって挙動は変わる (詳しい説明は割愛) 16
  17. 17. 複数送信時のデータ操作の流れ 🙅 17 5000歩 送信 2000歩 送信 トランザクション開始 歩数取得&ロック開始 歩数更新 ロック&トランザクション終了 0歩 5000歩 トランザクション開始 歩数取得&ロック開始 ロック&トランザクション終了 0歩 0歩 ロック待ち メッセージ取得 メッセージ取得 歩数更新 2000歩 切り取り この更新は 反映されず 0歩
  18. 18. 複数送信時のデータ操作の流れ 🙅 18 5000歩 送信 2000歩 送信 トランザクション開始 歩数取得&ロック開始 歩数更新 ロック&トランザクション終了 0歩 5000歩 トランザクション開始 歩数取得&ロック開始 ロック&トランザクション終了 0歩 0歩 ロック待ち メッセージ取得 メッセージ取得 歩数更新 2000歩 切り取り この更新は 反映されず 0歩 たった一行のデータ取得により ロック機構が上手く機能しなくなった
  19. 19. 歩数更新の実装 🙆 • トランザクション開始の直後にロック開始されるように修正 19 サーバー
  20. 20. まとめ • トランザクション開始の直後にロック開始するのが無難だと思う • ここにハマらないようにする方法があれば教えて欲しい 20 『歩いておトク』で発生した 歩数データに関する不具合を通して トランザクションに関する学びを得た話

×