ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

galera cluster 是如何检测冲突的

2021-03-05 21:53:13  阅读:216  来源: 互联网

标签:galera mariadb cluster cert 冲突 sql entry thd


大家都知道,galera cluster的作用是支持多节点写入,这样可以避免普通的mysql的主从切换时,造成数据冲突或者丢失。而支持多节点写入机制的原理是在事务提交层,做了主键冲突检查机制,也就是两个节点不能同时处理同一行数据,如果发现冲突,后面提交的那个事务则会回滚。

现在我们来分析一下原理,首先来张galera 官方的文档图:

图片
从上面这个图可以看到,galera 集群跟普通的mysql处理sql语句不同的地方,就在后面提交的部分,也就是commit 命令之后的部分。  真正在数据库commit 之前,会做一下commit的认证(certification), 而认证的核心作用是,检查两个节点是否有事务冲突,也就是判断是否存在修改同一行的事务。


通过几番查找,找到了验证是否冲突的核心函数,如下:

/* returns true on collision, false otherwise */

staticbool

certify_v3(galera::Certification::CertIndexNG& cert_index_ng,

           const galera::KeySet::KeyPart&      key,

           galera::TrxHandle*                  trx,

           boolconst store_keys, boolconst  log_conflicts)

{

    galera::KeyEntryNG ke(key);

   galera::Certification::CertIndexNG::iterator ci(cert_index_ng.find(&ke)); 

    if (cert_index_ng.end() == ci)

    {

        if (store_keys)

        {

            galera::KeyEntryNG* const kep(new galera::KeyEntryNG(ke));

            ci =cert_index_ng.insert(kep).first; 

            cert_debug << "created new entry";

        }

        return false;

    }

    else

    {

        cert_debug << "found existing entry"; 

        galera::KeyEntryNG* const kep(*ci);

        // Note: For we skip certification for isolated trxs, only

        // cert index and key_list is populated.

        return (!trx->is_toi() &&

               certify_and_depend_v3(kep, key, trx, log_conflicts));

    }

}

从上面函数的名字,我们就知道其是验证函数,来实现上述图表的验证功能。

certify_v3函数名中的v3,其实是该函数的版本号,因为还有其他版本的验证函数。下面来对上面的代码进行部分解析:

   galera::KeyEntryNG ke(key);  key 是函数的入参,表示的是想要提交的事务所涉及的其中一个key, 然后将做一下格式转换,方便下一行代码使用。

   galera::Certification::CertIndexNG::iterator ci(cert_index_ng.find(&ke)); 


 上行代码中cert_index_ng.find(&ke),就是在已有的key集合中查找是否存在跟事务中的key相冲突的key. 如果没有找到,则ci 就在cert_index_ng的末尾。于是有后面的判断。

if (cert_index_ng.end() == ci) 如果成立,则不存在相同的key, 然后将这个key进行cert_index_ng.insert(kep).first 操作,即放入cert_index_ng 集合列表中,并将其放在为集合列表的头部。 然后返回false , 即不存在冲突。

if (cert_index_ng.end() == ci) 如果不成立,则存在相同的key,需要做进一步的判断,即调用了函数 certify_and_depend_v3(kep, key, trx, log_conflicts)做进一步检查,如果该函数仍然返回true,则冲突。如果返回false ,则虽然存在相同的key, 但不冲突。

在一个sql事务提交时,galera集群中的节点都会执行这个函数,用于检查是否出现冲突。


下面是在执行sql节点上,certify_v3 函数的调用栈。

#1  0x00007f3b818be8f6 in certify_v3 (cert_index_ng=..., key=..., trx=0x7f3b0e8ae000, store_keys=true, log_conflicts=false) at galera/src/certification.cpp:571

#2  0x00007f3b818bea50 in galera::Certification::do_test_v3 (this=0x7f3b82f3a7b8, trx=0x7f3b0e8ae000, store_keys=true) at galera/src/certification.cpp:598

#3  0x00007f3b818bf55f in galera::Certification::do_test (this=0x7f3b82f3a7b8, trx=0x7f3b0e8ae000, store_keys=true) at galera/src/certification.cpp:749

#4  0x00007f3b818c0906 in galera::Certification::test (this=0x7f3b82f3a7b8, trx=0x7f3b0e8ae000, bval=true) at galera/src/certification.cpp:927

