xtrabackup可以在不加锁的情况下备份innodb数据表,不过此工具不能操作myisam。
innobackupex-1.5.1是一个脚本封装,它封装了xtrabackup,能同时处理innodb和myisam,但在处理myisam时需要加一个读锁。
一、完全备份与恢复
AN sql example of creating a database user with the minimum privileges required to full backups would be:
create user 'bkpuser'@'localhost' identified by 'xxxx'
grant reload ,lock tables,replication client on *.* to 'bkpuser'@'127.0.0.1';
flush privileges;
参数:
--defaults-file // 指定要备份的mysql实例的my.cnf文件,the only limitation is that it has to be the first option passed;并且在这个my.cnf中必须要有datadir等参数指明数据文件的路径!!
-host //数据库IP
-port //端口
-socket // unix/linux套接字连接mysql
--use-memory=4G // 此参数用来控制备份所使用到的内存大小,默认为100M! 一般与--apply-log一起使用,备份时指定了但好像没用到!!
--apply-log // 在数据库备份好后,这些备份的数据并不能立即用于恢复,因为这些刚备份的数据里包含了未提交的数据,需要回滚,oracle里称undo数据!也包括的已完成的事务在重做日志文件中并没有写入数据文件中,这些数据需要重做!oracle里称redo! 这个参数正是用于做这些事情,以保证数据文件的一致性!在数据库恢复之前,须先对备份的数据文件应用此参数!(innobackup会重现重做日志文件(redo log file)中的事务条目,重做已经提交的事务和回滚未提交的事务!)
--copy-back //把备份数据拷贝回server的datadir,它决定于my.cnf中的datadir参数,另外在恢复时datadir目录必须是空的,并且mysql数据库必须是shudown的!
--no-timestamp参数 //innobackupex --defaults-file=/etc/my.cnf --user=root --no-timestamp /tmp/backup/full
(使用--no-timestamp时,后面的这个full目录必须跟上且不能提前自己建立,它由innobackupex自动建立,否则会报innobackupex: Error: Failed to create backup directory /tmp/backup/full/: File exists at /usr/bin/innobackupex line 3899.)
--redo-only //在做增量恢复时,全备和增量备份的数据文件在恢复前必须先将在重做日志文件中的已提交的事务重做!此参数将会合并全备和增量备份的数据文件,但不包括最后一次增量备份的数据文件!(--redo-only should be used when merging all incrementals except the last one )
--compress //压缩选项,此选项不兼容--stream=tar,只兼容--stream=xbstream,此外加密项encrypted也不能兼容--stream=tar!
--decompress //在备份时如果使用了加密或者压缩选项,在用xbstream -x 解压包出来后,还须使用
innodbackupex --decompress /data/backup 压缩后的文件为ibdata1.qp qp结尾的文件!另外使用decompress还需yum install qpress.x86_64 装上qpress这个包!
--slave-info //This option is useful when backing up a replication slave server. It also writes this information to the "xtrabackup_slave_info" file as a "CHANGE MASTER" command. A new slave for this master can be set up by starting a slave server on this backup and issuing a "CHANGE"xtrabackup_slave_info" file. 在备份从服务器时,使用此参数能记录master的日志和偏移量!用于做一个新的从服务器!
一般情况下的全备份,master二进制日志文件以及偏移点会记录在xtrabackup_binlog_info这个文件中!
1.完全备份
innobackupex --defaults-file=/etc/my-3306.cnf --host=192.168.40.185 --port=3306 --user=root --password=ciwong --no-timestamp /data/backup1/full/
innobackupex --defaults-file=/etc/my-3306.cnf --host=127.0.0.1 --user=bkpuser --password=ciwong --stream=tar /data/backup/ 1> /data/backup/full20140719.tar 2>/data/backup/0719.log 指定输出日志文件!!(其中1和>符号之间没有空格)
2.备份并打包
innobackupex --user=root --password=12345 --defaults-file=/etc/my.cnf --stream=tar /root/backup/full >/root/backup/full/test.tar
innobackupex --defaults-file=/etc/my-3306.cnf --host=192.168.40.185 --port=3306 --user=root --password=ciwong --stream=xbstream --no-timestamp /data/backup1/partial3/ >partial3.xbstream
备份打包并压缩
innobackupex --user=root --password=12345 --defaults-file=/etc/my.cnf --stream=tar /root/backup/full/ |gzip - > /root/backup/full/test.tar.gz
|bzip2 ->/root/backup/full/test.tar.bz2
innobackupex --defaults-file=/etc/my-3306.cnf --host=192.168.40.185 --port=3306 --user=root --password=ciwong --stream=xbstream --compress --no-timestamp /data/backup1/partial4/ >/data/backup1/partial4/partial4.xbstream
innobackupex --stream=xbstream --compress /data/backup >/data/backup/backup.xbstream
备份打包并压缩并传输到另一台机器!
innobackupex --stream=xbstream --compress /data/backup 2>>back.log | ssh [email protected] “xbstream -x -C /root”
innobackupex --host=127.0.0.1 --user=root --password=ciwong --defaults-file=/etc/my-3306.cnf --stream=tar /data/backup/ 2>/data/backup/2.log |ssh [email protected] "tar -xi -C /data/mysqlback/"
innobackupex --stream=xbstream --compress /data/backup 2>>back.log | ssh [email protected] “cat > /data/backup/backup.xbstream”
innobackupex --stream=tar /data/backup 2>>back.log |ssh [email protected] \ "cat - > /data/backup/backup.tar"
innobackupex --host=127.0.0.1 --user=root --password=ciwong --defaults-file=/etc/my-3306.cnf --stream=tar /data/backup/ 2>/data/backup/2.log |ssh [email protected] "gzip - > /data/mysqlback/2.tar.gz"
innobackupex --defaults-file=/etc/my.cnf --host=192.168.40.125 --port=3306 --user=bakuser --password=ciwong --stream=tar /data/backup/ 2>/data/backup/2.log |ssh [email protected] \ "cat - > /data/backup/backup.tar"
在备份到远程机器上的时候,需在|管道符前把标准错误输出重定向到日志文件,不然不会提示输入密码,并且备份不成功!并且需要注意2>/data/backup/2.log在重定向日志的时候,2与>中间不能有空格!
在解压tar.gz文件时,须加上-i参数,tar -xvizf test.tar.gz
以及解压xbstream文件时:xbstream -x < partial4.xbstream -C /root/backup/
xtrabackup: error: compressed and encrypted backups are incompatible with the
'tar' streaming format. Use --stream=xbstream instead.
--compress 与加密参数与tar打包参数是不兼容的
3.基于全备份做一个增量备份
./innobackupex –defaults-file=/tmp/mysqld.cnf –no-timestamp –socket=/tmp/mysql.sock –user=admin –password=admin –incremental –incremental-basedir=$backupdir/full/ $backupdir/inc1
innobackupex --defaults-file=/etc/my.cnf --user=root --incremental --incremental-basedir=/tmp/backup/2014-03-27_17-38-40/ /tmp/backup/incr/
4.基于全备份和第一个增量备份做第二次增量备份
./innobackupex –defaults-file=/tmp/mysqld.cnf –no-timestamp –socket=/tmp/mysql.sock –user=admin –password=admin –incremental –incremental-basedir=$backupdir/inc1/ $backupdir/inc2
不管是做完一次全备还是增量备份,在备份文件xtrabackup_checkpoints 中都会有
backup_type = full-prepared
from_lsn = 0
to_lsn = 16376622412
last_lsn = 16376622412
compact = 0
等参数记录,分别表示备份类型,开始LSN,以及结束LSN,在下一次的增量备份中,便会引用上一次备份到的LSN,也就是to_lsn,last_lsn!表示新的备份将会从这个LSN点开始进行!
所以增量备份也可以写成如下形式:
innobackupex --defaults-file=/tmp/mysqld.cnf --incremental /data/incr1 --incremental-lsn=16376622412
5. 恢复全备份
./innobackupex $backupdir/full/ –apply-log
./innobackupex $backupdir/full/ --copy-back --defaults-file=/test/my.cnf
其中恢复也需要用到my.cnf文件,但如果my.cnf文件也丢失了或其它原因,可手动建立一个my.cnf
里面只要包含 [mysqld] datadir=/data/mysql3306 等路径参数,即可把备份正确恢复到目录下!
(恢复到指定目录后,记得修改文件属主chown -R mysql:mysql $backupdir/full/ )
6. 基于全备份进行二次增量备份的恢复
1. ./innobackupex --apply-log --redo-only $backupdir/full/
//先将全备的数据库文件执行redo重做操作(only redo)
2. ./innobackupex --apply-log --redo-only $backupdir/full/ --incremental-dir=$backupdir/inc1/ //将第一次增量备份执行重做操作并合并到全备里 (only redo)
3. ./innobackupex --apply-log $backupdir/full/ --incremental-dir=$backupdir/inc2/
//()将第二次增量备份合并到全备里,此时如果是最后一次增量备份,则不用使用--redo-only参数!
4. once you merge the base with all the increments,you can prepare it to roll back the uncommitted transactions;
Note: --redo-only should be used when merging all incrementals except the last one. That’s why the previous
line doesn’t contain the --redo-only option. Even if the --redo-only was used on the last step, backup would
still be consistent but in that case server would perform the rollback phase
innobackupex --apply-log $backupdir/full/ //now your backup is ready to be used immediately after restoring it ,this preparation step is optional ,however,if you restore without doing the prepare,the database server will begin to rollback uncommitted transactions!
5. restoring incremental backups with innobackupex
innobackupex --defaults-file=/etc/my3306.cnf --copy-back
二、partial backups 不完全备份恢复
innobackupex可以备份指定的数据库或表,但有个条件限制是数据库必须是独立表空间的,也就是开启了innodb_file_per_table参数,
一共三种参数可供使用:
--include //此参数需要匹配全路径表名,包括数据库名,in the form databasename.tablename,相当于oracle的schema.table
innobackupex --include=mysqldatabase.mytable /path/to/backup
--tables-file //此参数后可跟一个文本文件,文本文件里可以跟多个表名,表名也需要是databasename.tablename这种格式,一行一个!!
echo "mydatabase.mytable" >/tmp/tables.txt
innobackupex --tables-file=/tmp/tables.txt /path/to/backup
--databases //此参数后跟数据库名!可跟多个! 这里指定的数据库只对MyISAM表和InnoDB表的表结构有效,对于InnoDB 数据来说都是全备(所有数据库中的InnoDB数据都进行了备份,不是只备份指定的数据库,恢复时也一样innobackupex --databases="mydatabase.myable databasename" /path/to/backup
恢复
in server versions prior to 5.6,it is not possible to copy tables between servers by copying the files ,even with innodb_file_per_table, however,with the percona xtrabackup,you can export individual tables from any innodb database and import them into percona server with xtradb or mysql.5.6,this only works on individual .ibd files,and can not export a table that is not contained in its own .ibd file.
单表迁移必须是在5.6或以上版本,并且开启了独立表空间,因为5.5或以下版本中ibdata1系统表空间文件里还保存着表的字典信息,在各自表ibd文件中保存着事务ID和日志序列号!
--export
innobackupex --apply-log --export /path/to/backup //这将为每个表创建一个.exp扩展名的表空间文件!
-rw-r--r--. 1 root root 698 Jul 3 15:27 cataloguesections.cfg
-rw-r--r--. 1 root root 16384 Jul 3 15:27 cataloguesections.exp
-rw-r-----. 1 root root 8746 Jul 3 15:19 cataloguesections.frm
-rw-r-----. 1 root root 229376 Jul 3 15:19 cataloguesections.ibd
importint tables
导入表数据之前,需先创建一张与要导入表的结构一样的表
create table mytable (...) engine=innodb;
then discard its tablespace;
alter table mydatabase.mytable discard tablespace;
after this ,copy mytable.ibd and mytable.exp(or mytable.cfg if importing to mysql5.6)files to databses's home ,and import its tablespace:
alter table mydatabase.mytable import tablespace;
#Step 5: 基于全备份进行第一次增量备份的恢复 ./innobackupex $backupdir/full/ –incremental –incremental-dir=$backupdir/inc1/ –apply-log
#Step 6: 基于全备份和第一次增量备份,恢复第二次增量备份
./innobackupex $backupdir/full/ –incremental –incremental-dir=$backupdir/inc2/ –apply-log #Step 7: 将恢复好的数据按照配置文件的需求拷贝到相应目录 ./innobackupex –defaults-file=/tmp/mysqld2.cnf $backupdir/full/ –copy-back
在查看或解压由innodbbackupex创建的tar文件时需加i参数
tar -tivf test.tar.gz
tar -zxivf test.tar.gz
备份到远程主机
innobackupex --user=root --password=12345 --defaults-file=/etc/my.cnf --stream=tar /root/backup/full |ssh [email protected] \ "cat - >/data/backups/backup.tar" (通过)
innobackupex --user=root --password=12345 --defaults-file=/etc/my.cnf --stream=tar /root/backup/full/ | gzip - > test4.tar.gz |ssh [email protected] \ "cat - > /root/backup/test4.tar.gz"
(未通过,在192.168.1.11上查看最后文件大小为0)
scp /root/backup/test4.tar.gz [email protected]:/root/backup/
索引:
B+TREE 索引
哈希索引
空间数据索引(R-tree)
全文索引
索引优点:
1、可以大大减少服务器需要扫描的数据量
2、索引可以帮助服务器避免排序和临时表
3、索引可以将随机I/O变为顺序I/O
高性能索引策略:
1、独立的列(索引不能是语句中表达式的一部分,也不能是函数的参数)
2、前缀索引和索引选择性。索引的选择性是指,不重复的索引值(也能基数)和数据表的记录总数的比值,范围从1/t 到1之前,选择性越高索引效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也是最高的!使用索引前缀时,换句话说,前缀的基数应该接近于完整列的基数。
完整列的选择性:select count(distinct city)/count(*)from sakila.city_demo
不同索引前缀长度的选择性:
select count(distinct left(city,3))/count(*) as sel3,
-> count(distinct left(city,4))/count(*) as sel4,
-> count(distinct left(city,5))/count(*) as sel5
-> from sakila.city_demo;
创建前缀索引:
alter table skila.city_demo add key (city(7));
前缀索引是一种能索引更小,更快的有效办法,但使用前缀索引时无法使用order by和group by 也无法使用前缀索引做覆盖扫描,
3、多列索引
如果为多个列创建多个独立的索引,在mysql5.0后,查询会自动将结果合并(索引合并策略,1、OR条件的联合(union)2、and条件的相交(intersection)3、前二种情的联合以及相交),另外如果explain中出现索引合并,在更多的时候表时表上的索引建的很糟糕,
4、选择合适的索引列顺序
经验法则:将选择性最高的列放到索引最前列,比较不同列的索引选择性,索引选择性高的可以放在多列索引的前面。另外也需要注意where子句中的排序分组范围条件等因素,还有避免随机IO和排序。
索引案例学习
1、支持多种过滤条件
2、避免多个范围条件
3、优化排序
维护索引和表
维护表有三个主要的目的:
1、找到并修复损坏的表
check table:检查是否发生了表损坏
repair table:修复损坏的表
如果引擎不支持上述命令,可以通过一个不做任何操作的alter操作来重建表,例如修改表的存储引擎为当前的引擎
alter table innodb_tb1 engine=innodb;
2、维护准确的索引统计信息
mysql查询优化器通过二个API来了解存储引擎的索引值分布信息,以决定如何使用索引,records_in_range()通过向存储引擎传入二个边界值获取在这个范围大概有多少条记录,
info() 返回各种类型数据,包括索引的基数(每个键值有多少条记录,不重复的索引值),索引列的基数(cardinality)其显示了存储引擎估算索引列有多少个不同的取值,show index from table; 也可以通过查询information_schema.statistics表查询
如果索引统计信息不准确,可以运行analyze table table_name来重新生成统计信息
MYISAM将索引统计信息存储在磁盘中,analyze table需要进行一次全索引扫描来计算索引基数,在整个过程中需要锁表
INNODB不在磁盘存储索引统计信息,而是通过随机的索引访问进行评估并将其存储在内存中。INNODB通过抽样的方式来计算统计信息,首先读取少量的索引页面,默认是8个索引页面,新版本可通过innodb_stats_sample_pages来设置样本页的数量。
innodb_stats_on_metadata:参数控制自动索引信息采样更新,
3、减少碎片
行碎片
行间碎片
剩余空间碎片
可以通过optimize table 或导出再导入的方式来重新整理数据,也可以通过一个不做任何操作的alter table操作来重建表,alter table tablename engine=(engine),这种方式对标准MYSQL版本只会消除表(实际是聚簇索引)的碎片化,可以通过先删除所有索引,然后重建表,最后重新创建索引的方式做到消除表和索引的碎片化。xtrabackup --stats参数以非备份方式运行,可以打印索引和表的统计信息,包括页中的数据量和空余空间,这可以确定数据的碎片化程度。
MYSQL中大多数情况下都会使用B-tree索引,在选择和编写利用这些索引的查询时有如下三个原则始终记住:
1、单行的访问是很慢的
2、按顺序访问范围数据是很快的
3、索引覆盖查询是很快的。
总的来说,编写查询语句时应该尽可能的选择合适的索引以避免单行查找,尽可能的使用数据原生顺序从而避免额外的排序操作,并尽可能的使用索引覆盖查询
索引案例学习
1、支持多种过滤条件
2、避免多个范围条件
3、优化排序
维护索引和表
维护表有三个主要的目的:
1、找到并修复损坏的表
check table:检查是否发生了表损坏
repair table:修复损坏的表
如果引擎不支持上述命令,可以通过一个不做任何操作的alter操作来重建表,例如修改表的存储引擎为当前的引擎
alter table innodb_tb1 engine=innodb;
2、维护准确的索引统计信息
mysql查询优化器通过二个API来了解存储引擎的索引值分布信息,以决定如何使用索引,records_in_range()通过向存储引擎传入二个边界值获取在这个范围大概有多少条记录,
info() 返回各种类型数据,包括索引的基数(每个键值有多少条记录,不重复的索引值),索引列的基数(cardinality)其显示了存储引擎估算索引列有多少个不同的取值,show index from table; 也可以通过查询information_schema.statistics表查询
如果索引统计信息不准确,可以运行analyze table table_name来重新生成统计信息
MYISAM将索引统计信息存储在磁盘中,analyze table需要进行一次全索引扫描来计算索引基数,在整个过程中需要锁表
INNODB不在磁盘存储索引统计信息,而是通过随机的索引访问进行评估并将其存储在内存中。INNODB通过抽样的方式来计算统计信息,首先读取少量的索引页面,默认是8个索引页面,新版本可通过innodb_stats_sample_pages来设置样本页的数量。
innodb_stats_on_metadata:参数控制自动索引信息采样更新,
3、减少碎片
行碎片
行间碎片
剩余空间碎片
可以通过optimize table 或导出再导入的方式来重新整理数据,也可以通过一个不做任何操作的alter table操作来重建表,alter table tablename engine=(engine),这种方式对标准MYSQL版本只会消除表(实际是聚簇索引)的碎片化,可以通过先删除所有索引,然后重建表,最后重新创建索引的方式做到消除表和索引的碎片化。xtrabackup --stats参数以非备份方式运行,可以打印索引和表的统计信息,包括页中的数据量和空余空间,这可以确定数据的碎片化程度。
MYSQL中大多数情况下都会使用B-tree索引,在选择和编写利用这些索引的查询时有如下三个原则始终记住:
1、单行的访问是很慢的
2、按顺序访问范围数据是很快的
3、索引覆盖查询是很快的。
总的来说,编写查询语句时应该尽可能的选择合适的索引以避免单行查找,尽可能的使用数据原生顺序从而避免额外的排序操作,并尽可能的使用索引覆盖查询
查询性能优化
一、慢查询基础:优化数据访问
1、是否向数据库请求了不需要的数据,有些查询会请求超过实际需要的数据,然后这些多余的数据会被应用程序丢弃,
典型案例:
查询不需要的记录,简单的解决方法是在查询后面加上limit,
多表关联时返回全部列,
总是取出全部列,如select * from ...
重复查询相同的数据,
2、mysql是否在扫描额外的记录
mysql最简单的衡量查询开销的三个指标:
响应时间
扫描的行数
返回的行数
扫描的行数和访问类型
二、重构查询方式
1、一个复杂查询还是多个简单查询
2、切分查询
3、分解关联查询
三、查询执行的基础
1、客户端发送一条查询给服务器
mysql客户端和服务器之间的通信协议是半双工,这意味着在任何一个时刻,要么是服务器向客户端发关数据,要么是客户端向服务器发送数据,查询状态:show full processlist;
2、服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果,否则进入下一阶段,
这个检查使用一个大小写敏感的哈希查找实现。如果当前的查询恰好命中了缓存,在返回查询结果之前mysql会再检查一次用户权限,这仍然是不需要解析查询SQL语句的,因为在查询缓存中已经存放了妆肖查询需要访问的表的信息。
3、服务器端进行SQL解析,预处理,再由优化器生成对应的执行计划。
语法解析器和预处理:
查询优化器:
数据和索引的统计信息:
MYSQL如何执行关联查询:
执行计划:
关联查询优化器:
排序优化
4、mysql根据优化器生成的执行计划,调用存储引擎的API来执行查询
查询执行引擎,
5、将结果返回客户端
四、mysql查询优化器的局限性
1、关联子查询
2、UNION的限制
3、索引合并优化
4、等值传递
5、并行执行
6、哈希关联
7、松散索引扫描
8、最大值和最小值优化
9、在同一个表上查询和更新
五、查询优化器的提示(hint)
六、优化特定类型的查询
1、优化count()查询
2、优化关联查询
3、优化子查询
4、优化group by 和distinct
5、优化limit分页
6、优化sql_calc_found_rows
7、优化union查询
8、静态查询分析优化
9、使用用户自定义变量
优化服务器设置
mysql有大量可以修改的参数,但不应该随便动漫修改,通常只需要把基本的项配置正确,(大部分情况下只有很少的一些参数是真正重要的)应该将更多的时间花在schema的优化,索引,以及查询设计上,在正确地配置了mysql的基本配置项之后,再花力气去修改其它配置项的收益通常就比较小了