しかし、このような古典的なキャンペーンには多くの欠点があります。
- 対応するデータベースレコードが削除されても、ファイルは削除されません
- ファイルを更新しようとしたときの問題
- トランザクションのロールバック中のデータベースとファイルシステム間の同期違反
- データベース内の情報をバックアップおよび復元すると、ファイルシステムとの同期が解除される場合があります
- ファイルは、データベースによって課されるアクセス制限の対象ではありません
SQL AntipatternsプレゼンテーションのセクションPhantom Files、page 60で、データベースとは別にファイルを保存する場合に発生する問題について詳しく読むことができます。ちなみに、プレゼンテーションの作成者はソリューションを提供しています-ファイルをデータベースのBLOBフィールドに直接保存します。 確かに、これは各ケースでバランスのとれた決定であるべきであるという観察結果です。 実際、このファイル保存方法では、Webサーバーは各要求でスクリプトを呼び出してデータベースからファイルを抽出し、ユーザーに提供する必要があります。これはパフォーマンスに悪影響を及ぼします。
この問題の解決策を見つけるために、ブレーンストーミングセッションが実施され、問題を解決するためのいくつかのオプションが考案されました。
- レコードを削除する前に、同じ条件でSELECTを実行し、削除する必要があるファイルの名前を取得します。 問題は、削除されたファイルが多数ある場合、この操作には時間がかかる可能性があり、十分な時間、読み取りと書き込みのためにテーブルをロックする必要があり、多くの場合これは受け入れられないことです。
- 削除する前に、削除されたレコードに対して削除するレコードを設定し、このマークが付いたすべてのレコードを取得し、これらのレコードに関連付けられたファイルを削除し、最後にこのマークが付いたすべてのレコードを削除します。 このテーブルを使用するクエリは、フラグが設定されたレコードを選択しないように変更する必要があります。 短所-多くのクエリを編集する必要があるだけでなく、プロジェクトでは、削除するレコードがかなり複雑なSELECTによって選択されますが、1つのUPDATEに変換することはできません。
- 最初の2つの方法は、データベースのレコードを削除するときに「失われた」ファイルの問題を解決しようとしますが、これはファイルを保存する「古典的な」方法で発生しますが、このアプローチの残りの問題は解決しないため、データベースに直接ファイルを保存する肯定的な瞬間を使用するソリューションを考え出しましたこのアプローチに固有の欠点を取り除きます。
- トリガーを使用します 。 残念ながら、MySQLはその言語でのファイルの操作をサポートしていません。そのようなコマンドは、MySQLソースコードをいじって個別に実装する必要があります。 マイナスの点-ファイルはデータベースと同じホストに保存する必要があります。MySQLの既製のソリューションは見つかりませんでした。そのような既製のソリューションは見つかりませんでした。
- データベースにファイルを保存しますが、PHPを使用せずにWebサーバーに直接提供します。 これを実装するには、MySQLから直接ファイルを送信できるようにするモジュールまたはWebサーバー(nginxなど)にモジュールを書き込むか、 MySQLfsファイルシステムドライバーを使用します。 このアプローチは、上記のすべての問題を解決しますが、その欠点は、MySQLにファイルを保存するオーバーヘッドが増えることです。
- レコードをファイルとして保存するMySQL専用のストレージエンジン。
最後の点について詳しく見ていきましょう。 結局のところ、ファイルシステムを構成するのは、「ファイル名」キーを使用して、レコード(その内容)を取得できる特殊なデータベースです。 つまり、MySQL用の独自のデータストレージエンジンを実装できます。各エンジンには3つのフィールドがあります。
CREATE TABLE `data_storage`.`files` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`path` VARCHAR( 255 ) ,
`data` BLOB
) ENGINE = FILES
データはそのようなテーブルの `data`フィールドにのみ挿入できますが、それらは単にファイルに保存されますが、一意の名前が自動的に生成されます(` id`フィールドをプレフィックスとして使用)-たとえば764533、 `path`フィールドでは自動的に置換されますMySQLがデータを入れる正しいパス-たとえば、「/ mnt / storage / mysqldata / 76/45/33 / 764533_myfile.jpg」。 したがって、このようなテーブルに格納されたデータは単純なファイルとしてアクセスでき、MySQLはデータの整合性を維持します。 したがって、ファイルを保存するこの方法には、従来のアプローチのほとんどすべての欠点がなく(アクセス制限を除きますが、単純なスクリプトとX-Accel-Redirect nginxヘッダーを使用して行うこともできます )、同時にクライアントへのファイル転送のパフォーマンスは低下しません。
問題は小さい-アイデアは一般的に単純ですが、MySQL用のそのようなデータストレージエンジンの既製の実装を見つけることができませんでした。 アイデアが表面に浮かんでいるので、誰かがすでにそれを実装できることは確かであるため、おそらくハブロの人々の1人は、そのようなストレージエンジンの既製の実装へのリンクを提供します。
viperetが共同執筆した記事
PSはMySQLブログに移動しました