「将来」MySQL InnoDBログから抜け出す良い方法はありますか?


16

MySQL 5.0でこのInnoDBエラーが発生しました。Mysqldは完全に停止しましたが、その後ib_logfile0とib_logfile1を失いました。クリーンスタートアップの後、InnoDBは「クラッシュリカバリ」を実行しました。innodb_force_recovery = 4のビジネスを行って、ハングしたMyISAMテーブルを修復しました。これで、レプリケーションの準備が整いました。大きな数字を表明:

111116 15:49:36  InnoDB: Error: page 393457 log sequence number 111 561,760,232
InnoDB: is in the future! Current system log sequence number 70 3,946,969,851.
InnoDB: Your database may be corrupt or you may have copied the InnoDB
InnoDB: tablespace but not the InnoDB log files. See
InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html
InnoDB: for more information.

これはスレーブサーバー上にあります。上記のエラーは数百件も発生します。私はこの答えを見つけました:「ログシーケンス番号が十分に大きくなるように、64 GB以上のデータを挿入および削除します」。

http://forums.mysql.com/read.php?22,50163,50163#msg-50163

64GBの魔法の数字は、その男のinnodbログの「メジャー番号」が0から15に増加する必要がある4GB * 16に由来します。私のものは70から111 = 164 GBになります。これには5日かかります。スクリプトの高速化に取り組み続け、これを並列に実行して高速化します。それまでの間、私は他の誰かがより良い答えを持っていることを望んでいます。これはばかげています。


1つの有望な答え:「スレーブサーバーの場合、最善の解決策は、データベースを脇に移動し、マスターから新しいスナップショットをインストールすることです。」残念ながら、24時間365日稼働している25のデータベース(MyISAMとInnoDBの混合)に20,000のテーブルがあります。そのすべてをシャットダウンし、レプリケーションを再度開始する前に新しい完全なレプリケーションを行うには時間がかかりすぎます。
IcarusNM

4
164ギガのデータを作成および削除するために、この8コアマシンを無意味な競争でひざまずかせています。私が聞いている唯一の選択肢は、このスレーブ上のすべてを破棄し、最初からやり直すことです。すべてが2つのファイルの1つの数値を効果的に変更します。確かに、InnoDBのエンジニアにはプロのヒントがあります。誰かがEmacsでib_logfile0を開き、16進数でマジックナンバーを見つけて、それを変更したことがありますか?
IcarusNM

これを行うためのいくつかの方法に関する素晴らしい記事があります。Perconaは間違いなくMySQLの権威です。 percona.com/blog/2013/09/11/...
jbrahy

回答:


10

これは非常にまれな状況でした。InnoDBで「ログシーケンス番号は将来的になります!」と二度とそこに行きたくないと思っています。エラー。私の特定の詳細のため、サーバーのデータの再構築/復元は最後の手段でした。それを手助けするのは良いアイデアでしたが、結局、私はPerlスクリプトを改良し続けてこの馬鹿げたゲームをプレイし、できるだけ多くのギグ/時間をやり遂げることに決めました。一体何なのか、それは良いシステムストレステストです。

要確認:目標は、ib_logfile0およびib_logfile1のヘッダーのどこかに保存される単一のカウンター(「ログシーケンス番号」)を増やすことです。これは、InnoDBを偽造して、見かけ上のタイムワープを無視し、生活を続けることです。しかし、誰もその番号を編集する方法を知りません。または彼らが知っていれば、誰も話していない。

これが私の最終製品です。YMMVですが、mysqlのREPEAT関数を使用して内部的にデータを生成することは非常に効率的です。

 #!/usr/bin/perl
 use DBI;
 $table = shift || die;
 $dbh = DBI->connect("DBI:mysql:junk:host=localhost", "user", "pass"); #Edit "junk" (DB name), user, and pass to suit.
 $dbh->do("DROP TABLE IF EXISTS $table");
 $dbh->do("CREATE TABLE $table (str TEXT) ENGINE=INNODB");
 $sth = $dbh->prepare("INSERT INTO $table (str) VALUES (REPEAT(?,1000000))");
 foreach (1..50) {
    $sth->execute('0123456789');   # 10 MB
 }
 $dbh->do("DELETE FROM $table");

