zoukankan      html  css  js  c++  java
  • UNABLE TO PURGE A RECORD(二)

          上一篇文章说明了bug出现的原因和原理分析,要修复bug似乎已经水到渠成了,但远没有这么简单,只因为“并发”。要修复问题,首先要做的第一件事情是稳定的复现问题。由于数据库系统是一个并发系统,并且这个bug只有一定的概率出现,更说明了多个线程在一定的执行序列情况下才会出现这个bug。在没有用户请求的情况下,mysql自身的线程就很多,比如主线程,IO线程,监控线程,监听线程等;有用户请求的情况下,还会分配工作线程为用户服务。我们只找和bug相关的线程:purge线程,IO线程,工作线程。Purge线程主要工作是执行purge操作,产生IBUF_OP_DELETE操作;工作线程则主要执行DELETE,INSERT语句,产生IBUF_OP_INSERT和IBUF_OP_DELETE_MARK操作;IO线程则是IBUF的merge操作。为达到重现bug的目的,我们需要产生IBUF_OP_DELETE_MARK,IBUF_OP_INSERT和IBUF_OP_DELETE序列。由于这里面涉及到purge线程和用户线程,因此涉及一个协同问题。如何协同?

    DEBUG_SYNC

           DEBUG_SYNC是mysql源码中自带的宏,通过信号的方式实现多个线程间的同步。假设存在两个线程thread-1(A,B),thread-2(a,b),A,B和a,b分别是thread-1和thread-2的执行顺序。为了得到AaBb执行序列,可以通过DEBUG_SYNC实现。

    1) 源代码中,设置同步点

    Session-1(thread-1)

    Session-2(thread-2)

    A

    a

    DEBUG_SYNC(“after_A”)

    DEBUG_SYNC(“after_a”)

    B

    b

    DEBUG_SYNC(“after_B”)

     

     

    2) Session设置

    Session-1(thread-1)

    Session-2(thread-2)

     A

    set debug_sync = "now wait_for stepA ";

    set debug_sync="after_A signal stepA wait_for  stepa";

    a

    B

    set debug_sync = "after_a signal stepa wait_for stepB";

    set debug_sync=”after_B singal stepB”;

     b

          通过在代码中设置同步点,以及在会话中设置同步关系即可以实现在并发环境下稳定地得到AaBb序列。注意到2)中的蓝色字体表示同步点,红色字体signal和 wait_for表示动作。比如“after_A signal stepA wait_for  stepa”表示执行到同步点after_A后,发出信号after_A,并且等待stepa信号的到来。另外,其中now是一个特殊的关键字,表示执行到指定位置立即wait for 或者signal。debug_sync似乎已经完美地解决了同步问题,但问题是,通过debug_sync同步,需要会话设置等待或发出信号动作,如果需要和后台线程同步怎么办?而这个bug恰好又需要和后台线程purge,以及IO线程同步。别着急,有需求,就一定有解,mysql还有另外一种协同方法,DBUG_EXECUTE_IF。

    DBUG_EXECUTE_IF

          DBUG_EXECUTE_IF原理就很简单了,就是在某一点执行一定的操作,至于是什么操作则没有限制。显然,我们可以在某一个点执行sleep函数,虽然无法做到严格的同步,但也基本能满足需求。DEBUG_EXECUTE_IF的基本格式为:DEBUG_EXECUTE_IF(key, code),比如为了得到AaBb序列,可以通过DBUG_EXECUTE_IF实现

    1)  源代码中,设置操作点

    Session-1(thread-1)

    Session-2(thread-2)

     

    DEBUG_EXECUTE_IF (“before_a”,{my_sleep(1)})

    A

    a

    DEBUG_EXECUTE_IF (“after_A”,{my_sleep(3)})

    DEBUG_EXECUTE_IF(“after_b”, {my_sleep(5)})

    B

    b

    DEBUG_EXECUTE_IF (“after_B”, {my_sleep(7)})

     

    2) Session设置

    这里为了让后台线程也起作用,可以设置全局debug变量,若只想对本session起作用,可以设置会话debug变量。设置后,执行到对应的操作点时,则会额外执行DEBUG_EXECUTE_IF里面的代码。通过sleep方式来同步是一种取巧的方式,在实际情况中,需要不断调整sleep的时间,尽可能保证能按照预设的顺序执行。设置如下:红色部分是加的代码。

    set global debug=+d,before_a, after_A, after_B, after_b”;

    实践

           对于我们这个案例而言,为了得到指定的IBUF序列(IBUF_OP_DELETE_MARK,IBUF_OP_INSERT和IBUF_OP_DELETE),首先保证操作页面不出现在buffer_pool中;其次,执行INSERT操作产生的IBUF_OP_INSERT必需先于PURGE执行,最后,在整个过程中页面不能被MERGE,否则也将功亏一篑。对于第一点,可以通过将buffer_pool设置地比较小,然后扫描一个大表达到清理buffer_pool的目的;对于第二点,由于执行IBUF缓存的函数是IBUF_INSERT,针对类型为IBUF_OP_DELETE,强制其等待;对于第三点,在执行merge ibuf的地方,也强制其等待,并且比PURGE等待的时间要更长。具体设置点如下:

    /*storage/innobase/ibuf/ibuf0ibuf.cc: ibuf_insert*/
    ibuf_insert
    {
        DBUG_EXECUTE_IF("sleep_ibuf_insert",{
        if (op == IBUF_OP_DELETE)    
          my_sleep(3000000);
        });
    
      ......
     ibuf_insert_low();
    }
    
    /* storage/innobase/ibuf/ibuf0ibuf.cc:ibuf_merge_pages*/
    ibuf_merge_pages
    {
       ......
      DBUG_EXECUTE_IF("sleep_ibuf_merge",{my_sleep(5000000);});
     
       buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos, *n_pages);//merge操作
    }

     说明:为了使用debug_sync功能,编译mysqld时需要开启-DENABLE_DEBUG_SYNC=1 ,启动mysqld时,需要带启动选项--debug-sync-timeout

    总结

        在整个重现bug的过程中,其实还有很多细节,因为代码中总是会有很多if else的判断,以及特定标记位导致的特殊操作,因此打日志和debug很重要,通过打日志,了解大体执行流程;通过debug来了解细节,从而能掌握关键路径,在关键路径上设置合适的同步点,则能在并发环境下得到想要的执行序列。

    参考文档

    https://dev.mysql.com/doc/internals/en/debug-sync-facility.html

    http://www.gpfeng.com/?p=461

    http://hedengcheng.com/?p=238

    http://www.cnblogs.com/cchust/p/4544518.html

     

     

     

  • 相关阅读:
    Software Solutions CACHE COHERENCE AND THE MESI PROTOCOL
    CACHE COHERENCE AND THE MESI PROTOCOL
    Multiprocessor Operating System Design Considerations SYMMETRIC MULTIPROCESSORS
    Organization SYMMETRIC MULTIPROCESSORS
    PARALLEL PROCESSING
    1分钟内发送差评邮件
    Secure Digital
    SYMMETRIC MULTIPROCESSORS
    A Taxonomy of Parallel Processor Architectures
    parallelism
  • 原文地址:https://www.cnblogs.com/cchust/p/4564741.html
Copyright © 2011-2022 走看看