Merge lp:~vlad-lesin/percona-server/5.6-sql_timeout_twitter into lp:percona-server/5.6

Proposed by Vlad Lesin
Status: Merged
Approved by: Alexey Kopytov
Approved revision: no longer in the source branch.
Merged at revision: 428
Proposed branch: lp:~vlad-lesin/percona-server/5.6-sql_timeout_twitter
Merge into: lp:percona-server/5.6
Diff against target: 2612 lines (+1997/-29)
40 files modified
Percona-Server/config.h.cmake (+4/-0)
Percona-Server/configure.cmake (+19/-1)
Percona-Server/include/my_global.h (+13/-0)
Percona-Server/include/my_timer.h (+69/-0)
Percona-Server/include/mysql/plugin.h (+7/-0)
Percona-Server/include/mysql/plugin_audit.h.pp (+1/-0)
Percona-Server/include/mysql/plugin_auth.h.pp (+1/-0)
Percona-Server/include/mysql/plugin_ftparser.h.pp (+1/-0)
Percona-Server/include/mysql/thread_pool_priv.h (+6/-0)
Percona-Server/libmysqld/CMakeLists.txt (+3/-0)
Percona-Server/mysql-test/include/have_statement_timeout.inc (+4/-0)
Percona-Server/mysql-test/r/have_statement_timeout.require (+2/-0)
Percona-Server/mysql-test/r/max_statement_time_func.result (+116/-0)
Percona-Server/mysql-test/r/mysqld--help-notwin.result (+4/-0)
Percona-Server/mysql-test/r/mysqld--help-win.result (+4/-0)
Percona-Server/mysql-test/suite/sys_vars/r/have_statement_timeout_basic.result (+53/-0)
Percona-Server/mysql-test/suite/sys_vars/r/max_statement_time_basic.result (+89/-0)
Percona-Server/mysql-test/suite/sys_vars/t/have_statement_timeout_basic.test (+55/-0)
Percona-Server/mysql-test/suite/sys_vars/t/max_statement_time_basic.test (+78/-0)
Percona-Server/mysql-test/t/max_statement_time_func.test (+154/-0)
Percona-Server/mysys/CMakeLists.txt (+8/-0)
Percona-Server/mysys/kqueue_timers.c (+219/-0)
Percona-Server/mysys/posix_timers.c (+256/-0)
Percona-Server/sql/CMakeLists.txt (+4/-0)
Percona-Server/sql/handler.cc (+18/-0)
Percona-Server/sql/handler.h (+4/-0)
Percona-Server/sql/mysqld.cc (+22/-0)
Percona-Server/sql/set_var.h (+1/-0)
Percona-Server/sql/share/errmsg-utf8.txt (+3/-0)
Percona-Server/sql/signal_handler.cc (+3/-0)
Percona-Server/sql/sql_class.cc (+39/-15)
Percona-Server/sql/sql_class.h (+13/-0)
Percona-Server/sql/sql_parse.cc (+89/-1)
Percona-Server/sql/sql_timer.cc (+253/-0)
Percona-Server/sql/sql_timer.h (+50/-0)
Percona-Server/sql/sys_vars.cc (+10/-0)
Percona-Server/storage/innobase/handler/ha_innodb.cc (+49/-3)
Percona-Server/storage/innobase/include/lock0lock.h (+10/-0)
Percona-Server/storage/innobase/include/lock0priv.h (+0/-9)
Percona-Server/unittest/mysys/my_timer-t.c (+263/-0)
To merge this branch: bzr merge lp:~vlad-lesin/percona-server/5.6-sql_timeout_twitter
Reviewer Review Type Date Requested Status
Alexey Kopytov (community) Approve
Sergei Glushchenko (community) g2 Needs Fixing
Review via email: mp+146919@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

Vlad,

I see you encountered same issue as I did also. performance_schema *digest* tables are rely heavily on sql_yacc.yy grammar. So if someone just add new token (or even rule?) many of statement's digests will change.

I very dislike it as
1. There is a need to almost completely rewrite several *.result in perfscehma suite
2. There is no way to merge for example this branch and lp:~sergei.glushchenko/percona-server/ps56-univ-log-archive as both touch sql_yacc.yy. As resulting MD5 hashes will depend on changes made in both branches. The only possible way is once one of the branges been merged, update another one and recalculate digests in test cases.

Do you have any thoughts on how to workaround this?

Thanks,
Sergei

Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

Vlad,
Some minor comments:

lines 2279-2280 redundant change
likewise 2585
likewise 3023

in have_statement_timeout_basic.test
it has been said that error 'Readonly variable' is expected but what really
is expected is the 'Unknown column 'have_statement_timeout' in 'field list''
error and it is raised as well.

Revision history for this message
Sergei Glushchenko (sergei.glushchenko) :
review: Needs Fixing (g2)
Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

> I see you encountered same issue as I did also. performance_schema *digest*
> tables are rely heavily on sql_yacc.yy grammar. So if someone just add new
> token (or even rule?) many of statement's digests will change.
...
> Do you have any thoughts on how to workaround this?

Digest calculation is based on token IDs. So every time we add new token in the middle of tokens list we just shift token IDs that are after just inserted token. So I see two variants how to avoid that. The first is add new tokens at the end of the list. The second - calculate digest using text representation of query instead of set of tokens.

Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

First option obviously wouldn't work because there are additional PFS-specific tokens which are generated automatically (in gen_pfs_lex_token.cc) with IDs starting from max last token seen.

Maybe it isn't that bad to update test cases with new digests. I just wondering why that method of digest calculation has been chosen. Probably nobody should refer to digests in their scripts/applications/etc, and they are needed only for internal purposes.

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

> Vlad,
> Some minor comments:
>
> lines 2279-2280 redundant change
> likewise 2585
> likewise 3023
>
> in have_statement_timeout_basic.test
> it has been said that error 'Readonly variable' is expected but what really
> is expected is the 'Unknown column 'have_statement_timeout' in 'field list''
> error and it is raised as well.

Fixed.

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

> Maybe it isn't that bad to update test cases with new digests. I just
> wondering why that method of digest calculation has been chosen. Probably
> nobody should refer to digests in their scripts/applications/etc, and they are
> needed only for internal purposes.

It can lead to issues during merging. If several people make MP with updated tests merge captain should update that test results manually. But I think we can do nothing with it. We can't make rules for test scripts as we work with upstream code.

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Vlad,

  - do we really need the following change?

-#if !defined(__cplusplus) && !defined(bool)
-#define bool In_C_you_should_use_my_bool_instead()
-#endif
+#include <stdbool.h>

    The intention was to allow using C99 'bool' in C code (and break
    Windows compatibility), but I don't see any occurrences of such
    usage?

  - my_os_timer_* to avoid name clash with existing my_timer_init()

  - I'm having second thoughts on per-user MAX_STATEMENT_TIME limit
    after reviewing the code. It feels like it's going to be a pain to
    support and maintain. Let's remove it? It's a "nice to have" thing, but
    it was not a requirement for us originally, and would also
    unproportionally complicate migrations to/from upstream MySQL.

  - was there any specific reason to implement your own set of
    regression tests instead of porting them from the Twitter tree? Most
    of their tests use the SELECT hint that we chose not to implement,
    but those could be converted to SET ...; SELECT ... form.

  - include my_global.h and use DBUG_ASSERT() instead of assert()? Also
    don't include assert.h, errno.h and string.h?

  - unnecessary change:

@@ -4254,6 +4284,7 @@ static int replace_column_table(GRANT_TA
         goto end;
       }
     }
+
   }

   /*

  - remnant from SELECT hints implementation that is also unnecessary:

--- Percona-Server/sql/sql_lex.h 2013-06-27 15:15:35 +0000
+++ Percona-Server/sql/sql_lex.h 2013-08-06 11:40:36 +0000
@@ -2533,6 +2533,9 @@ struct LEX: public Query_tables_list

   class Explain_format *explain_format;

+ /** Maximum execution time for a statement. */
+ ulong max_statement_time;
+
   LEX();

   virtual ~LEX()

  - I would restructure get_max_statement_time() / set_statement_timer()
    a bit for performance reasons. We should first check if we do have
    some timeout defined (i.e. thd->variables.max_statement_time > 0)
    and then check other conditions. So that we do as less work as
    possible when timeouts are not used. likely()/unlikely() and
    explicit "inline" hints can also make a big difference.

  - can you explain changed in ha_innodb.cc? It looks like fixing a
    problem in the wrong place, i.e. implementing a workaround of
    thread_pool_priv.h defining MYSQL_SERVER unconditionally.

  - innobase_kill_connection() needs comments

review: Needs Fixing
Revision history for this message
Vlad Lesin (vlad-lesin) wrote :
Download full text (3.2 KiB)

> Vlad,
>
> - do we really need the following change?
>
> -#if !defined(__cplusplus) && !defined(bool)
> -#define bool In_C_you_should_use_my_bool_instead()
> -#endif
> +#include <stdbool.h>
>
> The intention was to allow using C99 'bool' in C code (and break
> Windows compatibility), but I don't see any occurrences of such
> usage?
>
Removed.

> - my_os_timer_* to avoid name clash with existing my_timer_init()
>
Done.

> - I'm having second thoughts on per-user MAX_STATEMENT_TIME limit
> after reviewing the code. It feels like it's going to be a pain to
> support and maintain. Let's remove it? It's a "nice to have" thing, but
> it was not a requirement for us originally, and would also
> unproportionally complicate migrations to/from upstream MySQL.
>
Removed.

> - was there any specific reason to implement your own set of
> regression tests instead of porting them from the Twitter tree? Most
> of their tests use the SELECT hint that we chose not to implement,
> but those could be converted to SET ...; SELECT ... form.
All tests are ported from Twitter tree except these two:
mysql-test/suite/randgen/t/max_statement_time.test
mysql-test/t/max_statement_time.test

The first one is not ported because I did not find randgen grammar files for the test
in the tree. The second one repeats the mysql-test/t/max_statement_time_func.test test
but uses statement timeout set instead of set with variable.

>
> - include my_global.h and use DBUG_ASSERT() instead of assert()? Also
> don't include assert.h, errno.h and string.h?
As we do not support BSD-based platforms and do not test code for such platforms with our
regression tests system the BSD-based platform specific files are kept as is.

> - unnecessary change:
>
> @@ -4254,6 +4284,7 @@ static int replace_column_table(GRANT_TA
> goto end;
> }
> }
> +
> }
>
> /*
>
> - remnant from SELECT hints implementation that is also unnecessary:
>
> --- Percona-Server/sql/sql_lex.h 2013-06-27 15:15:35 +0000
> +++ Percona-Server/sql/sql_lex.h 2013-08-06 11:40:36 +0000
> @@ -2533,6 +2533,9 @@ struct LEX: public Query_tables_list
>
> class Explain_format *explain_format;
>
> + /** Maximum execution time for a statement. */
> + ulong max_statement_time;
> +
> LEX();
>
> virtual ~LEX()
>
As per-user MAX_STATEMENT_TIME limit code is removed the above changes are removed too.

> - I would restructure get_max_statement_time() / set_statement_timer()
> a bit for performance reasons. We should first check if we do have
> some timeout defined (i.e. thd->variables.max_statement_time > 0)
> and then check other conditions. So that we do as less work as
> possible when timeouts are not used. likely()/unlikely() and
> explicit "inline" hints can also make a big difference.
>
Done.

> - can you explain changed in ha_innodb.cc? It looks like fixing a
> problem in the wrong place, i.e. implementing a workaround of
> thread_pool_priv.h defining MYSQL_SERVER unconditionally.
Made conditional #define in thread_pool_priv.h

> - innobase_kill_connection() needs comments
Done.

h...

Read more...