私の提案したレシピ:

  1. 「ジャンク」データベースを作成する
  2. 上記のperlスクリプトをjunk.plとして保存します。
  3. ファイル名を指定して実行junk.pl DATA1、およびjunk.pl DATA2、およびjunk.pl DATA3データベースサーバーなどなど、多くのCPUコアの一度など、すべてが、開始するには、持っています。複数のシェルを開き、各実行をBashループでラップしますwhile true; do date; junk.pl dataX; done

おそらく別のループで、LSNの成長を監視します。

 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 124 3871092821
 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 124 4209892586
 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 125 85212387

大きな数は4GBでラップする符号なし32ビットINTで、毎回小さい数を増やします。上記の例では、124から125にロールバックされました。最初は、このばかげたソリューションのGooglingを送信したmysqld.logに目標が隠されています。そのフィニッシュラインを超えたら、それだけです!角を吹く!紙吹雪を放します!

サイドバー:これにより、mysqld 5.0 w / REPEATの興味深いバグが見つかりました。20MBに移動すると、内部カウンターが反転し、約96 KBにロールオーバーします。どこにも警告やエラーはありません。私はそれを追跡する時間を無駄にしようとしていませんでした。10 MBはすばらしい。他の制限に達した場合、文句を言うかもしれません。さまざまなinnodbバッファーがデフォルトから増加しています。味わう季節。いつものように、mysqld.logを1つのウィンドウで監視します。



ジョナス、ありがとう。それは面白い。上記の方法に固執すると思います。彼は、実行中のmysqldに対してgdbを使用することを示していますが、これはおそらくリスクはありません。しかし、そこにも良い情報があります。
IcarusNM 14年

何らかの奇妙な理由で、MariaDBを使用すると、「小さい数字[スペース]大きい数字」のログシーケンス番号が得られません。もちろん、ログは更新されます。いつ停止するのかわかりません。
グウィネスLlewelyn

5

次の3つのオプションがあります。

オプション01:マスターからスレーブへのrsyncを実行(マスターのダウンタイム)

  • ステップ01:reset master;マスターで実行する(Zaps Binary Logs)
  • ステップ02:service mysql stopマスターで
  • ステップ03:service mysql stopスレーブ上
  • ステップ04:マスターからスレーブへのrsync / var / lib / mysql
  • ステップ05:service mysql startマスターで
  • ステップ06:レプリケーションを開始するログとして、マスターの最初のバイナリログを使用します。そのログのファイルサイズを、複製を開始する位置として使用します
  • ステップ07:service mysql stop --skip-slave-startスレーブ上
  • ステップ08:CHANGE MASTER TOコマンドを実行して、ステップ06で確認したログと位置からレプリケーションをセットアップします
  • ステップ09:start slave;スレーブ上で実行し、レプリケーションに追いつく

オプション02:マスターからスレーブへのrsyncを実行します(マスターの最小ダウンタイム)

  • ステップ01:reset master;マスターで実行する(Zaps Binary Logs)
  • ステップ02:service mysql stopスレーブ上
  • ステップ03:マスターからスレーブへのrsync / var / lib / mysql
  • ステップ04:2つの連続したrsyncが同じ時間かかるまでステップ03を繰り返します
  • ステップ05:service mysql stopマスターで
  • ステップ06:マスターからスレーブへのrsync / var / lib / mysql
  • ステップ07:service mysql startマスターで
  • ステップ08:レプリケーションを開始するログとして、マスター上の最初のバイナリログを使用します。そのログのファイルサイズを、複製を開始する位置として使用します
  • ステップ09:service mysql stop --skip-slave-startスレーブで
  • ステップ10:CHANGE MASTER TOコマンドを実行して、ステップ08で確認したログと位置からレプリケーションをセットアップします
  • ステップ11:start slave;スレーブで実行し、レプリケーションに追いつく

オプション03:XtraBackupを使用する

