web-dev-qa-db-ja.com

外部キーを削除しても既存のデータが破損しないことをどのように証明しますか?

TL; DR:実際には、alter table table_name drop foreign key constraint_nameステートメントを実行しても既存のデータが破損しないことを証明します。重要な考慮事項は、ステートメント自体の実行です。関係のない事実の後のデータ変更を検討してください。 (類推によって:安定したドアを開くことは、馬のボルト操作ではなく、有害なアクションです。)

上司と私は、MySQL/InnoDBデータベースで外部キーを使用するかどうかについて意見が異なります。私は、RIを適用し、ON DELETE CASCADEおよびON UPDATE RESTRICT/SET NULLを利用するためにそれらを使用することに反対していますが、彼は反対です(アプリケーションレベルでRIを強制できることを確信しています)。

彼の議論は主に:

  1. Drupalはそれらを使用せず、それらがなくても問題なく動作します。
  2. データや構造を変更する必要がある場合、柔軟性に欠けます。
  3. 彼は既存のテーブルからそれらを削除して物事を変更しました。トラフィックの多い/活動の多いサイトでは、数週間または数か月後にしかデータの破損が発生しなかったため、使用しませんでした。

私の主張は主に:

  1. Drupal 5-7(MyISAM、SQLite 3)enforceでサポートされているデータベース/ DBエンジンのすべてがデフォルトではFKではないため、Drupalは文書化されたままにしますただし、これはD8では異なる場合があります。
  2. はい、それらは対処するのに苦労する可能性がありますが、おそらく欠陥はFKではなく開発者側の不十分な計画/設計にあります。
  3. 確かに、DBMSレベルでFKを使用してRIを適用しないと、他の方法よりもデータが破損する可能性が高くなります。 (適切な事例は、既存のコンテンツが特定のステータスを持つ必要があるユーザーを参照する場合、D6のユーザー参照モジュールがユーザーステータスの変更を制限しないことです)。
  4. コードにDBMSがすでに実行していることを実行/試行させるのは、時間とリソースの浪費です。彼は自分のコードがDBMSと同じかそれ以上に機能することをどのように保証できますか?

基本的に、外部キー自体を削除する行為(その後のデータの挿入/更新に関係なく)が既存のデータを破損しないことを証明できれば、彼は私の考え方に立ち向かいます。実行前のデータと実行後のデータを比較する以外に、実行直後のdrop foreign keyの効果をどのように十分に観察または文書化するかがわからないため、それらの有用性/利点を証明する明確な方法がわかりません実行。

では、外部キーを使用しても問題は発生しないが、後で削除/変更しても既存のデータが破損しないことを証明して、外部キーを使用するように上司を説得するにはどうすればよいですか?実用的な使用テストをセットアップするにはどうすればよいですか?

注:FKを使用することは(エゴティスティックな観点から)私が正しいことをあまり証明したくありませんが、アプリケーションコードよりもDBMSレベルで使用する方がデータとアプリケーションコードにメリットがあります。レベル。

5
Agi Hammerthief

ポイントに直接対抗するには:

Drupalはそれらを使用せず、それらがなくても問題なく動作します。

Drupalは多くのデータベースレイヤーをサポートしています。おそらくそれらの少なくとも1つはFKをサポートしておらず、最も一般的な機能セットを使用することにしましたか?非常に多くの人々がdoを使用しており、人々がそれらを使用していない1つのデータポイントは比較的無意味です。車のシートベルトを着用しない人もいますが、他の人もそうです...

データや構造を変更する必要がある場合、柔軟性に欠けます。

FK関係を変更する必要があるところまで構造を変更する場合、既存の設計のすべてが柔軟性を欠くように見える可能性があります(特に、既存の設計が、最初にモデリングしていたシステムと適切に一致しなかった場合)。既存の構造を変更しようとしています)。