Revision history for this message
Alexey Kopytov (akopytov) :
review: Approve
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Percona-Server/config.h.cmake'
--- Percona-Server/config.h.cmake 2013-06-20 15:16:00 +0000
+++ Percona-Server/config.h.cmake 2013-09-09 15:30:42 +0000
@@ -306,6 +306,10 @@
306#cmakedefine STRUCT_DIRENT_HAS_D_NAMLEN 1306#cmakedefine STRUCT_DIRENT_HAS_D_NAMLEN 1
307#cmakedefine SPRINTF_RETURNS_INT 1307#cmakedefine SPRINTF_RETURNS_INT 1
308308
309#cmakedefine HAVE_POSIX_TIMERS 1
310#cmakedefine HAVE_KQUEUE_TIMERS 1
311#cmakedefine HAVE_MY_TIMER 1
312
309#cmakedefine DNS_USE_CPU_CLOCK_FOR_ID 1313#cmakedefine DNS_USE_CPU_CLOCK_FOR_ID 1
310#cmakedefine HAVE_EPOLL 1314#cmakedefine HAVE_EPOLL 1
311#cmakedefine HAVE_EPOLL_CTL 1315#cmakedefine HAVE_EPOLL_CTL 1
312316
=== modified file 'Percona-Server/configure.cmake'
--- Percona-Server/configure.cmake 2013-08-14 03:57:21 +0000
+++ Percona-Server/configure.cmake 2013-09-09 15:30:42 +0000
@@ -197,6 +197,7 @@
197 IF(NOT LIBRT)197 IF(NOT LIBRT)
198 MY_SEARCH_LIBS(clock_gettime rt LIBRT)198 MY_SEARCH_LIBS(clock_gettime rt LIBRT)
199 ENDIF()199 ENDIF()
200 MY_SEARCH_LIBS(timer_create rt LIBRT)
200 FIND_PACKAGE(Threads)201 FIND_PACKAGE(Threads)
201202
202 SET(CMAKE_REQUIRED_LIBRARIES 203 SET(CMAKE_REQUIRED_LIBRARIES
@@ -523,6 +524,10 @@
523CHECK_FUNCTION_EXISTS (nl_langinfo HAVE_NL_LANGINFO)524CHECK_FUNCTION_EXISTS (nl_langinfo HAVE_NL_LANGINFO)
524CHECK_FUNCTION_EXISTS (ntohll HAVE_HTONLL)525CHECK_FUNCTION_EXISTS (ntohll HAVE_HTONLL)
525526
527CHECK_FUNCTION_EXISTS (timer_create HAVE_TIMER_CREATE)
528CHECK_FUNCTION_EXISTS (timer_settime HAVE_TIMER_SETTIME)
529CHECK_FUNCTION_EXISTS (kqueue HAVE_KQUEUE)
530
526CHECK_FUNCTION_EXISTS (clock_gettime DNS_USE_CPU_CLOCK_FOR_ID)531CHECK_FUNCTION_EXISTS (clock_gettime DNS_USE_CPU_CLOCK_FOR_ID)
527CHECK_FUNCTION_EXISTS (epoll_create HAVE_EPOLL)532CHECK_FUNCTION_EXISTS (epoll_create HAVE_EPOLL)
528CHECK_FUNCTION_EXISTS (epoll_ctl HAVE_EPOLL_CTL)533CHECK_FUNCTION_EXISTS (epoll_ctl HAVE_EPOLL_CTL)
@@ -579,6 +584,8 @@
579CHECK_SYMBOL_EXISTS(TIOCSTAT "sys/ioctl.h" TIOCSTAT_IN_SYS_IOCTL)584CHECK_SYMBOL_EXISTS(TIOCSTAT "sys/ioctl.h" TIOCSTAT_IN_SYS_IOCTL)
580CHECK_SYMBOL_EXISTS(FIONREAD "sys/filio.h" FIONREAD_IN_SYS_FILIO)585CHECK_SYMBOL_EXISTS(FIONREAD "sys/filio.h" FIONREAD_IN_SYS_FILIO)
581CHECK_SYMBOL_EXISTS(gettimeofday "sys/time.h" HAVE_GETTIMEOFDAY)586CHECK_SYMBOL_EXISTS(gettimeofday "sys/time.h" HAVE_GETTIMEOFDAY)
587CHECK_SYMBOL_EXISTS(SIGEV_THREAD_ID "signal.h;time.h" HAVE_SIGEV_THREAD_ID)
588CHECK_SYMBOL_EXISTS(EVFILT_TIMER "sys/types.h;sys/event.h;sys/time.h" HAVE_EVFILT_TIMER)
582589
583CHECK_SYMBOL_EXISTS(finite "math.h" HAVE_FINITE_IN_MATH_H)590CHECK_SYMBOL_EXISTS(finite "math.h" HAVE_FINITE_IN_MATH_H)
584IF(HAVE_FINITE_IN_MATH_H)591IF(HAVE_FINITE_IN_MATH_H)
@@ -607,7 +614,18 @@
607 return 0;614 return 0;
608}" HAVE_FESETROUND)615}" HAVE_FESETROUND)
609616
610617# Check for the Linux-specific POSIX timers API.
618IF(HAVE_TIMER_CREATE AND HAVE_TIMER_SETTIME AND HAVE_SIGEV_THREAD_ID)
619 SET(HAVE_POSIX_TIMERS 1 CACHE INTERNAL "Have POSIX timer-related functions")
620ENDIF()
621
622IF(HAVE_KQUEUE AND HAVE_EVFILT_TIMER)
623 SET(HAVE_KQUEUE_TIMERS 1 CACHE INTERNAL "Have kqueue timer-related filter")
624ENDIF()
625
626IF(HAVE_POSIX_TIMERS OR HAVE_KQUEUE_TIMERS)
627 SET(HAVE_MY_TIMER 1 CACHE INTERNAL "Have mysys timer-related functions")
628ENDIF()
611629
612#630#
613# Test for endianess631# Test for endianess
614632
=== modified file 'Percona-Server/include/my_global.h'
--- Percona-Server/include/my_global.h 2013-06-26 14:15:01 +0000
+++ Percona-Server/include/my_global.h 2013-09-09 15:30:42 +0000
@@ -363,6 +363,19 @@
363#include <crypt.h>363#include <crypt.h>
364#endif364#endif
365365
366/**
367 Cast a member of a structure to the structure that contains it.
368
369 @param ptr Pointer to the member.
370 @param type Type of the structure that contains the member.
371 @param member Name of the member within the structure.
372*/
373#define my_container_of(ptr, type, member) \
374 ({ \
375 const typeof(((type *)0)->member) *__mptr= (ptr); \
376 (type *)((char *)__mptr - offsetof(type, member)); \
377 })
378
366/*379/*
367 A lot of our programs uses asserts, so better to always include it380 A lot of our programs uses asserts, so better to always include it
368 This also fixes a problem when people uses DBUG_ASSERT without including381 This also fixes a problem when people uses DBUG_ASSERT without including
369382
=== added file 'Percona-Server/include/my_timer.h'
--- Percona-Server/include/my_timer.h 1970-01-01 00:00:00 +0000
+++ Percona-Server/include/my_timer.h 2013-09-09 15:30:42 +0000
@@ -0,0 +1,69 @@
1/* Copyright (c) 2012, Twitter, Inc. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License along
13 with this program; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
15
16#ifndef MY_TIMER_H
17#define MY_TIMER_H
18
19#include "my_global.h" /* C_MODE_START, C_MODE_END */
20#include "my_config.h" /* HAVE_*_TIMERS */
21
22/* POSIX timers API. */
23#ifdef HAVE_POSIX_TIMERS
24# include <time.h> /* timer_t */
25 typedef timer_t os_timer_t;
26#elif HAVE_KQUEUE_TIMERS
27# include <sys/types.h> /* uintptr_t */
28 typedef uintptr_t os_timer_t;
29#endif
30
31/* Whether timer API is implemented. */
32#ifdef HAVE_MY_TIMER
33
34C_MODE_START
35
36typedef struct st_my_timer my_timer_t;
37
38/** Non-copyable timer object. */
39struct st_my_timer
40{
41 /** Timer ID used to identify the timer in timer requests. */
42 os_timer_t id;
43
44 /** Timer expiration notification function. */
45 void (*notify_function)(my_timer_t *);
46};
47
48/* Initialize internal components. */
49int my_os_timer_init_ext(void);
50
51/* Release any resources acquired. */
52void my_os_timer_deinit(void);
53
54/* Create a timer object. */
55int my_os_timer_create(my_timer_t *timer);
56
57/* Set the time (in milliseconds) until the next expiration of the timer. */
58int my_os_timer_set(my_timer_t *timer, unsigned long time);
59
60/* Reset the time until the next expiration of the timer. */
61int my_os_timer_reset(my_timer_t *timer, int *state);
62
63/* Delete a timer object. */
64void my_os_timer_delete(my_timer_t *timer);
65
66C_MODE_END
67
68#endif /* HAVE_MY_TIMER */
69#endif /* MY_TIMER_H */
070
=== modified file 'Percona-Server/include/mysql/plugin.h'
--- Percona-Server/include/mysql/plugin.h 2013-08-06 15:16:34 +0000
+++ Percona-Server/include/mysql/plugin.h 2013-09-09 15:30:42 +0000
@@ -627,6 +627,13 @@
627 unsigned long long *pos_var);627 unsigned long long *pos_var);
628628
629/**629/**
630 Set the killed status of the current statement.
631
632 @param thd user thread connection handle
633*/
634void thd_set_kill_status(const MYSQL_THD thd);
635
636/**
630 Return the thread id of a user thread637 Return the thread id of a user thread
631638
632 @param thd user thread connection handle639 @param thd user thread connection handle
633640
=== modified file 'Percona-Server/include/mysql/plugin_audit.h.pp'
--- Percona-Server/include/mysql/plugin_audit.h.pp 2013-05-12 06:24:46 +0000
+++ Percona-Server/include/mysql/plugin_audit.h.pp 2013-09-09 15:30:42 +0000
@@ -249,6 +249,7 @@
249void thd_binlog_pos(const void* thd,249void thd_binlog_pos(const void* thd,
250 const char **file_var,250 const char **file_var,
251 unsigned long long *pos_var);251 unsigned long long *pos_var);
252void thd_set_kill_status(const void* thd);
252unsigned long thd_get_thread_id(const void* thd);253unsigned long thd_get_thread_id(const void* thd);
253void thd_get_xid(const void* thd, MYSQL_XID *xid);254void thd_get_xid(const void* thd, MYSQL_XID *xid);
254void mysql_query_cache_invalidate4(void* thd,255void mysql_query_cache_invalidate4(void* thd,
255256
=== modified file 'Percona-Server/include/mysql/plugin_auth.h.pp'
--- Percona-Server/include/mysql/plugin_auth.h.pp 2013-05-12 06:24:46 +0000
+++ Percona-Server/include/mysql/plugin_auth.h.pp 2013-09-09 15:30:42 +0000
@@ -249,6 +249,7 @@
249void thd_binlog_pos(const void* thd,249void thd_binlog_pos(const void* thd,
250 const char **file_var,250 const char **file_var,
251 unsigned long long *pos_var);251 unsigned long long *pos_var);
252void thd_set_kill_status(const void* thd);
252unsigned long thd_get_thread_id(const void* thd);253unsigned long thd_get_thread_id(const void* thd);
253void thd_get_xid(const void* thd, MYSQL_XID *xid);254void thd_get_xid(const void* thd, MYSQL_XID *xid);
254void mysql_query_cache_invalidate4(void* thd,255void mysql_query_cache_invalidate4(void* thd,
255256
=== modified file 'Percona-Server/include/mysql/plugin_ftparser.h.pp'
--- Percona-Server/include/mysql/plugin_ftparser.h.pp 2013-05-12 06:24:46 +0000
+++ Percona-Server/include/mysql/plugin_ftparser.h.pp 2013-09-09 15:30:42 +0000
@@ -202,6 +202,7 @@
202void thd_binlog_pos(const void* thd,202void thd_binlog_pos(const void* thd,
203 const char **file_var,203 const char **file_var,
204 unsigned long long *pos_var);204 unsigned long long *pos_var);
205void thd_set_kill_status(const void* thd);
205unsigned long thd_get_thread_id(const void* thd);206unsigned long thd_get_thread_id(const void* thd);
206void thd_get_xid(const void* thd, MYSQL_XID *xid);207void thd_get_xid(const void* thd, MYSQL_XID *xid);
207void mysql_query_cache_invalidate4(void* thd,208void mysql_query_cache_invalidate4(void* thd,
208209
=== modified file 'Percona-Server/include/mysql/thread_pool_priv.h'
--- Percona-Server/include/mysql/thread_pool_priv.h 2013-05-12 06:24:46 +0000
+++ Percona-Server/include/mysql/thread_pool_priv.h 2013-09-09 15:30:42 +0000
@@ -30,7 +30,13 @@
30 to include sql_profile.h and table.h.30 to include sql_profile.h and table.h.
31*/31*/
32#include <mysqld_error.h> /* To get ER_ERROR_ON_READ */32#include <mysqld_error.h> /* To get ER_ERROR_ON_READ */
33/*
34 MYSQL_SERVER can be defined before including this header, check it to avoid
35 compilation error.
36*/
37#ifndef MYSQL_SERVER
33#define MYSQL_SERVER 138#define MYSQL_SERVER 1
39#endif //MYSQL_SERVER
34#include <scheduler.h>40#include <scheduler.h>
35#include <debug_sync.h>41#include <debug_sync.h>
36#include <sql_profile.h>42#include <sql_profile.h>
3743
=== modified file 'Percona-Server/libmysqld/CMakeLists.txt'
--- Percona-Server/libmysqld/CMakeLists.txt 2012-10-16 06:21:51 +0000
+++ Percona-Server/libmysqld/CMakeLists.txt 2013-09-09 15:30:42 +0000
@@ -78,6 +78,9 @@
78 ${IMPORTED_SOURCES}78 ${IMPORTED_SOURCES}
79)79)
8080
81IF(HAVE_MY_TIMER)
82 SET(SQL_EMBEDDED_SOURCES ${SQL_EMBEDDED_SOURCES} ../sql/sql_timer.cc)
83ENDIF()
8184
82ADD_CONVENIENCE_LIBRARY(sql_embedded ${SQL_EMBEDDED_SOURCES})85ADD_CONVENIENCE_LIBRARY(sql_embedded ${SQL_EMBEDDED_SOURCES})
83DTRACE_INSTRUMENT(sql_embedded)86DTRACE_INSTRUMENT(sql_embedded)
8487
=== added file 'Percona-Server/mysql-test/include/have_statement_timeout.inc'
--- Percona-Server/mysql-test/include/have_statement_timeout.inc 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/include/have_statement_timeout.inc 2013-09-09 15:30:42 +0000
@@ -0,0 +1,4 @@
1-- require r/have_statement_timeout.require
2disable_query_log;
3show variables like 'have_statement_timeout';
4enable_query_log;
05
=== added file 'Percona-Server/mysql-test/r/have_statement_timeout.require'
--- Percona-Server/mysql-test/r/have_statement_timeout.require 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/r/have_statement_timeout.require 2013-09-09 15:30:42 +0000
@@ -0,0 +1,2 @@
1Variable_name Value
2have_statement_timeout YES
03
=== added file 'Percona-Server/mysql-test/r/max_statement_time_func.result'
--- Percona-Server/mysql-test/r/max_statement_time_func.result 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/r/max_statement_time_func.result 2013-09-09 15:30:42 +0000
@@ -0,0 +1,116 @@
1SET @old_session_max_statement_time = @@SESSION.max_statement_time;
2#
3# Test max statement time interruption.
4# Note that if SLEEP() is interrupted, it returns 1.
5#
6SET @@SESSION.max_statement_time = 10;
7SELECT SLEEP(1000);
8SLEEP(1000)
91
10SET @@SESSION.max_statement_time = 0;
11#
12# Apply timeout to the top-level statement.
13#
14CREATE PROCEDURE p1()
15BEGIN
16SELECT SLEEP(1000);
17END|
18SET @@SESSION.max_statement_time = 10;
19CALL p1();
20SLEEP(1000)
211
22SET @@SESSION.max_statement_time = 0;
23# Apply timeout to prepared statements.
24PREPARE prep_1 FROM 'call p1()';
25SET @@SESSION.max_statement_time = 10;
26EXECUTE prep_1;
27SLEEP(1000)
281
29SET @@SESSION.max_statement_time = 0;
30DROP PREPARE prep_1;
31DROP PROCEDURE p1;
32#
33# Interrupt a statement that changes data.
34#
35CREATE TABLE t1 (a INT);
36CREATE FUNCTION f1() RETURNS INT
37BEGIN
38WHILE true DO
39INSERT INTO t1 VALUES (1);
40END WHILE;
41RETURN 1;
42END|
43SET @@SESSION.max_statement_time = 500;
44SELECT f1();
45ERROR 70101: Query execution was interrupted, max_statement_time exceeded
46SET @@SESSION.max_statement_time = 0;
47DROP FUNCTION f1;
48DROP TABLE t1;
49SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_set
50FROM INFORMATION_SCHEMA.GLOBAL_STATUS
51WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_SET';
52SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_exceeded
53FROM INFORMATION_SCHEMA.GLOBAL_STATUS
54WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_EXCEEDED';
55SET @@SESSION.max_statement_time = 100;
56SELECT SLEEP(1000);
57SLEEP(1000)
581
59# Ensure that the counters for:
60# - statements that are time limited; and
61# - statements that exceeded their maximum execution time
62# are incremented.
63SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS
64WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_SET'
65 AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_set;
66STATUS
67SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS
68WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_EXCEEDED'
69 AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_exceeded;
70STATUS
71SET @@SESSION.max_statement_time = default;
72
73# Check that the appropriate error status is set.
74
75CREATE TABLE t1 (a INT) ENGINE=InnoDB;
76INSERT INTO t1 VALUES (1);
77START TRANSACTION;
78SELECT * FROM t1 FOR UPDATE;
79a
801
81SET @@SESSION.max_statement_time = 100;
82UPDATE t1 SET a = 2;
83ERROR 70101: Query execution was interrupted, max_statement_time exceeded
84SHOW WARNINGS;
85Level Code Message
86Error 1877 Query execution was interrupted, max_statement_time exceeded
87ROLLBACK;
88DROP TABLE t1;
89#
90# Test interaction with lock waits.
91#
92CREATE TABLE t1 (a INT) ENGINE=InnoDB;
93INSERT INTO t1 VALUES (1);
94SET @@SESSION.max_statement_time = 500;
95LOCK TABLES t1 WRITE;
96LOCK TABLES t1 READ;
97ERROR 70101: Query execution was interrupted, max_statement_time exceeded
98UNLOCK TABLES;
99BEGIN;
100SELECT * FROM t1;
101a
1021
103ALTER TABLE t1 ADD COLUMN b INT;
104ERROR 70101: Query execution was interrupted, max_statement_time exceeded
105ROLLBACK;
106SELECT GET_LOCK('lock', 1);
107GET_LOCK('lock', 1)
1081
109SELECT GET_LOCK('lock', 1);
110GET_LOCK('lock', 1)
111NULL
112SELECT RELEASE_LOCK('lock');
113RELEASE_LOCK('lock')
1141
115DROP TABLE t1;
116SET @@SESSION.max_statement_time = @old_session_max_statement_time;
0117
=== modified file 'Percona-Server/mysql-test/r/mysqld--help-notwin.result'
--- Percona-Server/mysql-test/r/mysqld--help-notwin.result 2013-09-09 07:01:33 +0000
+++ Percona-Server/mysql-test/r/mysqld--help-notwin.result 2013-09-09 15:30:42 +0000
@@ -448,6 +448,9 @@
448 value are used; the rest are ignored)448 value are used; the rest are ignored)
449 --max-sp-recursion-depth[=#] 449 --max-sp-recursion-depth[=#]
450 Maximum stored procedure recursion depth450 Maximum stored procedure recursion depth
451 --max-statement-time=#
452 Kill any statement that takes over the specified number
453 of milliseconds
451 --max-tmp-tables=# Maximum number of temporary tables a client can keep open454 --max-tmp-tables=# Maximum number of temporary tables a client can keep open
452 at a time455 at a time
453 --max-user-connections=# 456 --max-user-connections=#
@@ -1209,6 +1212,7 @@
1209max-seeks-for-key 184467440737095516151212max-seeks-for-key 18446744073709551615
1210max-sort-length 10241213max-sort-length 1024
1211max-sp-recursion-depth 01214max-sp-recursion-depth 0
1215max-statement-time 0
1212max-tmp-tables 321216max-tmp-tables 32
1213max-user-connections 01217max-user-connections 0
1214max-write-lock-count 184467440737095516151218max-write-lock-count 18446744073709551615
12151219
=== modified file 'Percona-Server/mysql-test/r/mysqld--help-win.result'
--- Percona-Server/mysql-test/r/mysqld--help-win.result 2013-09-09 07:01:33 +0000
+++ Percona-Server/mysql-test/r/mysqld--help-win.result 2013-09-09 15:30:42 +0000
@@ -424,6 +424,9 @@
424 value are used; the rest are ignored)424 value are used; the rest are ignored)
425 --max-sp-recursion-depth[=#] 425 --max-sp-recursion-depth[=#]
426 Maximum stored procedure recursion depth426 Maximum stored procedure recursion depth
427 --max-statement-time=#
428 Kill any statement that takes over the specified number
429 of milliseconds
427 --max-tmp-tables=# Maximum number of temporary tables a client can keep open430 --max-tmp-tables=# Maximum number of temporary tables a client can keep open
428 at a time431 at a time
429 --max-user-connections=# 432 --max-user-connections=#
@@ -1155,6 +1158,7 @@
1155max-seeks-for-key 184467440737095516151158max-seeks-for-key 18446744073709551615
1156max-sort-length 10241159max-sort-length 1024
1157max-sp-recursion-depth 01160max-sp-recursion-depth 0
1161max-statement-time 0
1158max-tmp-tables 321162max-tmp-tables 32
1159max-user-connections 01163max-user-connections 0
1160max-write-lock-count 184467440737095516151164max-write-lock-count 18446744073709551615
11611165
=== added file 'Percona-Server/mysql-test/suite/sys_vars/r/have_statement_timeout_basic.result'
--- Percona-Server/mysql-test/suite/sys_vars/r/have_statement_timeout_basic.result 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/suite/sys_vars/r/have_statement_timeout_basic.result 2013-09-09 15:30:42 +0000
@@ -0,0 +1,53 @@
1# Displaying default value
2SELECT COUNT(@@GLOBAL.have_statement_timeout);
3COUNT(@@GLOBAL.have_statement_timeout)
41
51 Expected
6# Check if Value can set
7SET @@GLOBAL.have_statement_timeout=1;
8ERROR HY000: Variable 'have_statement_timeout' is a read only variable
9Expected error 'Read only variable'
10SELECT COUNT(@@GLOBAL.have_statement_timeout);
11COUNT(@@GLOBAL.have_statement_timeout)
121
131 Expected
14# Check if the value in GLOBAL Table matches value in variable
15SELECT @@GLOBAL.have_statement_timeout = VARIABLE_VALUE
16FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
17WHERE VARIABLE_NAME='have_statement_timeout';
18@@GLOBAL.have_statement_timeout = VARIABLE_VALUE
191
201 Expected
21SELECT COUNT(@@GLOBAL.have_statement_timeout);
22COUNT(@@GLOBAL.have_statement_timeout)
231
241 Expected
25SELECT COUNT(VARIABLE_VALUE)
26FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
27WHERE VARIABLE_NAME='have_statement_timeout';
28COUNT(VARIABLE_VALUE)
291
301 Expected
31# Check if accessing variable with and without GLOBAL point to same variable
32SELECT @@have_statement_timeout = @@GLOBAL.have_statement_timeout;
33@@have_statement_timeout = @@GLOBAL.have_statement_timeout
341
351 Expected
36# Check if have_statement_timeout can be accessed with and without @@ sign
37SELECT COUNT(@@have_statement_timeout);
38COUNT(@@have_statement_timeout)
391
401 Expected
41SELECT COUNT(@@local.have_statement_timeout);
42ERROR HY000: Variable 'have_statement_timeout' is a GLOBAL variable
43Expected error 'Variable is a GLOBAL variable'
44SELECT COUNT(@@SESSION.have_statement_timeout);
45ERROR HY000: Variable 'have_statement_timeout' is a GLOBAL variable
46Expected error 'Variable is a GLOBAL variable'
47SELECT COUNT(@@GLOBAL.have_statement_timeout);
48COUNT(@@GLOBAL.have_statement_timeout)
491
501 Expected
51SELECT have_statement_timeout = @@SESSION.have_statement_timeout;
52ERROR 42S22: Unknown column 'have_statement_timeout' in 'field list'
53Expected error 'Unknown column 'have_statement_timeout' in 'field list''
054
=== added file 'Percona-Server/mysql-test/suite/sys_vars/r/max_statement_time_basic.result'
--- Percona-Server/mysql-test/suite/sys_vars/r/max_statement_time_basic.result 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/suite/sys_vars/r/max_statement_time_basic.result 2013-09-09 15:30:42 +0000
@@ -0,0 +1,89 @@
1# Save initial value
2SET @start_session_value = @@session.max_statement_time;
3SELECT @start_session_value;
4@start_session_value
50
6# Display the DEFAULT value of max_statement_time
7SET @@session.max_statement_time = 20000;
8SET @@session.max_statement_time = DEFAULT;
9SELECT @@session.max_statement_time;
10@@session.max_statement_time
110
12# Check the DEFAULT value of max_statement_time
13SET @@session.max_statement_time = DEFAULT;
14SELECT @@session.max_statement_time = 28800;
15@@session.max_statement_time = 28800
160
17# Change the value of max_statement_time to a valid value for SESSION scope
18SET @@session.max_statement_time = 10000;
19SELECT @@session.max_statement_time;
20@@session.max_statement_time
2110000
22SET @@session.max_statement_time = 50050;
23SELECT @@session.max_statement_time;
24@@session.max_statement_time
2550050
26SET @@session.max_statement_time = 65535;
27SELECT @@session.max_statement_time;
28@@session.max_statement_time
2965535
30# Change the value of max_statement_time to an invalid value #
31SET @@session.max_statement_time = 0;
32SELECT @@session.max_statement_time;
33@@session.max_statement_time
340
35SET @@session.max_statement_time = -2;
36Warnings:
37Warning 1292 Truncated incorrect max_statement_time value: '-2'
38SELECT @@session.max_statement_time;
39@@session.max_statement_time
400
41SET @@session.max_statement_time = 65530.34;
42ERROR 42000: Incorrect argument type to variable 'max_statement_time'
43SET @@session.max_statement_time = 100000000;
44SELECT @@session.max_statement_time;
45@@session.max_statement_time
46100000000
47SET @@session.max_statement_time = test;
48ERROR 42000: Incorrect argument type to variable 'max_statement_time'
49SELECT @@session.max_statement_time;
50@@session.max_statement_time
51100000000
52# Check if the value in SESSION Table matches value in variable
53SELECT @@session.max_statement_time = VARIABLE_VALUE
54FROM INFORMATION_SCHEMA.SESSION_VARIABLES
55WHERE VARIABLE_NAME='max_statement_time';
56@@session.max_statement_time = VARIABLE_VALUE
571
58# Check if TRUE and FALSE values can be used on variable
59SET @@session.max_statement_time = TRUE;
60SELECT @@session.max_statement_time;
61@@session.max_statement_time
621
63SET @@session.max_statement_time = FALSE;
64SELECT @@session.max_statement_time;
65@@session.max_statement_time
660
67# Check if accessing variable with SESSION,LOCAL and without SCOPE points to same session variable
68SET @@max_statement_time = 10000;
69SELECT @@max_statement_time = @@local.max_statement_time;
70@@max_statement_time = @@local.max_statement_time
711
72SELECT @@local.max_statement_time = @@session.max_statement_time;
73@@local.max_statement_time = @@session.max_statement_time
741
75# Check if max_statement_time can be accessed with and without @@ sign
76SET max_statement_time = 10000;
77SELECT @@max_statement_time;
78@@max_statement_time
7910000
80SELECT local.max_statement_time;
81ERROR 42S02: Unknown table 'local' in field list
82SELECT session.max_statement_time;
83ERROR 42S02: Unknown table 'session' in field list
84SET @@global.max_statement_time = 0;
85# Restore initial value
86SET @@session.max_statement_time = @start_session_value;
87SELECT @@session.max_statement_time;
88@@session.max_statement_time
890
090
=== added file 'Percona-Server/mysql-test/suite/sys_vars/t/have_statement_timeout_basic.test'
--- Percona-Server/mysql-test/suite/sys_vars/t/have_statement_timeout_basic.test 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/suite/sys_vars/t/have_statement_timeout_basic.test 2013-09-09 15:30:42 +0000
@@ -0,0 +1,55 @@
1--source include/have_statement_timeout.inc
2
3--echo # Displaying default value
4
5SELECT COUNT(@@GLOBAL.have_statement_timeout);
6--echo 1 Expected
7
8--echo # Check if Value can set
9
10--error ER_INCORRECT_GLOBAL_LOCAL_VAR
11SET @@GLOBAL.have_statement_timeout=1;
12--echo Expected error 'Read only variable'
13
14SELECT COUNT(@@GLOBAL.have_statement_timeout);
15--echo 1 Expected
16
17--echo # Check if the value in GLOBAL Table matches value in variable
18
19SELECT @@GLOBAL.have_statement_timeout = VARIABLE_VALUE
20FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
21WHERE VARIABLE_NAME='have_statement_timeout';
22--echo 1 Expected
23
24SELECT COUNT(@@GLOBAL.have_statement_timeout);
25--echo 1 Expected
26
27SELECT COUNT(VARIABLE_VALUE)
28FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
29WHERE VARIABLE_NAME='have_statement_timeout';
30--echo 1 Expected
31
32--echo # Check if accessing variable with and without GLOBAL point to same variable
33
34SELECT @@have_statement_timeout = @@GLOBAL.have_statement_timeout;
35--echo 1 Expected
36
37--echo # Check if have_statement_timeout can be accessed with and without @@ sign
38
39SELECT COUNT(@@have_statement_timeout);
40--echo 1 Expected
41
42--error ER_INCORRECT_GLOBAL_LOCAL_VAR
43SELECT COUNT(@@local.have_statement_timeout);
44--echo Expected error 'Variable is a GLOBAL variable'
45
46--error ER_INCORRECT_GLOBAL_LOCAL_VAR
47SELECT COUNT(@@SESSION.have_statement_timeout);
48--echo Expected error 'Variable is a GLOBAL variable'
49
50SELECT COUNT(@@GLOBAL.have_statement_timeout);
51--echo 1 Expected
52
53--error ER_BAD_FIELD_ERROR
54SELECT have_statement_timeout = @@SESSION.have_statement_timeout;
55--echo Expected error 'Unknown column 'have_statement_timeout' in 'field list''
056
=== added file 'Percona-Server/mysql-test/suite/sys_vars/t/max_statement_time_basic.test'
--- Percona-Server/mysql-test/suite/sys_vars/t/max_statement_time_basic.test 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/suite/sys_vars/t/max_statement_time_basic.test 2013-09-09 15:30:42 +0000
@@ -0,0 +1,78 @@
1--source include/have_statement_timeout.inc
2
3--echo # Save initial value
4
5SET @start_session_value = @@session.max_statement_time;
6SELECT @start_session_value;
7
8--echo # Display the DEFAULT value of max_statement_time
9
10SET @@session.max_statement_time = 20000;
11SET @@session.max_statement_time = DEFAULT;
12SELECT @@session.max_statement_time;
13
14--echo # Check the DEFAULT value of max_statement_time
15
16SET @@session.max_statement_time = DEFAULT;
17SELECT @@session.max_statement_time = 28800;
18
19--echo # Change the value of max_statement_time to a valid value for SESSION scope
20
21SET @@session.max_statement_time = 10000;
22SELECT @@session.max_statement_time;
23SET @@session.max_statement_time = 50050;
24SELECT @@session.max_statement_time;
25SET @@session.max_statement_time = 65535;
26SELECT @@session.max_statement_time;
27
28--echo # Change the value of max_statement_time to an invalid value #
29
30SET @@session.max_statement_time = 0;
31SELECT @@session.max_statement_time;
32SET @@session.max_statement_time = -2;
33SELECT @@session.max_statement_time;
34--error ER_WRONG_TYPE_FOR_VAR
35SET @@session.max_statement_time = 65530.34;
36SET @@session.max_statement_time = 100000000;
37SELECT @@session.max_statement_time;
38
39--error ER_WRONG_TYPE_FOR_VAR
40SET @@session.max_statement_time = test;
41SELECT @@session.max_statement_time;
42
43--echo # Check if the value in SESSION Table matches value in variable
44
45SELECT @@session.max_statement_time = VARIABLE_VALUE
46FROM INFORMATION_SCHEMA.SESSION_VARIABLES
47WHERE VARIABLE_NAME='max_statement_time';
48
49--echo # Check if TRUE and FALSE values can be used on variable
50
51SET @@session.max_statement_time = TRUE;
52SELECT @@session.max_statement_time;
53SET @@session.max_statement_time = FALSE;
54SELECT @@session.max_statement_time;
55
56--echo # Check if accessing variable with SESSION,LOCAL and without SCOPE points to same session variable
57
58SET @@max_statement_time = 10000;
59SELECT @@max_statement_time = @@local.max_statement_time;
60SELECT @@local.max_statement_time = @@session.max_statement_time;
61
62--echo # Check if max_statement_time can be accessed with and without @@ sign
63
64SET max_statement_time = 10000;
65SELECT @@max_statement_time;
66--error ER_UNKNOWN_TABLE
67SELECT local.max_statement_time;
68--error ER_UNKNOWN_TABLE
69SELECT session.max_statement_time;
70
71#--echo # Check that the variable is a SESSION-only variable
72#--error ER_LOCAL_VARIABLE
73SET @@global.max_statement_time = 0;
74
75--echo # Restore initial value
76
77SET @@session.max_statement_time = @start_session_value;
78SELECT @@session.max_statement_time;
079
=== added file 'Percona-Server/mysql-test/t/max_statement_time_func.test'
--- Percona-Server/mysql-test/t/max_statement_time_func.test 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/t/max_statement_time_func.test 2013-09-09 15:30:42 +0000
@@ -0,0 +1,154 @@
1--source include/have_statement_timeout.inc
2--source include/not_embedded.inc
3--source include/have_innodb.inc
4
5SET @old_session_max_statement_time = @@SESSION.max_statement_time;
6
7--echo #
8--echo # Test max statement time interruption.
9--echo # Note that if SLEEP() is interrupted, it returns 1.
10--echo #
11
12SET @@SESSION.max_statement_time = 10;
13SELECT SLEEP(1000);
14SET @@SESSION.max_statement_time = 0;
15
16--echo #
17--echo # Apply timeout to the top-level statement.
18--echo #
19
20DELIMITER |;
21
22CREATE PROCEDURE p1()
23BEGIN
24 SELECT SLEEP(1000);
25END|
26
27DELIMITER ;|
28
29SET @@SESSION.max_statement_time = 10;
30CALL p1();
31SET @@SESSION.max_statement_time = 0;
32
33--echo # Apply timeout to prepared statements.
34PREPARE prep_1 FROM 'call p1()';
35SET @@SESSION.max_statement_time = 10;
36EXECUTE prep_1;
37SET @@SESSION.max_statement_time = 0;
38
39DROP PREPARE prep_1;
40DROP PROCEDURE p1;
41
42--echo #
43--echo # Interrupt a statement that changes data.
44--echo #
45
46CREATE TABLE t1 (a INT);
47
48DELIMITER |;
49
50CREATE FUNCTION f1() RETURNS INT
51BEGIN
52 WHILE true DO
53 INSERT INTO t1 VALUES (1);
54 END WHILE;
55 RETURN 1;
56END|
57
58DELIMITER ;|
59
60SET @@SESSION.max_statement_time = 500;
61--error ER_QUERY_TIMEOUT
62SELECT f1();
63SET @@SESSION.max_statement_time = 0;
64
65DROP FUNCTION f1;
66DROP TABLE t1;
67
68SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_set
69 FROM INFORMATION_SCHEMA.GLOBAL_STATUS
70 WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_SET';
71
72SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_exceeded
73 FROM INFORMATION_SCHEMA.GLOBAL_STATUS
74 WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_EXCEEDED';
75
76SET @@SESSION.max_statement_time = 100;
77SELECT SLEEP(1000);
78
79--echo # Ensure that the counters for:
80--echo # - statements that are time limited; and
81--echo # - statements that exceeded their maximum execution time
82--echo # are incremented.
83
84SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS
85 WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_SET'
86 AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_set;
87
88SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS
89 WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_EXCEEDED'
90 AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_exceeded;
91
92SET @@SESSION.max_statement_time = default;
93
94--echo
95--echo # Check that the appropriate error status is set.
96--echo
97
98CREATE TABLE t1 (a INT) ENGINE=InnoDB;
99INSERT INTO t1 VALUES (1);
100
101START TRANSACTION;
102SELECT * FROM t1 FOR UPDATE;
103
104connect (con1,localhost,root,,test,,);
105SET @@SESSION.max_statement_time = 100;
106--error ER_QUERY_TIMEOUT
107UPDATE t1 SET a = 2;
108SHOW WARNINGS;
109disconnect con1;
110
111connection default;
112ROLLBACK;
113
114DROP TABLE t1;
115
116
117--echo #
118--echo # Test interaction with lock waits.
119--echo #
120
121CREATE TABLE t1 (a INT) ENGINE=InnoDB;
122INSERT INTO t1 VALUES (1);
123
124connect (con1,localhost,root,,test,,);
125SET @@SESSION.max_statement_time = 500;
126
127connection default;
128LOCK TABLES t1 WRITE;
129
130connection con1;
131--error ER_QUERY_TIMEOUT
132LOCK TABLES t1 READ;
133
134connection default;
135UNLOCK TABLES;
136BEGIN;
137SELECT * FROM t1;
138
139connection con1;
140--error ER_QUERY_TIMEOUT
141ALTER TABLE t1 ADD COLUMN b INT;
142
143connection default;
144ROLLBACK;
145SELECT GET_LOCK('lock', 1);
146
147connection con1;
148SELECT GET_LOCK('lock', 1);
149
150disconnect con1;
151connection default;
152SELECT RELEASE_LOCK('lock');
153DROP TABLE t1;
154SET @@SESSION.max_statement_time = @old_session_max_statement_time;
0155
=== modified file 'Percona-Server/mysys/CMakeLists.txt'
--- Percona-Server/mysys/CMakeLists.txt 2013-08-06 15:16:34 +0000
+++ Percona-Server/mysys/CMakeLists.txt 2013-09-09 15:30:42 +0000
@@ -45,6 +45,14 @@
45 SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_alarm.c)45 SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_alarm.c)
46ENDIF()46ENDIF()
4747
48IF(HAVE_POSIX_TIMERS)
49 SET(MYSYS_SOURCES ${MYSYS_SOURCES} posix_timers.c)
50ENDIF()
51
52IF(HAVE_KQUEUE_TIMERS)
53 SET(MYSYS_SOURCES ${MYSYS_SOURCES} kqueue_timers.c)
54ENDIF()
55
48IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_C_COMPILER_ID MATCHES "SunPro")56IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_C_COMPILER_ID MATCHES "SunPro")
49 # Inline assembly template for rdtsc57 # Inline assembly template for rdtsc
50 SET_SOURCE_FILES_PROPERTIES(my_rdtsc.c58 SET_SOURCE_FILES_PROPERTIES(my_rdtsc.c
5159
=== added file 'Percona-Server/mysys/kqueue_timers.c'
--- Percona-Server/mysys/kqueue_timers.c 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysys/kqueue_timers.c 2013-09-09 15:30:42 +0000
@@ -0,0 +1,219 @@
1/* Copyright (c) 2012, Twitter, Inc. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License along
13 with this program; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
15
16#include "my_timer.h" /* my_timer_t */
17#include "my_pthread.h" /* my_thread_init, my_thread_end */
18
19#include <sys/types.h>
20#include <sys/event.h>
21#include <sys/time.h>
22#include <assert.h>
23#include <errno.h>
24
25static int kq_fd= -1;
26static pthread_t thread;
27
28/**
29 Timer expiration notification thread.
30
31 @param arg Unused.
32*/
33
34static void *
35timer_notify_thread(void *arg __attribute__((unused)))
36{
37 my_timer_t *timer;
38 struct kevent kev;
39
40 my_thread_init();
41
42 while (1)
43 {
44 if (kevent(kq_fd, NULL, 0, &kev, 1, NULL) < 0)
45 continue;
46
47 if (kev.filter == EVFILT_TIMER)
48 {
49 timer= kev.udata;
50 assert(timer->id == kev.ident);
51 timer->notify_function(timer);
52 }
53 else if (kev.filter == EVFILT_USER)
54 break;
55 }
56
57 my_thread_end();
58
59 return NULL;
60}
61
62
63/**
64 Create a helper thread to dispatch timer expiration notifications.
65
66 @return On success, 0. On error, -1 is returned.
67*/
68
69static int
70start_helper_thread(void)
71{
72 struct kevent kev;
73
74 EV_SET(&kev, 0, EVFILT_USER, EV_ADD, 0, 0, 0);
75
76 if (kevent(kq_fd, &kev, 1, NULL, 0, NULL) < 0)
77 return -1;
78
79 return pthread_create(&thread, NULL, timer_notify_thread, NULL);
80}
81
82
83/**
84 Initialize internal components.
85
86 @return On success, 0.
87 On error, -1 is returned, and errno is set to indicate the error.
88*/
89
90int
91my_os_timer_init_ext(void)
92{
93 int rc;
94
95 /* Create a file descriptor for event notification. */
96 if ((kq_fd= kqueue()) < 0)
97 return -1;
98
99 /* Create a helper thread. */
100 if ((rc= start_helper_thread()))
101 close(kq_fd);
102
103 return rc;
104}
105
106
107/**
108 Release any resources that were allocated as part of initialization.
109*/
110
111void
112my_os_timer_deinit(void)
113{
114 struct kevent kev;
115
116 EV_SET(&kev, 0, EVFILT_USER, 0, NOTE_TRIGGER, 0, 0);
117
118 /* There's not much to do if triggering the event fails. */
119 if (kevent(kq_fd, &kev, 1, NULL, 0, NULL) > -1)
120 pthread_join(thread, NULL);
121
122 close(kq_fd);
123}
124
125
126/**
127 Create a timer object.
128
129 @param timer Timer object.
130
131 @return On success, 0.
132 On error, -1 is returned, and errno is set to indicate the error.
133*/
134
135int
136my_os_timer_create(my_timer_t *timer)
137{
138 assert(kq_fd >= 0);
139
140 timer->id= (uintptr_t) timer;
141
142 return 0;
143}
144
145
146/**
147 Set the time until the next expiration of the timer.
148
149 @param timer Timer object.
150 @param time Amount of time (in milliseconds) before the timer expires.
151
152 @return On success, 0.
153 On error, -1 is returned, and errno is set to indicate the error.
154*/
155
156int
157my_os_timer_set(my_timer_t *timer, unsigned long time)
158{
159 struct kevent kev;
160
161 EV_SET(&kev, timer->id, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, time, timer);
162
163 return kevent(kq_fd, &kev, 1, NULL, 0, NULL);
164}
165
166
167/**
168 Reset the time until the next expiration of the timer.
169
170 @param timer Timer object.
171 @param state The state of the timer at the time of cancellation, either
172 signaled (false) or nonsignaled (true).
173
174 @return On success, 0.
175 On error, -1 is returned, and errno is set to indicate the error.
176*/
177
178int
179my_os_timer_reset(my_timer_t *timer, int *state)
180{
181 int status;
182 struct kevent kev;
183
184 EV_SET(&kev, timer->id, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
185
186 status= kevent(kq_fd, &kev, 1, NULL, 0, NULL);
187
188 /*
189 If the event was retrieved from the kqueue (at which point we
190 consider it to be signaled), the timer was automatically deleted.
191 */
192 if (!status)
193 *state= 1;
194 else if (errno == ENOENT)
195 {
196 *state= 0;
197 status= 0;
198 }
199
200 return status;
201}
202
203
204/**
205 Delete a timer object.
206
207 @param timer Timer object.
208*/
209
210void
211my_os_timer_delete(my_timer_t *timer)
212{
213 struct kevent kev;
214
215 EV_SET(&kev, timer->id, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
216
217 kevent(kq_fd, &kev, 1, NULL, 0, NULL);
218}
219
0220
=== added file 'Percona-Server/mysys/posix_timers.c'
--- Percona-Server/mysys/posix_timers.c 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysys/posix_timers.c 2013-09-09 15:30:42 +0000
@@ -0,0 +1,256 @@
1/* Copyright (c) 2012, Twitter, Inc. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License along
13 with this program; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
15
16#include "my_timer.h" /* my_timer_t */
17#include "my_pthread.h" /* my_thread_init, my_thread_end */
18#include "m_string.h" /* memset */
19#include <sys/syscall.h> /* SYS_gettid */
20
21#ifndef sigev_notify_thread_id
22#define sigev_notify_thread_id _sigev_un._tid
23#endif
24
25#define MY_TIMER_EVENT_SIGNO (SIGRTMIN)
26#define MY_TIMER_KILL_SIGNO (SIGRTMIN+1)
27
28/* Timer thread object. */
29static pthread_t thread;
30
31/* Timer thread ID (TID). */
32static pid_t thread_id;
33
34/**
35 Timer expiration notification function.
36
37 @param sigev_value Signal (notification) value.
38
39 @remark The notification function is usually run in a helper thread
40 and is called each time the timer expires.
41*/
42
43static void
44timer_notify_function(sigval_t sigev_value)
45{
46 my_timer_t *timer= sigev_value.sival_ptr;
47 timer->notify_function(timer);
48}
49
50
51/**
52 Timer expiration notification thread.
53
54 @param arg Barrier object.
55*/
56
57static void *
58timer_notify_thread(void *arg)
59{
60 sigset_t set;
61 siginfo_t info;
62 pthread_barrier_t *barrier= arg;
63
64 my_thread_init();
65
66 sigemptyset(&set);
67 sigaddset(&set, MY_TIMER_EVENT_SIGNO);
68 sigaddset(&set, MY_TIMER_KILL_SIGNO);
69
70 /* Get the thread ID of the current thread. */
71 thread_id= (pid_t) syscall(SYS_gettid);
72
73 /* Wake up parent thread, thread_id is available. */
74 pthread_barrier_wait(barrier);
75
76 while (1)
77 {
78 if (sigwaitinfo(&set, &info) < 0)
79 continue;
80
81 if (info.si_signo == MY_TIMER_EVENT_SIGNO)
82 timer_notify_function(info.si_value);
83 else if (info.si_signo == MY_TIMER_KILL_SIGNO)
84 break;
85 }
86
87 my_thread_end();
88
89 return NULL;
90}
91
92
93/**
94 Create a helper thread to dispatch timer expiration notifications.
95
96 @return On success, 0. On error, -1 is returned.
97*/
98
99static int
100start_helper_thread(void)
101{
102 pthread_barrier_t barrier;
103
104 if (pthread_barrier_init(&barrier, NULL, 2))
105 return -1;
106
107 if (pthread_create(&thread, NULL, timer_notify_thread, &barrier))
108 return -1;
109
110 pthread_barrier_wait(&barrier);
111 pthread_barrier_destroy(&barrier);
112
113 return 0;
114}
115
116
117/**
118 Initialize internal components.
119
120 @return On success, 0.
121 On error, -1 is returned, and errno is set to indicate the error.
122*/
123
124int
125my_os_timer_init_ext(void)
126{
127 int rc;
128 sigset_t set, old_set;
129
130 if (sigfillset(&set))
131 return -1;
132
133 /*
134 Temporarily block all signals. New thread will inherit signal
135 mask of the current thread.
136 */
137 if (pthread_sigmask(SIG_BLOCK, &set, &old_set))
138 return -1;
139
140 /* Create a helper thread. */
141 rc= start_helper_thread();
142
143 /* Restore the signal mask. */
144 pthread_sigmask(SIG_SETMASK, &old_set, NULL);
145
146 return rc;
147}
148
149
150/**
151 Release any resources that were allocated as part of initialization.
152*/
153
154void
155my_os_timer_deinit(void)
156{
157 /* Kill helper thread. */
158 pthread_kill(thread, MY_TIMER_KILL_SIGNO);
159
160 /* Wait for helper thread termination. */
161 pthread_join(thread, NULL);
162}
163
164
165/**
166 Create a timer object.
167
168 @param timer Location where the timer ID is returned.
169
170 @return On success, 0.
171 On error, -1 is returned, and errno is set to indicate the error.
172*/
173
174int
175my_os_timer_create(my_timer_t *timer)
176{
177 struct sigevent sigev;
178
179 memset(&sigev, 0, sizeof(sigev));
180
181 sigev.sigev_value.sival_ptr= timer;
182 sigev.sigev_signo= MY_TIMER_EVENT_SIGNO;
183 sigev.sigev_notify= SIGEV_SIGNAL | SIGEV_THREAD_ID;
184 sigev.sigev_notify_thread_id= thread_id;
185
186 return timer_create(CLOCK_MONOTONIC, &sigev, &timer->id);
187}
188
189
190/**
191 Set the time until the next expiration of the timer.
192
193 @param timer Timer object.
194 @param time Amount of time (in milliseconds) before the timer expires.
195
196 @return On success, 0.
197 On error, -1 is returned, and errno is set to indicate the error.
198*/
199
200int
201my_os_timer_set(my_timer_t *timer, unsigned long time)
202{
203 const struct itimerspec spec= {
204 .it_interval= {.tv_sec= 0, .tv_nsec= 0},
205 .it_value= {.tv_sec= time / 1000,
206 .tv_nsec= (time % 1000) * 1000000}
207 };
208
209 return timer_settime(timer->id, 0, &spec, NULL);
210}
211
212
213/**
214 Reset the time until the next expiration of the timer.
215
216 @param timer Timer object.
217 @param state The state of the timer at the time of cancellation, either
218 signaled (false) or nonsignaled (true).
219
220 @return On success, 0.
221 On error, -1 is returned, and errno is set to indicate the error.
222*/
223
224int
225my_os_timer_reset(my_timer_t *timer, int *state)
226{
227 int status;
228 struct itimerspec old_spec;
229
230 /* A zeroed initial expiration value disarms the timer. */
231 const struct timespec zero_time= { .tv_sec= 0, .tv_nsec= 0 };
232 const struct itimerspec zero_spec= { .it_value= zero_time };
233
234 /*
235 timer_settime returns the amount of time before the timer
236 would have expired or zero if the timer was disarmed.
237 */
238 if (! (status= timer_settime(timer->id, 0, &zero_spec, &old_spec)))
239 *state= (old_spec.it_value.tv_sec || old_spec.it_value.tv_nsec);
240
241 return status;
242}
243
244
245/**
246 Delete a timer object.
247
248 @param timer Timer object.
249*/
250
251void
252my_os_timer_delete(my_timer_t *timer)
253{
254 timer_delete(timer->id);
255}
256
0257
=== modified file 'Percona-Server/sql/CMakeLists.txt'
--- Percona-Server/sql/CMakeLists.txt 2013-06-25 13:13:06 +0000
+++ Percona-Server/sql/CMakeLists.txt 2013-09-09 15:30:42 +0000
@@ -206,6 +206,10 @@
206 )206 )
207ENDIF()207ENDIF()
208208
209IF(HAVE_MY_TIMER)
210 SET(SQL_SOURCE ${SQL_SOURCE} sql_timer.cc)
211ENDIF()
212
209MYSQL_ADD_PLUGIN(partition ha_partition.cc STORAGE_ENGINE DEFAULT STATIC_ONLY213MYSQL_ADD_PLUGIN(partition ha_partition.cc STORAGE_ENGINE DEFAULT STATIC_ONLY
210RECOMPILE_FOR_EMBEDDED)214RECOMPILE_FOR_EMBEDDED)
211215
212216
=== modified file 'Percona-Server/sql/handler.cc'
--- Percona-Server/sql/handler.cc 2013-08-22 13:38:28 +0000
+++ Percona-Server/sql/handler.cc 2013-09-09 15:30:42 +0000
@@ -887,6 +887,24 @@
887 plugin_foreach(thd, closecon_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0);887 plugin_foreach(thd, closecon_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0);
888}888}
889889
890static my_bool kill_handlerton(THD *thd, plugin_ref plugin, void *)
891{
892 handlerton *hton= plugin_data(plugin, handlerton *);
893
894 if (hton->state == SHOW_OPTION_YES && hton->kill_connection)
895 {
896 if (thd_get_ha_data(thd, hton))
897 hton->kill_connection(hton, thd);
898 }
899
900 return FALSE;
901}
902
903void ha_kill_connection(THD *thd)
904{
905 plugin_foreach(thd, kill_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0);
906}
907
890/* ========================================================================908/* ========================================================================
891 ======================= TRANSACTIONS ===================================*/909 ======================= TRANSACTIONS ===================================*/
892910
893911
=== modified file 'Percona-Server/sql/handler.h'
--- Percona-Server/sql/handler.h 2013-08-22 13:38:28 +0000
+++ Percona-Server/sql/handler.h 2013-09-09 15:30:42 +0000
@@ -908,6 +908,9 @@
908 const char *db, const char *table_name);908 const char *db, const char *table_name);
909 int (*release_temporary_latches)(handlerton *hton, THD *thd);909 int (*release_temporary_latches)(handlerton *hton, THD *thd);
910910
911 /* Terminate connection/statement notification. */
912 void (*kill_connection)(handlerton *hton, THD *thd);
913
911 /*914 /*
912 Get log status.915 Get log status.
913 If log_status is null then the handler do not support transaction916 If log_status is null then the handler do not support transaction
@@ -3399,6 +3402,7 @@
3399TYPELIB* ha_known_exts();3402TYPELIB* ha_known_exts();
3400int ha_panic(enum ha_panic_function flag);3403int ha_panic(enum ha_panic_function flag);
3401void ha_close_connection(THD* thd);3404void ha_close_connection(THD* thd);
3405void ha_kill_connection(THD *thd);
3402bool ha_flush_logs(handlerton *db_type);3406bool ha_flush_logs(handlerton *db_type);
3403void ha_drop_database(char* path);3407void ha_drop_database(char* path);
3404int ha_create_table(THD *thd, const char *path,3408int ha_create_table(THD *thd, const char *path,
34053409
=== modified file 'Percona-Server/sql/mysqld.cc'
--- Percona-Server/sql/mysqld.cc 2013-09-09 07:01:33 +0000
+++ Percona-Server/sql/mysqld.cc 2013-09-09 15:30:42 +0000
@@ -108,6 +108,8 @@
108#include "sp_cache.h"108#include "sp_cache.h"
109#include "sql_reload.h" // reload_acl_and_cache109#include "sql_reload.h" // reload_acl_and_cache
110110
111#include "my_timer.h" // my_os_timer_init_ext, my_os_timer_deinit
112
111#ifdef HAVE_POLL_H113#ifdef HAVE_POLL_H
112#include <poll.h>114#include <poll.h>
113#endif115#endif
@@ -720,6 +722,8 @@
720extern TYPELIB utility_user_privileges_typelib;722extern TYPELIB utility_user_privileges_typelib;
721ulonglong utility_user_privileges= 0;723ulonglong utility_user_privileges= 0;
722724
725SHOW_COMP_OPTION have_statement_timeout= SHOW_OPTION_DISABLED;
726
723/* Thread specific variables */727/* Thread specific variables */
724728
725pthread_key(MEM_ROOT**,THR_MALLOC);729pthread_key(MEM_ROOT**,THR_MALLOC);
@@ -1789,6 +1793,12 @@
17891793
1790 memcached_shutdown();1794 memcached_shutdown();
17911795
1796#ifdef HAVE_MY_TIMER
1797 if (have_statement_timeout == SHOW_OPTION_YES)
1798 my_os_timer_deinit();
1799#endif
1800
1801 have_statement_timeout= SHOW_OPTION_DISABLED;
1792 /*1802 /*
1793 make sure that handlers finish up1803 make sure that handlers finish up
1794 what they have that is dependent on the binlog1804 what they have that is dependent on the binlog
@@ -4584,6 +4594,15 @@
4584 if (table_def_init() | hostname_cache_init())4594 if (table_def_init() | hostname_cache_init())
4585 unireg_abort(1);4595 unireg_abort(1);
45864596
4597#ifdef HAVE_MY_TIMER
4598 if (my_os_timer_init_ext())
4599 sql_print_error("Failed to initialize timer component (errno %d).", errno);
4600 else
4601 have_statement_timeout= SHOW_OPTION_YES;
4602#else
4603 have_statement_timeout= SHOW_OPTION_NO;
4604#endif
4605
4587 query_cache_set_min_res_unit(query_cache_min_res_unit);4606 query_cache_set_min_res_unit(query_cache_min_res_unit);
4588 query_cache_init();4607 query_cache_init();
4589 query_cache_resize(query_cache_size);4608 query_cache_resize(query_cache_size);
@@ -7991,6 +8010,9 @@
7991 {"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},8010 {"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
7992 {"Last_query_partial_plans", (char*) offsetof(STATUS_VAR, last_query_partial_plans), SHOW_LONGLONG_STATUS},8011 {"Last_query_partial_plans", (char*) offsetof(STATUS_VAR, last_query_partial_plans), SHOW_LONGLONG_STATUS},
7993 {"Max_used_connections", (char*) &max_used_connections, SHOW_LONG},8012 {"Max_used_connections", (char*) &max_used_connections, SHOW_LONG},
8013 {"Max_statement_time_exceeded", (char*) offsetof(STATUS_VAR, max_statement_time_exceeded), SHOW_LONG_STATUS},
8014 {"Max_statement_time_set", (char*) offsetof(STATUS_VAR, max_statement_time_set), SHOW_LONG_STATUS},
8015 {"Max_statement_time_set_failed", (char*) offsetof(STATUS_VAR, max_statement_time_set_failed), SHOW_LONG_STATUS},
7994 {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH},8016 {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH},
7995 {"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH},8017 {"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH},
7996 {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_NOFLUSH},8018 {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_NOFLUSH},
79978019
=== modified file 'Percona-Server/sql/set_var.h'
--- Percona-Server/sql/set_var.h 2013-08-14 03:57:21 +0000
+++ Percona-Server/sql/set_var.h 2013-09-09 15:30:42 +0000
@@ -340,6 +340,7 @@
340extern SHOW_COMP_OPTION have_geometry, have_rtree_keys;340extern SHOW_COMP_OPTION have_geometry, have_rtree_keys;
341extern SHOW_COMP_OPTION have_crypt;341extern SHOW_COMP_OPTION have_crypt;
342extern SHOW_COMP_OPTION have_compress;342extern SHOW_COMP_OPTION have_compress;
343extern SHOW_COMP_OPTION have_statement_timeout;
343344
344/*345/*
345 Prototypes for helper functions346 Prototypes for helper functions
346347
=== modified file 'Percona-Server/sql/share/errmsg-utf8.txt'
--- Percona-Server/sql/share/errmsg-utf8.txt 2013-08-06 15:16:34 +0000
+++ Percona-Server/sql/share/errmsg-utf8.txt 2013-09-09 15:30:42 +0000
@@ -7082,6 +7082,9 @@
7082ER_STOP_SLAVE_IO_THREAD_TIMEOUT7082ER_STOP_SLAVE_IO_THREAD_TIMEOUT
7083 eng "STOP SLAVE command execution is incomplete: Slave IO thread got the stop signal, thread is busy, IO thread will stop once the current task is complete."7083 eng "STOP SLAVE command execution is incomplete: Slave IO thread got the stop signal, thread is busy, IO thread will stop once the current task is complete."
70847084
7085ER_QUERY_TIMEOUT 70101
7086 eng "Query execution was interrupted, max_statement_time exceeded"
7087
7085#7088#
7086# End of 5.6 error messages.7089# End of 5.6 error messages.
7087#7090#
70887091
=== modified file 'Percona-Server/sql/signal_handler.cc'
--- Percona-Server/sql/signal_handler.cc 2013-08-14 03:57:21 +0000
+++ Percona-Server/sql/signal_handler.cc 2013-09-09 15:30:42 +0000
@@ -181,6 +181,9 @@
181 case THD::KILL_QUERY:181 case THD::KILL_QUERY:
182 kreason= "KILL_QUERY";182 kreason= "KILL_QUERY";
183 break;183 break;
184 case THD::KILL_TIMEOUT:
185 kreason= "KILL_TIMEOUT";
186 break;
184 case THD::KILLED_NO_VALUE:187 case THD::KILLED_NO_VALUE:
185 kreason= "KILLED_NO_VALUE";188 kreason= "KILLED_NO_VALUE";
186 break;189 break;
187190
=== modified file 'Percona-Server/sql/sql_class.cc'
--- Percona-Server/sql/sql_class.cc 2013-08-14 03:57:21 +0000
+++ Percona-Server/sql/sql_class.cc 2013-09-09 15:30:42 +0000
@@ -66,6 +66,8 @@
66using std::min;66using std::min;
67using std::max;67using std::max;
6868
69#include "sql_timer.h" // thd_timer_end
70
69/*71/*
70 The following is used to initialise Table_ident with a internal72 The following is used to initialise Table_ident with a internal
71 table name73 table name
@@ -764,8 +766,11 @@
764 766
765 @note LOCK_thread_count mutex is not necessary when the function is invoked on767 @note LOCK_thread_count mutex is not necessary when the function is invoked on
766 the currently running thread (current_thd) or if the caller in some other768 the currently running thread (current_thd) or if the caller in some other
767 way guarantees that access to thd->query is serialized.769 way guarantees that the thread won't be going away.
768 770
771 @note The query string is only printed if the session (thd) to be
772 described belongs to the calling thread.
773
769 @return Pointer to string774 @return Pointer to string
770*/775*/
771776
@@ -778,13 +783,11 @@
778 char header[256];783 char header[256];
779 int len;784 int len;
780 /*785 /*
781 The pointers thd->query and thd->proc_info might change since they are786 The thd->proc_info pointer might change since it is being modified
782 being modified concurrently. This is acceptable for proc_info since its787 concurrently. This is acceptable for proc_info since its value
783 values doesn't have to very accurate and the memory it points to is static,788 doesn't have to be accurate and the memory it points to is static,
784 but we need to attempt a snapshot on the pointer values to avoid using NULL789 but we need to attempt a snapshot on the pointer values to avoid
785 values. The pointer to thd->query however, doesn't point to static memory790 using NULL values.
786 and has to be protected by LOCK_thread_count or risk pointing to
787 uninitialized memory.
788 */791 */
789 const char *proc_info= thd->proc_info;792 const char *proc_info= thd->proc_info;
790793
@@ -818,9 +821,7 @@
818 str.append(proc_info);821 str.append(proc_info);
819 }822 }
820823
821 mysql_mutex_lock(&thd->LOCK_thd_data);824 if (thd == current_thd && thd->query())
822
823 if (thd->query())
824 {825 {
825 if (max_query_len < 1)826 if (max_query_len < 1)
826 len= thd->query_length();827 len= thd->query_length();
@@ -830,8 +831,6 @@
830 str.append(thd->query(), len);831 str.append(thd->query(), len);
831 }832 }
832833
833 mysql_mutex_unlock(&thd->LOCK_thd_data);
834
835 if (str.c_ptr_safe() == buffer)834 if (str.c_ptr_safe() == buffer)
836 return buffer;835 return buffer;
837836
@@ -1129,6 +1128,8 @@
1129#ifndef DBUG_OFF1128#ifndef DBUG_OFF
1130 gis_debug= 0;1129 gis_debug= 0;
1131#endif1130#endif
1131
1132 timer= timer_cache= NULL;
1132}1133}
11331134
11341135
@@ -1766,6 +1767,11 @@
1766 mysql_mutex_lock(&LOCK_thd_data);1767 mysql_mutex_lock(&LOCK_thd_data);
1767 mysql_mutex_unlock(&LOCK_thd_data);1768 mysql_mutex_unlock(&LOCK_thd_data);
17681769
1770 DBUG_ASSERT(timer == NULL);
1771
1772 if (timer_cache)
1773 thd_timer_end(timer_cache);
1774
1769 DBUG_PRINT("info", ("freeing security context"));1775 DBUG_PRINT("info", ("freeing security context"));
1770 main_security_ctx.destroy();1776 main_security_ctx.destroy();
1771 my_free(db);1777 my_free(db);
@@ -1890,7 +1896,8 @@
1890 /* Set the 'killed' flag of 'this', which is the target THD object. */1896 /* Set the 'killed' flag of 'this', which is the target THD object. */
1891 killed= state_to_set;1897 killed= state_to_set;
18921898
1893 if (state_to_set != THD::KILL_QUERY)1899 if (state_to_set != THD::KILL_QUERY &&
1900 state_to_set != THD::KILL_TIMEOUT)
1894 {1901 {
1895#ifdef SIGNAL_WITH_VIO_SHUTDOWN1902#ifdef SIGNAL_WITH_VIO_SHUTDOWN
1896 if (this != current_thd)1903 if (this != current_thd)
@@ -1933,6 +1940,13 @@
1933 MYSQL_CALLBACK(scheduler, post_kill_notification, (this));1940 MYSQL_CALLBACK(scheduler, post_kill_notification, (this));
1934 }1941 }
19351942
1943 /* Interrupt target waiting inside a storage engine. */
1944 if (state_to_set != THD::NOT_KILLED)
1945 ha_kill_connection(this);
1946
1947 if (state_to_set == THD::KILL_TIMEOUT)
1948 status_var_increment(status_var.max_statement_time_exceeded);
1949
1936 /* Broadcast a condition to kick the target if it is waiting on it. */1950 /* Broadcast a condition to kick the target if it is waiting on it. */
1937 if (mysys_var)1951 if (mysys_var)
1938 {1952 {
@@ -4251,6 +4265,16 @@
4251}4265}
42524266
4253/**4267/**
4268 Set the killed status of the current statement.
4269
4270 @param thd user thread connection handle
4271*/
4272extern "C" void thd_set_kill_status(const MYSQL_THD thd)
4273{
4274 thd->send_kill_message();
4275}
4276
4277/**
4254 Return the thread id of a user thread4278 Return the thread id of a user thread
4255 @param thd user thread4279 @param thd user thread
4256 @return thread id4280 @return thread id
42574281
=== modified file 'Percona-Server/sql/sql_class.h'
--- Percona-Server/sql/sql_class.h 2013-08-14 03:57:21 +0000
+++ Percona-Server/sql/sql_class.h 2013-09-09 15:30:42 +0000
@@ -86,6 +86,8 @@
86class User_level_lock;86class User_level_lock;
87class user_var_entry;87class user_var_entry;
8888
89struct st_thd_timer;
90
89enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME };91enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME };
9092
91enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,93enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
@@ -600,6 +602,8 @@
600602
601 my_bool pseudo_slave_mode;603 my_bool pseudo_slave_mode;
602604
605 ulong max_statement_time;
606
603 Gtid_specification gtid_next;607 Gtid_specification gtid_next;
604 Gtid_set_or_null gtid_next_list;608 Gtid_set_or_null gtid_next_list;
605609
@@ -682,6 +686,11 @@
682 */686 */
683 double last_query_cost;687 double last_query_cost;
684 ulonglong last_query_partial_plans;688 ulonglong last_query_partial_plans;
689
690 ulong max_statement_time_exceeded;
691 ulong max_statement_time_set;
692 ulong max_statement_time_set_failed;
693
685} STATUS_VAR;694} STATUS_VAR;
686695
687/*696/*
@@ -2387,6 +2396,9 @@
2387 return m_binlog_filter_state;2396 return m_binlog_filter_state;
2388 }2397 }
23892398
2399 /** Timer object. */
2400 struct st_thd_timer *timer, *timer_cache;
2401
2390private:2402private:
2391 /**2403 /**
2392 Indicate if the current statement should be discarded2404 Indicate if the current statement should be discarded
@@ -3029,6 +3041,7 @@
3029 KILL_BAD_DATA=1,3041 KILL_BAD_DATA=1,
3030 KILL_CONNECTION=ER_SERVER_SHUTDOWN,3042 KILL_CONNECTION=ER_SERVER_SHUTDOWN,
3031 KILL_QUERY=ER_QUERY_INTERRUPTED,3043 KILL_QUERY=ER_QUERY_INTERRUPTED,
3044 KILL_TIMEOUT=ER_QUERY_TIMEOUT,
3032 KILLED_NO_VALUE /* means neither of the states */3045 KILLED_NO_VALUE /* means neither of the states */
3033 };3046 };
3034 killed_state volatile killed;3047 killed_state volatile killed;
30353048
=== modified file 'Percona-Server/sql/sql_parse.cc'
--- Percona-Server/sql/sql_parse.cc 2013-09-09 07:01:33 +0000
+++ Percona-Server/sql/sql_parse.cc 2013-09-09 15:30:42 +0000
@@ -105,6 +105,8 @@
105using std::max;105using std::max;
106using std::min;106using std::min;
107107
108#include "sql_timer.h" // thd_timer_set, thd_timer_reset
109
108#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")110#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
109111
110/**112/**
@@ -1123,6 +1125,85 @@
1123 DBUG_RETURN(FALSE);1125 DBUG_RETURN(FALSE);
1124}1126}
11251127
1128
1129/**
1130 Get the maximum execution time for a statement.
1131
1132 @return Length of time in milliseconds.
1133
1134 @remark A zero timeout means that no timeout should be
1135 applied to this particular statement.
1136*/
1137
1138static ulong inline get_max_statement_time(THD *thd)
1139{
1140
1141 /* Assume query execution timeout feature is not used in the most cases */
1142 if (likely(!thd->variables.max_statement_time))
1143 return 0;
1144
1145 /* Check if timer support is implemented and was initialized. */
1146 if (unlikely(have_statement_timeout != SHOW_OPTION_YES))
1147 return 0;
1148
1149 /* The maximum execution time only applies to top-level statements. */
1150 if (unlikely(thd->sp_runtime_ctx || thd->in_sub_stmt))
1151 return 0;
1152
1153 /* Also does not apply to statements made by the slave thread. */
1154 if (unlikely(thd->slave_thread))
1155 return 0;
1156
1157 return thd->variables.max_statement_time;
1158}
1159
1160
1161/**
1162 Set the time until the currently running statement is aborted.
1163
1164 @param thd Thread (session) context.
1165
1166 @return TRUE if the timer was armed.
1167*/
1168
1169static inline bool set_statement_timer(THD *thd)
1170{
1171 ulong max_statement_time= get_max_statement_time(thd);
1172
1173 /* Assume query execution timeout feature is not used in the most cases */
1174 if (likely(max_statement_time == 0))
1175 return false;
1176
1177 if (unlikely(thd->timer != NULL))
1178 return false;
1179
1180 thd->timer= thd_timer_set(thd, thd->timer_cache, max_statement_time);
1181 thd->timer_cache= NULL;
1182
1183 if (thd->timer)
1184 status_var_increment(thd->status_var.max_statement_time_set);
1185 else
1186 status_var_increment(thd->status_var.max_statement_time_set_failed);
1187
1188 return thd->timer;
1189}
1190
1191
1192/**
1193 Deactivate the timer associated with the statement that was executed.
1194
1195 @param thd Thread (session) context.
1196*/
1197
1198static void reset_statement_timer(THD *thd)
1199{
1200 DBUG_ASSERT(thd->timer);
1201 /* Cache the timer object if it can be reused. */
1202 thd->timer_cache= thd_timer_reset(thd->timer);
1203 thd->timer= NULL;
1204}
1205
1206
1126/**1207/**
1127 Perform one connection-level (COM_XXXX) command.1208 Perform one connection-level (COM_XXXX) command.
11281209
@@ -2613,6 +2694,8 @@
2613 } /* endif unlikely slave */2694 } /* endif unlikely slave */
2614#endif2695#endif
26152696
2697 bool reset_timer= set_statement_timer(thd);
2698
2616 status_var_increment(thd->status_var.com_stat[lex->sql_command]);2699 status_var_increment(thd->status_var.com_stat[lex->sql_command]);
26172700
2618 Opt_trace_start ots(thd, all_tables, lex->sql_command, &lex->var_list,2701 Opt_trace_start ots(thd, all_tables, lex->sql_command, &lex->var_list,
@@ -5201,12 +5284,17 @@
5201 DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() ||5284 DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() ||
5202 thd->in_multi_stmt_transaction_mode());5285 thd->in_multi_stmt_transaction_mode());
52035286
5287 if (reset_timer)
5288 reset_statement_timer(thd);
5289
5204 if (! thd->in_sub_stmt)5290 if (! thd->in_sub_stmt)
5205 {5291 {
5206 /* report error issued during command execution */5292 /* report error issued during command execution */
5207 if (thd->killed_errno())5293 if (thd->killed_errno())
5208 thd->send_kill_message();5294 thd->send_kill_message();
5209 if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA)5295 if (thd->killed == THD::KILL_QUERY ||
5296 thd->killed == THD::KILL_TIMEOUT ||
5297 thd->killed == THD::KILL_BAD_DATA)
5210 {5298 {
5211 thd->killed= THD::NOT_KILLED;5299 thd->killed= THD::NOT_KILLED;
5212 thd->mysys_var->abort= 0;5300 thd->mysys_var->abort= 0;
52135301
=== added file 'Percona-Server/sql/sql_timer.cc'
--- Percona-Server/sql/sql_timer.cc 1970-01-01 00:00:00 +0000
+++ Percona-Server/sql/sql_timer.cc 2013-09-09 15:30:42 +0000
@@ -0,0 +1,253 @@
1/* Copyright (c) 2012, Twitter, Inc. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License along
13 with this program; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
15
16#include "sql_class.h" /* THD */
17#include "sql_timer.h" /* thd_timer_set, etc. */
18#include "my_timer.h" /* my_timer_t */
19
20struct st_thd_timer
21{
22 THD *thd;
23 my_timer_t timer;
24 pthread_mutex_t mutex;
25 bool destroy;
26};
27
28C_MODE_START
29static void timer_callback(my_timer_t *);
30C_MODE_END
31
32/**
33 Allocate and initialize a thread timer object.
34
35 @return NULL on failure.
36*/
37
38static thd_timer_t *
39thd_timer_create(void)
40{
41 thd_timer_t *ttp;
42 DBUG_ENTER("thd_timer_create");
43
44 ttp= (thd_timer_t *) my_malloc(sizeof(*ttp), MYF(MY_WME | MY_ZEROFILL));
45
46 if (ttp == NULL)
47 DBUG_RETURN(NULL);
48
49 ttp->timer.notify_function= timer_callback;
50 pthread_mutex_init(&ttp->mutex, MY_MUTEX_INIT_FAST);
51
52 if (! my_os_timer_create(&ttp->timer))
53 DBUG_RETURN(ttp);
54
55 pthread_mutex_destroy(&ttp->mutex);
56 my_free(ttp);
57
58 DBUG_RETURN(NULL);
59}
60
61
62/**
63 Release resources allocated for a thread timer.
64
65 @param ttp Thread timer object.
66*/
67
68static void
69thd_timer_destroy(thd_timer_t *ttp)
70{
71 DBUG_ENTER("thd_timer_destroy");
72
73 my_os_timer_delete(&ttp->timer);
74 pthread_mutex_destroy(&ttp->mutex);
75 my_free(ttp);
76
77 DBUG_VOID_RETURN;
78}
79
80
81/**
82 Notify a thread (session) that its timer has expired.
83
84 @param ttp Thread timer object.
85
86 @return true if the object should be destroyed.
87*/
88
89static bool
90timer_notify(thd_timer_t *ttp)
91{
92 THD *thd= ttp->thd;
93
94 DBUG_ASSERT(!ttp->destroy || !thd);
95
96 /*
97 Statement might have finished while the timer notification
98 was being delivered. If this is the case, the timer object
99 was detached (orphaned) and has no associated session (thd).
100 */
101 if (thd)
102 {
103 mysql_mutex_lock(&thd->LOCK_thd_data);
104 thd->awake(THD::KILL_TIMEOUT);
105 mysql_mutex_unlock(&thd->LOCK_thd_data);
106 }
107
108 /* Mark the object as unreachable. */
109 ttp->thd= NULL;
110
111 return ttp->destroy;
112}
113
114
115/**
116 Timer expiration notification callback.
117
118 @param timer Timer (mysys) object.
119
120 @note Invoked in a separate thread of control.
121*/
122
123static void
124timer_callback(my_timer_t *timer)
125{
126 bool destroy;
127 thd_timer_t *ttp;
128
129 ttp= my_container_of(timer, thd_timer_t, timer);
130
131 pthread_mutex_lock(&ttp->mutex);
132 destroy= timer_notify(ttp);
133 pthread_mutex_unlock(&ttp->mutex);
134
135 if (destroy)
136 thd_timer_destroy(ttp);
137}
138
139
140/**
141 Set the time until the currently running statement is aborted.
142
143 @param thd Thread (session) context.
144 @param ttp Thread timer object.
145 @param time Length of time, in milliseconds, until the currently
146 running statement is aborted.
147
148 @return NULL on failure.
149*/
150
151thd_timer_t *
152thd_timer_set(THD *thd, thd_timer_t *ttp, unsigned long time)
153{
154 DBUG_ENTER("thd_timer_set");
155
156 /* Create a new thread timer object if one was not provided. */
157 if (ttp == NULL && (ttp= thd_timer_create()) == NULL)
158 DBUG_RETURN(NULL);
159
160 DBUG_ASSERT(!ttp->destroy && !ttp->thd);
161
162 /* Mark the notification as pending. */
163 ttp->thd= thd;
164
165 /* Arm the timer. */
166 if (! my_os_timer_set(&ttp->timer, time))
167 DBUG_RETURN(ttp);
168
169 /* Dispose of the (cached) timer object. */
170 thd_timer_destroy(ttp);
171
172 DBUG_RETURN(NULL);
173}
174
175
176/**
177 Reap a (possibly) pending timer object.
178
179 @param ttp Thread timer object.
180
181 @return true if the timer object is unreachable.
182*/
183
184static bool
185reap_timer(thd_timer_t *ttp, bool pending)
186{
187 bool unreachable;
188
189 /* Cannot be tagged for destruction. */
190 DBUG_ASSERT(!ttp->destroy);
191
192 /* If not pending, timer hasn't fired. */
193 DBUG_ASSERT(pending || ttp->thd);
194
195 /*
196 The timer object can be reused if the timer was stopped before
197 expiring. Otherwise, the timer notification function might be
198 executing asynchronously in the context of a separate thread.
199 */
200 unreachable= pending ? ttp->thd == NULL : true;
201
202 ttp->thd= NULL;
203
204 return unreachable;
205}
206
207/**
208 Deactivate the given timer.
209
210 @param ttp Thread timer object.
211
212 @return NULL if the timer object was orphaned.
213 Otherwise, the given timer object is returned.
214*/
215
216thd_timer_t *
217thd_timer_reset(thd_timer_t *ttp)
218{
219 bool unreachable;
220 int status, state;
221 DBUG_ENTER("thd_timer_reset");
222
223 status= my_os_timer_reset(&ttp->timer, &state);
224
225 /*
226 If the notification function cannot possibly run anymore, cache
227 the timer object as there are no outstanding references to it.
228 */
229 pthread_mutex_lock(&ttp->mutex);
230 unreachable= reap_timer(ttp, status ? true : !state);
231 ttp->destroy= unreachable ? false : true;
232 pthread_mutex_unlock(&ttp->mutex);
233
234 DBUG_RETURN(unreachable ? ttp : NULL);
235}
236
237
238/**
239 Release resources allocated for a given thread timer.
240
241 @param ttp Thread timer object.
242*/
243
244void
245thd_timer_end(thd_timer_t *ttp)
246{
247 DBUG_ENTER("thd_timer_end");
248
249 thd_timer_destroy(ttp);
250
251 DBUG_VOID_RETURN;
252}
253
0254
=== added file 'Percona-Server/sql/sql_timer.h'
--- Percona-Server/sql/sql_timer.h 1970-01-01 00:00:00 +0000
+++ Percona-Server/sql/sql_timer.h 2013-09-09 15:30:42 +0000
@@ -0,0 +1,50 @@
1/* Copyright (c) 2012, Twitter, Inc. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License along
13 with this program; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
15
16#ifndef SQL_TIMER_INCLUDED
17#define SQL_TIMER_INCLUDED
18
19class THD;
20struct st_thd_timer;
21typedef struct st_thd_timer thd_timer_t;
22
23#ifdef HAVE_MY_TIMER
24
25thd_timer_t *thd_timer_set(THD *, thd_timer_t *, unsigned long);
26thd_timer_t *thd_timer_reset(thd_timer_t *);
27void thd_timer_end(thd_timer_t *);
28
29#else
30
31static inline thd_timer_t *
32thd_timer_set(THD *, thd_timer_t *, unsigned long)
33{
34 return NULL;
35}
36
37static inline thd_timer_t *
38thd_timer_reset(thd_timer_t *)
39{
40 return NULL;
41}
42
43static inline void
44thd_timer_end(thd_timer_t *)
45{
46}
47
48#endif
49
50#endif /* SQL_TIMER_INCLUDED */
051
=== modified file 'Percona-Server/sql/sys_vars.cc'
--- Percona-Server/sql/sys_vars.cc 2013-09-09 07:01:33 +0000
+++ Percona-Server/sql/sys_vars.cc 2013-09-09 15:30:42 +0000
@@ -2928,6 +2928,12 @@
2928 sql_mode_names, DEFAULT(MODE_NO_ENGINE_SUBSTITUTION), NO_MUTEX_GUARD,2928 sql_mode_names, DEFAULT(MODE_NO_ENGINE_SUBSTITUTION), NO_MUTEX_GUARD,
2929 NOT_IN_BINLOG, ON_CHECK(check_sql_mode), ON_UPDATE(fix_sql_mode));2929 NOT_IN_BINLOG, ON_CHECK(check_sql_mode), ON_UPDATE(fix_sql_mode));
29302930
2931static Sys_var_ulong Sys_max_statement_time(
2932 "max_statement_time",
2933 "Kill any statement that takes over the specified number of milliseconds",
2934 SESSION_VAR(max_statement_time), CMD_LINE(REQUIRED_ARG),
2935 VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1));
2936
2931#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)2937#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
2932#define SSL_OPT(X) CMD_LINE(REQUIRED_ARG,X)2938#define SSL_OPT(X) CMD_LINE(REQUIRED_ARG,X)
2933#else2939#else
@@ -3966,6 +3972,10 @@
3966 "have_symlink", "have_symlink",3972 "have_symlink", "have_symlink",
3967 READ_ONLY GLOBAL_VAR(have_symlink), NO_CMD_LINE);3973 READ_ONLY GLOBAL_VAR(have_symlink), NO_CMD_LINE);
39683974
3975static Sys_var_have Sys_have_statement_timeout(
3976 "have_statement_timeout", "have_statement_timeout",
3977 READ_ONLY GLOBAL_VAR(have_statement_timeout), NO_CMD_LINE);
3978
3969static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type);3979static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type);
3970static Sys_var_mybool Sys_general_log(3980static Sys_var_mybool Sys_general_log(
3971 "general_log", "Log connections and queries to a table or log file. "3981 "general_log", "Log connections and queries to a table or log file. "
39723982
=== modified file 'Percona-Server/storage/innobase/handler/ha_innodb.cc'
--- Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-08-30 13:23:53 +0000
+++ Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-09-09 15:30:42 +0000
@@ -42,6 +42,7 @@
42#include <my_base.h> // HA_OPTION_*42#include <my_base.h> // HA_OPTION_*
43#include <mysys_err.h>43#include <mysys_err.h>
44#include <mysql/innodb_priv.h>44#include <mysql/innodb_priv.h>
45#include <mysql/thread_pool_priv.h>
4546
46/** @file ha_innodb.cc */47/** @file ha_innodb.cc */
4748
@@ -809,6 +810,15 @@
809 which to close the connection */810 which to close the connection */
810811
811/*****************************************************************//**812/*****************************************************************//**
813Cancel any pending lock request associated with the current THD. */
814static
815void
816innobase_kill_connection(
817/*======================*/
818 handlerton* hton, /*!< in: innobase handlerton */
819 THD* thd); /*!< in: handle to the MySQL thread being killed */
820
821/*****************************************************************//**
812Commits a transaction in an InnoDB database or marks an SQL statement822Commits a transaction in an InnoDB database or marks an SQL statement
813ended.823ended.
814@return 0 */824@return 0 */
@@ -1540,8 +1550,8 @@
1540 return(0);1550 return(0);
15411551
1542 case DB_INTERRUPTED:1552 case DB_INTERRUPTED:
1543 my_error(ER_QUERY_INTERRUPTED, MYF(0));1553 thd_set_kill_status(thd ? thd : thd_get_current_thd());
1544 /* fall through */1554 return(-1);
15451555
1546 case DB_FOREIGN_EXCEED_MAX_CASCADE:1556 case DB_FOREIGN_EXCEED_MAX_CASCADE:
1547 ut_ad(thd);1557 ut_ad(thd);
@@ -3017,6 +3027,8 @@
3017 = innobase_purge_changed_page_bitmaps;3027 = innobase_purge_changed_page_bitmaps;
3018 innobase_hton->is_fake_change = innobase_is_fake_change;3028 innobase_hton->is_fake_change = innobase_is_fake_change;
30193029
3030 innobase_hton->kill_connection = innobase_kill_connection;
3031
3020 ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);3032 ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
30213033
3022#ifndef DBUG_OFF3034#ifndef DBUG_OFF
@@ -4199,6 +4211,40 @@
4199 return(ROW_TYPE_NOT_USED);4211 return(ROW_TYPE_NOT_USED);
4200}4212}
42014213
4214/*****************************************************************//**
4215Cancel any pending lock request associated with the current THD. */
4216static
4217void
4218innobase_kill_connection(
4219/*======================*/
4220 handlerton* hton, /*!< in: innobase handlerton */
4221 THD* thd) /*!< in: handle to the MySQL thread being killed */
4222{
4223 trx_t* trx;
4224
4225 DBUG_ENTER("innobase_kill_connection");
4226 DBUG_ASSERT(hton == innodb_hton_ptr);
4227
4228 lock_mutex_enter();
4229
4230 trx = thd_to_trx(thd);
4231
4232 if (trx)
4233 {
4234 trx_mutex_enter(trx);
4235
4236 /* Cancel a pending lock request. */
4237 if (trx->lock.wait_lock)
4238 lock_cancel_waiting_and_release(trx->lock.wait_lock);
4239
4240 trx_mutex_exit(trx);
4241 }
4242
4243 lock_mutex_exit();
4244
4245 DBUG_VOID_RETURN;
4246}
4247
42024248
42034249
4204/****************************************************************//**4250/****************************************************************//**
@@ -11874,7 +11920,7 @@
1187411920
11875 prebuilt->trx->op_info = "";11921 prebuilt->trx->op_info = "";
11876 if (thd_killed(user_thd)) {11922 if (thd_killed(user_thd)) {
11877 my_error(ER_QUERY_INTERRUPTED, MYF(0));11923 thd_set_kill_status(user_thd);
11878 }11924 }
1187911925
11880 if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) {11926 if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) {
1188111927
=== modified file 'Percona-Server/storage/innobase/include/lock0lock.h'
--- Percona-Server/storage/innobase/include/lock0lock.h 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/include/lock0lock.h 2013-09-09 15:30:42 +0000
@@ -498,6 +498,16 @@
498lock_trx_release_locks(498lock_trx_release_locks(
499/*===================*/499/*===================*/
500 trx_t* trx); /*!< in/out: transaction */500 trx_t* trx); /*!< in/out: transaction */
501
502/*********************************************************************//**
503Cancels a waiting lock request and releases possible other transactions
504waiting behind it. */
505UNIV_INTERN
506void
507lock_cancel_waiting_and_release(
508/*============================*/
509 lock_t* lock); /*!< in/out: waiting lock request */
510
501/*********************************************************************//**511/*********************************************************************//**
502Removes locks on a table to be dropped or truncated.512Removes locks on a table to be dropped or truncated.
503If remove_also_table_sx_locks is TRUE then table-level S and X locks are513If remove_also_table_sx_locks is TRUE then table-level S and X locks are
504514
=== modified file 'Percona-Server/storage/innobase/include/lock0priv.h'
--- Percona-Server/storage/innobase/include/lock0priv.h 2013-06-10 20:44:22 +0000
+++ Percona-Server/storage/innobase/include/lock0priv.h 2013-09-09 15:30:42 +0000
@@ -98,15 +98,6 @@
98 ulint heap_no);/*!< in: heap number of the record */98 ulint heap_no);/*!< in: heap number of the record */
9999
100/*********************************************************************//**100/*********************************************************************//**
101Cancels a waiting lock request and releases possible other transactions
102waiting behind it. */
103UNIV_INTERN
104void
105lock_cancel_waiting_and_release(
106/*============================*/
107 lock_t* lock); /*!< in/out: waiting lock request */
108
109/*********************************************************************//**
110Checks if some transaction has an implicit x-lock on a record in a clustered101Checks if some transaction has an implicit x-lock on a record in a clustered
111index.102index.
112@return transaction id of the transaction which has the x-lock, or 0 */103@return transaction id of the transaction which has the x-lock, or 0 */
113104
=== added directory 'Percona-Server/unittest/mysys'
=== added file 'Percona-Server/unittest/mysys/my_timer-t.c'
--- Percona-Server/unittest/mysys/my_timer-t.c 1970-01-01 00:00:00 +0000
+++ Percona-Server/unittest/mysys/my_timer-t.c 2013-09-09 15:30:42 +0000
@@ -0,0 +1,263 @@
1/* Copyright (c) 2012, Twitter, Inc. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License along
13 with this program; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
15
16#include "m_string.h"
17#include "my_timer.h"
18#include "thr_template.c"
19
20typedef struct
21{
22 my_timer_t timer;
23 unsigned int fired;
24 pthread_mutex_t mutex;
25 pthread_cond_t cond;
26} test_timer_t;
27
28static void timer_notify_function(my_timer_t *timer)
29{
30 test_timer_t *test= my_container_of(timer, test_timer_t, timer);
31
32 pthread_mutex_lock(&test->mutex);
33 test->fired++;
34 pthread_cond_signal(&test->cond);
35 pthread_mutex_unlock(&test->mutex);
36}
37
38static void test_timer_create(test_timer_t *test)
39{
40 memset(test, 0, sizeof(test_timer_t));
41 pthread_mutex_init(&test->mutex, NULL);
42 pthread_cond_init(&test->cond, NULL);
43 ok(my_os_timer_create(&test->timer) == 0, "my_os_timer_create");
44 test->timer.notify_function= timer_notify_function;
45}
46
47static void test_timer_destroy(test_timer_t *test)
48{
49 pthread_mutex_destroy(&test->mutex);
50 pthread_cond_destroy(&test->cond);
51 my_os_timer_delete(&test->timer);
52}
53
54static void test_create_and_delete(void)
55{
56 int rc;
57 my_timer_t timer;
58
59 diag("test_create_and_delete");
60
61 memset(&timer, 0, sizeof(timer));
62
63 rc= my_os_timer_create(&timer);
64 ok(rc == 0, "my_os_timer_create");
65
66 my_os_timer_delete(&timer);
67}
68
69static void test_reset(void)
70{
71 int rc, state;
72 test_timer_t test;
73
74 diag("test_reset");
75
76 test_timer_create(&test);
77
78 rc= my_os_timer_set(&test.timer, 3600000U);
79 ok(rc == 0, "my_os_timer_set");
80
81 rc= my_os_timer_reset(&test.timer, &state);
82 ok(rc == 0, "my_os_timer_reset");
83
84 ok(state == 1, "timer state is nonsignaled");
85 ok(test.fired == 0, "timer has not fired");
86
87 test_timer_destroy(&test);
88}
89
90static void test_timer(void)
91{
92 int rc, state;
93 test_timer_t test;
94
95 diag("test_timer");
96
97 test_timer_create(&test);
98
99 pthread_mutex_lock(&test.mutex);
100
101 rc= my_os_timer_set(&test.timer, 5);
102 ok(rc == 0, "my_os_timer_set");
103
104 ok(test.fired == 0, "not fired yet");
105
106 while (!test.fired)
107 pthread_cond_wait(&test.cond, &test.mutex);
108
109 ok(test.fired == 1, "timer fired once");
110
111 rc= my_os_timer_reset(&test.timer, &state);
112 ok(rc == 0, "my_os_timer_reset");
113
114 ok(state == 0, "timer state was signaled");
115
116 pthread_mutex_unlock(&test.mutex);
117
118 test_timer_destroy(&test);
119}
120
121static void timer_set_and_wait(test_timer_t *test, unsigned int fired_count)
122{
123 int rc, state;
124
125 rc= my_os_timer_set(&test->timer, 5);
126 ok(rc == 0, "my_os_timer_set");
127
128 ok(test->fired != fired_count, "not fired yet");
129
130 while (test->fired != fired_count)
131 pthread_cond_wait(&test->cond, &test->mutex);
132
133 ok(test->fired == fired_count, "timer fired");
134
135 rc= my_os_timer_reset(&test->timer, &state);
136 ok(rc == 0, "my_os_timer_reset");
137
138 ok(state == 0, "timer state was signaled");
139}
140
141static void test_timer_reuse(void)
142{
143 test_timer_t test;
144
145 diag("test_timer_reuse");
146
147 test_timer_create(&test);
148
149 pthread_mutex_lock(&test.mutex);
150
151 timer_set_and_wait(&test, 1);
152 timer_set_and_wait(&test, 2);
153 timer_set_and_wait(&test, 3);
154
155 pthread_mutex_unlock(&test.mutex);
156
157 test_timer_destroy(&test);
158}
159
160static void test_independent_timers(void)
161{
162 int rc, state;
163 test_timer_t test;
164
165 diag("test_independent_timers");
166
167 test_timer_create(&test);
168
169 rc= my_os_timer_set(&test.timer, 3600000U);
170 ok(rc == 0, "my_os_timer_set");
171
172 test_timer();
173
174 rc= my_os_timer_reset(&test.timer, &state);
175 ok(rc == 0, "my_os_timer_reset");
176
177 ok(state == 1, "timer state is nonsignaled");
178 ok(test.fired == 0, "timer has not fired");
179
180 test_timer_destroy(&test);
181}
182
183static void test_timer_no_tap(void)
184{
185 int rc, state;
186 test_timer_t test;
187
188 memset(&test, 0, sizeof(test_timer_t));
189
190 pthread_mutex_init(&test.mutex, NULL);
191 pthread_cond_init(&test.cond, NULL);
192
193 test.timer.notify_function= timer_notify_function;
194
195 rc= my_os_timer_create(&test.timer);
196 assert(rc == 0);
197
198 pthread_mutex_lock(&test.mutex);
199
200 rc= my_os_timer_set(&test.timer, 5);
201 assert(rc == 0);
202
203 assert(test.fired == 0); /* not fired yet */
204
205 while (!test.fired)
206 pthread_cond_wait(&test.cond, &test.mutex);
207
208 assert(test.fired == 1); /* timer fired once */
209
210 rc= my_os_timer_reset(&test.timer, &state);
211 assert(rc == 0);
212
213 assert(state == 0); /* timer state was signaled */
214
215 pthread_mutex_unlock(&test.mutex);
216
217 pthread_mutex_destroy(&test.mutex);
218 pthread_cond_destroy(&test.cond);
219 my_os_timer_delete(&test.timer);
220}
221
222static pthread_handler_t test_timer_per_thread(void *arg)
223{
224 int iter= *(int *) arg;
225
226 while (iter--)
227 test_timer_no_tap();
228
229 pthread_mutex_lock(&mutex);
230 if (!--running_threads)
231 pthread_cond_signal(&cond);
232 pthread_mutex_unlock(&mutex);
233
234 return NULL;
235}
236
237static void test_reinitialization(void)
238{
239 diag("test_reinitialization");
240
241 my_os_timer_deinit();
242 ok(my_os_timer_init_ext() == 0, "my_os_timer_init_ext");
243 test_timer();
244 my_os_timer_deinit();
245 ok(my_os_timer_init_ext() == 0, "my_os_timer_init_ext");
246}
247
248void do_tests()
249{
250 plan(49);
251
252 ok(my_os_timer_init_ext() == 0, "my_os_timer_init_ext");
253
254 test_create_and_delete();
255 test_reset();
256 test_timer();
257 test_timer_reuse();
258 test_independent_timers();
259 test_concurrently("per-thread", test_timer_per_thread, THREADS, 5);
260 test_reinitialization();
261
262 my_os_timer_deinit();
263}

Subscribers

People subscribed via source and target branches