在 Database 分类下的文章

使用innobackupex备份和恢复MySQL

参考资料:
https://www.percona.com/doc/percona-xtrabackup/2.2/innobackupex/privileges.html
https://www.percona.com/doc/percona-xtrabackup/2.1/innobackupex/streaming_backups_innobackupex.html
https://www.percona.com/doc/percona-xtrabackup/2.1/howtos/recipes_ibkx_compressed.html
https://www.percona.com/doc/percona-xtrabackup/2.1/innobackupex/incremental_backups_innobackupex.html

背景介绍:
在一些技术群里面,看到仍然有一些运维在用mysqldump这样的命令来备份MySQL,于是感觉有必要介绍一下innobackupex。
现在,绝大多数使用MySQL的场景中,都用到了Master-Slave这样的架构。相对于mysqldump而言,使用innobackupex备份有以下好处:
1. 以数据文件为备份对象,文件级别备份,速度快,尤其适合需要对所有数据进行备份的场景;
2. 热备份,不会对现有的数据库访问造成影响;
3. 记录binlog以及replication相关信息,在创建和恢复Slave时非常有用;
4. 支持对备份后的数据进行同步并行压缩,有效节省磁盘空间;

目前,在我们的线上环境中,数据库的大小,在没有压缩之前为500G左右,压缩之后的大小为90G左右。
而在风哥的环境中,数据库的大小已经超过了1T,以下是风哥的几点补充:
1.用innobackupex可以做到不停业务在线备份,前提是对innodb引擎,对myisam也会锁表;
2.在备份过程会导致IO很高,建议在一台slave上做备份(一般用一台slave只做备份用),不建议在主上备份;
3.innobackupex可以用增量与全量备份方式配合;

另外,杨总在学习了ITIL之后,补充到:对于最近的一次全量备份,除了要做到异地备份以外,还应该尽量在数据库所在的服务器本地保存一份没有经过压缩打包的备份,这样在进行灾难恢复的时候,能够节省大量的时间。

具体用例:
环境介绍

架构:Master-Slave
服务器:idc1-master1, idc1-slave1
MySQL端口:3308
配置文件:/etc/my_3308.cnf
备份目录:/mysql-backup/3308
MySQL数据目录:/opt/mysql_3308/data
服务脚本:/etc/init.d/mysql_3308

1. 在Master和Slave上安装xtrabackup:
注意:如果你安装的不是Percona版本的MySQL,或者MySQL版本低于5.5,请安装percona-xtrabackup-20,并忽略下面所有压缩相关的步骤与参数。

# yum install http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm
# yum install -y percona-xtrabackup qpress
# yum install -y percona-xtrabackup-20 # 非Percona版本的MySQL,或者MySQL版本低于5.5

2. 在Master和Slave上创建一个用于备份的用户backup-user:

mysql> CREATE USER 'backup-user'@'localhost' IDENTIFIED BY 'backup-pass';
mysql> GRANT SUPER, RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'backup-user'@'localhost';
mysql> FLUSH PRIVILEGES;
mysql> EXIT;

注意:对于非Percona版本的MySQL,或者MySQL版本低于5.5,如5.1,需要额外增加SELECT权限,否则会出现mysql系统数据库备份权限不足的问题。

mysql> GRANT SELECT, SUPER, RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'backup-user'@'localhost';

3. 在Master上备份
常规方式

[root@idc1-master1 ~]# innobackupex --defaults-file=/etc/my_3308.cnf --user=backup-user --password=backup-pass --use-memory=4G /mysql-backup/3308

[root@idc1-master1 ~]# ls -rt1 /mysql-backup/3308/ | tail -n 1
2015-10-26_03-00-10

压缩打包方式

[root@idc1-master1 ~]# innobackupex --defaults-file=/etc/my_3308.cnf --user=backup-user --password=backup-pass --use-memory=4G --compress --compress-threads=8 --stream=xbstream --parallel=4 /mysql-backup/3308 > /mysql-backup/3308/$(date +%Y-%m-%d_%H-%M-%S).xbstream

[root@idc1-master1 ~]# ls -rt1 /mysql-backup/3308/ | tail -n 1
2015-10-26_03-05-05.xbstream

4. 在Slave上备份
常规方式

[root@idc1-slave1 ~]# innobackupex --defaults-file=/etc/my_3308.cnf --user=backup-user --password=backup-pass --use-memory=4G --slave-info --safe-slave-backup /mysql-backup/3308

[root@idc1-slave1 ~]# ls -rt1 /mysql-backup/3308/ | tail -n 1
2015-10-26_03-11-03

压缩打包方式

[root@idc1-slave1 ~]# innobackupex --defaults-file=/etc/my_3308.cnf --user=backup-user --password=backup-pass --use-memory=4G --slave-info --safe-slave-backup --compress --compress-threads=8 --stream=xbstream --parallel=4 /mysql-backup/3308 > /mysql-backup/3308/$(date +%Y-%m-%d_%H-%M-%S).xbstream

