• GTID


    一、GTID【Global Transaction Identifiers】

    • GTID(Global Transaction Identifiers)是全局事务标识,GTID=server_uuid+transaction_id
      • server_uuid,由于GTID会传递到slave,一个GTID在一个服务器上只执行一次
      • transaction_id,为当前服务器上已提交事务的一个序列号,通常从1开始自增长的序列,一个数值对应一个事务。
    • transaction_id 并不能代表执行顺序
    • GTID采用MASTER_AUTO_POSTION=1代替传统复制(file+pos)
    • GTID中slave端的binlog是必须开启的,目的是记录执行过的GTID(Executed_Gtid_Set)。
    • GTID中包涵了server_uuid,方便了replication 的failove

    二、GTID限制

    1. 不支持非事务引擎
    • 对于GTID不支持非事务引擎如何理解:
      • 不支持非事务引擎不是不能建立myisam表、对myisam表DML
      • innodb中一个事务中可以是多条SQL
      • myisam中,一条DML生成一个GTID号,所以不支持事务
    mysql> insert into user_myisam values (3,100);   -- myisam每条sql自动提交,所以myisam中不存在事务的概念
    Executed_Gtid_Set: 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-68 

    2. 不支持create table … select 语句复制(主库直接报错)
    mysql> create table t1 select * from user_innodb;
    ERROR 1786 (HY000): CREATE TABLE ... SELECT is forbidden when @@GLOBAL.ENFORCE_GTID_CONSISTENCY = 1.

    3. 不允许在一个SQL同时更新一个事务引擎和非事务引擎的表
    mysql> begin;
    mysql> update user_innodb set money=100 where id=1;
    mysql> update user_myisam set money=100 where id=1;
    ERROR 1785 (HY000): When @@GLOBAL.ENFORCE_GTID_CONSISTENCY = 1, updates to non-transactional tables can only be done in either autocommitted statements or single-statement transactions, and never in the same statement as updates to transactional tables.

    4. 在一个复制组中,必须要求统一开启GTID或是关闭GTID
    The slave IO thread stops because the master has @@GLOBAL.GTID_MODE ON and this server has @@GLOBAL.GTID_MODE OFF。
    5. 对于create temporary table 和drop temporary table语句不支持
    6. 不支持sql_slave_skip_counter

    三、GTID主从复制

    2.1 GTID的工作原理

    1. 当一个事务在主库端执行并提交时,产生GTID,一同记录到binlog日志中 [SET @@SESSION.GTID_NEXT]。
    2. binlog传输到slave,并存储到slave的relaylog后,开始重做。
    3. 执行SET @@SESSION.GTID_NEXT,从库对比[Executed_Gtid_Set] 是否执行过。
    4. 如果有记录,说明该GTID的事务已经执行,slave会忽略;
    5. 如果没有记录,
      1. 在读取执行事务前会先检查其他session持有该GTID,确保不被重复执行。
      2. slave就会执行该GTID事务,并记录[Executed_Gtid_Set],
    注意:从库执行relay log ,记录binlog时,还是记录主库的GTID,不会产生新的GTID号

    2.2 启动GTID的关键步骤

    由最初的GTID复制拓扑(包括一个主站和一个从站)构成的启动过程中的关键步骤如下:
    1. 如果复制已经在运行,则通过使这两个服务器成为只读方式来同步.
      1. mysql> SET @@global.read_only = ON;
    2. 停止两个服务器。
      1. shell> mysqladmin -uusername -p shutdown;
    3. 重新启动启用GTID的两个服务器,并配置正确的选项。
      1. gtid_mode=ON 
      2. enforce-gtid-consistency=true
    4. 指示从机使用主机作为复制数据源,并使用自动定位,然后启动从机。
      1. mysql> CHANGE MASTER TO> MASTER_HOST = host, MASTER_PORT = port, MASTER_USER = user, MASTER_PASSWORD = password, MASTER_AUTO_POSITION = 1;
      2. mysql> START SLAVE;
    5. 在两台服务器上再次启用读取模式,以便它们可以接受更新。
      1. mysql> SET @@global.read_only = OFF;

    2.3 数据和binlog的复制

    1、数据的复制
    • 使用mysql客户端导入使用mysqldump创建的转储文件。
      • 在源服务器上使用的 --master-data 选项包括二进制日志信息,
      • 并 --set-gtid-purged 以AUTO(默认),或者 ON,包括有关在转储执行交易的信息。
    2、binlog的复制

    2.4 GTID相关的参数

    1. --enforce-gtid-consistency
    服务器通过允许执行只能使用GTID安全地记录的语句来强制执行GTID一致性,影响:
    CREATE TABLE ... SELECT 声明
    CREATE TEMPORARY TABLE或 DROP TEMPORARY TABLE交易中的语句
    更新事务性和非事务性表的事务或语句。

    2.  --gtid-mode
    在MySQL 5.7.6及更高版本中,该 gtid_mode变量是动态的,并允许基于GTID的复制在线配置。

    3. --gtid-executed-compression-period
    该变量的默认值为1000; 这意味着,默认情况下,在每1000个事务之后执行表mysql.gtid_executed的压缩。

    4. binlog_gtid_simple_recovery
    5.7.7 之后默认值为on,只从最新的最老的binlogflie中计算得到gtid_purged and gtid_executed的值。

    2.5、GTID相关变量

    1.  gtid_executed
    存储已经执行过,并且记录到 binlog 的全局事务 ID 集合。它对应的 MySQL variable 是 gtid_executed,可以用命令:
    logged_gtids 用来判断 MySQL 有没有执行某个事务。例如,在 Master 发送 binlog 时,MySQL 5.6 能够根据 Slave 提供的 logged_gtids 记录,自动过滤 binlog 中不需要执行的事务
    2. gtid_purged
    记录从 binlog 删除的全局事务 ID 集合。它对应的 MySQL Global variable 是:gtid_purged 。
    每当 MySQL 5.6 调用 purge_logs 删除 binlog 时,会顺带更新 gtid_purged 的内容。这是通过读剩下的 binlog 文件实现的
    3.  gtid_owned
    正在由线程执行的全局事务 ID 集合。它对应的 MySQL variable 是:gtid_owned
    4. gtid_next
    • 取值:
      • AUTOMATIC: Use the next automatically-generated global transaction ID.
      • ANONYMOUS: Transactions do not have global identifiers, and are identified by file and position only.
      • A global transaction ID in UUID:NUMBER format.
    • Setting this variable has no effect if gtid_mode is OFF.
    • After this variable has been set to UUID:NUMBER,当发生一个事务设置为commit或rollback,需要再次声明这个变量的值。

    四、GTID跳过单个、批量事务

    1、概述

    使用gtid跳过事务有两种方法:
    1. set gtid_next,可以跳过单个事务
    2. set GTID_PURGED,可以跳过多个事务

    2、跳过单个事物

    1、情景:
        主新建了test.t1 表,从误操作删掉了test.t1;
        主往test.t1中插入一条数据,从库报错
    从库报错内容:
    mysql> show slave status G
              Last_SQL_Error: Worker 3 failed executing transaction '59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:17' at master log mysql-bin.000002, end_log_pos 3255; Error executing row event: 'Table 'test.t1' doesn't exist
              Retrieved_Gtid_Set: 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-17
              Executed_Gtid_Set: 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-16,29bd8c99-9e4d-11e7-a072-000c29d00b2d:1,
                    Auto_Position: 1
    得知:
        从库在执行59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:17 这个事务时,因为从库没有这个表而报错了。

    2、解决步骤:
    root用户手动重建test.t1表
    主库备份
    # mysqldump -uroot -p123123  -h127.0.0.1  --single-transaction --set-gtid-purged=off  --triggers --routines --events  test t1 >/tmp/t1.sql
    从库恢复
    # cat t1.sql |mysql -uroot -p123123 test
    root用户手动在59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:17 这个事务上执行一个空事务
    > stop slave;
    > SET @@SESSION.GTID_NEXT= '59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:17'/*!*/;
    > show variables like '%gtid%_next';
    > BEGIN;COMMIT;
    > SET gtid_next = 'AUTOMATIC';
    > START SLAVE;

    3、批量跳过

    1. 情景模拟
    由于数据不一致严重,跳过单个事务不能继续正常复制。
    从库删掉单表,然后跳过批量sql,继续复制
    2. 操作步骤
    1. 主库备份表
    # mysqldump -uroot -p123123  -h127.0.0.1  --single-transaction --set-gtid-purged=on  --triggers --routines --events  test t1 >/tmp/t1.sql
    2. 查看备份文件
    # cat /tmp/t1.sql |egrep SET |egrep -v "^/"
    SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;
    SET @@SESSION.SQL_LOG_BIN= 0;
    SET @@GLOBAL.GTID_PURGED='59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-22';
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    SET @@SESSION.SQL_LOG_BIN = @MYSQLDUMP_TEMP_LOG_BIN;
    3. 从库恢复
    > reset master;        //清空GTID_EXECUTED --  @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.
    # mysql -uroot -p123123 test < t1.sql  -- 会执行备份文件中的SET @@GLOBAL.GTID_PURGED。
    > show slave status G
              Retrieved_Gtid_Set: 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-22
              Executed_Gtid_Set: 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-22
    > start slave;

    五、GTID & 备份

    1、逻辑备份

    1. 与GTID相关的选项:
    • --set-gtid-purged=[ON | OFF | AUTO ] 
        如果ON,在备份文件中会有以下两句
                SET @@SESSION.SQL_LOG_BIN= 0;
                SET @@GLOBAL.GTID_PURGED=

        若OFF则不写入
        若AUTO,检测到GTID,自动添加上述语句,反之不加。
        
        主从的Executed_Gtid_Set列表应该是一致的,也就是说,从库除了除了重做binlog之外,不能在从库上生成从库的GTID。
        所以,用slave备份搭建slave,应该不记录binlog(SET @@SESSION.SQL_LOG_BIN= 0,恢复过程不产生从库的GTID),使用选项:--set-gtid-purged=ON

    • --dump-slave、--master-data

        在GTID中,不必使用dump-slave、--master-data,因为GTID中,不再使用传统复制中的 file 和 pos
    2. 备份案列:用slave搭建slave
    # mysqldump -uroot -p123123 --single-transaction  --routines --events  --set-gtid-purged=ON --all-databases >/tmp/10_2.sql
    # mysql </tmp/10_2.sql 
    mysql> CHANGE MASTER TO MASTER_HOST = '192.168.234.130', MASTER_PORT = 3306, MASTER_USER = 'repl', MASTER_PASSWORD = 'repl', MASTER_AUTO_POSITION = 1;
    mysql> start slave;

    2、物理备份

    备份的时候,只要在备份的时候记录下Executed_Gtid_Set($gtid_dump)即可,这个可以用于重新change master;
    # innobackupex --defaults-file=/export/servers/mysql/etc/my.cnf  --slave-info --user=root --password=123123 --no-timestamp /tmp/in.sql
    # cat xtrabackup_slave_info
    SET GLOBAL gtid_purged='29bd8c99-9e4d-11e7-a072-000c29d00b2d:1-5, 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-68';
    CHANGE MASTER TO MASTER_AUTO_POSITION=1
    > reset master;
    > SET @@GLOBAL.GTID_PURGED='$gtid_dump';   //上面备份文件中的值
    > change master to master_auto_position=1;

    六、GTID & 并行复制

    1. 为了兼容MySQL 5.6基于库的并行复制,5.7引入了新的变量slave-parallel-type,其可以配置的值有:
    DATABASE:默认值,基于库的并行复制方式
    LOGICAL_CLOCK:基于组提交的并行复制方式

    2. MySQL 5.7才可称为真正的并行复制
        这其中最为主要的原因就是master服务器上是怎么并行执行的slave上就怎样进行并行回放,一个组提交的事务都是可以并行回放。

    3. 在MySQL 5.7版本中,其设计方式是将组提交的信息存放在GTID中。如果用户没有开启GTID功能,引入了称之为Anonymous_Gtid的概念。
        较之原来的二进制日志内容多了last_committed和sequence_number;
        last_committed表示事务提交的时候,上次事务提交的编号,如果事务具有相同的last_committed,表示这些事务都在一组内,可以进行并行的回放。
    # mysqlbinlog -vv mysql-bin.000001 |egrep last_commit
    #171002 11:53:31 server id 1  end_log_pos 219 CRC32 0x4a9095a9  Anonymous_GTID  last_committed=0        sequence_number=1
    #171002 11:53:31 server id 1  end_log_pos 473 CRC32 0x786dd106  Anonymous_GTID  last_committed=1        sequence_number=2

         
  • 相关阅读:
    JAXB基本使用
    Spring MVC手札
    Oracle创建表空间和表
    oracle删除表,让整个表从数据库中彻底消失
    oracle创建用户操作
    查看运行时某个java对象占用JVM大小及通过idea查看java的内存占用情况
    如何查看java进程
    win10下查看进程,杀死进程
    js计算两个时间相差天数
    windows 端口号占用和解决方法
  • 原文地址:https://www.cnblogs.com/jesper/p/7623939.html
Copyright © 2020-2023  润新知