mysql -- GTID

GTID概念
GTID,全局事务ID globaltransaction identifiers
GTID是一个事务对应一个全局唯一ID,随事务记录到binlog中,用来标识事务。
GTID 对应事务在一个服务器上只执行一次,避免重复执行导致数据不一致。
GTID 用来代替传统的复制方法,不再使用传统的MASTER_LOG_FILE+ MASTER_LOG_POS,而是使用MASTER_AUTO+POSTION=1的方式
每个事务有一个Gtid_log_event

GTID的构成
UUID+Sequence Number
Sequence Number是MySQL服务器内部的一个事务顺序号.一个MySQL服务器上的事务不会有重复的顺序号(保证服务器内唯一)。
每个MySQL服务器有一个全局唯一的UUID.
 

GTID优势

  1. 简化复制的使用过程和降低复制集群的维护难度。
  2. 比传统的复制更能保证数据一致性

GTID的工作原理

  1. 当一个事务在主库端执行并提交时,产生GTID,一同记录到binlog日志中。
  2. Slave连接到Master时,会把gtid_executed中的gtid发给Master。Master会自动跳过这些事务,只将没有复制的事物发送到Slave上。
  3. binlog传输到slave,并存储到slave的relaylog后,读取这个GTID的这个值设置gtid_next变量,即告诉Slave,下一个要执行的GTID值。
  4. sql线程从relay log中获取GTID,然后对比slave端的binlog是否有该GTID。
  5. 如果有记录,说明该GTID的事务已经执行,slave会忽略。
  6. 如果没有记录,slave就会执行该GTID事务,并记录该GTID到自身的binlog,
  7. 在读取执行事务前会先检查其他session持有该GTID,确保不被重复执行。
  8. 在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。

GTID的作用
GTID 的使用不单单是用单独的标识符替换旧的二进制日志文件和位置,它也采用了新的复制协议。旧的协议往往简单直接,即:首先从服务器上在一个特定的偏移量位置连接到主服务器上一个给定的二进制日志文件,然后主服务器再从给定的连接点开始发送所有的事件。
新协议稍有不同:支持以全局统一事务 ID (GTID) 为基础的复制。当在主库上提交事务或者被从库应用时,可以定位和追踪每一个事务。GTID 复制是全部以事务为基础,使得检查主从一致性变得非常简单。如果所有主库上提交的事务也同样提交到从库上,一致性就得到了保证。
GTID 相关操作:默认情况下将一个事务记录进二进制文件时,首先记录它的 GTID,而且 GTID 和事务相关信息一并要发送给从服务器,由从服务器在本地应用认证,但是绝对不会改变原来的事务 ID 号。因此在 GTID 的架构上就算有了N层架构,复制是N级架构,事务 ID 依然不会改变,有效的保证了数据的完整和安全性。
你可以使用基于语句的或基于行的复制与 GTID ,但是,为了获得最佳效果,我们建议你使用基于行(ROW)的格式。

GTID功能的具体归纳主要有以下两点:
根据 GTID 可以知道事务最初是在哪个实例上提交的
GTID 的存在方便了 Replication 的 Failover
我们可以看下在 MySQL 5.6 的 GTID 出现以前 Replication Failover 的操作过程。假设我们有一个如下图的环境:

此时,Server A 的服务器宕机,需要将业务切换到 Server B 上。同时,我们又需要将 Server C 的复制源改成 Server B。复制源修改的命令语法很简单即:
CHANGE MASTER TO MASTER_HOST='xxx', MASTER_LOG_FILE='xxx', MASTER_LOG_POS=nnnn
而这种方式的难点在于,由于同一个事务在每台机器上所在的 binlog 名字和位置都不一样,那么怎么找到 Server C 当前同步停止点对应 Server B 上 master_log_file 和 master_log_pos 的位置就成为了难题。
这也就是为什么 M-S 复制集群需要使用 MMM、MHA 这样的额外管理工具的一个重要原因。 这个问题在 5.6 的 GTID 出现后,就显得非常的简单。
由于同一事务的 GTID 在所有节点上的值一致,那么根据 Server C 当前停止点的 GTID 就能唯一定位到 Server B 上的GTID。甚至由于 MASTER_AUTO_POSITION 功能的出现,我们都不需要知道 GTID 的具体值。直接使用以下命令就可以直接完成 Failover 的工作。
CHANGE MASTER TO MASTER_HOST='xxx', MASTER_AUTO_POSITION=='xxx'
环境
系统:redhat6.5 
防火墙:保持关闭 
selinux=disabled
mysql主机:server1 172.25.60.1/24 
mysql从机:server2 172.25.60.2/24

MySQL5.7安装启动
(1)安装包 

mysql-community-client-5.7.17-1.el6.x86_64.rpm 
mysql-community-common-5.7.17-1.el6.x86_64.rpm 
mysql-community-libs-5.7.17-1.el6.x86_64.rpm 
mysql-community-libs-compat-5.7.17-1.el6.x86_64.rpm 
mysql-community-server-5.7.17-1.el6.x86_64.rpm

(2)开启MySQL并修改密码

[root@server3 ~]# /etc/init.d/mysqld start ##开启mysql

grep password /var/log/mysqld.log ##查看密码

[root@server3 ~]# mysql -p Enter password: ##修改mysql的管理用户密码

mysql> ALTER USER root@localhost identified by 'newpassword'; ##输入查看到的密码

配置主从复制(常用)
mysql主库(master)
(1)配置主配置文件(/etc/my.cnf)

[root@server1 ~]# vim /etc/my.cnf
server-id=1 ##服务器ID
log-bin=mysql-bin ##开启二进制日志
binlog-do-db=test ##需要同步的数据库名
binlog-ignore-db=mysql ##禁止同步的数据库名
[root@server1 ~]# /etc/init.d/mysqld restart ##重启服务

(2)配置数据库 

##在主库上建立帐户并授权
##为了方便我将密码全部设置一致
mysql> grant replication slave on . to 'rep'@'192.168.32.129' identified by '
授权密码';
mysql> flush privileges;

##查看主库的状态

mysql> mysql> show master status;
File= master-bin.000003
Position=154

mysq从库(slave)

(1)配置文件(/etc/my.cnf)

[root@server2 ~]# vim /etc/my.cnf
##配置server-id,slave的server-id必须与master不同,即如果开启二进制日志,所有服务器的server-id必须不同
server-id=2
log-bin=mysql-bin
[root@server2 ~]# systemctl restart mysqld

(2)配置数据库

mysql> change master to master_host='192.168.32.140',master_user='rep',master_password='123456',master_log_file='master-bin.000002',master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.03 sec)
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)
mysql> show slave status\G;

1. row
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.32.140
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000002
Read_Master_Log_Pos: 154
Relay_Log_File: 192-relay-bin.000002
Relay_Log_Pos: 321
Relay_Master_Log_File: master-bin.000002
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
当看到Slave_IO_Running: Yes以及Slave_SQL_Running: Yes,则表示slave库已经正常运行了

当出现Slave_IO_Running: Connecting的提示时,说明主库和从库没有连接上,有以下三点原因:
1.网络问题:检查网络连接是否能够连接上
2.密码或POS号错误:查看pos号和主库的号是否对应
3.防火墙的问题:查看主库防火墙的策略,数据库是否拒绝外来连接,然后做相应的改动

利用mysql5.7的GTID来实现主从复制

GTID(Global Transaction ID)是对于一个已提交事务的编号,并且是一个全局唯一的编号。它的官方定义如下: 
​GTID = source_id :transaction_id 
每一个 GTID 代表一个数据库事务 
在mysql的数据目录(/var/lib/mysql)里查看二进制日志
##mysql-bin.000007为mysql二进制日志,后面为日志码
mysqlbinlog mysql-bin.000007
GTID即为SESSION.GTID_NEXT= ‘b1b6e236-0171-11e8-b3b9-525400c7a2a4:1 

利用GTID实现主从复制

1、配置配置文件(/etc/my.cnf)并重启mysql(主从都配置一样)

gtid_mode=ON
enforce-gtid-consistency=true

mysql> stop slave;
mysql> change master to master_host='192.168.32.140',master_user='rep',master_password='123456',master_log_file='master-bin.000003',master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

mysql> show slave status\G;
1. row
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.32.140
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000003
Read_Master_Log_Pos: 154
Relay_Log_File: 192-relay-bin.000002
Relay_Log_Pos: 321
Relay_Master_Log_File: master-bin.000003
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: 1
Master_UUID: c371c386-7a9c-11e8-9015-000c29524962
Master_Info_File: /usr/local/mysql/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: c371c386-7a9c-11e8-9015-000c29524962:1-3
Executed_Gtid_Set: c371c386-7a9c-11e8-9015-000c29524962:1-3 Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)

3.测试
主mysql:

mysql> create table test.caiwu ( id int,name varchar(10));
Query OK, 0 rows affected (0.03 sec)

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> insert into caiwu values (1,'name1');
Query OK, 1 row affected (0.01 sec)
mysql> insert into caiwu values (2,'name2');
Query OK, 1 row affected (0.02 sec)
mysql> select * from caiwu;
+------+-------+
| id | name |
+------+-------+
| 1 | name1 |
| 2 | name2 |
+------+-------+
2 rows in set (0.00 sec)

从mysql:

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| caiwu |
+----------------+
1 row in set (0.00 sec)

mysql> select * from caiwu;
+------+-------+
| id | name |
+------+-------+
| 1 | name1 |
| 2 | name2 |
+------+-------+
2 rows in set (0.00 sec)

猜你喜欢

转载自blog.51cto.com/13555423/2139756