MySQL服务读取参数文件my.cnf的规律研究探索
在MySQL中,它是按什么順序或規(guī)律去讀取my.cnf配置文件的呢?其實只要你花一點功夫,實驗測試一下就能弄清楚,下面的實驗環(huán)境為5.7.21 MySQL Community Server。其它版本如有不同,請以實際情況為準。
?
其實,MySQL是按照下面這個順序來讀取my.cnf:
?
??? 1: /etc/my.cnf
??? 2: /etc/mysql/my.cnf
??? 3: /usr/etc/my.cnf
??? 4: ~/.my.cnf
?
也就是說首先它會找/etc/my.cnf 這個文件, 如果這個文件不存在,那么它接下來去找/etc/mysql/my.cnf這個文件,依此類推(這個實驗很簡單,在此略過,不浪費篇幅),如果最后一個文件~/.my.cnf 也不存在,那么會怎么樣呢?
[root@gettestlnx02 ~]# mysql --help | grep my.cnf????????????????????? order of preference, my.cnf, $MYSQL_TCP_PORT,/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf [root@gettestlnx02 ~]# ls /etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnfls: cannot access /etc/mysql/my.cnf: No such file or directoryls: cannot access /usr/etc/my.cnf: No such file or directoryls: cannot access /root/.my.cnf: No such file or directory/etc/my.cnf[root@gettestlnx02 ~]#?
如上所示,其實MySQL安裝完成后,只生成了/etc/my.cnf這個配置文件。其它路徑的my.cnf文件是不存在的。我們先來測試一下,將配置文件移走。在這之前,我們先查看一下log_error的位置。如下所示:
?
?
mysql> show variables like '%log_error%';+---------------------+---------------------+| Variable_name?????? | Value?????????????? |+---------------------+---------------------+| binlog_error_action | ABORT_SERVER??????? || log_error?????????? | /var/log/mysqld.log || log_error_verbosity | 3?????????????????? |+---------------------+---------------------+3 rows in set (0.00 sec)?mysql> exitBye?
?
[root@gettestlnx02 ~]# mv /etc/my.cnf? /tmp/my.cnf[root@gettestlnx02 ~]# ls -lrt /etc/my.cnfls: cannot access /etc/my.cnf: No such file or directory[root@gettestlnx02 ~]# service mysqld stopStopping mysqld:? [? OK? ][root@gettestlnx02 ~]# service mysqld startStarting mysqld:? [? OK? ][root@gettestlnx02 ~]#?
?
?
?
如上所示,即使沒了my.cnf配置文件,MySQL服務依然可以啟動,那么這個是怎么回事呢? 我們知道service mysqld start啟動MySQL,其實是運行/etc/init.d/mysqld這個腳本。下面是腳本獲取給變量datadir、socketfile、errlogifle賦值的部分腳本,如下所示:
?
# Extract value of a MySQL option from config files# Usage: get_mysql_option OPTION DEFAULT SECTION1 SECTION2 SECTIONN# Result is returned in $result# We use my_print_defaults which prints all options from multiple files,# with the more specific ones later; hence take the last match.get_mysql_option () {??? option=$1??? default=$2??? shift 2? #移動到第3個參數(shù),詳情見下面調試。??? result=$(/usr/bin/my_print_defaults "$@" | sed -n "s/^--${option}=//p" | tail -n 1)??? if [ -z "$result" ]; then??????? # not found, use default??????? result="${default}"??? fi}?get_mysql_option datadir "/var/lib/mysql" mysqlddatadir="$result"get_mysql_option socket "$datadir/mysql.sock" mysqldsocketfile="$result"get_mysql_option log-error "/var/log/mysqld.log" mysqld mysqld_safeerrlogfile="$result"get_mysql_option pid-file "/var/run/mysqld/mysqld.pid" mysqld mysqld_safemypidfile="$result"?
如果你對shell很熟,那么可以忽略下面步驟,如果不熟悉,那么我們可以手工調試一下(# sh -x mysqld),看看它是如何獲取相關變量的值的呢?
?
?
?
?
[root@gettestlnx02 ~]# file /usr/bin/my_print_defaults/usr/bin/my_print_defaults: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped[root@gettestlnx02 ~]# /usr/bin/my_print_defaults mysqld[root@gettestlnx02 ~]#?
?
如上所示,因為/usr/bin/my_print_defaults mysqld輸出為空,所以result為空值, 所以result被授予${default}的值,而defualt=$2,其實就是第二個變量,如下所示,第二個變量被標記為紅色。
?
get_mysql_option datadir "/var/lib/mysql" mysqld
datadir="$result"
?
?
?
另外,my.cnf的位置是會影響腳本輸出結果的。如下所示:(不在幾個默認路徑的話,my_print_defaults是沒有輸出結果的)
?
[root@gettestlnx02 ~]# ls /tmp/my.cnf/tmp/my.cnf[root@gettestlnx02 ~]# /usr/bin/my_print_defaults mysqld[root@gettestlnx02 ~]# mv /tmp/my.cnf? /etc/my.cnf[root@gettestlnx02 ~]# /usr/bin/my_print_defaults mysqld--datadir=/var/lib/mysql--socket=/var/lib/mysql/mysql.sock--symbolic-links=0--log-error=/var/log/mysqld.log--pid-file=/var/run/mysqld/mysqld.pid?
?
?
?
?
接下來,我們將配置文件my.cnf挪回原位(/etc/my.cnf),然后更改數(shù)據(jù)庫數(shù)據(jù)存儲目錄(從/var/lib/mysql挪動到/data/mysqldata/mysql 步驟從略),然后我們再做下面測試:
?
?
[root@gettestlnx02 ~]# service mysqld stopStopping mysqld:? [? OK? ][root@gettestlnx02 ~]# mv /etc/my.cnf? /tmp/my.cnf[root@gettestlnx02 ~]# service mysqld startInitializing MySQL database:? 2018-03-16T01:26:19.589182Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).2018-03-16T01:26:20.034494Z 0 [Warning] InnoDB: New log files created, LSN=457902018-03-16T01:26:20.132219Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.2018-03-16T01:26:20.193504Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 07ee8c42-28b9-11e8-a04a-005056b3ebdf.2018-03-16T01:26:20.208662Z 0 [Warning] Gtid table is not ready to be used. Table 'mysql.gtid_executed' cannot be opened.2018-03-16T01:26:20.209919Z 1 [Note] A temporary password is generated for root@localhost: O;kZmIj+.6jf[? OK? ]Logging to '/var/lib/mysql/gettestlnx02.err'.Starting mysqld:? [? OK? ]?
?
?
MySQL服務居然也啟動了,它初始化了數(shù)據(jù)庫,數(shù)據(jù)文件位于/var/lib/mysql。這個確實讓我吃了一驚,原本預測,如果更改數(shù)據(jù)庫數(shù)據(jù)存儲目錄,MySQL又沒有my.cnf配置文件,MySQL服務應該啟動不了。當然這個啟動也沒有什么意義,因為你的數(shù)據(jù)和一些賬號權限配置都沒有了(有點類似于SQL Server里面的重建系統(tǒng)數(shù)據(jù)庫)
?
[root@gettestlnx02 mysql]# cd /var/lib/mysql[root@gettestlnx02 mysql]# ls -lrttotal 122948-rw-r-----. 1 mysql mysql 50331648 Mar 16 09:26 ib_logfile1-rw-r-----. 1 mysql mysql?????? 56 Mar 16 09:26 auto.cnfdrwxr-x---. 2 mysql mysql???? 4096 Mar 16 09:26 performance_schemadrwxr-x---. 2 mysql mysql???? 4096 Mar 16 09:26 mysqldrwxr-x---. 2 mysql mysql??? 12288 Mar 16 09:26 sys-rw-r-----. 1 mysql mysql????? 420 Mar 16 09:26 ib_buffer_pool-rw-------. 1 mysql mysql???? 1679 Mar 16 09:26 ca-key.pem-rw-r--r--. 1 mysql mysql???? 1107 Mar 16 09:26 ca.pem-rw-------. 1 mysql mysql???? 1675 Mar 16 09:26 server-key.pem-rw-r--r--. 1 mysql mysql???? 1107 Mar 16 09:26 server-cert.pem-rw-------. 1 mysql mysql???? 1675 Mar 16 09:26 client-key.pem-rw-r--r--. 1 mysql mysql???? 1107 Mar 16 09:26 client-cert.pem-rw-------. 1 mysql mysql???? 1675 Mar 16 09:26 private_key.pem-rw-r--r--. 1 mysql mysql????? 451 Mar 16 09:26 public_key.pem-rw-------. 1 mysql mysql??????? 6 Mar 16 09:26 mysql.sock.locksrwxrwxrwx. 1 mysql mysql??????? 0 Mar 16 09:26 mysql.sock-rw-r-----. 1 mysql mysql 12582912 Mar 16 09:26 ibtmp1-rw-r-----. 1 mysql mysql 12582912 Mar 16 09:26 ibdata1-rw-r-----. 1 mysql mysql 50331648 Mar 16 09:26 ib_logfile0-rw-r-----. 1 mysql mysql???? 3277 Mar 16 09:27 gettestlnx02.err[root@gettestlnx02 mysql]#?
測試、折騰過程發(fā)現(xiàn)并不是所有情況下都會成功初始化數(shù)據(jù)庫,如果當/var/lib/mysql下存在一些文件時,初始化會報錯“initialize specified but the data directory has files in it. Aborting.”此時,只要你清空
/var/lib/mysql下文件,就能成功初始化。
?
[root@gettestlnx02 ~]# service mysqld stop
[root@gettestlnx02 ~]# mv /etc/my.cnf? /tmp/my.cnf
[root@gettestlnx02 ~]# service mysqld start
Initializing MySQL database:? 2018-03-16T03:49:45.190114Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2018-03-16T03:49:45.192215Z 0 [ERROR] --initialize specified but the data directory has files in it. Aborting.
2018-03-16T03:49:45.192246Z 0 [ERROR] Aborting
?
[FAILED]
[root@gettestlnx02 ~]#
?
?
?
其實只要稍微花費一點心思,查看一下/etc/init.d/mysqld的代碼,就會發(fā)現(xiàn)start函數(shù)里面在條件滿足的情況就會初始化數(shù)據(jù)庫。
?
start(){??? [ -x $exec ] || exit 5??? # check to see if it's already running??? RESPONSE=$(/usr/bin/mysqladmin --no-defaults --socket="$adminsocket" --user=UNKNOWN_MYSQL_USER ping 2>&1)??? if [ $? = 0 ]; then??????? # already running, do nothing??????? action $"Starting $prog: " /bin/true??????? ret=0??? elif echo "$RESPONSE" | grep -q "Access denied for user"??? then??????? # already running, do nothing??????? action $"Starting $prog: " /bin/true??????? ret=0??? else??????? # prepare for start??????? if [ ! -e "$errlogfile" -a ! -h "$errlogfile" -a "x$(dirname "$errlogfile")" = "x/var/log" ]; then??????????? install /dev/null -m0640 -omysql -gmysql "$errlogfile"??????? fi??????? [ -x /sbin/restorecon ] && /sbin/restorecon "$errlogfile"??????? if [ ! -d "$datadir/mysql" ] ; then??????????? # First, make sure $datadir is there with correct permissions??????????? if [ ! -d "$datadir" -a ! -h "$datadir" -a "x$(dirname "$datadir")" = "x/var/lib" ]; then??????????????? install -d -m0751 -omysql -gmysql "$datadir" || exit 1??????????? fi??????????? if [ ! -h "$datadir" -a "x$(dirname "$datadir")" = "x/var/lib" ]; then??????????????? chown mysql:mysql "$datadir"??????????????? chmod 0751 "$datadir"??????????? fi??????????? if [ -x /sbin/restorecon ]; then??????????????? /sbin/restorecon "$datadir"??????????????? for dir in /var/lib/mysql-files /var/lib/mysql-keyring ; do??????????????????? if [ -x /usr/sbin/semanage -a -d /var/lib/mysql -a -d $dir ] ; then??????????????????????? /usr/sbin/semanage fcontext -a -e /var/lib/mysql $dir >/dev/null 2>&1??????????????????????? /sbin/restorecon -r $dir??????????????????? fi??????????????? done??????????? fi??????????? # Now create the database??????????? initfile="$(install_validate_password_sql_file)"??????????? action $"Initializing MySQL database: " /usr/sbin/mysqld --initialize --datadir="$datadir" --user=mysql --init-file="$initfile"??????????? ret=$???????????? rm -f "$initfile"??????????? [ $ret -ne 0 ] && return $ret??????????? # Generate certs if needed??????????? if [ -x /usr/bin/mysql_ssl_rsa_setup -a ! -e "${datadir}/server-key.pem" ] ; then??????????????? /usr/bin/mysql_ssl_rsa_setup --datadir="$datadir" --uid=mysql >/dev/null 2>&1??????????? fi?
?
另外,在多實例情況下,多實例有兩種方案:
?
1、基于mysqld_multi:?多個實例共用同一個my.cnf配置文件中,利用[mysqld1]、[mysqld2]、[mysqld*]標簽實現(xiàn)不同實例的差異化配置;
?
2、基于多配置文件:每一個實例單獨一個my.cnf配置文件
?
?
多實例啟動時都會指定對應的my.cnf,所以雖然這里沒有詳細測試,其實大致的原理也跟單實例是差不多的。當你有疑問或不解的時候,動手實踐是檢驗真理的唯一標準。
?
?
?
?
總結
以上是生活随笔為你收集整理的MySQL服务读取参数文件my.cnf的规律研究探索的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: React开发(230):ant des
- 下一篇: Exchange Server 2016