#5  0x00007f3b818c12f1 in galera::Certification::append_trx (this=0x7f3b82f3a7b8, trx=0x7f3b0e8ae000) at galera/src/certification.cpp:1033

#6  0x00007f3b818f4181 in galera::ReplicatorSMM::cert (this=0x7f3b82f39e00, trx=0x7f3b0e8ae000) at galera/src/replicator_smm.cpp:1700

#7  0x00007f3b818f0f29 in galera::ReplicatorSMM::cert_and_catch (this=0x7f3b82f39e00, trx=0x7f3b0e8ae000) at galera/src/replicator_smm.cpp:1785

#8  0x00007f3b818ec5c0 in galera::ReplicatorSMM::pre_commit (this=0x7f3b82f39e00, trx=0x7f3b0e8ae000, meta=0x7f3b1efff098) at galera/src/replicator_smm.cpp:730

#9  0x00007f3b819074a0 in galera_pre_commit (gh=0x7f3b82c993c0, conn_id=17, trx_handle=0x7f3b1efff0d0, flags=1, meta=0x7f3b1efff098) at galera/src/wsrep_provider.cpp:513

#10 0x00007f3b855f6f49 in wsrep_run_wsrep_commit (thd=thd@entry=0x7f3b1effa008, all=all@entry=true) at /data/mariadb/mariadb-10.1.14/sql/wsrep_hton.cc:483

#11 0x00007f3b855f7e58 in wsrep_prepare (hton=<optimized out>, thd=0x7f3b1effa008, all=<optimized out>) at /data/mariadb/mariadb-10.1.14/sql/wsrep_hton.cc:193

#12 0x00007f3b85656c32 in prepare_or_error (ht=ht@entry=0x7f3b82ee18c8, thd=thd@entry=0x7f3b1effa008, all=all@entry=true) at /data/mariadb/mariadb-10.1.14/sql/handler.cc:1147

#13 0x00007f3b856591bd in ha_commit_trans (thd=thd@entry=0x7f3b1effa008, all=all@entry=true) at /data/mariadb/mariadb-10.1.14/sql/handler.cc:1425

#14 0x00007f3b855bd0c4 in trans_commit (thd=thd@entry=0x7f3b1effa008) at /data/mariadb/mariadb-10.1.14/sql/transaction.cc:236

#15 0x00007f3b854f3786 in mysql_execute_command (thd=thd@entry=0x7f3b1effa008) at /data/mariadb/mariadb-10.1.14/sql/sql_parse.cc:4996

#16 0x00007f3b854f89f7 in mysql_parse (thd=thd@entry=0x7f3b1effa008, rawbuf=rawbuf@entry=0x7f3b0e872020 "commit", length=length@entry=6, parser_state=parser_state@entry=0x7f3b765f6610)

    at /data/mariadb/mariadb-10.1.14/sql/sql_parse.cc:7314

#17 0x00007f3b854f9181 in wsrep_mysql_parse (thd=thd@entry=0x7f3b1effa008, rawbuf=0x7f3b0e872020 "commit", length=6, parser_state=parser_state@entry=0x7f3b765f6610)

    at /data/mariadb/mariadb-10.1.14/sql/sql_parse.cc:7136

#18 0x00007f3b854fb6ab in dispatch_command (command=command@entry=COM_QUERY, thd=thd@entry=0x7f3b1effa008, packet=packet@entry=0x7f3b21787009 "commit", packet_length=packet_length@entry=6)

    at /data/mariadb/mariadb-10.1.14/sql/sql_parse.cc:1484

#19 0x00007f3b854fc511 in do_command (thd=0x7f3b1effa008) at /data/mariadb/mariadb-10.1.14/sql/sql_parse.cc:1107

#20 0x00007f3b855afc54 in do_handle_one_connection (thd_arg=thd_arg@entry=0x7f3b1effa008) at /data/mariadb/mariadb-10.1.14/sql/sql_connect.cc:1350

#21 0x00007f3b855afe27 in handle_one_connection (arg=0x7f3b1effa008) at /data/mariadb/mariadb-10.1.14/sql/sql_connect.cc:1262

#22 0x00007f3b84c98dc5 in start_thread () from /lib64/libpthread.so.0

#23 0x00007f3b83935ced in clone () from /lib64/libc.so.6


标签:galera,mariadb,cluster,cert,冲突,sql,entry,thd
来源: https://blog.51cto.com/15057824/2648691

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有