[root@idc1-slave1 ~]# ls -rt1 /mysql-backup/3308/ | tail -n 1
2015-10-26_03-15-03.xbstream

5. 在Master上恢复

[root@idc1-master1 ~]# /etc/init.d/mysql_3308 stop

[root@idc1-master1 ~]# mv /opt/mysql_3308/data /opt/mysql_3308/data_broken
[root@idc1-master1 ~]# mkdir /opt/mysql_3308/data

# 常规方式
[root@idc1-master1 ~]# innobackupex --apply-log --use-memory=4G /mysql-backup/3308/2015-10-26_03-00-10
[root@idc1-master1 ~]# innobackupex --defaults-file=/etc/my_3308.cnf --copy-back --use-memory=4G /mysql-backup/3308/2015-10-26_03-00-10 

# 压缩打包方式
[root@idc1-master1 ~]# mkdir -p /mysql-backup/3308/2015-10-26_03-05-05
[root@idc1-master1 ~]# xbstream -x < /mysql-backup/3308/2015-10-26_03-05-05.xbstream -C /mysql-backup/3308/2015-10-26_03-05-05
[root@idc1-master1 ~]# innobackupex --decompress --parallel=4 /mysql-backup/3308/2015-10-26_03-05-05
[root@idc1-master1 ~]# find /mysql-backup/3308/2015-10-26_03-05-05 -name "*.qp" -delete
[root@idc1-master1 ~]# innobackupex --apply-log --use-memory=4G /mysql-backup/3308/2015-10-26_03-05-05
[root@idc1-master1 ~]# innobackupex --defaults-file=/etc/my_3308.cnf --copy-back --use-memory=4G /mysql-backup/3308/2015-10-26_03-05-05 

[root@idc1-master1 ~]# chown -R mysql:mysql /opt/mysql_3308/data

[root@idc1-master1 ~]# /etc/init.d/mysql_3308 start

6. 在Slave上恢复

[root@idc1-slave1 ~]# /etc/init.d/mysql_3308 stop

[root@idc1-slave1 ~]# mv /opt/mysql_3308/data /opt/mysql_3308/data_broken
[root@idc1-slave1 ~]# mkdir /opt/mysql_3308/data

# 常规方式
[root@idc1-slave1 ~]# innobackupex --apply-log --use-memory=4G /mysql-backup/3308/2015-10-26_03-11-03
[root@idc1-slave1 ~]# innobackupex --defaults-file=/etc/my_3308.cnf --copy-back --use-memory=4G /mysql-backup/3308/2015-10-26_03-11-03 

# 压缩打包方式
[root@idc1-slave1 ~]# mkdir -p /mysql-backup/3308/2015-10-26_03-15-03
[root@idc1-slave1 ~]# xbstream -x < /mysql-backup/3308/2015-10-26_03-15-03.xbstream -C /mysql-backup/3308/2015-10-26_03-15-03 
[root@idc1-slave1 ~]# innobackupex --decompress --parallel=4 /mysql-backup/3308/2015-10-26_03-15-03 
[root@idc1-slave1 ~]# find /mysql-backup/3308/2015-10-26_03-15-03 -name "*.qp" -delete [root@idc1-slave1 ~]# innobackupex --apply-log --use-memory=4G /mysql-backup/3308/2015-10-26_03-15-03 
[root@idc1-slave1 ~]# innobackupex --defaults-file=/etc/my_3308.cnf --copy-back --use-memory=4G /mysql-backup/3308/2015-10-26_03-15-03 

[root@idc1-slave1 ~]# chown -R mysql:mysql /opt/mysql_3308/data 
[root@idc1-slave1 ~]# /etc/init.d/mysql_3308 start 

[root@idc1-slave1 ~]# cd /opt/mysql_3308/data 

# 从Master的备份中恢复时查看 xtrabackup_binlog_pos_innodb 
[root@idc1-slave1 data]# cat xtrabackup_binlog_pos_innodb ./bin-log-mysqld.000222 222333 

# 从Slave的备份中恢复时查看 xtrabackup_slave_info 
[root@idc1-slave1 data]# cat xtrabackup_slave_info 
CHANGE MASTER TO MASTER_LOG_FILE='bin-log-mysqld.000222', MASTER_LOG_POS=222333 

[root@idc1-slave1 data]# mysql_3308 -uroot -p 
mysql> change master to
master_host='idc1-master1',
master_port=3308,
master_user='backup-user',
master_password='backup-pass',
master_log_file='bin-log-mysqld.000222',
master_log_pos=222333;
mysql> start slave;
mysql> show slave status\G;
mysql> exit;

7. 增量备份与恢复
增量备份的原理是,基于一个现有的完整备份,针对InnoDB-based表仅备份增量的部分,针对MyISAM表则仍然保持全量备份。

