MySQL でバックアップを行うにはどうすればよいですか?[重複]
質問
この質問にはすでに答えがあります:
MySQL でバックアップを行うにはどうすればよいですか?
「x」時間ごとに mysqldump を実行するよりも良い方法があることを期待しています。
SQL Server のように、毎日完全バックアップを取得し、その後 1 時間ごとに増分バックアップを取得して、DB が停止した場合でも最新のバックアップまで復元できるものはありますか?
DB ログのようなもので、ログが死なない限り、DB が死んだ正確な時点まで復元できます。
また、これらのことはロックにどのような影響を与えるのでしょうか?mysqldump を実行すると、オンライン トランザクションがしばらくロックされることが予想されます。
解決
見てみるのもいいかもしれません 増分バックアップ.
他のヒント
mysqldump は合理的なアプローチですが、一部のエンジンではダンプの間テーブルがロックされることに注意してください。これにより、大規模な運用データセットの可用性が懸念されます。
これに代わる明らかな代替手段は、Maatkit の mk-Parallel-dump です (http://www.maatkit.org/) これは、mysql 管理者であればぜひチェックしてください。これにより、mysqldump を使用して複数のテーブルまたはデータベースが並行してダンプされるため、ダンプにかかる合計時間が短縮されます。
レプリケートされたセットアップで実行している場合 (本番環境で重要なデータに MySQL を使用している場合、そうしない理由はありません)、その目的専用のレプリケーション スレーブからダンプを取得すると、ロックの問題を防ぐことができます。トラブルを引き起こす。
次に明らかな代替手段は、少なくとも Linux では、LVM スナップショットを使用することです。テーブルをロックし、ファイルシステムのスナップショットを作成し、再度テーブルのロックを解除することができます。次に、そのスナップショットのマウントを使用して追加の MySQL を起動し、そこからダンプします。このアプローチについてはここで説明します。 http://www.mysqlperformanceblog.com/2006/08/21/using-lvm-for-mysql-backup-and-replication-setup/
今では私はこの製品のマーケティング担当者のように聞こえ始めています。私はそれで質問に答えました ここ, 、それから私はもう一度それを使って別の答えを返しました ここ.
一言で言えば、sqlyog (あなたの場合はエンタープライズ) を試してください。 ウェブヨガ すべての mysql 要件に対応します。それだけではありません バックアップをスケジュールする, 、 だけでなく スケジュールの同期 したがって、実際にデータベースをリモート サーバーに複製できます。
無料のコミュニティ エディションとエンタープライズ エディションがあります。私は後者をお勧めしますが、最初に comm edition から始めることもお勧めします。 気に入った様子を見てください.
私はmysqlhotcopyを使用します。 ローカル MySQL データベースおよびテーブル用の高速オンライン ホット バックアップ ユーティリティ. 。とても満足しています。
Percona の人たちは、innobackup に代わるオープンソースを作成しました...
エクストラバックアップ
https://launchpad.net/percona-xtrabackup/
XtraDB についてはこの記事を読んでください。http://www.linux-mag.com/cache/7356/1.html
現在のオフライン バックアップ スキームを次のように補足することもできます。 MySQLレプリケーション.
ハードウェア障害が発生した場合は、マシンを交換するだけで済みます。障害をすぐに発見できれば、ユーザーはダウンタイムやデータ損失にさえ気付かなくなります。
mysql データベースを tar.gz ファイルにダンプし、gpg を使用して暗号化し、メール アカウント (Google Mail ですが、実際には関係ありません) に送信する単純なスクリプトを使用します。
このスクリプトは Python スクリプトであり、基本的に次のコマンドを実行し、出力ファイルを電子メールで送信します。
mysqldump -u theuser -p mypassword thedatabase | gzip -9 - | gpg -e -r 12345 -r 23456 > 2008_01_02.tar.gz.gpg
これが全体のバックアップです。ファイルを tar/gzip/暗号化するだけの Web バックアップ部分もあります。かなり小さなサイトなので、Web バックアップは 20MB よりはるかに小さいため、問題なく GMail アカウントに送信できます (MySQL ダンプは小さく、約 300KB 圧縮されています)。これは非常に基本的なものであり、あまり拡張性が高くありません。週に1回cronを使って実行しています。
回答に長いスクリプトをどのように含めるべきかよくわからないので、コードブロックとして押し込むことにします。
#!/usr/bin/env python
#encoding:utf-8
#
# Creates a GPG encrypted web and database backups, and emails it
import os, sys, time, commands
################################################
### Config
DATE = time.strftime("%Y-%m-%d_%H-%M")
# MySQL login
SQL_USER = "mysqluser"
SQL_PASS = "mysqlpassword"
SQL_DB = "databasename"
# Email addresses
BACKUP_EMAIL=["email1@example.com", "email2@example.com"] # Array of email(s)
FROM_EMAIL = "root@myserver.com" # Only one email
# Temp backup locations
DB_BACKUP="/home/backupuser/db_backup/mysite_db-%(date)s.sql.gz.gpg" % {'date':DATE}
WEB_BACKUP="/home/backupuser/web_backup/mysite_web-%(date)s.tar.gz.gpg" % {'date':DATE}
# Email subjects
DB_EMAIL_SUBJECT="%(date)s/db/mysite" % {'date':DATE}
WEB_EMAIL_SUBJECT="%(date)s/web/mysite" % {'date':DATE}
GPG_RECP = ["MrAdmin","MrOtherAdmin"]
### end Config
################################################
################################################
### Process config
GPG_RECP = " ".join(["-r %s" % (x) for x in GPG_RECP]) # Format GPG_RECP as arg
sql_backup_command = "mysqldump -u %(SQL_USER)s -p%(SQL_PASS)s %(SQL_DB)s | gzip -9 - | gpg -e %(GPG_RECP)s > %(DB_BACKUP)s" % {
'GPG_RECP':GPG_RECP,
'DB_BACKUP':DB_BACKUP,
'SQL_USER':SQL_USER,
'SQL_PASS':SQL_PASS,
'SQL_DB':SQL_DB
}
web_backup_command = "cd /var/www/; tar -c mysite.org/ | gzip -9 | gpg -e %(GPG_RECP)s > %(WEB_BACKUP)s" % {
'GPG_RECP':GPG_RECP,
'WEB_BACKUP':WEB_BACKUP,
}
# end Process config
################################################
################################################
### Main application
def main():
"""Main backup function"""
print "Backing commencing at %s" % (DATE)
# Run commands
print "Creating db backup..."
sql_status,sql_cmd_out = commands.getstatusoutput(sql_backup_command)
if sql_status == 0:
db_file_size = round(float( os.stat(DB_BACKUP)[6] ) /1024/1024, 2) # Get file-size in MB
print "..successful (%.2fMB)" % (db_file_size)
try:
send_mail(
send_from = FROM_EMAIL,
send_to = BACKUP_EMAIL,
subject = DB_EMAIL_SUBJECT,
text = "Database backup",
files = [DB_BACKUP],
server = "localhost"
)
print "Sending db backup successful"
except Exception,errormsg:
print "Sending db backup FAILED. Error was:",errormsg
#end try
# Remove backup file
print "Removing db backup..."
try:
os.remove(DB_BACKUP)
print "...successful"
except Exception, errormsg:
print "...FAILED. Error was: %s" % (errormsg)
#end try
else:
print "Creating db backup FAILED. Output was:", sql_cmd_out
#end if sql_status
print "Creating web backup..."
web_status,web_cmd_out = commands.getstatusoutput(web_backup_command)
if web_status == 0:
web_file_size = round(float( os.stat(WEB_BACKUP)[6] ) /1024/1024, 2) # File size in MB
print "..successful (%.2fMB)" % (web_file_size)
try:
send_mail(
send_from = FROM_EMAIL,
send_to = BACKUP_EMAIL,
subject = WEB_EMAIL_SUBJECT,
text = "Website backup",
files = [WEB_BACKUP],
server = "localhost"
)
print "Sending web backup successful"
except Exception,errormsg:
print "Sending web backup FAIELD. Error was: %s" % (errormsg)
#end try
# Remove backup file
print "Removing web backup..."
try:
os.remove(WEB_BACKUP)
print "...successful"
except Exception, errormsg:
print "...FAILED. Error was: %s" % (errormsg)
#end try
else:
print "Creating web backup FAILED. Output was:", web_cmd_out
#end if web_status
#end main
################################################
################################################
# Send email function
# needed email libs..
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders
def send_mail(send_from, send_to, subject, text, files=[], server="localhost"):
assert type(send_to)==list
assert type(files)==list
msg = MIMEMultipart()
msg['From'] = send_from
msg['To'] = COMMASPACE.join(send_to)
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = subject
msg.attach( MIMEText(text) )
for f in files:
part = MIMEBase('application', "octet-stream")
try:
part.set_payload( open(f,"rb").read() )
except Exception, errormsg:
raise IOError("File not found: %s"%(errormsg))
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
msg.attach(part)
#end for f
smtp = smtplib.SMTP(server)
smtp.sendmail(send_from, send_to, msg.as_string())
smtp.close()
#end send_mail
################################################
if __name__ == '__main__':
main()
「--single-transaction --skip-lock-tables」オプションを使用して mysqldump を使用すると、ロック (ダウンタイム) せずに InnoDB データベース/テーブルの完全なダンプを作成できます。毎週のスナップショットと毎日/時間ごとのスナップショットの作成に適しています バイナリログの増分 (#バイナリ ログを使用して増分バックアップを有効にする)。
@ジェイク、
情報をありがとう。さて、バックアップ機能があるのは製品版のみのようです。
MySQL には適切なバックアップを実行するためのものは何も組み込まれていないのでしょうか?
MySQL の公式ページでは、「更新されていない限り、ファイルをコピーしても構いません」というようなことを推奨しています...
mysql データベース フォルダーの直接バックアップの問題は、バックアップ中に書き込みロックを行わない限り、バックアップの一貫性が必ずしも保たれないことです。
すべてのデータベースを反復処理するスクリプトを実行し、それぞれに対して mysqldump と gzip を実行してバックアップ フォルダーに保存し、そのフォルダーをテープにバックアップします。
ただし、これは、そのようなものは存在しないことを意味します 増分 夜間のダンプは完全なダンプであるため、バックアップが必要になります。しかし、私はこれが良いことである可能性があると主張します。 完全バックアップ 増分から復元するよりもはるかに速いプロセスになります。また、テープにバックアップしている場合は、完全な復元を行う前に多数のテープを集める必要があるでしょう。
いずれにせよ、どのバックアップ計画を採用する場合でも、必ず試行復元を実行してそれが機能することを確認し、どれくらいの時間がかかるか、実行する必要がある手順を正確に把握してください。
mysql サーバーの増分バックアップまたは継続バックアップを実行する正しい方法は、バイナリ ログを使用することです。
まず、すべてのテーブルをロックするか、サーバーを停止します。mysql dump を使用してバックアップを作成するか、データ ディレクトリをコピーするだけです。これは 1 回だけ行う必要があります。または、完全バックアップが必要な場合はいつでも行うことができます。
サーバーをバックアップする前に、バイナリ ログが有効になっていることを確認してください。
増分バックアップを作成するには、サーバーにログインし、FLUSH LOGS コマンドを発行します。次に、最後に閉じたバイナリ ログ ファイルをバックアップします。
すべての innodb テーブルがある場合は、inno ホット バックアップ (無料ではありません) または --single-transaction オプションを指定した mysqldump を使用する方が簡単です (トランザクションを処理するには大量のメモリがあった方がよいでしょう)。
おそらくバイナリ ログは増分バックアップを実行する正しい方法ですが、永続的なストレージとしてバイナリ ファイル形式を信頼しない場合は、増分バックアップを実行する ASCII 方法を次に示します。
mysqldump は悪い形式ではありませんが、主な問題はテーブルの内容を 1 つの大きな行として出力することです。次の簡単な sed は、出力をレコード境界に沿って分割します。
mysqldump -opt -p | sed -e "s/、(/、 n(/g"> database.dump
結果として得られるファイルは diff に非常に適しており、標準の SVN リポジトリにかなりうまく保存されています。これにより、最後のバージョンが中断され、先週のバージョンが必要になった場合に、バックアップの履歴を保存することもできます。
これは Linux シェルにとって非常に強力なソリューションです。私は何年も使っています:
http://sourceforge.net/projects/automysqlbackup/
- ローリング バックアップを実行します。毎日、毎月、毎年
- 豊富なオプション
@ダニエル、
まだ興味がある場合は、新しい (私にとっては新しい) ソリューションが共有されています。 ポール・ガルブレイス, と呼ばれる innodb テーブルのオンライン バックアップを可能にするツール ibbackup パウロの言葉を引用する神託から、
と組み合わせて使用する場合 innobackup, 、バックアップ中にダウンタイムなしで、毎晩のバックアップを作成するのに最適でした
詳細については、 ポールのブログ
トランザクションのロールバックについて話しているようですね。
つまり、何が必要かというと、すべての履歴クエリを含むログがあれば、それはすでにバックアップになっているのではないでしょうか?基本的に DB ログ内のすべての情報の冗長コピーである増分バックアップがなぜ必要なのでしょうか?
その場合は、mysqldump を使用して、時々バックアップを実行してみてはいかがでしょうか。