データを変更するとき、それらは意図的に柔軟性がありません。一時的にでも整合性が損なわれるような方法でデータを変更できないように設計されています。外部キー制約がデータ変更を停止する例を尋ねます。それぞれについて、なぜそれが良いことであるか、そして制約を操作して制約を破ることなく目標を達成する方法を説明できます(または逆に、代わりに、その特定のFK関係が間違っている理由を教えてください。ただし、他のFKが間違っているわけではなく、モデルのその部分に問題があったことを意味します。

彼はそれらを既存のテーブルから削除して物事を変更し、トラフィックの多い/アクティビティの多いサイトで数週間または数か月後にしか目立たなかったデータの破損を引き起こしたので、むしろそれらを使用しませんでした。

それらを削除すると、破損しません。それらを削除すると、他のいくつかのコードにバグがあり、時間の経過とともに破損する可能性があり、気付かれませんでした。キーが配置されていた場合、そのプロセスでエラーが発生し、おそらくその問題が通知されて修正されるのではなく、通知されるまで黙ってより多くのデータを破壊することはできません。制約を削除すると、データベースが停止し、将来の挿入/更新/削除に制約が適用されます。既存のデータには影響しません。

私はあなたがそうでなければそうであると確信している誰かに決定的に証明することについてどうやって行くのかわかりません。

私が考えることができる唯一の証拠は最初の原則です:外部キー制約が実際に何を行うかを再アサートし、それによって不整合が発生しないことを示し、 試行してキーを配置することでその問題を作成することができる(キーが持っていることを示す)不整合の作成を許可する代わりにエラーが発生しました)。

より具体的には、制約を削除した直後の影響について、制約を削除しても既存のデータはまったく変更されないことを示します。データベースのコピーを作成し、コピーにキーをドロップし、データの完全な比較を実行して、制約が解除された結果として何も変更されていないことを確認します。

彼は反対です(アプリケーションレベルでRIを強制できることを確信しています)。

bestは、開発/テスト時間の悪用ですが、最悪の場合、後で悪夢が生まれます。あなたはホイールを再発明しており、おそらく非効率的で潜在的にバグがあり、新しいホイールeverywhereを実装する必要がありますeveryアプリケーションは、データベースに毎回それを処理させるのではなく、現在進行中であり、コードのこれらのビットの1つにバグがある場合、データはすべてのアプリケーションの整合性を失う可能性があります時間。

もちろん、DBMSが適用できない複雑なビジネスルールがあるので、それらをBLレイヤーに実装する必要がありますが、このような基本事項については、DBに処理を任せます。

言及されていない余分なものですが、私は何度か聞いています:親オブジェクトに変更を加えると効率が悪くなります

これは、ほとんどのDBMSが各FKのインデックスを自動的に作成しないためです。多くの人々は、作成するものと想定し、期待するパフォーマンスメトリックが表示されないことに驚いています。必要のない場合は非常に無駄になる可能性があるため、DBはこれを行いません(予想よりも頻繁です)。 FKの列にインデックスが必要な場合、カスケード更新/削除(またはその方向の単純な結合クエリ)を効率的にするには、インデックスを作成します。

10
David Spillett

