MySQL备份恢复
Posted 辛辛之火可以开源
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL备份恢复相关的知识,希望对你有一定的参考价值。
备份恢复示例:
|
逻辑备份恢复示例(完全备份+增量备份) |
逻辑备份
=======
1. 检查数据库状态和确认数据库数据:
[root@cephclient ~]# mysql -ursun -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 13
Server version: 8.0.19-cluster MySQL Cluster Community Server - GPL
Copyright (c) 2000, 2020, Oracle and/or its affiliates.
All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> status;
--------------
mysql Ver 8.0.19-cluster for Linux on x86_64 (MySQL Cluster Community Server - GPL)
Connection id: 13
Current database:
Current user: rsun@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 8.0.19-cluster MySQL Cluster Community Server - GPL
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: utf8mb4
Conn. characterset: utf8mb4
UNIX socket: /var/lib/mysql/mysql.sock
Binary data as: Hexadecimal
Uptime: 22 min 13 sec
Threads: 2 Questions: 238 Slow queries: 0 Opens: 263 Flush tables: 3 Open tables: 183 Queries per second avg: 0.178
--------------
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.01 sec)
mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_mysql |
+---------------------------+
| columns_priv |
| component |
| db |
| default_roles |
| engine_cost |
| func |
| general_log |
| global_grants |
| gtid_executed |
| help_category |
| help_keyword |
| help_relation |
| help_topic |
| innodb_index_stats |
| innodb_table_stats |
| ndb_binlog_index |
| password_history |
| plugin |
| procs_priv |
| proxies_priv |
| role_edges |
| server_cost |
| servers |
| slave_master_info |
| slave_relay_log_info |
| slave_worker_info |
| slow_log |
| tables_priv |
| test |
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
| user |
+---------------------------+
35 rows in set (0.00 sec)
mysql> create table rsun_test as select * from server_cost;
Query OK, 6 rows affected (0.02 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> insert into rsun_test select * from rsun_test;
Query OK, 6 rows affected (0.02 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> select count(*) from rsun_test;
+----------+
| count(*) |
+----------+
| 12 |
+----------+
1 row in set (0.01 sec)
mysql> insert into rsun_test select * from rsun_test;
Query OK, 12 rows affected (0.00 sec)
Records: 12 Duplicates: 0 Warnings: 0
mysql> select count(*) from rsun_test;
+----------+
| count(*) |
+----------+
| 24 |
+----------+
1 row in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
《注释》:
使用`date +%y%m%d`
Example: mkdir `date +%y%m%d`
tar cfvz /tmp/bak.`date +%y%m%d`.tar.gz /etc
YmdHM代表年月日时分,可以通过date --hlep查看哪些字母代表什么
注意:`这个符号是键盘上~,而不是'。
重要说明点:
那个日期$(date +%Y%m%d)的date命令和后边的日期格式的+号之前有一个空格。
直接连写生成不了日期。
2. 完全备份:
[root@cephclient data]# mysqldump -uroot -p --all-databases --flush-logs --single-transaction --master-data=2 --log-error=/data/full_backup_log`date +%y%m%d%H%M`.log > /data/full_backu`date +%y%m%d%H%M`.sql
Enter password:
[root@cephclient data]# ls
full_backu2102210219.sql full_backup_log2102210219.log
vim full_backu2102210219.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='binlog.000019', MASTER_LOG_POS=155;
备份文件里记录了二进制日志的位置。
3. 增量数据:
mysql> create table 999test as select * from slave_master_info;
Query OK, 0 rows affected (0.12 sec)
Records: 0 Duplicates: 0 Warnings: 0
4. 检查此时的二进制日志的位置:
从备份文件里边记录的位置到我们此时的位置,即为增量的部分。
mysql> show master status;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000019 | 3956 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
5. 增量备份:
[root@docker-test ~]# mysqlbinlog --start-position=155 --stop-position=3956 /var/lib/mysql/binlog.000019 > /data/incremental_backup`date +%y%m%d%H%M`.sql
逻辑恢复(恢复到另外一个数据库)
===========================
1. 检查数据库当前数据:
mysql> use mysql
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_mysql |
+---------------------------+
| 123test |
| aaa |
| columns_priv |
| component |
| db |
| default_roles |
| engine_cost |
| func |
| general_log |
| global_grants |
| gtid_executed |
| help_category |
| help_keyword |
| help_relation |
| help_topic |
| innodb_index_stats |
| innodb_table_stats |
| ndb_binlog_index |
| newtest |
| password_history |
| plugin |
| procs_priv |
| proxies_priv |
| role_edges | |
| server_cost |
| servers |
| slave_master_info |
| slave_relay_log_info |
| slave_worker_info |
| slow_log |
| tables_priv |
| test |
| test123 |
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
| user |
+---------------------------+
39 rows in set (0.00 sec)
2. 获取数据库备份:
[root@docker-test mysqldump]# scp 192.168.189.77:/data/* ./
root@192.168.189.77's password:
full_backu2102210222.sql 100% 1012KB 18.8MB/s 00:00
full_backup_log2102210222.log 100% 0 0.0KB/s 00:00
incremental_backup2102210231.sql 100% 5749 2.1MB/s 00:00
100% 5749 4.1MB/s 00:00
[root@docker-test mysqldump]# ls
full_backu2102210222.sql full_backup_log2102210222.log incremental_backup2102210231.sql
[root@docker-test mysqldump]#
3. 首先恢复完全备份文件:
[root@docker-test mysqldump]# mysql -uroot -p < full_backu2102210222.sql
Enter password:
mysql> show tables;
+---------------------------+
| Tables_in_mysql |
+---------------------------+
| 123test |
| aaa |
| columns_priv |
| component |
| db |
| default_roles |
| engine_cost |
| func |
| general_log |
| global_grants |
| gtid_executed |
| help_category |
| help_keyword |
| help_relation |
| help_topic |
| innodb_index_stats |
| innodb_table_stats |
| ndb_binlog_index |
| newtest |
| password_history |
| plugin |
| procs_priv |
| proxies_priv |
| role_edges |
| rsun_test |
| server_cost |
| servers |
| slave_master_info |
| slave_relay_log_info |
| slave_worker_info |
| slow_log |
| tables_priv |
| test |
| test123 |
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
| user |
+---------------------------+
40 rows in set (0.00 sec)
4. 然后恢复增量备份文件:
[root@docker-test mysqldump]# mysql -uroot -p < incremental_backup2102210231.sql
Enter password:
mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_mysql |
+---------------------------+
| 123test |
| 999test |
| aaa |
| columns_priv |
| component |
| db |
| default_roles |
| engine_cost |
| func |
| general_log |
| global_grants |
| gtid_executed |
| help_category |
| help_keyword |
| help_relation |
| help_topic |
| innodb_index_stats |
| innodb_table_stats |
| ndb_binlog_index |
| newtest |
| password_history |
| plugin |
| procs_priv |
| proxies_priv |
| role_edges |
| rsun_test |
| server_cost |
| servers |
| slave_master_info |
| slave_relay_log_info |
| slave_worker_info |
| slow_log |
| tables_priv |
| test |
| test123 |
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
| user |
+---------------------------+
40 rows in set (0.00 sec)
物理备份恢复示例 |
物理备份
========
1. 完全关闭数据库:
mysql> shutdown;
Query OK, 0 rows affected (0.06 sec)
# systemctl stop mysqld
2. 在文件系统层级备份数据库所有文件:
# tar -cf mysql.tar /var/lib/mysql/*
物理恢复(恢复到另外一台机器)
===========================
1. 获取物理备份文件:
[root@docker-test lib]# scp 192.168.189.77:/var/lib/mysql.tar /var/lib/
root@192.168.189.77's password:
mysql.tar 100% 154MB 33.6MB/s 00:04
2. 恢复物理备份文件到/var/lib/mysql文件夹:
[root@docker-test lib]# tar xfv mysql.tar
[root@docker-test lib]# chown mysql mysql
or
[root@docker-test lib]# sudo mysql tar xfv mysql.tar
3. 启动数据库:
[root@docker-test lib]# systemctl start mysqld
[root@docker-test lib]# systemctl status mysqld
● mysqld.service - MySQL Server
Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor prese t: disabled)
Active: active (running) since Sun 2021-02-21 03:00:51 EST; 2s ago
Docs: man:mysqld(8)
http://dev.mysql.com/doc/refman/en/using-systemd.html
Process: 46778 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0 /SUCCESS)
Main PID: 46807 (mysqld)
Status: "Server is operational"
Tasks: 39
Memory: 398.3M
CGroup: /system.slice/mysqld.service
└─46807 /usr/sbin/mysqld
Feb 21 03:00:46 docker-test systemd[1]: Starting MySQL Server...
Feb 21 03:00:51 docker-test systemd[1]: Started MySQL Server.
[root@docker-test lib]#
4. 验证数据库恢复:
mysql> select * from rsun_test;
+------------------------------+------------+---------------------+---------+---------------+
| cost_name | cost_value | last_update | comment | default_value |
+------------------------------+------------+---------------------+---------+---------------+
| disk_temptable_create_cost | NULL | 2021-02-17 22:30:23 | NULL | 20 |
| disk_temptable_row_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.5 |
| key_compare_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.05 |
| memory_temptable_create_cost | NULL | 2021-02-17 22:30:23 | NULL | 1 |
| memory_temptable_row_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.1 |
| row_evaluate_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.1 |
| disk_temptable_create_cost | NULL | 2021-02-17 22:30:23 | NULL | 20 |
| disk_temptable_row_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.5 |
| key_compare_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.05 |
| memory_temptable_create_cost | NULL | 2021-02-17 22:30:23 | NULL | 1 |
| memory_temptable_row_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.1 |
| row_evaluate_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.1 |
| disk_temptable_create_cost | NULL | 2021-02-17 22:30:23 | NULL | 20 |
| disk_temptable_row_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.5 |
| key_compare_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.05 |
| memory_temptable_create_cost | NULL | 2021-02-17 22:30:23 | NULL | 1 |
| memory_temptable_row_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.1 |
| row_evaluate_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.1 |
| disk_temptable_create_cost | NULL | 2021-02-17 22:30:23 | NULL | 20 |
| disk_temptable_row_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.5 |
| key_compare_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.05 |
| memory_temptable_create_cost | NULL | 2021-02-17 22:30:23 | NULL | 1 |
| memory_temptable_row_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.1 |
| row_evaluate_cost | NULL | 2021-02-17 22:30:23 | NULL | 0.1 |
+------------------------------+------------+---------------------+---------+---------------+
24 rows in set (0.00 sec)
附:官方文档 |
This section discusses a procedure for performing backups that enables you to recover data after several types of crashes:
Operating system crash
Power failure
File system crash
Hardware problem (hard drive, motherboard, and so forth)
The example commands do not include options such as --user
and --password
for the mysqldump and mysql client programs. You should include such options as necessary to enable client programs to connect to the MySQL server.
Assume that data is stored in the InnoDB
storage engine, which has support for transactions and automatic crash recovery. Assume also that the MySQL server is under load at the time of the crash. If it were not, no recovery would ever be needed.
For cases of operating system crashes or power failures, we can assume that MySQL's disk data is available after a restart. The InnoDB
data files might not contain consistent data due to the crash, but InnoDB
reads its logs and finds in them the list of pending committed and noncommitted transactions that have not been flushed to the data files. InnoDB
automatically rolls back those transactions that were not committed, and flushes to its data files those that were committed. Information about this recovery process is conveyed to the user through the MySQL error log. The following is an example log excerpt:
InnoDB: Database was not shut down normally.
InnoDB: Starting recovery from log files...
InnoDB: Starting log scan based on checkpoint at
InnoDB: log sequence number 0 13674004
InnoDB: Doing recovery: scanned up to log sequence number 0 13739520
InnoDB: Doing recovery: scanned up to log sequence number 0 13805056
InnoDB: Doing recovery: scanned up to log sequence number 0 13870592
InnoDB: Doing recovery: scanned up to log sequence number 0 13936128
...
InnoDB: Doing recovery: scanned up to log sequence number 0 20555264
InnoDB: Doing recovery: scanned up to log sequence number 0 20620800
InnoDB: Doing recovery: scanned up to log sequence number 0 20664692
InnoDB: 1 uncommitted transaction(s) which must be rolled back
InnoDB: Starting rollback of uncommitted transactions
InnoDB: Rolling back trx no 16745
InnoDB: Rolling back of trx no 16745 completed
InnoDB: Rollback of uncommitted transactions completed
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Apply batch completed
InnoDB: Started
mysqld: ready for connections
Establishing a Backup Policy
To be useful, backups must be scheduled regularly. A full backup (a snapshot of the data at a point in time) can be done in MySQL with several tools. For example, MySQL Enterprise Backup can perform a physical backup of an entire instance, with optimizations to minimize overhead and avoid disruption when backing up InnoDB
data files; mysqldump provides online logical backup. This discussion uses mysqldump.
Assume that we make a full backup of all our InnoDB
tables in all databases using the following command on Sunday at 1 p.m., when load is low:
shell> mysqldump --all-databases --master-data --single-transaction > backup_sunday_1_PM.sql
The resulting .sql
file produced by mysqldump contains a set of SQL INSERT
statements that can be used to reload the dumped tables at a later time.
This backup operation acquires a global read lock on all tables at the beginning of the dump (using FLUSH TABLES WITH READ LOCK
). As soon as this lock has been acquired, the binary log coordinates are read and the lock is released. If long updating statements are running when the FLUSH
statement is issued, the backup operation may stall until those statements finish. After that, the dump becomes lock-free and does not disturb reads and writes on the tables.
It was assumed earlier that the tables to back up are InnoDB
tables, so --single-transaction
uses a consistent read and guarantees that data seen by mysqldump does not change. (Changes made by other clients to InnoDB
tables are not seen by the mysqldump process.) If the backup operation includes non transactional tables, consistency requires that they do not change during the backup. For example, for the MyISAM
tables in the mysql
database, there must be no administrative changes to MySQL accounts during the backup.
Full backups are necessary, but it is not always convenient to create them. They produce large backup files and take time to generate. They are not optimal in the sense that each successive full backup includes all data, even that part that has not changed since the previous full backup. It is more efficient to make an initial full backup, and then to make incremental backups. The incremental backups are smaller and take less time to produce. The tradeoff is that, at recovery time, you cannot restore your data just by reloading the full backup. You must also process the incremental backups to recover the incremental changes.
To make incremental backups, we need to save the incremental changes. In MySQL, these changes are represented in the binary log, so the MySQL server should always be started with the --log-bin
option to enable that log. With binary logging enabled, the server writes each data change into a file while it updates data. Looking at the data directory of a MySQL server that has been running for some days, we find these MySQL binary log files:
-rw-rw---- 1 guilhem guilhem 1277324 Nov 10 23:59 gbichot2-bin.000001
-rw-rw---- 1 guilhem guilhem 4 Nov 10 23:59 gbichot2-bin.000002
-rw-rw---- 1 guilhem guilhem 79 Nov 11 11:06 gbichot2-bin.000003
-rw-rw---- 1 guilhem guilhem 508 Nov 11 11:08 gbichot2-bin.000004
-rw-rw---- 1 guilhem guilhem 220047446 Nov 12 16:47 gbichot2-bin.000005
-rw-rw---- 1 guilhem guilhem 998412 Nov 14 10:08 gbichot2-bin.000006
-rw-rw---- 1 guilhem guilhem 361 Nov 14 10:07 gbichot2-bin.index
Each time it restarts, the MySQL server creates a new binary log file using the next number in the sequence. While the server is running, you can also tell it to close the current binary log file and begin a new one manually by issuing a FLUSH LOGS
SQL statement or with a mysqladmin flush-logs command. mysqldump also has an option to flush the logs. The .index
file in the data directory contains the list of all MySQL binary logs in the directory.
The MySQL binary logs are important for recovery because they form the set of incremental backups. If you make sure to flush the logs when you make your full backup, the binary log files created afterward contain all the data changes made since the backup. Let's modify the previous mysqldump command a bit so that it flushes the MySQL binary logs at the moment of the full backup, and so that the dump file contains the name of the new current binary log:
shell> mysqldump --single-transaction --flush-logs --master-data=2 \
--all-databases > backup_sunday_1_PM.sql
After executing this command, the data directory contains a new binary log file, gbichot2-bin.000007
, because the --flush-logs
option causes the server to flush its logs. The --master-data
option causes mysqldump to write binary log information to its output, so the resulting .sql
dump file includes these lines:
-- Position to start replication or point-in-time recovery from
-- CHANGE MASTER TO MASTER_LOG_FILE='gbichot2-bin.000007',MASTER_LOG_POS=4;
Because the mysqldump command made a full backup, those lines mean two things:
The dump file contains all changes made before any changes written to the
gbichot2-bin.000007
binary log file or higher.All data changes logged after the backup are not present in the dump file, but are present in the
gbichot2-bin.000007
binary log file or higher.
On Monday at 1 p.m., we can create an incremental backup by flushing the logs to begin a new binary log file. For example, executing a mysqladmin flush-logs command creates gbichot2-bin.000008
. All changes between the Sunday 1 p.m. full backup and Monday 1 p.m. are written in gbichot2-bin.000007
. This incremental backup is important, so it is a good idea to copy it to a safe place. (For example, back it up on tape or DVD, or copy it to another machine.) On Tuesday at 1 p.m., execute another mysqladmin flush-logs command. All changes between Monday 1 p.m. and Tuesday 1 p.m. are written in gbichot2-bin.000008
(which also should be copied somewhere safe).
The MySQL binary logs take up disk space. To free up space, purge them from time to time. One way to do this is by deleting the binary logs that are no longer needed, such as when we make a full backup:
shell> mysqldump --single-transaction --flush-logs --master-data=2 \
--all-databases --delete-master-logs > backup_sunday_1_PM.sql
Note:
Deleting the MySQL binary logs with mysqldump --delete-master-logs can be dangerous if your server is a replication source server, because replicas might not yet fully have processed the contents of the binary log. The description for the PURGE BINARY LOGS
statement explains what should be verified before deleting the MySQL binary logs. See Section 13.4.1.1, “PURGE BINARY LOGS Statement”.
以上是关于MySQL备份恢复的主要内容,如果未能解决你的问题,请参考以下文章