このソフトウェアツールは、実行中のマスターの控えめなコピーを作成するだけでなく、対応するib_logfilesも作成します。レプリケーションをセットアップする必要があります

このテーマについては以前にStackExchangeに投稿しました

私はこれらのことを私の雇用主のウェブホスティング会社のために何度も行ってきました。1人のクライアントに3.7 TBの移動があり、約16時間かかりました。64GBは比較して非常に小さいです。


オプション02ステップ05では、マスターを開始するように指示します。いつ停止しましたか?ライブマスターのRsyncは大胆です。私が感銘を受けた。幸運なことに、私はinnodb_file_per_tableを使用しています。しかし、最終的には、レプリケーションを開始する前に最後の1つのrsyncを実行するのに十分な長さの弾丸を噛んでマスターを停止する必要があります。それは私が頼ることができる可能性ですが、これは非常にアクティブなDBMSです。そして、XtraBackupで情報を確認します。
IcarusNM

@IcarusNM:ああ、タイプミス。修正しました。ありがとうございました !!!
RolandoMySQLDBA

オプション02は、おそらくいくつかの作業を使用できます。たとえば、手順1の前に手順2を実行する必要があります。おそらく、どこかにリセットスレーブが必要です。ステップ4のタイプミス。そして、ステップ5で「最初のバイナリログ」と言いますが、実際には「唯一」または「最後の」バイナリログを意味します。また、ファイルサイズではなくmysqlbinlogを使用してログの位置を確認する必要があります。そして、マスターをある時点で停止しない限り、これらはすべて機能しません。rsyncが終了したときにログの位置/時間を基にすることは、せいぜい危険です。
IcarusNM

私は過去4年間、TeraByte範囲のデータを持つDBホスティングクライアントでオプション2を行ってきました。実行中のサーバーに対して常に機能します。あなたが犯す可能性がある唯一の本当の間違いは、奴隷にあります。その間違いは、複製が適切にセットアップされたかどうかにあります。さらに、RESET SLAVE特に大量のGBのリレーログを蓄積している場合に便利です。rsyncプロセスとレプリケーションの再確立後、CHANGE MASTER TOコマンドもリレーログを消去することを忘れないでください。
RolandoMySQLDBA

うーん...奇妙な。(いつものように)xtrabackupを使用してスレーブをセットアップしても、これらのログエラー(percona mysql 5.5.x)が発生します...このスレーブで何か問題が発生したようで、再度実行する必要があります。
ハラルド

2

パーティション化されたテーブルでこの問題を解決するには、おそらくもっとクールな方法があることがわかりました。数年前からパーティションを削除する必要があり、2014年にはパーティションを追加する必要がありました。ほとんどすべてのパーティションがこのエラーを報告するため、古いものも報告します。非常に厄介なクラッシュ。

古いものを削除し、MAXVALUEパーティション(最後のパーティション)のREORGANIZEを使用している間は、問題のない新しいファイルが作成されるため、警告は少なくなります。それまでの間、ログシーケンスカウンターをインクリメントするのに役立つため、偽のデータを挿入する必要はありません。私はこれがマスターサーバーで起こっています...

したがって、この:

ALTER TABLE Events DROP PARTITION p1530 , p1535 , p1540 , p1545 , 
p1550, p1555 , p1560 , p1565 , p1570 , p1575 , p1580 , p1585 , p1590 , 
p1595 , p1600 , p1605 , p1610 , p1615 , p1620 , p1625 , p1630 , p1635 , 
p1640 , p1645 , p1650 , p1655 , p1660 , p1665 , p1670 , p1675 , p1680 , 
p1685 , p1690 , p1695 , p1700 , p1705 , p1710 , p1715 , p1720 , p1725 , 
p1730 , p1735 , p1740 , p1745 , p1750 , p1755 , p1760 , p1765 , p1770 , 
p1775 , p1780 , p1785 , p1790 , p1795 , p1800 , p1805 , p1810 , p1815 , 
p1820 , p1825 , p1830 , p1835 , p1840;

この:

ALTER table Events REORGANIZE PARTITION p3000 INTO (
PARTITION p3500 VALUES LESS THAN (TO_DAYS('2013-01-01')),
PARTITION p3510 VALUES LESS THAN (TO_DAYS('2013-01-04')),
PARTITION p3520 VALUES LESS THAN (TO_DAYS('2013-01-07')),
PARTITION p3530 VALUES LESS THAN (TO_DAYS('2013-01-10'))
...
PARTITION p4740 VALUES LESS THAN (TO_DAYS('2014-01-08')),
PARTITION p9000 VALUES LESS THAN MAXVALUE)

これにより、変更内の各パーティションが効果的に削除され、そこにあったコンテンツの一時コピーで再作成されます。必要に応じてテーブルごとにこれを行うことができます。私のアプリケーションではそれが可能になるため、同期されたバックアップなどを心配する必要はありません。

表の残りの部分では、プロセスのすべてのパーティションに触れていないため、ログシーケンスの警告が残っているものがあります。壊れているが、この再編成アクションでカバーされているパーティションについては、おそらくこれを実行します:

ALTER TABLE Events REBUILD PARTITION p0, p1;

またはその

ALTER TABLE Events OPTIMIZE PARTITION p0, p1;

だから、私は考えてみました、あなたは普通のバニラテーブルでこれを行い、ハッシュによって一時的にパーティションを追加し、後でそれを削除することができます(またはそれらを保持して、パーティションを強くお勧めします)。

ただし、mysqlではなくmariadbを使用しています(XtraDB)

おそらくこれは誰かを助ける。私はまだそれを実行していますが、これまでのところとても良いです。ENGINEを変更することでも同じように機能するようであるため、MyIsamとInnoDBの間でやり直します。

ENGINEを変更すると、innodbからテーブルが消えるので、これは問題になりません。

ALTER TABLE Events ENGINE=MyISAM;
ALTER TABLE Events ENGINE=InnoDB;

ここで動作するようです。パーティションテーブルに関するいくつかのことを確認できます。

  • ALTER TABLE xyz ENGINE = InnoDBは非常に低速で、Aria(mariadb)の2倍の速度ですが、一般的にログシーケンスカウンターをインクリメントする方法は低速です
  • ALTER TABLE xyz REBUILD PARTITION ALLは、テーブルを「修正」し、カウンターをインクリメントするのに役立つ最速の方法です
  • ALTER TABLE xyz ANALYZE PARTITION ALLは前者に比べて遅いため、チェックアウトしても問題ないパーティションを書き換えません。REBUILDは、一時テーブルスキーマへの書き換えを保証します。

最後のテーブルをいくつかのテーブルで使用しました。警告は、ファイルを開こうとするときに発生し、カウンターの問題で開くパーティション定義ごとに1つあります。本日、最後のテーブルのカウンターをほぼロールオーバーしました。処理がすべて完了したら、バイナリログをフラッシュする必要があると思います。

更新:この問題を解決することができたいくつかのことを結論付けることができます。

  • 私のクラッシュは、Aria形式(MariaDB)でテーブルのパーティションを再編成したことが原因でした。
  • (私にとって)パーティションの再構築を行うと、シーケンスカウンターを上げるために最善かつ最速で動作しました。エンジンの変更は遅く、innodbに影響を与えるには2回行う必要があります。innoDBへの変更は、MyIsamやAriaに比べて非常に遅いです。
  • 5.5ではなくMariaDB 5.3にアップグレードし(以前は5.2)、正常に動作しました。5.5のパーティション(および確認済みのバグ)には、その組み合わせを使用するにはあまりにも多くの問題があります。
  • ログシーケンスカウンタをリセットするより良い方法があるはずです。

MariaDBでは、USE INFORMATION_SCHEMA; SELECT CONCAT("ALTER TABLE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` REBUILD PARTITION ALL;") AS MySQLCMD AS MySQLCMD FROM TABLES;(source:dba.stackexchange.com/questions/35073/…)を使用してすべてのテーブルをすばやく変更し、一連のコマンドとして実行されるファイルにティーすることができます。
グウィネスルウェリン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.