MySQL + Git構造の同期

プロジェクトファイルを同期して履歴を保持するには、Gitなどのバージョン管理システムを使用します。 しかし、MySQLデータベースの構造のバージョン管理について質問したとき、満足のいく解決策を見つけることができませんでした。

多くのフレームワークとORMには、「すぐに使える」必要なメカニズム(移行、バージョン管理など)があります。 しかし、MySQLをネイティブに使用するには、すべてをペンで行う必要があります。 そして、変更を追跡するための自動システムを作成しようとするアイデアが生まれました。



挑戦する



開発サーバーのデータベース構造を変更し、実稼働サーバーでデータベース構造を自動的に更新し、Gitのすべての変更の履歴も確認したかったのは、既にコードの制御に使用されていたからです。 そして、すべてが無料で簡単になるように!

これを行うには、すべての変更要求(CREATE、ALTER、DROP)に関する情報を受け取る必要があります。



決定開始



MySQLは、ログを管理する3つの方法をサポートしています。エラーログ(エラーログ)、すべてのクエリのログ(一般ログ)、スロークエリログ(スローログ)です。

最初のオプションはまだ使用していませんが、アイデアがあります(詳細は以下)。 次に、他の2つのオプションについて説明します。

ログはmysqlテーブルまたはファイルに書き込むことができます。 ログファイルの形式はかなり不便なので、テーブルを使用することにしました。



すべてのmysqlログについて説明しているため、このソリューションは、MySQLに負荷をかけずに開発サーバーでのみ使用してください。



重要な点は、クエリの送信先のデータベースの定義です。この情報はクエリ自体のSQLテキストに含まれていない可能性があるためです。

CREATE TABLE /*DB_NAME.*/TABLE_NAME
      
      





一般的なログではサーバーのスレッド番号のみが書き込まれ、データベースを特定するには、使用されているデータベースでこのスレッドのレコードを検索する必要があります。 さらに、ログにはサーバーへの接続と切断に関する情報が含まれています。



Mysql.general_log構造





ただし、slow_logでは、必要なものがすべて見つかりました。まず、ログにはリクエストに関する情報のみが含まれ、次にリクエストが送信されるコンテキストのデータベースの名前が記憶されます。



Mysql.slow_log構造





my.cnfですべての要求を記録するスローログの設定は非常に簡単です

log-output=TABLE





slow_query_log = 1





long_query_time = 0





log_slow_admin_statements = 1







log_slow_admin_statementsは、ALTER要求を記録するために必要です。



ログ処理



そのため、常にすべてのクエリを選択し、そこからリクエストを選択してデータベース構造を変更し、残りをすべてクリアする必要があります。



mysql.slow_logテーブルにはキーフィールドが含まれていないため、ロックできません(したがって、エントリを部分的に削除します)。 したがって、私たちは私たちに合ったテーブルを作成します。



構造change_structure_log





ログローテーションの小さな手順:

 USE mysql; DELIMITER $$ CREATE PROCEDURE `change_structure_log_rotate`() BEGIN -- Definition start drop table if exists slow_log_copy; CREATE TABLE slow_log_copy LIKE slow_log; RENAME TABLE slow_log TO slow_log_old, slow_log_copy TO slow_log; insert into change_structure_log (start_time,query_time,sql_text, db) select start_time, query_time, sql_text,db from slow_log_old where sql_text like "ALTER%" OR sql_text like "CREATE%" OR sql_text like "DROP%"; drop table slow_log_old; -- Definition end END $$
      
      







また、MySQLスケジューラーに追加できます。

 CREATE EVENT `event_archive_mailqueue` ON SCHEDULE EVERY 5 MINUTE STARTS CURRENT_TIMESTAMP ON COMPLETION NOT PRESERVE ENABLE COMMENT '' DO call change_structure_log_rotate();
      
      







そのため、リストラのすべてのリクエストを含むテーブルがあります。 次に、それを処理する小さなスクリプトを作成します。 特定の言語は使用しません(私は個人的にPHPで記述しますが、コードには多数の依存関係があるため、コードをアップロードしても意味がありません)。



だから:

1. change_structure_logテーブルのすべてのエントリをループします。

2. sql_textの場合、たとえば、データベース名があればそれを定期的に引き出します

^ALTER\s+TABLE\s+(?:(?:ONLINE|OFFLINE)\s+)?(?:(?:IGNORE)\s+)?(?:([^\s\.]+)\.\s*)?([^\s\.]+)





3.要求に名前dbが指定されていない場合-dbフィールドから使用します。

4. Gitを使用して、対応するデータベースのすべてのレコードをプロジェクトフォルダーに書き込みます。 たとえば、20140508150500.sql.log。 データベースを使用しないクエリの場合、最初にuse $ DBと記述します。

5.処理されたすべてのレコードを削除します。



したがって、プロジェクトフォルダーには、データベースを変更する要求を含む新しいファイルがあります。これで、Gitクライアントで通常モードでそれらをコミットできます。



次に、本番サーバーで、新しいファイルの外観を追跡するスクリプトを作成し、mysqlで実行します。 そのため、運用サーバーのgitリポジトリをコードとともに更新するとき、データベースをdevサーバーの状態に変更します。



更新しました。 また( DsideSPbのプロンプトで)、Gitのチェックアウト後のフックを使用できます。これにより、外部のリスナーなしで更新の反復が継続的に行われます。



このソリューションは非常に原始的であり、多くのGit機能をサポートしていないことをすぐに言わなければなりません。 ただし、それに基づいて、特定のテーブルを変更することにより、たとえばORMファイルを自動的に変更するなど、さらにクールなことができます。

または、追加のプラグインなしで任意のMySQLクライアントを使用して、Yamlスキーマを自動的に作成します。

また、たとえば、データベース構造自体(トリガーなど)を変更せずに特定のテーブルのデータの変更を追跡することもできます。これは、さまざまなCMSに役立ちます。



PS遅いクエリについても学びたい場合は、これをシステムに統合できます。そのためには、プロシージャからフィルタを削除し、スクリプトで遅いクエリのリクエストを作成して保存する必要があります。



All Articles