ビジネスが大規模なトランザクションを作成したため、MySQL のバイナリログが拡大しました。大規模なバイナリログを解析するときに、解析が不可能になるこの問題がよく発生しますが、他のツールを使用しないと問題を解析するのは困難です。
著者: Sun Xuzong、新浪微博 DBA チームのエンジニア。主に MySQL や PostgreSQL などのリレーショナル データベースの運用と保守を担当。
Aikeson オープン ソース コミュニティによって作成されています。オリジナルのコンテンツを許可なく使用することはできません。転載する場合は編集者に連絡し、出典を示してください。
この記事は合計 3200 ワードあり、読むのに 10 分かかると予想されます。
故障現象
ビジネスが大規模なトランザクションを作成したため、MySQL のバイナリログが拡大しました。大規模なバイナリログを解析するときに、解析が不可能になるこの問題がよく発生しますが、他のツールを使用しないと問題を解析するのは困難です。
障害の再発
[root@xuzong mysql]# ls -lh mysql-bin.003300
-rw-r----- 1 my3696 mysql 6.7G Oct 30 16:24 mysql-bin.003300
[root@xuzong mysql]# /usr/local/mysql-5.7.35/bin/mysqlbinlog -vv mysql-bin.003300 > 1.sql
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.334z3P' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
mysqlbinlog: Error writing file '/tmp/tmp.0Uirch' (Errcode: 28 - No space left on device)
推測
- 設定ファイルの tmpdir に問題がある可能性がありますが、これを変更するには MySQL を再起動する必要があります。
- MySQL を再起動せずにこの一時スペースを変更することはできますか?
推測を検証する
一つ当ててみてください
my.cnf に設定されている tmpdir を見ると、このパラメータは使用されていないことがわかり、推測は間違っていたようです。
[root@mysql mysql]# cat my.cnf | grep tmpdir
tmpdir = /data1/dbatemp
推測 2
ネットで検索すると、一時テーブルがいっぱいになる問題を解決する方法がほとんどですが、これは最初の推測ですが、mybinlog の解析時に使用される一時ハンドルが占有する領域を変更する明確な方法はありません。
問題分析
ソース コードを見て、mysqlbinlog がどのように tmpdir を取得するかを確認することしかできません。
mysqbinlog.cc
int main(int argc, char** argv)
{
........
MY_TMPDIR tmpdir;
tmpdir.list= 0;
if (!dirname_for_local_load)
{
if (init_tmpdir(&tmpdir, 0))
exit(1);
dirname_for_local_load= my_strdup(PSI_NOT_INSTRUMENTED,
my_tmpdir(&tmpdir), MY_WME);
}
........
}
mf_tempdir.cc
my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist)
{
char *end, *copy;
char buff[FN_REFLEN];
DBUG_ENTER("init_tmpdir");
DBUG_PRINT("enter", ("pathlist: %s", pathlist ? pathlist : "NULL"));
Prealloced_array<char*, 10, true> full_list(key_memory_MY_TMPDIR_full_list);
memset(tmpdir, 0, sizeof(*tmpdir));
if (!pathlist || !pathlist[0])
{
/* Get default temporary directory */
pathlist=getenv("TMPDIR"); /* Use this if possible */ //这里能看到是获取的机器环境变量
#if defined(_WIN32)
if (!pathlist)
pathlist=getenv("TEMP"); //windows是temp
if (!pathlist)
pathlist=getenv("TMP"); //linux是tmp
#endif
if (!pathlist || !pathlist[0])
pathlist= DEFAULT_TMPDIR;
}
........
}
いいですね、取得したマシン環境変数であることが判明したので、この問題は解決しました。
問題解決
マシンの tmpdir 変数を一時的に変更するだけです。
[root@mysql mysql]# export TMPDIR="/data1"
[root@mysql mysql]# echo ${TMPDIR:-/tmp}
[root@xuzong mysql]# /usr/local/mysql-5.7.35/bin/mysqlbinlog -vv mysql-bin.003300 > 1.sql
要約する
- ご不明な点がございましたら、ソースコードをご確認ください。
- この問題を解決するには、bin2sql などの binlog 解析ツールの使用を検討できます。
- スローログに記録があるかどうかを確認できます。
補充する
この問題はMySQL 公式マニュアルに記載されていることが判明したので、ここで補足しておきます。
大きなバイナリ ログに対して mysqlbinlog を実行する場合は、ファイル システムに結果のファイルを格納するのに十分なスペースがあることに注意してください。mysqlbinlog が一時ファイルに使用するディレクトリを設定するには、TMPDIR 環境変数を使用します。
さらに技術的な記事については、https: //opensource.actionsky.com/をご覧ください。
SQLEについて
SQLE は、開発環境から運用環境までの SQL 監査と管理をカバーする包括的な SQL 品質管理プラットフォームです。主流のオープンソース、商用および国内データベースをサポートし、開発、運用および保守のためのプロセス自動化機能を提供し、オンライン効率を向上させ、データ品質を向上させます。
SQL取得
タイプ | 住所 |
---|---|
リポジトリ | https://github.com/actiontech/sqle |
書類 | https://actiontech.github.io/sqle-docs/ |
リリースニュース | https://github.com/actiontech/sqle/releases |
データ監査プラグイン開発ドキュメント | https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse |