web-dev-qa-db-fra.com

MySQL donne une erreur "hors mémoire" lors de l'insertion d'un fichier volumineux. D'où est-ce que cette limitation de fichier est-elle découlante?

J'utilise une base de données MySQL pour stocker des fichiers.

La table que j'utilise est structurée comme suit:

+--------------+----------+------+-----+---------+-------+
| Field        | Type     | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+-------+
| AttachmentID | int(11)  | NO   | PRI | NULL    |       |
| Data         | longblob | NO   |     | NULL    |       |
+--------------+----------+------+-----+---------+-------+

La commande INSERT J'utilise est aussi simple que possible:

INSERT INTO table (AttachmentID, Data) VALUES (attachmentID, attachmentData);

Évidemment, où attachmentID est un INT, et attachmentData est un grand tableau d'octets.

Après avoir lu plusieurs guides sur la manière de stocker des fichiers dans une base de données, j'ai augmenté le max_allowed_packet Réglage du fichier de configuration sur "512m", plus que suffisant pour les fichiers que je voudrais réellement insérer.

Cela a fonctionné bien pour plusieurs fichiers de 30 Mo - 40 Mo. Cependant, maintenant que je insère des fichiers plus gros dans la plage de 90 Mo +, je reçois une exception "hors mémoire", avec un certain nombre d'octets nécessaires à la taille du fichier que j'ai essayé d'insérer.

Le serveur est un serveur virtuel, avec 4 Go alloué et rien d'autre qui fonctionne qui pourrait interférer.

Pourquoi est-ce que je reçois une erreur de mémoire de mémoire pour les fichiers plus volumineux et non plus? Où se trouve cette limitation de taille de fichier?

J'ai inclus mon fichier de configuration ci-dessous:

[client]
port        = 3306
socket      = /tmp/mysql.sock

[mysqld]
port        = 3306
socket      = /tmp/mysql.sock
skip-locking
key_buffer_size = 256M
table_open_cache = 256
sort_buffer_size = 1M
read_buffer_size = 1M
read_rnd_buffer_size = 4M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size= 16M
thread_concurrency = 8
max_allowed_packet = 512M

ft_min_Word_len=2

ignore-builtin-innodb
plugin-load=innodb=ha_innodb_plugin.so

log-bin=mysql-bin
binlog_format=mixed
server-id = 1

[mysqldump]
quick
max_allowed_packet = 16M

[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

EDIT: Je peux réussir avec succès INSERT un fichier de taille 41 586 KB, mais pas l'un des 44 119 Ko. La limite est quelque part entre eux.

6
Ben Jenkinson

Ce n'est pas la réponse en soi, mais un très bon conseil pour ce sujet:

Ne stockez pas de fichiers qui grandes dans une base de données.

Pourquoi sont-ils censés être stockés dans une DB quand même? L'accès à celui-ci via le système de fichiers est bien plus efficace de gérer et d'éviter un gonflement massif des tables. Si ces fichiers sont changés souvent (je ne sais pas si tel est le cas dans votre scénario), il existe également une charge massive sur le serveur DB. La lecture des fichiers est également plus rapide puisqu'un Serverver + System est là pour envoyer des fichiers à un client (ou ailleurs).

C'est (IMO) une meilleure pratique pour stocker simplement le chemin du fichier dans la base de données comme référence. Si vous le faites pour protéger vos fichiers, vous devez utiliser l'accès à vos fichiers .htaccess ou bloquer le fichier direct à vos fichiers via le serveur Web lui-même et utiliser un wrapper autour de ce fichier (en php, quelque chose comme ... File.php? File = myfile .pdf afin que l'ACL et d'autres cecks puissent être effectués, la lecture que vous utilisez .NET, je suis sûr qu'il y a quelque chose comme ça disponible, aussi) ou utilisez d'autres machenisms votre serveur/langue fournit.

2
DrColossos

Vous devez également vérifier votre langage d'application/programmation avant. Par exemple, si vous utilisez php, vérifiez le fichier php.ini (ou) pour upload_max_filesize and post_max_size. Définissez-les sur votre valeur souhaitée: upload_max_filesize = 100M post_max_size = 100M.

1
StanleyJohns