web-dev-qa-db-ja.com

外部キーを使用してデータベースからエンティティを削除する方法

microserviceアーキテクチャでは、いくつかの異なるエンティティを保持するデータベースと対話するためのメソッドを持つBREAD(CRUD)サービスがあります。お互いを参照してください。また、クエリが正常に返された後、エンティティ(Add、Edit、Deleteメソッド)に変更が発生したときにメッセージブローカーを使用してメッセージを公開します。

問題

別のテーブルで参照されているデータベースのテーブルから行を削除する場合、2つのオプションしかありません。最初に参照している行を削除し、ON DELETE CASCADEオプションを使用します。私の場合、それだけでは十分ではありません。私が解決する必要がある問題は:

MQへの変更を公開する機能を維持しながら、それを参照する行を含むデータベースからエンティティを削除する方法

考慮されたソリューション

I.チャネル(それらが存在する言語)

Complexity: High

エンティティごとに双方向チャネルを作成します。スレーブエンティティがマスターエンティティのチャネルにサブスクライブすると、スレーブエンティティはチャネルにregistrationメッセージを送信し、マスターエンティティに依存するエンティティを通知します。エンティティを削除する場合は、削除することをリスナーに通知するメッセージをチャネルにプッシュします。すべてのスレーブの確認メッセージが受信されるのを待ってから、エンティティを削除します。

Create user, email, attachment channels (or a single one with filtering in each service)
Create user, email, attachment services with its master channel and channels of the parent dependency.  

(later)

Request (delete user) 
  -> publish on user channel that a user will be deleted
    -> email entity receives, send a requests in its channel that it will be deleted
      -> attachment entity receives, deletes the attachments for the email
      <- publish change to MQ and respond that the attachments are deleted
    <- publish change to MQ and respond that the emails have been deleted
    -> contact entity receives, deletes all the user contacts
    <- publish change to MQ and respond that the contacts have been deleted
  <- deletes the user, responds to a requests

II。コールバック

Complexity: Medium

エンティティが削除される前に呼び出されるコールバックを作成します。コールバックは、すべての依存エンティティで削除メソッドを呼び出します。

Create user, email, attachment services
Create user, email, attachment callbacks with references to its dependencies
Attach callback to service

(later)

Request (delete user) 
  -> run user callback
    -> email entity `Delete()` is called. run email callback
      -> attachment entity `Delete()` is called, deletes the attachments for the email
      <- publish change to MQ and return that the attachments are deleted
    <- publish change to MQ and return that the emails are deleted
    -> contact entity `Delete()` is called, deletes all the user contacts
    <- publish change to MQ and return that the contacts are deleted
  <- deletes the user, publish change to MQ and responds to a requests

III。 DBエンジン通知

Complexity: Medium

一部のデータベースエンジンには、通知を送受信するための内部チャネルがあります

Create listener on user, email, attachment DB channels (or a single channel with filtering in each service)
Create user, email, attachment services and pass the channel listener(s)

(later)

Request (delete user) 
  -> run user callback
  <- deletes the user with `CASCADE` and responds to a requests
    -> email entity listener handler is called - publish change to MQ
    -> attachment entity listener handler is called - publish change to MQ
    -> contact entity listener handler is called - publish change to MQ

該当しないソリューション

SQL CASCADE

削除カスケード(通知なし)を使用している場合、上記の例では、電子メール、添付ファイル、および連絡先エンティティのイベントを発行できなくなるため、変更をMQに送信できません。

データベースレベルで変更をストリーミングするためのソリューション(例 Debezium

いつ、どのように、どこにメッセージを送信するかを完全に制御したいのですが、厳密に必要でない場合は、サードパーティの依存関係を導入したくありません。

結論

特定の要件で削除を処理することについてのあなたの意見、および上記の解決策についてのあなたの考えを聞きたいと思います。

1
CodeBreaker

DELETEアクションとNotifyアクションは分離する必要があります。エンティティを削除する前に、削除されるすべてのエンティティを見つけて、通知をキューに入れる必要があります。これは、それらのメッセージを公開する必要があることを必ずしも意味しません。リストまたはある種のコレクションでそれらを追跡する必要があるだけです( 重複メッセージに対する保護 を忘れないでください)。

その後、削除操作を実行します。そのトランザクションをコミットしたら、通知を発行します。

削除するすべてのアイテムをクエリして発見する必要があるため、ON DELETE CASCADEは、送信する通知を収集してからINSERT操作を実行するまでの間に他のDELETEsがあった場合に最適な解決策ではない可能性があります。エンティティの削除に関するロジックを取得したら、データベースで削除するよりも、アプリケーションレイヤーからエンティティを削除する方がよいでしょう。

もちろん、{Font:Dripping blood} TRIGGERS {/ Font}と保留中の通知を保存するためのテーブルを使用してこれを実行したい場合を除き...

3
Greg Burghardt