• Mysql双主实战


    参考:
    http://dev.mysql.com/doc/refman/5.1/en/replication-options-slave.html
    http://blog.chinaunix.net/uid-26446098-id-3267556.html

    一、 环境
    master1 192.168.11.100
    CentOS release 6.2

    master2 192.168.11.110
    CentOS release 6.2


    二、软件安装
    yum -y install mysql-server perl lua


    三、配置
    1、基本目录准备
    两台服务器分别执行
    数据目录和binlog目录
    [root@master1 ~]# mkdir -p /data/mysql/binlogs && chown -R mysql.mysql /data/mysql/
    日志目录
    [root@master1 ~]# mkdir /data/logs/mysql/ && chown -R mysql.mysql /data/logs/mysql/
    binlog目录


    2、配置
    两台服务器分别执行
    [root@master1 ~]# egrep -v '^#|^$' /usr/share/doc/mysql-server-5.1.69/my-huge.cnf > /etc/my.cnf
    [root@master2 ~]# egrep -v '^#|^$' /usr/share/doc/mysql-server-5.1.69/my-huge.cnf > /etc/my.cnf
    master1配置文件
    [root@master1 ~]# cat /etc/my.cnf
    ### NO-3306 Master ###
    [mysqld]
    datadir = /data/mysql/
    port = 3306
    socket = /data/mysql/mysql.sock
    pid-file = /data/mysql/mysql.pid

    #log
    log-error = /data/logs/mysql/3306_error.log
    long_query_time = 2
    slow-query-log-file = /data/logs/mysql/3306_slow.log

    log-bin = binlogs/mysql-bin
    binlog_format = ROW
    relay-log = binlogs/mysql-relay-bin

    #data
    innodb_data_file_path = ibdata1:500M;ibdata2:500M:autoextend
    innodb_buffer_pool_size = 256M
    innodb_additional_mem_pool_size = 50M
    innodb_log_file_size = 256M
    innodb_open_files = 500
    back_log = 1000
    join_buffer_size = 8M
    query_cache_size = 16M
    read_buffer_size = 4M
    sort_buffer_size = 8M
    innodb_thread_concurrency = 8

    character_set_server = utf8
    init-connect = 'SET NAMES utf8'

    replicate-ignore-db = mysql
    replicate-ignore-db = test
    replicate-ignore-db = performance_schema

    skip-name-resolve

    skip-external-locking
    slave-skip-errors = all
    server-id = 33061
    log-slave-updates = 1

    [mysqldump]
    quick
    max_allowed_packet = 16M
    [mysql]
    no-auto-rehash

    [myisamchk]
    key_buffer_size = 256M
    sort_buffer_size = 256M
    read_buffer = 2M
    write_buffer = 2M

    [mysqlhotcopy]
    interactive-timeout

    master2 配置文件 和master一样 不过是serverid增加1

    ### NO-3306 Master backup ###
    [mysqld]
    datadir = /data/mysql/
    port = 3306
    socket = /data/mysql/mysql.sock
    pid-file = /data/mysql/mysql.pid

    #log
    log-error = /data/logs/mysql/3306_error.log
    long_query_time = 2
    slow-query-log-file = /data/logs/mysql/3306_slow.log

    log-bin = binlogs/mysql-bin
    binlog_format = ROW
    relay-log = binlogs/mysql-relay-bin

    #data
    innodb_data_file_path = ibdata1:500M;ibdata2:500M:autoextend
    innodb_buffer_pool_size = 256M
    innodb_additional_mem_pool_size = 50M
    innodb_log_file_size = 256M
    innodb_open_files = 500
    back_log = 1000
    join_buffer_size = 8M
    query_cache_size = 16M
    read_buffer_size = 4M
    sort_buffer_size = 8M
    innodb_thread_concurrency = 8

    character_set_server = utf8
    init-connect = 'SET NAMES utf8'

    replicate-ignore-db = mysql
    replicate-ignore-db = test
    replicate-ignore-db = performance_schema

    skip-name-resolve
    skip-external-locking
    slave-skip-errors = all
    server-id = 33062
    log-slave-updates = 1

    [mysqldump]
    quick
    max_allowed_packet = 16M
    [mysql]
    no-auto-rehash

    [myisamchk]
    key_buffer_size = 256M
    sort_buffer_size = 256M
    read_buffer = 2M
    write_buffer = 2M

    [mysqlhotcopy]
    interactive-timeout


    四、初始化数据库并启动
    1、初始化
    [root@master1 ~]# mysql_install_db --datadir=/data/mysql/ --user=mysql --force
    [root@master2 ~]# mysql_install_db --datadir=/data/mysql/ --user=mysql --force

    2、启动
    [root@master1 ~]# /usr/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &
    [root@master2 ~]# /usr/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &

    3、权限
    [root@master1 ~]# mysqladmin -S /data/mysql/mysql.sock -uroot -p password 'password'
    Enter password:

    [root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password
    复制权限
    mysql> grant REPLICATION SLAVE on *.* to 'repl'@'192.168.11.%' identified by 'replpwd';
    proxy权限
    mysql> grant all on *.* to 'dbproxy'@'192.168.11.%' identified by 'dbproxypwd';

    同样的操作在master2上执行一遍

    五、同步

    同步前再次确认网络连通情况
    [root@master1 ~]# telnet 192.168.11.110 3306
    [root@master2 ~]# telnet 192.168.11.100 3306
    1、master1做主master2做从
    [root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"show master status;"
    +------------------+----------+--------------+------------------+
    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +------------------+----------+--------------+------------------+
    | mysql-bin.000004 | 106 | | |
    +------------------+----------+--------------+------------------+
    mysql> change master to MASTER_HOST='192.168.11.100',MASTER_PORT=3306,MASTER_USER='repl',MASTER_PASSWORD='replpwd',MASTER_LOG_FILE='mysql-bin.000004',MASTER_LOG_POS=106;
    Query OK, 0 rows affected (0.03 sec)
    mysql> start slave;
    Query OK, 0 rows affected (0.01 sec)
    mysql> show slave statusG;
    *************************** 1. row ***************************
    Slave_IO_State: Waiting for master to send event
    Master_Host: 192.168.11.100
    Master_User: repl
    Master_Port: 3306
    Connect_Retry: 60
    Master_Log_File: mysql-bin.000004
    Read_Master_Log_Pos: 106
    Relay_Log_File: mysql-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: mysql,test,performance_schema
    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: 106
    Relay_Log_Space: 406
    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:
    1 row in set (0.00 sec)


    2、master2做主master1做从
    [root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"show master status;"
    +------------------+----------+--------------+------------------+
    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +------------------+----------+--------------+------------------+
    | mysql-bin.000005 | 106 | | |
    +------------------+----------+--------------+------------------+

    [root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password
    mysql> change master to MASTER_HOST='192.168.11.110',MASTER_PORT=3306,MASTER_USER='repl',MASTER_PASSWORD='replpwd',MASTER_LOG_FILE='mysql-bin.000005',MASTER_LOG_POS=106;
    Query OK, 0 rows affected (0.03 sec)
    mysql> start slave;
    Query OK, 0 rows affected (0.01 sec)

    mysql> show slave statusG;
    *************************** 1. row ***************************
    Slave_IO_State: Waiting for master to send event
    Master_Host: 192.168.11.110
    Master_User: repl
    Master_Port: 3306
    Connect_Retry: 60
    Master_Log_File: mysql-bin.000005
    Read_Master_Log_Pos: 106
    Relay_Log_File: mysql-relay-bin.000002
    Relay_Log_Pos: 251
    Relay_Master_Log_File: mysql-bin.000005
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
    Replicate_Do_DB:
    Replicate_Ignore_DB: mysql,test,performance_schema
    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: 106
    Relay_Log_Space: 406
    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:
    1 row in set (0.00 sec)

    六、测试
    1、验证master1复制到master2
    再master1创建库master1和表test_jin测试
    [root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"create database master1;"
    [root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"show databases;" |grep master1
    master1
    [root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"create table master1.test_jin (id int(6) not null,name varchar(20) not null);"
    [root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"use master1;show tables;"
    +-------------------+
    | Tables_in_master1 |
    +-------------------+
    | test_jin |
    +-------------------+
    [root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"insert into master1.test_jin values (100001,'kaijin');"
    [root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"select * from master1.test_jin;"
    +--------+--------+
    | id | name |
    +--------+--------+
    | 100001 | kaijin |
    +--------+--------

    可见从master1复制到master2成功

    2、验证master2复制到master1
    [root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"create database master2;"
    [root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"show databases;" |grep master2
    master2

    [root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"create table master2.test_master2 (id int(6) not null,name varchar(20) not null);"
    [root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"use master2;show tables;"
    +-------------------+
    | Tables_in_master2 |
    +-------------------+
    | test_master2 |
    +-------------------+

    [root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"insert into master2.test_master2 values (100002,'master2');"
    [root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"select * from master2.test_master2;"
    +--------+---------+
    | id | name |
    +--------+---------+
    | 100002 | master2 |
    +--------+---------+

    可见
    验证master2复制到master1成功

    双主相互复制成功

    这里也解决了我一个疑问,创建库是否也复制。毫无疑问是复制的,只要记录在binglog里都会复制


    七、总结
    1、几个重点
    1)log_slave_updates
    log-slave-updates 默认未开启
    log-slave-updates = 1开启
    log-slave-updates是为从库的写操作记录binlog
    在双主上必须配置。没有有它,双主是配不成的,关于它的详细介绍。在如下网址:
    http://dev.mysql.com/doc/refman/5.1/en/replication-options-slave.html#option_mysqld_log-slave-updates
    就是可以A -> B -> C,保证A可以作为master,复制到B,B可以作为master,复制到C.所以呢,如果A和B互相的话,就是双主了。
    2)binlog_format
    binlog_format = ROW
    详细介绍binlog_format几种模式的区别,可以参考
    http://codejm.iteye.com/blog/1540046

    八、未测试部分
    1、auto_increment 数据唯一性
    测试可以参考:http://www.mysqlops.com/2011/06/07/mysql-replication-data-consistency.html

    这里只往其中一个master写数据的保险的方法,如果要同时往两个master都写数据呢?
    模拟出现的问题(多主自增长ID重复)
    假如我们在master1,master2都建立一张test表,表中有一个auto increment的字段
    停掉master1的同步,在master2上对数据表test(存在自增长ID)执行插入操作,返回插入ID为1
    然后停掉master2的同步,在master1上对数据表test(存在自增长ID)执行插入操作,返回的插入ID也是1
    然后同时启动master1,master2,就会出现主键ID重复


    解决方法:
    我们只要保证两台服务器上插入的自增长数据不同就可以了
    master1增加配置
    auto_increment_increment=2
    auto_increment_offset=1

    master2增加配置
    auto_increment_increment=2
    auto_increment_offset=2

    具体
    auto_increment_increment和auto_increment_offset用于主服务器-主服务器(master-to-master)复制
    auto_increment_increment的默认值为1。
    auto_increment_offset的默认值为1。

    mysql> SHOW VARIABLES LIKE 'auto_inc%';
    +--------------------------+-------+
    | Variable_name | Value |
    +--------------------------+-------+
    | auto_increment_increment | 1 |
    | auto_increment_offset | 1 |
    +--------------------------+-------+
    2 rows in set (0.01 sec)


    auto_increment_offset确定AUTO_INCREMENT列值的起点。影响到在复制设置主可以有多少主服务器(例如将该值设置为10表示设置可以支持10个服务器)

    第一个变量名 auto_increment_increment 就是指 字段一次递增多少;
    第二个变量名 auto_increment_offset 指 自增字段的起始值。
    比如,有个表test,字段id为主键,自增;
    如果auto_increment_offset=1 , 并且auto_increment_increment=1,那么向表中插入第一条数据时,则该条数据的id=1,第二条id=2,第三条id=3以此类推……
    如果auto_increment_offset=2 , 并且auto_increment_increment=10,那么向表中插入第一条数据时,则该条数据的id=2,第二条id=12,第三条id=22以此类推……
    注意:如果auto_increment_offset的值大于auto_increment_increment的值,则auto_increment_offset的值被忽略。

    在这里设置
    auto_increment_increment=2
    auto_increment_offset=1
    第一条数据为1,第二条3,第三条5

    auto_increment_increment=2
    auto_increment_offset=2
    第一条数据为2,第二条4,第三条6

    2、read-only(保证只读)
    在第二master上添加次参数
    添加上测试一下
    read-only默认未开启
    read-only = 1 开启测试看看

    [root@master2 ~]# kill $(cat /data/mysql/mysql.pid)
    [root@master2 ~]#/usr/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &
    [root@master2 ~]# mysqladmin -S /data/mysql/mysql.sock --password=password VARIABLES |grep read_only
    | read_only | ON

    master2写入数据 看是否同步到master1
    [root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"insert into master2.test_master2 values (100003,'master3');"
    [root@master2 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"select * from master2.test_master2;"
    +--------+---------+
    | id | name |
    +--------+---------+
    | 100002 | master2 |
    | 100003 | master3 |
    +--------+---------+
    可以写入master2

    [root@master1 ~]# mysql -S /data/mysql/mysql.sock --password=password -e"select * from master2.test_master2;"
    +--------+---------+
    | id | name |
    +--------+---------+
    | 100002 | master2 |
    | 100003 | master3 |
    +--------+---------+
    也同步过去了
    Cause the slave to permit no updates except from slave threads or from users having the SUPER privilege. On a slave server,
    this can be useful to ensure that the slave accepts updates only from its master server and not from clients. This variable does not apply to TEMPORARY tables.
    官方说明
    导致从不允许任何更新,除了从从属线程或具有SUPER权限的用户。从服务器上的,这可能是有用的,以确保只从它的主服务器,而不是从客户的奴隶接受更新。此变量不适临时表。

    这个参数不加也不要紧。要使用第二个主,也是在proxy里加入readonly

  • 相关阅读:
    <Error>: CGContextRestoreGState
    Google 常用镜像收集
    NSCharacterSet 详解
    JAVA并发,CyclicBarrier
    JAVA并发,CountDownLatch使用
    JAVA并发,经典死锁案例-哲学家就餐
    Git-常用命令集合
    (转)《JAVA与模式》之模板方法模式
    JAVA并发,同步锁性能测试
    《转》JAVA并发编程:volatile关键字解析
  • 原文地址:https://www.cnblogs.com/diege/p/3355875.html
Copyright © 2020-2023  润新知