mysql_connect (localhost / 127.0.0.1) slow on Windows platform - php

I am using Windows 7, Apache 2, PHP 5, MySQL 5, all are on the same machine.
I have found an interesting issue, I have the following code:
$sql = "select * from user1";
$conn = mysql_connect("localhost", "root", "xxxxxxxx");
mysql_select_db("test1");
mysql_query("set names utf8");
$result = mysql_query($sql, $conn);
while ($row = mysql_fetch_assoc($result)){
foreach ($row as $key => $value){
echo $key." => ".$value." || ";
}
echo "<br/>";
}
mysql_free_result($result);
mysql_close($conn);
The running time for the above code is over 1 second.
When I use 127.0.0.1 instead of localhost, the running time is around 10 ms.
I tried to find the underlying reason on the internet, and this is the result:
I recently moved my development from XP to Windows 7 and found that webpages I had developed were taking 5 seconds long to load. This was unacceptable of course so I had to track down the problem.
I eventually tracked down the offending function/method pdo::construct. I also found that mysql_connect was taking about 1 second to make a connection. After a little googling I found an explaination that php had issues with IPv6 and that you could fix the problem by either disabling IPv6 or switching to the ipaddress 127.0.0.1 when making your connection.
I wonder what the issue of IPv6 on PHP is, just want to get a deeper understaning. Thanks.

PHP is attempting to open a connection to localhost. Because your computer is connected to your network via IPv6 it's trying the IPv6 version of 'localhost' first, which is which is an IP address of ::1
http://en.wikipedia.org/wiki/IPv6_address#Special_addresses
::1/128 — The loopback address is a unicast localhost address. If an
application in a host sends packets to this address, the IPv6 stack
will loop these packets back on the same virtual interface
(corresponding to 127.0.0.0/8 in IPv4).
It looks like your MySQL server isn't listening to that address, instead it's only bound to an IPv4 address and so once PHP fails to open the connection it falls back and tries to open localhost via IPv4 aka 127.0.0.1
I personally prefer to use either IP addresses or use ether the Windows hosts file or Mac equivalent to define 'fake' domain names and then use those when connecting to MySQL, which resolve to IP addresses. Either way I can know exactly whether an IPv4 or IPv6 address will be used.
Both MySQL and Apache support IPv6 but you have to tell them to use an IPv6 address explicitly. For MySQL see:
http://dev.mysql.com/doc/refman/5.5/en/ipv6-server-config.html
For Apache config see:
http://httpd.apache.org/docs/2.2/bind.html
Apache supports multiple IP addresses so you can use both at once - if the network card in the machine has both an IPv4 and IPv6 address. MySQL only supports one address.

PHP is trying to connect to "localhost" in Windows 7/8/10 it is ::1, but MySQL is not listening on IPv6 sockets, you can apply several fixes:
1) In your host file (C:/windows/system32/drivers/etc/host) set localhost to 127.0.0.1
2) In PHP the MySQL server change from localhost to 127.0.0.1
3) In my.ini, add or edit: bind-address = ::
If the address is ::, the server accepts TCP/IP connections on all
server host IPv4 and IPv6 interfaces. Use this address to permit both
IPv4 and IPv6 connections on all server interfaces.
Suggested option if you have MySQL >= 5.5.3

Related

PHP imap only works with IP address, not with domain name - DNS issue?

