web-dev-qa-db-ja.com

データベースレコードの物理削除対論理削除/ソフト削除

レコードを実際にまたは物理的に削除するのではなく、レコードを論理的/ソフト的に削除する(つまり、レコードが削除されたことを示すフラグを設定する)利点は何ですか?

これは一般的な習慣ですか?

これは安全ですか?

102
user21826

利点は、履歴を保持し(監査に適している)、削除する行を参照するデータベース内の他のさまざまなテーブルを介して削除をカスケードすることを心配する必要がないことです。欠点は、フラグを考慮するためにレポート/表示メソッドをコーディングする必要があることです。

それが一般的な慣習である限り-私はイエスと言うでしょうが、あなたがそれを使用するかどうかは何でもそうですが、あなたのビジネスニーズに依存します。

編集:別の欠点の考え-テーブルに一意のインデックスがある場合、削除されたレコードはまだ「1」レコードを占有するため、その可能性もコーディングする必要があります(たとえば、一意のインデックスを持つユーザーテーブルユーザー名;削除されたレコードは、新しいレコードの削除されたユーザーのユーザー名をブロックします。これを回避するには、GUID=削除されたユーザー名列に追加できますが、推奨されません。おそらく、そのような状況では、ユーザー名が使用された後は、絶対に置き換えられないというルールを設定する方が良いでしょう。

64
Chris Shaffer

論理的な削除は一般的ですか?はい、私はこれを多くの場所で見ました。彼らは安全ですか?それは本当にあなたがそれを削除する前のデータよりも安全性が低いのですか?

私が技術リーダーだったとき、私はチームがすべてのデータを保持することを要求しました。である。これは、監査、トラブルシューティング、レポートの観点からは良好でしたが(これはB2Bトランザクション用のeコマース/ツールサイトであり、誰かがツールを使用した場合、後でアカウントがオフになった場合でも記録したいと考えていました)、いくつかの欠点がありました。

欠点は次のとおりです(すでに言及した他のものは含みません):

  1. すべてのデータを保持することのパフォーマンスへの影響、さまざまなアーカイブ戦略を開発します。たとえば、アプリケーションの1つの領域は、1週間あたり約1Gbのデータの生成に近づいていました。
  2. データを保持するコストは時間とともに増加しますが、ディスクスペースは安価ですが、オンラインとオフラインの両方でテラバイトのデータを保持および管理するためのインフラストラクチャの量は膨大です。冗長性のために大量のディスクが必要であり、バックアップが迅速に移動することを保証するための時間などが必要です。

論理的、物理的削除、またはアーカイブの使用を決定するとき、次の質問を自問します。

  1. このデータは、テーブルに再挿入する必要がある可能性がありますか。たとえば、ユーザーアカウントをアクティブ化または非アクティブ化する可能性があるため、ユーザーアカウントはこのカテゴリに適合します。この場合、論理的な削除が最も理にかなっています。
  2. データの保存に本質的な価値はありますか?その場合、生成されるデータの量。これに応じて、論理的な削除を行うか、アーカイブ戦略を実装します。論理的に削除されたレコードはいつでもアーカイブできることに注意してください。
24
JoshBerke

少し遅れるかもしれませんが、論理削除/ソフト削除について Pinal Daveのブログ投稿 を確認することをお勧めします。

私はこの種の設計[ソフト削除]がまったく好きではありません。私は、必要なデータのみを単一のテーブルに入れ、不要なデータをアーカイブされたテーブルに移動するアーキテクチャを強く信じています。 isDeleted列に従うのではなく、2つの異なるテーブルを使用することをお勧めします。1つは注文あり、もう1つは削除済み注文です。その場合、両方のテーブルを維持する必要がありますが、実際には維持するのは非常に簡単です。 isDeleted列にUPDATEステートメントを書き込むときは、INSERT INTOを別のテーブルに書き込み、元のテーブルから削除します。状況がロールバックの場合、別のINSERT INTOとDELETEを逆の順序で書き込みます。失敗したトランザクションが心配な場合は、このコードをTRANSACTIONでラップします。

上記の状況で、小さなテーブルと大きなテーブルの利点は何ですか?

  • 小さいテーブルは保守が簡単です
  • インデックスの再構築操作ははるかに高速です
  • アーカイブデータを別のファイルグループに移動すると、プライマリファイルグループの負荷が軽減されます(すべてのファイルグループが異なるシステム上にあると考えられます)。これにより、バックアップも高速化されます。
  • 統計はサイズが小さいため頻繁に更新され、これによりリソースの消費が少なくなります。
  • インデックスのサイズは小さくなります
  • テーブルのサイズを小さくすると、テーブルのパフォーマンスが向上します。
15
Tohid

私はNoSQL開発者であり、前回の仕事で、誰かにとって常に重要なデータを扱っていました。作成されたその日に偶然に削除された場合、前回のバックアップでそれを見つけることができませんでした昨日から!そのような状況では、ソフト削除は常に1日を節約しました。

タイムスタンプを使用してソフト削除を行い、ドキュメントが削除された日付を登録しました。

IsDeleted = 20150310  //yyyyMMdd

毎週日曜日に、プロセスがデータベース上を歩き、IsDeletedフィールドをチェックしました。現在の日付とタイムスタンプの差がN日よりも大きい場合、ドキュメントは完全に削除されました。何らかのバックアップでドキュメントがまだ利用可能であることを考慮すると、それを行うのは安全でした。

EDIT:このNoSQLのユースケースは、データベースで作成される大きなドキュメントに関するもので、毎日数十から数百のドキュメントですが、数千から数百万ではありません。一般的に、これらはワークフロープロセスのステータス、データ、および添付ファイルを含むドキュメントでした。これが、ユーザーが重要なドキュメントを削除する可能性がある理由です。このユーザーは、ほんの数例を挙げると、管理者権限を持つユーザー、またはドキュメントの所有者である可能性があります。

TL; DR私のユースケースはビッグデータではありませんでした。その場合、別のアプローチが必要になります。

12
Mario S

私が使用したパターンの1つは、ミラーテーブルを作成し、プライマリテーブルにトリガーをアタッチすることです。そのため、すべての削除(および必要に応じて更新)はミラーテーブルに記録されます。

これにより、削除/変更されたレコードを「再構築」できます。また、プライマリテーブルを完全に削除して「クリーン」に保つことができます。また、「元に戻す」機能を作成できます。また、日付、時間も記録できます。 、およびミラーテーブルでアクションを実行したユーザー(魔女狩りの状況では非常に貴重です)。

もう1つの利点は、ミラーテーブルのレコードを意図的に含めない限り、プライマリからクエリするときに削除されたレコードを誤って含める可能性がないことです(ライブレコードと削除されたレコードを表示することができます)。

別の利点は、実際の外部キー参照がないため、ミラーテーブルを個別にパージできることです。これは、ソフト削除を使用しているが他のテーブルへの参照接続を保持しているプラ​​イマリテーブルからのパージと比較して、これを比較的簡単な操作にします。

他にどのような利点がありますか?-多数のコーダーがプロジェクトに携わっており、スキルと詳細レベルに注意を払ってデータベースの読み取りを行う場合、素晴らしいことです。それらの1つは、削除されたレコードを含めないことを忘れていませんでした(笑、削除されたレコードを含めない= True)、その結果、クライアントが利用可能なキャッシュポジションを言い過ぎて、株式を購入します(つまり、取引のように)システム)、トレーディングシステムを使用すると、堅牢なソリューションの価値は、初期の「オーバーヘッド」が少し増えている場合でも、すぐにわかります。

例外:
-ガイドとして、ユーザー、カテゴリなどの「参照」データにはソフト削除を使用し、「ファクト」タイプのデータ、つまりトランザクション履歴のミラーテーブルへのハード削除を使用します。

8
Code Warrior

私はよく論理的な削除を使用します-「削除された」データをアーカイブされたテーブルに断続的にアーカイブすると(必要に応じて検索できます)、アプリケーションのパフォーマンスに影響を与える可能性がないときにうまく機能することがわかります.

監査を受けた場合でもデータが残っているため、うまく機能します。物理的に削除した場合、なくなった

4
Galwegian

私は、特に基幹業務アプリケーションまたはユーザーアカウントのコンテキストでの論理削除の大ファンです。私の理由は簡単です:多くの場合、ユーザーがシステムを使用できないようにする必要があります(したがって、アカウントは削除済みとしてマークされます)が、ユーザーを削除すると、すべての作業などが失われます。

別の一般的なシナリオは、ユーザーが削除された後しばらくして再作成される場合があることです。ユーザーは、データを再作成するのではなく、削除する前の状態ですべてのデータを表示する方がはるかに便利です。

私は通常、ユーザーを無期限に「一時停止」することで、ユーザーを削除することを考えています。彼らがいつ合法的に戻る必要があるのか​​、あなたは決して知りません。

4
Jon Dewees

私はほとんどの場合、ソフト削除を行います。その理由は次のとおりです。

  • お客様から削除を求められた場合、削除したデータを復元できます。ソフト削除を使用して、より幸せな顧客。バックアップから特定のデータを復元するのは複雑です
  • どこでもisdeletedをチェックすることは問題ではありません。とにかくuseridをチェックする必要があります(データベースに複数のユーザーからのデータが含まれている場合)。これら2つのチェックを別の関数に配置する(またはビューを使用する)ことで、コードによるチェックを実施できます。
  • 正常な削除。削除されたコンテンツを処理するユーザーまたはプロセスは、次の更新が行われるまで「表示」され続けます。プロセスが突然削除されたデータを処理している場合、これは非常に望ましい機能です
  • 同期:データベースとモバイルアプリ間の同期メカニズムを設計する必要がある場合、ソフト削除の実装がはるかに簡単になります。
4

Re:「これは安全ですか?」 -それはあなたの意味に依存します。

物理的な削除を実行するということであれば、削除されたデータをだれも見つけられないようにする、そうであれば、多かれ少なかれ真実です。消去する必要がある機密データを物理的に削除する方が安全です。これは、データベースから永久に削除されるためです。 (ただし、バックアップ、トランザクションログ、または転送中に記録されたバージョン(パケットスニファーなど)など、問題のデータの他のコピーが存在する可能性があることに注意してください-データベースから削除しただけではありません他の場所に保存されなかったことを保証します。)

論理的な削除を行うことで、データがより安全になりますデータを失うことはありませんであり、これも事実です。これは監査シナリオに適しています。一度データが生成されると、決してreally消えることはないという基本的な事実を認めているため、私はこのように設計する傾向があります(特にたとえば、インターネット検索エンジンによってキャッシュされる機能)。もちろん、実際の監査シナリオでは、論理的な削除だけでなく、変更の時間と変更を行ったアクターとともに、更新もログに記録する必要があります。

データが表示されるはずのないユーザーの手に渡らないことを意味する場合、それはアプリケーションとそのセキュリティ構造次第です。その点で、論理的な削除は、データベース内の他の何よりも安全ではありません。

3
Ian Varley

参照整合性が難しい場合の論理削除。

テーブルデータに一時的な側面がある場合(FROM_DATE-TO_DATEが有効)に行うのは正しい考えです。

それ以外の場合は、データを監査テーブルに移動し、レコードを削除します。

プラス面:

ロールバックするのが最も簡単な方法です(可能な場合)。

特定の時点での状態を簡単に確認できます。

2
pkario

同期に依存するモバイルアプリは、物理的な削除ではなく論理的な削除の使用を強いる場合があります。サーバーは、レコードが削除された(マークされた)ことをクライアントに示すことができなければなりません。

2
axd

何かの履歴を保持したい場合にはかなり標準的です(例:@Jon Deweesが言及しているユーザーアカウント)。そして、ユーザーが削除の取り消しを要求する可能性が高い場合、それは確かに素晴らしいアイデアです。

クエリから削除されたレコードをフィルタリングして複雑にし、クエリを複雑にするだけのロジックが心配な場合は、フィルタリングを行うビューを作成し、それに対してクエリを使用できます。レポートソリューションなどでこれらのレコードが漏洩することを防ぎます。

2
BQ.

古いレコードを保持するためだけに、ソフト削除を実行していました。私は、ユーザーが思ったほど頻繁に古いレコードを表示することを気にしないことに気付きました。ユーザーが古いレコードを表示したい場合は、アーカイブまたは監査テーブルから表示するだけですよね?それで、ソフト削除の利点は何ですか?より複雑なクエリステートメントなどにつながるだけです。

以下は、ソフト削除しないようにする前に実装したものです。

  1. 監査を実装して、すべてのアクティビティを記録します(追加、編集、削除)。監査にリンクされている外部キーがないこと、このテーブルが保護されていること、管理者以外は誰も削除できないことを確認してください。

  2. どのテーブルが「トランザクションテーブル」と見なされるかを特定します。これは長期間保持される可能性が非常に高く、ユーザーは過去のレコードまたはレポートを表示する可能性が非常に高くなります。例えば;購入取引。このテーブルは、マスターテーブルのID(dept-idなど)だけでなく、参照としての名前(dept-nameなど)、またはレポートに必要なその他のフィールドなどの追加情報も保持する必要があります。

  3. マスターテーブルの「アクティブ/非アクティブ」または「有効/無効」または「非表示/表示」レコードを実装します。そのため、ユーザーはレコードを削除する代わりに、マスターレコードを無効化/非アクティブ化できます。この方がはるかに安全です。

ちょうど私の2セントの意見。

2
David

私は強く同意しない論理的な削除では、多くのエラーにさらされるためです。

すべてのクエリの最初に、各クエリはIsDeletedフィールドを処理する必要があり、複雑なクエリではエラーの可能性が高くなります。