备份环境:
在Slave服务器上进行

备份策略:
每天1次完整备份 + 每天2次增量备份

具体步骤:
7.1 增量备份
7.1.1 准备完整备份(压缩但不打包方式):

[root@idc1-slave1 ~]# innobackupex --defaults-file=/etc/my_3308.cnf --user=backup-user --password=backup-pass --use-memory=4G --slave-info --safe-slave-backup --compress --compress-threads=8 /mysql-backup/3308

[root@idc1-slave1 ~]# ls -rt1 /mysql-backup/3308/ | tail -n 1
2015-10-26_06-48-33

[root@idc1-slave1 ~]# cat /mysql-backup/3308/2015-10-26_06-48-33/xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0
to_lsn = 1631145
last_lsn = 1631145
compact = 0
recover_binlog_info = 0

7.1.2 进行第1次增量备份(压缩但不打包方式):

[root@idc1-slave1 ~]# innobackupex --defaults-file=/etc/my_3308.cnf --user=backup-user --password=backup-pass --use-memory=4G --slave-info --safe-slave-backup --compress --compress-threads=8 --incremental /mysql-backup/3308 --incremental-basedir=/mysql-backup/3308/2015-10-26_06-48-33

[root@idc1-slave1 ~]# ls -rt1 /mysql-backup/3308/ | tail -n 1
2015-10-26_06-55-12

[root@idc1-slave1 ~]# cat /mysql-backup/3308/2015-10-26_06-55-12/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 1631145
to_lsn = 1635418
last_lsn = 1635418
compact = 0
recover_binlog_info = 0

7.1.3 进行第2次增量备份(压缩但不打包方式):

[root@idc1-slave1 ~]# innobackupex --defaults-file=/etc/my_3308.cnf --user=backup-user --password=backup-pass --use-memory=4G --slave-info --safe-slave-backup --compress --compress-threads=8 --incremental /mysql-backup/3308 --incremental-basedir=/mysql-backup/3308/2015-10-26_06-55-12

[root@idc1-slave1 ~]# ls -rt1 /mysql-backup/3308/ | tail -n 1
2015-10-26_06-59-49

[root@idc1-slave1 ~]# cat /mysql-backup/3308/2015-10-26_06-59-49/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 1635418
to_lsn = 1639678
last_lsn = 1639678
compact = 0
recover_binlog_info = 0

7.2 增量恢复:
7.2.1 取回完整备份(必须加参数 --redo-only)

[root@idc1-slave1 ~]# innobackupex --decompress --parallel=4 /mysql-backup/3308/2015-10-26_06-48-33
[root@idc1-slave1 ~]# find /mysql-backup/3308/2015-10-26_06-48-33 -name "*.qp" -delete
[root@idc1-slave1 ~]# innobackupex --apply-log --redo-only --use-memory=4G /mysql-backup/3308/2015-10-26_06-48-33

7.2.2 合并第1个增量(必须加参数 --redo-only)

[root@idc1-slave1 ~]# innobackupex --decompress --parallel=4 /mysql-backup/3308/2015-10-26_06-55-12
[root@idc1-slave1 ~]# find /mysql-backup/3308/2015-10-26_06-55-12 -name "*.qp" -delete
[root@idc1-slave1 ~]# innobackupex --apply-log --redo-only --use-memory=4G /mysql-backup/3308/2015-10-26_06-48-33 --incremental-dir=/mysql-backup/3308/2015-10-26_06-55-12

7.2.3 合并第2个增量(合并最后一个增量备份时不加 --redo-only)

[root@idc1-slave1 ~]# innobackupex --decompress --parallel=4 /mysql-backup/3308/2015-10-26_06-59-49
[root@idc1-slave1 ~]# find /mysql-backup/3308/2015-10-26_06-59-49 -name "*.qp" -delete
[root@idc1-slave1 ~]# innobackupex --apply-log --use-memory=4G /mysql-backup/3308/2015-10-26_06-48-33 --incremental-dir=/mysql-backup/3308/2015-10-26_06-59-49

7.2.4 准备完整备份(定稿完整备份时不加 --redo-only)

[root@idc1-slave1 ~]# innobackupex --apply-log --use-memory=4G /mysql-backup/3308/2015-10-26_06-48-33

7.2.5 恢复完整备份(按照以上 常规方式,执行从--copy-back开始及之后的步骤)

,

No Comments

绕开SST通过IST方式添加Node到Percona XtraDB Cluster

参考资料:
https://github.com/percona/xtradb-cluster-tutorial/blob/master/instructions/Avoiding%20SST.rst#bad-configuration

服务器:
idc1-server1, idc1-server2, idc1-server3

