专职DBA-MySQL主从异步复制 MySQL主从复制企业级应用场景 1.从服务器作为主服务器的实时数据备份。 2.主从服务器实现读写分离,从服务器实现负载均衡。 3.根据业务重要性对多个从服务器进行拆分访问。 MySQL主从读写分离实现方案 1.通过开发程序实现读写分离(需要程序支持) 2.通过开源的软件实现读写分离。 3.大型门户独立开发DAL层综合软件。 mysql主从复制原理重点小结: 1.主从复制是异步的逻辑的SQL语句级的复制。 2.复制时,主库有一个binlog dump线程,从库有两个线程,I/O线程和SQL线程。 3.从mysql 5.6起,slave从库的SQL线程可以是多个。 4.实现主从复制的必要条件是主库要开启记录binlog的功能。 5.用于复制的所有mysql节点配置中的server-id都不能相同。 6.binlog文件只记录对数据库有更改的SQL语句(来自主库内容的更改),不记录任何(select,show)查询以及未对数据库做出更改的语句。 链接克隆两台主机,模板机安装请参考install_linux_os.sh VMware克隆Centos6.4虚拟机网卡无法启动问题 # cat /etc/sysconfig/network-scripts/ifcfg-eth0 # sed -i '/UUID/d' /etc/sysconfig/network-scripts/ifcfg-eth0 # sed -i '/HWADDR/d' /etc/sysconfig/network-scripts/ifcfg-eth0 # >/etc/udev/rules.d/70-persistent-net.rules # reboot 如果是克隆安装好的mysql虚拟机,还要修改数据目录下auto.cnf文件的UUID /data/mysql/3306/data/auto.cnf MySQL数据目录中通常存在一个名为auto.cnf文件,存储了server-uuid的值, MySQL启动时,会自动从data_dir/auto.cnf 文件中获取server-uuid值,并将这个值存储在全局变量server_uuid中。 如果这个值或者这个文件不存在,那么将会生成一个新的uuid值,并将这个值保存在auto.cnf文件中。 server-uuid与server-id一样,用于标识MySQL实例在集群中的唯一性,这两个参数在主从复制中具有重要作用, 默认情况下,如果主从库的server-uuid或者server-id的值一样,将会导致主从复制报错中断。 你可以把auto.cnf删除或者mv走,数据库启动会自动生成auto.cnf 主、从库server-uuid值一样,导致主从复制异常中断 主、从库server-id值一样,同样导致主从复制异常中断 参考文章https://www.jianshu.com/p/2347b1a9eacd 参考文章https://www.jianshu.com/p/2347b1a9eacd 主机规划 数据库角色 主机名 bond0(ssh连接ip) bond1(内网通信ip) 数据库端口 主库master db01 10.0.0.11 192.168.10.11 3306 从库slave db02 10.0.0.12 192.168.10.12 3306 按照专职DBA数据库安装文档,先把数据库安装上。 [root@db01 ~]# vim /etc/my.cnf [mysql] #prompt ="\\u@\\h [\\d]> \" #prompt ="mysql [\\d]> \" prompt ="Master [\\d]> \" #prompt ="Slave [\\d]> \" [root@db02 ~]# vim /etc/my.cnf [mysql] #prompt ="\\u@\\h [\\d]> \" #prompt ="mysql [\\d]> \" #prompt ="Master [\\d]> \" prompt ="Slave [\\d]> \" 数据库配置文件示例 [root@db01 ~]# cat /data/mysql/3306/my.cnf [mysqld] # for mysql global user = mysql basedir = /usr/local/mysql datadir = /data/mysql/3306/data tmpdir = /data/mysql/3306/tmp pid_file = /data/mysql/3306/3306.pid socket = /data/mysql/3306/mysql.sock port = 3306 server_id = 113306 character-set-server = utf8 # for binlog binlog_format = row log_bin = /data/mysql/3306/logs/mysql-bin # for error log log_error = /data/mysql/3306/error.log # general log general_log = off general_log_file = /data/mysql/3306/general.log # for slow query log slow_query_log = on slow_query_log_file = /data/mysql/3306/slow.log long_query_time = 1.000000 # for gtid gtid_mode = on enforce_gtid_consistency = on # for replication # for innodb [mysql] character-set-client = utf8 #prompt ="\\u@\\h [\\d]> \" #prompt ="mysql [\\d]> \" #prompt ="Master [\\d]> \" #prompt ="Slave [\\d]> \" 检查数据库的当前状态 [root@db01 ~]# mysqld --defaults-file=/data/mysql/3306/my.cnf & [1] 6735 [root@db01 ~]# ss -tunlp | grep mysql tcp LISTEN 0 80 :::3306 :::* users:(("mysqld",pid=6735,fd=34)) [root@db01 ~]# netstat -tunlp | grep mysql tcp6 0 0 :::3306 :::* LISTEN 6735/mysqld [root@db01 ~]# lsof -i :3306 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mysqld 6735 mysql 34u IPv6 35637 0t0 TCP *:mysql (LISTEN) [root@db01 ~]# lsof -i :mysql COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mysqld 6735 mysql 34u IPv6 35637 0t0 TCP *:mysql (LISTEN) [root@db01 ~]# ps -aux | grep mysql mysql 6735 2.0 35.0 1118452 171692 pts/0 Sl 06:02 0:01 mysqld --defaults-file=/data/mysql/3306/my.cnf root 6787 0.0 0.1 112708 976 pts/0 R+ 06:03 0:00 grep --color=auto mysql [root@db01 ~]# ps -ef | grep mysql mysql 6735 6697 1 06:02 pts/0 00:00:01 mysqld --defaults-file=/data/mysql/3306/my.cnf root 6790 6697 0 06:03 pts/0 00:00:00 grep --color=auto mysql [root@db02 ~]# mysqld --defaults-file=/data/mysql/3306/my.cnf & [1] 6761 [root@db02 ~]# ps -ef | grep mysql mysql 6761 6739 10 06:04 pts/0 00:00:01 mysqld --defaults-file=/data/mysql/3306/my.cnf root 6790 6739 0 06:04 pts/0 00:00:00 grep --color=auto mysql 在主库master上执行操作配置 1.设置server_id的值,并开启binlog功能参数 (1).修改主库的配置文件/etc/my.cnf [root@db01 ~]# egrep "server_id|log_bin" /data/mysql/3306/my.cnf server_id = 113306 log_bin = /data/mysql/3306/logs/mysql-bin (2).登录数据库检查参数的更改情况 [root@db01 ~]# mysql -S /data/mysql/3306/mysql.sock -p Master [(none)]> show global variables like "server_id"; +---------------+--------+ | Variable_name | Value | +---------------+--------+ | server_id | 113306 | +---------------+--------+ 1 row in set (0.00 sec) Master [(none)]> show global variables like "log_bin"; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | log_bin | ON | +---------------+-------+ 1 row in set (0.01 sec) 2.在主库上创建用于主从复制的账号 从库要想与主库同步,必须要有一个可以连接主库的账号,并且这个账号是在主库上创建的,权限是允许从库连接主库并同步数据。 Master [(none)]> grant replication slave on *.* to 'rep'@'192.168.10.%' identified by '123'; Query OK, 0 rows affected, 1 warning (0.00 sec) Master [(none)]> flush privileges; Query OK, 0 rows affected (0.00 sec) Master [(none)]> select user,host from mysql.user; +---------------+--------------+ | user | host | +---------------+--------------+ | rep | 192.168.10.% | | mysql.session | localhost | | mysql.sys | localhost | | root | localhost | +---------------+--------------+ 4 rows in set (0.00 sec) Master [(none)]> show grants for 'rep'@'192.168.10.%'; +--------------------------------------------------------+ | Grants for rep@192.168.10.% | +--------------------------------------------------------+ | GRANT REPLICATION SLAVE ON *.* TO 'rep'@'192.168.10.%' | +--------------------------------------------------------+ 1 row in set (0.00 sec) 3、对主库锁表只读后进行备份(当前窗口不要关闭) (1).对主库锁表只读 Master [(none)]> reset master; Query OK, 0 rows affected (0.01 sec) Master [(none)]> flush table with read lock; Query OK, 0 rows affected (0.01 sec) a.窗口关闭后锁表会失效。 b.超时参数设置的时间到了,锁表也会失效。 对于不同引擎,这个锁表命令的时间会受到下面参数的控制。锁表时,如果超过了设置的时间则会自动解锁。 Master [(none)]> show variables like '%timeout%'; +-----------------------------+----------+ | Variable_name | Value | +-----------------------------+----------+ | connect_timeout | 10 | | delayed_insert_timeout | 300 | | have_statement_timeout | YES | | innodb_flush_log_at_timeout | 1 | | innodb_lock_wait_timeout | 50 | | innodb_rollback_on_timeout | OFF | | interactive_timeout | 28800 | | lock_wait_timeout | 31536000 | | net_read_timeout | 30 | | net_write_timeout | 60 | | rpl_stop_slave_timeout | 31536000 | | slave_net_timeout | 60 | | wait_timeout | 28800 | +-----------------------------+----------+ 13 rows in set (0.00 sec) (2).锁表后查看主库的状态 Master [(none)]> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 154 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) (3).导出主库数据 锁表后,一定要再打开一个CRT窗口去操作 [root@db01 ~]# mysqldump -S /data/mysql/3306/mysql.sock -p -A -B |gzip > /backup/bak_$(date +%F).sql.gz 也可以加上-x --master-data=1就可以在从库配置复制参数的时候省去以下两个参数: MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=407; [root@db01 ~]# ls -l /backup/ total 200 -rw-r--r-- 1 root root 196911 Jul 15 06:25 bak_2019-07-15.sql.gz drwxr-xr-x 2 root root 29 Jul 12 03:50 conf -rw-r--r-- 1 root root 2243 Jul 15 05:28 eth0123.zip drwxr-xr-x 2 root root 54 Jul 12 05:39 sh drwxr-xr-x 2 root root 49 Jul 12 03:52 sql 为了确保导出数据期间,数据库没有数据插入操作,导库完毕后再检查一下主库的状态信息。 Master [(none)]> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 154 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) (4).导出数据完毕后,解锁主库,恢复可写,因为主库还要对外提供服务,因此不能一直锁定不让用户访问吧。 Master [(none)]> unlock tables; Query OK, 0 rows affected (0.00 sec) 4.把主库导出的mysql数据迁移到从库 [root@db01 ~]# ping -c 3 192.168.10.12 PING 192.168.10.12 (192.168.10.12) 56(84) bytes of data. 64 bytes from 192.168.10.12: icmp_seq=1 ttl=64 time=0.633 ms 64 bytes from 192.168.10.12: icmp_seq=2 ttl=64 time=0.718 ms 64 bytes from 192.168.10.12: icmp_seq=3 ttl=64 time=0.543 ms --- 192.168.10.12 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2002ms rtt min/avg/max/mdev = 0.543/0.631/0.718/0.074 ms [root@db01 ~]# scp -rp /backup/bak_$(date +%F).sql.gz root@192.168.10.12:/backup/ The authenticity of host '192.168.10.12 (192.168.10.12)' can't be established. ECDSA key fingerprint is SHA256:auBeaQTHqMvqa5fgR9w9UDEho26UWpxRqc0bHUwCv/Y. ECDSA key fingerprint is MD5:fc:ad:3a:4d:d7:83:20:a5:a1:49:c6:59:39:0b:1c:e5. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.10.12' (ECDSA) to the list of known hosts. root@192.168.10.12's password: bak_2019-07-15.sql.gz 100% 192KB 16.0MB/s 00:00 在slave从库上执行的操作过程 1.设置server_id的值,并关闭binlog功能参数 从库的server_id不能与主库以及其他从库一样,并且需要注释掉从库binlog参数配置。 这里开启binlog反而会增加从库磁盘I/O的压力。 以下两种情况需要开启从库的binlog参数配置,记录数据库更新的sql语句: •级联同步复制A--->B--->C,中间的B数据库服务需要开启binlog记录功能。 •在从库中做数据库备份时需要开启binlog记录功能。因为数据库备份必须要有全备和binlog日志,才是完整的备份。 (1).修改配置文件 [root@db02 ~]# egrep "server_id|log_bin" /data/mysql/3306/my.cnf server_id = 123306 #log_bin = /data/mysql/3306/logs/mysql-bin (3).重启从库 [root@db02 ~]# mysqladmin -S /data/mysql/3306/mysql.sock -p shutdown [root@db02 ~]# mysqld --defaults-file=/data/mysql/3306/my.cnf & (4).登录数据库检查参数的改变情况 [root@db02 ~]# mysql -S /data/mysql/3306/mysql.sock -p Enter password: Slave [(none)]> show global variables like "server_id"; +---------------+--------+ | Variable_name | Value | +---------------+--------+ | server_id | 123306 | +---------------+--------+ 1 row in set (0.03 sec) Slave [(none)]> show global variables like "log_bin"; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | log_bin | OFF | +---------------+-------+ 1 row in set (0.01 sec) 2.将刚才主库mysqldump导出的数据恢复到从库 [root@db02 ~]# zcat /backup/bak_2019-07-15.sql.gz | mysql -S /data/mysql/3306/mysql.sock -p Enter password: 3.登录从库配置复制参数 CHANGE MASTER TO MASTER_HOST='192.168.10.11', MASTER_PORT=3306, MASTER_USER='rep', MASTER_PASSWORD='123', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=154; 参数的值不能有空格!!! Slave [(none)]> CHANGE MASTER TO -> MASTER_HOST='192.168.10.11', -> MASTER_PORT=3306, -> MASTER_USER='rep', -> MASTER_PASSWORD='123', -> MASTER_LOG_FILE='mysql-bin.000001', -> MASTER_LOG_POS=154; Query OK, 0 rows affected, 2 warnings (0.02 sec) 以上操作原理是把用户密码等信息写入从库新的master.info文件中 [root@db02 ~]# ls -l /data/mysql/3306/data/master.info -rw-r----- 1 mysql mysql 86 Jul 15 06:37 /data/mysql/3306/data/master.info [root@db02 ~]# cat /data/mysql/3306/data/master.info 25 mysql-bin.000001 154 192.168.10.11 rep 123 3306 60 0 0 30.000 0 86400 0 4.启动从库同步开关并测试主从复制 (1).启动从库主从复制开关,并查看复制状态。 Slave [(none)]> start slave; Query OK, 0 rows affected (0.01 sec) Slave [(none)]> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.10.11 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 154 Relay_Log_File: db02-relay-bin.000002 Relay_Log_Pos: 320 Relay_Master_Log_File: mysql-bin.000001 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: 154 Relay_Log_Space: 526 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: Replicate_Ignore_Server_Ids: Master_Server_Id: 113306 Master_UUID: 7c145945-a680-11e9-baea-000c29a14cf7 Master_Info_File: /data/mysql/3306/data/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec) [root@db02 ~]# mysql -S /data/mysql/3306/mysql.sock -p -e "show slave status\G;"|egrep "IO_Running|SQL_Running:|_Behind_Master" Enter password: Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 0 #0表示状态已经同步 测试主从同步,在主库写入数据。 Master [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.00 sec) Master [(none)]> create database shenzhen; Query OK, 1 row affected (0.00 sec) Master [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | shenzhen | | sys | +--------------------+ 5 rows in set (0.00 sec) Slave [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | shenzhen | | sys | +--------------------+ 5 rows in set (0.01 sec) Master [shenzhen]> create table t1(id int); Query OK, 0 rows affected (0.03 sec) Master [shenzhen]> insert into t1(id) values(1); Query OK, 1 row affected (0.04 sec) Slave [(none)]> select * from shenzhen.t1; +------+ | id | +------+ | 1 | +------+ 1 row in set (0.00 sec) Master [(none)]> show slave hosts; +-----------+------+------+-----------+--------------------------------------+ | Server_id | Host | Port | Master_id | Slave_UUID | +-----------+------+------+-----------+--------------------------------------+ | 123306 | | 3306 | 113306 | ab0bfc5a-a681-11e9-bf5d-000c296165a9 | +-----------+------+------+-----------+--------------------------------------+ 1 row in set (0.00 sec) Master [(none)]> show processlist; +----+------+---------------------+------+-------------+------+---------------------------------------------------------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+---------------------+------+-------------+------+---------------------------------------------------------------+------------------+ | 6 | root | localhost | NULL | Query | 0 | starting | show processlist | | 8 | rep | 192.168.10.12:55924 | NULL | Binlog Dump | 270 | Master has sent all binlog to slave; waiting for more updates | NULL | +----+------+---------------------+------+-------------+------+---------------------------------------------------------------+------------------+ 2 rows in set (0.00 sec) [root@db01 ~]# cat /data/mysql/3306/data/auto.cnf [auto] server-uuid=7c145945-a680-11e9-baea-000c29a14cf7 [root@db02 ~]# mysql -S /data/mysql/3306/mysql.sock -p -e "show slave status\G;"|egrep "Master_UUID" Enter password: Master_UUID: 7c145945-a680-11e9-baea-000c29a14cf7 5.MySQL主从复制线程状态说明及用途 (1).登录主库查看mysql主从复制线程状态说明 Master [(none)]> show full processlist; +----+------+---------------------+------+-------------+------+---------------------------------------------------------------+-----------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+---------------------+------+-------------+------+---------------------------------------------------------------+-----------------------+ | 6 | root | localhost | NULL | Query | 0 | starting | show full processlist | | 8 | rep | 192.168.10.12:55924 | NULL | Binlog Dump | 386 | Master has sent all binlog to slave; waiting for more updates | NULL | +----+------+---------------------+------+-------------+------+---------------------------------------------------------------+-----------------------+ 2 rows in set (0.00 sec) Master [(none)]> show full processlist\G *************************** 1. row *************************** Id: 6 User: root Host: localhost db: NULL Command: Query Time: 0 State: starting Info: show full processlist *************************** 2. row *************************** Id: 8 User: rep Host: 192.168.10.12:55924 db: NULL Command: Binlog Dump #用于复制的主库线程 Time: 401 State: Master has sent all binlog to slave; waiting for more updates #当前状态 Info: NULL 2 rows in set (0.00 sec) (2).登录从库查看mysql主从复制线程状态说明 Slave [(none)]> show processlist\G *************************** 1. row *************************** Id: 2 User: root Host: localhost db: NULL Command: Query Time: 0 State: starting Info: show processlist *************************** 2. row *************************** Id: 4 User: system user Host: db: NULL Command: Connect Time: 510 State: Waiting for master to send event #线程已经连接上主服务器,正在等待二进制binlog日志事件的到达。 Info: NULL *************************** 3. row *************************** Id: 5 User: system user Host: db: NULL Command: Connect Time: 319 State: Slave has read all relay log; waiting for more updates Info: NULL 3 rows in set (0.00 sec) 6.主从复制存在的问题 (1).主库show master status;没有返回状态结果 原因是binlog功能没打开或者没生效。 (2).change master to的时候参数不能有空格。 (3).mysql服务无法启动 数据库目录权限和用户属主问题,数据库目录使用mysql用户。 my.cnf文件参数出错。 数据库初始化有问题,需要重新初始化。 (4).先在从库创建一个库,然后在主库创建同名的库,导致主从数据冲突。 stop slave; set global sql_slave_skip_counter=1; start slave; (5).mysql自身的原因,以及人为重复插入数据。 (6).不同的数据库版本会引起不同步,主从数据库版本不一致。 (7).mysql运行错误,或者程序有bug. (8).binlog记录模式,例如row level模式就比默认的语句模式要好。
来源:https://www.cnblogs.com/zhouwanchun/p/11186312.html