DEBUG_SYNC的功能,默认是关闭的。除非在启动的时候指定了–debug-sync-timeout[=N] 选项,N是可选的,可以指定也可以不指定。不指定的话,默认是300秒。

这个选项是启动时变量,为了能在测试中使用DEBUG_SYNC功能,必须在启动的时候指定–debug-sync-timeout[=N] 选项。这个参数有两个作用: 1) 其一是指定wait_for一个同步点的最大等待时间(单位:秒),若超过这个时间就会timeout; 2) 另一个是打开/关闭DEBUG_SYNC功能的选项,当其后的参数N为0时,就关闭了DEBUG_SYNC功能。

其核心代码主要通过定义的宏DEBUG_SYNC做为入口,其定义如下:

  1. do { \
  2. if (unlikely(opt_debug_sync_timeout)) \
  3. } while (0)

这个宏的源码实现,主要是通过定义一个同步点(这个同步点是通过这里定义的名字来表示的_sync_point_name_),线程就会在这个同步点执行定义的行为动作,比如是在这个同步点发信号给等在其他同步点的线程、还是等在某个定义的事件上。在DEBUG_SYNC目前同步点的行为只定义了给其它同步点发信号、和等在某个信号上。其实现的主要数据结构如下:

  1. if (ds_control->ds_active &&
  2. (action = debug_sync_find(ds_control->ds_action, ds_control->ds_active,
  3. action->activation_count) {
  4. /* Sync point is active (action exists). */
  5. debug_sync_execute(thd, action);
  6. /* Statistics. */
  7. /* If action became inactive, remove it to shrink the search array. */
  8. if (!action->activation_count) debug_sync_remove_action(ds_control, action);
  9. }

首先在debug_sync_find里通过二分查找是否有同步点的要执行的行为动作,若是找到的话,就通过debug_sync_execute函数去执行。在debug_sync_execute根据定义的同步点执行次数,去判断是否达到了执行的次数,若没有达到执行的次数,则会在每次都会等这个event的信号。

在源码中使用的例子如下所示,开发者可以在任意的位置加入同步点,并给同步点命名,这样这个同步点就可以在接下来的测试案例中使用了。

  1. open_tables(...)
  2. DEBUG_SYNC(thd, "after_open_tables");
  3. lock_tables(...)

在测试场景中使用同步点

测试场景使用的语法,可以参考 。在测试场景中,同步点的使用主要有以下几种情况: 1)SET DEBUG_SYNC=‘sync point name SIGNAL signal name WAIT_FOR signal name 是最常用的方法。 比如: SET DEBUG_SYNC= ‘after_open_tables SIGNAL opened WAIT_FOR flushed’; 大部分情况下同步点都是未激活状态,当对整个同步点请求某个行为时就激活了这个同步点。比如上面这个例子,当执行到同步点after_open_tables后会向等待opened事件发送信号同时等在flushed时间上时,就激活了after_open_tables同步点。

2)SET DEBUG_SYNC= ‘after_open_tables SIGNAL a,b,c WAIT_FOR flushed’; 这中用法和1)的主要区别就是一次唤醒多个事件a、b、c,其它和1)相同

4)SET DEBUG_SYNC= ‘name SIGNAL sig EXECUTE 3’; 一般情况下,等待线程被激活执行完后,马上就清除唤醒等待线程的信号。为了不立马清除激活信号,我们可以通过关键字EXECUTE指定执行的次数,执行完指定的次数后,才清除激活信号。比如这个例子指定了执行3次、每执行完一次这个数字就会减1,直到减到0为止。

5) SET DEBUG_SYNC= ‘name WAIT_FOR sig TIMEOUT 10 EXECUTE 2’; 在MySQL启动的时候,可以通过参数debug-sync-timeout指定一个等待事件的超时时间,也可以通过TIMEOUT 关键字为每个等待事件单独指定超时时间。这个例子就是等待线程最长等待10秒,若超过10秒还没收到唤醒等待事件的信号,就会超时不再等待了。

6)SET DEBUG_SYNC= ‘name SIGNAL sig EXECUTE 2 HIT_LIMIT 3’; 如果你想在执行完指定的次数后,返回一个错误消息并且中断这个线程的话,可以通过HIT_LIMIT来指定。这个例子中就是在执行完3次后,会返回一个错误消息并且中断这个查询。

7)SET DEBUG_SYNC= ‘name CLEAR’; 这个是可以在任何时候都清除name指定的同步点,不管它执行了还是没执行。