MySQL開啟的檔案描述符限制

2021-07-03 21:11:03 字數 4156 閱讀 3194

mysql開啟的檔案描述符限制

2010-10-21  |  23:19分類:

mysql,

**細節  |  

如果遇到如下錯誤:

can't open file: '.\test\mytable.frm' (errno: 24)

shell> perror 24

os error code 24: too many open files

這就是mysql的檔案描述不夠用了。先說解決辦法,再說背後的原因吧。

1. 如何解決

檔案/etc/security/limits.conf新增如下行:

mysql soft nofile 65535

mysql hard nofile 65535

上面的配置,是os限制各個使用者能夠開啟的檔案描述符限制(hard soft區別參看man ulimit),新增上面兩行,表示mysql使用者能夠開啟65535個檔案描述符(可以使用lsof -u mysql|wc -l檢視當前開啟了多少個檔案描述符)。

第二步:修改mysql引數:

在mysql配置檔案my.cnf中新增下面的行

open_files_limit = 65535

innodb_open_files=65535

然後重啟你的mysql一般問題就解決了。

2. 背後的問題

上面的辦法一般就能解決問題了。不過在實踐中發現,在my.cnf中設定的引數open_files_limit值是無效的,即mysql啟動後open_files_limit始終以os的檔案描述符為準。(版本mysql5.1.45 rhel5.4)

root@(none) 11:27:07>show global variables like "%open_files_limit%";

+------------------+-------+

| variable_name | value |

+------------------+-------+

| open_files_limit | 20000 |

+------------------+-------+

1 row in set (0.01 sec)

root@(none) 11:27:09>system ulimit -n

20000

那my.cnf引數open_files_limit是否真的是沒用呢?接下來會是一篇很長、很蛋疼的關於該問題的研究,如果不是很有時間,不建議看下去。

3. 源**中如何設定open_files_limit

3.1 實驗驗證

配置檔案中配置:open_files_limit = 10000;$ulimit -n 20000;啟動資料庫,觀察:

root@(none) 11:48:57>show global variables like "%open_files_limit%";

+------------------+-------+

| variable_name | value |

+------------------+-------+

| open_files_limit | 20000 |

+------------------+-------+

看到引數open_files_limit確實沒有作用(已經實驗了很多次了)。

3.1 **追蹤watch

首先使用gdb/watch觀察open_files_limit變數值,

old value = 0

new value = 10000

0x000000000086a6f2 in setval ()

old value = 10000

new value = 20000

0x00000000005ba159 in init_common_variables ()

看到,配置檔案my.cnf中的10000,又沒有生效。

3.2 夢境:更多的**細節

wanted_files= 10+max_connections+table_cache_size*2;

max_open_files= max(max(wanted_files, max_connections*5),

open_files_limit);

files= my_set_max_open_files(max_open_files);

這一段可以看到,首先會比較open_files_limit,max_connections*5和10+max_connections+table_cache_size*2中最大值,並呼叫函式my_set_max_open_files設定檔案描述符限制。

繼續跟蹤函式my_set_max_open_files,在檔案mysys/my_file.c中:

uint my_set_max_open_files(uint files)

} dbug_print("exit",("max_file_limit: %u", max_file_limit));

dbug_return(max_file_limit);

}

上面的**中:

if (rlimit.rlim_cur >= max_file_limit)

dbug_return(rlimit.rlim_cur); /* purecov: inspected */

看到,如果當前的os檔案描述符(rlimit.rlim_cur)限制大於配置檔案的引數max_file_limit,則函式返回不再對使用描述符做任何限制。

所以,當配置檔案設定的open_files_limit值小於os檔案描述符限制時,將不會呼叫setrlimit,即檔案描述符限制是os的限制值。

這裡**還可以看到,如果open_files_limit的值大於os檔案描述符限制時,將會嘗試呼叫setrlimit(rlimit_nofile, &rlimit)將描述符設定open_files_limit,事實上,setrlimit會呼叫失敗。

所以,當配置檔案設定的open_files_limit值大於os檔案描述符限制時,會呼叫setrlimit,但是會失敗,即檔案描述符限制仍然是os的限制值。

即,無論如何,mysql開啟的檔案描述符限制都是os的檔案描述符限制,和配置檔案中open_files_limit的設定沒有關係。

(如果看到這,說明你已經成功進入第二層夢境了:my_set_max_open_files和set_max_open_files)

4 **外的**

估計看到這,看客已經暈了吧。因為這個問題並沒有那麼重要,解決辦法也很簡單,所以確實也不用追究的這麼細。不過都到這兒了,我打算繼續。

在如果想設定open-files-limit也有成功的時候,那就是使用root帳號,執行mysqld_safe指令碼啟動mysql(或者使用mysql.server啟動),如果使用--open-files-limit是可以成功設定的:

./mysqld_safe --open-files-limit=25000 &

root@(none) 02:50:54>show variables like "%open_files_limit%";

+------------------+-------+

| variable_name | value |

+------------------+-------+

| open_files_limit | 25000 |

+------------------+-------+

這是因為在mysqld_safe中做了如下處理:

if test -w / -o "$user" = "root"

then

......

if test -n "$open_files"

then

ulimit -n $open_files

fi

fi

可以看到,直接或間接使用mysqld_safe啟動mysql時,其實是在啟動mysqld程式之前,呼叫了ulimit -n $open_files來實現檔案描述符的限制。

參考:1. mysql source code

2. mysql如何計算開啟檔案數

3. mysql manual

MySQL開啟的檔案描述符限制

如果遇到如下錯誤 can t open file test mytable.frm errno 24 shell perror 24 os error code 24 too many open files 這就是mysql的檔案描述不夠用了。先說解決辦法,再說背後的原因吧。1.如何解決 檔案 et...

mysql中的開啟的檔案描述符限制

can t open file test mytable.frm errno 24 shell perror 24 os error code 24 too many open files 這樣的錯誤的話,應該是mysql的檔案描述符不夠了,解決的方法為,增加操作 系統的描述符號 在檔案 etc s...

mysql 檔案描述符 檔案描述符

toc 首先,linux的世界裡一切皆為檔案,無論是裝置還是乙個socket連線。檔案又可分為 普通檔案 目錄檔案 鏈結檔案和裝置檔案。檔案描述符 file descriptor 是核心為了高效管理已被開啟的檔案所建立的索引,其是乙個非負整數 通常是小整數 用於指代被開啟的檔案,所有執行i o操作的...