mysql INSERT завершается неудачно, но не выдается ошибка: max_allowed_packet: настройки показывают противоречивые результаты - PullRequest
0 голосов
/ 12 февраля 2020

Я успешно получаю данные в учетную запись клиента сервера через _POST, но не могу вставить данные в таблицу строк, которая содержит типы длинных объектов, когда данные строк превышают ~ 25 МБ. Я не вижу никаких ошибок, выдаваемых php подготовленными операторами / файлом, php файл закрывается изящно. Я проверяю, правильно ли настроен мой max_allowed_packet.

У меня нет привилегий и доступа к серверу root, я не вижу my.cnf, и я говорю с моим хостом, чтобы убедиться, что и клиент, и сервер max_allowed_packet установлен на 256M.

php раздел вставки файла:

$itemAttributes=$_POST['itemAttributes'];
$itemName=$_POST['itemName'];

if(!($stmt = $conn->prepare("INSERT INTO $itemTable (`itemName`, `itemAttributes`) VALUES (?, ?)")))
        echo "<br/>Failed to Prepare";
        else
          echo "<br/>Prepare success.";  

$stmt->execute([$itemName,$itemAttributes]);
          echo " Success executing";

$conn->connection=null;
if($conn->connection==null)
  echo "<br />Connection Closed.......";

Это проверки, которые я делаю, я пропускаю какие-либо, чтобы убедиться, что max_allowed_packet не будет переопределен в другом месте и настроен во всех размещает правильно?

Проверка настроек клиента: все эти три проверки дают мне 256 МБ max_allowed_packet:

mysql SHOW VARIABLES LIKE 'max_allowed_packet' 
mysql SHOW GLOBAL VARIABLES LIKE 'max_allowed_packet'
mysql SHOW SESSION VARIABLES LIKE 'max_allowed_packet'

Однако я успешно вошел в mysql командную строку (mysql --user userName --password databaseName), чтобы проверить max_allowed_packet, но он показывает NULL, что это значит?

mysql> select @max_allowed_packet;
+---------------------+
| @max_allowed_packet |
+---------------------+
| NULL                |
+---------------------+
1 row in set (0.00 sec)

Проверка настроек сервера: как я могу проверить сервер 'max_allowed_packet' для GLOBAL и SESSION? Я пытаюсь описать выше, заменив "mysql" на "mysqld", но я не получаю результатов и предупреждений, которые не могут относиться к размеру 'max_allowed_packet':

[useraccount@cloud ~]$ mysqld SHOW GLOBAL VARIABLES LIKE 'max_allowed_packet'
2020-02-12T07:47:33.832292Z 0 [Warning] Could not increase number of max_open_files to more than 1024 (request: 65536)
2020-02-12T07:47:33.832480Z 0 [Warning] Changed limits: max_connections: 214 (requested 256)
2020-02-12T07:47:33.832487Z 0 [Warning] Changed limits: table_open_cache: 400 (requested 2000)
2020-02-12T07:47:33.945335Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2020-02-12T07:47:33.945476Z 0 [Warning] Can't create test file /var/lib/mysql/cloud.lower-test
2020-02-12T07:47:33.945569Z 0 [Note] mysqld (mysqld 5.7.29) starting as process 75 ...
2020-02-12T07:47:33.947615Z 0 [Warning] Can't create test file /var/lib/mysql/cloud.lower-test
2020-02-12T07:47:33.947631Z 0 [Warning] Can't create test file /var/lib/mysql/cloud.lower-test
2020-02-12T07:47:33.948025Z 0 [ERROR] Could not open file '/var/log/mysqld.log' for error logging: Permission denied
2020-02-12T07:47:33.948066Z 0 [ERROR] Aborting
2020-02-12T07:47:33.948138Z 0 [Note] Binlog end
2020-02-12T07:47:33.948287Z 0 [Note] mysqld: Shutdown complete

mysqldump check: Наконец, я пытаюсь читать max_allowed_packet для mysqldump с помощью трех команд выше (т.е. mysqldump SHOW VARIABLES LIKE 'max_allowed_packet'), заменяя "mysql" на "mysqldump", но я получаю отказ в доступе. В качестве альтернативы я затем успешно захожу в mysqldump для чтения max_allowed_packet (mysqldump --user userName --password databaseName), и я получаю много мусора, прокручивающего экран, поэтому я не могу получить это значение.

1 Ответ

1 голос
/ 12 февраля 2020

Как оказалось, это не имеет ничего общего с MySQL напрямую.

Неустранимая ошибка: допустимый объем памяти 134217728 байт исчерпан (попытка выделить 32000179 байт) в /home/client/public_html/phpfile.php в строке 175

Это сообщение об ошибке PHP, в котором говорится, что ваш сценарий превысил предел памяти 128M .

Вы можете увеличить предел либо в своем конфигурационном файле, либо в своем скрипте с помощью

ini_set('memory_limit','256M');

. Вы можете использовать -1 в качестве значения, чтобы полностью отключить ограничение.

Однако вы должны избегать копирования больших объемов данных.

Следующий случай ясен:

$itemAttributes=$_POST['itemAttributes'];

Вы копируете 32M данных в новую переменную. И ваш сценарий по крайней мере сейчас на 64M.

Метод execute() с параметрами более сложен, и я не уверен, что следующее действительно верно: вы передаете новый массив как параметр

[$itemName,$itemAttributes]

Этот массив сначала должен быть создан в памяти, прежде чем он будет передан в execute(). Это снова потребляет как минимум 32 млн. Больше. Затем из-за внутренней реализации (которую я не знаю) каждый элемент массива передается во что-то вроде bindValue(), что снова копирует все данные. На данный момент ваш сценарий уже на пределе 128M (32 * 4).

Поэтому вы должны сделать что-то вроде следующего:

Удалите эти строки:

$itemAttributes=$_POST['itemAttributes'];
$itemName=$_POST['itemName'];

Подготовьте оператор:

$stmt = $conn->prepare("INSERT INTO $itemTable (`itemName`, `itemAttributes`) VALUES (?, ?)");

Привязать параметры с помощью bindParam :

$stmt->bindParam(1, $_POST['itemName'], PDO::PARAM_STR);
$stmt->bindParam(2, $_POST['itemAttributes'], PDO::PARAM_LOB);

bindParam() использует вызов по ссылке , который вы можете увидеть в описании

publi c PDOStatement :: bindParam (смешанный $ параметр, смешанный & $ variable [, int $ data_type = PDO :: PARAM_STR [, int $ length [, mixed $ driver_options]]]): bool

& в &$variable указывает, что копирование не будет выполнено, но ссылка на вместо этого передается значение.

Обратите внимание, что я обычно не являюсь другом по ссылке и избегаю его, когда не имею дело с кодом, критичным к ресурсам. execute([..]) подходит в большинстве случаев.

Если вы хотите увидеть, сколько памяти было выделено, вы можете использовать memory_get_peak_usage () где-то в конце вашего скрипта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...