実際にまたは物理的にレコードを削除するのではなく、レコードを論理的/ソフトに削除する(つまり、レコードが削除されたことを示すフラグを設定する)ことの利点は何ですか?
これは一般的な方法ですか?
これは安全ですか?
実際にまたは物理的にレコードを削除するのではなく、レコードを論理的/ソフトに削除する(つまり、レコードが削除されたことを示すフラグを設定する)ことの利点は何ですか?
これは一般的な方法ですか?
これは安全ですか?
利点は、履歴を保持し(監査に適している)、削除する行を参照するデータベース内の他のさまざまなテーブルを介して削除をカスケードすることを心配する必要がないことです。欠点は、フラグを考慮に入れるためにレポート/表示メソッドをコーディングする必要があることです。
それが一般的な慣行である限り、私はそう言うでしょうが、他の場合と同様に、それを使用するかどうかはビジネスニーズによって異なります。
編集:別の欠点についての考え-テーブルに一意のインデックスがある場合でも、削除されたレコードは「1つの」レコードを占めるため、その可能性についてもコーディングする必要があります(たとえば、一意のインデックスを持つユーザーテーブルusername;削除されたレコードは、新しいレコードの削除されたユーザーのユーザー名をブロックします。これを回避するには、削除されたユーザー名の列にGUIDを追加できますが、これは非常にハッキーな回避策であり、お勧めしません。ユーザー名を使用すると、それを置き換えることはできないというルールを設定することをお勧めします。)
論理的な削除は一般的な方法ですか? はい、私はこれを多くの場所で見てきました。彼らは安全ですか?それは、データを削除する前よりも安全性が低いかどうかにかかっていますか?
私が技術リーダーだったとき、私はチームにすべてのデータを保持するよう要求しました。その時点では、そのすべてのデータを使用してさまざまな BI アプリケーションを構築することになることはわかっていましたが、その時点では要件がどうなるかはわかりませんでした。なれ。これは監査、トラブルシューティング、およびレポートの観点からは良かったのですが (これは B2B トランザクションの e コマース/ツール サイトであり、誰かがツールを使用した場合、後でアカウントがオフになった場合でも記録したかったためです)、それにはいくつかの欠点がありました。
欠点には次のようなものがあります (既に言及されているものは除きます)。
論理的削除、物理的削除、またはアーカイブの使用を決定するとき、私は次の質問を自問します。
少し遅れているかもしれませんが、論理/ソフト削除に関するPinal Dave のブログ投稿をチェックすることをお勧めします。
私はこの種のデザイン [soft delete] がまったく好きではありません。私は、必要なデータのみを単一のテーブルに配置し、不要なデータをアーカイブされたテーブルに移動する必要があるアーキテクチャを強く信じています。isDeleted 列をたどる代わりに、2 つの異なるテーブルを使用することをお勧めします。その場合、両方のテーブルを維持する必要がありますが、実際には維持するのは非常に簡単です。isDeleted 列に UPDATE ステートメントを記述する場合は、INSERT INTO 別のテーブルを記述し、元のテーブルから DELETE を記述します。状況がロールバックの場合は、別の INSERT INTO と DELETE を逆の順序で記述します。トランザクションの失敗が心配な場合は、このコードを TRANSACTION でラップしてください。
上記の状況で、小さいテーブルと大きいテーブルの利点は何ですか?
- 小さいテーブルはメンテナンスが簡単
- インデックスの再構築操作が大幅に高速化
- アーカイブ データを別のファイル グループに移動すると、プライマリ ファイル グループの負荷が軽減されます (すべてのファイル グループが異なるシステム上にあることを考慮すると)。これにより、バックアップも高速化されます。
- サイズが小さいため、統計は頻繁に更新され、リソースの消費が少なくなります。
- インデックスのサイズが小さくなる
- テーブルのサイズを小さくすると、テーブルのパフォーマンスが向上します。
私は NoSQL 開発者です。以前の仕事では、誰かにとって常に重要なデータを扱っていました。データが作成された同じ日に誤って削除された場合、最後のバックアップでそれを見つけることができませんでした。昨日から!そのような状況では、ソフト削除は常にその日を救いました。
タイムスタンプを使用してソフト削除を行い、ドキュメントが削除された日付を登録しました。
IsDeleted = 20150310 //yyyyMMdd
毎週日曜日に、プロセスがデータベースを歩き回り、IsDeleted
フィールドをチェックしました。現在の日付とタイムスタンプの差が N 日を超えていた場合、ドキュメントは完全に削除されました。ドキュメントがまだ何らかのバックアップで利用可能であることを考えると、それを行うのは安全でした.
編集:この NoSQL の使用例は、データベースで作成される大きなドキュメントに関するもので、毎日数十または数百のドキュメントが作成されますが、数千または数百万ではありません。一般に、これらはワークフロー プロセスのステータス、データ、および添付ファイルを含むドキュメントでした。そのため、ユーザーが重要なドキュメントを削除する可能性がありました。このユーザーは、ほんの数例を挙げると、管理者権限を持つユーザー、またはドキュメントの所有者である可能性があります。
TL;DR 私のユースケースはビッグデータではありませんでした。その場合、別のアプローチが必要になります。
私が使用した 1 つのパターンは、ミラー テーブルを作成し、プライマリ テーブルにトリガーをアタッチして、すべての削除 (および必要に応じて更新) がミラー テーブルに記録されるようにすることです。
これにより、削除/変更されたレコードを「再構築」できます。また、プライマリ テーブルをハード削除して「クリーン」に保つこともできます。また、「元に戻す」機能を作成することもでき、日付、時刻を記録することもできます。 、およびミラー テーブルでアクションを実行したユーザー (魔女狩りの状況では非常に貴重です)。
もう 1 つの利点は、ミラー テーブルから意図的にレコードを含めるというトラブルを起こさない限り、プライマリからクエリを実行するときに誤って削除されたレコードを含める可能性がないことです (ライブ レコードと削除されたレコードを表示したい場合があります)。
もう 1 つの利点は、ミラー テーブルには実際の外部キー参照が含まれていないため、独立してパージできることです。これにより、論理的な削除を使用しているが他のテーブルへの参照接続を保持しているプライマリ テーブルからのパージと比較して、比較的簡単な操作になります。
その他のメリットは?-プロジェクトに取り組んでいるコーダーがたくさんいて、スキルと詳細レベルへの注意が混在しているデータベースで読み取りを行っている場合に最適です。そのうちの1人が削除されていないことを忘れていないことを期待して夜更かしする必要はありませんレコード (笑、削除されたレコードを含めない = True) を使用すると、クライアントが利用可能な現金ポジションを誇張するような結果になります (つまり、取引システムのように)、取引システムで作業する場合、初期の「オーバーヘッド」が少し増えるかもしれませんが、堅牢なソリューションの価値を非常に迅速に見つけることができます。
例外:
- ガイドとして、ユーザー、カテゴリなどの「参照」データにはソフト削除を使用し、「ファクト」タイプのデータ、つまりトランザクション履歴にはミラー テーブルにハード削除を使用します。
私は通常、論理的な削除を使用します。「削除された」データをアーカイブされたテーブル(必要に応じて検索できます)に断続的にアーカイブする場合にもうまく機能するため、アプリケーションのパフォーマンスに影響を与える可能性はありません。
監査を受けたことがあればデータが残っているので、うまく機能します。物理的に削除すると消えてしまいます!
私は、特に基幹業務アプリケーションの場合、またはユーザー アカウントのコンテキストにおいて、論理的な削除の大ファンです。私の理由は単純です。多くの場合、ユーザーがシステムをもう使用できないようにしたいのですが (そのため、アカウントは削除済みとしてマークされます)、ユーザーを削除すると、すべての作業が失われます。
もう 1 つの一般的なシナリオは、ユーザーが削除された後、しばらくしてから再作成される可能性があることです。ユーザーにとっては、データを再作成するよりも、削除される前の状態ですべてのデータが存在する方がはるかに優れたエクスペリエンスです。
通常、ユーザーをさらに削除することは、ユーザーを無期限に「一時停止」することだと考えています。彼らがいつ合法的に戻ってくる必要があるかはわかりません。
古いレコードを保持するためだけに、論理的な削除を行っていました。私が思っていたほど、ユーザーはわざわざ古い記録を閲覧していないことに気付きました。ユーザーが古いレコードを表示したい場合は、アーカイブまたは監査テーブルから表示できますよね? では、論理的な削除の利点は何ですか? より複雑なクエリステートメントなどにつながるだけです。
以下は、ソフト削除を行わないことを決定する前に、私が実装したものです。
監査を実装して、すべてのアクティビティ (追加、編集、削除) を記録します。監査にリンクされた外部キーがないことを確認し、このテーブルが保護されており、管理者以外は誰も削除できないことを確認してください。
どのテーブルが「トランザクション テーブル」と見なされるかを特定します。このテーブルは長期間保持される可能性が非常に高く、ユーザーが過去の記録やレポートを表示する可能性が非常に高くなります。例えば; 購入取引。このテーブルは、マスター テーブルの ID (dept-id など) を保持するだけでなく、参照としての名前 (dept-name など) やその他のレポートに必要なフィールドなどの追加情報も保持する必要があります。
マスターテーブルの「アクティブ/非アクティブ」または「有効/無効」または「非表示/表示」レコードを実装します。そのため、レコードを削除する代わりに、ユーザーはマスター レコードを無効化/非アクティブ化できます。この方法の方がはるかに安全です。
私の2セントの意見です。
私はほとんどの場合、論理的な削除を行います。その理由は次のとおりです。
isdeleted
。userid
これらの2つのチェックを別の関数に配置する(またはビューを使用する)ことにより、コードでチェックを強制できますRe: 「安全ですか?」-それはあなたが何を意味するかによります。
物理的な削除を行うことで、削除されたデータを誰も見つけることができなくなるという意味であれば、はい、それは多かれ少なかれ真実です。消去する必要がある機密データを物理的に削除する方が安全です。これは、データがデータベースから完全に削除されることを意味するためです。(ただし、問題のデータの他のコピーが存在する可能性があることに注意してください。たとえば、バックアップ、トランザクション ログ、またはパケット スニファーなどの転送中の記録されたバージョンなどです。データベースから削除したからといって、そうではありません。他の場所に保存されていないことを保証します。)
論理的な削除を行うことで、データが失われることがないため、データがより安全になるという意味であれば、それも真実です。これは、監査シナリオに適しています。私がこのように設計する傾向があるのは、一度データが生成されると、それが実際に消えることはないという基本的な事実を認めているためです (特に、インターネット検索エンジンによってキャッシュされる機能があった場合)。もちろん、実際の監査シナリオでは、削除が論理的であるだけでなく、変更の時刻と変更を行ったアクターとともに、更新もログに記録される必要があります。
データが見られるはずのない人の手に渡らないことを意味する場合、それは完全にアプリケーションとそのセキュリティ構造次第です。その点で、論理的な削除は、データベース内の他の何よりも安全ではありません。
多くのエラーにさらされるため、論理的な削除には強く反対します。
まず、各クエリは IsDeleted フィールドに注意する必要があり、複雑なクエリではエラーの可能性が高くなります。
2 番目のパフォーマンス: 100000 個のレコードがあり、アクティブなものが 3 つしかないテーブルを想像してください。データベースのテーブルにこの数を掛けます。別のパフォーマンス上の問題として、新しいレコードと古い (削除された) レコードが競合する可能性があります。
TableName,OldValues,NewValues,Date,User,[..]
私が見る唯一の利点はレコードの履歴ですが、この結果を達成するための他の方法があります。たとえば、情報を保存できるログ テーブルを作成*Values
できvarchar
ますfieldname : value
。[..] または情報を として保存しxml
ます。
これはすべてコードまたはトリガーを介して達成できますが、すべての履歴を持つ 1 つのテーブルにすぎません。もう 1 つのオプションは、指定されたデータベース エンジンが変更の追跡をネイティブでサポートしているかどうかを確認することです。たとえば、SQL Server データベースには SQL Track Data Change があります。
参照整合性が難しい場合の論理的な削除。
テーブル データに一時的な側面がある場合 (FROM_DATE - TO_DATE が有効) に行うのは正しい考えです。
それ以外の場合は、データを監査テーブルに移動し、レコードを削除してください。
プラス面:
これは、ロールバックする最も簡単な方法です (可能な場合)。
特定の時点でどのような状態であったかを簡単に確認できます。
何かの履歴を保持したい場合 (@Jon Dewees が言及しているユーザー アカウントなど) では、かなり標準的です。また、ユーザーが削除の取り消しを求める可能性が高い場合は、確かに素晴らしいアイデアです。
削除されたレコードをクエリから除外するロジックが煩雑になり、クエリが複雑になることに懸念がある場合は、フィルタリングを行うビューを作成し、それに対してクエリを使用することができます。レポート ソリューションなどでこれらのレコードが漏洩するのを防ぎます。
カスケード機能などを役に立たなくする必要があるため、データベースを実行させません。
挿入などの単純なものの場合、再挿入の場合は、その背後にあるコードが 2 倍になります。
単純に挿入するだけではなく、存在を確認して挿入するか、存在する場合は削除フラグを更新し、他のすべての列を新しい値に更新する必要があります。これはデータベース トランザクション ログへの更新と見なされ、不正確な監査ログの原因となる新しい挿入ではありません。
テーブルが冗長データで目詰まりするため、パフォーマンスの問題が発生します。特に一意性のあるインデックス作成で大混乱を引き起こします。
私は論理的な削除の大ファンではありません。
良い!皆さんおっしゃる通り、状況次第です。
UserName や EmailID のような列にインデックスがあり、同じ UserName や EmailID が再び使用されることを期待していない場合。ソフト削除を使用できます。
とはいえ、SELECT 操作で主キーが使用されているかどうかを常に確認してください。SELECT ステートメントで主キーを使用する場合、WHERE 句にフラグを追加しても大きな違いはありません。例を見てみましょう(疑似):
テーブル ユーザー (UserID [主キー]、EmailID、IsDeleted)
SELECT * FROM Users where UserID = 123456 and IsDeleted = 0
UserID 列には主キーがあるため、このクエリではパフォーマンスに違いはありません。最初に、PK に基づいてテーブルをスキャンし、次の条件を実行します。
論理的な削除がまったく機能しない場合:
ほとんどすべての Web サイトでサインアップすると、一意の ID として EmailID が使用されます。メール ID が facebook や G+ などの Web サイトで使用されると、他のユーザーは使用できなくなります。
ユーザーがウェブサイトから自分のプロフィールを削除したい日が来ます。ここで、論理削除を行うと、そのユーザーは二度と登録できなくなります。また、同じ EmailID を使用して再度登録しても、すべての履歴が復元されるわけではありません。誰もが知っているように、削除は削除を意味します。このようなシナリオでは、物理的な削除を行う必要があります。ただし、アカウントの履歴全体を維持するには、そのようなレコードを常にアーカイブ テーブルまたは削除済みテーブルにアーカイブする必要があります。
はい、多くの外部テーブルがある状況では、取り扱いが非常に面倒です。
また、ソフト/論理削除によりテーブル サイズが増加するため、インデックス サイズも増加することに注意してください。
一部のデータを公開したくないが、歴史的な理由でそれを保持する必要があるため、ほとんどの場合ソフト削除が使用されます (製品が廃止される可能性があるため、新しいトランザクションは必要ありませんが、それでも作業する必要があります)販売取引の履歴)。ちなみに、商品を参照するのではなく、販売取引データ内の商品情報の値をコピーして対応しているものもあります。
実際、表示/非表示またはアクティブ/非アクティブ機能の言い換えのように見えます。それがビジネスの世界における「削除」の意味だからです。ターミネーターは人を削除するかもしれませんが、ボスはただ解雇するだけです。
このプラクティスは非常に一般的なパターンであり、さまざまな理由から多くのアプリケーションで使用されています。これを達成する唯一の方法ではないので、何千人もの人々がそれは素晴らしいとかでたらめだと言っていて、どちらもかなり良い議論をしています。
セキュリティの観点から、SoftDelete は Audit のジョブを置き換えるものではなく、バックアップのジョブも置き換えるものではありません。「2 つのバックアップ ケース間の挿入/削除」が怖い場合は、完全または一括復旧モデルについてお読みください。SoftDelete を使用すると、回復プロセスがより簡単になる可能性があることは認めます。
あなたの要件を知るのはあなた次第です。
私はすでに別の投稿で答えています。ただし、私の答えはここの質問により適していると思います。
論理的な削除に対する私の実際的な解決策は、次の列を持つ新しいテーブルを作成してアーカイブすることです:
original_id
,table_name
,payload
, (およびオプションの主キー「id」)。
original_id
は削除されたレコードの元の ID、は削除されたレコードtable_name
のテーブル名 (この場合"user"
)、payload
削除されたレコードのすべての列からの JSON 文字列化された文字列です。
original_id
後でデータを取得するために、列にインデックスを作成することもお勧めします。この方法でデータをアーカイブします。こんなメリットがあります
- 履歴のすべてのデータを追跡する
- 削除されたレコードのテーブル構造に関係なく、任意のテーブルからレコードをアーカイブする場所は 1 つだけです。
- 元のテーブルの一意のインデックスの心配はありません
- 元のテーブルで外部インデックスをチェックする心配はありません
WHERE
すべてのクエリで、削除をチェックするための句はもうありませんソフト削除が実際には良い考えではない理由を説明する議論はすでに ここにあります。ソフト削除は、レコードのカウントなど、将来的にいくつかの潜在的な問題を引き起こします...
ケースにもよりますが、以下を参考にしてください。
通常、レコードを「ソフト削除」する必要はありません。シンプルかつ高速に保ちます。 例: 利用できなくなった製品を削除すると、その製品がアプリ全体 (カウント、製品リスト、推奨製品など) でソフト削除されていないことを確認する必要がなくなります。
それでも、データ ウェアハウス モデルでは "論理的な削除" を検討するかもしれません。例:削除された製品の古いレシートを表示しています。*