1. 安装Percona XtraDB Cluster,在 idc1-server1,idc1-server2,idc1-server3 上
$ sudo yum install http://www.percona.com/downloads/percona-release/percona-release-0.0-1.x86_64.rpm
$ sudo yum install http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ sudo yum install Percona-Server-shared-compat
$ sudo yum install Percona-XtraDB-Cluster-server Percona-XtraDB-Cluster-client
$ sudo mkdir -p /opt/mysql/{data,tmp,run,binlogs,log}
$ sudo chown mysql:mysql /opt/mysql/{data,tmp,run,binlogs,log}
$ sudo -i
# su - mysql
$ mysql_install_db --user=mysql --datadir=/opt/mysql/data/
$ exit
# exit

2. 配置 my.cnf,在 idc1-server1 上
[heydevops@idc1-server1 ~]$ sudo vim /etc/my.cnf

 
[mysqld]
# basic settings
datadir = /opt/mysql/data
tmpdir = /opt/mysql/tmp
socket = /opt/mysql/run/mysqld.sock
pid-file = /opt/mysql/run/mysqld.pid

# innodb settings
default-storage-engine = INNODB
innodb_file_per_table = 1
log-bin = /opt/mysql/binlogs/bin-log-mysqld
log-bin-index = /opt/mysql/binlogs/bin-log-mysqld.index
innodb_data_home_dir = /opt/mysql/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /opt/mysql/data

# xtradb cluster settings
binlog_format = ROW
wsrep_cluster_name = mycluster
wsrep_cluster_address = gcomm://10.100.1.3,10.100.1.4,10.100.1.5
wsrep_node_address = 10.100.1.3
wsrep_provider = /usr/lib64/libgalera_smm.so
wsrep_sst_method = xtrabackup
wsrep_sst_auth = sst:secret
wsrep_provider_options = "gcache.size=8G;"
wsrep_sst_receive_address = 10.100.1.3
innodb_locks_unsafe_for_binlog = 1
innodb_autoinc_lock_mode = 2

# server id
server-id=123

# other settings
[mysqld_safe]
log-error = /opt/mysql/log/mysqld.log
pid-file = /opt/mysql/run/mysqld.pid
open-files-limit = 8192

[mysqlhotcopy]
interactive-timeout

[client]
port = 3306
socket = /opt/mysql/run/mysqld.sock
default-character-set = utf8

阅读全文 »

, , , ,

2 Comments

Percona XtraDB Cluster 功能测试

参考资料:
http://www.mysqlperformanceblog.com/2013/09/23/percona-xtradb-cluster-setting-simple-cluster/

背景介绍:
在我们的生产环境,目前还采用的是单节点的Mater对应多个Slave节点;为了避免Master单点故障,需要尝试其它方案;
类似于通过Keepalived(VIP)或MySQL-Proxy等的方式,应用的比较多,如MySQL MMM;
由于线上采用了Percona Server,因为Manager更推荐采用 Percona 官方的Auto-Failover方式或者XtraDB Cluster的方式,Auto-Failover方式我在上一篇文章中已经讲过了。
因此,本章节主要讲解XtraDB Cluster的功能测试情况。

环境介绍:
servers: demoenv-trial-1 demoenv-trial-2 demoenv-trial-3

1. 安装 Percona Server,在所有服务器上:
$ sudo yum install http://www.percona.com/downloads/percona-release/percona-release-0.0-1.x86_64.rpm
$ sudo yum install http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ sudo yum install Percona-Server-shared-compat
$ sudo yum install Percona-Server-server-55 Percona-Server-client-55

2. 配置 /etc/my.cnf,在所有服务器上:
$ sudo vim /etc/my.cnf

[mysqld]
# basic settings
datadir = /opt/mysql/data
tmpdir = /opt/mysql/tmp
socket = /opt/mysql/run/mysqld.sock
port = 3306
pid-file = /opt/mysql/run/mysqld.pid

skip-external-locking
max_allowed_packet = 16M

# innodb settings
default-storage-engine = INNODB
innodb_file_per_table = 1
log-bin = /opt/mysql/binlogs/bin-log-mysqld
log-bin-index = /opt/mysql/binlogs/bin-log-mysqld.index
innodb_data_home_dir = /opt/mysql/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /opt/mysql/data
binlog-do-db = testdb

# server id
server-id=1

# other settings
[mysqld_safe]
log-error = /opt/mysql/log/mysqld.log
pid-file = /opt/mysql/run/mysqld.pid
open-files-limit = 8192

[mysqlhotcopy]
interactive-timeout

[client]
port = 3306
socket = /opt/mysql/run/mysqld.sock
default-character-set = utf8

3. 创建所需目录,在所有服务器上:
$ sudo mkdir -p /opt/mysql/{data,tmp,run,binlogs,log}
$ sudo chown mysql:mysql /opt/mysql/{data,tmp,run,binlogs,log}

4. 初始化数据库,在所有服务器上:
$ sudo -i
# su - mysql
$ mysql_install_db --user=mysql --datadir=/opt/mysql/data/
$ exit
# exit
$ sudo /etc/init.d/mysql start

