(Errcode: 24 - Too many open files)

Unifex

New Member
Heute hat es eine Tabelle zerrissen in eine Datenbank.
Ich konnte sie wieder herstellen aber nun möchte ich dem Problem auf den Grund gehen.

Die erste beiden Fehlermeldungen, die dem Crash voraus gingen, lauteten so:

Code:
Zend_Db_Adapter_Mysqli_Exception: Can't read dir of './neu@002dxxxx/' (errno: 24 - Too many open files) - library/Zend/Db/Adapter/Mysqli.php:144

Zend_Db_Statement_Mysqli_Exception: Mysqli prepare error: Out of resources when opening file './neu@002dxxxx/xf_search_index.MYD' (Errcode: 24 - Too many open files) - library/Zend/Db/Statement/Mysqli.php:77

Ich kann damit wenig anfangen. Kann mir da bitte jemand helfen?
 
Ist das ein Vserver?
Wenn ja:
Mit welcher Virtualisierung?

Die meisten Virtualisierungen haben bestimmte Resourcengrenzen. Eben auch die maximal gleichzeitig geöffneten Dateien. Je nach Virtualisierung kann man das mit einem Befehl nachsehen. Wahrscheinlich hat der Server nur zu wenig Resourcen.
 
Vielleicht sind dem System Dateideskriptoren ausgegangen.

Was zeigen denn in der Shell:
ulimit -Hn
ulimit -Sn
ulimit -a


Und in der MySQL-Konfiguration ist vielleicht open_files_limit auf einen Wert gesetzt.
 
Sorry, hätte dazu schreiben sollen, dass es ein Root Server 32 Gb Ram ist.

Mysql 5.6.19

Nun zu den Werten:

Nicht vorhanden ist der Eintrag open_files_limit in der my.cnf

Stattdessen habe ich dort folgenden Wert:
innodb_open_files = 8192

Die Datenbank besteht eigentlich nur aus innodb Tabellen aber die gecrashte Tabelle ist die einzige myisam Tabelle.

Braucht die vielleicht einen extra Eintrag in der my.cnf?


ulimit -Hn
4096

ulimit -Sn
1024

Code:
ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 257373
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 257373
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
 
Vielen Dank erst mal für die Antwort. Ich hab einige interessante Daten gesammelt, die ich hier mit anhänge.

Zunächst das hier:

Code:
cat /proc/$(pgrep 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             257373               257373               processes
Max open files            1024                 4096                 files
Max locked memory         65536                65536                bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       257373               257373               signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us

Im Anhang findest du eine Auswertung zu der momentanen Auswertung was die open Files im laufenden MySql Server betrifft.

Es sieht für mich so aus, als wenn der SQL Server tatsächlich die Werte vom Debian automatisch übernimmt was das open File Limit angeht.
 

Attachments

  • open-files-2.JPG
    open-files-2.JPG
    45.6 KB · Views: 311
Stellts sich immer noch die Frage warum die PHP-Anwendung die Tabelle zermurkst hat. Da ist wohl auch keine Transaction in dem Programm. Und MyISAM hat keien Transactions.

Von derzeit 16 auf das Hardlimit von 4096 zu kommen, muss wohl einiges im Argen sein.

Musst du für die einzige Tabelle MyISAM nutzen?
 
Last edited by a moderator:
Von derzeit 16 auf das Hardlimit von 4096 zu kommen, muss wohl einiges im Argen sein.

Musst du für die einzige Tabelle MyISAM nutzen?

Leider ja, denn die Tabelle hat den Suchindex der Anwendung.
Ich kann was das angeht aber demnächst auf eine andere Anwendung ausweichen (elasticsearch).

Zu dem Zeitpunkt des Crashes habe ich gerade auch an dem SQL Server gearbeitet. Also alte Datenbanken gelöscht und auch eine neue Erstellt und ein Restore angeschmissen.

Es war also deutlich mehr los auf dem Datenbankserver aber nicht direkt in der Datenbank.

Aber was solls. Der Server hat noch massig Resourcen frei.

Vielleicht sollte ich wirklich mal versuchen die Limits in der Datei /etc/security/limits.conf hochzusetzen.

Dein Link schlägt da folgendes vor:
Code:
* soft nofile 1024000
* hard nofile 1024000
* soft nproc 10240
* hard nproc 10240

Ich habe da wenig Erfahrung aber das scheint mir doch reichlich zu sein oder?
 
Da die Anwendung, welche die Datenbank/Tabelle bedient/nutzt, nicht sonderlich robust programmiert scheint, kann dir das theoretisch wieder passieren, dass die Dateihandles ausgehen oder die Tabelle geschrottet wird.


Du kannst das limit so höher setzen.
Musst du halt in der Praxis testen.
 
Komisch, irgendwie scheint das mit den Eintragungen in der Limits.conf nicht übernommen zu werden.

Der Inhalt der Datei sieht jetzt so aus:

HTML:
# /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain>        <type>  <item>  <value>
#
#Where:
#<domain> can be:
#        - an user name
#        - a group name, with @group syntax
#        - the wildcard *, for default entry
#        - the wildcard %, can be also used with %group syntax,
#                 for maxlogin limit
#        - NOTE: group and wildcard limits are not applied to root.
#          To apply a limit to the root user, <domain> must be
#          the literal username root.
#
#<type> can have the two values:
#        - "soft" for enforcing the soft limits
#        - "hard" for enforcing hard limits
#
#<item> can be one of the following:
#        - core - limits the core file size (KB)
#        - data - max data size (KB)
#        - fsize - maximum filesize (KB)
#        - memlock - max locked-in-memory address space (KB)
#        - nofile - max number of open files
#        - rss - max resident set size (KB)
#        - stack - max stack size (KB)
#        - cpu - max CPU time (MIN)
#        - nproc - max number of processes
#        - as - address space limit (KB)
#        - maxlogins - max number of logins for this user
#        - maxsyslogins - max number of logins on the system
#        - priority - the priority to run user process with
#        - locks - max number of file locks the user can hold
#        - sigpending - max number of pending signals
#        - msgqueue - max memory used by POSIX message queues (bytes)
#        - nice - max nice priority allowed to raise to values: [-20, 19]
#        - rtprio - max realtime priority
#        - chroot - change root to directory (Debian-specific)
#
#<domain>      <type>  <item>         <value>
#

#*               soft    core            0
#root            hard    core            100000
#*               hard    rss             10000
#@student        hard    nproc           20
#@faculty        soft    nproc           20
#@faculty        hard    nproc           50
#ftp             hard    nproc           0
#ftp             -       chroot          /ftp
#@student        -       maxlogins       4

* soft nofile 102400
* hard nofile 102400
* soft nproc 10240
* hard nproc 10240



# End of file

Ich habe die Änderungen gemacht und mich ein zweites mal dann am Server angemeldet.

ulimit -a gibt die selben Werte aus wie vor der Änderung. Wo liegt der Fehler?
 
Hat irgendjemand eine Idee? Laut Doku wird nur ein neues Einloggen und kein Reboot des Servers verlangt, damit die neuen Werte aktiv sein sollen.
 
ulimit setzt ja die Werte für den jeweiligen Nutzer.
Du hast auch mit su auf den User geschaltet, der MySQL laufen lässt?
Ist MySQL neu gestartet?

Was zeigt das systemweite limit mit sysctl -a | grep fs.file
 
Mit ulimit sind die Werte ja überhaupt nicht gesetzt worden sondern sie sind in der limits.conf eingetragen mit dem Sternchen.

Eigentlich genauso, wie in deinem Link vorgeschlagen.

Den MySQL Server zu starten würde ja nichts bringen nach meiner Meinung da ulimit ja noch die selbern Werte anzeigt.

Was wäre eigentlich, wen ich in die my.cnf folgenden Wert eintrage:

Code:
[mysqld]
open_files_limit = 102400

Würden die open file Limits Werte dann höher im mysql sein, als es die Werte des Betriebssystems her geben?

Verstehst du was ich meine?
 
Bis hier mal jemand erläutert hat, was der MySQLd mit dem pam_limits PAM-Modul zu tun hat, legst Du erstmal ein Backup Deiner my.cnf und der Datenbanken an. Danach ersetzt beziehungsweise fügst Du folgende Optionen im Abschnitt [mysqld] der my.cnf hinzu:
Code:
key_buffer_size                 = 256M
join_buffer_size                = 128K
sort_buffer_size                = 2M
read_buffer_size                = 128K
read_rnd_buffer_size            = 256K
bulk_insert_buffer_size         = 8M
myisam_sort_buffer_size         = 8M
max_allowed_packet              = 64M
max_heap_table_size             = 64M
tmp_table_size                  = 64M
thread_stack                    = 192K
table_open_cache                = 8192
table_definition_cache          = 8192
open_files_limit                = 32768
query_cache_type                = 1
query_cache_size                = 64M
query_cache_limit               = 2M
query_cache_min_res_unit        = 4K
innodb_log_files_in_group       = 2
innodb_flush_log_at_trx_commit  = 2
innodb_max_dirty_pages_pct      = 90
innodb_file_per_table           = 1
innodb_purge_threads            = 1
innodb_strict_mode              = 1
innodb_old_blocks_time          = 1000
innodb_stats_on_metadata        = 0
innodb_write_io_threads         = 8
innodb_read_io_threads          = 8
innodb_io_capacity              = 200
innodb_open_files               = 8192
Den MySQLd bitte restarten und beobachten. Bei Fehlern bitte sofort melden, ansonsten nach 48-72 Stunden bitte die Ausgaben von mysqltuner.pl und tuning-primer.sh posten, danke.
 
Bis hier mal jemand erläutert hat, was der MySQLd mit dem pam_limits PAM-Modul zu tun hat, legst Du erstmal ein Backup Deiner my.cnf und der Datenbanken an.

Die Idee (und Frage) dahinter war ja, ob das "pam_limit" auch automatisch das open files limit bei dem mysql Server beeinflusst.

Ich habe jetzt meine my.cnf mit dem Wert "open_files_limit = 32768" erweitert und siehe da.... wenn ich mir die Parameter der Datenbank im phpmyadmin anschaue, dann wird da immer noch open files limit mit 1024 ausgegeben.

Meine cnf sieht momentan so aus:

Code:
[client]
port		= 3306
socket		= /var/run/mysqld/mysqld.sock

[mysqld_safe]
socket		= /var/run/mysqld/mysqld.sock
nice		= 0

[mysqld]
user		= mysql
pid-file	= /var/run/mysqld/mysqld.pid
socket		= /var/run/mysqld/mysqld.sock
port		= 3306
basedir		= /usr
datadir		= /var/lib/mysql
tmpdir		= /tmp
lc-messages-dir	= /usr/share/mysql

explicit_defaults_for_timestamp

bind-address		= 127.0.0.1

default-storage-engine          = InnoDB
back_log                        = 500
sync_binlog                     = 0
binlog_cache_size               = 4M
binlog_stmt_cache_size          = 4M
max_binlog_size                 = 500M
binlog-format                   = MIXED
expire_logs_days	              = 14
slow-query-log                  = 1
slow-query-log-file             = /etc/mysql/slow-query.log
safe-user-create                = 1
delay-key-write                 = ALL
key_buffer_size                 = 2048M
max_allowed_packet	            = 64M
max_heap_table_size             = 256M
tmp_table_size                  = 256M
thread_stack		                = 192K
table_open_cache                = 16384
table_definition_cache          = 8192
query_cache_type                = 0
query_cache_size                = 0
thread_cache_size               = 150
max_connections                 = 200
ft_max_word_len                 = 20
ft_min_word_len                 = 3
long_query_time                 = 1
log-warnings                    = 2
skip-external-locking
skip-symbolic-links
innodb_thread_concurrency       = 8
innodb_buffer_pool_size         = 4G
innodb_buffer_pool_instances    = 4
innodb_use_sys_malloc           = ON
innodb_data_file_path = ibdata1:10G:autoextend
innodb_flush_method             = O_DIRECT
innodb_log_file_size            = 256M
innodb_log_buffer_size          = 16M
innodb_log_files_in_group       = 2
innodb_flush_log_at_trx_commit  = 2
innodb_max_dirty_pages_pct      = 90
innodb_file_per_table           = 1
innodb_purge_threads            = 1
innodb_strict_mode              = 1
innodb_old_blocks_time          = 1000
innodb_stats_on_metadata        = 0
innodb_write_io_threads         = 8
innodb_read_io_threads          = 8
innodb_io_capacity              = 200
innodb_open_files               = 8192

join_buffer_size                = 10M
read_rnd_buffer_size            = 6M
sort_buffer_size                = 2M
table_open_cache_instances      = 8
explicit_defaults_for_timestamp = TRUE
read_buffer_size                = 128K
open_files_limit                = 32768

myisam-recover                  = FORCE,BACKUP
query_cache_limit	= 1M
query_cache_size        = 16M
innodb_data_file_path=ibdata1:10M:autoextend

[mysqldump]
quick
quote-names
max_allowed_packet	= 64M

[mysql]
[isamchk]
key_buffer_size                 = 256M

[myisamchk]
key_buffer_size                 = 256M
!includedir /etc/mysql/conf.d/

Wo liegt das Problem?
 
Hi,

evtl. liegt es auch einfach an dem Init-Script von MySQL. Es kann sein, dass das die ulimits von Deiner Root-Shell erbt (schau also mal, was ulimit da ausgibt).

Oder verwendest Du ggf. schon upstart? In dem Fall musst Du die Datei /etc/init/mysql.conf anpassen:

Code:
# NB: Upstart scripts do not respect
# /etc/security/limits.conf, so the open-file limits
# settings need to be applied here.
limit nofile 32768 32768
limit nproc 32768 32768


Viele Grüße,

Marcel
 
Hi,

evtl. liegt es auch einfach an dem Init-Script von MySQL. Es kann sein, dass das die ulimits von Deiner Root-Shell erbt (schau also mal, was ulimit da ausgibt).

Ja, die Werte stehen ja schon hier im Thread. Die wurden ja als root abgefragt.

Oder verwendest Du ggf. schon upstart? In dem Fall musst Du die Datei /etc/init/mysql.conf anpassen:

Die Datei gibt es in dem Ordner nicht also vermute ich, es wird kein upstart verwendet.
 
Hi,

es gab da IIRC noch eine Subtilität, dass der Parameter open_files_limit nicht kleiner als das soft-limit sein darf. Probier mal, ob es funktioniert, wenn Du entweder open_files_limit auf 102400 oder alternativ das soft ulimit auf kleiner als 32768 setzt.

BTW: Was steht denn im MySQL error log?

HTH,

Marcel
 
Back
Top