By
兰春
Updated:
先了解一下mysql的shutdown流程
- The shutdown process is initiated.
- The server creates a shutdown thread if necessary.
- The server stops accepting new connections.
- The server terminates current activity.
- The server shuts down or closes storage engines.
- The server exits.
以上只是官方文档中介绍的一些基本的关机流程,正确的关机命令当然是mysqladmin -xx shutdown 。接下来,我们来关注一下我们的问题
问题描述
mysqladmin shutdown 不但没有关闭掉,反而会restart
提示信息如下:
1 2
| 150105 14:50:47 mysqld_safe Number of processes running now: 0 150105 14:50:47 mysqld_safe mysqld restarted
|
齐了个怪了,我的参数明明是shutdown ,为什么提示信息是 restart呢? 错误日志中也无明显错误, 程序Bug了?
唯一能关闭的方法就是: kill , 这是非法的,我们当然不能这样做。
于是尝试了N种方法
1 2 3 4 5 6 7
| * 可能是/usr/local/mysql/data/xxxx.pid文件没有写的权限 * 可能进程里已经存在mysql进程 * 可能是第二次在机器上安装mysql,有残余数据影响了服务的启动。 * mysql在启动时没有指定配置文件时会使用/etc/my.cnf配置文件,请打开这个文件查看在[mysqld]节下有没有指定数据目录(datadir)。 * skip-federated字段问题 * 错误日志目录不存在 * selinux惹的祸,如果是centos系统,默认会开启selinux
|
很不幸的是,都不是上述问题造成。既然google也找不到,那只能看源码了。
大家都知道,mysqld_safe 是 启动mysql的守护进程,我想89不离10,应该是由它重启的,那就一窥究竟吧。
源码文件如下: mysqld_safe
下面是部分重要的部分,特拿出来分析,其中添加了一些注释和一些方便调试的断点代码(add by keithlan)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| eval_log_error () { cmd="$1" case $logging in file) cmd="$cmd >> "`shell_quote_string "$err_log"`" 2>&1" ;; syslog) cmd="$cmd 2>&1 | logger -t '$syslog_tag_mysqld' -p daemon.error" ;; *) echo "Internal program error (non-fatal):" \ " unknown logging method '$logging'" >&2 ;; esac echo "Running mysqld: [$cmd]" --add by Keithlan eval "$cmd" } log_notice "Starting $MYSQLD daemon with databases from $DATADIR" while true do rm -f $safe_mysql_unix_port "$pid_file" log_notice "rm -f $safe_mysql_unix_port $pid_file !" eval_log_error "$cmd" log_notice " after running mysql " last_pid=`ls -l /usr/local/mysql/var/` log_notice " last_pid = $last_pid !!" if test ! -f "$pid_file" then log_notice "$pid_file" break fi if true && test $KILL_MYSQLD -eq 1 then numofproces=`ps xaww | grep -v "grep" | grep "$ledir/$MYSQLD\>" | grep -c "pid-file=$pid_file"` log_notice "Number of processes running now: $numofproces" I=1 while test "$I" -le "$numofproces" do PROC=`ps xaww | grep "$ledir/$MYSQLD\>" | grep -v "grep" | grep "pid-file=$pid_file" | sed -n '$p'` for T in $PROC do break done if kill -9 $T then log_error "$MYSQLD process hanging, pid $T - killed" else break fi I=`expr $I + 1` done fi log_notice "mysqld restarted" log_notice "Keithlan" done log_notice "mysqld from pid file $pid_file ended"
|
简单描述一下过程就是:myqsld_safe 会用eval去启动mysqld,再后台运行,知道接受到kill 命令,或者shutdown 进程来kill掉它。
如果是非正常kill,mysqld_safe 会一直监控,将mysqld进程 restart起来。
经过调试后,手动去rm -f 掉pid文件, 然后再mysqladmin shutdown,是可以正常关闭的,很明显,就能定位到问题就出在pid上。为什么mysqladmin 进程shutdown的时候没有删除掉pid文件呢? 首先可以排除掉权限等问题,因为既然能够create pid,当然可以delete pid咯。问题一定是mysqladmin 哪个地方出问题了,果然,根据线索找到mysqladmin 代码中断言出现问题Failing assertion: UT_LIST_GET_LEN(rseg->update_undo_list) == 0,网上搜了一堆的bug。 后来,想想,是不是表空间出了问题,mysql shutdown的时候回去回收表空间记录,如果回收不成功,导致不能normal shutdown,导致无法删除掉pid文件。 于是,将表空间重建后,问题消失。
总结
由于时间成本的问题,没能去详细了解mysqladmin 和 table space 的关系,但是却对mysql 的shutdown 流程有了进一步的认识,总算对自己有了一点交代。