细致的备份让人可以安心睡觉

为什么要备份

我们第一点想到的是灾难恢复,即使是对技术不感兴趣的领导,也会很自然的想到这一点, 他们经常会担忧万一出了事故,数据是否安全,系统是否能够即时从事故中恢复。 对于我们开发人员来说,备份还有一个很重要的作用就是用于开发和测试,我们开发人员经常需要使用最新的生产环境数据来更新测试服务器, 我们需要定期把备份文件还原到测试 服务器以供开发和测试。

备份之前的信息收集

在备份之前我们需要尽可能地收集相关的信息,比如服务器的版本,有哪些定时任务在操作数据库, 有哪些应用和数据库关联等等, 将这些信息列一个清单以方便以后查阅对照. 对于数据库本身的信息, 我们需要确认数据库的大小,使用了那些存储引擎等。我们可以使用下面的 sql 查询需要的数据库信息, 以方便对数据库进行审核:

  SELECT table_schema, engine, 
	     ROUND(SUM(data_length+index_length)/1024/1024) AS total_mb,
		 ROUND(SUM(data_length)/1024/1024) AS data_mb,
		 ROUND(SUM(index_length)/104/1024) AS index_mb,
		 COUNT(*) as tables
  FROM information_schema.tables
  GROUP BY table_schema, engine
  ORDER BY 3 DESC;
  

在我本地执行结果如下:

+--------------------+--------------------+----------+---------+----------+--------+
| table_schema       | engine             | total_mb | data_mb | index_mb | tables |
+--------------------+--------------------+----------+---------+----------+--------+
| meihe              | InnoDB             |       63 |      44 |      190 |     86 |
| mysql              | InnoDB             |       10 |      10 |        0 |      9 |
| peatio_development | InnoDB             |        1 |       1 |        4 |     35 |
| mysql              | MyISAM             |        1 |       1 |        1 |     22 |
| information_schema | MEMORY             |        0 |       0 |        0 |     51 |
| mysql              | CSV                |        0 |       0 |        0 |      2 |
| sys                | InnoDB             |        0 |       0 |        0 |      1 |
| performance_schema | PERFORMANCE_SCHEMA |        0 |       0 |        0 |     87 |
| information_schema | InnoDB             |        0 |       0 |        0 |     10 |
| sys                | NULL               |     NULL |    NULL |     NULL |    100 |
+--------------------+--------------------+----------+---------+----------+--------+
10 rows in set, 48 warnings (0.32 sec)

我们发现数据库使用了多种存储引擎,有的使用 InnoDB, 有的使用 MyISAM, 不同的引擎会对我们的备份参数产生影响,比如锁策略。

我们要备份的对象长什么样

在备份前,我们需要再做一些额外的工作,比如熟悉 my.cnf, mysql 数据库文件的目录结构等.

my.cnf 是 mysql 的配置文件, 网上有很多样本文件,这里不详细贴出来了,我们列举下其中和备份比较相关的选项:

  • datadir 是所有数据库, 表, InnoDB, 数据, 服务器日志和二进制日志文件在文件系统上的存储目录.

  • basedir 是 MySQL 的安装目录在文件系统中的位置.

  • innodb_data_file_path 这个变量确定单个 InnoDB 数据文件的位置以及它们的大小和行为.

  • innodb_file_per_table 当 innodb_file_per_table 被激活时,所有使用 InnoDB 存储引擎创建的表都将创建自己的表空间.

  • innodb_flush_log_at_trx_commit 默认值是 1, 意味着每次提交后都把日志缓冲区的内容写到 InnoDB 日志文件中, 并在该日志文件上执行清除磁盘操作. 设置为 2, 则意味着将以每秒一次的松散时间隔将日志缓冲区中的内容写到 InnoDB 日志文件中,不推荐使用 0.

  • server_id 给 MySQL 拓扑中的每一台 slave 服务器设置一个唯一的 server_id 值将确保复制数据能被正确应用.

  • log_bin 激活二进制日志

  • log_bin_index 文件保留二进制日志名并且以之为索引

  • binlog_format 使用这个变量可以控制 MySQL 所使用的二进制日志类型

  • binlog_cache_size 这个缓存用于在事物过程中保存二进制日志的变化

  • binlog_stmt_cache_size 这个变量为二进制日志指定缓冲区大小

  • relay_log 在 SQL 线程把被复制的数据库变化应用到从服务器之前, MySQL 使用一个编了号的被称为中继日志的文件集合来保留它们.

  • relay_log_index 这个变量保留所有中继日志的名称以便快速查找.

  • slave_skip_errors 当指定了 slave_skip_errors 时, 复制错误代码可以被自动跳过.

  • slave_exec_mode 它有两个有效值: IDEMPOTENT 和 STRICT. 这个变量用于解析复制冲突和检查错误.

  • log_slave_updates 当把此变量设置为真并把二进制日志文件打开时, slave 服务器主机将把所有被复制的变化写到自己的二进制日志文件中.

备份的分类

1.物理备份和逻辑备份

物理备份 : 它是直接拷贝mysql的存储在磁盘上的数据文件。这种备份使用的空间大,特别是innodb存储数据使用的表空间,因为表空间分配大小是按一定的比例增长,所以存在没有使用的空间。但是恢复时使用的时间少。
逻辑备份 : 将数据以sql语句的形式导出。导出数据和恢复数据所用的时间多,但占用空间小。

2.热备、温备、冷备

热备 : 对线上环境不见任何锁,不影响线上任何数据库操作。
温备 : 在备份之间要获取锁,并施加锁。在加锁期间会影响某些操作。
冷备 : 备份之前停掉服务器,然后在备份。

备份工具的选择和使用

作为一名开发人员,最熟悉的备份工具可能就是 mysqldump 了, 在项目的初期, 我经常使用 mysqldump 同步一些 staging 环境的数据到本地。

mysqldump

1. 最简单的方式

$ mysqldump -uroot --all-databases > backup.sql  

mysqldump 命令产生了一个 ASCII 转储文件,保存为 backup.sql

2. 远程备份

$ mysqldump -u<user> -p<password> --host db-server --compress --all-database > backup.sql

3. 使用 SSH

使用带有密钥认证的标准 SSH, 可以使备份自动地通过网络进行传输. 在下面的例子中, SSH 连接已经被简化到了只需要使用别名即可进行备份:
$ cat $HOME/.ssh/config

Host backup
IdentityFile /home/ubuntu/.ssh/admin.pem
User ubuntu
HostName db_server.com


$ mysqldump --all-database \| ssh backup "cat -> backup.sql"

4. 使用 nc

通过利用 netcat(nc), 可以在一个给定端口上直接通过 TCP/UDP 来传递文件.
$ ssh backup "nc -l 9306" > /mysql/backup/nc/first.sql" & mysqldump -all-database | nc backup 9306

在项目开始的阶段,我们使用 mysqldump 来备份数据库是合适的,但是如果项目发展的很好,数据库越来越庞大时,我们就需要更加专业的工具来备份数据库。

使用 XtraBackup

官网: https://www.percona.com/software/mysql-database/percona-xtrabackup Xtrabackup是由percona提供的mysql数据库备份工具,据官方介绍其特点如下:

  1. Fast and reliable database backups (e.g. hot backup, incremental backups, bacula backup, etc.)
  2. Uninterrupted transaction processing during backups
  3. Savings on disk space and network bandwidth with better compression
  4. Automatic backup verification
  5. Higher uptime due to faster restore time
  6. Point-in-time recovery

Xtrabackup中主要包含两个工具:

xtrabackup:是用于热备份innodb, xtradb表中数据的工具,不能备份其他类型的表,也不能备份数据表结构;

innobackupex:是将xtrabackup进行封装的perl脚本,提供了备份myisam表的能力。

常用命令

默认情况下备份是在指定的 backup-dir 目录下创建一个时间戳目录,然后备份集写入到时间目录下:

$ innobackupex --host=127.0.0.1 --port=3306 --user=root --password=123456 --defaults-file=/etc/my.cnf backup-dir

也可以通过流方式输出到标准输出:

$ innobackupex --host=127.0.0.1 --port=3306 --user=root --password=123456 --defaults-file=/etc/my.cnf --stream=tar backup-dir | gzip > backup.tar.gz

其它备份工具

MySQL 还有其它一些备份工具,比如 MySQL 企业备份(MEB), mydumper, 可以在适当的时间研究下.