I'm displaying a simple list of emails using the imap_* functions of PHP:
$connection = "{mail-server:993/ssl/novalidate-cert}INBOX";
$imap = imap_open($connection, 'my-login', 'my-pass');
$check = imap_check($imap);
$overview = imap_fetch_overview($imap, "1:{$check->Nmsgs}", 0);
foreach ($overview as $msg) {
echo "{$msg->msgno} ({$msg->date}), from {$msg->from}: {$msg->subject}\n";
}
imap_close($imap);
I'm connecting to the same machine. This works perfectly fine and I see the list of emails. However, at the very bottom of the page, a notice is shown:
Notice: Unknown: Can't connect to mail-server,993: Connection refused (errflg=1) in Unknown on line 0
This notice is shown when I use my domain name or localhost(!) as mail-server. When I use my IP address or 127.0.0.1, everything works fine. I got that idea from this question.
I did an nslookup for both my domain name and localhost, from the machine itself. Both return the right IP address, however, both also show that it is a 'Non-authoritative answer'.
Here's the contents of /etc/hosts:
127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
I don't understand how nslookup localhost can give 127.0.0.1 as a non-authoritative answer if it's in the hosts file.
Anyway, am I right that PHP throwing this notice is because of the DNS being non-authoritative? If so, how can I fix it? If not, how can I fix it?
I don't experience any other issues with the DNS. I can access the machine from everywhere using its domain name. Also note that PHP actually can connect when I use the domain name - it just also spits out the notice.
Also, there's no problem using thunderbird on a remote computer using the same connection.
I'm running Ubuntu 14.04, PHP 5.5.9, and Dovecot 2.2.9 for the IMAP server.
This can happen when your lookup resolves to an IPv6 address, but your server isn't configured to support IPv6. The client will first try the IPv6 address, and then the IPv4 address when that fails.
You can check if this is the case by removing localhost from the line:
::1 localhost ip6-localhost ip6-loopback
in your hosts file.
Authoritative/non-authoritative DNS queries don't make a difference here. See https://serverfault.com/q/413124/265582 for more information.
You can also let dovecot accept ipv6 connections. How to do that depends on your configuration. If you have inet_listener blocks, make sure that the address line contains ::. For example:
inet_listener {
address = *, ::
port = 143
}
inet_listener {
address = *, ::
port = 993
ssl = yes
}
If you don't have inet_listener blocks, change the listen directive to:
listen=[::]
In both cases, this will make dovecot listen on both ipv4 and ipv6 connections.

Connect to external mysql server from a specific ip

I've been searching and couldn't find an answer to this.
I have a server that holds multiple ip addresses - lets say 1.1.1.1 (as the main ip) and 1.1.1.2
I need to connect to an external mysql server that allows only 1.1.1.2 to connect to it but it tries to connect from 1.1.1.1
is there any way to "choose" what ip the server will try to connect from?
thanks
1) try check my.cnf (for bind to multiple IPs)
bind-address = 0.0.0.0
#skip-networking
2) check server firewall rules (or try disable firewall to test connection).
More information:
http://www.cyberciti.biz/faq/unix-linux-mysqld-server-bind-to-more-than-one-ip-address/
http://www.cyberciti.biz/tips/how-do-i-enable-remote-access-to-mysql-database-server.html

How should I refer to a MySQL server on a web host?

