從原始碼解析ERROR 1129 (HY000)(2)以及unauthenticated user
原創 水平有限,只為拋磚,有誤請指出
這裡主要找一下m_connect是什麼,以及怎麼增加的,因為前文我沒有找到,再次用斷點的方式
描述一下unauthenticated user
一、m_connect是什麼怎麼增加的
m_connect實際上就是m_handshake下面是
sql_authentication.cc:
acl_authenticate函式
聚合函式Hostname.cc
sql_authentication.cc:1900
do_auth_once函式呼叫
下面是錯誤的宏定義
也就是說每次由於mpvio->write_packet函式問題導致的握手失敗都會觸發他+1,其實這很可能是網路
問題,關於mpvio->write_packet的返回值感興趣的可以繼續跟中下去
下面是官方關於錯誤的解釋
If the following error occurs, it means that mysqldhas received many connection requests from the given
host that were interrupted in the middle:
Host 'host_name' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'
The value of the max_connect_errorssystem variable determines how many successive
interrupted connection requests are permitted. (See Section 6.1.4, “Server System Variables”.) After
max_connect_errorsfailed requests without a successful connection, mysqldassumes that something
is wrong (for example, that someone is trying to break in), and blocks the host from further connections
until you issue a FLUSH HOSTSstatement or execute a mysqladmin flush-hostscommand.
By default, mysqldblocks a host after 100 connection errors. You can adjust the value by setting
max_connect_errorsat server startup:
shell> mysqld_safe --max_connect_errors=10000 &
The value can also be set at runtime:
mysql> SET GLOBAL max_connect_errors=10000;
If you get the Host 'host_name' is blockederror message for a given host, you should first verify
that there is nothing wrong with TCP/IP connections from that host. If you are having network problems, it
does you no good to increase the value of the max_connect_errorsvariable.
二、 unauthenticated user為什麼和反解析有關
check_connection會呼叫ip_to_hostname和acl_authenticate進行解析和密碼認證過程,但是
ip_to_hostname出現在sql_connect.cc:1166而acl_authenticate出現在sql_connect.cc:1243
可以看到ip_to_hostname確實在acl_authenticate函式前,也就是反解析在密碼認證前,也是在MYSQL協議握手成功前。
這也說明什麼了為什麼解析慢會導致unauthenticated user的使用者。
mysql> show processlist;
+----+----------------------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined |
+----+----------------------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
| 5 | unauthenticated user | 192.168.190.60:12770 | NULL | Connect | 35 | login | NULL | 0 | 0 |
| 6 | root | localhost | NULL | Query | 0 | starting | show processlist | 0 | 0 |
+----+----------------------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
為了驗證我在原始碼check_connection處增加了等待10秒並且打日誌的來驗證不然不好觀察這個問題,確實如上所訴
mysql> show processlist;
+----+----------------------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined |
+----+----------------------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
| 4 | root | localhost | NULL | Query | 0 | starting | show processlist | 0 | 0 |
| 6 | unauthenticated user | 192.168.190.60:61688 | NULL | Connect | 8 | login | NULL | 0 | 0 |
+----+----------------------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
2 rows in set (0.00 sec)
mysql> show processlist;
+----+---------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined |
+----+---------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
| 4 | root | localhost | NULL | Query | 0 | starting | show processlist | 0 | 0 |
| 6 | testuuu | 192.168.190.60:61688 | NULL | Connect | 12 | login | NULL | 0 | 0 |
+----+---------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
2 rows in set (0.00 sec)
日誌輸出:
2017-05-31T22:34:28.605325Z 10 [Note] Before acl_authenticate sleep(10) check unauthenticated user
2017-05-31T22:34:38.606414Z 10 [Note] After acl_authenticate sleep(10) check authenticated user
作者微信:
這裡主要找一下m_connect是什麼,以及怎麼增加的,因為前文我沒有找到,再次用斷點的方式
描述一下unauthenticated user
一、m_connect是什麼怎麼增加的
m_connect實際上就是m_handshake下面是
點選(此處)摺疊或開啟
-
Hostname.h
-
void sum_connect_errors()
-
{
-
/* Current (historical) behavior: */
-
m_connect= m_handshake;
- }
sql_authentication.cc:
acl_authenticate函式
點選(此處)摺疊或開啟
-
res= do_auth_once(thd, auth_plugin_name, &mpvio);
-
-
...
-
-
case CR_AUTH_PLUGIN_ERROR:
-
errors.m_auth_plugin= 1;
-
break;
-
case CR_AUTH_HANDSHAKE:
-
errors.m_handshake= 1;//這裡m_handshake=1也就是m_connect=1,這裡會在後面進行聚合
-
break;
-
case CR_AUTH_USER_CREDENTIALS:
-
errors.m_authentication= 1;
-
break;
- case CR_ERROR:
點選(此處)摺疊或開啟
-
void Host_errors::aggregate(const Host_errors *errors)//接受一個Host_errors型別指標,和當前this->* 進行相加
-
{
-
m_connect+= errors->m_connect; //指標指向的Host_errors Host_errors 和this->m_connect相加 相加後存入 this->m_connect
-
m_host_blocked+= errors->m_host_blocked;
-
m_nameinfo_transient+= errors->m_nameinfo_transient;
-
m_nameinfo_permanent+= errors->m_nameinfo_permanent;
-
m_format+= errors->m_format;
-
m_addrinfo_transient+= errors->m_addrinfo_transient;
-
m_addrinfo_permanent+= errors->m_addrinfo_permanent;
-
m_FCrDNS+= errors->m_FCrDNS;
-
m_host_acl+= errors->m_host_acl;
-
m_no_auth_plugin+= errors->m_no_auth_plugin;
-
m_auth_plugin+= errors->m_auth_plugin;
-
m_handshake+= errors->m_handshake;
-
m_proxy_user+= errors->m_proxy_user;
-
m_proxy_user_acl+= errors->m_proxy_user_acl;
-
m_authentication+= errors->m_authentication;
-
m_ssl+= errors->m_ssl;
-
m_max_user_connection+= errors->m_max_user_connection;
-
m_max_user_connection_per_hour+= errors->m_max_user_connection_per_hour;
-
m_default_database+= errors->m_default_database;
-
m_init_connect+= errors->m_init_connect;
- m_local+= errors->m_local;
sql_authentication.cc:1900
do_auth_once函式呼叫
點選(此處)摺疊或開啟
-
sql_authentication.cc:2672
-
native_password_authenticate函式
-
if (mpvio->write_packet(mpvio, (uchar*) mpvio->scramble, SCRAMBLE_LENGTH + 1))
-
DBUG_RETURN(CR_AUTH_HANDSHAKE);//這裡看到了錯誤
-
......
-
if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0)
-
DBUG_RETURN(CR_AUTH_HANDSHAKE); //這裡看到了錯誤
- DBUG_PRINT("info", ("reply read : pkt_len=%d", pkt_len));
下面是錯誤的宏定義
點選(此處)摺疊或開啟
-
#define CR_AUTH_PLUGIN_ERROR 3
-
/**
-
Authentication failed, client server handshake.
-
An error occurred during the client server handshake.
-
These errors are reported in table performance_schema.host_cache,
-
column COUNT_HANDSHAKE_ERRORS.
-
*/
-
#define CR_AUTH_HANDSHAKE 2
-
/**
-
Authentication failed, user credentials.
-
For example, wrong passwords.
-
These errors are reported in table performance_schema.host_cache,
-
column COUNT_AUTHENTICATION_ERRORS.
-
*/
-
#define CR_AUTH_USER_CREDENTIALS 1
-
/**
-
Authentication failed. Additionally, all other CR_xxx values
-
(libmysql error code) can be used too.
-
-
The client plugin may set the error code and the error message directly
-
in the MYSQL structure and return CR_ERROR. If a CR_xxx specific error
-
code was returned, an error message in the MYSQL structure will be
-
overwritten. If CR_ERROR is returned without setting the error in MYSQL,
-
CR_UNKNOWN_ERROR will be user.
-
*/
-
#define CR_ERROR 0
-
/**
-
Authentication (client part) was successful. It does not mean that the
-
authentication as a whole was successful, usually it only means
-
that the client was able to send the user name and the password to the
-
server. If CR_OK is returned, the libmysql reads the next packet expecting
-
it to be one of OK, ERROR, or CHANGE_PLUGIN packets.
-
*/
-
#define CR_OK -1
-
/**
-
Authentication was successful.
-
It means that the client has done its part successfully and also that
-
a plugin has read the last packet (one of OK, ERROR, CHANGE_PLUGIN).
-
In this case, libmysql will not read a packet from the server,
-
but it will use the data at mysql->net.read_pos.
-
-
A plugin may return this value if the number of roundtrips in the
-
authentication protocol is not known in advance, and the client plugin
-
needs to read one packet more to determine if the authentication is finished
-
or not.
-
*/
- #define CR_OK_HANDSHAKE_COMPLETE -2
也就是說每次由於mpvio->write_packet函式問題導致的握手失敗都會觸發他+1,其實這很可能是網路
問題,關於mpvio->write_packet的返回值感興趣的可以繼續跟中下去
下面是官方關於錯誤的解釋
If the following error occurs, it means that mysqldhas received many connection requests from the given
host that were interrupted in the middle:
Host 'host_name' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'
The value of the max_connect_errorssystem variable determines how many successive
interrupted connection requests are permitted. (See Section 6.1.4, “Server System Variables”.) After
max_connect_errorsfailed requests without a successful connection, mysqldassumes that something
is wrong (for example, that someone is trying to break in), and blocks the host from further connections
until you issue a FLUSH HOSTSstatement or execute a mysqladmin flush-hostscommand.
By default, mysqldblocks a host after 100 connection errors. You can adjust the value by setting
max_connect_errorsat server startup:
shell> mysqld_safe --max_connect_errors=10000 &
The value can also be set at runtime:
mysql> SET GLOBAL max_connect_errors=10000;
If you get the Host 'host_name' is blockederror message for a given host, you should first verify
that there is nothing wrong with TCP/IP connections from that host. If you are having network problems, it
does you no good to increase the value of the max_connect_errorsvariable.
二、 unauthenticated user為什麼和反解析有關
點選(此處)摺疊或開啟
-
斷點:
-
(gdb) info b
-
Num Type Disp Enb Address What
-
1 breakpoint keep y 0x0000000000ebd3b3 in main(int, char**) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/main.cc:25
-
breakpoint already hit 1 time
-
2 breakpoint keep y 0x0000000000ee48ac in do_auth_once(THD*, LEX_CSTRING const&, MPVIO_EXT*)
-
at /root/mysql5.7.14/percona-server-5.7.14-7/sql/auth/sql_authentication.cc:1877
-
breakpoint already hit 2 times
-
3 breakpoint keep y 0x0000000000f7aeb7 in ip_to_hostname(sockaddr_storage*, char const*, char**, uint*)
-
at /root/mysql5.7.14/percona-server-5.7.14-7/sql/hostname.cc:412
-
breakpoint already hit 1 time
-
4 breakpoint keep y 0x0000000000ee6f8b in native_password_authenticate(MYSQL_PLUGIN_VIO*, MYSQL_SERVER_AUTH_INFO*)
-
at /root/mysql5.7.14/percona-server-5.7.14-7/sql/auth/sql_authentication.cc:2672
- breakpoint already hit 1 time
點選(此處)摺疊或開啟
-
ip_to_hostname棧幀:
-
(gdb) bt
-
#0 ip_to_hostname (ip_storage=0x7fffe80102e8, ip_string=0x7fffe800d020 "192.168.190.60", hostname=0x7fffec16dc38, connect_errors=0x7fffec16dc5c)
-
at /root/mysql5.7.14/percona-server-5.7.14-7/sql/hostname.cc:412
-
#1 0x000000000154b73c in check_connection (thd=0x7fffe8007e20, extra_port_connection=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_connect.cc:1166
-
#2 0x000000000154be1c in login_connection (thd=0x7fffe8007e20, extra_port_connection=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_connect.cc:1292
-
#3 0x000000000154c67f in thd_prepare_connection (thd=0x7fffe8007e20, extra_port_connection=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_connect.cc:1447
-
#4 0x00000000016e1d22 in handle_connection (arg=0x3d6d120) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/conn_handler/connection_handler_per_thread.cc:306
-
#5 0x0000000001d72124 in pfs_spawn_thread (arg=0x3f25420) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/perfschema/pfs.cc:2188
-
#6 0x0000003ca62079d1 in start_thread () from /lib64/libpthread.so.0
- #7 0x0000003ca5ee8b6d in clone () from /lib64/libc.so.6
點選(此處)摺疊或開啟
-
acl_authenticate棧幀:
-
(gdb) bt
-
#0 native_password_authenticate (vio=0x7fffec16d140, info=0x7fffec16d158) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/auth/sql_authentication.cc:2672
-
#1 0x0000000000ee499f in do_auth_once (thd=0x7fffe8007e20, auth_plugin_name=..., mpvio=0x7fffec16d140)
-
at /root/mysql5.7.14/percona-server-5.7.14-7/sql/auth/sql_authentication.cc:1900
-
#2 0x0000000000ee54f0 in acl_authenticate (thd=0x7fffe8007e20, command=COM_CONNECT, extra_port_connection=false)
-
at /root/mysql5.7.14/percona-server-5.7.14-7/sql/auth/sql_authentication.cc:2170
-
#3 0x000000000154bca2 in check_connection (thd=0x7fffe8007e20, extra_port_connection=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_connect.cc:1243
-
#4 0x000000000154be1c in login_connection (thd=0x7fffe8007e20, extra_port_connection=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_connect.cc:1292
-
#5 0x000000000154c67f in thd_prepare_connection (thd=0x7fffe8007e20, extra_port_connection=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_connect.cc:1447
-
#6 0x00000000016e1d22 in handle_connection (arg=0x3d6d120) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/conn_handler/connection_handler_per_thread.cc:306
-
#7 0x0000000001d72124 in pfs_spawn_thread (arg=0x3f25420) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/perfschema/pfs.cc:2188
-
#8 0x0000003ca62079d1 in start_thread () from /lib64/libpthread.so.0
- #9 0x0000003ca5ee8b6d in clone () from /lib64/libc.so.6
check_connection會呼叫ip_to_hostname和acl_authenticate進行解析和密碼認證過程,但是
ip_to_hostname出現在sql_connect.cc:1166而acl_authenticate出現在sql_connect.cc:1243
可以看到ip_to_hostname確實在acl_authenticate函式前,也就是反解析在密碼認證前,也是在MYSQL協議握手成功前。
這也說明什麼了為什麼解析慢會導致unauthenticated user的使用者。
mysql> show processlist;
+----+----------------------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined |
+----+----------------------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
| 5 | unauthenticated user | 192.168.190.60:12770 | NULL | Connect | 35 | login | NULL | 0 | 0 |
| 6 | root | localhost | NULL | Query | 0 | starting | show processlist | 0 | 0 |
+----+----------------------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
為了驗證我在原始碼check_connection處增加了等待10秒並且打日誌的來驗證不然不好觀察這個問題,確實如上所訴
點選(此處)摺疊或開啟
-
sql_print_information("Before acl_authenticate sleep(10) check unauthenticated user");
-
sleep(10);
-
-
auth_rc= acl_authenticate(thd, COM_CONNECT, extra_port_connection);
-
-
sql_print_information("After acl_authenticate sleep(10) check authenticated user");
- sleep(10);
+----+----------------------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined |
+----+----------------------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
| 4 | root | localhost | NULL | Query | 0 | starting | show processlist | 0 | 0 |
| 6 | unauthenticated user | 192.168.190.60:61688 | NULL | Connect | 8 | login | NULL | 0 | 0 |
+----+----------------------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
2 rows in set (0.00 sec)
mysql> show processlist;
+----+---------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
| Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined |
+----+---------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
| 4 | root | localhost | NULL | Query | 0 | starting | show processlist | 0 | 0 |
| 6 | testuuu | 192.168.190.60:61688 | NULL | Connect | 12 | login | NULL | 0 | 0 |
+----+---------+----------------------+------+---------+------+----------+------------------+-----------+---------------+
2 rows in set (0.00 sec)
日誌輸出:
2017-05-31T22:34:28.605325Z 10 [Note] Before acl_authenticate sleep(10) check unauthenticated user
2017-05-31T22:34:38.606414Z 10 [Note] After acl_authenticate sleep(10) check authenticated user
作者微信:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2140177/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 從原始碼解析ERROR 1129 (HY000):Host is blocked because of many connection errors原始碼ErrorBloC
- 【MySQL】關於 unauthenticated user的哲學思考MySql
- Golang 學習——error 和建立 error 原始碼解析GolangError原始碼
- 從原始碼解析 Go 的切片型別以及擴容機制原始碼Go型別
- MySQL建立使用者報錯 ERROR 1396 (HY000): Operation CREATE USER failed for 'afei'@'%'MySqlErrorAI
- koa2原始碼解析原始碼
- Retrofit2原始碼解析原始碼
- 【原始碼SOLO】Retrofit2原始碼解析(一)原始碼
- 【原始碼SOLO】Retrofit2原始碼解析(二)原始碼
- 從原始碼解析 Swift 弱引用原始碼Swift
- struts2 檔案上傳和下載,以及部分原始碼解析原始碼
- RxJava2 原始碼解析(一)RxJava原始碼
- Retrofit2原始碼解析(一)原始碼
- Promise-Polyfill原始碼解析(2)Promise原始碼
- RxJava2 原始碼解析(二)RxJava原始碼
- underscore.js原始碼解析2JS原始碼
- ptmalloc2原始碼解析初探原始碼
- mina2原始碼解析原始碼
- PureComponent 使用注意事項以及原始碼解析原始碼
- CyberRT_recorder原始碼解讀以及record解析原始碼
- Webpack原始碼基礎-Tapable從使用Hook到原始碼解析Web原始碼Hook
- 從Chrome原始碼看HTTP/2Chrome原始碼HTTP
- myBatis原始碼解析-快取篇(2)MyBatis原始碼快取
- Netty原始碼解析2-ReactorNetty原始碼React
- 深入RxJava2 原始碼解析(一)RxJava原始碼
- Mybatis原始碼解析2—— 例項搭建MyBatis原始碼
- 深入RxJava2 原始碼解析(二)RxJava原始碼
- RxDownload2 原始碼解析(三)原始碼
- RxDownload2 原始碼解析(二)原始碼
- AFNetworking原始碼解析系列(2)原始碼
- gulp原始碼解析(2):vinyl-fs原始碼
- 從Chrome原始碼看DNS解析過程Chrome原始碼DNS
- 從JDK原始碼看Java域名解析JDK原始碼Java
- Struts2 原始碼分析-----攔截器原始碼解析 --- ParametersInterceptor原始碼
- 友好 RxJava2.x 原始碼解析(三)zip 原始碼分析RxJava原始碼
- mysql連線的時候報 ERROR 1129MySqlError
- MySQL 5.7 建立使用者報錯 ERROR 1805 (HY000): Column count of mysql.user is wrongMySqlError
- ERROR 1010 (HY000): Error dropping databaseErrorDatabase