t1

来自实践的教训

以下每段都是对实践中遇到的真实问题的总结,个别内容还有待更深入地探索。

自增列步长兼容性问题

准生产上线的当天,发现一个重要模块的某些功能随机报错,错误信息大致为“Primary Key not Found”,经过各层面的调查,最后终于发现是PXC的自调整自增列的默认行为,与公司使用的OR-Mapping的Ruby类库Active Record不匹配。PXC默认会开启wsrep_auto_increment_control,每个节点的自增列步长会根据PXC节点数量的变化自动设置,而Active Record的某些函数假设新增列的步长为1,并没有考虑到>1的情况。最终关闭wsrep_auto_increment_control并保持单点写入作为解决方案。

关于GTID空洞的坑

目前我们的实践经验是,GTID或者PXC单独使用都可以,如果二者同时使用,某些情况下会导致GTID产生空洞,再切换Slave时不能自动转接,需要DBA人工干预。具体细节如下:正常GTID为UUID:X1-Y1的格式,但有时会有:UUID:X1-X2:X3-Y1(X3>X2+1,也就是不连续)的情况发生。这里提醒读者,一定注意小心验证,防止Slave不能Switch Master的尴尬问题发生。具体原则就是Slave的UUID一定要是Master GTID的子集。一般说来可以通过SELECT GTID_SUBSET(“uuid:xxxxxx”,“uuid:yyyyyyy”)来提前判定,源代码层面以下代码段的检查需要正确返回才可以:

        mysql-server/sql/rpl_binlog_sender.cc(5.6):707:
        int Binlog_sender::check_start_file()
        {……
        if (! m_exclude_gtid->is_subset_for_sid(&gtid_executed_and_owned,
                                                    gtid_state->get_server_
        sidno(),
                                                  subset_sidno))
            {
              errmsg= ER(ER_SLAVE_HAS_MORE_GTIDS_THAN_MASTER);
              global_sid_lock->unlock();
              set_fatal_error(errmsg);
              return 1;
        }
        if (! gtid_state->get_lost_gtids()->is_subset(m_exclude_gtid))
        {
              errmsg= ER(ER_MASTER_HAS_PURGED_REQUIRED_GTIDS);
              global_sid_lock->unlock();
              set_fatal_error(errmsg);
              return 1;
            }

不兼容SQL的问题

这里不再多说,GTID启用备战时,以下两个场景测试都被我们命中,得以提前推动开发团队进行完善。这里提醒读者的就是一定要采用尽量完备的测试用例,不然上线后会非常被动。

i.显示事务内的create/drop temp table不支持

ii. create table… select statement不支持

SST/IST对性能的影响

为了尽量避免PXC的SST(全量恢复),我们做了定制化设置:

        wsrep_provider_options="gcache.size=1G"
        wsrep_sst_donor = pxc02
        [sst]
        rlimit=70m

gcache.size用于尽量使用IST, wsrep_sst_donor用于保护PXC01的IO性能;

rlimit用于在IST/SST时三节点之间的网络限速。而且必须安装linux PV command。