需求:实现主从复制,且可以向从服务器写数据。
一、主服务器配置 1、启用binlog并设置服务器ID
编辑主服务器
的配置文件 /etc/my.cnf
(宝塔默认),添加如下内容:
1 2 3 4 5 [mysqld] #不带路径则与数据库所在路径一致 log-bin=/www/server/data/mysql-bin #服务器编号,在主从架构中必须唯一 server-id=1
如果省略server-id(或将其显式设置为默认值0),则主服务器
拒绝来自从服务器
的任何连接。
2、设置binlog存放路径/www/server/data
可写权限
1 2 mkdir /www/server/data chown mysql.mysql /www/server/data
宝塔默认存放在/www/server/data
并设置可写权限,此步骤可跳过。
3、其他设置 为了在使用带事务的InnoDB进行复制设置时尽可能提高持久性和一致性,应该在主服务器
的 my.cnf
文件中使用以下配置项:
1 2 innodb_flush_log_at_trx_commit = 1 sync_binlog = 100
注意: 默认sync_binlog=0
,表示MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。 如果sync_binlog>0
,表示每sync_binlog
次事务提交,MySQL调用文件系统的刷新操作将缓存刷下去。最安全的就是sync_binlog=1
了,表示每次事务提交,MySQL都会把binlog刷下去,是最安全但是性能损耗最大的设置。这样的话,在数据库所在的主机操作系统损坏或者突然掉电的情况下,系统才有可能丢失1个事务的数据。 很多MySQL DBA设置的sync_binlog并不是最安全的1,而是100或者是0。 参考:https://www.cnblogs.com/xuxubaobao/p/10839979.html
4、重启MySql
1 /etc/init.d/mysqld restart
5、检查skip_networking是否为OFF 确保在主服务器
上 skip_networking
选项处于 OFF
关闭状态, 这是默认值。 如果是启用ON
的,则从服务器
无法与主服务器
通信,并且复制失败。
1 2 3 4 5 6 7 mysql> show variables like '%skip_networking%'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | skip_networking | OFF | +-----------------+-------+ 1 row in set (0.00 sec)
6、创建一个专门用于复制数据的用户 每个从服务器
需要使用Mysql 主服务器上的用户名和密码连接到主服务器。 例如,计划使用用户 simon
可以从任何主机上连接到主服务器
上进行复制操作, 并且用户 simon
仅可以使用复制的权限。 在主服务器Mysql中执行如下操作:
1 2 3 4 5 6 #创建用户 CREATE USER 'simon'@'%' #开通Repl_slave_priv: Y权限 grant replication slave on *.* to 'simon'@'%' identified by '2019Simon'; show grants for 'simon'@'%'; #revoke all on *.* from 'simon'@'%'; #移除权限
为了验证创建用户是否成功可用,我们在从服务器
上尝试一下登录:
1 mysql -h115.29.*.108 -usimon -p2019Simon
如果可以正常登录,说明成功可用。如果不行,请检查一下防火墙安全规则,开放3306端口。
二、备份数据 情况一:主服务器中已经存在数据,而且数据量不大
1、使用mysqldump
命令从主库导出数据,并写入二进制日志
1 2 cd ~ mysqldump -uroot -pee5ff2292e649127 --single-transaction --master-data --databases db_ssp > db_ssp_bak.sql
--master-data
参数,锁定所有表并写入二进制日志,个人理解:是告诉从服务器
从刚刚导出数据的哪个点开始同步数据。 如果不使用 –master-data 参数,则需要手动锁定单独会话中的所有表。 如果使用–ignore-table 参数,可忽略某个表,忽略多个表时,如:--ignore-table=db_ssp.ssp_ads_fail_log --ignore-table=db_ssp.ssp_channel_flow_collect
InnoDB引擎可带--single-transaction
参数,以上只针对某一个数据库,如果是所有数据库,则执行:
1 2 cd ~ mysqldump -uroot -pee5ff2292e649127 --all-databases --master-data=1 > all.sql
2、在主服务器
中使用rsync
工具,把备份出来的数据传输到从服务器
中。
1 rsync -P --rsh=ssh db_ssp_bak20191122.sql 47.103.38.242:/root/
3、导入从服务器
数据库
1 2 mysql> use db_ssp; mysql> source /root/db_ssp_bak20191122.sql;
情况二:主服务器中已经存在数据,而且数据量很大 略
情况三:主服务器中无数据 略
三、从服务器配置 1、启用binlog并设置服务器ID
1 2 3 4 5 [mysqld] #不带路径则与数据库所在路径一致 log-bin=/www/server/data/mysql-bin #服务器编号,在主从架构中必须唯一 server-id=2
2、配置要复制的和忽略的数据库
1 2 3 4 5 6 7 8 9 10 11 replicate_do_db=db_ssp #replicate_do_db=db_ssp2 #如果复制多个库,不用逗号隔开,而是一行一个 replicate_ignore_db=information_schema #忽略复制mysql5.7默认的4个库 replicate_ignore_db=performance_schema replicate_ignore_db=mysql replicate_ignore_db=sys replicate_ignore_table=db_ssp.ssp_admin_user #忽略复制db_ssp库中的几张表 replicate_ignore_table=db_ssp.ssp_ads_access_count replicate_ignore_table=db_ssp.ssp_ads_fail_log replicate_ignore_table=db_ssp.ssp_channel_flow_collect replicate_ignore_table=db_ssp.ssp_stat_income_display
replicate_do_db
为白名单,表示同步哪几个数据库,注意:在my.cnf中设置多个数据库时,不能使用逗号隔开,需要一行一个。如果只复制指定的表,使用replicate_do_table=表名
;replicate_ignore_db
为黑名单,表示不同步哪几个数据库。如果不复制指定的表replicate_ignore_table=库名.表名
。 以上参数仅限在从服务器
上设置。 也可以在主服务器
上设置:
1 2 binlog_do_db=db_ssp binlog_do_db=db_ssp2
但过滤功能会造成一定的负载,推荐放在从服务器
上配置。
四、启动主从复制 1、进入从服务器
,登录Mysql,设置要复制的主服务器信息
1 mysql> change master to MASTER_HOST='115.29.*.108', MASTER_USER='simon', MASTER_PASSWORD='2019Simon';
分别输入主服务器的IP、上面创建的专用于复制的用户名和密码,回车。
2、启动从服务器
的复制线程
3、检查是否成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 115.29.191.108 //主库IP Master_User: simon //复制用户名(连接主库的用户) Master_Port: 3306 //主库的端口 Connect_Retry: 60 //断链之后重试次数 Master_Log_File: mysql-bin.000004 //已经获取到binlog的文件名 Read_Master_Log_Pos: 428027692 //已经获取到的binlog位置号 Relay_Log_File: iZuf61lyoku3o73ozrd7x1Z-relay-bin.000004 //从库已经运行过的relaylog的文件名 Relay_Log_Pos: 252264496 //从库已经运行过的relay的位置号 Relay_Master_Log_File: mysql-bin.000004 //主库当前最新binlog文件名 Slave_IO_Running: Yes //从库IO线程状态 Slave_SQL_Running: Yes //从库SQL线程状态 Replicate_Do_DB: db_ssp Replicate_Ignore_DB: information_schema,performance_schema,mysql,sys 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: 428027544 Relay_Log_Space: 428028296 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: 1 Master_UUID: a3d29300-efeb-11e9-830b-00163e0ac428 Master_Info_File: /www/server/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) ERROR: No query specified
从以上结果中,我们可以看到Slave_IO_Running: Yes
( I/O 线程)、 YESSlave_SQL_Running: Yes
(SQL线程)都是yes
,表示主从复制搭建成功!
五、常见问题 1、MySQL主从复制故障,报1007错误的解决办法 通过show slave status
我们发现如下错误:
1 2 Last_SQL_Errno: 1007 Last_SQL_Error: Error 'Can't create database 'db_ssp'; database exists' on query. Default database: 'db_ssp'. Query: 'create database `db_ssp` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci'
答: 解决方法一:直接跳过该步骤
1 2 3 stop slave; set global sql_slave_skip_counter=1; start slave;
解决方法二:根据可以忽略的错误号修改从服务器
的配置文件
1 2 vim /etc/my.cnf slave-skip-errors=1007,1008,1032,1062
参考:https://www.2cto.com/database/201807/763757.html
2、MySQL主从复制故障,报1062错误的解决办法 答:先登录从服务器
的Mysql,执行show slave status\G;
,发现如下错误提示:
1 2 3 4 5 6 Slave_IO_Running: Yes Slave_SQL_Running: No Last_Errno: 1062 Last_Error: Error 'Duplicate entry '87' for key 'PRIMARY'' on query. Default database: 'db_ssp'. Query: 'INSERT INTO `ssp_stat_income_display` (`ad_id`, `channel_id`, `show_num`, `click_num`, `date`, `media_id`) VALUES (10, 5, 240, 18, 20191123, 4)' Last_SQL_Errno: 1062 Last_SQL_Error: Error 'Duplicate entry '87' for key 'PRIMARY'' on query. Default database: 'db_ssp'. Query: 'INSERT INTO `ssp_stat_income_display` (`ad_id`, `channel_id`, `show_num`, `click_num`, `date`, `media_id`) VALUES (10, 5, 240, 18, 20191123, 4)'
从以上反馈中可以得知,Slave_IO线程正常,即从主服务器
上同步Relay log
(中断日志)是正常的,Slave_SQL线程处于NO
状态,即从服务器
从Relay log
(中断日志)中执行sql命令失败。 Last_SQL_Error告诉我们表中id=87的主键值已经存在了,插入失败。原因是因为同事在从服务器
(测试环境)上做了写入操作,导致Slave_SQL线程执行命令失败,主从同步中断。 恢复操作如下:
1 2 3 4 5 6 stop slave; change master to MASTER_HOST='115.29.*.108', MASTER_USER='simon', MASTER_PASSWORD='2019Simon'; start slave; #发现再次出现了上面第1个问题的错误 stop slave; set global sql_slave_skip_counter=1; start slave;
参数sql_slave_skip_counter跳过的是event,不是单个事务,参考:https://blog.csdn.net/weixin_34236869/article/details/90251043 也可以将数据库设置成readonly
3、从服务器
的my.cnf
添加replicate_lgnore_table
后,启动不了,提示如下:
1 2 3 [....] Starting mysqld (via systemctl): mysqld.serviceJob for mysqld.service failed because the control process exited with error code. See "systemctl status mysqld.service" and "journalctl -xe" for details. failed!
原因是:从库已经存在之前的relay log,解决办法同第4个问题
4、从服务器
Mysql执行start slave
后报错ERROR1872,提示如下:
1 ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository
原因是:从库已经存在之前的relay log,解决办法:使用RESET SLAVE语句,清除master信息和relay日志的信息,删除所有的relay日志文件,并开始创建一个全新的中继日志
1 2 mysql> stop slave; mysql> reset slave;
5、在不影响主从复制的情况下,假设我们需要在主服务器
上执行一些SQL语句,但又不想同步到从服务器
,怎么办? 答:登录mysql命令窗口,执行SET sql_log_bin=0
,本次连接mysql的session里面所输入并执行的语句都不会被计入bin_log,也不会被从服务器
执行。执行SET sql_log_bin=1
又可以恢复计入bin_log,很有用,强调一下:SET sql_log_bin=0
这个设置只对当前这次连接有效,不影响其他操作计入bin_log。 测试方法:一边在navicat
上修改,一边在mysql命令窗口修改,观察主从变化情况。
更多故障排查,参考:https://www.jianshu.com/p/ecd00306cf92
六、附录 主服务器my.cnf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 [client] #password = your_password port = 3306 socket = /tmp/mysql.sock [mysqld] port = 3306 socket = /tmp/mysql.sock datadir = /www/server/data default_storage_engine = InnoDB performance_schema_max_table_instances = 400 table_definition_cache = 400 skip-external-locking key_buffer_size = 64M max_allowed_packet = 100G table_open_cache = 256 sort_buffer_size = 1M net_buffer_length = 4K read_buffer_size = 1M read_rnd_buffer_size = 256K myisam_sort_buffer_size = 16M thread_cache_size = 32 query_cache_size = 32M tmp_table_size = 64M sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES explicit_defaults_for_timestamp = true #skip-name-resolve max_connections = 500 max_connect_errors = 100 open_files_limit = 65535 log-bin=mysql-bin binlog_format=mixed server-id = 1 expire_logs_days = 10 slow_query_log=1 slow-query-log-file=/www/server/data/mysql-slow.log long_query_time=0.1 log_queries_not_using_indexes=on early-plugin-load = "" innodb_data_home_dir = /www/server/data innodb_data_file_path = ibdata1:10M:autoextend innodb_log_group_home_dir = /www/server/data innodb_buffer_pool_size = 256M innodb_log_file_size = 128M innodb_log_buffer_size = 32M innodb_flush_log_at_trx_commit = 1 sync_binlog = 0 innodb_lock_wait_timeout = 50 innodb_max_dirty_pages_pct = 90 innodb_read_io_threads = 2 innodb_write_io_threads = 2 [mysqldump] user=root password="ee5ff2292e649***" quick max_allowed_packet = 500M [mysql] no-auto-rehash [myisamchk] key_buffer_size = 64M sort_buffer_size = 1M read_buffer = 2M write_buffer = 2M [mysqlhotcopy] interactive-timeout
从服务器my.cnf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 [client] #password = your_password port = 3306 socket = /tmp/mysql.sock [mysqld] port = 3306 socket = /tmp/mysql.sock datadir = /www/server/data default_storage_engine = InnoDB performance_schema_max_table_instances = 400 table_definition_cache = 400 skip-external-locking key_buffer_size = 128M max_allowed_packet = 100G table_open_cache = 512 sort_buffer_size = 2M net_buffer_length = 4K read_buffer_size = 2M read_rnd_buffer_size = 256K myisam_sort_buffer_size = 32M thread_cache_size = 64 query_cache_size = 64M tmp_table_size = 64M sql-mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES explicit_defaults_for_timestamp = true #skip-name-resolve max_connections = 500 max_connect_errors = 100 open_files_limit = 65535 log-bin=mysql-bin binlog_format=mixed server-id = 2 expire_logs_days = 10 slow_query_log=1 slow-query-log-file=/www/server/data/mysql-slow.log long_query_time=0.1 log_queries_not_using_indexes=on early-plugin-load = "" #自定义================================================ replicate_do_db=db_ssp replicate_ignore_db=information_schema replicate_ignore_db=performance_schema replicate_ignore_db=mysql replicate_ignore_db=sys replicate_ignore_table=db_ssp.ssp_admin_user replicate_ignore_table=db_ssp.ssp_ads_access_count replicate_ignore_table=db_ssp.ssp_ads_fail_log replicate_ignore_table=db_ssp.ssp_channel_flow_collect replicate_ignore_table=db_ssp.ssp_stat_income_display slave-skip-errors=1007,1008,1032,1062 #================================================ innodb_data_home_dir = /www/server/data innodb_data_file_path = ibdata1:10M:autoextend innodb_log_group_home_dir = /www/server/data innodb_buffer_pool_size = 512M innodb_log_file_size = 256M innodb_log_buffer_size = 64M innodb_flush_log_at_trx_commit = 1 innodb_lock_wait_timeout = 50 innodb_max_dirty_pages_pct = 90 innodb_read_io_threads = 2 innodb_write_io_threads = 2 [mysqldump] quick max_allowed_packet = 500M [mysql] no-auto-rehash [myisamchk] key_buffer_size = 128M sort_buffer_size = 2M read_buffer = 2M write_buffer = 2M [mysqlhotcopy] interactive-timeout
七、心得 1、在主从复制架构中,为了避免从服务器
复制因为人为写原因导致中断,可以将库设置为只读:mysql> set global read_only=1;
(也可以将从服务器
的 my.cnf 设置 read-only=1) 这样的话,从服务器
上的数据库就被设置成全局只读了,但是如果只针对某一个数据库只读,可以创建一个只读用户(只能select)即可。 解除全局只读命令:mysql> set global read_only=0;
参考:https://blog.csdn.net/u013636377/article/details/50905768
参考:https://www.jianshu.com/p/faf0127f1cb2 https://blog.csdn.net/z69183787/article/details/70183284 https://www.jianshu.com/p/ecd00306cf92 https://www.imooc.com/learn/539 MySQL主从复制教程https://blog.csdn.net/tr1912/article/details/81302648 双机热备,即主主复制,看懂了,哈哈https://dev.mysql.com/doc/refman/5.7/en/replication-options-slave.html#option_mysqld_replicate-ignore-table 官方主从复制参数详解