From 07f09df92bc2ab7d18833dd6ce149a6681ae8a32 Mon Sep 17 00:00:00 2001 From: vinchen Date: Fri, 21 Oct 2016 16:02:51 +0800 Subject: [PATCH] fix the ABI and stop slave hang problem --- include/mysql.h.pp | 1 - include/mysql_com.h | 3 ++- include/sql_common.h | 1 + sql-common/client.c | 10 ++++++++-- sql/net_serv.cc | 14 ++++++++++---- sql/slave.cc | 40 ++++++++++++++++++++++++++-------------- 6 files changed, 47 insertions(+), 22 deletions(-) diff --git a/include/mysql.h.pp b/include/mysql.h.pp index 1da038c9c7f..857f5b99a90 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -35,7 +35,6 @@ typedef struct st_net { my_bool thread_specific_malloc; unsigned char compress; my_bool unused3; - unsigned long real_network_read_len; void *thd; unsigned int last_errno; unsigned char error; diff --git a/include/mysql_com.h b/include/mysql_com.h index fe78e922ffb..60a3c9f8a9a 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -424,7 +424,6 @@ typedef struct st_net { Pointer to query object in query cache, do not equal NULL (0) for queries in cache that have not stored its results yet */ - unsigned long real_network_read_len; // the my_real_read length for each package #endif void *thd; /* Used by MariaDB server to avoid calling current_thd */ unsigned int last_errno; @@ -586,6 +585,8 @@ my_bool net_write_command(NET *net,unsigned char command, const unsigned char *packet, size_t len); int net_real_write(NET *net,const unsigned char *packet, size_t len); unsigned long my_net_read_packet(NET *net, my_bool read_from_server); +ulong my_net_read_packet_reallen(NET *net, my_bool read_from_server, + ulong* reallen); #define my_net_read(A) my_net_read_packet((A), 0) #ifdef MY_GLOBAL_INCLUDED diff --git a/include/sql_common.h b/include/sql_common.h index 49616f6d56c..bbf459e1e55 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -104,6 +104,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, const unsigned char *arg, ulong arg_length, my_bool skip_check, MYSQL_STMT *stmt); unsigned long cli_safe_read(MYSQL *mysql); +unsigned long cli_safe_read_reallen(MYSQL *mysql, ulong* reallen); void net_clear_error(NET *net); void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net); void set_stmt_error(MYSQL_STMT *stmt, int errcode, const char *sqlstate, diff --git a/sql-common/client.c b/sql-common/client.c index 858e9ec4b5b..fc76fa976e0 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -569,16 +569,22 @@ err: Error message is set. @retval */ - ulong cli_safe_read(MYSQL *mysql) +{ + ulong reallen = 0; + return cli_safe_read_reallen(mysql, &reallen); +} + +ulong +cli_safe_read_reallen(MYSQL *mysql, ulong* reallen) { NET *net= &mysql->net; ulong len=0; restart: if (net->vio != 0) - len= my_net_read_packet(net, 0); + len= my_net_read_packet_reallen(net, 0, reallen); if (len == packet_error || len == 0) { diff --git a/sql/net_serv.cc b/sql/net_serv.cc index bd7298701a9..581bc12b35b 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -1133,16 +1133,22 @@ ulong my_net_read(NET *net) The function returns the length of the found packet or packet_error. net->read_pos points to the read data. */ +ulong +my_net_read_packet(NET *net, my_bool read_from_server) +{ + ulong reallen = 0; + return my_net_read_packet_reallen(net, read_from_server, &reallen); +} ulong -my_net_read_packet(NET *net, my_bool read_from_server) +my_net_read_packet_reallen(NET *net, my_bool read_from_server, ulong* reallen) { size_t len, complen; MYSQL_NET_READ_START(); - net->real_network_read_len = 0; + *reallen = 0; #ifdef HAVE_COMPRESS if (!net->compress) { @@ -1167,7 +1173,7 @@ my_net_read_packet(NET *net, my_bool read_from_server) if (len != packet_error) { net->read_pos[len]=0; /* Safeguard for mysql_use_result */ - net->real_network_read_len = len; + *reallen = len; } MYSQL_NET_READ_DONE(0, len); return len; @@ -1269,7 +1275,7 @@ my_net_read_packet(NET *net, my_bool read_from_server) return packet_error; } buf_length+= complen; - net->real_network_read_len += packet_len; + *reallen += packet_len; } net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE; diff --git a/sql/slave.cc b/sql/slave.cc index 52bb668fe70..3a6517f54c4 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3315,7 +3315,8 @@ static int request_dump(THD *thd, MYSQL* mysql, Master_info* mi, number Length of packet */ -static ulong read_event(MYSQL* mysql, Master_info *mi, bool* suppress_warnings, ulong* network_read_len) +static ulong read_event(MYSQL* mysql, Master_info *mi, bool* suppress_warnings, + ulong* network_read_len) { ulong len; DBUG_ENTER("read_event"); @@ -3330,7 +3331,7 @@ static ulong read_event(MYSQL* mysql, Master_info *mi, bool* suppress_warnings, DBUG_RETURN(packet_error); #endif - len = cli_safe_read(mysql); + len = cli_safe_read_reallen(mysql, network_read_len); if (len == packet_error || (long) len < 1) { if (mysql_errno(mysql) == ER_NET_READ_INTERRUPTED) @@ -3357,8 +3358,6 @@ static ulong read_event(MYSQL* mysql, Master_info *mi, bool* suppress_warnings, DBUG_RETURN(packet_error); } - *network_read_len = mysql->net.real_network_read_len ; - DBUG_PRINT("exit", ("len: %lu net->read_pos[4]: %d", len, mysql->net.read_pos[4])); DBUG_RETURN(len - 1); @@ -4479,29 +4478,42 @@ Stopping slave I/O thread due to out-of-memory error from master"); goto err; } - /* Control the binlog read speed of master when read_binlog_speed_limit is non-zero + /* Control the binlog read speed of master + when read_binlog_speed_limit is non-zero */ - ulonglong read_binlog_speed_limit_in_bytes = opt_read_binlog_speed_limit * 1024; - if (read_binlog_speed_limit_in_bytes) + ulonglong speed_limit_in_bytes = opt_read_binlog_speed_limit * 1024; + if (speed_limit_in_bytes) { - /* prevent the tokenamount become a large value, - for example, the IO thread doesn't work for a long time + /* Prevent the tokenamount become a large value, + for example, the IO thread doesn't work for a long time */ - if (tokenamount > read_binlog_speed_limit_in_bytes * 2) + if (tokenamount > speed_limit_in_bytes * 2) { lastchecktime = my_hrtime().val; - tokenamount = read_binlog_speed_limit_in_bytes * 2; + tokenamount = speed_limit_in_bytes * 2; } do { ulonglong currenttime = my_hrtime().val; - tokenamount += (currenttime - lastchecktime) * read_binlog_speed_limit_in_bytes / (1000*1000); + tokenamount += (currenttime - lastchecktime) * speed_limit_in_bytes / (1000*1000); lastchecktime = currenttime; if(tokenamount < network_read_len) { - ulonglong micro_sleeptime = 1000*1000 * (network_read_len - tokenamount) / read_binlog_speed_limit_in_bytes ; - my_sleep(micro_sleeptime > 1000 ? micro_sleeptime : 1000); // at least sleep 1000 micro second + ulonglong micro_time = 1000*1000 * (network_read_len - tokenamount) / speed_limit_in_bytes ; + ulonglong second_time = micro_time / (1000 * 1000); + micro_time = micro_time % (1000 * 1000); + + // at least sleep 1000 micro second + my_sleep(micro_time > 1000 ? micro_time : 1000); + + /* + If it sleep more than one second, + it should use slave_sleep() to avoid the STOP SLAVE hang. + */ + if (second_time) + slave_sleep(thd, second_time, io_slave_killed, mi); + } }while(tokenamount < network_read_len); tokenamount -= network_read_len;