• 涂抹mysql笔记-mysql复制特性


    <>mysql复制特性:既可以实现整个服务(all databases)级别的复制,也可以只复制某个数据库或某个数据库中的某个指定的表对象。即可以实现A复制到B(主从单向复制),B再复制到C。也可以实现A直接复制到B和C(单主多从复制),甚至A的数据复制给B,B的数据也复制会A(双主复制)

    <>mysql复制处理数据时,有三种不同的模式:
    1、基于语句复制(Statement Based Replication):基于实际执行的sql语句的模式方案简称SBR
    2、基于记录复制(Row Based Replication):基于修改的列的复制模式简称RBR
    3、混合复制模式(Mixed Based Replication):基于上述两种模式的混合简称MBR

    <>创建复制环境:环境条件:master在创建过程中没有读写操作。
    1、停止mysql服务。
    2、复制数据文件 /mysql 打包复制到从服务器
    3、修改初始化参数添加server_id和开启binlog
    mkdir -p /mysql/relaylog
    [mysqld]
    server_id=0611
    log-bin=/mysql/binlog/mysql-bin
    relay-log=/mysql/relaylog/mysql-relay-bin
    relay-log-index=/mysql/relaylog/mysql-relay-bin.index
    master-info-file=/mysql/conf/master.info
    relay-log-info-file=/mysql/conf/relay-log.info
    4、创建复制用户:mysql中的slave若想获取二进制日志,它是得主动连接master节点去请求数据。因为slave节点将关于master的配置都保存在master.info文件中,该文件明文记录连接master节点的所有配置,包括连接的用户名、密码。所以最好单独建个复制账户保证安全性。
    system@(none)>grant replication slave on *.* to 'repl' @'192.168.1.%' identified by 'oralinux';
    Query OK, 0 rows affected (0.00 sec) 上述命令创建了一个名为repl的用户,允许从192.168.1网段连接服务器,仅拥有读取二进制日志的权限。
    5、获取master端的binlog位置和position,执行show master status;
    system@(none)>show master status;
    +------------------+----------+--------------+------------------+-------------------+
    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +------------------+----------+--------------+------------------+-------------------+
    | mysql-bin.000019 | 322 | | | |
    +------------------+----------+--------------+------------------+-------------------+
    File列显示当前正在使用的二进制日志文件名,Position则显示该日志文件中当前写入的位置。
    1 row in set (0.00 sec)
    6、配置slave端的选项文件:增加server_id
    mkdir -p /mysql/relaylog
    [mysqld]
    server_id=0612
    log-bin=/mysql/binlog/mysql-bin
    relay-log=/mysql/relaylog/mysql-relay-bin
    relay-log-index=/mysql/relaylog/mysql-relay-bin.index
    master-info-file=/mysql/conf/master.info
    relay-log-info-file=/mysql/conf/relay-log.info
    7、删除slave端data下的auto.cnf
    rm /mysql/data/auto.cnf
    8、启动slave服务并配置slave到master的连接:
    system@(none)>change master to master_host='192.168.1.6',master_port=3306,master_user='repl',master_password='oralinux',master_log_file='mysql-bin.000019',master_log_pos=322;
    Query OK, 0 rows affected, 2 warnings (0.08 sec)
    9、启动slave端:start slave;
    system@(none)>start slave;
    Query OK, 0 rows affected (0.02 sec)
    10、复制环境数据同步测试:
    prompt Master>
    Master>create table 5ienet.jason_v2(id int);
    Query OK, 0 rows affected (0.10 sec)
    创建好表后再slave节点查看表是否生成。
    prompt Slave>
    Slave>desc 5ienet.jason_v2;
    +-------+---------+------+-----+---------+-------+
    | Field | Type | Null | Key | Default | Extra |
    +-------+---------+------+-----+---------+-------+
    | id | int(11) | YES | | NULL | |
    +-------+---------+------+-----+---------+-------+
    1 row in set (0.00 sec)
    可以看到slave端表已经发现。如果slave端没有找到表对象,数据没有成功同步过来使用show slave status;查看slave端的数据接收和应用状态。
    Slave>show slave status G
    *************************** 1. row ***************************
    Slave_IO_State: Waiting for master to send event
    Master_Host: 192.168.1.6
    Master_User: repl
    Master_Port: 3306
    Connect_Retry: 60
    Master_Log_File: mysql-bin.000021
    Read_Master_Log_Pos: 228
    Relay_Log_File: mysql-relay-bin.000004
    Relay_Log_Pos: 391
    Relay_Master_Log_File: mysql-bin.000021
    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: 228
    Relay_Log_Space: 727
    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: 611
    Master_UUID: 2584299a-2100-11e7-af61-080027196296
    Master_Info_File: /mysql/data/master.info
    SQL_Delay: 0
    SQL_Remaining_Delay: NULL
    Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
    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
    1 row in set (0.00 sec)
    查看Last_IO_Error参数是否有值,如果有值则代表主从复制环境有误

    ##################################################################################################################################
    #修改relay_log生成位置mysql slave启动后会在data目录下生成mysql-relay-bin日志,这样不利于管理。修改要在mysql slave停止状态下修改。#
    #拷贝data下的mysql-relay-bin日志集索引文件到新建的relaylog路径下 #
    #mkdir /mysql/relaylog #
    #cp /mysql/data/mysql-relay-bin* /mysql/relaylog #
    #修改my.cnf #
    #[mysqld] #
    #relay-log=/mysql/relaylog/mysql-relay-bin #
    #relay-log-index=/mysql/relaylog/mysql-relay-bin.index #
    #编辑mysql-relay-bin.index把路径改为新的绝对路径,编辑relay-log.info文件也改为绝对路径。 #
    ##################################################################################################################################

    常用的复制环境管理命令:在slave节点执行获取该节点与master节点的同步信息:
    show slave status G
    Slave_IO_State:显示Slave当前状态
    Slave_IO_Running:显示I/O线程是否在允许,正常情况下应该在允许,除非dba手动将其停止,或者出现错误
    Slave_SQL_Running:显示sql线程是否在允许,正常情况下应该在运行,除非dba手动将其停止或者出现错误
    Last_IO_Error/Last_SQL_Error:正常情况下应该是控制,如果遇到错误那么在这里就会输出错误信息。
    Seconds_Behind_Master:显示当前slave节点与master节点的同步延迟。Slave节点接收到Master的日志文件和已经应用的日志文件位置之间的差距,比如说I/O线程接收到的日志文件写入位置为34560,而sql线程才应用到34000,这两个位置之间时间上的差距是1小时,那么Seconds_Behind_Master就会显示3600秒,而有可能此时Master已经写到34660的位置了,只是还没有被IO线程读取到slave节点,这个参数显示的值并不是完全精确的主从之间的延迟时间,而只是slave节点本地日志接收和应用上的差异。这个参数值最好是0,如果参数值较大(延迟较大)可能性有两种,一个是IO_THREAD在运行,但SQL_THREAD被停止了。如果不是手动停止的SQL_THREAD那么八成是出现错误了。那么可以根据Last_SQL_Error参数总的信息进一步分析。
    Master_Log_File/Read_Master_Log_Pos:显示当前读取的master节点二进制日志文件和文件位置。
    Relay_Master_Log_File/Exec_Master_Log_Pos:显示当前slave节点正在应用的日志文件位置。
    Relay_Log_File/Relay_Log_Pos:显示当前Slave节点正在处理中继的日志文件和位置

    Master>show processlist G
    *************************** 1. row ***************************
    Id: 5
    User: repl
    Host: linux02:55206
    db: NULL
    Command: Binlog Dump
    Time: 2813
    State: Master has sent all binlog to slave; waiting for binlog to be updated
    Info: NULL

    Slave>show processlist G
    *************************** 1. row ***************************
    Id: 4
    User: system user
    Host:
    db: NULL
    Command: Connect
    Time: 2726
    State: Waiting for master to send event
    Info: NULL
    *************************** 2. row ***************************
    Id: 5
    User: system user
    Host:
    db: NULL
    Command: Connect
    Time: 1493
    State: Slave has read all relay log; waiting for the slave I/O thread to update it
    Info: NULL
    通过Master/Slave中连接信息表明每一组Master、Slave都有三个线程(Master1个、Slave2个)维护复制环境中数据的同步。

    Master节点可以通过show slave hosts;语句查询该节点当前所有的Slave。
    Master>show slave hosts;
    +-----------+------+------+-----------+--------------------------------------+
    | Server_id | Host | Port | Master_id | Slave_UUID |
    +-----------+------+------+-----------+--------------------------------------+
    | 612 | | 3306 | 611 | 09228313-230e-11e7-bcc6-080027f93f02 |
    +-----------+------+------+-----------+--------------------------------------+
    1 row in set (0.00 sec)

    启停Slave线程:
    Slave>stop slave;
    Query OK, 0 rows affected (0.00 sec)

    Slave>show slave status G
    *************************** 1. row ***************************
    Slave_IO_State:
    Master_Host: 192.168.1.6
    Master_User: repl
    Master_Port: 3306
    Connect_Retry: 60
    Master_Log_File: mysql-bin.000021
    Read_Master_Log_Pos: 450
    Relay_Log_File: mysql-relay-bin.000007
    Relay_Log_Pos: 505
    Relay_Master_Log_File: mysql-bin.000021
    Slave_IO_Running: No
    Slave_SQL_Running: No
    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: 450
    Relay_Log_Space: 841
    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: NULL
    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: 611
    Master_UUID: 2584299a-2100-11e7-af61-080027196296
    Master_Info_File: /mysql/data/master.info
    SQL_Delay: 0
    SQL_Remaining_Delay: NULL
    Slave_SQL_Running_State:
    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
    1 row in set (0.00 sec)
    Slave>start slave;
    Query OK, 0 rows affected (0.00 sec)
    Slave>show slave status G
    *************************** 1. row ***************************
    Slave_IO_State: Waiting for master to send event
    Master_Host: 192.168.1.6
    Master_User: repl
    Master_Port: 3306
    Connect_Retry: 60
    Master_Log_File: mysql-bin.000021
    Read_Master_Log_Pos: 450
    Relay_Log_File: mysql-relay-bin.000008
    Relay_Log_Pos: 283
    Relay_Master_Log_File: mysql-bin.000021
    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: 450
    Relay_Log_Space: 841
    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: 611
    Master_UUID: 2584299a-2100-11e7-af61-080027196296
    Master_Info_File: /mysql/data/master.info
    SQL_Delay: 0
    SQL_Remaining_Delay: NULL
    Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
    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
    1 row in set (0.00 sec)

    Slave服务由两个线程组成:
    IO_THREAD:负责读取Master端的二进制日志,并写入到本地的中继日志(relay-log)并复制更新master.info文件
    SQL_THREAD:复制从本地中继日志中读取事件并执行。并复制更新relay-log.info文件
    这是两个独立的线程,他们的启动和停止也可以分别控制。这两个线程的启动和停止并没有依赖性,可以选择启动SQL_THREAD线程,停止IO_THREAD线程。或者做相反的操作。
    灵活利用这两个子线程的启停可以使复制环境的应用场景更加灵活,如下执行备份时为了保持备份数据一致性,很多人往往会选项停止整个slave,但是IO_THREAD并不需要停止,它可以继续从Master读取二进制日志,保持在本地的中继日志中。这样还可以起到对Master节点数据冗余保护的作用。我们只需要停止SQL_THREAD,记录下当前应用到的日志文件名和位置,就可以开始备份任务。因为此时slave不会有数据更新。相当于此时数据库处于只读状态,这样创建出来就是体制下备份了。当然数据在备份期间与master是不同步的

    单独启动或停止IO_THREAD/SQL_THREAD只需在start slave后加线程名称就可以
    Slave>stop slave sql_thread;
    Query OK, 0 rows affected (0.01 sec)

    Slave> start slave sql_thread;
    Query OK, 0 rows affected (0.29 sec)

    Slave>

    <>复制特性的实施原理和关键
    复制特性依赖于二进制日志,slave端获取master的二进制日志并应用这些日志进行数据同步。二进制日志在记录事件时支持多种格式由binlog_format参数控制:
    基于语句记录(Statement-Based Logging,SBL)对应的参数值为statement
    基于行格式记录(Row-Based Logging RBL)对应的参数值为row
    混合模式记录(Mixed-Based Logging MBL)对应的参数值为mixed

    复制格式种类从逻辑上将分为三类:
    基于语句复制(Statement-Based Replication SBR)二进制日志文件中保存的是执行的sql语句。5.1.4版本之前只有这一种日志记录方式
    基于行复制(Row-Based Replication RBR)二进制日志文件中写入事件时,记录的是变更的记录行的信息。
    混合记录模式(Mixed-Based Replication MBR)记录事件到二进制日志时根据需要动态修改日志的格式。注意这是一种记录的模式不是记录的格式。这种模式下,默认还是会选择基于语句的格式记录日志,只有在需要的场景下,才会自动切换成基于行的格式记录日志。
    mysql5.6版本中默认的日志记录格式是基于语句,建议修改为混合模式:
    [mysqld]
    binlog_format=mixed

    使用SBR的优点:
    1、技术成熟3.23版本就提供对这种记录格式的支持
    2、生成日志少,特别是对于大量更新及删除的操作。
    3、由于能够记录下数据库做过的所有变更操作日志可用于行为审计
    使用SBR的缺点:
    1、存在安全隐患,Master孔二道门椎间盘买个产生的修改操作(INSERT DELETE UPDATE REPLACE)并不是都能通过基于语句方式完整的复制到Slave节点,对于不确定的行为在基于语句复制时,很难确保Slave节点会执行并获得正确的数据。这点从逻辑上证明了主从出现不一致的合理性。比如说Master节点和Slaves节点分别执行FOUND_ROWS()、SYSDATE()、UUID()这类函数可能出现返回不同的结果,如果使用了这些函数那么执行语句时就排除下列警告信息(客户端通过show warnings查看):
    [Warning] Statement is not safe to log in Statement format
    2、执行insert...select语句时需要持有更多的行锁(相比RBR而言)
    3、update要扫描表(无可用索引情况下)时需要持有更多的行锁(相比RBR而言)
    4、对于InnoDB引擎,insert语句使用aotu_increment会阻塞其他insert语句。
    5、对于复杂的语句,Slave节点执行时语句必须先被评估,而对于基于row格式复制,则slave节点只需要修改具体的记录即可。(不必执行跟master端相同的sql语句,这既是有点也是缺点)
    6、如果语句在slave节点执行时操作失败,基于Statement格式复制就会增加主从不一致的概率
    7、如单条语句中执行的函数中调用now()返回日志相同,但是存储过程就不一定了
    8、对象定义必须(最好)拥有唯一键。主要是为了避免冲突。

    使用RBR的优点:
    1、所有修改都能被完全地复制到slave节点
    2、与其他RDBMS实现的技术类似,其他数据库软件管理和维护方面的经验也可以继承使用
    3、Master端执行修改操作时,仅需极少的锁持有,因此可获得更高的并发性能。
    使用RBR的缺点:
    1、可能会生产更多的日志。创建备份和恢复可能需要更长的时间。以及二进制日志会被更长时间加锁以写数据,也可能带来额外的并发性能上的问题。
    2、UDFS生成BLOB值需要花费比基于statement格式日志更长的时间。这是因为Blob列的值是被记录的,而不是语句生成的。
    3、不能通过分析日志来获取曾经执行过的语句。不过可通过mysqlbinlog工具能够看到哪些数据被修改了。
    4、对于非事务存储引擎,比如MyISAM表对象,Slave节点应用insert操作时,使用RBR模式要比使用SBR模式持有更强的锁定,这也就是说使用RBR模式在Slave节点上没有并行插入的概念。

    SBR和RBR不同场景的表现:
    1、有条很复杂的sql执行一小时最终修改了一条记录,若使用SBR模式那么salve节点也要执行一小时才能完成,但是使用RBR最终记录的是执行后的变更结果,那么slave端应用瞬秒就完成了。
    2、有条简单的sql语句,向库中插入一千万条语句,采用RBR模式一千万条记录生成的二进制日志非常多,那么slave端需要长时间接收,以后还得话长时间慢慢应用。若使用SBR那么二进制日志中记录的事件就是该条sqk语句,占不了几个字节,salve端很快就接收完毕,然后开始应用。总体开销比RBR模式小很多。

    MBR模式也是SBR模式,只有存在数据安全隐患时自动将记录格式变更为基于行格式记录。

    <>中继日志文件和状态文件:中继日志文件和二进制日志文件极为相似,这俩唯一的区别更多是逻辑上的,二进制日志文件用于保存节点自身产生的事件。中继日志文件则是保存接收自其它节点的事件(也是二进制格式的)也可以通过mysqlbinlog命令解析。中继日志文件默认保存在data下host_name-relay-bin.nnnnnn的命名规则。其保存路径可通过--relay-log和--relay-log-index参数进行自定义。

    slave节点在满足下列条件时触发创建新的中继日志文件,并更新相关索引文件:
    1、启动slaves节点I/O线程时
    2、执行日志刷新命令,比如flush logs或mysqladmin flush-logs等
    3、中继日志文件达到指定最大值。有两种情况:
    如果max_relay_log_size参数值大于0,则日志文件超过该值后即会重建。
    如果max_relay_log_size参数值为0,则通过max_binlog_size确定单个Relay日志文件的最大值。
    中继日志文件的管理可以完全交由slave节点的SQL_THREAD线程来维护。他会自动删除无用的中继日志文件,至于到底如何删除以及何时进行删除,并没有明确的机制由SQL_THRAD线程自己全部搞定。

    master.info和relay-log.info信息默认保存在data目录下,可以通过--master-info-file和--relay-log-info-file参数修改文件的名称和保存路径
    master.info:保存复制环境中连接Master节点的配置信息,5.6版本后也可以将这些信息保存在mysql.slave_master_info表对象
    relay-log.info:保存处理进度及中继日志文件的位置。5.6后也可以保存在mysql.slave_relay_log_info表对象中。

    <>复制过程规则:
    Slave节点在接收日志时没有选择权,Master节点写过的日志它全得收到本地,保存在中继日志文件中。
    1、库级过滤规则
    2、表级复制选项
    3、过滤规则的应用示例:Slave节点过滤Master节点jason库和jason_mc中所有对象,以及5ienet库下的rep_t1对象所有操作。并复制jason库下的j1表。
    master节点修改my.cnf:binlog_format=statement
    slave节点my.cnf文件:
    replicate-ignore-db=jason
    replicate-ignore-db=jason_mc
    replicate-ignore-table=5ienet.rep_t1
    replicate-do-table=jason.j1

    修改完后重启master和slave服务

    <>高级应用技巧
    1、通过Xtrabackup创建slave节点:操作过程不需要重启master节点。
    1.1、创建完整备份:使用我们封装好的脚本进行备份。脚本内容如下:
    [mysql@linux01 scripts]$ cat /mysql/scripts/mysql_env.ini
    #set env
    MYSQL_USER=system
    MYSQL_PASS='oralinux'

    #check parameter
    if [ $# -ne 1 ]
    then
    HOST_PORT=3306
    else
    HOST_PORT=$1
    fi

    新建mysql_full_backup_byxtra.sh
    #!/bin/sh
    #Created by jason 20170414

    source /mysql/scripts/mysql_env.ini

    BACKUP_PATH=/mysql/backup
    BACKUP_FILE=${BACKUP_PATH}/xtra_fullbak_`date +%F`.tar.gz
    BACKUPLOG_FILE=${BACKUP_PATH}/xtra_fullbak_`date +%F`.log
    ORI_CONF_FILE=/mysql/conf/my.cnf
    NEW_CONF_FILE=$BACKUP_PATH/my_`date +%F`.cnf
    MYSQL_PATH=/mysql/xtrabackup/bin
    MYSQL_CMD="${MYSQL_PATH}/innobackupex --defaults-file=$ORI_CONF_FILE --user=xtrabk --password='oralinux' --stream=tar /tmp"

    echo > $BACKUPLOG_FILE
    echo -e "===Jobs started at `date +%F' '%T' '%w`=== " >> $BACKUPLOG_FILE
    echo -e "===First cp my.cnf file to backup directory===" >> $BACKUPLOG_FILE
    /bin/cp $ORI_CONF_FILE $NEW_CONF_FILE
    echo > $BACKUPLOG_FILE

    echo -e "****Executed command:${MYSQL_CMD} | gzip > $BACKUP_FILE" >> $BACKUPLOG_FILE
    ${MYSQL_CMD} 2>> $BACKUPLOG_FILE | gzip - > $BACKUP_FILE
    echo -e "****Executed finished at `date +%F' '%T' '%w` ===" >> $BACKUPLOG_FILE
    echo -e "****Backup file size: `du -sh $BACKUP_FILE` === " >> $BACKUPLOG_FILE
    echo -e "---Find expired backup and delete those files---" >> $BACKUPLOG_FILE
    for tfile in $(/usr/bin/find $BACKUP_PATH/ -mtime +6)
    do
    if [ -d $tfile ] ; then
    rmdir $tfile
    elif [ -f $tfile ] ; then
    rm -f $tfile
    fi
    echo -e "---Delete file:$tfile---" >> $BACKUPLOG_FILE
    done
    echo -e " ===Job ended at `date +%F' '%T' '%w`=== " >> $BACKUPLOG_FILE
    ./mysql_full_backup_byxtra.sh创建备份。
    1.2、复制和创建备份集,scp把备份集复制到slave节点
    scp xtra_fullbak_2017-04-18.tar.gz linux02:/mysql/backup/
    scp my_2017-04-18.cnf linux02:/mysql/backup/
    chown mysql:mysql xtra_fullbak_2017-04-18.tar.gz
    chown mysql:mysql my_2017-04-18.cnf
    解压缩备份集注意执行解压时务必附加参数-i
    tar -zixvf xtra_fullbak_2017-04-18.tar.gz -C /mysql/data
    准备数据执行innobackupex命令附加--apply-log参数:
    innobackupex --apply-log /mysql/data 这一步是为了使数据文件达到一致性状态最后提示complete OK就对了。
    1.3、创建复制环境专用账户:前面已创建repl账户这里不做重复
    1.4、配置slave节点初始化参数文件:在master节点的初始化参数文件复制一份即可。修改slave节点my.cnf添加server_id=0612
    1.5、启动slave节点
    1.6、配置slave节点复制环境:查看Xtrabackup中的xtrabackup_binlog_info文件:
    [mysql@linux02 data]$ cat /mysql/data/xtrabackup_binlog_info
    mysql-bin.000022 120
    1.7、执行change master命令:
    system@(none)>change master to master_host='192.168.1.6',master_port=3306,master_user='repl',master_password='oralinux',master_log_file='mysql-bin.000022',master_log_pos=120;
    Query OK, 0 rows affected, 2 warnings (0.01 sec)
    1.8、启动slave服务:start slave;
    1.9、检查
    system@(none)>show slave status G
    *************************** 1. row ***************************
    Slave_IO_State: Waiting for master to send event
    Master_Host: 192.168.1.6
    Master_User: repl
    Master_Port: 3306
    Connect_Retry: 60
    Master_Log_File: mysql-bin.000022
    Read_Master_Log_Pos: 120
    Relay_Log_File: mysql-relay-bin.000002
    Relay_Log_Pos: 283
    Relay_Master_Log_File: mysql-bin.000022
    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: 120
    Relay_Log_Space: 456
    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: 611
    Master_UUID: 2584299a-2100-11e7-af61-080027196296
    Master_Info_File: /mysql/conf/master.info
    SQL_Delay: 0
    SQL_Remaining_Delay: NULL
    Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
    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
    1 row in set (0.00 sec)

    <>利用slave节点创建备份:
    1、停止slave服务中的SQL_THREAD线程
    2、记录当前接收和应用的二进制日志文件及位置
    3、执行备份命令
    4、再次记录当前接收和应用的二进制日志文件及位置
    5、启动slave服务中的SQL_THERAD线程。

    创建slave节点的备份脚本mysqldump方式:mysql_full_backup_slave.sh
    #!/bin/sh
    #Created by jason 20170418

    show_slave_status(){
    echo -e "---master.info:---" >> $BACKUPLOG_FILE
    cat /mysql/conf/master.info |sed -n '2,3p' >> $BACKUPLOG_FILE
    echo -e "--show slave status:---" >> $BACKUPLOG_FILE
    echo "show slave status G" | $MYSQL_CMD | egrep "Slave_IO_Running|Slave_SQL_Running|Master_Log_File|Read_Master_Log_Pos|Exec_Master_Log_Pos|Relay_Log_File|Relay_Log_Pos" >> $BACKUPLOG_FILE
    echo -e "" >> $BACKUPLOG_FILE
    }

    #source /mysql/scripts/mysql_env.ini
    #set env
    MYSQL_USER=system
    MYSQL_PASS='oralinux'

    #check parameter
    if [ $# -ne 1 ]
    then
    HOST_PORT=3306
    else
    HOST_PORT=$1
    fi

    BACKUP_PATH=/mysql/backup
    BACKUP_FILE=${BACKUP_PATH}/dbfullbak_`date +%F`.sql.gz
    BACKUPLOG_FILE=${BACKUP_PATH}/dbfullbak_`date +%F`.log
    MYSQL_PATH=/mysql/bin
    MYSQL_CMD="${MYSQL_PATH}/mysql -u${MYSQL_USER} -p${MYSQL_PASS} -S /mysql/conf/mysql.sock"
    MYSQL_DUMP="${MYSQL_PATH}/mysqldump -u${MYSQL_USER} -p${MYSQL_PASS} -S /mysql/conf/mysql.sock -A -R --single-transaction -l --default-character_set=utf8"
    echo > $BACKUPLOG_FILE
    echo -e "===Jobs started at `date +%F' '%T' '%w`=== " >> $BACKUPLOG_FILE
    echo -e "****stared position:===" >> $BACKUPLOG_FILE
    echo "stop slave SQL_THREAD;" | $MYSQL_CMD
    show_slave_status
    echo -e "****Executed command:${MYSQL_DUMP} | gzip > $BACKUP_FILE" >> $BACKUPLOG_FILE
    ${MYSQL_DUMP} | gzip > $BACKUP_FILE
    echo -e "****Executed finished at `date +%F' '%T' '%w` ===" >> $BACKUPLOG_FILE
    echo -e "****Backup file size: `du -sh $BACKUP_FILE` === " >> $BACKUPLOG_FILE
    echo -e "****recheck position===" >> $BACKUPLOG_FILE
    show_slave_status
    echo "start slave SQL_THREAD;" | $MYSQL_CMD
    echo -e "---Find expired backup and delete those files---" >> $BACKUPLOG_FILE
    for tfile in $(/usr/bin/find $BACKUP_PATH/ -mtime +6)
    do
    if [ -d $tfile ] ; then
    rmdir $tfile
    elif [ -f $tfile ] ; then
    rm -f $tfile
    fi
    echo -e "---Delete file:$tfile---" >> $BACKUPLOG_FILE
    done
    echo -e " ===Job ended at `date +%F' '%T' '%w`=== " >> $BACKUPLOG_FILE

    使用Xtrabackup方式备份mysql_full_backupxtra_slave.sh:
    #!/bin/sh
    #Created by jason 20170418

    show_slave_status(){
    echo -e "---master.info:---" >> $BACKUPLOG_FILE
    cat /mysql/conf/master.info |sed -n '2,3p' >> $BACKUPLOG_FILE
    echo -e "--show slave status:---" >> $BACKUPLOG_FILE
    echo "show slave status G" | $MYSQL_CMD | egrep "Slave_IO_Running|Slave_SQL_Running|Master_Log_File|Read_Master_Log_Pos|Exec_Master_Log_Pos|Relay_Log_File|Relay_Log_Pos" >> $BACKUPLOG_FILE
    echo -e "" >> $BACKUPLOG_FILE
    }

    #source /mysql/scripts/mysql_env.ini
    #set env
    MYSQL_USER=system
    MYSQL_PASS='oralinux'

    #check parameter
    if [ $# -ne 1 ]
    then
    HOST_PORT=3306
    else
    HOST_PORT=$1
    fi

    BACKUP_PATH=/mysql/backup
    BACKUP_FILE=${BACKUP_PATH}/xtra_fullbak_`date +%F`.tar.gz
    BACKUPLOG_FILE=${BACKUP_PATH}/xtra_fullbak_`date +%F`.log
    ORI_CONF_FILE=/mysql/conf/my.cnf
    NEW_CONF_FILE=$BACKUP_PATH/my_`date +%F`.cnf
    MYSQL_PATH=/mysql/bin
    MYSQL_BACKUP_PATH=/mysql/xtrabackup/bin
    MYSQL_CMD="${MYSQL_PATH}/mysql -u${MYSQL_USER} -p${MYSQL_PASS} -S /mysql/conf/mysql.sock"
    MYSQL_BACKUP="${MYSQL_BACKUP_PATH}/innobackupex --defaults-file=$ORI_CONF_FILE --user=xtrabk --password='oralinux' --stream=tar /tmp"
    echo > $BACKUPLOG_FILE
    echo -e "===Jobs started at `date +%F' '%T' '%w`=== " >> $BACKUPLOG_FILE
    echo -e "===First cp my.cnf file to backup directory===" >> $BACKUPLOG_FILE
    /bin/cp $ORI_CONF_FILE $NEW_CONF_FILE
    echo > $BACKUPLOG_FILE
    echo -e "****stared position:===" >> $BACKUPLOG_FILE
    echo "stop slave SQL_THREAD;" | $MYSQL_CMD
    show_slave_status
    echo -e "****Executed command:${MYSQL_BACKUP} | gzip > $BACKUP_FILE" >> $BACKUPLOG_FILE
    ${MYSQL_BACKUP} 2>> $BACKUPLOG_FILE | gzip - > $BACKUP_FILE
    echo -e "****Executed finished at `date +%F' '%T' '%w` ===" >> $BACKUPLOG_FILE
    echo -e "****Backup file size: `du -sh $BACKUP_FILE` === " >> $BACKUPLOG_FILE
    echo -e "****recheck position===" >> $BACKUPLOG_FILE
    show_slave_status
    echo "start slave SQL_THREAD;" | $MYSQL_CMD
    echo -e "---Find expired backup and delete those files---" >> $BACKUPLOG_FILE
    for tfile in $(/usr/bin/find $BACKUP_PATH/ -mtime +6)
    do
    if [ -d $tfile ] ; then
    rmdir $tfile
    elif [ -f $tfile ] ; then
    rm -f $tfile
    fi
    echo -e "---Delete file:$tfile---" >> $BACKUPLOG_FILE
    done
    echo -e " ===Job ended at `date +%F' '%T' '%w`=== " >> $BACKUPLOG_FILE
    通过脚本备份完成后查看读取和应用的master节点二进制日志及位置有无变化,只要Relay_Master_Log_File和Exec_Master_Log_Pos属性值没有变化我们就可以人为备份数据是一致的。后续希望时间增量备份,只要把备份操作之后的所有二进制文件保存到备份路径下即可。恢复时从指定位置(Relay_Master_Log_File和Exec_Master_Log_Pos顺序所在的位置)开始应用即可。

    <>复制文件方式创建备份:
    1、停止Slave节点数据库服务
    2、复制数据库主目录
    3、启动slave节点数据库服务

    <>部署级联Slave增强复制性能
    --log-slave-updates参数即使是应用中继日志产生的数据库修改,也将会写到本地二进制日志文件中。
    1、配置RelaySlave节点修改my.cnf在[mysqld]区块中添加log-salve-update如下:
    vi /mysql/conf/my.cnf
    [mysqld]
    log-salve-update
    2、重新启动RelaySlave节点的mysql服务使参数生效。正确的步骤先停止SQL_THREAD线程:
    stop slave sql_thread;
    3、查看当前节点二进制日志文件和位置:show master status;
    system@(none)>show master status;
    +------------------+----------+--------------+------------------+-------------------+
    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +------------------+----------+--------------+------------------+-------------------+
    | mysql-bin.000026 | 418 | | | |
    +------------------+----------+--------------+------------------+-------------------+
    1 row in set (0.00 sec)
    4、RelaySlave节点的重新启动。
    注:RelaySlave节点也必须开启binlog
    5、级联的slave3节点创建,创建步骤省略。(参照前面的各种方法都行)
    6、级联的slave3创建成功并启动后,配置到master节点的连接。注意此处的master是RelaySlave节点执行命令如下:
    change master to master_host='192.168.1.7',master_port=3306,master_user='repl',master_password='oralinux',master_log_file='mysql-bin.000026',master_log_pos=418;
    7、级联的slave3节点start slave; 并使用show slave status;查看两个关键线程启动没有。

    <>同步机制:master节点每进行一个操作,在事务提交并返回成功信息给发出请求的会话前,先等待salve节点在本地执行这个事务,当salve执行成功并返回成功执行的消息给master节点。master才会将事务提交信息返回给发出请求的会话。在分布式事务中管叫两阶段提交。这种方式能够最大程度地保证数据安全,但是缺点也很明显,客户端每提交一个请求,从事务启动到成功执行,中间可能出现较长时间的延迟,影响性能。
    <>半同步机制:Master在返回操作成功(或失败)信息给发起请求的客户端前,还是要将事务发送给Slave节点(不这样不足以保证安全性和及时性)不过为了降低中间的数据通信、数据传输等时间等待等成本。它还是做了一定的取舍。在半同步机制下,Master节点只要确认至少一个Slave节点接收到乐事务,即可向发起请求的客户端返回操作成功的信息。Master节点甚至不需要等待Slave节点也成功执行完这个事务,只要至少有一个Slave节点接收到这个事务,并且将之成功写入到本地的中继日志文件就算成功。这种模式下Master节点出现宕机也没关系。Slave节点还能扛起数据恢复的重任。

    <>配置半同步复制环境
    5.5版本官方引进半同步复制插件。需要安装semisynchronous这个插件。通过show plugins;查看我们现在的环境没有安装这个插件。
    show variables like 'plugin_dir'; 插件存放的位置以.so结尾的文件
    system@5ienet> show variables like 'plugin_dir';
    +---------------+--------------------+
    | Variable_name | Value |
    +---------------+--------------------+
    | plugin_dir | /mysql/lib/plugin/ |
    +---------------+--------------------+
    1 row in set (0.00 sec)
    [mysql@linux01 scripts]$ ll /mysql/lib/plugin/ |grep semi
    -rwxr-xr-x. 1 mysql mysql 435084 3月 30 17:30 semisync_master.so
    -rwxr-xr-x. 1 mysql mysql 258182 3月 30 17:30 semisync_slave.so

    1、在master节点执行命令、加载semisynchronous插件:install plugin rpl_semi_sync_master soname 'semisync_master.so';
    master@mysql>install plugin rpl_semi_sync_master soname 'semisync_master.so';
    Query OK, 0 rows affected (0.00 sec)
    在slave节点加载插件:install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
    slave@mysql>install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
    Query OK, 0 rows affected (0.01 sec)
    配置完成后通过show plugins;查看插件是否处于可用状态
    2、在master节点设置下列变量:
    set global rpl_semi_sync_master_enabled=1;
    set global rpl_semi_sync_master_timeout=3000;
    在slave节点只需要设置一个变量:
    set global rpl_semi_sync_slave_enabled=1;
    以上参数可以动态修改,但是强烈建议将所有配置的变量保存在初始化参数文件中。这样每次启动mysql时不用再手动配置了。
    Master:[mysqld]
    #replcation_master
    rpl_semi_sync_master_enabled=1
    rpl_semi_sync_master_timeout=3000

    Slave:[mysqld]
    #replcation_slave
    rpl_semi_sync_slave_enabled=1

    set global rpl_semi_sync_master_enabled=1;用于控制是否在master节点启用半同步复制,默认为1即启用状态。
    set global rpl_semi_sync_master_timeout=3000; 用于指定master节点等待slave相应的时间,单位是毫秒我们这里设置为3秒,若超出指定的时间slave节点仍无响应,那么当前复制环境就临时被转换为异步复制。
    set global rpl_semi_sync_slave_enabled=1; 控制slave是否启用半同步复制

    3、重新启动Slave节点的IO_THREAD线程。这一步主要是为了叫Slave节点重新连接master节点,注册成为半同步Slave身份。
    slave@mysql>stop slave io_thread;
    Query OK, 0 rows affected (0.00 sec)

    slave@mysql>start slave io_thread;
    Query OK, 0 rows affected (0.00 sec)

    <>监控半同步复制环境
    Slave节点与半同步复制相关的状态变量只有一项Rpl_semi_sync_slave_status,标示当前slave是否启动半同步复制模式。
    slave@mysql>show status like 'rpl%';
    +----------------------------+-------+
    | Variable_name | Value |
    +----------------------------+-------+
    | Rpl_semi_sync_slave_status | ON |
    +----------------------------+-------+
    1 row in set (0.01 sec)

    Master节点与半同步复制相关的变量要多一些,其中值得关注的有:
    Rpl_semi_sync_master_clients:显示当前处于半同步模式的Slave节点数量。
    Rpl_semi_sync_master_status:标示当前Master节点是否启用了半同步模式。
    Rpl_semi_sync_master_no_tx:当前未成功发送到Slave节点的事务数量。
    Rpl_semi_sync_master_yes_tx:当前已成功发送到Slave节点的事务数量。

    master@mysql>show status like 'rpl%';
    +--------------------------------------------+-------+
    | Variable_name | Value |
    +--------------------------------------------+-------+
    | Rpl_semi_sync_master_clients | 1 |
    | Rpl_semi_sync_master_net_avg_wait_time | 1367 |
    | Rpl_semi_sync_master_net_wait_time | 1367 |
    | Rpl_semi_sync_master_net_waits | 1 |
    | Rpl_semi_sync_master_no_times | 0 |
    | Rpl_semi_sync_master_no_tx | 0 |
    | Rpl_semi_sync_master_status | ON |
    | Rpl_semi_sync_master_timefunc_failures | 0 |
    | Rpl_semi_sync_master_tx_avg_wait_time | 1513 |
    | Rpl_semi_sync_master_tx_wait_time | 1513 |
    | Rpl_semi_sync_master_tx_waits | 1 |
    | Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
    | Rpl_semi_sync_master_wait_sessions | 0 |
    | Rpl_semi_sync_master_yes_tx | 1 |
    +--------------------------------------------+-------+
    14 rows in set (0.00 sec)

    在master节点执行一条语句:insert into 5ienet.jason_v2 values(3);
    master@mysql>insert into 5ienet.jason_v2 values(3);
    Query OK, 1 row affected (0.01 sec)
    在Slave节点查询数据:select * from 5ienet.jason_v2;
    slave@mysql>select * from 5ienet.jason_v2;
    +------+
    | id |
    +------+
    | 1 |
    | 2 |
    | 4 |
    | 3 |
    +------+
    4 rows in set (0.00 sec)
    然后再次查询Master节点中的相关变量值,会发现已经产生了变化
    master@mysql>show status like 'rpl%';
    +--------------------------------------------+-------+
    | Variable_name | Value |
    +--------------------------------------------+-------+
    | Rpl_semi_sync_master_clients | 1 |
    | Rpl_semi_sync_master_net_avg_wait_time | 1444 |
    | Rpl_semi_sync_master_net_wait_time | 2889 |
    | Rpl_semi_sync_master_net_waits | 2 |
    | Rpl_semi_sync_master_no_times | 0 |
    | Rpl_semi_sync_master_no_tx | 0 |
    | Rpl_semi_sync_master_status | ON |
    | Rpl_semi_sync_master_timefunc_failures | 0 |
    | Rpl_semi_sync_master_tx_avg_wait_time | 1688 |
    | Rpl_semi_sync_master_tx_wait_time | 3377 |
    | Rpl_semi_sync_master_tx_waits | 2 |
    | Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
    | Rpl_semi_sync_master_wait_sessions | 0 |
    | Rpl_semi_sync_master_yes_tx | 2 |
    +--------------------------------------------+-------+
    14 rows in set (0.00 sec)
    根据这些状态值我们就可以分析当前半同步复制的运行情况了。如果半同步出现异常。那么像Rpl_semi_sync_master_no_tx变量值就会累加,而Rpl_semi_sync_master_net_wait_time和Rpl_semi_sync_master_net_avg_wait_time这类以时间计数的变量值增长更是迅猛。这时候只要再检查一下Rpl_semi_sync_master_status和Rpl_semi_sync_slave_status的值就能判断到底是半同步还是异步复制了。

    <>复制环境中的故障切换
    主从是个逻辑概念,我们把数据库的写挡在那个数据库实例执行,那么该实例就可被视为Master。因此如果master出现故障,我们将应用连接的数据库指向一台新的mysql实例即可。其次slave节点随时都可以通过change master to语句修改其参照的master。需要注意的是预备切换的slave节点需要开启binlog

    举例:一主三从的架构,主故障,slave2接管应用。从宕机到现在slave2触发了很多数据变更。若让slave1和slave3节点选择从slave2节点的当前位置开始读取数据,那么中间的数据必然就丢失了。所以这种问题如何解决?所以实际操作中,不是执行故障切换时将哪个slave转换为master角色,二是若master角色拥有多个slave实例,将其中某个slave提升为新的master后,其他那些slave如何在不影响数据完整性的前提下注册到新的master节点中。
    所以在master出现故障后,第一时间检查slave1-3各节点slave状态信息(show slave status;)重点关注当前读取的master节点日志文件和读取位置(Master_Log_File和Read_Master_Log_Pos),已经执行过的日志位置(Exec_Master_Log_Pos),Slave节点IO和SQL线程运行状态。主从之前的延迟间隔(Seconds_Behind_Master)等信息。也可以再通过show processlist;语句查看相关线程的当前状态是否包含有“Slave has read all relay log”之类的字眼,来交叉验证slave节点的数据应用情况。如果三个节点中接收到的返回信息都相同,说明3个节点的数据处于一致状态。这就好办了。

    登陆到slave2节点执行下列命令:
    stop slave;
    reset slave;
    这两条命令会清除slave2节点中与slave相关的配置,删除master.info relay-log文件然后执行:
    show master status; 记录当前正在操作的二进制日志文件名和写入位置。接下来可以叫应用层修改连接地址改为slave2实例。先将业务恢复。对于其他的slave节点,现在我们已经拥有了最关键的master_log_file和master_log_pos两个信息。因此随时可以配置slave1和slave3两个实例执行change master to命令使其连接slave2节点获取数据。而后master节点恢复后也可以通过change master to 语句将其变为复制环境中的一个slave节点。

    <>延迟复制:指定slave节点中change master to master_delay=n; 单位是秒。设置完成后start slave;就可以是指生效,无需重启mysql。这样设置后slave节点接收到master节点生成的二进制日志不会马上应用而是等待。知道时间符合设定的延迟条件后才开始应用。
    设置延迟后通过show slave status;查看slave节点复制信息时有3个列值于此有关:
    SQL_Delay:显示当前设定的延迟时间,单位为秒
    SQL_Remaining_Delay:当Slave_SQL_Running_State列的状态是“Waiting until MASTER_DELAY seconds after master execute event”时,本列显示的值就是距离延迟阈值的时间,换个说法是还有多长时间才能开始应用。否则的话本列值应该是NULL。
    Slave_SQL_Running_State:显示当前SQL_THREAD的状态,当SQL_THREAD处于延迟等待阶段,show processlist;显示该进程状态时,将会显示为“Waiting until MASTER_DELAY seconds after master execute event”这些信息都说明当前环境配置了延迟复制。

  • 相关阅读:
    xcode 查看stastic
    erlang 游戏服务器开发
    同一世界服务器架构--Erlang游戏服务器
    理解Erlang/OTP
    使用SecureCRT连接AWS的EC2
    redis单主机多实例
    Redis命令总结
    [redis] redis配置文件redis.conf的详细说明
    [转至云风的博客]开发笔记 (2) :redis 数据库结构设计
    Redis 集群方案
  • 原文地址:https://www.cnblogs.com/datalife/p/6781302.html
Copyright © 2020-2023  润新知