5. 删除原有软件包,在所有服务器上:
因为XtraDB Cluster的软件包与原有软件包冲突:

Error: Percona-XtraDB-Cluster-client conflicts with Percona-Server-client-55-5.5.34-rel32.0.591.rhel6.x86_64
Error: Percona-XtraDB-Cluster-server conflicts with Percona-Server-server-55-5.5.34-rel32.0.591.rhel6.x86_64
Error: Percona-XtraDB-Cluster-shared conflicts with Percona-Server-shared-55-5.5.34-rel32.0.591.rhel6.x86_64

$ sudo /etc/init.d/mysql stop
$ sudo rpm -qa | grep Percona-Server | grep -v compat | xargs sudo rpm -e --nodeps
阅读全文 »

, ,

2 Comments

MySQL 官方 Auto-Failover 功能测试

参考资料:
http://www.clusterdb.com/mysql/replication-and-auto-failover-made-easy-with-mysql-utilities

环境介绍:
master: demoenv-trial-1
slaves: demoenv-trial-2 demoenv-trial-3

1. 安装 Percona Server,在所有服务器上:
$ sudo yum install http://www.percona.com/downloads/percona-release/percona-release-0.0-1.x86_64.rpm
$ sudo yum install Percona-Server-shared-compat
$ sudo yum install Percona-Server-server-56

$ sudo yum install http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ sudo yum install mysql-utilities

2. 配置 /etc/my.cnf,在所有服务器上:
注意:确保 server-id 不同且 report-host 与自身主机名相同
$ sudo vim /etc/my.cnf

[mysqld]
# basic setting
datadir = /opt/mysql/data
tmpdir = /opt/mysql/tmp
socket = /opt/mysql/run/mysqld.sock
port = 3306
pid-file = /opt/mysql/run/mysqld.pid

# innodb setting
default-storage-engine = INNODB
innodb_file_per_table = 1
log-bin = /opt/mysql/binlogs/bin-log-mysqld
log-bin-index = /opt/mysql/binlogs/bin-log-mysqld.index
innodb_data_home_dir = /opt/mysql/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /opt/mysql/data
binlog-do-db = testdb

# server id
server-id=1

# gtids setting
binlog-format = ROW
log-slave-updates = true
gtid-mode = on
enforce-gtid-consistency = true
report-host = demoenv-trial-1
report-port = 3306
master-info-repository = TABLE
relay-log-info-repository = TABLE
sync-master-info = 1

# other settings
[mysqld_safe]
log-error = /opt/mysql/log/mysqld.log
pid-file = /opt/mysql/run/mysqld.pid
open-files-limit = 8192

[mysqlhotcopy]
interactive-timeout

[client]
port = 3306
socket = /opt/mysql/run/mysqld.sock
default-character-set = utf8

3. 创建所需目录,在所有服务器上:
$ sudo mkdir -p /opt/mysql/{data,tmp,run,binlogs,log}
$ sudo chown mysql:mysql /opt/mysql/{data,tmp,run,binlogs,log}

4. 初始化数据库,在所有服务器上:
$ sudo -i
# su - mysql
$ mysql_install_db --user=mysql --datadir=/opt/mysql/data/
$ exit
# exit
$ sudo /etc/init.d/mysql start

5. 创建授权用户 root@'%' 以便通过 mysqlreplicate 来进行主从复制的配置,在所有服务器上:
$ mysql -uroot

mysql> grant all on *.* to root@'%' identified by 'pass' with grant option;
mysql> quit;

6. 创建复制所需的用户,在所有服务器上:
$ mysql -uroot

mysql> grant replication slave on *.* to 'rpl'@'%' identified by 'rpl';
mysql> quit;

7. 配置主从复制,可选择任意一台服务器操作:
[dong.guo@demoenv-trial-1 ~]$ mysql -uroot

mysql> use mysql;
mysql> drop user root@'demoenv-trial-1';
mysql> quit;

[dong.guo@demoenv-trial-1 ~]$ mysqlreplicate --master=root:pass@'demoenv-trial-1':3306 --slave=root:pass@'demoenv-trial-2':3306 --rpl-user=rpl:rpl

# master on demoenv-trial-1: ... connected.
# slave on demoenv-trial-2: ... connected.
# Checking for binary logging on master...
# set up replication...
# ...done.

阅读全文 »

, ,

No Comments

使用参数innodb_file_per_table支持MySQL InnoDB表数据共享空间自动收缩

参考资料:
http://linuxfun.me/?p=1263

