diff options
author | Konstantin Osipov <kostja@sun.com> | 2010-11-12 15:56:21 +0300 |
---|---|---|
committer | Konstantin Osipov <kostja@sun.com> | 2010-11-12 15:56:21 +0300 |
commit | 4749b884942f464febbb8221b4a73f5b85e98090 (patch) | |
tree | 47b1a5ab7416e5cc83776aa9a0543a058f35d724 | |
parent | 936bec8e2cf0362e0cf8902ab1f7ea8141b880cc (diff) | |
download | mariadb-git-4749b884942f464febbb8221b4a73f5b85e98090.tar.gz |
Implement a fix for Bug#57058 -- send SERVER_QUERY_WAS_SLOW over
network when a query was slow.
When a query is slow, sent a special flag to the client
indicating this fact.
Add a test case.
Implement review comments.
-rw-r--r-- | include/mysql_com.h | 6 | ||||
-rw-r--r-- | sql/protocol.cc | 4 | ||||
-rw-r--r-- | sql/sp_head.cc | 5 | ||||
-rw-r--r-- | sql/sql_class.h | 14 | ||||
-rw-r--r-- | sql/sql_cursor.cc | 3 | ||||
-rw-r--r-- | sql/sql_db.cc | 1 | ||||
-rw-r--r-- | sql/sql_error.cc | 2 | ||||
-rw-r--r-- | sql/sql_error.h | 15 | ||||
-rw-r--r-- | sql/sql_parse.cc | 5 | ||||
-rw-r--r-- | tests/mysql_client_test.c | 42 |
10 files changed, 70 insertions, 27 deletions
diff --git a/include/mysql_com.h b/include/mysql_com.h index d4223211710..bc9296a6d02 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -255,7 +255,11 @@ enum enum_server_command #define SERVER_STATUS_CLEAR_SET (SERVER_QUERY_NO_GOOD_INDEX_USED| \ SERVER_QUERY_NO_INDEX_USED|\ SERVER_MORE_RESULTS_EXISTS|\ - SERVER_STATUS_METADATA_CHANGED) + SERVER_STATUS_METADATA_CHANGED |\ + SERVER_QUERY_WAS_SLOW |\ + SERVER_STATUS_DB_DROPPED |\ + SERVER_STATUS_CURSOR_EXISTS|\ + SERVER_STATUS_LAST_ROW_SENT) #define MYSQL_ERRMSG_SIZE 512 #define NET_READ_TIMEOUT 30 /* Timeout on read */ diff --git a/sql/protocol.cc b/sql/protocol.cc index dd3a5d92a87..03b151e4346 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -505,11 +505,11 @@ void Protocol::end_statement() thd->stmt_da->get_sqlstate()); break; case Diagnostics_area::DA_EOF: - error= send_eof(thd->stmt_da->server_status(), + error= send_eof(thd->server_status, thd->stmt_da->statement_warn_count()); break; case Diagnostics_area::DA_OK: - error= send_ok(thd->stmt_da->server_status(), + error= send_ok(thd->server_status, thd->stmt_da->statement_warn_count(), thd->stmt_da->affected_rows(), thd->stmt_da->last_insert_id(), diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 47b698c3a2f..27238fa05d2 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -3100,7 +3100,12 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) res= m_lex_keeper.reset_lex_and_exec_core(thd, nextp, FALSE, this); if (thd->stmt_da->is_eof()) + { + /* Finalize server status flags after executing a statement. */ + thd->update_server_status(); + thd->protocol->end_statement(); + } query_cache_end_of_result(thd); diff --git a/sql/sql_class.h b/sql/sql_class.h index 8bf72f1cdb2..cc41595e56c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2234,6 +2234,20 @@ public: } void set_time_after_lock() { utime_after_lock= my_micro_time(); } ulonglong current_utime() { return my_micro_time(); } + /** + Update server status after execution of a top level statement. + + Currently only checks if a query was slow, and assigns + the status accordingly. + Evaluate the current time, and if it exceeds the long-query-time + setting, mark the query as slow. + */ + void update_server_status() + { + ulonglong end_utime_of_query= current_utime(); + if (end_utime_of_query > utime_after_lock + variables.long_query_time) + server_status|= SERVER_QUERY_WAS_SLOW; + } inline ulonglong found_rows(void) { return limit_found_rows; diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index 7a9834b4cde..acc591f1ea2 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -277,7 +277,6 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused))) rc= result->send_result_set_metadata(item_list, Protocol::SEND_NUM_ROWS); thd->server_status|= SERVER_STATUS_CURSOR_EXISTS; result->send_eof(); - thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; } return rc; } @@ -318,12 +317,10 @@ void Materialized_cursor::fetch(ulong num_rows) case 0: thd->server_status|= SERVER_STATUS_CURSOR_EXISTS; result->send_eof(); - thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; break; case HA_ERR_END_OF_FILE: thd->server_status|= SERVER_STATUS_LAST_ROW_SENT; result->send_eof(); - thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT; close(); break; default: diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 4df8748429c..1dea2f279e9 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -866,7 +866,6 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) thd->clear_error(); thd->server_status|= SERVER_STATUS_DB_DROPPED; my_ok(thd, (ulong) deleted); - thd->server_status&= ~SERVER_STATUS_DB_DROPPED; } else if (mysql_bin_log.is_open()) { diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 8c038e10a1f..f042a7cd164 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -365,7 +365,6 @@ Diagnostics_area::set_ok_status(THD *thd, ulonglong affected_rows_arg, if (is_error() || is_disabled()) return; - m_server_status= thd->server_status; m_statement_warn_count= thd->warning_info->statement_warn_count(); m_affected_rows= affected_rows_arg; m_last_insert_id= last_insert_id_arg; @@ -395,7 +394,6 @@ Diagnostics_area::set_eof_status(THD *thd) if (is_error() || is_disabled()) return; - m_server_status= thd->server_status; /* If inside a stored procedure, do not return the total number of warnings, since they are not available to the client diff --git a/sql/sql_error.h b/sql/sql_error.h index 87e98e27673..14dc5e6d12c 100644 --- a/sql/sql_error.h +++ b/sql/sql_error.h @@ -79,12 +79,6 @@ public: const char* get_sqlstate() const { DBUG_ASSERT(m_status == DA_ERROR); return m_sqlstate; } - uint server_status() const - { - DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF); - return m_server_status; - } - ulonglong affected_rows() const { DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; } @@ -111,15 +105,6 @@ private: char m_sqlstate[SQLSTATE_LENGTH+1]; /** - Copied from thd->server_status when the diagnostics area is assigned. - We need this member as some places in the code use the following pattern: - thd->server_status|= ... - my_eof(thd); - thd->server_status&= ~... - Assigned by OK, EOF or ERROR. - */ - uint m_server_status; - /** The number of rows affected by the last statement. This is semantically close to thd->row_count_func, but has a different life cycle. thd->row_count_func stores the value returned by diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e95745634e8..4f4e26d1df0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1438,8 +1438,7 @@ void log_slow_statement(THD *thd) ulonglong end_utime_of_query= thd->current_utime(); thd_proc_info(thd, "logging slow query"); - if (((end_utime_of_query - thd->utime_after_lock) > - thd->variables.long_query_time || + if (((thd->server_status & SERVER_QUERY_WAS_SLOW) || ((thd->server_status & (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) && opt_log_queries_not_using_indexes && @@ -5505,6 +5504,8 @@ void mysql_parse(THD *thd, char *rawbuf, uint length, thd->end_statement(); thd->cleanup_after_query(); DBUG_ASSERT(thd->change_list.is_empty()); + /* Finalize server status flags after executing a statement. */ + thd->update_server_status(); } DBUG_VOID_RETURN; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index b85a6c587e4..3d709720727 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -19061,7 +19061,7 @@ static void test_bug49972() my_bool is_null; DBUG_ENTER("test_bug49972"); - myheader("test_49972"); + myheader("test_bug49972"); rc= mysql_query(mysql, "DROP FUNCTION IF EXISTS f1"); myquery(rc); @@ -19148,6 +19148,45 @@ static void test_bug49972() DBUG_VOID_RETURN; } + +/** + Bug#57058 SERVER_QUERY_WAS_SLOW not wired up. +*/ + +static void test_bug57058() +{ + MYSQL_RES *res; + int rc; + + DBUG_ENTER("test_bug57058"); + myheader("test_bug57058"); + + rc= mysql_query(mysql, "set @@session.long_query_time=0.1"); + myquery(rc); + + DIE_UNLESS(!(mysql->server_status & SERVER_QUERY_WAS_SLOW)); + + rc= mysql_query(mysql, "select sleep(1)"); + myquery(rc); + + /* + Important: the flag is sent in the last EOF packet of + the query, the one which ends the result. Read the + result to see the "slow" status. + */ + res= mysql_store_result(mysql); + + DIE_UNLESS(mysql->server_status & SERVER_QUERY_WAS_SLOW); + + mysql_free_result(res); + + rc= mysql_query(mysql, "set @@session.long_query_time=default"); + myquery(rc); + + DBUG_VOID_RETURN; +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -19481,6 +19520,7 @@ static struct my_tests_st my_tests[]= { { "test_bug42373", test_bug42373 }, { "test_bug54041", test_bug54041 }, { "test_bug47485", test_bug47485 }, + { "test_bug57058", test_bug57058 }, { 0, 0 } }; |