昨日、ある顧客が突然、大量のデータを誤って削除したと言い、CTO が私を直接ディスカッション グループに引き入れ、データの回復を手伝うと言いました。自分たちで穴を掘り、業務ログを基に開発側に復元させる予定だったが、主キーの削除などの情報のみが記録されており、物理的な削除は不可能だったという。
サーバーに記録されたログを確認したところ、いくつかのサーバーが誤ってレコード出力を削除していたことがわかりました。 Alibaba RDSではインスタンスのクローンを作成して削除前に復元することができますが、数万点に散在するIDを見つけるのは難しく、複数のテーブルに関連付けられたデータも復元する必要があり面倒です。
MySQL のフラッシュバック ソリューションについて考えてみましょう。以前にいくつかの関連記事を読み、python を使用してバイナリを解析し、それを逆にしてロールバック SQL を取得するところでした。本当に時間がないので、今すぐ使用する必要があります。私はすぐにオンラインで「既製のソリューション」を探しました。
本文始まり
MySQL (Alibaba RDS を含む) の高速フラッシュバックは、データベースの誤操作に対する後悔の薬と言えます。フラッシュバック機能は、データベースを誤操作前の状態に戻すことができます。ただし、Oracle データベースでも、短期間内のフラッシュバックのみがサポートされます。
インターネット上の既存のオープンソース MySQL フラッシュバック実装では、binlog を解析して逆方向 SQL を生成するという原則を使用しています: (行モードである必要があります)
削除操作の場合、挿入 (DELETE_ROWS_EVENT) を生成します
更新操作の場合, ビンログの値の順序を入れ替える(UPDATE_ROWS_EVENT)
挿入操作の場合は削除を逆生成(WRITE_ROWS_EVENT)
複数のイベントの場合はSQLを逆生成
上記2つの実装方法はどちらもpython-mysql-replication パッケージは、元のライブラリのスレーブ ライブラリをシミュレートし、show binary logs
を実行してバイナリ ログを取得し、バイナリ ログを同期するリクエストを開始して、EVENT を解析します。ただし、Alibaba Cloud RDS のビンログがスレーブ ライブラリに同期された後、すぐにパージされました show binary logs
来获取binlog,发起同步binlog的请求,再解析EVENT。但是阿里云 RDS 的binlog在同步给从库之后, 很快就被 purge 掉了 。如果要恢复 昨天 的 部分数据 ,两种方案都是拿不到binlog的。也就是闪回的时间有限。
还有一些比较简单的实现,就是解析 binlog 物理文件,实现回滚,如 binlog-rollback.pl
,试过,但是速度太慢。
为了不影响速度,又想使用比较成熟的闪回方案,我们可以这样做:
借助一个自建的 mysqld 实例,将已purge掉的binlog拷贝到该实例的目录下
在自建实例里,提前创建好需要恢复的表(结构),因为工具需要连接上来从 information_schema.columns
获取元数据信息
拷贝的时候,可以替换掉mysql实例自己的binlog文件名,保持连续
可能要修改 mysql-bin.index
,确保文件名还能被mysqld识别到
-
重启mysql实例,show binary logs
。昨日の
データ の一部を復元 - する場合、どちらのオプションでも binlog は取得されません。言い換えれば、フラッシュバック時間には制限があります。
binlog-rollback.pl
など、binlog 物理ファイルを解析してロールバックを実装する比較的単純な実装もいくつかあります。試してみましたが、速度が遅すぎます。
- 速度に影響を与えず、より成熟したフラッシュバック ソリューションを使用したい場合は、次のようにすることができます:
自己構築された mysqld インスタンスを使用して、パージされた binlog をインスタンスのディレクトリにコピーします
自作インスタンスではinformation_schema.columns
からメタデータ情報を取得するためにツールを接続する必要があるため、事前に復元が必要なテーブル(構造体)を作成しておきます コピーする際は、 mysql を置き換えることができます。インスタンスの binlog ファイル名は連続したものにする必要があります。mysql インスタンスがファイル名を確実に認識できるように、mysql-bin.index
を変更する必要がある場合があります。 show binary logs
それがリストにあるかどうかを確認します その後、上記のツールのいずれかを使用してスレーブ ライブラリをシミュレートし、バイナリ ログ ファイル、開始時刻、終了時刻、そして、ロールバックSQLを取得します そして、ビジネスロジックに従って、必要なSQLが選択されます
要するに、別のmysqlを使用してbinlogイベントを送信することです。暖かいリマインダー:
2 つのインスタンス間のバージョンの差が大きすぎないようにします
ファイルのアクセス許可に注意してください
元のライブラリで gtid が有効になっている場合、この自己構築インスタンスも gtid を有効にする必要があります
-
例: python mysqlbinlog_back.py --host="localhost" --username="ecuser" --password="ecuser" --port=3306 \
--schema=dbname --tables="t_xx1,t_xx2,t_xx3" -S "mysql-bin.000019" -E "2017-03-02 13:00:00" -N "2017-03-02 14:09:00" -I -U
===log will also write to .//mysqlbinlog_flashback.log===
parameter={'start_binlog_file': 'mysql-bin.000019', 'stream': None, 'keep_data': True,
'file': {'data_create': None, 'flashback': None, 'data': None}, 'add_schema_name': False, 'start_time': None,
'keep_current_data': False, 'start_to_timestamp': 1488430800,
'mysql_setting': {'passwd': 'ecuser', 'host': 'localhost', 'charset': 'utf8', 'port': 3306, 'user': 'ecuser'},
'table_name': 't_xx1,t_xx2,t_xx3', 'skip_delete': False, 'schema': 'dbname', 'stat': {'flash_sql': {}},
'table_name_array': ['t_xx1', 't_xx2', 't_xx3'],
'one_binlog_file': False, 'output_file_path': './log', 'start_position': 4, 'skip_update': True,
'dump_event': False, 'end_to_timestamp': 1488434940, 'skip_insert': True, 'schema_array': ['dbname']
}
scan 10000 events ....from binlogfile=mysql-bin.000019,timestamp=2017-03-02T11:42:14
scan 20000 events ....from binlogfile=mysql-bin.000019,timestamp=2017-03-02T11:42:29
...
ログイン後にコピー
ヒント:
binlog は ROW 形式であり、dml の影響を受ける各行は、Table_map と Row_log の 2 つのイベントを記録します。 table_map の table_id は、どのインスタンスに適用されるかには影響しません。この ID は、テーブル構造のバージョンを記録するための論理メカニズムと考えることができます。table_diction_cache 内にテーブル定義が見つからない場合、ID は 1 ずつ増分され、次のように割り当てられます。ターゲットをbinlogテーブルに記録します。
-
mysqlbinlog_back.py の使用経験
:
🎜🎜ライブラリ名、表示、開始バイナリログファイル名、開始時刻、終了時刻を必ず指定してください。スキャンを高速化できます。 🎜🎜🎜🎜回復のニーズに応じて、-I、-U、-D を選択して、ロールバックする操作の種類を指定します。 🎜🎜🎜🎜(完全なフラッシュバックではなく)部分的な表データのみがリストアされる場合、関連する表は正しくリストアできません。たとえば、削除されたデータは復元する必要がありますが、削除によって更新された他のテーブルのデータは、完全なフラッシュバックがない限り復元できません。 🎜🎜🎜🎜 t_xx3 の f_do_type フィールドなど、列挙型のテーブル フィールドはサポートされません。自己構築インスタンスの enum 定義を int に変更できます。 🎜🎜🎜
以上がオフライン バイナリ ログに基づく MySQL の高速「フラッシュバック」の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。