使用过MySQL的同学,刚开始接触最多的莫过于MyISAM表引擎了,这种引擎的数据库会分别创建三个文件:表结构、表索引、表数据空间。我们可以将某个数据库目录直接迁移到其他数据库也可以正常工作。
然而当你使用InnoDB的时候,一切都变了。InnoDB 默认会将所有的数据库InnoDB引擎的表数据存储在一个共享空间中:ibdata1,这样就感觉不爽,增删数据库的时候,ibdata1文件不会自动收缩,单个数据库的备份也将成为问题。通常只能将数据使用mysqldump 导出,然后再导入解决这个问题。
在MySQL的配置文件[mysqld]部分,增加innodb_file_per_table参数,可以修改InnoDB为独立表空间模式,每个数据库的每个表都会生成一个数据空间。

独立表空间
优点:
1.每个表都有自已独立的表空间。
2.每个表的数据和索引都会存在自已的表空间中。
3.可以实现单表在不同的数据库中移动。
4.空间可以回收(drop/truncate table方式操作表空间不能自动回收)
5.对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会处理。

缺点:
单表增加比共享空间方式更大。

结论:
共享表空间在Insert操作上有一些优势,但在其它都没独立表空间表现好。
当启用独立表空间时,请合理调整一下 innodb_open_files 参数。

下面,就是一次针对线上Zabbix的MySQL数据库history历史记录过多导致ibdata1文件过大的实战解决步骤
1.查看文件大小
$ sudo cd /var/lib/mysql
$ ls -lh

 
total 14G
-rw-r--r-- 1 root root 0 Dec 1 14:31 debian-5.1.flag
-rw-rw---- 1 mysql mysql 5.0M Jan 17 21:31 ib_logfile0
-rw-rw---- 1 mysql mysql 5.0M Jan 17 21:29 ib_logfile1
-rw-rw---- 1 mysql mysql 14G Jan 17 21:31 ibdata1
drwx------ 2 mysql root 4.0K Dec 1 14:31 mysql
-rw-rw---- 1 root root 6 Dec 1 14:31 mysql_upgrade_info
drwx------ 2 mysql mysql 4.0K Jan 17 21:29 zabbix

共享表数据空间文件ibdata1大小已经达到了14G
阅读全文 »

, ,

No Comments

MongoDB主从复制与副本集群实践

参考资料:
http://www.cnblogs.com/huangxincheng/archive/2012/03/04/2379755.html
http://blog.sina.com.cn/s/blog_a34f10a4010113df.html

一、部署主从复制

1、主服务器和从服务器必须开启安全认证:--auth
2、主服务器和从服务器的admin数据库中必须有全局用户。
3、主服务器的local数据库和从服务器的local数据均有名为repl且密码相同的用户名。

主服务器设置:
dongguo@mongodb:~$ mongo

MongoDB shell version: 2.2.0
connecting to: test
> use admin
switched to db admin
> db.addUser('rootm','rootm')
{
	"user" : "rootm",
	"readOnly" : false,
	"pwd" : "aa6526e3b7cbcecc18b2bd822f7c3547",
	"_id" : ObjectId("50659e14d2fe6be605337c18")
}
> db.addUser('repl','repl')
{
	"user" : "repl",
	"readOnly" : false,
	"pwd" : "c9f242649c23670ff94c4ca00ea06fe7",
	"_id" : ObjectId("5065a85eccf77b17681365b7")
}
> use cloud
switched to db cloud
> db.addUser('repl','repl')
{
	"_id" : ObjectId("5065a7cbb70f43c4d157e8ec"),
	"user" : "repl",
	"readOnly" : false,
	"pwd" : "c9f242649c23670ff94c4ca00ea06fe7"
}
> use local
switched to db local
> db.addUser('repl','repl')
{
	"user" : "repl",
	"readOnly" : false,
	"pwd" : "c9f242649c23670ff94c4ca00ea06fe7",
	"_id" : ObjectId("50659e2cd2fe6be605337c19")
}
> exit
bye

dongguo@mongodb:~$ sudo /etc/init.d/mongod stop

dongguo@mongodb:~$ sudo vim /opt/mongodb/etc/mongod.conf
修改如下设置:

master = true
auth = true

阅读全文 »

,

No Comments

安装配置RockMongo图形化管理工具

安装配置RockMongo图形化管理工具

$ sudo apt-get install apache2 php5 php5-dev dh-make-php

$ wget http://rock-php.googlecode.com/files/rockmongo-v1.1.2.zip
$ unzip rockmongo-v1.1.2.zip

$ sudo mv rockmongo /var/www/
$ sudo chown -R www-data:www-data /var/www/

$ sudo pecl install -f mongo 2.2.0

配置php.ini:
$ sudo vim /etc/php5/apache2/php.ini
extension_dir = "/usr/lib/php5/20090626"
extension = "mongo.so"

$ sudo /etc/init.d/apache2 restart

访问:http://10.6.1.145/rockmongo/
默认的账号与密码:admin/admin
登陆后如下图所示:

阅读全文 »

,

No Comments

安装配置MongoDB

参考资料:
http://blog.izhoufeng.com/posts/205.html

