MySQL8.0 PXC 集群--GTID-分布式事务

https://zhuanlan.zhihu.com/p/608898859

一句话概括:基于GTID(全局事务标识符),同步复制事务信息到其他节点,其他节点采用写时复制-也就是构造副本来修改然后提交给协调节点-随后协调节点进行事务的提交或者回滚--其中会通过多并发版本机制来避免数据冲突-也就是采用最新的版本号

  1. 主库将修改操作写入二进制日志(Binary Log)中。
  2. 从库连接主库,并请求复制日志。
  3. 主库将二进制日志中的数据发送给从库,并在从库上执行。
  4. 从库将执行结果写入中继日志(Relay Log)中。
  5. 从库根据中继日志中的信息更新自己的数据。

具体来说,当一个事务在PXC中执行写操作时,会生成一个新的版本号,并将该版本号作为GTID广播给其他节点。其他节点在接收到该GTID后,会在本地创建一个新的版本,并保存该版本号。这样,每个节点都有了一个最新的版本号,用于确定数据行的最新版本。

协调节点是集群中的一个特殊节点,它不参与具体的数据读写操作,而是负责管理整个集群的状态和数据同步。

为了避免这些问题,InnoDB存储引擎提供了MVCC和GTID的支持。

在MVCC中,每个数据行都会有多个版本,每个版本有一个唯一的ID。在修改数据时,InnoDB会创建一个新的版本,并将新版本的ID作为GTID广播给其他节点。在读取数据时,InnoDB会选择一个合适的版本来返回,以保证读取的数据是一致的。例如,T1和T2同时读取了表中的记录,T1会选择原始版本,T2会选择T1提交的版本,这样就可以避免出现数据不一致的情况。

