MysqlはToo many connectionsに報告して、むやみにulimitを使わないでください。どうやって正確にプロセスを修正する最大のファイル数を見てください。

20660 ワード

背景
今日はmysqlを勉強していますが、一つのケースを見ました。大体クライアントToo many connectionsです。しかし、クライアントの接続プールは、200に制限されています。二つのクライアントのjavaプロセスは、400しかないです。そして、mysqlは800の接続を配置しました。
mysqlはmy.cnfに配置されています。

[root@localhost CAD_OneKeyDeploy]# vim /etc/my.cnf

[mysqld]
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
max_connections=800
symbolic-links = 0
これはいけないですよね。最大400個の接続を作って、データベースに最大接続800個を設置しました。結果を報告します。
そしてmysqlで実行します。
SHOW VARIABLES LIKE 'max_connections'
発見結果は200ぐらいで、設定が効きましたか?
結果はmysqlでの起動ログ:
Could not increase number of max_open_files to more than mysqld (request: 65535)
Changed limits: max_connections: 214 (requested 2000)
そしてケースの中のブロガーは修正に行きました。
ulimit -HSn 65535
vim /etc/security/limits.conf

私はフォローして操作しましたが、結局、そうではないことに気づきました。
つまり、私はそのとおりにしましたが、効果はありませんでした。
ここで、私はいくつかの資料をまとめました。まず見てください。そして最後に、プロセスの最大ファイル数をどのように正しく設定するかを説明します。
プロセスの最大ファイル数は、多面的な影響を受ける:
shell登録後、手動で起動するプロセス
影響要因は以下を含む。
  • オペレーティングシステム全体の、全プロセスが開くことができるファイル数の合計(/proc/sys/fs/file-maxによって制御される)。
  • このshellユーザは、開くことができる最大のファイル数(/etc/security/limits.confによって制御される)。
  • プロセス自体の最大ファイル数制限
    自動起動プロセス
    影響要因は以下を含む。
  • オペレーティングシステム全体の、全プロセスが開くことができるファイル数の合計(/proc/sys/fs/file-maxによって制御される)。
  • systemで起動すると、systemのserviceファイルに制限ができます。
  • 知識の制限を受けて、現在知っているのは上のこれらだけで、shellは私の知っているところによると、またlogとno-log shellを分けて、よく分からないで、先に飛びます。
    実行中のリソース制限を表示します。
    一度修正した後、修正が有効かどうかを知りたい場合は、次のような方法で変更できます。
    まずプロセスを実行して、最終的に有効になる資源制限を確認する方法は以下の通りです。
    [root@localhost ~]# cat /proc/6660/limits 
    Limit                     Soft Limit           Hard Limit           Units     
    Max cpu time              unlimited            unlimited            seconds   
    Max file size             unlimited            unlimited            bytes     
    Max data size             unlimited            unlimited            bytes     
    Max stack size            8388608              unlimited            bytes     
    Max core file size        0                    unlimited            bytes     
    Max resident set          unlimited            unlimited            bytes     
    Max processes             3795                 3795                 processes 
    -----------------------------  
    Max open files            5000                 5000                 files     
    Max locked memory         65536                65536                bytes     
    Max address space         unlimited            unlimited            bytes     
    Max file locks            unlimited            unlimited            locks     
    Max pending signals       3795                 3795                 signals   
    Max msgqueue size         819200               819200               bytes     
    Max nice priority         0                    0                    
    Max realtime priority     0                    0                    
    Max realtime timeout      unlimited            unlimited            us        
    
    OSレベルは、どのように表示し、設定しますか?
    表示は以下のコマンドによりできます。
    [root@localhost ~]# cat  /proc/sys/fs/file-max
    95086
    
    ここは実はプロジェクトの中のある書類を見ましたが、この書類の意味は何ですか?ヘルプを表示:
    man proc
    ...
    /proc/sys/fs/file-max
    
    This file defines a system-wide limit on the number of open files for all processes.  (See also setrlimit(2), which can be used by a process to set the per-process limit, RLIMIT_NOFILE, on the number of files  it  may open.)  If you get lots of error messages in the kernel log about running out of file handles (look for "VFS: file-max limit  reached"), try increasing this value:
    
    echo 100000 > /proc/sys/fs/file-max
    
    The kernel constant NR_OPEN imposes an upper limit on the value that may be placed in file-max.
    
    If you increase /proc/sys/fs/file-max, be sure to increase /proc/sys/fs/inode-max to 3-4 times the new value of /proc/sys/fs/file-max, or you will run out of inodes.
    
    Privileged processes (CAP_SYS_ADMIN) can override the file-max limit.
    
    簡単な翻訳の下で、このファイルはオペレーティングシステムのレベルを定義しています。最大で開くことができるファイルの数制限(すべてのプロセスに合わせて)。
    プロセスに対して、各プロセスに対して最大のオープン可能ファイル数の制限を設定します。setrlimitRLIMIT_NOFILEを見ることができます。
    変更する場合は、
    echo 100000 > /proc/sys/fs/file-max
    
    修正後、Osを再起動して有効になります。
    codingの場合、apiを呼び出して資源制限を行います。
    マンで確認できます。
    man setrlimit
    
    GETRLIMIT(2)                                                                                           Linux Programmer's Manual                                                                                           GETRLIMIT(2)
    
    NAME
           getrlimit, setrlimit, prlimit - get/set resource limits
    
    SYNOPSIS
           #include 
           #include 
    
           int getrlimit(int resource, struct rlimit *rlim);
           int setrlimit(int resource, const struct rlimit *rlim);
    
    		The getrlimit() and setrlimit() system calls get and set resource limits respectively.  		Each resource has an associated soft and hard limit, as defined by the rlimit structure:
    
               struct rlimit {
                   rlim_t rlim_cur;  /* Soft limit */
                   rlim_t rlim_max;  /* Hard limit (ceiling for rlim_cur) */
               };
    
    注意してください。これは全部現在のプロセスに対してです。つまり、c言語でプログラミングすれば、基本的には直接にこれと付き合います。
    RLIMIT_NPROC
    
    The maximum number of processes (or, more precisely on Linux, threads) that can be created for the real user ID of the calling process.  Upon encountering this limit, fork(2) fails with the error EAGAIN.
    
    私はredisのソースコードの中で、関連のアプリの呼び出しを見たことがあります。
    単一ユーザ/ユーザグループに対するリソース制限(修正後、shellを再登録した後、起動するプロセスは有効)
    表示:
    vim /etc/security/limits.conf
    
    
    変更する場合は、上記のファイルに次の2行を追加し、前のワイルドカードは、任意のユーザとグループにマッチすることを表します。
    * soft nofile 65535
    * hard nofile 65535
    
    ここで任意のユーザーの最大ファイル数を65535に変更します。
    また、私はここでelastic searchの公式サイトを見ました。それは煩わしいと覚えています。これらを直す必要があります。
    https://www.elastic.co/guide/en/elasticsearch/reference/master/setting-system-settings.html#ulimit
    その中に次のような話があります。
    On Linux systems, persistent limits can be set for a particular user by editing the /etc/security/limits.conf file. To set the maximum number of open files for the elasticsearch user to 65,535, add the following line to the limits.conf file:
    
    elasticsearch  -  nofile  65535
    
    This change will only take effect the next time the elasticsearch user opens a new session.
    
    linuxでは、あるユーザーの恒久化リソースに対して、設定/etc/security/limits.com nfを利用することができるという意味です。
    例えば、elasticsearchを設定するユーザの最大ファイル数は65535です。下のように追加する必要があります。
    elasticsearch  -  nofile  65535
    
    なお、このchangeは次のelasticsearchで新しいセッションを開く時のみ有効としています。
    上のelasticsearchの文書は本当にいいです。見てもいいです。
    ですから、これはshellレベルです。修正したら、shellに再登録します。この修正ファイルは有効になります。また、shellに登録してから、起動するプロセスが役に立ちます。
    簡単なテスト
    私たちはこの文書を修正しました。
    * soft nofile 6666
    * hard nofile 6666
    
    次いでプロセスを開始し、1235ポートを傍受する。
    [root@localhost ~]# nc -l 1235
    
    他のshellにおいて、プロセスのリソース情報を確認する。
    [root@localhost ~]#       netstat -nltp
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:1235            0.0.0.0:*               LISTEN      7015/nc             
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      6632/sshd           
    tcp6       0      0 :::3306                 :::*                    LISTEN      6670/mysqld         
    tcp6       0      0 :::1235                 :::*                    LISTEN      7015/nc             
    tcp6       0      0 :::22                   :::*                    LISTEN      6632/sshd           
    [root@localhost ~]# cat /proc/7015/limits 
    Limit                     Soft Limit           Hard Limit           Units     
    Max cpu time              unlimited            unlimited            seconds   
    Max file size             unlimited            unlimited            bytes     
    Max data size             unlimited            unlimited            bytes     
    Max stack size            8388608              unlimited            bytes     
    Max core file size        0                    unlimited            bytes     
    Max resident set          unlimited            unlimited            bytes     
    Max processes             3795                 3795                 processes 
    Max open files            65535                65535                files     
    
    ここの最後の行は、ファイルの数が65535です。
    その後、私達はshellを閉じて、再登録します。この時、新しい/etc/security/limits.confを実行します。6666に設定して、プロセスを開始します。
    [root@localhost ~]# nc -l 1236
    
    もう一つのshellでこのプロセスを確認します。
    [root@localhost ~]#       netstat -nltp
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:1236            0.0.0.0:*               LISTEN      7089/nc             
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      6632/sshd           
    tcp6       0      0 :::3306                 :::*                    LISTEN      6670/mysqld         
    tcp6       0      0 :::1236                 :::*                    LISTEN      7089/nc             
    tcp6       0      0 :::22                   :::*                    LISTEN      6632/sshd           
    [root@localhost ~]# cat /proc/7089/limits 
    Limit                     Soft Limit           Hard Limit           Units     
    Max cpu time              unlimited            unlimited            seconds   
    Max file size             unlimited            unlimited            bytes     
    Max data size             unlimited            unlimited            bytes     
    Max stack size            8388608              unlimited            bytes     
    Max core file size        0                    unlimited            bytes     
    Max resident set          unlimited            unlimited            bytes     
    Max processes             3795                 3795                 processes 
    Max open files            6666                 6666                 files  
    
    6666になりました。
    まとめてみますと、この方式はファイルを修正した後、shellを再起動してから有効になります。また、shellで起動するプロセスが有効になります。
    ulimit方式(推奨しない)
    なお、この方式は現在のshellのみ有効であり、修正後に起動するプロセスのみ有効である。
    例えば、ここでshell 1の下で、修正します。
    [root@localhost ~]# ulimit -HSn 9999
    [root@localhost ~]# nc -l 1234
    
    そしてプロセスを開始し、1234ポートを傍受した。
    そして、このプロセスのリソース情報を見ます。
    [root@localhost ~]#       netstat -nltp
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:1234            0.0.0.0:*               LISTEN      6982/nc             
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      6632/sshd           
    tcp6       0      0 :::3306                 :::*                    LISTEN      6670/mysqld         
    tcp6       0      0 :::1234                 :::*                    LISTEN      6982/nc             
    tcp6       0      0 :::22                   :::*                    LISTEN      6632/sshd           
    [root@localhost ~]# cat /proc/6982/limits 
    Limit                     Soft Limit           Hard Limit           Units     
    Max cpu time              unlimited            unlimited            seconds   
    Max file size             unlimited            unlimited            bytes     
    Max data size             unlimited            unlimited            bytes     
    Max stack size            8388608              unlimited            bytes     
    Max core file size        0                    unlimited            bytes     
    Max resident set          unlimited            unlimited            bytes     
    Max processes             3795                 3795                 processes 
    Max open files            9999                 9999                 files     
    
    そして、私はshellを閉じて、shellを再登録して入ってきたら、実行します。
    [root@localhost ~]# nc -l 1234
    
    また確認します。
    [root@localhost ~]#       netstat -nltp
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:1234            0.0.0.0:*               LISTEN      7007/nc             
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      6632/sshd           
    tcp6       0      0 :::3306                 :::*                    LISTEN      6670/mysqld         
    tcp6       0      0 :::1234                 :::*                    LISTEN      7007/nc             
    tcp6       0      0 :::22                   :::*                    LISTEN      6632/sshd           
    
    [root@localhost ~]# cat /proc/7007/limits 
    Limit                     Soft Limit           Hard Limit           Units     
    Max cpu time              unlimited            unlimited            seconds   
    Max file size             unlimited            unlimited            bytes     
    Max data size             unlimited            unlimited            bytes     
    Max stack size            8388608              unlimited            bytes     
    Max core file size        0                    unlimited            bytes     
    Max resident set          unlimited            unlimited            bytes     
    Max processes             3795                 3795                 processes 
    --------------------------- 1
    Max open files            65535                65535                files     
    Max locked memory         65536                65536                bytes     
    Max address space         unlimited            unlimited            bytes     
    
    なお、ここ1箇所の表示は、すでに65535になっています。
    この制限は、この値を設定してから起動するプロセスが有効です。また、起動してからのプロセスは、何の役にも立たないはずです。
    このような方法は提案しません。
    
    ulimit [-HSTabcdefilmnpqrstuvx [limit]]
    
    Provides  control over the resources available to the shell and to processes started by it, on systems that allow such control. 
    
    
    
    長く有効にするなら、このようにすることができます。
    echo ulimit -SHn 65535 >> /etc/profile
    
    
    しかし、これはshellによって起動されるプロセスだけに対してです。例えば起動したもの、たとえばmysqlはこれで制御できないはずです。
    mysqlがsystemd方式で起動した時、どのように正しく修正しますか?
    こちらのmysqlは、rpmを使ってインストールしています。インストールする時は、次のコマンドを使いました。
        sed -i '/\# End of file/i * soft nofile 65535' /etc/security/limits.conf
        sed -i '/\# End of file/i * hard nofile 65535' /etc/security/limits.conf
        echo ulimit -SHn 65535 >> /etc/profile
        source /etc/profile
    
    また、その設定ファイルを変更しました。
    /etc/my.cnf
    
    [root@localhost CAD_OneKeyDeploy]# vim /etc/my.cnf
    
    [mysqld]
    datadir = /var/lib/mysql
    socket = /var/lib/mysql/mysql.sock
    max_connections=10000
    symbolic-links = 0
    
    例えばここのmax_connections=10000。
    しかし、起動して再起動したら、使用:
    [root@localhost CAD_OneKeyDeploy]# cat /proc/6677/limits 
    Limit                     Soft Limit           Hard Limit           Units     
    Max cpu time              unlimited            unlimited            seconds   
    Max file size             unlimited            unlimited            bytes     
    Max data size             unlimited            unlimited            bytes     
    Max stack size            8388608              unlimited            bytes     
    Max core file size        0                    unlimited            bytes     
    Max resident set          unlimited            unlimited            bytes     
    Max processes             3795                 3795                 processes 
    // 1------------------
    Max open files            5000                 5000                 files     
    Max locked memory         65536                65536                bytes     
    
    上の1箇所で、最大で開くファイルは5000です。なぜですか?説明は効果がないですね。
    なぜですか?探してみたら、私達のmysqlはsystemd方式で起動しています。
    [root@localhost CAD_OneKeyDeploy]#  systemctl status mysqld
    ● mysqld.service - MySQL Server
       // 1
       Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
       Active: active (running) since Sat 2020-07-18 10:58:07 CST; 44min ago
         Docs: man:mysqld(8)
               http://dev.mysql.com/doc/refman/en/using-systemd.html
      Process: 6674 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS (code=exited, status=0/SUCCESS)
      Process: 6636 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)
     Main PID: 6677 (mysqld)
       CGroup: /system.slice/mysqld.service
               └─6677 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid
    
    Jul 18 10:58:05 localhost.localdomain systemd[1]: Starting MySQL Server...
    Jul 18 10:58:07 localhost.localdomain systemd[1]: Started MySQL Server.
    
    上の1箇所は、このサービスの位置を指定しています。/usr/lib/systemd/system/mysqld.service.
    このファイルを開けてみます。
    ...
    [Service]
    User=mysql
    Group=mysql
    
    Type=forking
    
    PIDFile=/var/run/mysqld/mysqld.pid
    
    # Disable service start and stop timeout logic of systemd for mysqld service.
    TimeoutSec=0
    
    # Execute pre and post scripts as root
    PermissionsStartOnly=true
    
    # Needed to create system tables
    ExecStartPre=/usr/bin/mysqld_pre_systemd
    
    # Start main service
    ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS
              
    # Use this to switch malloc implementation
    EnvironmentFile=-/etc/sysconfig/mysql
    
    # 1 Sets open_files_limit 
    LimitNOFILE = 5000
    
    
    ここの最後の行に注意してください。
    # 1 Sets open_files_limit 
    LimitNOFILE = 5000
    
    これが問題です。
    ここを10000に変えて実行します。
    systemctl daemon-reload
    
    そしてmysqlを再起動します。
    systemctl restart mysqld
    
    最大リソース制限を再表示:
    [root@localhost CAD_OneKeyDeploy]# cat /proc/`pidof mysqld`/limits
    Limit                     Soft Limit           Hard Limit           Units     
    Max cpu time              unlimited            unlimited            seconds   
    Max file size             unlimited            unlimited            bytes     
    Max data size             unlimited            unlimited            bytes     
    Max stack size            8388608              unlimited            bytes     
    Max core file size        0                    unlimited            bytes     
    Max resident set          unlimited            unlimited            bytes     
    Max processes             3795                 3795                 processes 
    Max open files            10000                10000                files     
    
    最後の一行を見て、10000に変えました。
    再起動後のテストは依然として10000です。修正が成功したと説明します。
    表示/var/log/mysql.logは次のような文字があります。
    2020-07-18T03:48:11.235058Z 0 [Warning] Changed limits: max_open_files: 10000 (requested 50000)
    
    ここでは、systemのserviceで10000に制限されていますので、ここで10000と表示されます。
    テスト
    mysqlの中で、/usr/lib/systemd/system/mysqld.serviceは10000で、/etc/security/limits.conf は6666に設定する時、最終的にどの値を使いますか?
    再起動したら、答えは10000.
    なぜですか?みんなは/etc/security/limits.conf の注釈を見ます。
    # /etc/security/limits.conf
    #
    #This file sets the resource limits for the users logged in via PAM.
    #It does not affect resource limits of the system services.
    
    このファイルは、PAMでログインしたユーザに対してリソース制限を行う。system serviceに影響しません。
    上の状況は再起動して、またテストします。
    shellでログイン後、実行:
    [root@localhost ~]# systemctl restart mysqld
    [root@localhost ~]# cat /proc/`pidof mysqld`/limits
    Limit                     Soft Limit           Hard Limit           Units     
    Max cpu time              unlimited            unlimited            seconds   
    Max file size             unlimited            unlimited            bytes     
    Max data size             unlimited            unlimited            bytes     
    Max stack size            8388608              unlimited            bytes     
    Max core file size        0                    unlimited            bytes     
    Max resident set          unlimited            unlimited            bytes     
    Max processes             3795                 3795                 processes 
    Max open files            10000                10000                files     
    
    最大ファイル数は依然として10000であり、/etc/security/limits.confの影響を受けないことが分かります。
    締め括りをつける
    osレベルの場合、必ず変更してから再起動しなければなりません。
    ulimit方式は、極端に推奨されていません。臨時修正しかできません。
    /etc/security/limits.com方式、ユーザーレベル、修正後、ユーザーはshellに再登録する必要があります。ファイルは有効になります。これから起動するプロセスが有効になります。
    システムモードの起動は起動プロセスから、対応するserviceファイルを修正するのが有効です。このように設定されているのは、/etc/security/limits.com nfの影響を受けません。
    参考:
    https://mp.weixin.qq.com/s?__biz=MjM 5 ODY 4 ODIxOA=&mid=26533232&idx=1&sn=7051 c 8 b 580 c 6 d 3 f 112527 c 847 df 381 CentOS 7におけるMySQL接続数は214個に制限される解決方法