首页 > 数据库 > MySQL > 正文

MySQL 5.7半同步机制

2022-07-16 17:16:10
字体:
来源:转载
供稿:网友
  所谓半同步机制,master节点只要确认有至少一个slave节点接收到了事物,即可向客户端返回操作成功的信息,master节点甚至不需要等待slave节点也成功执行完这个事物,只要至少有一个slave节点接收到这个事物,并且将之成功写入到本地的中继日志文件,就算成功。
 
  一,MySQL的半同步复制是以插件形式提供,查看目前是否安装
 
  (root@localhost) [(none)]> show plugins;
  +----------------------------+----------+--------------------+---------+---------+
  | Name | Status | Type | Library | License |
  +----------------------------+----------+--------------------+---------+---------+
  | binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
  | mysql_native_password | ACTIVE | AUTHENTICATION | NULL | GPL |
  | sha256_password | ACTIVE | AUTHENTICATION | NULL | GPL |
  | MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |
  | InnoDB | ACTIVE | STORAGE ENGINE | NULL | GPL |
  | INNODB_TRX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_LOCKS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_LOCK_WAITS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_CMP | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_CMP_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_CMPMEM | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_CMPMEM_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_CMP_PER_INDEX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_CMP_PER_INDEX_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_BUFFER_PAGE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_BUFFER_PAGE_LRU | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_BUFFER_POOL_STATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_TEMP_TABLE_INFO | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_METRICS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_FT_DEFAULT_STOPWORD | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_FT_DELETED | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_FT_BEING_DELETED | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_FT_CONFIG | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_FT_INDEX_CACHE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_FT_INDEX_TABLE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_SYS_TABLES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_SYS_TABLESTATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_SYS_INDEXES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_SYS_COLUMNS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_SYS_FIELDS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_SYS_FOREIGN | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_SYS_FOREIGN_COLS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_SYS_TABLESPACES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_SYS_DATAFILES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | INNODB_SYS_VIRTUAL | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
  | MRG_MYISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
  | PERFORMANCE_SCHEMA | ACTIVE | STORAGE ENGINE | NULL | GPL |
  | CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |
  | MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
  | ARCHIVE | ACTIVE | STORAGE ENGINE | NULL | GPL |
  | partition | ACTIVE | STORAGE ENGINE | NULL | GPL |
  | FEDERATED | DISABLED | STORAGE ENGINE | NULL | GPL |
  | BLACKHOLE | ACTIVE | STORAGE ENGINE | NULL | GPL |
  | ngram | ACTIVE | FTPARSER | NULL | GPL |
  +----------------------------+----------+--------------------+---------+---------+
  44 rows in set (0.00 sec)
  二,本例目前还没有安装,查看plugin目录位置
 
  (root@localhost) [(none)]> show variables like 'plugin_dir';
  +---------------+------------------------------+
  | Variable_name | Value |
  +---------------+------------------------------+
  | plugin_dir | /usr/local/mysql/lib/plugin/ |
  +---------------+------------------------------+
  1 row in set (0.00 sec)
  三,在plugin目录下有两个与半同步相关的插件
 
  [root@oracle11gtest plugin]# ls -al semisync*
  -rwxr-xr-x 1 root root 688816 Feb 6 19:44 semisync_master.so
  -rwxr-xr-x 1 root root 150555 Feb 6 19:44 semisync_slave.so
  四,在master端安装semisync_master.so,在slave端安装semisync_slave.so
 
  (root@localhost) [(none)]> install plugin rpl_semi_sync_master SONAME 'semisync_master.so' ;
  Query OK, 0 rows affected (0.04 sec)
 
  (root@localhost) [(none)]> install plugin rpl_semi_sync_slave SONAME 'semisync_slave.so';
  Query OK, 0 rows affected (0.01 sec)
  五,安装好之后分别用show plugins命令check下
 
  六,修改主端半同步相关参数
 
  (root@localhost) [(none)]> show variables like '%rpl_semi_sync%';
  +-------------------------------------------+------------+
  | Variable_name | Value |
  +-------------------------------------------+------------+
  | rpl_semi_sync_master_enabled | OFF |
  | rpl_semi_sync_master_timeout | 10000 |
  | rpl_semi_sync_master_trace_level | 32 |
  | rpl_semi_sync_master_wait_for_slave_count | 1 |
  | rpl_semi_sync_master_wait_no_slave | ON |
  | rpl_semi_sync_master_wait_point | AFTER_SYNC |
  +-------------------------------------------+------------+
  6 rows in set (0.00 sec)
 
  (root@localhost) [(none)]> set global rpl_semi_sync_master_enabled=1;  ---用于控制是否在主端启用半同步复制,
  Query OK, 0 rows affected (0.00 sec)
 
  (root@localhost) [(none)]> set global rpl_semi_sync_master_timeout=3000;  ---用于指导主端等待slave响应的时间,单位是毫秒,我这里设为3秒
  Query OK, 0 rows affected (0.00 sec)
  七,修改slave端半同步相关参数
 
  (root@localhost) [(none)]> show variables like '%rpl_semi_sync%';
  +---------------------------------+-------+
  | Variable_name | Value |
  +---------------------------------+-------+
  | rpl_semi_sync_slave_enabled | OFF |
  | rpl_semi_sync_slave_trace_level | 32 |
  +---------------------------------+-------+
  2 rows in set (0.01 sec)
 
  (root@localhost) [(none)]> set global rpl_semi_sync_slave_enabled=1; ---用于控制是否在slave端启用半同步复制,
  Query OK, 0 rows affected (0.00 sec)
  八,重启slave节点的io_thread线程,目的是让slave重新连接master,注册成为半同步的slave身份
 
  (root@localhost) [(none)]> stop slave io_thread;
  Query OK, 0 rows affected (0.01 sec)
 
  (root@localhost) [(none)]> start slave io_thread;
  Query OK, 0 rows affected (0.00 sec)
  九,测试
 
  在master端插入数据
  insert into oms3.gl values('zg');
  insert into oms3.gl values('gl');
  查看slave是否应用
 
  (root@localhost) [(none)]> select * from oms3.gl;
  +------+
  | abcd |
  +------+
  | test |
  | gl |
  | zg |
  +------+
  查看master相关变量
  (root@localhost) [mysql]> show status like 'rpl_semi_sync%';
  +--------------------------------------------+-------+
  | Variable_name | Value |
  +--------------------------------------------+-------+
  | Rpl_semi_sync_master_clients | 1 |
  | Rpl_semi_sync_master_net_avg_wait_time | 0 |
  | Rpl_semi_sync_master_net_wait_time | 0 |
  | Rpl_semi_sync_master_net_waits | 0 |
  | 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 | 417 |
  | Rpl_semi_sync_master_tx_wait_time | 834 |
  | 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 | 1 |
  主要关注四个参数:
  Rpl_semi_sync_master_status ---表示当前master节点是否启用了半同步模式
 
  Rpl_semi_sync_master_no_tx  ---表示当前未成功发送到slave节点的事物数量
 
  Rpl_semi_sync_master_yes_tx ---表示当前已成功发送到slave节点的事物数量
 
  Rpl_semi_sync_master_clients---表示当前处于半同步模式的slave节点数量
 
  5.7的半同步机制变化
 
  一:rpl_semi_sync_master_wait_slave_count参数设置有几个slave接收到了binlog才成功返回客户端请求,缺省是一台,但不可以指定是具体哪台。
 
  二:rpl_semi_sync_master_wait_point 参数,它有两种选择:
 
  AFTER_SYNC(5.7缺省值,5.6中无此选项)
      主库把每一个事务写到二进制日志并且发送给从库,主库在等待从库写到自己的relay-log里的确认信息,在接到确认信息后,主数据库把事务写到存储引擎里并把相应结果反馈给客户端。
 
  AFTER_COMMIT(5.6缺省值)
      主库把每一个事务写到二进制日志并且发送给从库,然后马上就把事务写到存储引擎里;主库在等待从库写到自己的relay-log里的信息确认后,主库把相应结果反馈给客户端。
 
  他们俩个的区别:
  AFTER_COMMIT模式的弊端在于,虽然主库一直没有告诉提交事务的客户端事务已经成功(在从库成功确认前)但是实际已经提交了,其它客户端此时已经可以看到事务的结果了。
  也就是对于事务提交者自身,的确保证了只要收到成功就一定成功了,但是其它客户端却可能存在发现事务成功了,但最后却没成功,因为数据已经到了存储引擎层。
 
  比如A客户端执行事务将字段id从0修改为1
  1.A提交事务到主库
  2.主库写binlog
  3.主库发送给从库,同时主库提交事务到存储引擎
  此时还未收到从库确认,此时A还在等待结果,但是此时另外客户端B已经可以看到字段id为1了。
 
  假如此时主库宕机,如果从库实际收到刚才的事务仅仅是主库未收到确认,那么此时从库的数据还是正确的也是id=1,客户端切换到从库后,都看到id=1
  但是如果从库没有实际收到刚才的事务,那么此时从库上id=0,对于客户端A,这个并没有问题,因为A先前提交的事务没有收到任何反馈,所以A需要通过其它方式来确定先前事务是否成功,也就是A可以接受id=0或id=1。
  但是对于客户端B来说,已经id=1的变成id=0则很可能是无法接受的
 
  AFTER_SYNC模式则可以解决这个问题,继续上面的例子:
  1.A提交事务到主库
  2.主库写binlog
  3.主库发送给从库
  4.主库等待从库确认,此时id=0,没有任何客户端能看到id=1的结果,因为没有提交
  5.主库收到从库确认,主库开始提交到存储引擎
  6.主库返回结果给客户端
 
  假如第4步时主库宕机,客户端切换到从库,如果从库实际接收到事务,那么此时id=1,如果从库未接收到事务,那么此时id=0,
  无论哪种状态,对于所有客户端数据库都是一致,事务都没有丢失,同样客户端A需要自己检查事务状态,因为他没收到反馈,业务上他本身就允许两种可能(提交or回滚)

(编辑:错新网)

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表