在GTID的同步复制中,每个事务都有一个全局唯一的ID,用于标识这个事务在整个集群中的执行情况。在修改数据时,InnoDB会记录修改操作的GTID,并将该GTID广播给其他节点。在其他节点接收到该GTID后,它们会执行相同的操作,并将本地提交的结果发送回协调节点。协调节点会对各个节点提交的结果进行整合和验证,并进行最终的提交或者回滚。这样,InnoDB可以保证数据的一致性和完整性。

  • master节点在更新数据的时候,会在事务前产生GTID信息,一同记录到binlog日志中。
  • slave节点的io线程将binlog写入到本地relay log中。
  • 然后SQL线程从relay log中读取GTID,设置gtid_next的值为该gtid,然后对比slave端的binlog是否有记录。
  • 如果有记录的话,说明该GTID的事务已经运行,slave会忽略。
  • 如果没有记录的话,slave就会执行该GTID对应的事务,并记录到binlog中。
  • 作者:GreatSQL

    链接:https://juejin.cn/post/7064384838039666701

    来源:稀土掘金

    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    • GTID事务是全局唯一性的,并且一个事务对应一个GTID值。
    • 一个GTID值在同一个MySQL实例上只会执行一次。

    GTID(Global Transaction ID,全局事务标识符)

    跟踪事务:GTID 可以跟踪事务在分布式环境中的执行情况,当一个节点提交了一个事务时,它会生成一个全局事务标识符,并将该标识符发送给其他节点。其他节点会通过该标识符来判断事务的提交情况,并进行数据同步

    GTID 主要由两个部分组成:server_uuid 和 sequence_number。其中,server_uuid 是一个唯一的标识符,用于标识 MySQL 实例;sequence_number 是一个递增的数字,用于标识 MySQL 实例中提交的事务数。

    在多主复制的实现过程中,Galera 使用了基于写时复制(copy-on-write)的技术来避免数据冲突。当一个节点更新了数据时,它会将更新的数据存储在内存中,并将内存中的数据复制到其他节点,而不是直接更新磁盘上的数据。这种方式可以避免数据冲突,提高并发性能。

    在多主复制的实现过程中,通常采用乐观锁或者版本控制来避免数据冲突,而不是采用传统的分布式锁。具体来说,每个节点都维护一个事务日志,当一个节点更新数据时,它会在事务日志中记录一个版本号。其他节点在更新数据时,会检查数据的版本号是否与自己的版本号一致,如果一致,则更新数据;如果不一致,则认为数据已经被其他节点更新,需要进行冲突处理。

    GTID 机制仅适用于分布式环境下的 MySQL 实例。在单个 MySQL 实例中,可以使用 binlog 文件来跟踪事务的执行情况。

    Galera是同步复制方案,事务在本地节点(客户端提交事务的节点)上提交成功时,其它节点保证执行该事务。在提交事务时,本地节点把事务复制到所有节点后,之后各个节点独立异步地进行certification test、事务插入待执行队列、执行事务。然而由于不同节点之间执行事务的速度不一样,长时间运行后,慢节点的待执行队列可能会越积越长,最终可能导致事务丢失。Galera内部实现了flow control,作用就是协调各个节点,保证所有节点执行事务的速度大于队列增长速度,从而避免丢失事务。

    Raft算法会先选举出Leader,Leader完全负责replicated log的管理,Leader负责接受所有客户端更新请求,然后复制到Follower,并在“安全”的时候执行这些请求,如果Leader故障,Follower会重新选举出新的Leader,保证一致性。

    Paxos proposer将发起提案(value)给所有accpetor,超过半数accpetor获得批准后,proposer将提案写入accpetor内,最终所有accpetor获得一致性的确定性取值,且后续不允许再修改。

    将所有节点都写入同一个值,且被写入后不再更改。

    MySQL 数据库主从复制有异步复制、半同步复制和全同步复制的方式。

    异步复制:异步复制模式下,主库在接受并处理客户端的写入请求时,直接返回执行结果,不关心从库同步是否成功,这样就会存在上面说的问题,主库崩溃以后,可能有部分操作没有同步到从库,出现数据丢失问题。

    半同步复制:在半同步复制模式下,主库需要等待至少一个从库完成同步之后,才完成写操作。主库在执行完客户端提交的事务后,从库将日志写入自己本地的 relay log 之后,会返回一个响应结果给主库,主库确认从库已经同步完成,才会结束本次写操作。相对于异步复制,半同步复制提高了数据的安全性,避免了主库崩溃出现的数据丢失,但是同时也增加了主库写操作的耗时。

    全同步复制:全同步复制指的是在多从库的情况下,当主库执行完一个事务,需要等待所有的从库都同步完成以后,才完成本次写操作。全同步复制需要等待所有从库执行完对应的事务,所以整体性能是最差的。

    作者:我是一只鱼吖

    链接:https://juejin.cn/post/7143541597165060109

    来源:稀土掘金

    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    pxc-master.yml 文件

    version: '3'
    services:
      pxc1:
        image: percona/percona-xtradb-cluster:8.0
        restart: always
        container_name: pxc1
        privileged: true
        ports:
          - 13306:3306
          - 14444:4444
          - 14567:4567
          - 14568:4568
        environment:
          - MYSQL_ROOT_PASSWORD=123456
          - CLUSTER_NAME=pxc_cluster
        volumes:
          - /var/lib/docker/volumes/v1/mysql/data:/var/lib/mysql/
          - /var/lib/docker/volumes/v1/mysql/cert:/cert/
          - /var/lib/docker/volumes/v1/mysql/config:/etc/percona-xtradb-cluster.conf.d
        networks:
          default:
            ipv4_address: 172.20.0.2
    
    
      pxc2:
        image: percona/percona-xtradb-cluster:8.0
        restart: always
        container_name: pxc2
        privileged: true
        ports:
          - 33306:3306
          - 34444:4444
          - 34567:4567
          - 34568:4568
        environment:
          - MYSQL_ROOT_PASSWORD=123456
          - CLUSTER_NAME=pxc_cluster
          - CLUSTER_JOIN=172.20.0.2
        volumes:
          - /var/lib/docker/volumes/v2/mysql/data:/var/lib/mysql/
          - /var/lib/docker/volumes/v2/mysql/cert:/cert/
          - /var/lib/docker/volumes/v2/mysql/config:/etc/percona-xtradb-cluster.conf.d
        networks:
          default:
            ipv4_address: 172.20.0.12
      pxc3:
        image: percona/percona-xtradb-cluster:8.0
        restart: always
        container_name: pxc3
        privileged: true
        ports:
          - 23306:3306
          - 24444:4444
          - 24567:4567
          - 24568:4568
        environment:
          - MYSQL_ROOT_PASSWORD=123456
          - CLUSTER_NAME=pxc_cluster
          - CLUSTER_JOIN=172.20.0.2
        volumes:
          - /var/lib/docker/volumes/v3/mysql/data:/var/lib/mysql/
          - /var/lib/docker/volumes/v3/mysql/cert:/cert/
          - /var/lib/docker/volumes/v3/mysql/config:/etc/percona-xtradb-cluster.conf.d
        networks:
          default:
            ipv4_address: 172.20.0.13
    # volumes:
    #   v1/mysql/data:
    #   v1/mysql/cert:
    #   v1/mysql/config:
    #   v2/mysql/data:
    #   v2/mysql/cert:
    #   v2/mysql/config:
    #   v3/mysql/data:
    #   v3/mysql/cert:
    #   v3/mysql/config:
    networks:
      default:
        external:
          name: mysql_default
    

    custom.cnf

    [mysqld]
    ssl-ca = /cert/ca.pem
    ssl-cert = /cert/server-cert.pem
    ssl-key = /cert/server-key.pem
    
    [client]
    ssl-ca = /cert/ca.pem
    ssl-cert = /cert/client-cert.pem
    ssl-key = /cert/client-key.pem
    
    [sst]
    encrypt = 4
    ssl-ca = /cert/ca.pem
    ssl-cert = /cert/server-cert.pem
    ssl-key = /cert/server-key.pem
    
    

    node.cnf

    [mysqld]
    
    default_authentication_plugin=mysql_native_password
    datadir=/var/lib/mysql
    socket=/tmp/mysql.sock
    skip-host-cache
    
    #coredumper
    #server_id=0
    binlog_format=ROW
    default_storage_engine=InnoDB
    
    innodb_flush_log_at_trx_commit  = 0
    innodb_flush_method             = O_DIRECT
    innodb_file_per_table           = 1
    innodb_autoinc_lock_mode=2
    
    bind_address = 0.0.0.0
    
    wsrep_slave_threads=2
    wsrep_cluster_address=gcomm://
    wsrep_provider=/usr/lib64/galera4/libgalera_smm.so
    
    wsrep_cluster_name=pxc_cluster
    wsrep_node_address=172.20.0.2
    wsrep_node_incoming_address=8a69f9baf846:3306
    
    wsrep_sst_method=xtrabackup-v2
    
    [client]
    socket=/tmp/mysql.sock
    
    [sst]
    progress=/var/lib/mysql/sst_in_progress
    pxc-encrypt-cluster-traffic=OFF
    
    

    #多主复制#
    全部评论

    相关推荐

    不愿透露姓名的神秘牛友
    06-20 20:30
    点赞 评论 收藏
    分享
    避坑恶心到我了大家好,今天我想跟大家聊聊我在成都千子成智能科技有限公司(以下简称千子成)的求职经历,希望能给大家一些参考。千子成的母公司是“同创主悦”,主要经营各种产品,比如菜刀、POS机、电话卡等等。听起来是不是有点像地推销售公司?没错,就是那种类型的公司。我当时刚毕业,急需一份临时工作,所以在BOSS上看到了千子成的招聘信息。他们承诺无责底薪5000元,还包住宿,这吸引了我。面试的时候,HR也说了同样的话,感觉挺靠谱的。于是,我满怀期待地等待结果。结果出来后,我通过了面试,第二天就收到了试岗通知。试岗的内容就是地推销售,公司划定一个区域,然后你就得见人就问,问店铺、问路人,一直问到他们有意向为止。如果他们有兴趣,你就得摇同事帮忙推动,促进成交。说说一天的工作安排吧。工作时间是从早上8:30到晚上18:30。早上7点有人叫你起床,收拾后去公司,然后唱歌跳舞(销售公司都这样),7:55早课(类似宣誓),8:05同事间联系销售话术,8:15分享销售技巧,8:30经理训话。9:20左右从公司下市场,公交、地铁、自行车自费。到了市场大概10点左右,开始地推工作。中午吃饭时间大约是12:00,公司附近的路边盖饭面馆店自费AA,吃饭时间大约40分钟左右。吃完饭后继续地推工作,没有所谓的固定中午午休时间。下午6点下班后返回公司,不能直接下班,需要与同事交流话术,经理讲话洗脑。正常情况下9点下班。整个上班的一天中,早上到公司就是站着的,到晚上下班前都是站着。每天步数2万步以上。公司员工没有自己的工位,百来号人挤在一个20平方米的空间里听经理洗脑。白天就在市场上奔波,公司的投入成本几乎只有租金和工资,没有中央空调。早上2小时,晚上加班2小时,纯蒸桑拿。没有任何福利,节假日也没有3倍工资之类的。偶尔会有冲的酸梅汤和西瓜什么的。公司的晋升路径也很有意思:新人—组长—领队—主管—副经理—经理。要求是业绩和团队人数,类似传销模式,把人留下来。新人不能加微信、不能吐槽公司、不能有负面情绪、不能谈恋爱、不能说累。在公司没有任何坐的地方,不能依墙而坐。早上吃早饭在公司外面的安全通道,未到上班时间还会让你吃快些不能磨蹭。总之就是想榨干你。复试的时候,带你的师傅会给你营造一个钱多事少离家近的工作氛围,吹嘘工资有多高、还能吹自己毕业于好大学。然后让你早点来公司、无偿加班、抓住你可能不会走的心思进一步压榨你。总之,大家在找工作的时候一定要擦亮眼睛,避免踩坑!———来自网友
    qq乃乃好喝到咩噗茶:不要做没有专业门槛的工作
    点赞 评论 收藏
    分享
    爱睡觉的冰箱哥:学历不够啊兄弟,分析师都是9硕✌🏻咱搞不过他们滴
    点赞 评论 收藏
    分享
    评论
    点赞
    收藏
    分享

    创作者周榜

    更多
    牛客网
    牛客网在线编程
    牛客网题解
    牛客企业服务