2番目のパフォーマンス:アクティブな3つだけの100000レコードを持つテーブルを想像してください。データベースのテーブルにこの数を掛けます。別のパフォーマンス問題は、古い(削除されたレコード)を持つ新しいレコードとの競合の可能性です。

私が見る唯一の利点はレコードの履歴ですが、この結果を達成する他の方法があります。たとえば、情報を保存できるロギングテーブルを作成できます:TableName,OldValues,NewValues,Date,User,[..]ここで、*Valuesvarcharになり、この形式で詳細を記述しますfieldname : value; [..]または情報をxmlとして保存します。

これはすべてコードまたはトリガーを介して実現できますが、あなたは[〜#〜] one [〜#〜]すべての履歴を持つテーブルです。別のオプションは、指定されたデータベースエンジンが変更の追跡のネイティブサポートであるかどうかを確認することです。たとえば、SQL ServerデータベースにはSQL Track Data Changeがあります。

2
Max

システム設計以外にも、回答が必要な要件があります。記録保持における法的または法定の要件は何ですか?行の関係によっては、データが「一時停止」された後、一定期間保持されるという法的要件がある場合があります。

一方、要件は、レコードが「削除」されると、真にかつ取消不能に削除されることです。決定を下す前に、利害関係者に相談してください。

2
Dave

Tohidのコメントに返信するために、レコードの履歴を保持したいという同じ問題に直面し、is_deleted列が必要かどうかもわかりませんでした。

pythonの実装と、私たちがヒットした同様のユースケースについて話しています。

https://github.com/kvesteri/sqlalchemy-continuum に遭遇しました。これは、対応するテーブルのバージョン管理テーブルを取得する簡単な方法です。コードの最小行と追加、削除、更新の履歴をキャプチャします。

これは、is_deleted列だけではありません。このエントリで何が起こったのかを確認するために、いつでもバージョンテーブルをバックリファレンスできます。エントリが削除、更新、または追加されたかどうか。

このようにis_deleted列を持つ必要はまったくなく、削除関数は非常に簡単でした。このように、どのapiでもis_deleted=Falseをマークすることを覚えておく必要もありません。

1
Lalit

カスケード機能が役に立たないようなものをレンダリングする必要があるため、データベースを実行させません。

挿入などの単純なものの場合、再挿入の場合、その背後のコードは2倍になります。

単に挿入するだけではなく、存在を確認し、存在しない場合は挿入するか、存在する場合は削除フラグを更新し、他のすべての列を新しい値に更新する必要があります。これは、データベーストランザクションログの更新と見なされ、不正確な監査ログを引き起こす新しい挿入ではありません。

テーブルは冗長データで詰まっているため、パフォーマンスの問題が発生します。特に一意性を備えたインデックス作成機能を備えています。

私は論理的な削除の大ファンではありません。

1
Taqveem

2018年であり、ソフト削除の1つの大きな欠点は次のとおりです。

GDPRコンプライアンス

個人データとみなされるものに対してソフト削除を行う場合、アプリケーションはおそらくGDPRに準拠していません。 [ 1 ] [ 2 ]

また、企業がEU内になくても、EUの企業、居住者、または市民のデータを処理している限り、GDPRに準拠する必要があります。 []

1
zypA13510

それはすべて、システムとそのデータのユースケースに依存します。

たとえば、政府が規制するシステム(たとえば、品質システムの一部と見なされ、電子記録に関するFDAガイドラインに従う必要がある製薬会社のシステム)について話している場合は、ハードデリートを行わないほうがよいでしょう! FDAの監査人が来て、製品番号ABC-123に関連するシステム内のすべての記録を要求することができ、すべてのデータが利用可能になります。ビジネスプロセスの所有者が、システムが今後新しいレコードで製品番号ABC-123を使用することを許可してはならないと言う場合、代わりに履歴削除データを保持しながら、システム内で「非アクティブ」にする代わりにsoft-deleteメソッドを使用します。

ただし、システムとそのデータには、「北極の天気を追跡する」などのユースケースが含まれている可能性があります。たぶん、あなたは1時間に1度の温度測定値を取り、一日の終わりに1日平均を集計します。集約後に毎時データは使用されなくなる可能性があり、集約の作成後に毎時の読み取り値を完全に削除します。 (これは、構成された簡単な例です。)

重要なのは、それはすべてシステムとそのデータのユースケースに依存するものであり、純粋に技術的な観点から行われる決定ではないということです。

0
HardCode

ソフト削除は、データの関連性が高い場合にほとんどのアプリケーションで実行されるプログラミング方法です。エンドユーザーのミスによる削除が致命的な可能性がある金融アプリケーションの場合を考えてみましょう。これは、ソフト削除が関連する場合です。ソフト削除では、ユーザーは実際にレコードからデータを削除するのではなく、IsDeletedとしてtrueのフラグが付けられます(通常の規則により)。

EF 6.xまたはEF 7以降では、Softdeleteが属性として追加されますが、当面はカスタム属性を作成する必要があります。

データベースの設計ではSoftDeleteを強くお勧めします。これは、プログラミングの慣習として適切な規則です。

0
Sanu Antony

まあ!皆が言ったように、それは状況に依存します。

UserNameやEmailIDなどの列にインデックスがあり、同じUserNameまたはEmailIDが再び使用されることを期待しない場合。ソフト削除を使用できます。

つまり、SELECT操作で主キーが使用されているかどうかを常に確認してください。 SELECTステートメントで主キーを使用する場合、WHERE句でフラグを追加してもそれほど違いはありません。例を見てみましょう(疑似):

テーブルユーザー(UserID [プライマリキー]、EmailID、IsDeleted)

SELECT * FROM Users where UserID = 123456 and IsDeleted = 0

UserID列には主キーがあるため、このクエリではパフォーマンスの面で違いはありません。最初に、PKに基づいてテーブルをスキャンし、次の条件を実行します。

ソフト削除がまったく機能しない場合:

ほとんどすべてのWebサイトでのサインアップでは、EmailIDを一意のIDとして使用します。 Facebook、G +などのWebサイトでEmailIDが使用されると、他の人が使用することはできなくなります。

ユーザーが自分のプロファイルをウェブサイトから削除したい日が来ます。論理的な削除を行うと、そのユーザーは二度と登録できなくなります。また、同じEmailIDを使用して再度登録しても、履歴全体が復元されるわけではありません。削除は削除を意味します。このようなシナリオでは、物理的な削除を行う必要があります。ただし、アカウントの履歴全体を維持するために、常にそのようなレコードをアーカイブテーブルまたは削除されたテーブルにアーカイブする必要があります。

はい、多くの外部テーブルがある状況では、処理は非常に面倒です。

また、ソフト削除または論理削除によってテーブルサイズが増加するため、インデックスサイズも増加することに注意してください。

0
Jiten

別の方法として、Mobile Linkを介して更新するリモートデバイスを使用するユーザーがいます。サーバーデータベースのレコードを削除すると、それらのレコードがクライアントデータベースで削除済みとしてマークされることはありません。

両方を行います。クライアントと協力して、データを回復できる期間を決定します。たとえば、一般的に顧客と製品はクライアントから削除するまでアクティブですが、販売履歴は13か月間のみ保持され、その後自動的に削除されます。クライアントは、削除された顧客と製品を2か月間保持し、6か月間履歴を保持したい場合があります。

そのため、これらのパラメーターに従って論理的に削除されたものをマークするスクリプトを一晩実行し、2、6か月後に、今日論理的に削除されたものは完全に削除されます。

スマートフォンなど、メモリが限られているクライアントデバイスに巨大なデータベースを配置することよりも、データのセキュリティについては問題ありません。 4年間で週に2回200個の製品を注文するクライアントは、81,000行を超える履歴を持ちます。その75%は、クライアントが見たとしても気にしません。

0
TychaBrahe

データの一部を公開したくないが、歴史的な理由でそれを保持する必要があるため、ほとんどの時間ソフト削除が使用されます(製品が廃止される可能性があるため、新しいトランザクションは必要ありませんが、販売取引の履歴)。ところで、これを処理するために製品への参照を作成する代わりに、販売トランザクションデータの製品情報値をコピーしている人もいます。

実際、表示/非表示またはアクティブ/非アクティブ機能の言い回しのように見えます。それがビジネスの世界で「削除」の意味だからです。ターミネーターは人々を削除するかもしれないが、ボスは彼らを解雇するだけだと言いたい。

この方法は非常に一般的なパターンであり、多くの理由で多くのアプリケーションで使用されています。それがこれを達成する唯一の方法ではないので、あなたはそれが素晴らしいかでたらめであると言っている何千人もの人々を持ち、両方ともかなり良い議論を持っています。

セキュリティの観点から、SoftDeleteはAuditのジョブを置き換えません。また、バックアップのジョブも置き換えません。 「2つのバックアップケース間の挿入/削除」が怖い場合は、完全復旧モデルまたは一括復旧モデルについてお読みください。 SoftDeleteを使用すると、回復プロセスをより簡単にすることができます。

あなたの要件を知るのはあなた次第です。

0
Marco Guignard