多实例mysql主从复制

mysql的多实例即在一台linux服务器上安装了一个mysql开启多个不同的服务器端口来运行多个mysql服务进程共用一套mysql软件,使用不同的mysql.cnf软件,使用不同的mysql.cock的这样的一套系统称为mysql的多实例(个人分析)。

本节我们不谈论主从复制的原理,我们讨论的是mysql多实例的主从复制是如何实现的。

实现环境:

centos 5.5,内核版本为2.6.18-194.el5  ;mysql的version: 5.0.22

字符集的问题--------改变字符集不会出现乱码问题,并非本实现需要,

[root@book 3307]# echo $LANG            -------------查看当前字符集
zh_CN.UTF-8
[root@book 3307]# echo "LANG=en_US.UTF-8" >> /etc/profile   增加一个变量
[root@book 3307]# source /etc/profile      --------------让这个变量生效
[root@book 3307]# echo $LANG          -------------查看当前字符集
en_US.UTF-8
[root@book 3307]#

linux服务器的IP地址为:192.168.6.7

准备开启3307端口库做为主库,3308端口的库为从库

我们的数据库的安装目录为/lamp/mysql

我们的多实例的安装目录为/lamp/mysql-multi

然后在mysql-multi目录中再建立两个目录3307和3308,

[root@book ~]# tree /lamp/mysql-multi/
/lamp/mysql-multi/
|-- 3307
`-- 3308

2 directories, 0 files

下面我们先来配置开启3307端口的主库,

我们切换到/lamp/mysql-multi/3307这个目录,然后用rz命令上传我们需要的文件

上传之后,我们查看文件

 [root@book 3307]# ll
total 16
-rw-r--r-- 1 root root 2012 Aug 18  2012 my.cnf
-rw-r--r-- 1 root root  786 Aug 18  2012 mysql

我们配置mysql多实例我们需要my.cnf 和mysql这两个配置文件,其中my.cnf为mysql的主要配置文件,mysql这个文件为启动脚本文件,下面我们来把这两个文件做如下修改,最终结果为

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

 [root@book 3307]# cat my.cnf
[client]
port            = 3307
socket          =
/lamp/mysql-multi/3307/mysql.sock

[mysql]
no-auto-rehash

[mysqld]
user    = mysql
port    = 3307
socket  = /lamp/mysql-multi/3307/mysql.sock
basedir = /lamp/mysql
datadir = /lamp/mysql-multi/3307/data
open_files_limit    = 1024
back_log = 600
max_connections = 800
max_connect_errors = 3000
table_cache = 614
external-locking = FALSE
max_allowed_packet =8M
sort_buffer_size = 1M
join_buffer_size = 1M
thread_cache_size = 100
thread_concurrency = 2
query_cache_size = 2M
query_cache_limit = 1M
query_cache_min_res_unit = 2k
default_table_type = InnoDB
thread_stack = 192K
transaction_isolation = READ-COMMITTED
tmp_table_size = 2M
max_heap_table_size = 2M
long_query_time = 1
log_long_format
log-error = /lamp/mysql-multi/3307/error.log
log-slow-queries = /lamp/mysql-multi/3307/slow.log
pid-file = /lamp/mysql-multi/3307/mysql.pid
#log-bin = /lamp/mysql-multi/3307/mysql-bin
relay-log = /lamp/mysql-multi/3307/relay-bin
relay-log-info-file = /lamp/mysql-multi/3307/relay-log.info
binlog_cache_size = 1M
max_binlog_cache_size = 1M
max_binlog_size = 2M
expire_logs_days = 7
key_buffer_size = 16M
read_buffer_size = 1M
read_rnd_buffer_size = 1M
bulk_insert_buffer_size = 1M
myisam_sort_buffer_size = 1M
myisam_max_sort_file_size = 10G
myisam_max_extra_sort_file_size = 10G
myisam_repair_threads = 1
myisam_recover

lower_case_table_names = 1
skip-name-resolve
slave-skip-errors = 1032,1062
replicate-ignore-db=mysql

server-id = 1

innodb_additional_mem_pool_size = 4M
innodb_buffer_pool_size = 32M
innodb_data_file_path = ibdata1:128M:autoextend
innodb_file_io_threads = 4
innodb_thread_concurrency = 8
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 2M
innodb_log_file_size = 4M
innodb_log_files_in_group = 3
innodb_max_dirty_pages_pct = 90
innodb_lock_wait_timeout = 120
innodb_file_per_table = 0
[mysqldump]
quick
max_allowed_packet = 2M

[mysqld_safe]
log-error=/lamp/mysql-multi/3307/mysql_3307.error
pid-file=
/lamp/mysql-multi/3307/mysqld.pid

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

在这个my.conf配置文件中我们要注意路径书写一定要正确!

 然后我们再去修改mysql这个启动文件,最终修改结果如下:

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

 [root@book 3307]# cat mysql
#!/bin/sh
port=3307
mysql_user="root"
mysql_pwd=""      -------------我们设置了密码之后这里要输入密码
CmdPath="/lamp/mysql/bin"

#startup function
function_start_mysql()
{
    printf "Starting MySQL...\n"
    /bin/sh ${CmdPath}/mysqld_safe --defaults-file=/lamp/mysql-multi/${port}/my.cnf 2>&1 > /dev/null &
}

#stop function
function_stop_mysql()
{
    printf "Stoping MySQL...\n"
    ${CmdPath}/mysqladmin -u ${mysql_user} -p${mysql_pwd} -S /lamp/mysql-multi/${port}/mysql.sock shutdown
}

#restart function
function_restart_mysql()
{
    printf "Restarting MySQL...\n"
    function_stop_mysql
    sleep 2
    function_start_mysql
}

case $1 in
start)
    function_start_mysql
;;
stop)
    function_stop_mysql
;;
restart)
    function_restart_mysql
;;
*)
    printf "Usage: /lamp/mysql-multi/${port}/mysql {start|stop|restart}\n"
esac

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

 还是要提醒大家注意细节,

为了安全期间和能顺利的配置我们需要更改一下权限配置,

[root@book 3307]# cd ..
[root@book mysql-multi]# chown mysql:mysql 3307 -R
[root@book mysql-multi]# chmod 700 3307 -R

下面我们就来初始化我们的数据库了,

[root@book mysql-multi]# /lamp/mysql/bin/mysql_install_db --datadir=/lamp/mysql-multi/3307/data --user=mysql

然后我们再切换回3307这个目录(目录之间实际上是不用切换的,切换为的是更直观)

[root@book mysql-multi]# cd 3307
[root@book 3307]# ./mysql start
[root@book 3307]# netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State     
tcp        0      0 0.0.0.0:3307                0.0.0.0:*                   LISTEN     
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN     
tcp        0      0 0.0.0.0:978                 0.0.0.0:*                   LISTEN     
tcp        0      0 127.0.0.1:631               0.0.0.0:*                   LISTEN     
tcp        0      0 127.0.0.1:25                0.0.0.0:*                   LISTEN     
tcp        0      0 :::80                       :::*                        LISTEN     
tcp        0      0 :::22                       :::*                        LISTEN     
tcp        0      0 ::ffff:192.168.6.7:22       ::ffff:192.168.6.1:4645     ESTABLISHED

我们看到3307端口已经开启来了,下面我们另外开一个终端来登录一下数据库
[root@book ~]# /lamp/mysql/bin/mysql -S /lamp/mysql-multi/3307/mysql.sock -uroot -p

因为我们以后要多次用到/lamy/mysql/bin/这个目录里的命令,所以我们就添加一个路径到$PATH里,

[root@book 3307]# echo "PATH=$PATH:/lamp/mysql/bin/" >> /etc/profile
[root@book 3307]# source /etc/profile
[root@book 3307]# tail -2 /etc/profile
LANG=en_US.UTF-8
PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/lamp/mysql/bin/

以后我们再用/lamp/mysql/bin/下的命令的时候就可以直接输入了,就又如刚才我们初始化的时候的命令和登录数据库时候的命令就可以写成

[root@book mysql-multi]# mysql_install_db --datadir=/lamp/mysql-multi/3307/data --user=mysql

[root@book ~]# mysql -S /lamp/mysql-multi/3307/mysql.sock -uroot -p

重要提示:要使这两条命令生效必须重新登录终端,不然变量不能应用

 

 

 第二个实例的创建:

用以上类同的方法我们再开启一个3308这样一个终端,结果就下:

再打开一个终端然后登录数据库

现在在一台服务器上我们实现了两个实例的安装,下面我们就来实现两个实例之间的数据复制,首先我们还是先做一些准备工作,(很重要哟) 

 1,我们首先给开启端口为3307的这个实例设置一个密码,

[root@book ~]# mysqladmin -uroot password '123456' -S /lamp/mysql-multi/3307/mysql.sock

 2,再给开启端口为3308的这个实例设置一个密码,

[root@book ~]# mysqladmin -uroot password '123456' -S /lamp/mysql-multi/3308/mysql.sock

 设置这两个密码可以在打开的三个终端的任意终端上完成,

 然后可以分别测试……  OK了没有问题,继续下面的操作,

 注意:

在本次实例中我们以开启3307端口的库为主库,开启3308端口库为从库,

 下面我们要授权并创建主从数据库复制的用户,这里我们用一条命令来实现,

进入开启3307端口的数据结构然后做如下操作,

mysql> grant replication slave on *.* to  redcock@'192.168.6.%' identified by 'hellomysql';

这句话的意思是说,我们授受redcock这个用户,密码为hellomysql在192.168.6.0/24这个段里有复制从库的权限,

我们可以查看新增加的用户

mysql> select user,host from mysql.user;
+---------+-------------+
| user    | host        |
+---------+-------------+
| redcock | 192.168.6.% |
|         | book        |
| root    | book        |
|         | localhost   |
| root    | localhost   |
+---------+-------------+
5 rows in set (0.00 sec)

我们可以查看权限

mysql> show grants for redcock@'192.168.6.%';

+------------------------------------------------------------------------------------------------------------------------------+
| Grants for redcock@192.168.6.%                                                                                               |
+------------------------------------------------------------------------------------------------------------------------------+
| GRANT REPLICATION SLAVE ON *.* TO 'redcock'@'192.168.6.%' IDENTIFIED BY PASSWORD '*7EBECCF45B488A62A1B829E8369C3F578FFE49B2' |
+------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

红色部分我们看到只有复制从库的权限, 

下面我们要做的就是锁表操作-----锁表的原因请参阅复制原理,这里不介绍

mysql> flush tables with read lock;

注意:锁表时间是有定义的,我们可以查看默认值,

mysql> mysql> show variables like '%timeout%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| connect_timeout          | 5     |
| delayed_insert_timeout   | 300   |
| innodb_lock_wait_timeout | 120   |
| interactive_timeout      | 28800 |
| net_read_timeout         | 30    |
| net_write_timeout        | 60    |
| slave_net_timeout        | 3600  |
| table_lock_wait_timeout  | 50    |
| wait_timeout             | 28800 |
+--------------------------+-------+
9 rows in set (0.00 sec)

 注:时间单位是多少我也没有验证 

 锁表之后我们可以测试着创建数据库,我们会发现提示表已经锁住为只读!

这里我们要记录下现在的数据信息,

mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)

mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |       98 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

下面的操作我们就要备份数据库了,

因为我们这是在一台服务器上建立的多实例,所以备份完之后不用远程拷贝复制文件,只需要在服务器上建立一个备份文件的目录,

[root@book ~]# mkdir /mysqlback
[root@book ~]# mysqldump -uroot -p'123456' -S /lamp/mysql-multi/3307/mysql.sock  -A -B |gzip > /mysqlback/mysql_bak.$(date +%F).sql.gz

 然后去查询一下是不是生成了3307这个实例数据库的备份

[root@book ~]# ls /mysqlback/
mysql_bak.2012-08-18.sql.gz

下面就可以把刚才锁住的表解开了,我们进入3307这个实例的数据库。

mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)

先前的准备工作都做完之后我们要修改配置文件了,

首先在主库上(开启3307端口的库)修改配置文件,

修改主服务器上的my.cnf这个文件
service -id=某个数(在同一个局域网中不要一样)
把log-bin打开,如果前面有#号就把前面的#号去掉,没有就加上这一行,

如下: 

server-id = 1

 log-bin = /lamp/mysql-multi/3307/mysql-bin

 然后修改mysql这个文件

把刚才设置的密码给加上,如下:

mysql_pwd="123456"

然后我们重新启动3307这个实例

[root@book 3307]# ./mysql restart
Restarting MySQL...
Stoping MySQL...
Starting MySQL...

这中间可能要等一会,如果提示要输入密码则是你刚才没有把数据库的密码放进去配置文件中,这样主库我们就配置完成了,下面我们到从库上去操作,

在从库上的操作,

解压备份数据

[root@book ~]# gzip -d /mysqlback/mysql_bak.2012-08-18.sql.gz
[root@book ~]# ls /mysqlback/
mysql_bak.2012-08-18.sql

然后还原数据库文件到开启3308这台服务器的数据库里,(在哪个终端上做都可以)

 [root@book ~]# mysql -uroot -p'123456' -S /lamp/mysql-multi/3308/mysql.sock < /mysqlback/mysql_bak.2012-08-18.sql

 然后在客户端我们去看一下配置文件,把my.cnf其中的选项修改如下:

#log-bin = /lamp/mysql-multi/3308/mysql-bin
server-id = 2

再把mysql这个启动文件里mysql_pwd这一项加上刚才设置的数据库密码

mysql_pwd="123456"

然后重新启动数据库

[root@book 3308]# ./mysql restart
Restarting MySQL...
Stoping MySQL...
Starting MySQL...

可能又要等一小会,重启有点慢,呵呵,

然后我们再在客户端运行这些

cat |mysql -uroot -p'123456' -S /lamp/mysql-multi/3308/mysql.sock<< EOF
CHANGE MASTER TO 
MASTER_HOST='192.168.6.7',
MASTER_PORT=3307,
MASTER_USER='redcock',
MASTER_PASSWORD='hellomysql',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=98;
EOF

 然后我们在从库服务器上开启从库

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)

也可以用这种方式来启动

mysql -uroot -p'123456' -S /lamp/mysql-multi/3308/mysql.sock -e "start slave;"

然后我们查看一下从服务器的状态有没有什么问题

mysql> show slave status\G;
*************************** 1. row ***************************
             Slave_IO_State: Waiting for master to send event
                Master_Host: 192.168.6.7
                Master_User: redcock
                Master_Port: 3307
              Connect_Retry: 60
            Master_Log_File: mysql-bin.000001
        Read_Master_Log_Pos: 98
             Relay_Log_File: relay-bin.000003
              Relay_Log_Pos: 235
      Relay_Master_Log_File: mysql-bin.000001
           Slave_IO_Running: Yes
          Slave_SQL_Running: Yes
            Replicate_Do_DB:
        Replicate_Ignore_DB: mysql
         Replicate_Do_Table:
     Replicate_Ignore_Table:
    Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
                 Last_Errno: 0
                 Last_Error:
               Skip_Counter: 0
        Exec_Master_Log_Pos: 98
            Relay_Log_Space: 235
            Until_Condition: None
             Until_Log_File:
              Until_Log_Pos: 0
         Master_SSL_Allowed: No
         Master_SSL_CA_File:
         Master_SSL_CA_Path:
            Master_SSL_Cert:
          Master_SSL_Cipher:
             Master_SSL_Key:
      Seconds_Behind_Master: 0
1 row in set (0.00 sec)

ERROR:
No query specified

我们看到IO和sql线程都已经启动了,应该是可以了,我们测试

首先在主库上建立一个数据库,然后我们看从库上有没有这个数据库,

在主库上:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test               |
+--------------------+
3 rows in set (0.00 sec)

mysql> create database xiaogou;
Query OK, 1 row affected (0.01 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test               |
| xiaogou            |
+--------------------+
4 rows in set (0.00 sec)

mysql>

然后我们去从库上去查看


mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test               |
| xiaogou            |
+--------------------+
4 rows in set (0.00 sec)

我们看到在从数据库服务器上,xiaogou这个数据库也已经自动建立好了,到此我们的实验就告一段落了。