When using PHP to connect to a MySQL database on a web host, what is the best way to refer to the server?
The MySQL admin page on my web host says what the IP address of the server is, but can I use something else other than the IP number?
Eg.
$con = mysql_connect("l00.50.10.10","user","password");
if (!$con) { die('Could not connect: ' . mysql_error()); }
When I use localhost I get this output:
Could not connect: Can't connect to local MySQL server through socket
'/var/lib/mysql/mysql.sock' (2)
You can refer to the script's system with "localhost" as the host.
$con = mysql_connect("localhost", "user", "password");
However, connecting to the IP is most likely failing because you have a lowercase L where you should have a one digit (but I'm hoping the IP in the question was just an example).
Also, use mysqli or PDO instead of mysql, which is on the verge of deprecation.
You can the database server's host name, e.g. mydbbox.example.com. Using the IP address may be faster, as no DNS lookup will be necessary.
Also see this SO question.
The answer to this question depends on how your host (or their control panel) configures MySQL privileges. The privileges are IP or hostname specific, so often connecting by IP or by hostname may not have the same connection results. If in doubt, I would stick to exactly the settings they give you.
Read more: http://dev.mysql.com/doc/refman/5.0/en/account-names.html
If database host is same computer - use localhost. MySQL will connect by local socket, not tcpip (network) when you use localhost with port number or not.
Sometimes server does not support socket connections, and you will get error like this:
Could not connect: Can't connect to local MySQL server through socket ...
EDIT/CORRECTED:
If you cant connect by socket - use 127.0.0.1. It will force conncetion by tcpip.
If database server is installed on other machine - you can use IP address or domain.
IP address is better in most cases, because connection can be established even when DNS (domain name server) is not working correctly or when domain expired.
And one advice - use mysqli_ instead of mysql_ functions in new application. New functions are very similar in use, but more secure.
Old mysql_ functions are obsolete and they are not recommended for new applications. They are still available in PHP, because of compatibility with old, outdated software (CMS systems, e-commerce systems etc
PHP Help says (about mysql_connect):
Use of this extension is discouraged. Instead, the MySQLi or PDO_MySQL
extension should be used.
More about connecting with localhost - info from MySQL Reference
On Unix, MySQL programs treat the host name localhost specially, in a
way that is likely different from what you expect compared to other
network-based programs. For connections to localhost, MySQL programs
attempt to connect to the local server by using a Unix socket file.
This occurs even if a --port or -P option is given to specify a port
number. To ensure that the client makes a TCP/IP connection to the
local server, use --host or -h to specify a host name value of
127.0.0.1
Note, that "--port" and "-P" options are decribed in other context than PHP, but connection mechanism works similar and localhost is "special" name, doesnt matter is this PHP, console or some other software.
Have you tried to type in google something like this?
php Could not connect: Can't connect to local MySQL server through
socket '/var/lib/mysql/mysql.sock' (2)
This depends mostly on how your host has things configured. From my experience you will use "localhost", the server's IP address or a subdomain of some sort set up by the host.
I'd start by testing "localhost" as this is the default for most shared hosting environments.
$con = mysql_connect("localhost", "username", "password");

Cannot connect to mysql with 127.0.0.1

With the following code I can connect to mysql:
mysql_connect("localhost","username","");
But if I change localhost to 127.0.0.1 I get the following error:
Can't connect to MySQL server on '127.0.0.1' (13)
Why doesn't it work with 127.0.0.1?
localhost is special cased and uses UNIX sockets instead of TCP/IP. 127.0.0.1 doesn't get that special handling.
See the documentation:
On Unix, MySQL programs treat the host name localhost specially, in a way that is likely different from what you expect compared to other network-based programs. For connections to localhost, MySQL programs attempt to connect to the local server by using a Unix socket file. This occurs even if a --port or -P option is given to specify a port number. To ensure that the client makes a TCP/IP connection to the local server, use --host or -h to specify a host name value of 127.0.0.1, or the IP address or name of the local server. You can also specify the connection protocol explicitly, even for localhost, by using the --protocol=TCP option.
If it doesn't work when you use TCP/IP then the database probably isn't listening on the network. This is generally a good thing as it enhances security (not that listening on 127.0.0.1 exposes any problems, but listening on all interfaces gives more opportunity for attacks).
If you really want to allow connections via the network, then see skip-networking.
have you got an entry in your hosts file mapping 127.0.0.7 to localhost?
Do you have more than 1 mysql servers installed/running on your system? If so, please specify the port number of the mysql server you are trying to access like 127.0.0.1:3306,127.0.0.1:8889 etc.
If you do not know whether there are any other mysql server instances running on your system also, please specify the port.
You will be able to access it when you add the privileges for 'root'#'127.0.0.1' in the "USER_PRIVILEGES" table in the "information_schema" database
You might also try disabling SELINUX

Unable to telnet to another machine

I am getting a bit desperate after hours of research:
A Windows 7 computer with a local PHP application that listens to port 12345 with a socket.
From the same Windows 7:
If I do telnet localhost 12345, the php code sees the connection.
If I do telnet 127.0.0.1 12345, the php code sees the connection.
If I do telnet <local_ip_address> 12345, the php code DOES NOT see the connection.
If I do telnet <dns_name> 12345, the php code DOES NOT see the connection.
From another machine I don't have any connection at all when I use the ip or the dns address.
Doing a telnet from another machine with the same address but on ports 80 or 21 work perfectly.
Even with the local firewall / antivirus disabled I get the same result.
I am using a standard Apple TimeCapsule as access point, but not configured specially, not sure if that can influence for ports > 1024...
Would you have any idea for me ?
Thanks !
There are really 2 options to get this behavior that I can see;
Your firewall is enabled (which you tested)
Your socket is binding to 127.0.0.1 instead of your public IP.
I'd have a look at your local binding, aka the address you give to socket_bind().
If it says "127.0.0.1", change it to 0.
telnet 12345 is trying to connect to a machine whose IP is 12345 decimal, aka 0.0.4.210 in dotted quad format. You cannot use telnet like that - the argument cannot be simply a port number. It'll be interpreted as an IP.

Categories