小结:
1 mysql的账户名格式为 user@host,host为%时表示匹配任意主机或ip,但是localhost除外,也就是说必须为localhost显示创建账号;
2 登录mysql时若指定localhost选项则采用unix socket,而非tcp/ip协议;
以下为验证过程,
1 localhost VS % 的登录权限
先创建一个用户,其host为%,当前数据库没有localhost匿名用户
- mysql> grant select on *.* to 'test1'@'%' identified by 'test1';
- Query OK, 0 rows affected (0.00 sec)
- mysql> select host,user,password from mysql.user order by 1 desc ,2;
- +-----------------------------------------+--------------+-------------------------------------------+
- | host | user | password |
- +-----------------------------------------+--------------+-------------------------------------------+
- | localhost | root | |
- | ::1 | root | |
- | 127.0.0.1 | root | |
- | % | root | *96B86EC8D3F883B0C55D488A951E11B037E74816 |
- | % | test1 | *06C0BF5B64ECE2F648B5F048A71903906BA08E5C |
- +-----------------------------------------+--------------+-------------------------------------------+
- 11 rows in set (0.00 sec)
尝试以unix socket方式登录,均失败
- [root@mysqlslave3 ~]# /data1-new/app/services/mysql55d/bin/mysql --socket=/data1-new/app/tmp/mysql55d.sock -utest1 -ptest1
- ERROR 1045 (28000): Access denied for user 'test1'@'localhost' (using password: YES)
- [root@mysqlslave3 ~]# /data1-new/app/services/mysql55d/bin/mysql -utest1 -ptest1 --socket=/data1-new/app/tmp/mysql55d.sock -hlocalhost
- ERROR 1045 (28000): Access denied for user 'test1'@'localhost' (using password: YES)
另外,即便指定了socket选项,-h127.0.0.1也会强制采用tcp/ip连接登录
- [root@mysqlslave3 ~]# /data1-new/app/services/mysql55d/bin/mysql --socket=/data1-new/app/tmp/mysql55d.sock -utest1 -ptest1 -h127.0.0.1
- mysql> status
- --------------
- /data1-new/app/services/mysql55d/bin/mysql Ver 14.14 Distrib 5.5.31, for Linux (x86_64) using readline 5.1
- Connection id:1449940
- Current database:
- Current user:test1@127.0.0.1
- SSL:Not in use
- Current pager:stdout
- Using outfile:''
- Using delimiter:;
- Server version:5.5.31-log Source distribution
- Protocol version:10
- Connection:127.0.0.1 via TCP/IP
- Server characterset:utf8
- Db characterset:utf8
- Client characterset:utf8
- Conn. characterset:utf8
- TCP port:3306
- Uptime:79 days 12 hours 22 min 29 sec
-
- Threads: 1 Questions: 4746519297 Slow queries: 144823 Opens: 18675 Flush tables: 79 Open tables: 24 Queries per second avg: 690.890
-
- mysql> select user(),current_user();
- +-----------------+----------------+
- | user() | current_user() |
- +-----------------+----------------+
- | test1@127.0.0.1 | test1@% |
- +-----------------+----------------+
- 1 row in set (0.00 sec)
创建基于localhost的用户,
- mysql> grant select on *.* to 'test1'@'localhost' identified by 'test1';
- Query OK, 0 rows affected (0.00 sec)
- mysql> select host,user,password from mysql.user order by 1 desc ,2;
- +-----------------------------------------+--------------+-------------------------------------------+
- | host | user | password |
- +-----------------------------------------+--------------+-------------------------------------------+
- | localhost | root | |
- | localhost | test1 | *06C0BF5B64ECE2F648B5F048A71903906BA08E5C |
- | ::1 | root | |
- | 127.0.0.1 | root | |
- | % | root | *96B86EC8D3F883B0C55D488A951E11B037E74816 |
- | % | test1 | *06C0BF5B64ECE2F648B5F048A71903906BA08E5C |
- +-----------------------------------------+--------------+-------------------------------------------+
- 11 rows in set (0.00 sec)
再次以unix socket方式登录,成功
- [root@mysqlslave3 ~]# /data1-new/app/services/mysql55d/bin/mysql -utest1 -ptest1 --socket=/data1-new/app/tmp/mysql55d.sock
- mysql> status
- --------------
- /data1-new/app/services/mysql55d/bin/mysql Ver 14.14 Distrib 5.5.31, for Linux (x86_64) using readline 5.1
- Connection id:8
- Current database:
- Current user:test1@localhost
- SSL:Not in use
- Current pager:stdout
- Using outfile:''
- Using delimiter:;
- Server version:5.5.31-log Source distribution
- Protocol version:10
- Connection:Localhost via UNIX socket
- Server characterset:utf8
- Db characterset:utf8
- Client characterset:utf8
- Conn. characterset:utf8
- UNIX socket:/data1-new/app/tmp/mysql55d.sock
- Uptime:9 min 44 sec
-
- Threads: 1 Questions: 87 Slow queries: 4 Opens: 38 Flush tables: 2 Open tables: 2 Queries per second avg: 0.148
-
- mysql> select current_user(),user();
- +-----------------+-----------------+
- | current_user() | user() |
- +-----------------+-----------------+
- | test1@localhost | test1@localhost |
- +-----------------+-----------------+
- 1 row in set (0.00 sec)
2 localhost的登录协议
- 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. For example:
- shell> mysql --host=127.0.0.1
- shell> mysql --protocol=TCP
- http://dev.mysql.com/doc/refman/5.6/en/connecting.htm
当指定-h localhost选项时,采用unix socket方式连接,
- [root@mysqlslave3 ~]# strace /data1/app/services/mysql55a/bin/mysql --socket=/data1/app/tmp/mysql55a.sock -hlocalhost -utest1 -ptest1
- execve("/data1/app/services/mysql55a/bin/mysql", ["/data1/app/services/mysql55a/bin"..., "--socket=/data1/app/tmp/mysql55a"..., "-hlocalhost", "-utest1", "-ptest1", "-o", "/tmp/tmp12.log"], [/* 30 vars */]) = 0
- ......
- stat("/etc/my.cnf", 0x7ffeb7006980) = -1 ENOENT (No such file or directory)
- stat("/etc/mysql/my.cnf", 0x7ffeb7006980) = -1 ENOENT (No such file or directory)
- stat("/data1/app/services/mysql55/etc/my.cnf", 0x7ffeb7006980) = -1 ENOENT (No such file or directory)
- stat("/root/.my.cnf", 0x7ffeb7006980) = -1 ENOENT (No such file or directory)
- socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
- connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
- close(3) = 0
- socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
- connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
- close(3) = 0
- ......
- socket(PF_LOCAL, SOCK_STREAM, 0) = 3
- fcntl(3, F_SETFL, O_RDONLY) = 0
- fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
- connect(3, {sa_family=AF_LOCAL, sun_path="/data1/app/tmp/mysql55a.sock"}, 110) = 0
- setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, "\2003\341\1\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
- setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, "\2003\341\1\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
- setsockopt(3, SOL_IP, IP_TOS, [8], 4) = -1 EOPNOTSUPP (Operation not supported)
- setsockopt(3, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
- read(3, "N\0\0\0\n5.5.31-log\0\372f\25\0rvz&Gs04\0\377\367!"..., 16384) = 82
- open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 4
- fstat(4, {st_mode=S_IFREG|0644, st_size=106065056, ...}) = 0
- mmap(NULL, 106065056, PROT_READ, MAP_PRIVATE, 4, 0) = 0x7f21b9ad9000
- close(4) = 0
- stat("/data1/app/services/mysql55/share/charsets/Index.xml", 0x7ffeb7006100) = -1 ENOENT (No such file or directory)
- futex(0x90d540, FUTEX_WAKE_PRIVATE, 2147483647) = 0
- write(3, "`\0\0\1\215\246\17\0\0\0\0\1!\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 100) = 100
- read(3, "I\0\0\2\377\25\4#28000Access denied for u"..., 16384) = 77
- shutdown(3, SHUT_RDWR) = 0
- close(3) = 0
- fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
- mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f21c8956000
- write(2, "ERROR 1045 (28000): ", 20ERROR 1045 (28000): ) = 20
- write(2, "Access denied for user 'test1'@'"..., 64Access denied for user 'test1'@'localhost' (using password: YES)) = 64
- write(2, "\n", 1
- ) = 1
- write(1, "\7", 1) = 1
- gettimeofday({1436522608, 908777}, NULL) = 0
- exit_group(1) = ?
采用TCP/IP协议连接
- [root@mysqlslave3 ~]# strace /data1/app/services/mysql55a/bin/mysql -h127.0.0.1 -utest1 -ptest1
- execve("/data1/app/services/mysql55a/bin/mysql", ["/data1/app/services/mysql55a/bin"..., "-h127.0.0.1", "-utest1", "-ptest1"], [/* 30 vars */]) = 0
- ......
- socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
- connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
- close(3) = 0
- socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
- connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
- close(3) = 0
- ......
- socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
- connect(3, {sa_family=AF_INET, sin_port=htons(3306), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
- fcntl(3, F_SETFL, O_RDONLY) = 0
- fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
- setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, "\2003\341\1\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
- setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, "\2003\341\1\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
- setsockopt(3, SOL_IP, IP_TOS, [8], 4) = 0
- setsockopt(3, SOL_TCP, TCP_NODELAY, [1], 4) = 0
- setsockopt(3, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
- read(3, "N\0\0\0\n5.5.31-log\0\7g\25\0r2>$6$PH\0\377\367!"..., 16384) = 82
- ......
- poll([{fd=3, events=POLLIN|POLLPRI}], 1, 0) = 0 (Timeout)
- write(3, "!\0\0\0\3select @@version_comment li"..., 37) = 37
- read(3, "\1\0\0\1\1'\0\0\2\3def\0\0\0\21@@version_comme"..., 16384) = 90
- write(1, "Your MySQL connection id is 1402"..., 83Your MySQL connection id is 1402631
- Server version: 5.5.31-log Source distribution
- ) = 83
- ......
我们再看一下分别通过unix socket和TCP/IP连接数据库时,mysqld都做了什么事情
- [root@mysqlslave3 ~]# strace -p 23465
- [root@mysqlslave3 ~]# /data1-new/app/services/mysql55d/bin/mysql -uroot -p -h127.0.0.1 -P3309
- Process 23465 attached
- restart_syscall(<... resuming interrupted call ...>) = 1
- fcntl(14, F_GETFL) = 0x2 (flags O_RDWR)
- fcntl(14, F_SETFL, O_RDWR|O_NONBLOCK) = 0
- accept(14, {sa_family=AF_INET, sin_port=htons(6771), sin_addr=inet_addr("127.0.0.1")}, [16]) = 17
- fcntl(14, F_SETFL, O_RDWR) = 0
- getsockname(17, {sa_family=AF_INET, sin_port=htons(3309), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0
- fcntl(17, F_SETFL, O_RDONLY) = 0
- fcntl(17, F_GETFL) = 0x2 (flags O_RDWR)
- setsockopt(17, SOL_SOCKET, SO_RCVTIMEO, "\36\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
- setsockopt(17, SOL_SOCKET, SO_SNDTIMEO, ", 16) = 0
- fcntl(17, F_SETFL, O_RDWR|O_NONBLOCK) = 0
- setsockopt(17, SOL_IP, IP_TOS, [8], 4) = 0
- setsockopt(17, SOL_TCP, TCP_NODELAY, [1], 4) = 0
- futex(0xf444a4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0xf444a0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
- futex(0xf438c0, FUTEX_WAKE_PRIVATE, 1) = 1
- poll([{fd=14, events=POLLIN}, {fd=16, events=POLLIN}], 2, 4294967295
-
-
- [root@mysqlslave3 ~]# strace -p 23465
- [root@mysqlslave3 ~]# /data1-new/app/services/mysql55d/bin/mysql --socket=/data1-new/app/tmp/mysql55d.sock -uroot -P3309
- Process 23465 attached
- restart_syscall(<... resuming interrupted call ...>) = 1
- fcntl(16, F_GETFL) = 0x2 (flags O_RDWR)
- fcntl(16, F_SETFL, O_RDWR|O_NONBLOCK) = 0
- accept(16, {sa_family=AF_LOCAL, NULL}, [2]) = 17
- fcntl(16, F_SETFL, O_RDWR) = 0
- getsockname(17, {sa_family=AF_LOCAL, sun_path="/data1-new/app/tmp/mysql55d.sock"}, [35]) = 0
- fcntl(17, F_SETFL, O_RDONLY) = 0
- fcntl(17, F_GETFL) = 0x2 (flags O_RDWR)
- setsockopt(17, SOL_SOCKET, SO_RCVTIMEO, "\36\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
- setsockopt(17, SOL_SOCKET, SO_SNDTIMEO, ", 16) = 0
- fcntl(17, F_SETFL, O_RDWR|O_NONBLOCK) = 0
- setsockopt(17, SOL_IP, IP_TOS, [8], 4) = -1 EOPNOTSUPP (Operation not supported)
- futex(0xf444a4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0xf444a0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
- futex(0xf438c0, FUTEX_WAKE_PRIVATE, 1) = 1
- poll([{fd=14, events=POLLIN}, {fd=16, events=POLLIN}], 2, 4294967295
3 Unix socket VS IP socket
https://lists.freebsd.org/pipermail/freebsd-performance/2005-February/001143.html
1 UNIX domain sockets use the file system as the address name space.
2 UNIX domain sockets have explicit knowledge that they're executing on
the same system. They avoid the extra context switch through the
netisr, and a sending thread will write the stream or datagrams directly
into the receiving socket buffer. No checksums are calculated, no
headers are inserted, no routing is performed, etc.
3 In general, the argument for implementing over TCP is that it gives you
location independence and immediate portability -- you can move the client
or the daemon, update an address, and it will "just work". The sockets
layer provides a reasonable abstraction of communications services, so
it's not hard to write an application so that the connection/binding
portion knows about TCP and UNIX domain sockets, and all the rest just
uses the socket it's given. So if you're looking for performance locally,
I think UNIX domain sockets probably best meet your need. Many people
will code to TCP anyway because performance is often less critical, and
the network portability benefit is substantial.
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15480802/viewspace-1755100/,如需转载,请注明出处,否则将追究法律责任。