Upgrade to Pro — share decks privately, control downloads, hide ads and more …

デッドロックを回避するリポジトリ実装の勘所

男爵
April 16, 2023

 デッドロックを回避するリポジトリ実装の勘所

ScalaMatsuri2023の登壇資料です。

男爵

April 16, 2023
Tweet

More Decks by 男爵

Other Decks in Programming

Transcript

  1. Points of implementation of
    Repository to avoid Deadlock
    @dnskimox
    デッドロックを回避する
    リポジトリ実装の勘所

    View full-size slide

  2. HELLO!
    男爵 @dnskimox
    Dansyaku / Tanga Kenichi
    A backend developer at
    2
    自己紹介

    View full-size slide

  3. Table of Contents
    ✘ Sample of DDD like domain model
    ✘ Implementation policy of Repository
    ✘ Making persistence of Value Object
    ✘ Deadlock examples and corrections
    ✘ Points of implementation of Repository
    ✘ More fundamental solutions of deadlock
    3
    目次

    View full-size slide

  4. Preconditions of System
    ✘ RDB is Amazon Aurora (compatible with
    MySQL 5.7).
    ✘ Default storage engine is InnoDB
    ✘ Default transaction separation level is
    Repeatable Read.
    ✘ Primary keys in tables are UUID.
    4
    MySQL 5.7、InnoDB、リピータブルリード、UUID

    View full-size slide

  5. Sample Domain Model
    like DDD
    DDD風のサンプルドメインモデル

    View full-size slide

  6. CloudSign
    Salesforce
    Dashboard(SPA)
    Client Service
    MakeInvoice
    架空の請求書発行SaaS

    View full-size slide

  7. 7
    請求書、カスタムフィールド、カスタムフィールドマス
    ター

    View full-size slide

  8. 8
    請求書テーブル、カスタムフィールドテーブル、カスタム
    フィールドマスターテーブル

    View full-size slide

  9. Implementation policy
    of Repository
    リポジトリ実装の方針

    View full-size slide

  10. 10
    参考書籍:実践ドメイン駆動設計

    View full-size slide

  11. 11
    集約毎とリポジトリを一対一で用意する

    View full-size slide

  12. 12
    実装クラスはSQLを発行する機能を持ち、ロックありで集約を
    取得した場合、SELECT 〜 FOR UPDATE文を発行

    View full-size slide

  13. Making persistence
    of Value Object
    値オブジェクトの永続化について

    View full-size slide

  14. 14
    参考書籍:エンタープライズアプリケーションアーキテク
    チャパターン

    View full-size slide

  15. 15
    依存オブジェクトは唯一つの親を持つ
    親以外からの参照は存在しない
    - A dependent must have exactly one
    owner.
    - There must be no references from
    any object other than the owner to
    the dependent
    Dependent Mapping

    View full-size slide

  16. Update logic for custom fields is very simple
    16
    DELETE FROM custom_fields where invoice_id = X;
    INSERT INTO custom_fields (id, invoice_id, …) VALUES (uuid(), X, …);
    INSERT INTO custom_fields (id, invoice_id, …) VALUES (uuid(), X, …);
    値オブジェクトの更新は非常にシンプル

    View full-size slide

  17. Why that sql is effectively update value objects?
    ✘ Value Object don't have an identity.
    ✘ A permanent Value Object necessarily
    depends on one parent entity.
    ✘ Value Object is immutable.
    17
    なぜこのSQLが効果的に働くのか?

    View full-size slide

  18. Deadlock examples and
    corrections
    デッドロックの実例と修正方法

    View full-size slide

  19. 1. Illegal aggregate boundary
    about table reference
    テーブル参照における集約の境界違反

    View full-size slide

  20. 20
    ロックの競合が発生しやすいクエリ
    TX1 > SELECT * FROM invoices iv
    JOIN custom_field cf ON cf.invoice_id = iv.id
    JOIN custom_field_master cfm ON cf.master_id = cfm.id
    WHERE iv.id = X FOR UPDATE;
    TX2 > SELECT * FROM invoices iv
    JOIN custom_field cf ON cf.invoice_id = iv.id
    JOIN custom_field_master cfm ON cf.master_id = cfm.id
    WHERE iv.id = Y FOR UPDATE;
    TX2 > (Waiting for lock granted …)

    View full-size slide

  21. 21
    ドメインモデルを再確認

    View full-size slide

  22. 22
    custom_field_mastersの値を共有しているzuzu a

    View full-size slide

  23. 23
    custom_fields側に値を非正規化する

    View full-size slide

  24. 24
    ロックの競合が発生しづらいクエリ
    TX1 > select * from invoices iv
    join custom_field cf on cf.invoice_id = iv.id
    where iv.id = X fo update;
    TX2 > select * from invoices iv
    join custom_field cf on cf.invoice_id = iv.id
    where iv.id = Y fo update;
    TX2 > (Query returns immediately)

    View full-size slide

  25. Correction
    Don`t select tables belonging to aggregate to
    recreate an aggregate.
    Select tables belonging to an aggregate itself
    only.
    25
    集約の再構築には、自身に所属するテーブルだけを使う

    View full-size slide

  26. 2. Gaplock problem on
    DELETE/INSERT approach
    DELETE/INSERT方式におけるギャップロックの問題

    View full-size slide

  27. 27
    デッドロックの発生しやすいクエリ
    TX1 > select * from custom_fields where invoice_id = X for update;
    TX1 > delete from custom_fields where invoice_id = X;
    TX1 > insert into custom_fields values (uuid(), X, …);
    TX1 > (Waiting for lock granted …)
    TX2 > select * from custom_fields where invoice_id = Y for update;
    TX2 > delete from custom_fields where invoice_id = Y;
    TX2 > insert into custom_fields values (uuid(), Y, …);
    TX2 > Deadlock Detected!

    View full-size slide

  28. 28
    クラス図(修正前)zuzu a

    View full-size slide

  29. 29
    クラス図(修正後)zuzu

    View full-size slide

  30. Correction
    Mix in many objects into aggregate in spite of
    difference of its life cycle
    Extract value object having its own life cycle
    from aggregate as a new aggregate.
    30
    独自のライフサイクルを持つ値オブジェクトを、新たな集
    約として抽出する

    View full-size slide

  31. 3. Other complicated
    deadlock problems
    その他の込み入った問題たち

    View full-size slide

  32. Correction
    Issue a query only one time and raise a
    deadlock alert to engineers.
    Retry queries having deadlock lisk
    automatically.
    32
    ロックが競合する可能性のあるクエリは、自動的にリトラ
    イする

    View full-size slide

  33. Points of implementation
    of Repository
    リポジトリ実装の勘所

    View full-size slide

  34. Points of implementation of Repository
    ✘ Don’t share a database row with another
    aggregate.
    ✘ If another lifecycle is detected extract a new
    aggregate.
    ✘ Retry failed transaction for deadlock.
    34
    リポジトリ実装の勘所

    View full-size slide

  35. More fundamental solutions
    of deadlock
    より根本的なデッドロック対策

    View full-size slide

  36. More fundamental solutions of deadlock
    ✘ Consider to change transaction separation
    level.
    Do you really need that level of integrity?
    Think about boundary of aggregate.
    36
    トランザクション分離レベルの変更を検討する

    View full-size slide

  37. THANKS!
    Any questions?
    You can find me at
    ✘  @dnxkimox
    ✘ https:/
    /dnskimox.hateblo.jp
    ✘ https:/
    /note.com/dnskimo
    37
    ご清聴ありがとうございました!

    View full-size slide

  38. Reference documents
    ✘ Implementing Domain-Driven Design
    ✘ Patterns of Enterprise Application
    Architecture
    38
    参考文献

    View full-size slide