アプリレベルでこれを実装するのは悪夢です。あなたとあなたのチームはコードをテスト、再確認、再テストする必要があります[〜#〜]正確に[〜#〜]これまでと同じです[〜#〜]何百万[〜#〜]のMySQL(InnoDB用)によって[〜#〜]年[〜#〜]

議論に従ってください(stackoverflowで見た中で最高のスレッドの1つ) here 。あなたとあなたのチームに敬意を払って、あなたの上司は[〜#〜]本当に[〜#〜]バグなしで書けると思いますか? 5年未満で重要な機能を持つRI(参照整合性)コード?私は確かにしません!

私が他のフォーラム(主にOracle)で読んだ回数については、RIがアプリレイヤーで適用された場所で継承したアプリに、貧弱なシュマックが目をそらしている回数はわかりません。孤立したレコード、子供がいない親、一貫性のないデータ...リストはどんどん増えています...データもスイスチーズかもしれません、それは多くの穴があります! book データベースの専門家(Oracleの専門家、私が今まで見た中で最高で最も読みやすいテクニカルライティングのいくつか)でこれを読むように上司に伝えてください。レビューから ここ -ジョナサンルイス(530ページを書いた男性 のみ(これを入手)の概要 Oracleオプティマイザーの[〜#〜]基本[〜#〜]

第10章:災害の設計、Jonathan Lewis著

第8章のファンのための、より多くの戦争物語! 「さあ、 『世界最悪のオラクルプロジェクト』について読む準備をしてください。」-ジョナサンルイス。

この章では、Oracleデータベースアプリケーションの開発における最も一般的な間違いについて説明します。多くの人々が頑固に特定の信念にしがみついているので、あなたは確かにそれらのいくつかを認識します。私はこれらのような一般的な議論に遭遇したときに彼のポイントのいくつかを取り上げたいのを知っています:
1。アプリケーションを「データベース非依存」にする必要があります。
2。 Oracleの制約チェック機能を利用する代わりに、アプリケーションレベルでデータの整合性をチェックします。
3。主キーにシーケンスを使用したいと思います。

[〜#〜]注意してください[〜#〜]ポイント2に注意してください!あなたの上司がこの狂気に固執するなら、あなたへの私のアドバイスは速く走って遠くに走ることです!絶え間ない消火活動の悲惨な地獄で日々を過ごし、開発者やDBAとしての潜在能力を決して発揮できず、ほとんど何も学べないでしょう。ほんの少しの考え!

11
Vérace

インデックスに対してDDLを実行しているため、外部キーを削除してもデータは破損しません。

いったんそれを行うと、(既存のデータであっても)将来のデータの整合性をテストするために整合性をテストする必要があります。

create table parent
(
    id int not null auto_increment,
    ...
    primary key (id)
);
create table child
(
    id int not null auto_increment,
    fk_id int not null,
    ...
    primary key (id),
    key fk_index (fk_id),
    CONSTRAINT FK FOREIGN KEY (fk_id) REFERENCES parent(id)
);

制約を削除するとします

create table parent
(
    id int not null auto_increment,
    ...
    primary key (id)
);
create table child
(
    id int not null auto_increment,
    fk_id int not null,
    ...
    primary key (id),
    key fk_index (fk_id)
);

数日の運用後、次のクエリを実行する必要があります

ORPHANED CHILD RECORDS

select COUNT(A.id) orphans from child A left join parent B
on A.fk_id = B.id where B.id IS NULL;

orphansのゼロ以外の数値を取得すると、孤立した子レコードが取得されます。制約を削除する可能性があります。

子供がいない親

select COUNT(A.id) childless_parents from parent A left join child B
on A.id = B.fk_id where B.id IS NULL;

childless_parentsのゼロ以外の数値を取得した場合、子のない親を取得しました(申し訳ありませんが、これはかなり冗長に聞こえます)。制約を削除する可能性があります。

エピローグ

完全な世界では、参照整合性は後付けであるか、当然と見なされます。したがって、外部キー制約を削除する場合は、目を覚ましてサンドマンを目から離し、DB内のすべての制約を見つけて、定期的にチェックしてください。

ゼロ以外のorphansの場合、それらのレコードを削除するか、それらを親に割り当てる必要があります。

2
RolandoMySQLDBA

TL; DR-データベースの仕組みを説明する

長いバージョン:FKを削除するとできないが破損を引き起こすことを示すことはできません。これは実際には真実ではないため、理論的には可能です。あなたが示すことができることは、それが破損を引き起こさないこと、そしてそれが破損を引き起こす可能性が実際よりも理論的である理由を説明することです。

それが実際に腐敗を引き起こす可能性が事実上無視できる理由から始めます。外部キーはメタデータであり、データベースエンジンであるプログラムが受信コマンドの処理方法を決定するために使用するデータです。 これはデータの一部ではありませんが、基本的に同じ方法で処理されます。外部キーに関するデータの削除で破損を引き起こしたデータベースエンジンは、ほぼ確実にデータの削除と同じ問題を抱えています(つまり、テーブル[a]からデータを削除すると、テーブル[b]からデータが破損または削除され、データが大きくなります。これはより頻繁に発生します)。

データの各行には、「これはaからbへのfkです」という記述はありません。代わりに、テーブルaとテーブルb、および関連する列への参照を持つ別のテーブルがあります。したがって、外部キーを表すデータはデータと混同されず、分離されます。これが、数百万、または数十億の行を含むテーブルがあり、マイクロ秒単位で外部キー制約を削除できる理由です。 。実際にその事実を使用して、破損が発生していないことを示すことができます。膨大な数の行を持つサンプルデータベースを作成し、fkを作成し、データファイルをバックアップし、Fkを削除し、結果のデータファイルを元のファイルと比較します。データのFK関係がデータに埋め込まれている場合、そのすべてを変更する必要がありますが、実際には変更されないため、非常に迅速に処理できます。また、fk制約を追加または削除しても、データベースのサイズが基本的に変更されないのはこのためです。インデックスとは異なり、制約は単なるルールとして存在し、それに関連する重要なサイズの実際のデータはありません。

1
jmoreno

実際、私はあなたの上司の言葉に答えがあると思います:

3.変更を加えるために既存のテーブルからそれらを削除し、トラフィックの多い/アクティビティの多いサイトで数週間または数か月後に気づかれたデータ破損を引き起こしたため、彼はそれらを使用しません。

FKを削除してもデータは変更されませんが、誰かがDBに対してクエリを実行した場合、上司のようにアプリケーションレベルのRIが破損を防ぐ方法?話し合わないことですが、データを変更するためにFKを削除しなければならなかったことを思い出してください。

1
JoseTeixeira