@accountnujen

Как взаимодействовать с базой, если у тебя запущен вечный скрипт?

У меня был вопрос, касаемый, почему возникает ошибка 2006. К счастью мне удалось её воспроизвести. Она возникает после повторного получения данных из базы через длительное время.

Кратко поясняю суть скрипта: скрипт поддерживает вечное соединение с камерой и опрашивает её на новые видео, записывая путь к файлу каждого видео в БД. В случае разрыва соединения, он обращается к базе и получает информацию о последнем удачном полученном видео с камеры. В тот момент, когда соединение будет восстановлено, он должен проверить: "не появилось ли новых видео с момента возникновения ошибки, до успешного переподключения".

Если сократить, то код у меня выглядит вот так:
# ----------------------------
# PDO 
$pdo = new PDO('mysql:host=127.0.0.1;dbname=cam;charset=utf8mb4', $usr, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false]);
# ----------------------------
# Получение данных из БД 
function getDB($action, $data = false) {
	global $pdo;

	if ($action === "getlast") {
		$sql ="SELECT * FROM joblist ORDER BY id DESC LIMIT 1";
	}

	return $pdo->query($sql)->fetchAll();
}
# ----------------------------
# Цикличная функция writer
function writer($ch, $data) {
	# обрабатываем данные...
	return strlen($data);
}



# здесь у меня вечное curl подключение к камере с CURLOPT_TIMEOUT => 0 и CURLOPT_WRITEFUNCTION => 'writer'
restart:
$curl_result = curl_exec($ch);
# если возникает ошибка (свет отключился), то мы выходим из вечного цикла функции writer
if ($status === 1) {
	# меняем статус
	$status = 0;
	# получаем время возникновения ошибки
	$time_err = getDB("getlast")[0]["time"] ?? date("Y-m-d H:i:s");
}
# возвращаемся выше для переподключения к камере
goto restart; # опустим момент с goto. здесь было проще реализовать, чем for.


Вчера и симулирую отключение камеры и скрипт фиксирует время отключения, после я восстанавливаю коннект с камерой (не перезапуская скрипт). Спустя 12 часов я повторил отключение камеры и мне выдало ошибку 2006. То есть ошибка возникает, когда я через какое-то время снова пытаюсь получить данные с БД.

Я так понимаю, что когда он первый раз опрашивает БД он создаёт подключение к БД и не отключает его. В сети писали, что mysql подключение нужно разрывать, а pdo подключение достаточно обнулить. То есть вместо global $pdo; я должен выполнять условную функцию initPDO(), которая будет делать что-то типа такого:
function initPDO() {
	return new PDO('mysql:host=127.0.0.1....
}

а в самой функции получения данных из бд вместо global $pdo делать $pdo = initPDO();?
Я прав?
  • Вопрос задан
  • 194 просмотра
Решения вопроса 1
nokimaro
@nokimaro
Меня невозможно остановить, если я смогу начать.
Да, логика правильная. То есть надо переписать код так чтобы отлавливать ошибку с потерей соединения с базой, например в момент неудачного выполнения запроса, переподключаться и повторять запрос.

Если процедурный код обернуть в простейший класс то сделать всё это будет гораздо проще.
goto и global рекомендую избегать. Всё что можно сделать с ними - можно сделать и без них.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@Everything_is_bad
Удобней всего работать с базой не явно получая коннект, а через их пул, часто это самое простое решение с протуханием коннектов.
Ответ написан
@pantsarny
Можно в базу посылать пинг , с интервалом
Можно проверять успешность выполнения запроса, и если он фейлится по дисконнекту - коннект и повтор запроса
Можно коннектится при каждом запросе
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы