MyException - 我的反常网
当时方位:我的反常网» MySQL » MySQL 5.6 大局业务 ID(GTID)完结原理(二)

MySQL 5.6 大局业务 ID(GTID)完结原理(二)

www.x8vin4.com  网友共享于:2013-01-24  阅读:60次
MySQL 5.6 大局业务 ID(GTID)完结原理(二)
前文 MySQL 5.6 大局业务 ID(GTID)完结原理(一)​ 介绍了 MySQL 5.6 大局业务 ID 的界说和相关的数据结构 Gtid_set 与 Sid_map。接下来,这一篇的首要方针是深化了解文章最终说到的大局业务状况 Gtid_state。并且,假如或许 —— 趁便介绍下这些 Gtid_state 在主备仿制中的功用:
 
大局业务状况 Gtid_state
 
Gtid_state 是 MySQL 5.6 内的一个大局目标,它的数据结构如下: 
(mysql-5.6.9-rc\sql\rpl_gtid.h,line 2043)
 
Gtid_state := (logged_gtids, lost_gtids, owned_gtids)
 
创立 Gtid_state 的代码能够在 mysqld.cc 的 gtid_server_init 办法里找到。
(代码途径:mysql-5.6.9-rc\sql\mysqld.cc, 1719 line)
 
Gtid_state 的重要性是,它保护三个与大局业务 ID 有关的 MySQL global variables:
 
logged_gtids / `gtid_executed`
 
存储现已履行过,并且记载到 binlog 的大局业务 ID 调集。它对应的 MySQL variable 是 gtid_executed,能够用指令:
 
SHOW GLOBAL VARIABLES LIKE 'gtid_executed'
 
查看数据库上现已履行的大局业务 ID。
 
MySQL 5.6 在敞开 --gtid_mode​=ON 后,每逢履行完一个业务,就会调用 Gtid_state 的 update_on_flush() 办法,把业务对应的 GTID 写入 logged_gtids。
 
具体一点的进程是这样的:
 
为了避免写入 binlog 的是一组不完整的业务,MySQL 会缓存整个业务的 binlog 内容在 binlog_cache_data 中。假如业务提交,MySQL 会履行一个叫 ordered_commit() 的三阶段提交操作:
(源代码:mysql-5.6.9-rc\sql\binlog.cc,line 6245)
 
第一步:调用 process_flush_stage_queue() 和 flush_io_cache() 将缓存在 binlog_cache_data 中的内容刷出到 binlog 文件。此刻,Gtid_state 的 update_on_flush() 调用到,业务对应的 GTID 写入 logged_gtids。
 
第二步:调用 sync_binlog_file() 在 binlog 文件上履行 fsync() 确保内容更新到磁盘。 
 
第三步:调用 process_commit_stage_queue() 履行一切业务提交,在存储引擎上调用 ha_commit_low()。
 
完毕后,MySQL 调用 Gtid_state 的 update_on_commit(),从 owned_gtids 里删去完结  commit 的大局业务 ID。
 
与姓名相同,logged_gtids 用来判别 MySQL 有没有履行某个业务。例如,在 Master 发送 binlog 时,MySQL 5.6 能够根据 Slave 供给的 logged_gtids 记载,主动过滤 binlog 中不需求履行的业务(请参阅新增 COM_BINLOG_DUMP_GTID 协议)。 
 
别的,MySQL 5.6 支撑在 START SLAVE 时指定 UNTIL_SQL_BEFORE_GTIDS / UNTIL_SQL_AFTER_GTIDS 条件,让 Slave 履行完所需求的业务后就主动中止仿制。这个功用也依赖于 Slave 的 logged_gtids 记载来查看作为条件的 GTIDs 是否满意。
 
lost_gtids / `gtid_purged`
 
记载从 binlog 删去的大局业务 ID 调集。它对应的 MySQL Global variable 是:gtid_purged​ 。
 
每逢 MySQL 5.6 调用 purge_logs 删去 binlog 时,会顺带更新 lost_gtids 的内容。这是经过读剩余的 binlog 文件完结的,我会在介绍 GTID 在 binlog 的存储办法时描绘。
(源代码:mysql-5.6.9-rc\sql\binlog.cc,line 3754)
 
它的作用是查看 Slave 恳求的 Gtids 是否现已被 Master 删去。假如 Master 的 lost_gtids 记载现已不是 Slave 的 logged_gtids 记载的子集,恳求的 Slave 会收到代码为 ER_MASTER_HAS_PURGED_REQUIRED_GTIDS 的过错。
 
owned_gtids / `gtid_owned`
 
正在由线程履行的大局业务 ID 调集。它对应的 MySQL variable 是:gtid_owned,而对应​的类型是 Owned_gtids,基本上能够看作一个 Gtid 到 owner_thread_id 的 hash_map 映射:
 
Owned_gtids := array(sidno => hash_map(Node))
 
Node := (gno, owner_thread_id) 
 
其间 gno 是 Gtid 中的业务 ID。
 
在 MySQL 5.6 中,owned_gtids 供给了一个正在履行的业务纪录(以及履行它们的线程 ID)。这份记载是怎样保护的? —— 这与 MySQL 发生 GTID 的进程有关:
 
每个数据库更新都会发生一条 binlog,当一条 binlog 写入 binlog_cache_data 之前,MySQL Master 会调用 generate_automatic_gno() 发生一个 gno —— 业务 ID,具体进程是这样的:
 
首要,generate_automatic_gno  会查看 Gtid_state 中的 logged_gtids 和 owned_gtids,找到一个当时最大的并且没有运用的 gno(Gtid_state 的 get_automatic_gno() 办法),创立出新的 Gtid。
 
然后,MySQL 调用 Gtid_state 的 acquire_ownership(),把新的 Gtid 写入大局的 owned_gtids,并记载到线程的 owned_gtid 变量(留意:NDB 集群的处理有不同,这儿我纷歧一介绍了)。
 
当业务完毕时,MySQL 会调用 Gtid_state 的 update_on_commit / update_on_rollback 办法,把线程履行的 owned_gtid 从大局 owned_gtids 中删去。
 
大局 owned_gtids 常常用来反向查找履行业务的线程。有个重点是,在 Gtid_state 的 acquire_ownership() 办法中,假如所给的 Gtid 在大局 owned_gtids 现已被标记成另一个线程履行,那么 MySQL 会测验等候并查看这个线程是否被 kill。
 
Gtid_state 回忆
 
从上面 Gtid_state 的完结逻辑中,我们能够看到,在 MySQL 5.6 里一个大局业务 ID 的生命周期是这样的:
 
首要,履行数据库操作时,发生一个大局业务 ID,当即记载到大局和当时线程的 gtid_owned (owned_gtids)状况。
 
接着,提交数据库业务时,新发生的大局业务 ID 被写入 binlog,接着记载到 gtid_executed(logged_gtids)状况,然后从大局与线程区域的 gtid_owned (owned_gtids)状况中铲除。
 
假如 DBA 履行了 purge 操作删去 binlog,被删去的大局业务 ID 会记载到 gtid_lost(lost_gtids)。可是,这些大局业务 ID 依然包含在 gtid_executed(logged_gtids)大局状况里。
 
最终。
 
在上面的介绍中,我故意没有说到 MySQL 是怎样坚持这些大局业务状况的耐久化的。由于这些和 5.6 新增的 binlog 作业 Gdit_log_event / Previous_gtid_log_event 有关。下一篇,我会先介绍一下 MySQL 5.6 对 binlog 格局的扩展,然后再介绍大局业务 ID 是怎样作用于新的主备仿制流程的。
 
(未完待续)

文章谈论

软件开发程序过错反常ExceptionCopyright © 2009-2015 MyException 版权一切