26

MySQL でバックアップを行うにはどうすればよいですか?

「x」時間ごとに mysqldump を実行するよりも優れた方法があることを願っています。

SQL Server のように、毎日完全バックアップを取り、その後 1 時間ごとにインクリメンタルを作成できるようなものはありますか? DB が停止した場合、最新のバックアップまで復元できますか?

DBログのようなもので、ログが死なない限り、DBが死んだ正確な時点まで復元できますか?

また、これらはロックにどのように影響しますか? mysqldump を実行すると、オンライン トランザクションがしばらくロックされることが予想されます。

4

15 に答える 15

13

増分バックアップを見たいと思うかもしれません。

于 2008-09-05T18:52:22.903 に答える
11

mysqldump は合理的なアプローチですが、一部のエンジンでは、ダンプ中にテーブルがロックされることに注意してください。これには、大規模な実稼働データセットの可用性に関する懸念があります。

これに代わる明らかな代替手段は、Maatkit ( http://www.maatkit.org/ ) の mk-parallel-dump です。これは、mysql 管理者であれば実際に確認する必要があります。これにより、mysqldump を使用して複数のテーブルまたはデータベースが並行してダンプされるため、ダンプにかかる合計時間が短縮されます。

レプリケートされたセットアップで実行している場合 (また、本番環境で重要なデータに MySQL を使用している場合、そうしない理由はありません)、専用のレプリケーション スレーブからダンプを取得すると、ロックの問題が発生するのを防ぐことができます。面倒を起こす。

次の明白な代替手段 (少なくとも Linux では) は、LVM スナップショットを使用することです。テーブルをロックし、ファイルシステムのスナップショットを作成し、テーブルを再度ロック解除できます。次に、そのスナップショットのマウントを使用して追加の MySQL を開始し、そこからダンプします。このアプローチについては、 http ://www.mysqlperformanceblog.com/2006/08/21/using-lvm-for-mysql-backup-and-replication-setup/ で説明しています。

于 2008-09-15T13:08:48.510 に答える
7

今、私はこの製品のマーケティング担当者のように聞こえ始めています. ここで質問に答えてから、ここで別の質問に答えました。

簡単に言えば、すべてのmysql要件について、webyogのsqlyog(あなたの場合はエンタープライズ)を試してください。バックアップをスケジュールするだけでなく、同期もスケジュールして、データベースをリモート サーバーに実際に複製できるようにします。

無料のコミュニティ エディションとエンタープライズ エディションがあります。私はあなたに後者をお勧めします.

于 2008-09-05T19:24:43.497 に答える
4

私は、ローカルの MySQL データベースとテーブルの高速オンライン ホット バックアップ ユーティリティである mysqlhotcopy を使用しています。私はそれでかなり満足しています。

于 2008-09-05T19:39:20.747 に答える
4

Percona の連中は、innobackup に代わるオープン ソースを作成しました ...

エクストラバックアップ

https://launchpad.net/percona-xtrabackup/

XtraDB に関するこの記事を読んで ください http://www.linux-mag.com/cache/7356/1.html

于 2009-07-08T09:54:37.860 に答える
3

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/gzips/encrypts するだけの Web バックアップ部分もあります。これはかなり小さなサイトなので、Web バックアップは 20MB をはるかに下回り、問題なく GMail アカウントに送信できます (MySQL ダンプは小さく、約 300KB 圧縮されています)。これは非常に基本的なものであり、あまりうまく拡張できません。cronを使用して週に1回実行します。

長いスクリプトを回答に入れる方法がよくわからないので、コードブロックとして押し込みます..

#!/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()
于 2008-09-06T09:22:23.933 に答える
3

現在のオフライン バックアップ スキームをMySQL レプリケーションで補うことができます。

その後、ハードウェアに障害が発生した場合は、マシンを交換するだけです。障害をすばやく見つければ、ユーザーはダウンタイムやデータ損失にさえ気付かないでしょう。

于 2008-09-06T03:54:24.317 に答える
2

「--single-transaction --skip-lock-tables」オプションを使用して、mysqldump を介して、ロック (ダウンタイム) なしで InnoDB データベース/テーブルの完全なダンプを作成できます。毎週のスナップショットと毎日/毎時のバイナリ ログの増分を作成するのに適しています(#バイナリ ログを使用して増分バックアップを有効にする)。

于 2008-10-23T07:56:01.293 に答える
1

これはLinuxシェルにとってかなり堅実なソリューションです。私はそれを何年も使用しています:

http://sourceforge.net/projects/automysqlbackup/

  • ローリングバックアップを実行します:毎日、毎月、毎年
  • たくさんのオプション
于 2009-09-11T15:14:48.370 に答える
1

@ジェイク、

情報をありがとう。現在、商用版のみがバックアップ機能を備えているようです。

まともなバックアップを行うためにMySQLに組み込まれているものはありませんか?

公式のMySQLページでは、「更新されていない限り、ファイルをコピーできます」などの推奨事項さえあります...

于 2008-09-05T19:29:29.023 に答える
1

mysql データベース フォルダの単純なバックアップの問題は、バックアップ中に書き込みロックを行わない限り、バックアップの一貫性が必ずしも保たれないことです。

すべてのデータベースを反復処理するスクリプトを実行し、それぞれに対して mysqldump と gzip を実行してバックアップ フォルダーに保存し、そのフォルダーをテープにバックアップします。

ただし、夜間のダンプは完全なダンプであるため、これは増分バックアップなどがないことを意味します。しかし、フル バックアップからの復元は、増分からの復元よりもはるかに高速なプロセスになるため、これは良いことであると私は主張します。完全な復元を行うことができます。

いずれの場合でも、どのバックアップ プランを使用する場合でも、必ず試用版の復元を実行して機能することを確認し、復元にかか​​る時間を把握し、実行する必要がある手順を正確に把握してください。

于 2008-09-06T06:44:33.610 に答える
1

mysql サーバーの増分バックアップまたは連続バックアップを実行する正しい方法は、バイナリ ログを使用することです。

まず、すべてのテーブルをロックするか、サーバーを停止します。mysql dump を使用してバックアップを作成するか、単にデータ ディレクトリをコピーします。これは一度だけ、または完全バックアップが必要なときにいつでも行う必要があります。

サーバーを再起動する前に、バイナリ ログが有効になっていることを確認してください。

増分バックアップを作成するには、サーバーにログインして FLUSH LOGS コマンドを発行します。次に、最後に閉じたバイナリ ログ ファイルをバックアップします。

すべての innodb テーブルがある場合は、 --single-transaction オプションを指定して inno hot backup (無料ではない) または mysqldump を使用する方が簡単です (トランザクションを処理するには、多くのメモリが必要です)。

于 2008-09-15T15:32:08.463 に答える
1

バイナリ ログはおそらく増分バックアップを行うための正しい方法ですが、永続的なストレージとしてバイナリ ファイル形式を信頼できない場合は、ここで増分バックアップを行うための ASCII の方法を使用します。

mysqldump は悪い形式ではありません。主な問題は、テーブルを 1 つの大きな行として出力することです。次の単純な sed は、レコードの境界に沿って出力を分割します。

mysqldump --opt -p | sed -e "s/,(/,\n(/g" > database.dump

結果として得られるファイルは、非常に diff に適したものであり、私はそれらを標準の SVN リポジトリにかなりうまく保存しています。これにより、最後のバージョンが中断され、先週のバージョンが必要な場合に、バックアップの履歴を保持することもできます。

于 2008-09-15T15:40:45.870 に答える
0

@ダニエル、

それでも興味がある場合は、Paul Galbraith によって共有された新しい (私にとっては新しい) ソリューションあります。

innobackupと組み合わせて使用 ​​すると、バックアップ中のダウンタイムなしで、夜間のバックアップの作成にうまく機能しました

詳細については、ポールのブログをご覧ください。

于 2008-09-17T18:18:44.037 に答える
0

トランザクションのロールバックについて話しているように聞こえます。

必要なものに関して言えば、すべての履歴クエリを含むログがある場合、それは既にバックアップではありませんか? 基本的に DB ログ内のすべての情報の冗長コピーである増分バックアップが必要なのはなぜですか?

もしそうなら、mysqldump を使用して時々バックアップを行ってみませんか?

于 2008-12-29T06:08:06.373 に答える