zoukankan      html  css  js  c++  java
  • MySQL备份与恢复

    一、备份与恢复

    MySQL备份与恢复
        备份
            备份方式
                是否停业务
                    冷备:停掉业务或DB进行备份(copy、rsync)
                    热备:不停业务的情况下进行备份
                        逻辑备份:导出SQL脚本进行备份
                            mysqldump:只支持单线程工作
                            mysqlpump:并行的最小粒度是单个数据库对象,对于每张表的导出只能是单个线程的
                            mydumper:支持对单表多个线程备份,参数-r
                            select into outfile
                        物理备份:通过拷贝文件进行备份
                            xtrabackup+binlog
                是否拷贝所有数据
                    全量备份:某一时刻整个数据库快照
                    增量备份:首次增量基于全量,后续增量可选择基于全量/增量
                保存位置
                    本地备份
                    远程备份
            备份原理
                mysqldump、mysqlpump、mydumper、xtrabackup备份原理
                InnoDB Crash Recovery
                    MySQLD Crash Recovery和InnoDB Crash Recovery的区别
                    redo大小调整:5.6以上直接修改my.cnf;5.6以下在apply-log前修改backup-my.cnf中的innodb_log_file%
                DML、DDL操作对备份的影响
                    DML操作可能导致mysqldump、mysqlpump备份的non-InnoDB表不一致
                    DDL操作可能导致InnoDB表开启一致性快照事务之后,如果表结构定义发生改变,事务将无法对该表执行查询
            备份方案选择
                数据量小:逻辑备份
                数据量大:xtrabackup+binlog,日常备份使用方案
        恢复
            备份时刻恢复
                物理备份->copy-back;逻辑备份->mysql、myloader、source
            任意时间点恢复
                binlog2sql实现对误操作的闪回
                全备+mysqlbinlog
                高级技术
                    原始节点做master,恢复节点做slave
                    copy binlog 2 relay-log利用sql_thread应用日志
                    binlog伪装成master,利用io_thread读取日志恢复
    View Code


    对于数据量超大的情况,建议结合Delayed Replication。其实最好是做分库分表,控制单实例的大小●-●

    二、备份参考

    2.1、txt、csv导出导入

    1、备份生成文本
    1.1、mysqldump -T
    mysqldump -T 批量导出表结构 tablename.sql(对应逻辑show create table)和数据文件 tablename.txt(对应逻辑select into outfile)
    mysqldump -h127.0.0.1 -P3306 -umydba -p123456 --skip-lock-tables sbtest sbtest1 -T /tmp/
    1.2select into outfile
    mysql> select * from sbtest.sbtest1 into outfile '/tmp/sbtest1.csv';
    注意上面两种方式目标路径要和 secure_file_priv 变量一致,生成的数据文件不包含列名
    
    2、文本文件导入
    2.1、mysqlimport
    通过向服务器发送LOAD DATA INFILE语句来实现,可以使用--local选项使 mysqlimport 从客户端主机(而不是mysql server主机)读取数据文件
    mysqlimport -h192.168.18.135 -P3306 -umydba -p123456 sbtest /tmp/sbtest1.csv
    mysqlimport -h192.168.18.135 -P3306 -umydba -p123456 --local sbtest /tmp/sbtest1.csv
    要使用local子句,server端需开启 local_infile(与secure_file_priv无关);mysqlimport client端使用 --local[=1],mysql client端使用 --local-infile[=1] 启用local data loading。客户端尽量避免使用LOCAL子句
    https://dev.mysql.com/doc/refman/8.0/en/load-data-local.html
    binlog_format=row,写到binlog中时内部把load data语句转换为了row格式的insert
    2.2、LOAD DATA INFILE
    mysql> load data infile '/tmp/sbtest1.csv' into table sbtest.sbtest1;
    load data infile需要开启 secure_file_priv
    View Code

    2.2、mysqldump

    1、默认选项(--opt)
    mysqldump默认备份表结构&触发器&视图 + 数据;mysqldump默认会备份mysql库,不会备份information_schema、performance_schema、sys库
    LOCK TABLES `sbtest1` READ /*!32311 LOCAL */,`sbtest2` READ /*!32311 LOCAL */,`sbtest3` READ /*!32311 LOCAL */,`sbtest4` READ /*!32311 LOCAL */,`sbtest5` READ /*!32311 LOCAL */
    ...
    SELECT /*!40001 SQL_NO_CACHE */ * FROM `sbtest1`
    SELECT /*!40001 SQL_NO_CACHE */ * FROM `sbtest2`
    ...
    UNLOCK TABLES
    备份开始对所有的表加锁,直到备份完成才释放
    
    2、推荐选项
    mysqldump --single-transaction --master-data=2 
    
        1、FLUSH /*!40101 LOCAL */ TABLES:强制刷新表缓存到磁盘并关闭表
        2、FLUSH TABLES WITH READ LOCK:对整个实例加全局读锁
        3、SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ:在session级别修改隔离级别为RR
        4、START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */:开启一个一致性快照事务,需在RR隔离级别
        5、SHOW VARIABLES LIKE 'gtid\_mode':查看是否开启GTID
        6、SELECT @@GLOBAL.GTID_EXECUTED:如果开启GTID则查看当前的事务GTID集合
        7、SHOW MASTER STATUS:查看当前数据的binlog pos
        8、UNLOCK TABLES:释放全局读锁
        9、SHOW DATABASES
            10、DBNAME1
                11、SHOW CREATE DATABASE IF NOT EXISTS `dbname1`
                12、SAVEPOINT sp:设置一个保存点(回滚点)
                13、show tables
                    14、show table status like 'tbname1'
                    15、SET SESSION character_set_results = 'binary'
                    16、show create table `tbname1`
                    17、SET SESSION character_set_results = 'utf8'
                    18、show fields from `tbname1`
                    19、SELECT /*!40001 SQL_NO_CACHE */ * FROM `tbname1`
                    20、SET SESSION character_set_results = 'binary'
                    21、SHOW TRIGGERS LIKE 'tbname1'
                    22、SET SESSION character_set_results = 'utf8'
                    23、ROLLBACK TO SAVEPOINT sp:释放select产生的MDL锁
                    24、参照tbname1操作库下的其他表
                25、RELEASE SAVEPOINT sp
            26、参照DBNAME1操作其他库
    
    --master-data:change master to、--lock-all-tables
    --single-transaction:RR、WITH CONSISTENT SNAPSHOT
    UNLOCK TABLE~SELECT * FROM 之间如果对non-InnoDB表进行DML操作,会导致备份出来的数据与show master status不一致
    START TRANSACTION WITH CONSISTENT SNAPSHOT~SELECT * FROM 之间如果有DDL操作,事务将无法查询数据(5.7.19)
    SAVEPOINT sp~SELECT * FROM 之间如果有DDL操作,事务将无法查询数据(8.0.18)
    
    3、mysqldump tips
    # 导出结构(表&触发器&视图、事件、存储过程&函数)
    mysqldump -h127.0.0.1 -P3306 -umydba -p123456 -dER sbtest > /tmp/mysqldump/sbtest_schema.sql
    # 导出数据,不加锁
    mysqldump -h127.0.0.1 -P3306 -umydba -p123456 -t --skip-triggers --skip-lock-tables sbtest > /tmp/mysqldump/sbtest_data.sql
    mysqldump -h127.0.0.1 -P3306 -umydba -p123456 -t --skip-triggers --skip-lock-tables sbtest sbtest1 sbtest2 sbtest3> /tmp/mysqldump/sbtest_tablelist_data.sql
    # 导出结构(表&触发器&视图、事件、存储过程&函数) + 数据,不加锁
    mysqldump -h127.0.0.1 -P3306 -umydba -p123456 -ER --skip-lock-tables sbtest > /tmp/mysqldump/sbtest_all.sql
    mysqldump -h127.0.0.1 -P3306 -umydba -p123456 -ER --skip-lock-tables -A > /tmp/mysqldump/all.sql
    mysqldump -h127.0.0.1 -P3306 -umydba -p123456 -ER --skip-lock-tables -B db1 db2 > /tmp/mysqldump/dblist_all.sql
    # 参数说明
    -n, --no-create-db:Suppress the CREATE DATABASE ... IF EXISTS statement that normally is output for each dumped database if --all-databases or --databases is given
    -t, --no-create-info:Don not write table creation info
    -d, --no-data: No row information
    -R, --routines:Dump stored routines (functions and procedures, Defaults to off)
    -E, --events:Dump events(Defaults to off)
    --triggers:Dump triggers for each dumped table.(Defaults to on; use --skip-triggers to disable.)
    -f, --force:Continue even if we get an SQL error
    View Code

    2.3、mydumper

    1、mydumper安装
    wget https://github.com/maxbube/mydumper/releases/download/v0.9.5/mydumper-0.9.5-2.el7.x86_64.rpm
    yum localinstall mydumper-0.9.5-2.el7.x86_64.rpm
    
    2、默认选项
    mydumper -S /data/mysql3306/run/mysqld.sock -u mydba -p 123456 -o /tmp/mydumper/
    mydumper默认备份表结构&视图 + 数据;mydumper默认会备份mysql、sys库,不会备份information_schema、performance_schema库
    
        1、连接目标数据库
        2、通过show processlist来判断是否有长语句(Query状态),根据参数long-query-guard和kill-long-queries决定退出或杀掉长语句
        3、主线程flush tables with read lock;start transaction with consistent snapshot
        4、主线程读取当前时间点的二进制日志文件名和日志写入的位置并记录在metadata文件中,以供即时点恢复使用
        5、创建dump线程,缺省为4个,start transaction with consistent snapshot
        6、确定候选表,根据类别分别插入non_innodb_table、innodb_tables以及table_schemas链表
        7、将候选表通过g_async_queue_push加入任务队列(队列最后元素是thread shutdown),由dump线程从队列中读取表信息并执行数据导出 
        8、备份完non_innodb_table后立即unlock tables解锁,以减少锁定时间
        9、等待dump InnoDB tables完成
    
    runtime < long-query-guard,正常备份
    runtime > long-query-guard, 如果指定-K(--kill-long-queries),则kill长语句;如果没有指定-K,则退出mydumper
    
    3、mydumper tips
    # 备份结构(表&视图、触发器、事件、存储过程&函数)
    mydumper -S /data/mysql3306/run/mysqld.sock -u mydba -p 123456 -x '^(?!(mysql.|sys.))' -dGER -c -o /tmp/mydumper/
    # 备份数据
    mydumper -S /data/mysql3306/run/mysqld.sock -u mydba -p 123456 -x '^(?!(mysql.|sys.))' -m -c -o /tmp/mydumper/
    # 备份结构(表&视图、触发器、事件、存储过程&函数) + 数据
    mydumper -S /data/mysql3306/run/mysqld.sock -u mydba -p 123456 -x '^(?!(mysql.|sys.))' -GER -c -o /tmp/mydumper/
    # 备份指定表,不加锁
    mydumper -S /data/mysql3306/run/mysqld.sock -u mydba -p 123456 -B sbtest -T sbtest1,sbtest2,sbtest3 -k -c -o /tmp/mydumper/
    -d不备份数据、-G备份triggers、-E备份events、-R备份routines、-m不备份库表结构、-c压缩文件、-o指定输出路径、-k不加读锁
    # 还原
    myloader -S /data/mysql3306/run/mysqld.sock -u mydba -p 123456 -v 3 -e -o -d /tmp/mydumper/ >/tmp/myloader.log 2>&1
    -v显示导入详细信息,-e导入语句记录binlog,-o覆盖已有对象。备份时指定-c,在导入时并不需要我们手动gunzip/指定-c,myloader会处理
    
    4、mysql用户信息
    建议使用PT工具中的./pt-show-grants生成用户信息,尤其在跨大版本的情况下
    ./pt-show-grants -h127.0.0.1 -P3306 -umydba -p123456 >/tmp/mysql_user.sql
    此命令会将数据库账户、密码、权限完整的备份出来。建议检查生成的.sql文件,删除不安全的账户信息(''@''之类的)
    View Code

    2.4、XtraBackup

    Percona XtraBackup 8.0 专门用于 MySQL 8.0的版本;Percona XtraBackup 2.4 专门用于5.6/5.7的版本
    innobackupex 在8.0中已经被移除,建议全部采用 xtrabackup 命令备份数据库

    1、推荐选项
    # 备份-backup
    xtrabackup --defaults-file=/data/mysql3306/my3306.cnf --backup --host=127.0.0.1 --port=3306 --user=mydba --password=123456 --target-dir=/tmp/xtrabackup/
    # 还原-step1-prepare
    xtrabackup --prepare --target-dir=/tmp/xtrabackup/
    # 还原-step2-copy-back
    xtrabackup --defaults-file=/data/mysql6306/my6306.cnf --copy-back --target-dir=/tmp/xtrabackup/
    
    2、xtrabackup全备过程
    
        1、根据命令行参数,连接到MySQL
        2、读取配置文件,找到相应的数据和日志文件位置
        3、start xtrabackup_log:以读写模式打开xtrabackup_logfile并读取redo log,检查当前checkpoint点,从当前checkpoint点位置开始拷贝redo log,同时持续扫描redo log,有新产生的redo log数据就拷贝到xtrabackup_logfile文件中
        4、copy ./ibdata1、.ibd
        5、FLUSH NO_WRITE_TO_BINLOG TABLES、FLUSH TABLES WITH READ LOCK
        6、copy non-InnoDB tables .MYD、.MYI、.frm、misc files和InnoDB tables .frm、misc files  --8.0版本InnoDB表没有.frm文件
        7、Get binary log file position 并写到xtrabackup_binlog_info文件中
        8、FLUSH NO_WRITE_TO_BINLOG BINARY LOGS  --8.0添加,copy newest binlog
        9、FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS  --刷新redo log buffer到磁盘
        10、Stopping log copying thread
        11、UNLOCK TABLES
        12、备份收尾工作:生成backup-my.cnf、xtrabackup_info等文件,完成后退出备份进程
    
    --kill-long-query-type=all|select
    --kill-long-queries-timeout=seconds,在执行FTWRL时碰到阻塞,等待该参数指定的秒数之后,如果仍然有查询在运行,则执行kill掉这些查询
    View Code

    三、坑坑洼洼

    1、source dump.sql的数据不能复制到从库
    GTID环境,使用mysqldump --single-transaction --master-data=2 -B dbname >xxx.sql,然后source xxx.sql到另一组主从复制环境的主库,发现主库有数据,从库却没有数据
    原因:备份选项没有指定--set-gtid-purged=off,该选项影响是否在输出文件添加 set @@global.gtid_purged、set @@session.sql_log_bin=0语句
    如果备份用于还原数据/搭建从库,--set-gtid-purged=on(输出带set gtid_purged,sql_log_bin=0),还原过程不产生binlog
    如果备份用于新主,--set-gtid-purged=off(输出不带set gtid_purged,sql_log_bin=0),还原过程产生binlog
    GTID环境,没有指定--set-gtid-purged参数时(默认为AUTO),备份输出文件会加上set语句,load备份不会记录binlog,因此从库就获取不到数据啦●-●
    2、mysqldump对MyISAM表没做一致性备份
    mysqldump --single-transaction --master-data=2 -B dbname >xxx.sql
    UNLOCK TABLE~SELECT * FROM 之间如果对non-InnoDB表进行DML操作,会导致备份出来的数据与show master status不一致
    START TRANSACTION WITH CONSISTENT SNAPSHOT~SELECT * FROM 之间如果有DDL操作,事务将无法查询数据(5.7.19)
    SAVEPOINT sp~SELECT * FROM 之间如果有DDL操作,事务将无法查询数据(8.0.18)
    3、XtraBackup只备份InnoDB表也要加FTWRL
    XtraBackup借助InnoDB Crash Recovery机制来备份InnoDB表,对于MyISAM的备份,还得施加FTWRL以保证一致性备份。同时,XtraBackup是在施加FTWRL期间备份InnoDB表对应的.frm文件。可以通过innobackupex --include=databasename.tablename/xtrabackup --tables=databasename.tablename >back.log 2>&1查看日志输出
    扩展阅读:MySQL备份可能遇到的坑 

  • 相关阅读:
    (转)C3P0连接池配置和实现详解
    (转)jquery插件Validate的使用
    二叉树和翻转二叉树
    利用@media screen实现网页布局的自适应
    (转)防止SQL注入的五种方法
    java代码规范
    Java泛型-类型擦除
    js中的isNaN()
    (转)sublime 一些常用功能和快捷键
    (转)java中不常见的关键字:strictfp,transient
  • 原文地址:https://www.cnblogs.com/Uest/p/9098750.html
Copyright © 2011-2022 走看看