1. Mongodb介绍
1.1 MongoDB (名称来自”humongous”) 是一个可扩展的,高性能,开源,模式自由,面向文档的数据库,使用C++编写;以下是MongoDB特点:
1.1.1 面向集合的存储:适合存储对象及JSON形式的数据。
1.1.2 动态查询:Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。
1.1.3 完整的索引支持:包括文档内嵌对象及数组。Mongo的查询优化器会分析查询表达式,并生成一个高效的查询计划。
1.1.4 查询监视:Mongo包含一个监视工具用于分析数据库操作的性能。
1.1.5 复制及自动故障转移:Mongo数据库支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。复制的主要目标是提供冗余及自动故障转移。
1.1.6 高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)。
1.1.7 自动分片以支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器。

1.2 MongoDB的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)以及传统的RDBMS系统(丰富的功能)架起一座桥梁,集两者的优势于一身。根据官方网站的描述,Mongo适合用于以下场景:
1.2.1 网站数据:Mongo非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
1.2.2 缓存:由于性能很高,Mongo也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo搭建的持久化缓存层可以避免下层的数据源过载。
1.2.3 大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。
1.2.4 高伸缩性的场景:Mongo非常适合由数十或数百台服务器组成的数据库。Mongo的路线图中已经包含对MapReduce引擎的内置支持。
1.2.5 用于对象及JSON数据的存储:Mongo的BSON数据格式非常适合文档化格式的存储及查询。

1.3 自然,MongoDB的使用也会有一些限制,例如它不适合:
1.3.1 高度事务性的系统:例如银行或会计系统。传统的关系型数据库更适用于需要大量原子性复杂事务的应用程序。
1.3.2 传统的商业智能应用:针对特定问题的BI数据库会对产生高度优化的查询方式,数据仓库可能是更合适的选择。
1.3.3 需要SQL的问题。

2. Mongodb安装部署
2.1 建立数据目录和日志目录
$ sudo mkdir -p /opt/mongodb/data
$ sudo mkdir -p /opt/mongodb/log
$ sudo mkdir -p /opt/mongodb/etc
$ sudo mkdir -p /opt/mongodb/run

2.2 下载压缩包
$ wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.2.0.tgz

2.3 解压缩文件后不用安装
$ tar xzvf mongodb-linux-x86_64-2.2.0.tgz
$ sudo mv mongodb-linux-x86_64-2.2.0/bin /opt/mongodb/

2.4 查看命令help
$ /opt/mongodb/bin/mongod --help
以下是部分参数的解释:
阅读全文 »

2 Comments

什么叫key/value数据库

参考资料:
http://www.oschina.net/question/7910_16600?sort=default&p=1#answers
http://singlelove1983.blog.163.com/blog/static/50849047200863122550370/

想要明白什么是key/value数据库,就必须了解哈希表(Hash Table)这种数据结构。
比如,Berkley DB就是典型的key/value数据库。

以下内容对哈希表进行了很形象的描述:
========================================
Google搜索到的头条:散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。
这个映射函数叫做散列函数,存放记录的数组叫做散列表。

这个解释其实太含糊,想要整明白哈希表,那就得明白哈希表到底有什么样的优势。
数据结构中,有个时间算法复杂度O(n)的概念来衡量某种算法在时间效率上的优劣。
哈希表的理想算法复杂度为O(1),也就是说利用哈希表查找某个值,系统所使用的时间在理想情况下为定值,这就是它的优势。
那么哈希表是如何做到这一点的呢?

我们定义一个很大的有序数组,想要得到位于该数组第n个位置的值,它的算法复杂度为O(1)。
哈希表利用哈希函数将需要存储的内容的关键值转换为这个有序数组中的某个值,在被存储内容和有序数组之间建立了映射关系。
这样,下次我们对这个值进行查找时只要使用同一个哈希函数对关键值进行转换,找到这个数组值 就可以了。

如果还没有明白是怎么回事的话,那我们来举个例子。假设我们要做个存储结构,需要存储下来三国中的人物,以及他们的详细信息。
我们用他们的名字来作为存储 的关键值,例如:刘备,曹操,孙权,关羽,张飞……等等。
这个时候我们如果想用一般的方法来查找这些英雄豪杰,需要遍历整个存储空间,如果这些英雄豪杰一 共有n个,那么这时候的时间算法复杂度为O(n)。
显然如果n值很大,每次想要找到某个英雄就需要比较长的时间。

此时我们先定义一个大的有序结构数组HashValue[m],用来存放各位英雄豪杰的信息。
然后编写一个哈希函数ChangeToHashValue (name),函数的具体内容就不细说了,反正这个函数会将这些做为关键值的名字转换为HashValue[m]中的某个下标值x。
然后可以将英雄的信息 放进HashValue[x]中去。这样,可以将所有英雄的信息存储起来。当查询的时候再使用哈希函数ChangeToHashValue(name)得到这个下标值,这样就很容易得到了这个英雄的信息。

