Innodb引擎 long semaphore waits

上一篇介绍了因为子表过多,导致innodb crash的情况,但crash的原因是long semaphore waits。
long semaphore waits又为何物?

 

背景:Innodb使用了mutex和rw_lock来保护内存数据结构,同步的机制要么是互斥,要么是读写阻塞的模式,
Innode认为mutex和rw_lock hold的时间足够短,所以,如果有线程wait mutex或者rw_lock时间过长,那么
很可能是程序有bug,所以就会异常主动crash。

 

关于innodb的锁:可以参考前面介绍的blog。

 

1. Innodb如何界定时间过长?  

/* The following is the maximum allowed duration of a lock wait. */
UNIV_INTERN ulint    srv_fatal_semaphore_wait_threshold = 600;

Innodb的认为600s足够长。

 

2. Innodb如何判断?

    /* Create the thread which warns of long semaphore waits */
    os_thread_create(&srv_error_monitor_thread, NULL,
             thread_ids + 3 + SRV_MAX_N_IO_THREADS);

innodb后台启动了一个线程,专门监控wait队列,

   if (sync_array_print_long_waits(&waiter, &sema)
        && sema == old_sema && os_thread_eq(waiter, old_waiter)) {
        fatal_cnt++;
        if (fatal_cnt > 10) {
            fprintf(stderr,
                "InnoDB: Error: semaphore wait has lasted"
                " > %lu seconds\n"
                "InnoDB: We intentionally crash the server,"
                " because it appears to be hung.\n",
                (ulong) srv_fatal_semaphore_wait_threshold);

            ut_error;
        }

判断10次,如果是同一个线程,等待同一个sema,那么就crash掉Innodb。

    for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
        double    diff;
        void*    wait_object;
        cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
        wait_object = cell->wait_object;
        if (wait_object == NULL || !cell->waiting) {
            continue;
        }
        diff = difftime(time(NULL), cell->reservation_time);
        if (diff > SYNC_ARRAY_TIMEOUT) {
            fputs("InnoDB: Warning: a long semaphore wait:\n",
                  stderr);
            sync_array_cell_print(stderr, cell);
            noticed = TRUE;
        }
        if (diff > fatal_timeout) {
            fatal = TRUE;
        }
        if (diff > longest_diff) {
            longest_diff = diff;
            *sema = wait_object;
            *waiter = cell->thread;

sync_primary_wait_array是一个数组,每一个wait sema的进入队列, 找到等待时间最长的,并且大于600s的,就设置fatal=TRUE。

posted @ 2014-08-09 21:41  xpchild  阅读(1629)  评论(0编辑  收藏  举报