1. MySQL主从原理以及应用场景MySQL的Replication原理非常简单,总结一下: 每个从仅可以设置一个主。 主在执行sql之后,记录二进制log文件(bin-log)。 从连接主,并从主获取binlog,存于本地relay-log,并从上次记住的位置起执行sql,一旦遇到错误则停止同步。 从这几条Replication原理来看,可以有这些推论: 1)主从间的数据库不是实时同步,就算网络连接正常,也存在瞬间,主从数据不一致。 2)如果主从的网络断开,从会在网络正常后,批量同步。 3)如果对从进行修改数据,那么很可能从在执行主的bin-log时出现错误而停止同步,这个是很危险的操作。所以一般情况下,非常小心的修改从上的数据。 一个衍生的配置是双主,互为主从配置,只要双方的修改不冲突,可以工作良好。 如果需要多主的话,可以用环形配置,这样任意一个节点的修改都可以同步到所有节点。 可以应用在读写分离的场景中,用以降低单台MySQL服务器的I/O 可以实现MySQL服务的HA集群 可以是1主多从,也可以是相互主从(主主) 为了做实验方便,我们在同一台机器上配置两个MySQL服务(开两个端口) 1、安装、配置MySQL 事先已经安装好mysql; [root@localhost ~]# cd /usr/local/ [root@localhost local]# cp -r mysql/ mysql_2 [root@localhost local]# cd mysql_2/ 初始化mysql2,如果出现两个 “OK”并且生成/data/mysql2目录说明正确; [root@localhost mysql_2]# ./scripts/mysql_install_db --user=mysql--datadir=/data/mysql2 拷贝配置文件 [root@localhost mysql_2]# cp /etc/my.cnf ./my.cnf 修改配置文件相关参数,更改port 以及 socket ,并增加datadir=/data/mysql2 [root@localhost mysql_2]# vi my.cnf [mysqld] port = 3307 socket = /tmp/mysql2.sock datadir=/data/mysql2 启动: [root@localhost mysql_2]# /usr/local/mysql_2/bin/mysqld_safe--defaults-file=/usr/local/mysql_2/my.cnf --user=mysql & 如果想开机启动,需加入到/etc/rc.local里; # echo "/usr/local/mysql_2/bin/mysqld_safe--defaults-file=/usr/local/mysql_2/my.cnf --user=mysql &" >>/etc/rc.d/rc.local netstat查看已经有2个mysqld服务: [root@localhost mysql2]# netstat -nlp |grep mysqld tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 1203/mysqld tcp 0 0 0.0.0.0:3307 0.0.0.0:* LISTEN 1744/mysqld unix 2 [ ACC ] STREAM LISTENING 8804 1203/mysqld /tmp/mysql.sock unix 2 [ ACC ] STREAM LISTENING 14159 1744/mysqld /tmp/mysql2.sock 2、 配置主从准备工作 设定mysql_2为主(master)端口3307,mysql为从(slave)端口为3306 使用sock文件登录主mysql [root@localhost mysql2]# /usr/local/mysql_2/bin/mysql -uroot -S/tmp/mysql_2.sock -S 后面指定mysql的socket文件路径,这也是登陆mysql的一种方法,因为在一台服务器上跑了两个mysql端口,所以,只能用 -S 这样的方法来区分。 在主上创建测试库db1 mysql> create database db1; mysql> quit 导出主的mysql库数据然后导入给db1 [root@localhost mysql2]#/usr/local/mysql_2/bin/mysqldump -uroot -S /tmp/mysql2.sock mysql > 123.sql [root@localhost mysql2]# /usr/local/mysql_2/bin/mysql-uroot -S /tmp/mysql2.sock db1 < 123.sql 3、配置主(master) vim /usr/local/mysql_2/my.cnf 在[mysqld]部分查看是否有以下内容,如果没有则添加: server-id=1 log-bin=mysql-bin 两个可选参数(2选1): binlog-do-db=db1,db2 #需要同步的库 binlog-ignore-db=db1,db2 #忽略不同步的库 binlog-do-db=需要复制的数据库名,多个数据库名,使用逗号分隔。binlog-ignore-db=不需要复制的数据库库名,多个数据库名,使用逗号分隔。 修改配置文件后,重启mysql_2 [root@localhost mysql2]# pid=`ps aux |grep mysql_2.sock |grep -vgrep |awk '{print $2}'` [root@localhost mysql2]# kill $pid [root@localhost mysql_2]# /usr/local/mysql_2/bin/mysqld_safe--defaults-file=/usr/local/mysql_2/my.cnf --user=mysql & 设置root密码: [root@localhost mysql2]# /usr/local/mysql_2/bin/mysqladmin -uroot -S/tmp/mysql_2.sock password 'openstack' [root@localhostmysql2]# /usr/local/mysql_2/bin/mysql-uroot -S /tmp/mysql_2.sock -popenstack mysql> grant replication slave on *.* to 'repl'@'127.0.0.1'identified by 'openstack'; //这里的repl是为slave端设置的访问master端mysql数据的用户,密码为openstack,这里的127.0.0.1为slave的ip(本次试验配置的master和slave都在本机)。 mysql> flush privileges; //刷新库,内存的数据写入磁盘; mysql> flush tables with readlock; //锁定数据库,此时不允许更改任何数据,这一步很重要, mysql> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000005 | 668 | | | +------------------+----------+--------------+------------------+ //查看状态,这些数据是要记录的,要在slave端用到; 4、 设置从(slave) vim /etc/my.cnf #修改或增加 server-id = 2 #这个数值不能和主一样 可选参数:replicate-do-db=db1,db2 replicate-ignore-db=db1,db2 #意义同主的那两个可选参数 重启从的mysql服务:service mysqld restart 拷贝主的db1库数据到从: 先导出db1.sql文件,然后在从数据库中同样创建数据库db1,导入主的db1.sql文件到从; [root@localhost ~]# /usr/local/mysql_2/bin/mysqldump -uroot -S /tmp/mysql_2.sock -popenstack db1 > db1.sql(导出zhuangbility的db1数据库) 在从上创建数据库: [root@localhost ~]# /usr/local/mysql/bin/mysql -uroot -S/tmp/mysql.sock -e "create database db1" [root@localhost ~]# /usr/local/mysql/bin/mysql -uroot -S/tmp/mysql.sock db1 < db1.sql 登陆从的mysql [root@localhost ~]# /usr/local/mysql/bin/mysql -uroot-S /tmp/mysql.sock mysql> slave stop; mysql> change master tomaster_host='127.0.0.1',master_port=3307,master_user='repl',master_password='openstack',master_log_file='mysql-bin.000005',master_log_pos=668; //master_log_file='mysql-bin.000004',master_log_pos=378为主show master status显示的前2列内容; mysql> slave start; 主上,解锁表: [root@localhost ~]# /usr/local/mysql_2/bin/mysql -uroot -S/tmp/mysql_2.sock -popenstack -e"unlock tables" 登录从 [root@localhost ~]# /usr/local/mysql/bin/mysql -uroot-S /tmp/mysql.sock 查看从的状态showslave status\G; 确认以下两项参数都为yes: Slave_IO_Running: Yes Slave_SQL_Running: Yes mysql> show slave status\G; *************************** 1. row*************************** Slave_IO_State: Waiting for master to send event Master_Host: 127.0.0.1 Master_User: repl Master_Port: 3307 Connect_Retry: 60 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 378 Relay_Log_File: localhost-relay-bin.000002 Relay_Log_Pos: 251 Relay_Master_Log_File: mysql-bin.000004 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: 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: 378 Relay_Log_Space: 410 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 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: 5、 测试主从 主上清空db1库的db表 : 登录主 [root@localhost ~]# /usr/local/mysql_2/bin/mysql -uroot -S /tmp/mysql_2.sock -popenstack mysql> use db1; mysql> select count(*) from db; +----------+ | count(*) | +----------+ | 2 | +----------+ 清空db表; mysql> truncate table db; mysql> select count(*) from db; +----------+ | count(*) | +----------+ | 0 | +----------+ 进入slave,查看db1库db表,和主的数据一样,表示同步OK; [root@localhost ~]# mysql -uroot -S /tmp/mysql.sock mysql> use db1; mysql> select count(*) from db; +----------+ | count(*) | +----------+ | 0 | +----------+ 登录主,删除表db; [root@localhost ~]# mysql -uroot -S /tmp/mysql2.sock-p123456 mysql> drop table db; 登录从,查看db表不存在; [root@localhost ~]# mysql -uroot -S /tmp/mysql.sock mysql> select * from db; ERROR 1146 (42S02): Table 'db1.db' doesn't exist 建议: MySQL主从机制比较脆弱,谨慎操作。如果重启master,务必要先把slave停掉,也就是说需要在slave上去执行slave stop 命令,然后再去重启master的mysql服务,否则很有可能就会中断了。当然重启完后,还需要把slave给开启 slave start。 扩展学习:
|