例如:ChangeToHashValue(刘备)为10,那么就将刘备存储到HashValue [10]里面。
当查询的时候再次使用ChangeToHashValue(刘备)得到10,这个时候我们就可以很容易找到刘备的所有信息。
在实际应用中如果我们想把所有的英雄豪杰都存储进系统时,需要定义m>n。
就是数组的大小要大于需要存储的信息量,所以说哈希表是一个以空间换取时间的数据结构。

这个时候问题来了,出现了这种情况ChangeToHashValue(关羽)和ChangeToHashValue(张飞)得到的值是一样的,都是250,我们岂不是在存储过程中会遇到麻烦,怎么安排他们二位的地方呢(总不能让二位打一架,谁赢了谁呆在那吧),这就需要一个解决冲突的方法。
当遇到这种情况时我们可以这样处理,先存储好了关羽,当张飞进入系统时会发现关羽已经是250了,那咱就加一位,251得了,这不就解决了。
我们查找张飞的时候也 是,一看250不是张飞,那就加个1,就找到了。
这时还存在一个问题,直接用ChangeToHashValue(赵云)为251,张飞已经早早占了他的地方,那就再加1存到252呗。
呵呵,这时我们会发现,当哈希函数冲突发生的机率很高时,可能会有一群英雄豪杰在250这个值后面扎堆排队。
要命的是查找的时候,时间算法复杂度早已不是O(1)了(所以我们说理想情况下哈希表的时间算法复杂度为O(1))。

这就是说哈希函数的编写是哈希表的一个关键问题,会涉及到一个存储值在哈希表中的统计分布。
如果哈希函数已经定义好了,冲突的解决就成为了改变系统性能的关键因素。
其实还有很多种方法来解决冲突情况下的存储和查找问题,不一定非要线性向后排队,如果有好的哈希表冲突的解决方法也能很大程度上提高系统的效率。

, ,

No Comments

MySQL InnoDB 故障解决记录

这是一起生产环境的故障解决记录,出错的数据库属于Zabbix监控系统,而整个操作过程由公司的专职DBA完成并记录。

1. 故障表现:Mysqld 进程持续重启,大量的错误日志:
120906 7:29:43 InnoDB: Page checksum 4195361555, prior-to-4.0.14-form checksum 2124157186
InnoDB: stored checksum 3323954773, prior-to-4.0.14-form stored checksum 2124157186
InnoDB: Page lsn 54 139070759, low 4 bytes of lsn at page end 139070759
InnoDB: Page number (if stored to page already) 134634,
InnoDB: space id (if created with >= MySQL-4.1.1 and stored already) 0
InnoDB: Page may be an index page where index id is 0 89
InnoDB: (index "history_1" of table "zabbix"."history")
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 134634.
InnoDB: You may have to recover from a backup.
InnoDB: It is also possible that your operating
InnoDB: system has corrupted its own file cache
InnoDB: and rebooting your computer removes the
InnoDB: error.
InnoDB: If the corrupt page is an index page
InnoDB: you can also try to fix the corruption
InnoDB: by dumping, dropping, and reimporting
InnoDB: the corrupt table. You can use CHECK
InnoDB: TABLE to scan your table for corruption.
InnoDB: See also http://dev.mysql.com/doc/refman/5.1/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
InnoDB: Ending processing because of a corrupt database page.

2. 故障原因,这类情况一般有2种情况:
mysql 服务异常关闭和硬件磁盘损坏。Innodb 自检过程中checksum与退出时不一致便会去recover;
或者退出时buffer中flush到磁盘的任务未正常结束并update checksum。

3. 解决办法。首先确定出错的数据表。(index "history_1" of table "zabbix"."history")。按下面的顺序尝试。
A. 进入mysql,如果mysql持续报错,但mysqld线程稳定,使用check table,optmize table 进行修复,大部分情况是失败。无响应或者ERROR 2013 (HY000): Lost connection to MySQL server during query
B. mysqld 进程不断重启(由innodb引擎发起的重启),check 和optimize 几乎无法在一个重启周期内完成。在my.cnf文件增加innodb_force_recovery=1 保证进程稳定。

4. 数据的恢复。
Check table 和 Optmize 其实对innodb效果不明显,所以80%解决不了问题,数据恢复有2种情况:
A.表数据完整,但checksum不一致
a) 新建同结构表,engine=myisam
b) Insert into new select * from old
c) Alter table new type=innodb
d) Drop table old,rename table new to old
B.表数据丢失,这种一般是磁盘损坏,方法和上面一样,区别在于,需要去需找破坏点,找到损坏的数据页面范围,达到最小数据损失。在有主键id的情况下相对容易且损失数据更小。

5. 恢复后在配置文件中注释 innodb_force_recovery=1 ,并重启。

No Comments