您的位置:首页 > 数据库 > SQL

MYSQL:同时设置innodb_force_recovery和innodb_purge_thread导致无限loop

2012-01-29 13:58 507 查看
转载请署名:印风

--------------------------------------------------------------------------

版本:Percona5.5.18

设置参数:

innodb_force_recovery>=2

innodb_purge_thread = 1

观察alert.log,出现大量信息:

InnoDB: Waiting for the background threads to start


我们定位到相应的代码:

在srv_purge_thread里,会判断当前是否以recovery mode启动:

879         /* Check for shutdown and whether we should do purge at all. */
3880         if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND
3881             || srv_shutdown_state != 0
3882             || srv_fast_shutdown) {
3883 
3884             break;
3885         }


其中SRV_FORCE_NO_BACKGROUND值为2,可以看看不同的恢复级别分别代表什么:

enum {
    SRV_FORCE_IGNORE_CORRUPT = 1,   /*!< let the server run even if it
                    detects a corrupt page */
    SRV_FORCE_NO_BACKGROUND = 2,    /*!< prevent the main thread from
                    running: if a crash would occur
                    in purge, this prevents it */
    SRV_FORCE_NO_TRX_UNDO = 3,  /*!< do not run trx rollback after
                    recovery */
    SRV_FORCE_NO_IBUF_MERGE = 4,    /*!< prevent also ibuf operations:
                    if they would cause a crash, better
                    not do them */
    SRV_FORCE_NO_UNDO_LOG_SCAN = 5, /*!< do not look at undo logs when
                    starting the database: InnoDB will
                    treat even incomplete transactions
                    as committed */
    SRV_FORCE_NO_LOG_REDO = 6   /*!< do not do the log roll-forward
                    in connection with recovery */
};


也就是说,当恢复级别大于等于2时,将会从while循环中break然后退出线程(os_thread_exit)
但在函数innobase_start_or_create_for_mysql里,由于设置innodb_purge_thread为1,因此这里会等待purge线程起来

2027     while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
2028         if (srv_thread_has_reserved_slot(SRV_MASTER) == ULINT_UNDEFINED
2029             || (srv_n_purge_threads == 1
2030             && srv_thread_has_reserved_slot(SRV_WORKER)
2031             == ULINT_UNDEFINED)) {
2032 
2033             ut_print_timestamp(stderr);
2034             fprintf(stderr, "  InnoDB: "
2035                 "Waiting for the background threads to "
2036                 "start\n");
2037             os_thread_sleep(1000000);
2038         } else {
2039             break;
2040         }
2041     }


FIX:
在创建purge线程前,同时判断recovery值,当>=2时,我们强制将innodb_purge_thread置为0,以防止无限Loop

diff -ur Percona-Server-5.5.18.stock/storage/innobase/srv/srv0start.c Percona-Server-5.5.18.fix-purge/storage/innobase/srv/srv0start.c
--- Percona-Server-5.5.18.stock/storage/innobase/srv/srv0start.c        2012-01-07 16:38:37.000000000 +0800
+++ Percona-Server-5.5.18.fix-purge/storage/innobase/srv/srv0start.c    2012-01-29 11:34:09.000000000 +0800
@@ -2019,7 +2019,14 @@
        /* If the user has requested a separate purge thread then
        start the purge thread. */
        if (srv_n_purge_threads == 1) {
-               os_thread_create(&srv_purge_thread, NULL, NULL);
+               if (srv_force_recovery < SRV_FORCE_NO_BACKGROUND) {
+                       os_thread_create(&srv_purge_thread, NULL, NULL);
+               } else {
+                       fprintf(stderr, " InnoDB: "
+                                       "we will force innodb_purge_thread to 0 "
+                                       "becanse force recovery is larger than 1\n");
+                       srv_n_purge_threads = 0;
+               }
        }
 
        /* Wait for the purge and master thread to startup. */
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: