Я хочу подключиться к удаленному экземпляру MySQL (Google Cloud SQL), используя его адрес IPv6.
Я использую PHP PDO так:
$db = new \PDO('mysql:host=<ipv6-address>;port=3306;dbname=<database-name>',
'<username>',
'<password>'
);
Но это всегда терпит неудачу со следующим сообщением об исключении:
PDOException: SQLSTATE [HY000] [2002] Нет маршрута к хосту
Из терминала я могу без проблем подключиться к экземпляру MySQL, например так:
mysql --host=<ipv6-address> --user=<username> --<password>
Любая помощь будет по достоинству оценена.
Спасибо
В случае, если кто-то еще споткнется о той же проблеме и сэкономит 2 часа на изучении источника PHP, соединения PDO MySQL IPv6 будут работать, если вы поставите квадратные скобки вокруг адреса.
Увидеть: https://github.com/php/php-src/blob/master/main/streams/xp_socket.c#L568
например
$pdo = new PDO("mysql:host=[1234:5678::42];port=3306;dbname=foo", ...);
Читать это https://www.saotn.org/php-mysql-and-ipv6-still-slow/ дает следующую идею:
Зная, что обычно IPv6 имеет приоритет над IPv4 (который настраивается), пользователи остаются с медленно реагирующими веб-сайтами и операциями с базой данных, только потому, что в подключении к IPv6-адресу в PHP отказано, и отказ в соединении не обрабатывается должным образом, что замедляет откат к IPv4. Это займет mysql.connect_timeout секунд
Примечание: источник кажется заслуживающим доверия
Кроме того, это хорошее чтение: http://dev.mysql.com/worklog/task/?id=798
Необходимо добавить поддержку для работы MySQL через IPv6.
(«Интернет-протокол версии 6»).
Это означает:
— пользователи могут подключаться с IPv6. это частично проблема с разъемом.
— хранение информации об адресе пользователя, например, в mysql.user, может быть в формате IPv6
— предлагаемые новые типы данных CIDR и INET допускают формат IPv6, как описано в WL # 2037 «Добавить типы данных CIDR и INET»
— функции типа inet_ntoa () нуждаются в пересмотре
Попробуйте использовать это для подключения к PDO и посмотрите, работает ли он.
$dbh = new PDO('mysql:host=<ipv6-address>;port=<port>;dbname=<dbname>', <dbusername>, <dbpassword>);
В случае неудачи, вы можете лучше использовать try...catch
точно понять ошибку
<?php
try {
$dbh = new PDO('mysql:host=<ipv6-address>;port=<port>;dbname=<dbname>', <dbusername>, <dbpassword>);
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
?>