From 5f313125d428e0aaf9a27884a60c436566d63b5e Mon Sep 17 00:00:00 2001 From: Ashish Agarwal Date: Mon, 2 Jul 2012 15:20:23 +0530 Subject: BUG#13555854: CHECK AND REPAIR TABLE SHOULD BE MORE ROBUST [1] ISSUE: Incorrect key file. Key file is corrupted, Reading incorrect key information (keyseg) from index file. Key definition in .MYI and .FRM file differs. Starting pointer to read the keyseg information is changed to a value greater than the pack_reclength. Memcpy tries to read keyseg information from unallocated memory which causes the crash. SOLUTION: One more check added to compare the the key definition in .MYI and .FRM file. If the definition differ, server produces an error. --- storage/myisam/ha_myisam.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 34532d39443..72a29cd8130 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -516,7 +516,8 @@ int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo, t1_keysegs[j].language != t2_keysegs[j].language) || t1_keysegs_j__type != t2_keysegs[j].type || t1_keysegs[j].null_bit != t2_keysegs[j].null_bit || - t1_keysegs[j].length != t2_keysegs[j].length) + t1_keysegs[j].length != t2_keysegs[j].length || + t1_keysegs[j].start != t2_keysegs[j].start) { DBUG_PRINT("error", ("Key segment %d (key %d) has different " "definition", j, i)); -- cgit v1.2.1 From 425f07eacee344113ddcb90198072bddafbd2064 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Jul 2012 18:51:07 +0200 Subject: Raise version number after cloning 5.5.27 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 2ac736f0617..4ed7f1471fd 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=27 +MYSQL_VERSION_PATCH=28 MYSQL_VERSION_EXTRA= -- cgit v1.2.1 From 357a008ad32704df620411bcb8a7cb26f15662de Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Thu, 12 Jul 2012 16:42:07 +0530 Subject: Bug #11765218 58157: INNODB LOCKS AN UNMATCHED ROW EVEN THOUGH USING RBR AND RC Description: When scanning and locking rows with < or <=, InnoDB locks the next row even though row based binary logging and read committed is used. Solution: In the handler, when the row is identified to fall outside of the range (as specified in the query predicates), then request the storage engine to unlock the row (if possible). This is done in handler::read_range_first() and handler::read_range_next(). --- sql/handler.cc | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 9e43d5aba93..4f5c613a6a4 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4287,7 +4287,19 @@ int handler::read_range_first(const key_range *start_key, ? HA_ERR_END_OF_FILE : result); - DBUG_RETURN (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE); + if (compare_key(end_range) <= 0) + { + DBUG_RETURN(0); + } + else + { + /* + The last read row does not fall in the range. So request + storage engine to release row lock if possible. + */ + unlock_row(); + DBUG_RETURN(HA_ERR_END_OF_FILE); + } } @@ -4319,7 +4331,20 @@ int handler::read_range_next() result= index_next(table->record[0]); if (result) DBUG_RETURN(result); - DBUG_RETURN(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE); + + if (compare_key(end_range) <= 0) + { + DBUG_RETURN(0); + } + else + { + /* + The last read row does not fall in the range. So request + storage engine to release row lock if possible. + */ + unlock_row(); + DBUG_RETURN(HA_ERR_END_OF_FILE); + } } -- cgit v1.2.1 From 8dc96fc7aa2d65d44f7ae86b25c5e167e57b64a8 Mon Sep 17 00:00:00 2001 From: Nuno Carvalho Date: Fri, 13 Jul 2012 10:04:59 +0100 Subject: BUG#14310067: RPL_CANT_READ_EVENT_INCIDENT AND RPL_BUG41902 FAIL ON 5.5 rpl_cant_read_event_incident: Slave applies updates from bug11747416_32228_binlog.000001 file which contains a CREATE TABLE t statement and an incident, when SQL thread is running slowly IO thread may reach the incident before SQL thread executes the create table statement. Execute "drop table if exists t" and also perform a RESET MASTER to clean slave binary logs. rpl_bug41902: Error "MYSQL_BIN_LOG::purge_logs was called with file ./master-bin.000001 not listed in the index." suppression is not considering windows path, there is ".\master-bin.000001". Changed suppression to: "MYSQL_BIN_LOG::purge_logs was called with file ..master-bin.000001 not listed in the index", to match ".\" and "./". --- mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result | 4 +++- mysql-test/suite/rpl/t/rpl_bug41902.test | 4 ++-- mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test | 7 ++++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result b/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result index d86911fc0ce..4937062bcc3 100644 --- a/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result +++ b/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result @@ -15,5 +15,7 @@ Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary reset master; stop slave; reset slave; -drop table t; +drop table if exists t; +reset master; End of the tests +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_bug41902.test b/mysql-test/suite/rpl/t/rpl_bug41902.test index 12eeb903003..36439633500 100644 --- a/mysql-test/suite/rpl/t/rpl_bug41902.test +++ b/mysql-test/suite/rpl/t/rpl_bug41902.test @@ -52,10 +52,10 @@ purge binary logs to 'master-bin.000001'; --disable_query_log call mtr.add_suppression("Failed to locate old binlog or relay log files"); -call mtr.add_suppression("MYSQL_BIN_LOG::purge_logs was called with file ./master-bin.000001 not listed in the index"); +call mtr.add_suppression("MYSQL_BIN_LOG::purge_logs was called with file ..master-bin.000001 not listed in the index"); connection slave; call mtr.add_suppression("Failed to locate old binlog or relay log files"); -call mtr.add_suppression("MYSQL_BIN_LOG::purge_logs was called with file ./master-bin.000001 not listed in the index"); +call mtr.add_suppression("MYSQL_BIN_LOG::purge_logs was called with file ..master-bin.000001 not listed in the index"); --enable_query_log --echo ==== clean up ==== diff --git a/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test b/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test index 27478a318b8..daacb4d14f0 100644 --- a/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test +++ b/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test @@ -60,6 +60,11 @@ reset master; --connection slave stop slave; reset slave; -drop table t; # table was created from binlog. it does not exist on master. +# Table was created from binlog, it may not be created if SQL thread is running +# slowly and IO thread reaches incident before SQL thread applies it. +drop table if exists t; +reset master; --echo End of the tests +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc -- cgit v1.2.1 From ddcd6867e925613c90e699dcf3e51ab765cf07ba Mon Sep 17 00:00:00 2001 From: Chaithra Gopalareddy Date: Wed, 18 Jul 2012 14:36:08 +0530 Subject: Bug#11762052: 54599: BUG IN QUERY PLANNER ON QUERIES WITH "ORDER BY" AND "LIMIT BY" CLAUSE PROBLEM: When a 'limit' clause is specified in a query along with group by and order by, optimizer chooses wrong index there by examining more number of rows than required. However without the 'limit' clause, optimizer chooses the right index. ANALYSIS: With respect to the query specified, range optimizer chooses the first index as there is a range present ( on 'a'). Optimizer then checks for an index which would give records in sorted order for the 'group by' clause. While checking chooses the second index (on 'c,b,a') based on the 'limit' specified and the selectivity of 'quick_condition_rows' (number of rows present in the range) in 'test_if_skip_sort_order' function. But, it fails to consider that an order by clause on a different column will result in scanning the entire index and hence the estimated number of rows calculated above are wrong (which results in choosing the second index). FIX: Do not enforce the 'limit' clause in the call to 'test_if_skip_sort_order' if we are creating a temporary table. Creation of temporary table indicates that there would be more post-processing and hence will need all the rows. This fix is backported from 5.6. This problem is fixed in 5.6 as part of changes for work log #5558 mysql-test/r/subselect.result: Changes for Bug#11762052 results in the correct number of rows. sql/sql_select.cc: Do not pass the actual 'limit' value if 'need_tmp' is true. --- mysql-test/r/subselect.result | 2 -- sql/sql_select.cc | 11 +++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 26fe129feed..49cf73677b1 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4555,8 +4555,6 @@ SELECT * FROM t1 WHERE EXISTS (SELECT DISTINCT a FROM t2 WHERE t1.a < t2.a ORDER BY b); pk a 1 10 -3 30 -2 20 DROP TABLE t1,t2; CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a), KEY b (b)); INSERT INTO t1 VALUES (1,NULL), (9,NULL); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f2007f609e0..c097c4d16ef 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1482,12 +1482,19 @@ JOIN::optimize() DBUG_RETURN(1); } } - + /* + Calculate a possible 'limit' of table rows for 'GROUP BY': 'need_tmp' + implies that there will be more postprocessing so the specified + 'limit' should not be enforced yet in the call to + 'test_if_skip_sort_order'. + */ + const ha_rows limit = need_tmp ? HA_POS_ERROR : unit->select_limit_cnt; + if (!(select_options & SELECT_BIG_RESULT) && ((group_list && (!simple_group || !test_if_skip_sort_order(&join_tab[const_tables], group_list, - unit->select_limit_cnt, 0, + limit, 0, &join_tab[const_tables].table-> keys_in_use_for_group_by))) || select_distinct) && -- cgit v1.2.1 From 913e3a8475f0cc69dcd149668291f973538e5046 Mon Sep 17 00:00:00 2001 From: Venkata Sidagam Date: Thu, 19 Jul 2012 13:52:34 +0530 Subject: Bug #12615411 - server side help doesn't work as first statement Problem description: Giving "help 'contents'" in the mysql client as a first statement gives error Analysis: In com_server_help() function the "server_cmd" variable was initialised with buffer->ptr(). And the "server_cmd" variable is not updated since we are passing "'contents'"(with single quote) so the buffer->ptr() consists of the previous buffer values and it was sent to the mysql_real_query() hence we are getting error. Fix: We are not initialising the "server_cmd" variable and we are updating the variable with "server_cmd= cmd_buf" in any of the case i.e with single quote or without single quote for the contents. As part of error message improvement, added new error message in case of "help 'contents'". client/mysql.cc: com_server_help(): Properly updated the server_cmd variable and improved the error message. --- client/mysql.cc | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 49d58a832a2..595d5e1d969 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2803,7 +2803,7 @@ static int com_server_help(String *buffer __attribute__((unused)), char *line __attribute__((unused)), char *help_arg) { MYSQL_ROW cur; - const char *server_cmd= buffer->ptr(); + const char *server_cmd; char cmd_buf[100 + 1]; MYSQL_RES *result; int error; @@ -2818,9 +2818,12 @@ static int com_server_help(String *buffer __attribute__((unused)), *++end_arg= '\0'; } (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS); - server_cmd= cmd_buf; } - + else + (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help ", help_arg, NullS); + + server_cmd= cmd_buf; + if (!status.batch) { old_buffer= *buffer; @@ -2888,6 +2891,11 @@ static int com_server_help(String *buffer __attribute__((unused)), else { put_info("\nNothing found", INFO_INFO); + if (strncasecmp(server_cmd, "help 'contents'", 15) == 0) + { + put_info("\nPlease check if 'help tables' are loaded.\n", INFO_INFO); + goto err; + } put_info("Please try to run 'help contents' for a list of all accessible topics\n", INFO_INFO); } } -- cgit v1.2.1 From 6aaf15798556b4d6880124ce858f9623e9de570c Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Thu, 19 Jul 2012 12:57:36 +0200 Subject: Bug #14035452 - MODULARIZE MYSQL_CLIENT_TEST Added new minimal client using same framework Added internal test using it Small changes to top level make/configure/cmake to have it built --- CMakeLists.txt | 3 +++ Makefile.am | 2 +- configure.in | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c30db2927d4..75927c40cae 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -310,3 +310,6 @@ IF(WITH_EMBEDDED_SERVER) ADD_SUBDIRECTORY(libmysqld/examples) ENDIF(WITH_EMBEDDED_SERVER) ADD_SUBDIRECTORY(mysql-test/lib/My/SafeProcess) +IF(EXISTS ${CMAKE_SOURCE_DIR}/internal/CMakeLists.txt) + ADD_SUBDIRECTORY(internal) +ENDIF() diff --git a/Makefile.am b/Makefile.am index f4179f5cb47..2a89aea3c70 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \ SUBDIRS = . include @docs_dirs@ @zlib_dir@ \ @readline_topdir@ sql-common scripts \ @sql_union_dirs@ unittest \ - @sql_server@ @man_dirs@ tests \ + @sql_server@ @man_dirs@ tests internal \ netware @libmysqld_dirs@ \ mysql-test support-files sql-bench @tools_dirs@ \ win diff --git a/configure.in b/configure.in index 068328992e0..24e46259957 100644 --- a/configure.in +++ b/configure.in @@ -2849,6 +2849,10 @@ if test -d "$srcdir/cmd-line-utils/readline" ; then AC_CONFIG_FILES(cmd-line-utils/readline/Makefile) fi +if test -d "$srcdir/internal" ; then + AC_CONFIG_FILES(internal/Makefile) +fi + AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl unittest/Makefile unittest/mytap/Makefile unittest/mytap/t/Makefile dnl unittest/mysys/Makefile unittest/strings/Makefile dnl -- cgit v1.2.1 -- cgit v1.2.1 From 0893a90fd7d07d568a4b702b6c607bc406d8cba5 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Thu, 19 Jul 2012 15:55:41 +0200 Subject: Reverting broken configure/make stuff --- Makefile.am | 2 +- configure.in | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2a89aea3c70..f4179f5cb47 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \ SUBDIRS = . include @docs_dirs@ @zlib_dir@ \ @readline_topdir@ sql-common scripts \ @sql_union_dirs@ unittest \ - @sql_server@ @man_dirs@ tests internal \ + @sql_server@ @man_dirs@ tests \ netware @libmysqld_dirs@ \ mysql-test support-files sql-bench @tools_dirs@ \ win diff --git a/configure.in b/configure.in index 24e46259957..068328992e0 100644 --- a/configure.in +++ b/configure.in @@ -2849,10 +2849,6 @@ if test -d "$srcdir/cmd-line-utils/readline" ; then AC_CONFIG_FILES(cmd-line-utils/readline/Makefile) fi -if test -d "$srcdir/internal" ; then - AC_CONFIG_FILES(internal/Makefile) -fi - AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl unittest/Makefile unittest/mytap/Makefile unittest/mytap/t/Makefile dnl unittest/mysys/Makefile unittest/strings/Makefile dnl -- cgit v1.2.1 -- cgit v1.2.1 From 1cb513ba6b199c5bd4a2ae159839adb5dd7561a4 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 24 Jul 2012 09:27:00 +0400 Subject: Fixing wrong copyright. Index.xml was modified in 2005, while the copyright notice still mentioned 2003. --- sql/share/charsets/Index.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml index 80b844e2f19..07e7e37b798 100644 --- a/sql/share/charsets/Index.xml +++ b/sql/share/charsets/Index.xml @@ -3,7 +3,7 @@ - Copyright (C) 2003 MySQL AB + Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -- cgit v1.2.1 From d4caad52a524c6607ad37680226f7a3d8c0b4c35 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Tue, 24 Jul 2012 12:32:14 +0200 Subject: Fix bug#14318456 SPEC FILE DOES NOT RUN THE TEST SUITE DURING RPM BUILD Add a macro "runselftest" to the spec file for RPM builds. If its value is 1 (the default), the test suite will be run during the RPM build. To prevent that, add this to the rpmbuild command line: --define "runselftest 0" Failures of the test suite will NOT make the RPM build fail! support-files/mysql.spec.sh: Add the "runselftest" macro following the model provided by RedHat. This code is similar to what we plan to use for ULN RPMs. --- support-files/mysql.spec.sh | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 5b9a296d90a..0d673e5b339 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -252,6 +252,9 @@ Vendor: %{mysql_vendor} Provides: msqlormysql MySQL-server mysql BuildRequires: %{distro_buildreq} +# Regression tests may take a long time, override the default to skip them +%{!?runselftest:%global runselftest 1} + # Think about what you use here since the first step is to # run a rm -rf BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -403,6 +406,16 @@ For a description of MySQL see the base MySQL RPM or http://www.mysql.com/ ############################################################################## %build +# Fail quickly and obviously if user tries to build as root +%if %runselftest + if [ x"`id -u`" = x0 ]; then + echo "The MySQL regression tests may fail if run as root." + echo "If you really need to build the RPM as root, use" + echo "--define='runselftest 0' to skip the regression tests." + exit 1 + fi +%endif + # Be strict about variables, bail at earliest opportunity, etc. set -eu @@ -480,6 +493,13 @@ mkdir release make ${MAKE_JFLAG} VERBOSE=1 ) +%if %runselftest + MTR_BUILD_THREAD=auto + export MTR_BUILD_THREAD + + (cd release && make test-bt-fast || true) +%endif + ############################################################################## %install @@ -1146,6 +1166,14 @@ echo "=====" >> $STATUS_HISTORY # merging BK trees) ############################################################################## %changelog +* Tue Jul 24 2012 Joerg Bruehe + +- Add a macro "runselftest": + if set to 1 (default), the test suite will be run during the RPM build; + this can be oveeridden via the command line by adding + --define "runselftest 0" + Failures of the test suite will NOT make the RPM build fail! + * Wed Sep 28 2011 Joerg Bruehe - Fix duplicate mentioning of "mysql_plugin" and its manual page, -- cgit v1.2.1 From 03993d03a75049d2df659b46f8ec5e263b7ff1bd Mon Sep 17 00:00:00 2001 From: Sujatha Sivakumar Date: Tue, 24 Jul 2012 16:26:16 +0530 Subject: Bug#13961678:MULTI-STATEMENT TRANSACTION REQUIRED MORE THAN 'MAX_BINLOG_CACHE_SIZE' ERROR Problem: ======= MySQL returns following error in win64. "ERROR 1197 (HY000): Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again" when user tries to load >4G file even if max_binlog_cache_size set to maximum value. On Linux everything works fine. Analysis: ======== The `max_binlog_cache_size' variable is of type `ulonglong'. This value is set to `ULONGLONG_MAX' at the time of server start up. The above value is stored in an intermediate variable named `saved_max_binlog_cache_size' which is of type `ulong'. In visual c++ complier the `ulong' type is of 4bytes in size and hence the value is getting truncated to '4GB' and the cache is not able to grow beyond 4GB size. The same limitation is observed with "max_binlog_stmt_cache_size" as well. Similar fix has been applied. Fix: === As part of fix the type "ulong" is replaced with "my_off_t" which is of type "ulonglong". mysys/mf_iocache.c: Added debug statement to simulate a scenario where the cache file's current position is set to >4GB sql/log.cc: Replaced the type of `saved_max_binlog_cache_size' from "ulong" to "my_off_t", which is a type def for "ulonglong". --- mysys/mf_iocache.c | 7 ++++++- sql/log.cc | 8 ++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 03d11c6f6af..8c91befe905 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -1528,8 +1528,13 @@ int _my_b_get(IO_CACHE *info) int _my_b_write(register IO_CACHE *info, const uchar *Buffer, size_t Count) { size_t rest_length,length; + my_off_t pos_in_file= info->pos_in_file; - if (info->pos_in_file+info->buffer_length > info->end_of_file) + DBUG_EXECUTE_IF("simulate_huge_load_data_file", + { + pos_in_file=5000000000; + }); + if (pos_in_file+info->buffer_length > info->end_of_file) { my_errno=errno=EFBIG; return info->error = -1; diff --git a/sql/log.cc b/sql/log.cc index fc11dcc77ce..1cc94d2fb02 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -300,7 +300,7 @@ public: before_stmt_pos= MY_OFF_T_UNDEF; } - void set_binlog_cache_info(ulong param_max_binlog_cache_size, + void set_binlog_cache_info(my_off_t param_max_binlog_cache_size, ulong *param_ptr_binlog_cache_use, ulong *param_ptr_binlog_cache_disk_use) { @@ -377,7 +377,7 @@ private: is configured. This corresponds to either . max_binlog_cache_size or max_binlog_stmt_cache_size. */ - ulong saved_max_binlog_cache_size; + my_off_t saved_max_binlog_cache_size; /* Stores a pointer to the status variable that keeps track of the in-memory @@ -415,8 +415,8 @@ private: class binlog_cache_mngr { public: - binlog_cache_mngr(ulong param_max_binlog_stmt_cache_size, - ulong param_max_binlog_cache_size, + binlog_cache_mngr(my_off_t param_max_binlog_stmt_cache_size, + my_off_t param_max_binlog_cache_size, ulong *param_ptr_binlog_stmt_cache_use, ulong *param_ptr_binlog_stmt_cache_disk_use, ulong *param_ptr_binlog_cache_use, -- cgit v1.2.1 From 7baba64497ea0ac127fd86e10b7a60a27114fc65 Mon Sep 17 00:00:00 2001 From: Harin Vadodaria Date: Tue, 24 Jul 2012 18:45:58 +0530 Subject: Bug#13904906: YASSL PRE-AUTH CRASH WITH 5.1.62, 5.5.22 Problem: Valgrind reports errors when an invalid certificate is used on the client. Solution: Updated yaSSL to version 2.2.2. --- cmake/ssl.cmake | 2 +- extra/yassl/README | 11 +++- extra/yassl/include/lock.hpp | 9 +-- extra/yassl/include/openssl/ssl.h | 2 +- extra/yassl/include/yassl_error.hpp | 2 +- extra/yassl/src/cert_wrapper.cpp | 3 +- extra/yassl/src/lock.cpp | 4 +- extra/yassl/src/ssl.cpp | 3 +- extra/yassl/src/yassl_error.cpp | 7 +- extra/yassl/taocrypt/include/aes.hpp | 1 - extra/yassl/taocrypt/include/pwdbased.hpp | 4 +- extra/yassl/taocrypt/src/asn.cpp | 4 +- extra/yassl/taocrypt/src/coding.cpp | 21 ++++++ extra/yassl/taocrypt/taocrypt.dsw | 17 ++++- extra/yassl/taocrypt/test.dsp | 102 ------------------------------ extra/yassl/taocrypt/test/memory.cpp | 2 +- extra/yassl/taocrypt/test/test.dsp | 102 ++++++++++++++++++++++++++++++ extra/yassl/yassl.dsw | 5 +- 18 files changed, 170 insertions(+), 131 deletions(-) delete mode 100644 extra/yassl/taocrypt/test.dsp create mode 100644 extra/yassl/taocrypt/test/test.dsp diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake index 9b16bf09394..9cb80a2303c 100644 --- a/cmake/ssl.cmake +++ b/cmake/ssl.cmake @@ -25,7 +25,7 @@ MACRO (MYSQL_USE_BUNDLED_SSL) SET(SSL_LIBRARIES yassl taocrypt) SET(SSL_INCLUDE_DIRS ${INC_DIRS}) SET(SSL_INTERNAL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/mySTL) - SET(SSL_DEFINES "-DHAVE_YASSL -DYASSL_PURE_C -DYASSL_PREFIX -DHAVE_OPENSSL -DYASSL_THREAD_SAFE") + SET(SSL_DEFINES "-DHAVE_YASSL -DYASSL_PURE_C -DYASSL_PREFIX -DHAVE_OPENSSL -DMULTI_THREADED") CHANGE_SSL_SETTINGS("bundled") #Remove -fno-implicit-templates #(yassl sources cannot be compiled with it) diff --git a/extra/yassl/README b/extra/yassl/README index 7720a9453dd..24bdf32f989 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -12,7 +12,16 @@ before calling SSL_new(); *** end Note *** -yaSSL Release notes, version 2.1.2 (9/2/2011) +yaSSL Release notes, version 2.2.2 (7/5/2012) + + This release of yaSSL contains bug fixes and more security checks around + malicious certificates. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 2.1.2 (9/2/2011) This release of yaSSL contains bug fixes, better non-blocking support with SSL_write, and OpenSSL RSA public key format support. diff --git a/extra/yassl/include/lock.hpp b/extra/yassl/include/lock.hpp index ae875001633..487bedfcc70 100644 --- a/extra/yassl/include/lock.hpp +++ b/extra/yassl/include/lock.hpp @@ -27,7 +27,7 @@ Visual Studio Source Annotations header (sourceannotations.h) fails to compile if outside of the global namespace. */ -#ifdef YASSL_THREAD_SAFE +#ifdef MULTI_THREADED #ifdef _WIN32 #include #endif @@ -36,8 +36,9 @@ namespace yaSSL { -#ifdef YASSL_THREAD_SAFE +#ifdef MULTI_THREADED #ifdef _WIN32 + #include class Mutex { CRITICAL_SECTION cs_; @@ -77,7 +78,7 @@ namespace yaSSL { }; #endif // _WIN32 -#else // YASSL_THREAD_SAFE (WE'RE SINGLE) +#else // MULTI_THREADED (WE'RE SINGLE) class Mutex { public: @@ -87,7 +88,7 @@ namespace yaSSL { }; }; -#endif // YASSL_THREAD_SAFE +#endif // MULTI_THREADED diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index 0d99888da88..2fcba67cfdd 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -35,7 +35,7 @@ #include "rsa.h" -#define YASSL_VERSION "2.2.0" +#define YASSL_VERSION "2.2.2" #if defined(__cplusplus) diff --git a/extra/yassl/include/yassl_error.hpp b/extra/yassl/include/yassl_error.hpp index 87bb4c55e96..8efc7f72e87 100644 --- a/extra/yassl/include/yassl_error.hpp +++ b/extra/yassl/include/yassl_error.hpp @@ -65,7 +65,7 @@ enum YasslError { enum Library { yaSSL_Lib = 0, CryptoLib, SocketLib }; enum { MAX_ERROR_SZ = 80 }; -void SetErrorString(unsigned long, char*); +void SetErrorString(YasslError, char*); /* remove for now, if go back to exceptions use this wrapper // Base class for all yaSSL exceptions diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp index 7e73464001a..917cfa1a8fb 100644 --- a/extra/yassl/src/cert_wrapper.cpp +++ b/extra/yassl/src/cert_wrapper.cpp @@ -250,8 +250,7 @@ int CertManager::Validate() TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length()); TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_); - int err = cert.GetError().What(); - if ( err ) + if (int err = cert.GetError().What()) return err; const TaoCrypt::PublicKey& key = cert.GetPublicKey(); diff --git a/extra/yassl/src/lock.cpp b/extra/yassl/src/lock.cpp index 9eb41408ff7..d603440757f 100644 --- a/extra/yassl/src/lock.cpp +++ b/extra/yassl/src/lock.cpp @@ -26,7 +26,7 @@ namespace yaSSL { -#ifdef YASSL_THREAD_SAFE +#ifdef MULTI_THREADED #ifdef _WIN32 Mutex::Mutex() @@ -79,7 +79,7 @@ namespace yaSSL { #endif // _WIN32 -#endif // YASSL_THREAD_SAFE +#endif // MULTI_THREADED diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 00a3b885f88..ab5fee45038 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -27,7 +27,6 @@ - /* see man pages for function descriptions */ #include "runtime.hpp" @@ -1014,7 +1013,7 @@ char* ERR_error_string(unsigned long errNumber, char* buffer) static char* msg = (char*)"Please supply a buffer for error string"; if (buffer) { - SetErrorString(errNumber, buffer); + SetErrorString(YasslError(errNumber), buffer); return buffer; } diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp index 74735347841..b9fccf782f0 100644 --- a/extra/yassl/src/yassl_error.cpp +++ b/extra/yassl/src/yassl_error.cpp @@ -31,11 +31,6 @@ #pragma warning(disable: 4996) #endif -#ifdef _MSC_VER - // 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy - #pragma warning(disable: 4996) -#endif - namespace yaSSL { @@ -60,7 +55,7 @@ Library Error::get_lib() const */ -void SetErrorString(unsigned long error, char* buffer) +void SetErrorString(YasslError error, char* buffer) { using namespace TaoCrypt; const int max = MAX_ERROR_SZ; // shorthand diff --git a/extra/yassl/taocrypt/include/aes.hpp b/extra/yassl/taocrypt/include/aes.hpp index dc19c98a83a..e2041fc9350 100644 --- a/extra/yassl/taocrypt/include/aes.hpp +++ b/extra/yassl/taocrypt/include/aes.hpp @@ -92,7 +92,6 @@ typedef BlockCipher AES_CBC_Encryption; typedef BlockCipher AES_CBC_Decryption; - } // naemspace #endif // TAO_CRYPT_AES_HPP diff --git a/extra/yassl/taocrypt/include/pwdbased.hpp b/extra/yassl/taocrypt/include/pwdbased.hpp index f40a336e2c3..d050fd8988b 100644 --- a/extra/yassl/taocrypt/include/pwdbased.hpp +++ b/extra/yassl/taocrypt/include/pwdbased.hpp @@ -48,9 +48,11 @@ word32 PBKDF2_HMAC::DeriveKey(byte* derived, word32 dLen, const byte* pwd, word32 pLen, const byte* salt, word32 sLen, word32 iterations) const { - if (dLen > MaxDerivedKeyLength()) + if (dLen > MaxDerivedKeyLength()) return 0; + if (iterations < 0) + return 0; ByteBlock buffer(T::DIGEST_SIZE); HMAC hmac; diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp index 5ec4cac1c44..ad054809879 100644 --- a/extra/yassl/taocrypt/src/asn.cpp +++ b/extra/yassl/taocrypt/src/asn.cpp @@ -154,6 +154,8 @@ word32 GetLength(Source& source) else length = b; + if (source.IsLeft(length) == false) return 0; + return length; } @@ -832,7 +834,7 @@ void CertDecoder::GetName(NameType nt) if (email) { if (!(ptr = AddTag(ptr, buf_end, "/emailAddress=", 14, length))) { source_.SetError(CONTENT_E); - return; + return; } } diff --git a/extra/yassl/taocrypt/src/coding.cpp b/extra/yassl/taocrypt/src/coding.cpp index 8647ea13f20..ba485eea77e 100644 --- a/extra/yassl/taocrypt/src/coding.cpp +++ b/extra/yassl/taocrypt/src/coding.cpp @@ -103,6 +103,16 @@ void HexDecoder::Decode() byte b = coded_.next() - 0x30; // 0 starts at 0x30 byte b2 = coded_.next() - 0x30; + // sanity checks + if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) { + coded_.SetError(PEM_E); + return; + } + if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0])) { + coded_.SetError(PEM_E); + return; + } + b = hexDecode[b]; b2 = hexDecode[b2]; @@ -178,6 +188,7 @@ void Base64Decoder::Decode() { word32 bytes = coded_.size(); word32 plainSz = bytes - ((bytes + (pemLineSz - 1)) / pemLineSz); + const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1; plainSz = ((plainSz * 3) / 4) + 3; decoded_.New(plainSz); @@ -200,6 +211,16 @@ void Base64Decoder::Decode() if (e4 == pad) pad4 = true; + if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) { + coded_.SetError(PEM_E); + return; + } + + if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) { + coded_.SetError(PEM_E); + return; + } + e1 = base64Decode[e1 - 0x2B]; e2 = base64Decode[e2 - 0x2B]; e3 = (e3 == pad) ? 0 : base64Decode[e3 - 0x2B]; diff --git a/extra/yassl/taocrypt/taocrypt.dsw b/extra/yassl/taocrypt/taocrypt.dsw index d10d7534c3d..43115069160 100644 --- a/extra/yassl/taocrypt/taocrypt.dsw +++ b/extra/yassl/taocrypt/taocrypt.dsw @@ -3,6 +3,21 @@ Microsoft Developer Studio Workspace File, Format Version 6.00 ############################################################################### +Project: "benchmark"=.\benchmark\benchmark.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name taocrypt + End Project Dependency +}}} + +############################################################################### + Project: "taocrypt"=.\taocrypt.dsp - Package Owner=<4> Package=<5> @@ -15,7 +30,7 @@ Package=<4> ############################################################################### -Project: "test"=.\test.dsp - Package Owner=<4> +Project: "test"=.\test\test.dsp - Package Owner=<4> Package=<5> {{{ diff --git a/extra/yassl/taocrypt/test.dsp b/extra/yassl/taocrypt/test.dsp deleted file mode 100644 index 1084f8e06e3..00000000000 --- a/extra/yassl/taocrypt/test.dsp +++ /dev/null @@ -1,102 +0,0 @@ -# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=test - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "test.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "test - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "test___Win32_Release" -# PROP BASE Intermediate_Dir "test___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "test\Release" -# PROP Intermediate_Dir "test\Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /O2 /I "include" /I "mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "test - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "test___Win32_Debug" -# PROP BASE Intermediate_Dir "test___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "test\Debug" -# PROP Intermediate_Dir "test\Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "test - Win32 Release" -# Name "test - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\test\test.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/extra/yassl/taocrypt/test/memory.cpp b/extra/yassl/taocrypt/test/memory.cpp index ec398a64c45..a9b21f94902 100644 --- a/extra/yassl/taocrypt/test/memory.cpp +++ b/extra/yassl/taocrypt/test/memory.cpp @@ -31,7 +31,7 @@ To use MemoryTracker merely add this file to your project No need to instantiate anything -If your app is multi threaded define YASSL_THREAD_SAFE +If your app is multi threaded define MULTI_THREADED *********************************************************************/ diff --git a/extra/yassl/taocrypt/test/test.dsp b/extra/yassl/taocrypt/test/test.dsp new file mode 100644 index 00000000000..93b369de3d9 --- /dev/null +++ b/extra/yassl/taocrypt/test/test.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "test___Win32_Release" +# PROP BASE Intermediate_Dir "test___Win32_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../include" /I "../mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "test___Win32_Debug" +# PROP BASE Intermediate_Dir "test___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../include" /I "../mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "test - Win32 Release" +# Name "test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\test.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/extra/yassl/yassl.dsw b/extra/yassl/yassl.dsw index 288c88dfd5b..8da089fc1fa 100644 --- a/extra/yassl/yassl.dsw +++ b/extra/yassl/yassl.dsw @@ -90,7 +90,7 @@ Package=<4> ############################################################################### -Project: "test"=.\taocrypt\test.dsp - Package Owner=<4> +Project: "test"=.\taocrypt\test\test.dsp - Package Owner=<4> Package=<5> {{{ @@ -113,9 +113,6 @@ Package=<5> Package=<4> {{{ - Begin Project Dependency - Project_Dep_Name taocrypt - End Project Dependency Begin Project Dependency Project_Dep_Name yassl End Project Dependency -- cgit v1.2.1 From 1c6f78e337bd725c0254cc235e16844e7bfdfd8e Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Wed, 25 Jul 2012 10:48:16 +0530 Subject: Bug #13113026 INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRUFROM 5.6 BACKPORT Backporting the WL#5716, "Information schema table for InnoDB buffer pool information". Backporting revisions 2876.244.113, 2876.244.102 from mysql-trunk. rb://1177 approved by Jimmy Yang. --- mysql-test/r/information_schema.result | 2 + mysql-test/r/mysqlshow.result | 14 +- .../r/innodb_information_schema_buffer.result | 130 ++ .../innodb/t/innodb_information_schema_buffer.test | 76 + storage/innobase/buf/buf0buf.c | 11 +- storage/innobase/handler/ha_innodb.cc | 5 +- storage/innobase/handler/i_s.cc | 1871 +++++++++++++++++++- storage/innobase/handler/i_s.h | 3 + storage/innobase/include/buf0buf.h | 33 +- storage/innobase/include/buf0buf.ic | 26 + storage/innobase/include/fil0fil.h | 2 + storage/innobase/include/log0log.h | 3 + 12 files changed, 2151 insertions(+), 25 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb_information_schema_buffer.result create mode 100644 mysql-test/suite/innodb/t/innodb_information_schema_buffer.test diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 88a56edbb5c..062fa0a92af 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -863,6 +863,8 @@ TABLES TABLE_NAME select TABLE_CONSTRAINTS TABLE_NAME select TABLE_PRIVILEGES TABLE_NAME select VIEWS TABLE_NAME select +INNODB_BUFFER_PAGE TABLE_NAME select +INNODB_BUFFER_PAGE_LRU TABLE_NAME select delete from mysql.user where user='mysqltest_4'; delete from mysql.db where user='mysqltest_4'; flush privileges; diff --git a/mysql-test/r/mysqlshow.result b/mysql-test/r/mysqlshow.result index 4293465df67..7280d036d62 100644 --- a/mysql-test/r/mysqlshow.result +++ b/mysql-test/r/mysqlshow.result @@ -109,13 +109,16 @@ Database: information_schema | TRIGGERS | | USER_PRIVILEGES | | VIEWS | -| INNODB_CMP_RESET | +| INNODB_BUFFER_PAGE | | INNODB_TRX | -| INNODB_CMPMEM_RESET | +| INNODB_BUFFER_POOL_STATS | | INNODB_LOCK_WAITS | | INNODB_CMPMEM | | INNODB_CMP | | INNODB_LOCKS | +| INNODB_CMPMEM_RESET | +| INNODB_CMP_RESET | +| INNODB_BUFFER_PAGE_LRU | +---------------------------------------+ Database: INFORMATION_SCHEMA +---------------------------------------+ @@ -151,13 +154,16 @@ Database: INFORMATION_SCHEMA | TRIGGERS | | USER_PRIVILEGES | | VIEWS | -| INNODB_CMP_RESET | +| INNODB_BUFFER_PAGE | | INNODB_TRX | -| INNODB_CMPMEM_RESET | +| INNODB_BUFFER_POOL_STATS | | INNODB_LOCK_WAITS | | INNODB_CMPMEM | | INNODB_CMP | | INNODB_LOCKS | +| INNODB_CMPMEM_RESET | +| INNODB_CMP_RESET | +| INNODB_BUFFER_PAGE_LRU | +---------------------------------------+ Wildcard: inf_rmation_schema +--------------------+ diff --git a/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result b/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result new file mode 100644 index 00000000000..b4a350e77a3 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result @@ -0,0 +1,130 @@ +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; +SELECT count(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; +SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; +CREATE TABLE infoschema_buffer_test (col1 INT) ENGINE = INNODB; +INSERT INTO infoschema_buffer_test VALUES(9); +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test" + and PAGE_STATE="file_page" and PAGE_TYPE="index"; +TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE +test/infoschema_buffer_test GEN_CLUST_INDEX 1 29 FILE_PAGE INDEX +INSERT INTO infoschema_buffer_test VALUES(19); +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test" +and PAGE_STATE="file_page" and PAGE_TYPE="index"; +TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE +test/infoschema_buffer_test GEN_CLUST_INDEX 2 58 FILE_PAGE INDEX +CREATE INDEX idx ON infoschema_buffer_test(col1); +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test" +and PAGE_STATE="file_page" and INDEX_NAME = "idx" and PAGE_TYPE="index"; +TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE +test/infoschema_buffer_test idx 2 32 FILE_PAGE INDEX +DROP TABLE infoschema_buffer_test; +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test"; +TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE +CREATE TABLE infoschema_parent (id INT NOT NULL, PRIMARY KEY (id)) +ENGINE=INNODB; +CREATE TABLE infoschema_child (id INT, parent_id INT, INDEX par_ind (parent_id), +FOREIGN KEY (parent_id) +REFERENCES infoschema_parent(id) +ON DELETE CASCADE) +ENGINE=INNODB; +SELECT count(*) +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_child" and PAGE_STATE="file_page" +and PAGE_TYPE="index"; +count(*) +2 +DROP TABLE infoschema_child; +DROP TABLE infoschema_parent; +show create table information_schema.innodb_buffer_page; +Table Create Table +INNODB_BUFFER_PAGE CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE` ( + `POOL_ID` bigint(21) unsigned NOT NULL DEFAULT '0', + `BLOCK_ID` bigint(21) unsigned NOT NULL DEFAULT '0', + `SPACE` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGE_NUMBER` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGE_TYPE` varchar(64) DEFAULT NULL, + `FLUSH_TYPE` bigint(21) unsigned NOT NULL DEFAULT '0', + `FIX_COUNT` bigint(21) unsigned NOT NULL DEFAULT '0', + `IS_HASHED` varchar(3) DEFAULT NULL, + `NEWEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT '0', + `OLDEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT '0', + `ACCESS_TIME` bigint(21) unsigned NOT NULL DEFAULT '0', + `TABLE_NAME` varchar(1024) DEFAULT NULL, + `INDEX_NAME` varchar(1024) DEFAULT NULL, + `NUMBER_RECORDS` bigint(21) unsigned NOT NULL DEFAULT '0', + `DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0', + `COMPRESSED_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGE_STATE` varchar(64) DEFAULT NULL, + `IO_FIX` varchar(64) DEFAULT NULL, + `IS_OLD` varchar(3) DEFAULT NULL, + `FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT '0' +) ENGINE=MEMORY DEFAULT CHARSET=utf8 +show create table information_schema.innodb_buffer_page_lru; +Table Create Table +INNODB_BUFFER_PAGE_LRU CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE_LRU` ( + `POOL_ID` bigint(21) unsigned NOT NULL DEFAULT '0', + `LRU_POSITION` bigint(21) unsigned NOT NULL DEFAULT '0', + `SPACE` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGE_NUMBER` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGE_TYPE` varchar(64) DEFAULT NULL, + `FLUSH_TYPE` bigint(21) unsigned NOT NULL DEFAULT '0', + `FIX_COUNT` bigint(21) unsigned NOT NULL DEFAULT '0', + `IS_HASHED` varchar(3) DEFAULT NULL, + `NEWEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT '0', + `OLDEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT '0', + `ACCESS_TIME` bigint(21) unsigned NOT NULL DEFAULT '0', + `TABLE_NAME` varchar(1024) DEFAULT NULL, + `INDEX_NAME` varchar(1024) DEFAULT NULL, + `NUMBER_RECORDS` bigint(21) unsigned NOT NULL DEFAULT '0', + `DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0', + `COMPRESSED_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0', + `COMPRESSED` varchar(3) DEFAULT NULL, + `IO_FIX` varchar(64) DEFAULT NULL, + `IS_OLD` varchar(3) DEFAULT NULL, + `FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT '0' +) ENGINE=MEMORY DEFAULT CHARSET=utf8 +show create table information_schema.innodb_buffer_pool_stats; +Table Create Table +INNODB_BUFFER_POOL_STATS CREATE TEMPORARY TABLE `INNODB_BUFFER_POOL_STATS` ( + `POOL_ID` bigint(21) unsigned NOT NULL DEFAULT '0', + `POOL_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0', + `FREE_BUFFERS` bigint(21) unsigned NOT NULL DEFAULT '0', + `DATABASE_PAGES` bigint(21) unsigned NOT NULL DEFAULT '0', + `OLD_DATABASE_PAGES` bigint(21) unsigned NOT NULL DEFAULT '0', + `MODIFIED_DATABASE_PAGES` bigint(21) unsigned NOT NULL DEFAULT '0', + `PENDING_DECOMPRESS` bigint(21) unsigned NOT NULL DEFAULT '0', + `PENDING_READS` bigint(21) unsigned NOT NULL DEFAULT '0', + `PENDING_FLUSH_LRU` bigint(21) unsigned NOT NULL DEFAULT '0', + `PENDING_FLUSH_LIST` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGES_MADE_YOUNG` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGES_NOT_MADE_YOUNG` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGES_MADE_YOUNG_RATE` double NOT NULL DEFAULT '0', + `PAGES_MADE_NOT_YOUNG_RATE` double NOT NULL DEFAULT '0', + `NUMBER_PAGES_READ` bigint(21) unsigned NOT NULL DEFAULT '0', + `NUMBER_PAGES_CREATED` bigint(21) unsigned NOT NULL DEFAULT '0', + `NUMBER_PAGES_WRITTEN` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGES_READ_RATE` double NOT NULL DEFAULT '0', + `PAGES_CREATE_RATE` double NOT NULL DEFAULT '0', + `PAGES_WRITTEN_RATE` double NOT NULL DEFAULT '0', + `NUMBER_PAGES_GET` bigint(21) unsigned NOT NULL DEFAULT '0', + `HIT_RATE` bigint(21) unsigned NOT NULL DEFAULT '0', + `YOUNG_MAKE_PER_THOUSAND_GETS` bigint(21) unsigned NOT NULL DEFAULT '0', + `NOT_YOUNG_MAKE_PER_THOUSAND_GETS` bigint(21) unsigned NOT NULL DEFAULT '0', + `NUMBER_PAGES_READ_AHEAD` bigint(21) unsigned NOT NULL DEFAULT '0', + `NUMBER_READ_AHEAD_EVICTED` bigint(21) unsigned NOT NULL DEFAULT '0', + `READ_AHEAD_RATE` double NOT NULL DEFAULT '0', + `READ_AHEAD_EVICTED_RATE` double NOT NULL DEFAULT '0', + `LRU_IO_TOTAL` bigint(21) unsigned NOT NULL DEFAULT '0', + `LRU_IO_CURRENT` bigint(21) unsigned NOT NULL DEFAULT '0', + `UNCOMPRESS_TOTAL` bigint(21) unsigned NOT NULL DEFAULT '0', + `UNCOMPRESS_CURRENT` bigint(21) unsigned NOT NULL DEFAULT '0' +) ENGINE=MEMORY DEFAULT CHARSET=utf8 diff --git a/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test b/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test new file mode 100644 index 00000000000..751a2bd6b5e --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test @@ -0,0 +1,76 @@ +# Exercise the code path for INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS +# and INFORMATION_SCHEMA.INNODB_BUFFER_PAGE + +-- source include/have_innodb.inc + +-- disable_result_log +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; + +# How many buffer pools we have +SELECT count(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; + +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; + +# This gives the over all buffer pool size +SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; + +-- enable_result_log + +# Create a table and check its page info behave correctly in the pool +CREATE TABLE infoschema_buffer_test (col1 INT) ENGINE = INNODB; + +INSERT INTO infoschema_buffer_test VALUES(9); + +# We should be able to see this table in the buffer pool if we check +# right away +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test" + and PAGE_STATE="file_page" and PAGE_TYPE="index"; + +# The NUMBER_RECORDS and DATA_SIZE should check with each insertion +INSERT INTO infoschema_buffer_test VALUES(19); + +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test" +and PAGE_STATE="file_page" and PAGE_TYPE="index"; + +CREATE INDEX idx ON infoschema_buffer_test(col1); + +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test" +and PAGE_STATE="file_page" and INDEX_NAME = "idx" and PAGE_TYPE="index"; + + +# Check the buffer after dropping the table +DROP TABLE infoschema_buffer_test; + +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test"; + +# Do one more test +#--replace_regex /'*[0-9]*'/'NUM'/ +CREATE TABLE infoschema_parent (id INT NOT NULL, PRIMARY KEY (id)) +ENGINE=INNODB; + +CREATE TABLE infoschema_child (id INT, parent_id INT, INDEX par_ind (parent_id), + FOREIGN KEY (parent_id) + REFERENCES infoschema_parent(id) + ON DELETE CASCADE) +ENGINE=INNODB; + +SELECT count(*) +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_child" and PAGE_STATE="file_page" +and PAGE_TYPE="index"; + +DROP TABLE infoschema_child; +DROP TABLE infoschema_parent; + +show create table information_schema.innodb_buffer_page; +show create table information_schema.innodb_buffer_page_lru; +show create table information_schema.innodb_buffer_pool_stats; + diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index 32d376136e6..70841a168ab 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -294,14 +294,7 @@ be effective only if PFS_GROUP_BUFFER_SYNC is defined. */ # endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */ #endif /* UNIV_PFS_MUTEX || UNIV_PFS_RWLOCK */ -/** A chunk of buffers. The buffer pool is allocated in chunks. */ -struct buf_chunk_struct{ - ulint mem_size; /*!< allocated size of the chunk */ - ulint size; /*!< size of frames[] and blocks[] */ - void* mem; /*!< pointer to the memory area which - was allocated for the frames */ - buf_block_t* blocks; /*!< array of buffer control blocks */ -}; + /********************************************************************//** Gets the smallest oldest_modification lsn for any page in the pool. Returns @@ -4424,7 +4417,7 @@ buf_stats_aggregate_pool_info( Collect buffer pool stats information for a buffer pool. Also record aggregated stats if there are more than one buffer pool in the server */ -static +UNIV_INTERN void buf_stats_get_pool_info( /*====================*/ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 60a62482f9c..a68ed48fead 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -11767,7 +11767,10 @@ i_s_innodb_lock_waits, i_s_innodb_cmp, i_s_innodb_cmp_reset, i_s_innodb_cmpmem, -i_s_innodb_cmpmem_reset +i_s_innodb_cmpmem_reset, +i_s_innodb_buffer_page, +i_s_innodb_buffer_page_lru, +i_s_innodb_buffer_stats mysql_declare_plugin_end; /** @brief Initialize the default value of innodb_commit_concurrency. diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index e9905930699..f4916b48641 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -45,8 +45,93 @@ extern "C" { #include "srv0start.h" /* for srv_was_started */ #include "trx0i_s.h" #include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */ +#include "btr0btr.h" +#include "page0zip.h" +#include "log0log.h" } +/** structure associates a name string with a file page type and/or buffer +page state. */ +struct buffer_page_desc_str_struct{ + const char* type_str; /*!< String explain the page + type/state */ + ulint type_value; /*!< Page type or page state */ +}; + +typedef struct buffer_page_desc_str_struct buf_page_desc_str_t; + +/** Any states greater than FIL_PAGE_TYPE_LAST would be treated as unknown. */ +#define I_S_PAGE_TYPE_UNKNOWN (FIL_PAGE_TYPE_LAST + 1) + +/** We also define I_S_PAGE_TYPE_INDEX as the Index Page's position +in i_s_page_type[] array */ +#define I_S_PAGE_TYPE_INDEX 1 + +/** Name string for File Page Types */ +static buf_page_desc_str_t i_s_page_type[] = { + {"ALLOCATED", FIL_PAGE_TYPE_ALLOCATED}, + {"INDEX", FIL_PAGE_INDEX}, + {"UNDO_LOG", FIL_PAGE_UNDO_LOG}, + {"INODE", FIL_PAGE_INODE}, + {"IBUF_FREE_LIST", FIL_PAGE_IBUF_FREE_LIST}, + {"IBUF_BITMAP", FIL_PAGE_IBUF_BITMAP}, + {"SYSTEM", FIL_PAGE_TYPE_SYS}, + {"TRX_SYSTEM", FIL_PAGE_TYPE_TRX_SYS}, + {"FILE_SPACE_HEADER", FIL_PAGE_TYPE_FSP_HDR}, + {"EXTENT_DESCRIPTOR", FIL_PAGE_TYPE_XDES}, + {"BLOB", FIL_PAGE_TYPE_BLOB}, + {"COMPRESSED_BLOB", FIL_PAGE_TYPE_ZBLOB}, + {"COMPRESSED_BLOB2", FIL_PAGE_TYPE_ZBLOB2}, + {"UNKNOWN", I_S_PAGE_TYPE_UNKNOWN} +}; + +/* Check if we can hold all page type in a 4 bit value */ +#if I_S_PAGE_TYPE_UNKNOWN > 1<<4 +# error "i_s_page_type[] is too large" +#endif + +/** This structure defines information we will fetch from pages +currently cached in the buffer pool. It will be used to populate +table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE */ +struct buffer_page_info_struct{ + ulint block_id; /*!< Buffer Pool block ID */ + unsigned space_id:32; /*!< Tablespace ID */ + unsigned page_num:32; /*!< Page number/offset */ + unsigned access_time:32; /*!< Time of first access */ + unsigned pool_id:MAX_BUFFER_POOLS_BITS; + /*!< Buffer Pool ID. Must be less than + MAX_BUFFER_POOLS */ + unsigned flush_type:2; /*!< Flush type */ + unsigned io_fix:2; /*!< type of pending I/O operation */ + unsigned fix_count:19; /*!< Count of how manyfold this block + is bufferfixed */ + unsigned hashed:1; /*!< Whether hash index has been + built on this page */ + unsigned is_old:1; /*!< TRUE if the block is in the old + blocks in buf_pool->LRU_old */ + unsigned freed_page_clock:31; /*!< the value of + buf_pool->freed_page_clock */ + unsigned zip_ssize:PAGE_ZIP_SSIZE_BITS; + /*!< Compressed page size */ + unsigned page_state:BUF_PAGE_STATE_BITS; /*!< Page state */ + unsigned page_type:4; /*!< Page type */ + unsigned num_recs:UNIV_PAGE_SIZE_SHIFT-2; + /*!< Number of records on Page */ + unsigned data_size:UNIV_PAGE_SIZE_SHIFT; + /*!< Sum of the sizes of the records */ + lsn_t newest_mod; /*!< Log sequence number of + the youngest modification */ + lsn_t oldest_mod; /*!< Log sequence number of + the oldest modification */ + index_id_t index_id; /*!< Index ID if a index page */ +}; + +typedef struct buffer_page_info_struct buf_page_info_t; + +/** maximum number of buffer page info we would cache. */ +#define MAX_BUF_INFO_CACHED 10000 + + #define OK(expr) \ if ((expr) != 0) { \ DBUG_RETURN(1); \ @@ -1792,18 +1877,1786 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset = STRUCT_FLD(flags, 0UL), }; +/* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */ +static ST_FIELD_INFO i_s_innodb_buffer_stats_fields_info[] = +{ +#define IDX_BUF_STATS_POOL_ID 0 + {STRUCT_FLD(field_name, "POOL_ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_POOL_SIZE 1 + {STRUCT_FLD(field_name, "POOL_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_FREE_BUFFERS 2 + {STRUCT_FLD(field_name, "FREE_BUFFERS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_LRU_LEN 3 + {STRUCT_FLD(field_name, "DATABASE_PAGES"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_OLD_LRU_LEN 4 + {STRUCT_FLD(field_name, "OLD_DATABASE_PAGES"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_FLUSH_LIST_LEN 5 + {STRUCT_FLD(field_name, "MODIFIED_DATABASE_PAGES"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PENDING_ZIP 6 + {STRUCT_FLD(field_name, "PENDING_DECOMPRESS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PENDING_READ 7 + {STRUCT_FLD(field_name, "PENDING_READS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_FLUSH_LRU 8 + {STRUCT_FLD(field_name, "PENDING_FLUSH_LRU"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_FLUSH_LIST 9 + {STRUCT_FLD(field_name, "PENDING_FLUSH_LIST"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_YOUNG 10 + {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_NOT_YOUNG 11 + {STRUCT_FLD(field_name, "PAGES_NOT_MADE_YOUNG"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_YOUNG_RATE 12 + {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 13 + {STRUCT_FLD(field_name, "PAGES_MADE_NOT_YOUNG_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_READ 14 + {STRUCT_FLD(field_name, "NUMBER_PAGES_READ"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_CREATED 15 + {STRUCT_FLD(field_name, "NUMBER_PAGES_CREATED"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_WRITTEN 16 + {STRUCT_FLD(field_name, "NUMBER_PAGES_WRITTEN"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_READ_RATE 17 + {STRUCT_FLD(field_name, "PAGES_READ_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_CREATE_RATE 18 + {STRUCT_FLD(field_name, "PAGES_CREATE_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_WRITTEN_RATE 19 + {STRUCT_FLD(field_name, "PAGES_WRITTEN_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_GET 20 + {STRUCT_FLD(field_name, "NUMBER_PAGES_GET"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_HIT_RATE 21 + {STRUCT_FLD(field_name, "HIT_RATE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_MADE_YOUNG_PCT 22 + {STRUCT_FLD(field_name, "YOUNG_MAKE_PER_THOUSAND_GETS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 23 + {STRUCT_FLD(field_name, "NOT_YOUNG_MAKE_PER_THOUSAND_GETS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_READ_AHREAD 24 + {STRUCT_FLD(field_name, "NUMBER_PAGES_READ_AHEAD"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_READ_AHEAD_EVICTED 25 + {STRUCT_FLD(field_name, "NUMBER_READ_AHEAD_EVICTED"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_READ_AHEAD_RATE 26 + {STRUCT_FLD(field_name, "READ_AHEAD_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 27 + {STRUCT_FLD(field_name, "READ_AHEAD_EVICTED_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_LRU_IO_SUM 28 + {STRUCT_FLD(field_name, "LRU_IO_TOTAL"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_LRU_IO_CUR 29 + {STRUCT_FLD(field_name, "LRU_IO_CURRENT"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_UNZIP_SUM 30 + {STRUCT_FLD(field_name, "UNCOMPRESS_TOTAL"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_UNZIP_CUR 31 + {STRUCT_FLD(field_name, "UNCOMPRESS_CURRENT"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + END_OF_ST_FIELD_INFO +}; + /*******************************************************************//** -Unbind a dynamic INFORMATION_SCHEMA table. -@return 0 on success */ +Fill Information Schema table INNODB_BUFFER_POOL_STATS for a particular +buffer pool +@return 0 on success, 1 on failure */ static int -i_s_common_deinit( -/*==============*/ - void* p) /*!< in/out: table schema object */ +i_s_innodb_stats_fill( +/*==================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + const buf_pool_info_t* info) /*!< in: buffer pool + information */ { - DBUG_ENTER("i_s_common_deinit"); + TABLE* table; + Field** fields; + + DBUG_ENTER("i_s_innodb_stats_fill"); + + table = tables->table; + + fields = table->field; + + OK(fields[IDX_BUF_STATS_POOL_ID]->store(info->pool_unique_id)); + + OK(fields[IDX_BUF_STATS_POOL_SIZE]->store(info->pool_size)); + + OK(fields[IDX_BUF_STATS_LRU_LEN]->store(info->lru_len)); + + OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store(info->old_lru_len)); + + OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store(info->free_list_len)); + + OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store( + info->flush_list_len)); + + OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store(info->n_pend_unzip)); + + OK(fields[IDX_BUF_STATS_PENDING_READ]->store(info->n_pend_reads)); + + OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store(info->n_pending_flush_lru)); + + OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store(info->n_pending_flush_list)); + + OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store(info->n_pages_made_young)); + + OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store( + info->n_pages_not_made_young)); + + OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store( + info->page_made_young_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store( + info->page_not_made_young_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_READ]->store(info->n_pages_read)); + + OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store(info->n_pages_created)); + + OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store(info->n_pages_written)); + + OK(fields[IDX_BUF_STATS_GET]->store(info->n_page_gets)); + + OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store(info->pages_read_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store(info->pages_created_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store(info->pages_written_rate)); + + if (info->n_page_get_delta) { + OK(fields[IDX_BUF_STATS_HIT_RATE]->store( + 1000 - (1000 * info->page_read_delta + / info->n_page_get_delta))); + + OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store( + 1000 * info->young_making_delta + / info->n_page_get_delta)); + + OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store( + 1000 * info->not_young_making_delta + / info->n_page_get_delta)); + } else { + OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0)); + OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0)); + OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0)); + } + + OK(fields[IDX_BUF_STATS_READ_AHREAD]->store(info->n_ra_pages_read)); + + OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store( + info->n_ra_pages_evicted)); + + OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store( + info->pages_readahead_rate)); + + OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store( + info->pages_evicted_rate)); + + OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store(info->io_sum)); + + OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store(info->io_cur)); + + OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store(info->unzip_sum)); + + OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store( info->unzip_cur)); + + DBUG_RETURN(schema_table_store_record(thd, table)); +} + +/*******************************************************************//** +This is the function that loops through each buffer pool and fetch buffer +pool stats to information schema table: I_S_INNODB_BUFFER_POOL_STATS +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_stats_fill_table( +/*===============================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + Item* ) /*!< in: condition (ignored) */ +{ + int status = 0; + buf_pool_info_t* pool_info; + + DBUG_ENTER("i_s_innodb_buffer_fill_general"); + + /* Only allow the PROCESS privilege holder to access the stats */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + pool_info = (buf_pool_info_t*) mem_zalloc( + srv_buf_pool_instances * sizeof *pool_info); + + /* Walk through each buffer pool */ + for (ulint i = 0; i < srv_buf_pool_instances; i++) { + buf_pool_t* buf_pool; + + buf_pool = buf_pool_from_array(i); + + /* Fetch individual buffer pool info */ + buf_stats_get_pool_info(buf_pool, i, pool_info); + + status = i_s_innodb_stats_fill(thd, tables, &pool_info[i]); + + /* If something goes wrong, break and return */ + if (status) { + break; + } + } + + mem_free(pool_info); + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_pool_stats_init( +/*==============================*/ + void* p) /*!< in/out: table schema object */ +{ + ST_SCHEMA_TABLE* schema; + + DBUG_ENTER("i_s_innodb_buffer_pool_stats_init"); + + schema = reinterpret_cast(p); + + schema->fields_info = i_s_innodb_buffer_stats_fields_info; + schema->fill_table = i_s_innodb_buffer_stats_fill_table; + + DBUG_RETURN(0); +} + +UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_stats = +{ + /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + /* int */ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + + /* pointer to type-specific plugin descriptor */ + /* void* */ + STRUCT_FLD(info, &i_s_info), + + /* plugin name */ + /* const char* */ + STRUCT_FLD(name, "INNODB_BUFFER_POOL_STATS"), + + /* plugin author (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(author, plugin_author), + + /* general descriptive text (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(descr, "InnoDB Buffer Pool Statistics Information "), + + /* the plugin license (PLUGIN_LICENSE_XXX) */ + /* int */ + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + + /* the function to invoke when plugin is loaded */ + /* int (*)(void*); */ + STRUCT_FLD(init, i_s_innodb_buffer_pool_stats_init), + + /* the function to invoke when plugin is unloaded */ + /* int (*)(void*); */ + STRUCT_FLD(deinit, i_s_common_deinit), + + /* plugin version (for SHOW PLUGINS) */ + /* unsigned int */ + STRUCT_FLD(version, INNODB_VERSION_SHORT), + + /* struct st_mysql_show_var* */ + STRUCT_FLD(status_vars, NULL), + + /* struct st_mysql_sys_var** */ + STRUCT_FLD(system_vars, NULL), + + /* reserved for dependency checking */ + /* void* */ + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), +}; + +/* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */ +static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = +{ +#define IDX_BUFFER_POOL_ID 0 + {STRUCT_FLD(field_name, "POOL_ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_BLOCK_ID 1 + {STRUCT_FLD(field_name, "BLOCK_ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_SPACE 2 + {STRUCT_FLD(field_name, "SPACE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_NUM 3 + {STRUCT_FLD(field_name, "PAGE_NUMBER"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_TYPE 4 + {STRUCT_FLD(field_name, "PAGE_TYPE"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_FLUSH_TYPE 5 + {STRUCT_FLD(field_name, "FLUSH_TYPE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_FIX_COUNT 6 + {STRUCT_FLD(field_name, "FIX_COUNT"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_HASHED 7 + {STRUCT_FLD(field_name, "IS_HASHED"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_NEWEST_MOD 8 + {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_OLDEST_MOD 9 + {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_ACCESS_TIME 10 + {STRUCT_FLD(field_name, "ACCESS_TIME"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_TABLE_NAME 11 + {STRUCT_FLD(field_name, "TABLE_NAME"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_INDEX_NAME 12 + {STRUCT_FLD(field_name, "INDEX_NAME"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_NUM_RECS 13 + {STRUCT_FLD(field_name, "NUMBER_RECORDS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_DATA_SIZE 14 + {STRUCT_FLD(field_name, "DATA_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_ZIP_SIZE 15 + {STRUCT_FLD(field_name, "COMPRESSED_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_STATE 16 + {STRUCT_FLD(field_name, "PAGE_STATE"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_IO_FIX 17 + {STRUCT_FLD(field_name, "IO_FIX"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_IS_OLD 18 + {STRUCT_FLD(field_name, "IS_OLD"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_FREE_CLOCK 19 + {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + END_OF_ST_FIELD_INFO +}; + +/*******************************************************************//** +Fill Information Schema table INNODB_BUFFER_PAGE with information +cached in the buf_page_info_t array +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_page_fill( +/*========================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + const buf_page_info_t* info_array, /*!< in: array cached page + info */ + ulint num_page, /*!< in: number of page info + cached */ + mem_heap_t* heap) /*!< in: temp heap memory */ +{ + TABLE* table; + Field** fields; + + DBUG_ENTER("i_s_innodb_buffer_page_fill"); + + table = tables->table; + + fields = table->field; + + /* Iterate through the cached array and fill the I_S table rows */ + for (ulint i = 0; i < num_page; i++) { + const buf_page_info_t* page_info; + const char* table_name; + const char* index_name; + const char* state_str; + enum buf_page_state state; + + page_info = info_array + i; + + table_name = NULL; + index_name = NULL; + state_str = NULL; + + OK(fields[IDX_BUFFER_POOL_ID]->store(page_info->pool_id)); + + OK(fields[IDX_BUFFER_BLOCK_ID]->store(page_info->block_id)); + + OK(fields[IDX_BUFFER_PAGE_SPACE]->store(page_info->space_id)); + + OK(fields[IDX_BUFFER_PAGE_NUM]->store(page_info->page_num)); + + OK(field_store_string( + fields[IDX_BUFFER_PAGE_TYPE], + i_s_page_type[page_info->page_type].type_str)); + + OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store( + page_info->flush_type)); + + OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store( + page_info->fix_count)); + + if (page_info->hashed) { + OK(field_store_string( + fields[IDX_BUFFER_PAGE_HASHED], "YES")); + } else { + OK(field_store_string( + fields[IDX_BUFFER_PAGE_HASHED], "NO")); + } + + OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store( + (longlong) page_info->newest_mod, true)); + + OK(fields[IDX_BUFFER_PAGE_OLDEST_MOD]->store( + (longlong) page_info->oldest_mod, true)); + + OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store( + page_info->access_time)); + + /* If this is an index page, fetch the index name + and table name */ + if (page_info->page_type == I_S_PAGE_TYPE_INDEX) { + const dict_index_t* index; + + mutex_enter(&dict_sys->mutex); + index = dict_index_get_if_in_cache_low( + page_info->index_id); + + /* Copy the index/table name under mutex. We + do not want to hold the InnoDB mutex while + filling the IS table */ + if (index) { + const char* name_ptr = index->name; + + if (name_ptr[0] == TEMP_INDEX_PREFIX) { + name_ptr++; + } + + index_name = mem_heap_strdup(heap, name_ptr); + + table_name = mem_heap_strdup(heap, + index->table_name); + + } + + mutex_exit(&dict_sys->mutex); + } + + OK(field_store_string( + fields[IDX_BUFFER_PAGE_TABLE_NAME], table_name)); + + OK(field_store_string( + fields[IDX_BUFFER_PAGE_INDEX_NAME], index_name)); + + OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store( + page_info->num_recs)); + + OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store( + page_info->data_size)); + + OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store( + page_info->zip_ssize + ? (PAGE_ZIP_MIN_SIZE >> 1) << page_info->zip_ssize + : 0)); + +#if BUF_PAGE_STATE_BITS > 3 +# error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<(page_info->page_state); + + switch (state) { + /* First three states are for compression pages and + are not states we would get as we scan pages through + buffer blocks */ + case BUF_BLOCK_ZIP_FREE: + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_ZIP_DIRTY: + state_str = NULL; + break; + case BUF_BLOCK_NOT_USED: + state_str = "NOT_USED"; + break; + case BUF_BLOCK_READY_FOR_USE: + state_str = "READY_FOR_USE"; + break; + case BUF_BLOCK_FILE_PAGE: + state_str = "FILE_PAGE"; + break; + case BUF_BLOCK_MEMORY: + state_str = "MEMORY"; + break; + case BUF_BLOCK_REMOVE_HASH: + state_str = "REMOVE_HASH"; + break; + }; + + OK(field_store_string(fields[IDX_BUFFER_PAGE_STATE], + state_str)); + + switch (page_info->io_fix) { + case BUF_IO_NONE: + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + "IO_NONE")); + break; + case BUF_IO_READ: + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + "IO_READ")); + break; + case BUF_IO_WRITE: + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + "IO_WRITE")); + break; + case BUF_IO_PIN: + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + "IO_PIN")); + break; + } + + OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD], + (page_info->is_old) ? "YES" : "NO")); + + OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store( + page_info->freed_page_clock)); + + if (schema_table_store_record(thd, table)) { + DBUG_RETURN(1); + } + } + + DBUG_RETURN(0); +} + +/*******************************************************************//** +Set appropriate page type to a buf_page_info_t structure */ +static +void +i_s_innodb_set_page_type( +/*=====================*/ + buf_page_info_t*page_info, /*!< in/out: structure to fill with + scanned info */ + ulint page_type, /*!< in: page type */ + const byte* frame) /*!< in: buffer frame */ +{ + if (page_type == FIL_PAGE_INDEX) { + const page_t* page = (const page_t*) frame; + + /* FIL_PAGE_INDEX is a bit special, its value + is defined as 17855, so we cannot use FIL_PAGE_INDEX + to index into i_s_page_type[] array, its array index + in the i_s_page_type[] array is I_S_PAGE_TYPE_INDEX + (1) */ + page_info->page_type = I_S_PAGE_TYPE_INDEX; + + page_info->index_id = btr_page_get_index_id(page); + + page_info->data_size = (ulint)(page_header_get_field( + page, PAGE_HEAP_TOP) - (page_is_comp(page) + ? PAGE_NEW_SUPREMUM_END + : PAGE_OLD_SUPREMUM_END) + - page_header_get_field(page, PAGE_GARBAGE)); + + page_info->num_recs = page_get_n_recs(page); + } else if (page_type >= I_S_PAGE_TYPE_UNKNOWN) { + /* Encountered an unknown page type */ + page_info->page_type = I_S_PAGE_TYPE_UNKNOWN; + } else { + /* Make sure we get the right index into the + i_s_page_type[] array */ + ut_a(page_type == i_s_page_type[page_type].type_value); + + page_info->page_type = page_type; + } + + if (page_info->page_type == FIL_PAGE_TYPE_ZBLOB + || page_info->page_type == FIL_PAGE_TYPE_ZBLOB2) { + page_info->page_num = mach_read_from_4( + frame + FIL_PAGE_OFFSET); + page_info->space_id = mach_read_from_4( + frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); + } +} +/*******************************************************************//** +Scans pages in the buffer cache, and collect their general information +into the buf_page_info_t array which is zero-filled. So any fields +that are not initialized in the function will default to 0 */ +static +void +i_s_innodb_buffer_page_get_info( +/*============================*/ + const buf_page_t*bpage, /*!< in: buffer pool page to scan */ + ulint pool_id, /*!< in: buffer pool id */ + ulint pos, /*!< in: buffer block position in + buffer pool or in the LRU list */ + buf_page_info_t*page_info) /*!< in: zero filled info structure; + out: structure filled with scanned + info */ +{ + ut_ad(pool_id < MAX_BUFFER_POOLS); + + page_info->pool_id = pool_id; + + page_info->block_id = pos; + + page_info->page_state = buf_page_get_state(bpage); + + /* Only fetch information for buffers that map to a tablespace, + that is, buffer page with state BUF_BLOCK_ZIP_PAGE, + BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_FILE_PAGE */ + if (buf_page_in_file(bpage)) { + const byte* frame; + ulint page_type; + + page_info->space_id = buf_page_get_space(bpage); + + page_info->page_num = buf_page_get_page_no(bpage); + + page_info->flush_type = bpage->flush_type; + + page_info->fix_count = bpage->buf_fix_count; + + page_info->newest_mod = bpage->newest_modification; + + page_info->oldest_mod = bpage->oldest_modification; + + page_info->access_time = bpage->access_time; + + page_info->zip_ssize = bpage->zip.ssize; + + page_info->io_fix = bpage->io_fix; + + page_info->is_old = bpage->old; + + page_info->freed_page_clock = bpage->freed_page_clock; + + if (page_info->page_state == BUF_BLOCK_FILE_PAGE) { + const buf_block_t*block; + + block = reinterpret_cast(bpage); + frame = block->frame; + page_info->hashed = (block->index != NULL); + } else { + ut_ad(page_info->zip_ssize); + frame = bpage->zip.data; + } + + page_type = fil_page_get_type(frame); + + i_s_innodb_set_page_type(page_info, page_type, frame); + } else { + page_info->page_type = I_S_PAGE_TYPE_UNKNOWN; + } +} + +/*******************************************************************//** +This is the function that goes through each block of the buffer pool +and fetch information to information schema tables: INNODB_BUFFER_PAGE. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_fill_buffer_pool( +/*========================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + buf_pool_t* buf_pool, /*!< in: buffer pool to scan */ + const ulint pool_id) /*!< in: buffer pool id */ +{ + int status = 0; + mem_heap_t* heap; + + DBUG_ENTER("i_s_innodb_fill_buffer_pool"); + + heap = mem_heap_create(10000); + + /* Go through each chunk of buffer pool. Currently, we only + have one single chunk for each buffer pool */ + for (ulint n = 0; n < buf_pool->n_chunks; n++) { + const buf_block_t* block; + ulint n_blocks; + buf_page_info_t* info_buffer; + ulint num_page; + ulint mem_size; + ulint chunk_size; + ulint num_to_process = 0; + ulint block_id = 0; + + /* Get buffer block of the nth chunk */ + block = buf_get_nth_chunk_block(buf_pool, n, &chunk_size); + num_page = 0; + + while (chunk_size > 0) { + /* we cache maximum MAX_BUF_INFO_CACHED number of + buffer page info */ + num_to_process = ut_min(chunk_size, + MAX_BUF_INFO_CACHED); + + mem_size = num_to_process * sizeof(buf_page_info_t); + + /* For each chunk, we'll pre-allocate information + structures to cache the page information read from + the buffer pool. Doing so before obtain any mutex */ + info_buffer = (buf_page_info_t*) mem_heap_zalloc( + heap, mem_size); + + /* Obtain appropriate mutexes. Since this is diagnostic + buffer pool info printout, we are not required to + preserve the overall consistency, so we can + release mutex periodically */ + buf_pool_mutex_enter(buf_pool); + + /* GO through each block in the chunk */ + for (n_blocks = num_to_process; n_blocks--; block++) { + i_s_innodb_buffer_page_get_info( + &block->page, pool_id, block_id, + info_buffer + num_page); + block_id++; + num_page++; + } + + buf_pool_mutex_exit(buf_pool); + + /* Fill in information schema table with information + just collected from the buffer chunk scan */ + status = i_s_innodb_buffer_page_fill( + thd, tables, info_buffer, + num_page, heap); + + /* If something goes wrong, break and return */ + if (status) { + break; + } + + mem_heap_empty(heap); + chunk_size -= num_to_process; + num_page = 0; + } + } + + mem_heap_free(heap); + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Fill page information for pages in InnoDB buffer pool to the +dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_page_fill_table( +/*==============================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + Item* ) /*!< in: condition (ignored) */ +{ + int status = 0; + + DBUG_ENTER("i_s_innodb_buffer_page_fill_table"); + + /* deny access to user without PROCESS privilege */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + /* Walk through each buffer pool */ + for (ulint i = 0; i < srv_buf_pool_instances; i++) { + buf_pool_t* buf_pool; + + buf_pool = buf_pool_from_array(i); + + /* Fetch information from pages in this buffer pool, + and fill the corresponding I_S table */ + status = i_s_innodb_fill_buffer_pool(thd, tables, buf_pool, i); + + /* If something wrong, break and return */ + if (status) { + break; + } + } + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_page_init( +/*========================*/ + void* p) /*!< in/out: table schema object */ +{ + ST_SCHEMA_TABLE* schema; + + DBUG_ENTER("i_s_innodb_buffer_page_init"); + + schema = reinterpret_cast(p); + + schema->fields_info = i_s_innodb_buffer_page_fields_info; + schema->fill_table = i_s_innodb_buffer_page_fill_table; + + DBUG_RETURN(0); +} + +UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page = +{ + /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + /* int */ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + + /* pointer to type-specific plugin descriptor */ + /* void* */ + STRUCT_FLD(info, &i_s_info), + + /* plugin name */ + /* const char* */ + STRUCT_FLD(name, "INNODB_BUFFER_PAGE"), + + /* plugin author (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(author, plugin_author), + + /* general descriptive text (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(descr, "InnoDB Buffer Page Information"), + + /* the plugin license (PLUGIN_LICENSE_XXX) */ + /* int */ + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + + /* the function to invoke when plugin is loaded */ + /* int (*)(void*); */ + STRUCT_FLD(init, i_s_innodb_buffer_page_init), + + /* the function to invoke when plugin is unloaded */ + /* int (*)(void*); */ + STRUCT_FLD(deinit, i_s_common_deinit), + + /* plugin version (for SHOW PLUGINS) */ + /* unsigned int */ + STRUCT_FLD(version, INNODB_VERSION_SHORT), + + /* struct st_mysql_show_var* */ + STRUCT_FLD(status_vars, NULL), + + /* struct st_mysql_sys_var** */ + STRUCT_FLD(system_vars, NULL), + + /* reserved for dependency checking */ + /* void* */ + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), +}; + +static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = +{ +#define IDX_BUF_LRU_POOL_ID 0 + {STRUCT_FLD(field_name, "POOL_ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_POS 1 + {STRUCT_FLD(field_name, "LRU_POSITION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_SPACE 2 + {STRUCT_FLD(field_name, "SPACE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_NUM 3 + {STRUCT_FLD(field_name, "PAGE_NUMBER"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_TYPE 4 + {STRUCT_FLD(field_name, "PAGE_TYPE"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_FLUSH_TYPE 5 + {STRUCT_FLD(field_name, "FLUSH_TYPE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_FIX_COUNT 6 + {STRUCT_FLD(field_name, "FIX_COUNT"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_HASHED 7 + {STRUCT_FLD(field_name, "IS_HASHED"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_NEWEST_MOD 8 + {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_OLDEST_MOD 9 + {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_ACCESS_TIME 10 + {STRUCT_FLD(field_name, "ACCESS_TIME"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_TABLE_NAME 11 + {STRUCT_FLD(field_name, "TABLE_NAME"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_INDEX_NAME 12 + {STRUCT_FLD(field_name, "INDEX_NAME"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_NUM_RECS 13 + {STRUCT_FLD(field_name, "NUMBER_RECORDS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_DATA_SIZE 14 + {STRUCT_FLD(field_name, "DATA_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_ZIP_SIZE 15 + {STRUCT_FLD(field_name, "COMPRESSED_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_STATE 16 + {STRUCT_FLD(field_name, "COMPRESSED"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_IO_FIX 17 + {STRUCT_FLD(field_name, "IO_FIX"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_IS_OLD 18 + {STRUCT_FLD(field_name, "IS_OLD"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_FREE_CLOCK 19 + {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + END_OF_ST_FIELD_INFO +}; + +/*******************************************************************//** +Fill Information Schema table INNODB_BUFFER_PAGE_LRU with information +cached in the buf_page_info_t array +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buf_page_lru_fill( +/*=========================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + const buf_page_info_t* info_array, /*!< in: array cached page + info */ + ulint num_page) /*!< in: number of page info + cached */ +{ + TABLE* table; + Field** fields; + mem_heap_t* heap; + + DBUG_ENTER("i_s_innodb_buf_page_lru_fill"); + + table = tables->table; + + fields = table->field; + + heap = mem_heap_create(1000); + + /* Iterate through the cached array and fill the I_S table rows */ + for (ulint i = 0; i < num_page; i++) { + const buf_page_info_t* page_info; + const char* table_name; + const char* index_name; + const char* state_str; + enum buf_page_state state; + + table_name = NULL; + index_name = NULL; + state_str = NULL; + + page_info = info_array + i; + + OK(fields[IDX_BUF_LRU_POOL_ID]->store(page_info->pool_id)); + + OK(fields[IDX_BUF_LRU_POS]->store(page_info->block_id)); + + OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store(page_info->space_id)); + + OK(fields[IDX_BUF_LRU_PAGE_NUM]->store(page_info->page_num)); + + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_TYPE], + i_s_page_type[page_info->page_type].type_str)); + + OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store( + page_info->flush_type)); + + OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store( + page_info->fix_count)); + + if (page_info->hashed) { + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_HASHED], "YES")); + } else { + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_HASHED], "NO")); + } + + OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store( + page_info->newest_mod, true)); + + OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store( + page_info->oldest_mod, true)); + + OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store( + page_info->access_time)); + + /* If this is an index page, fetch the index name + and table name */ + if (page_info->page_type == I_S_PAGE_TYPE_INDEX) { + const dict_index_t* index; + + mutex_enter(&dict_sys->mutex); + index = dict_index_get_if_in_cache_low( + page_info->index_id); + + /* Copy the index/table name under mutex. We + do not want to hold the InnoDB mutex while + filling the IS table */ + if (index) { + const char* name_ptr = index->name; + + if (name_ptr[0] == TEMP_INDEX_PREFIX) { + name_ptr++; + } + + index_name = mem_heap_strdup(heap, name_ptr); + + table_name = mem_heap_strdup(heap, + index->table_name); + } + + mutex_exit(&dict_sys->mutex); + } + + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_TABLE_NAME], table_name)); + + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_INDEX_NAME], index_name)); + OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store( + page_info->num_recs)); + + OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store( + page_info->data_size)); + + OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store( + page_info->zip_ssize ? + 512 << page_info->zip_ssize : 0)); + + state = static_cast(page_info->page_state); + + switch (state) { + /* Compressed page */ + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_ZIP_DIRTY: + state_str = "YES"; + break; + /* Uncompressed page */ + case BUF_BLOCK_FILE_PAGE: + state_str = "NO"; + break; + /* We should not see following states */ + case BUF_BLOCK_ZIP_FREE: + case BUF_BLOCK_READY_FOR_USE: + case BUF_BLOCK_NOT_USED: + case BUF_BLOCK_MEMORY: + case BUF_BLOCK_REMOVE_HASH: + state_str = NULL; + break; + }; + + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE], + state_str)); + + switch (page_info->io_fix) { + case BUF_IO_NONE: + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], + "IO_NONE")); + break; + case BUF_IO_READ: + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], + "IO_READ")); + break; + case BUF_IO_WRITE: + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], + "IO_WRITE")); + break; + } + + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD], + (page_info->is_old) ? "YES" : "NO")); + + OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store( + page_info->freed_page_clock)); + + if (schema_table_store_record(thd, table)) { + mem_heap_free(heap); + DBUG_RETURN(1); + } + + mem_heap_empty(heap); + } + + mem_heap_free(heap); + + DBUG_RETURN(0); +} + +/*******************************************************************//** +This is the function that goes through buffer pool's LRU list +and fetch information to INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_fill_buffer_lru( +/*=======================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + buf_pool_t* buf_pool, /*!< in: buffer pool to scan */ + const ulint pool_id) /*!< in: buffer pool id */ +{ + int status = 0; + buf_page_info_t* info_buffer; + ulint lru_pos = 0; + const buf_page_t* bpage; + ulint lru_len; + + DBUG_ENTER("i_s_innodb_fill_buffer_lru"); + + /* Obtain buf_pool mutex before allocate info_buffer, since + UT_LIST_GET_LEN(buf_pool->LRU) could change */ + buf_pool_mutex_enter(buf_pool); + + lru_len = UT_LIST_GET_LEN(buf_pool->LRU); + + /* Print error message if malloc fail */ + info_buffer = (buf_page_info_t*) my_malloc( + lru_len * sizeof *info_buffer, MYF(MY_WME)); + + if (!info_buffer) { + status = 1; + goto exit; + } + + memset(info_buffer, 0, lru_len * sizeof *info_buffer); + + /* Walk through Pool's LRU list and print the buffer page + information */ + bpage = UT_LIST_GET_LAST(buf_pool->LRU); + + while (bpage != NULL) { + /* Use the same function that collect buffer info for + INNODB_BUFFER_PAGE to get buffer page info */ + i_s_innodb_buffer_page_get_info(bpage, pool_id, lru_pos, + (info_buffer + lru_pos)); + + bpage = UT_LIST_GET_PREV(LRU, bpage); + + lru_pos++; + } + + ut_ad(lru_pos == lru_len); + ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU)); + +exit: + buf_pool_mutex_exit(buf_pool); + + if (info_buffer) { + status = i_s_innodb_buf_page_lru_fill( + thd, tables, info_buffer, lru_len); + + my_free(info_buffer); + } + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Fill page information for pages in InnoDB buffer pool to the +dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buf_page_lru_fill_table( +/*===============================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + Item* ) /*!< in: condition (ignored) */ +{ + int status = 0; + + DBUG_ENTER("i_s_innodb_buf_page_lru_fill_table"); + + /* deny access to any users that do not hold PROCESS_ACL */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + /* Walk through each buffer pool */ + for (ulint i = 0; i < srv_buf_pool_instances; i++) { + buf_pool_t* buf_pool; + + buf_pool = buf_pool_from_array(i); + + /* Fetch information from pages in this buffer pool's LRU list, + and fill the corresponding I_S table */ + status = i_s_innodb_fill_buffer_lru(thd, tables, buf_pool, i); + + /* If something wrong, break and return */ + if (status) { + break; + } + } + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_page_lru_init( +/*============================*/ + void* p) /*!< in/out: table schema object */ +{ + ST_SCHEMA_TABLE* schema; + + DBUG_ENTER("i_s_innodb_buffer_page_lru_init"); + + schema = reinterpret_cast(p); + + schema->fields_info = i_s_innodb_buf_page_lru_fields_info; + schema->fill_table = i_s_innodb_buf_page_lru_fill_table; + + DBUG_RETURN(0); +} + +UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page_lru = +{ + /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + /* int */ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + + /* pointer to type-specific plugin descriptor */ + /* void* */ + STRUCT_FLD(info, &i_s_info), + + /* plugin name */ + /* const char* */ + STRUCT_FLD(name, "INNODB_BUFFER_PAGE_LRU"), + + /* plugin author (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(author, plugin_author), + + /* general descriptive text (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(descr, "InnoDB Buffer Page in LRU"), + + /* the plugin license (PLUGIN_LICENSE_XXX) */ + /* int */ + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + + /* the function to invoke when plugin is loaded */ + /* int (*)(void*); */ + STRUCT_FLD(init, i_s_innodb_buffer_page_lru_init), + + /* the function to invoke when plugin is unloaded */ + /* int (*)(void*); */ + STRUCT_FLD(deinit, i_s_common_deinit), + + /* plugin version (for SHOW PLUGINS) */ + /* unsigned int */ + STRUCT_FLD(version, INNODB_VERSION_SHORT), + + /* struct st_mysql_show_var* */ + STRUCT_FLD(status_vars, NULL), + + /* struct st_mysql_sys_var** */ + STRUCT_FLD(system_vars, NULL), + + /* reserved for dependency checking */ + /* void* */ + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), +}; + +/*******************************************************************//** +Unbind a dynamic INFORMATION_SCHEMA table. +@return 0 on success */ +static +int +i_s_common_deinit( +/*==============*/ + void* p) /*!< in/out: table schema object */ +{ + DBUG_ENTER("i_s_common_deinit"); + + /* Do nothing */ + + DBUG_RETURN(0); +} - /* Do nothing */ - DBUG_RETURN(0); -} diff --git a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h index dc0deef119b..6b95ce25b58 100644 --- a/storage/innobase/handler/i_s.h +++ b/storage/innobase/handler/i_s.h @@ -35,5 +35,8 @@ extern struct st_mysql_plugin i_s_innodb_cmp; extern struct st_mysql_plugin i_s_innodb_cmp_reset; extern struct st_mysql_plugin i_s_innodb_cmpmem; extern struct st_mysql_plugin i_s_innodb_cmpmem_reset; +extern struct st_mysql_plugin i_s_innodb_buffer_page; +extern struct st_mysql_plugin i_s_innodb_buffer_page_lru; +extern struct st_mysql_plugin i_s_innodb_buffer_stats;; #endif /* i_s_h */ diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index a39592943d8..fd8620eab3b 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -68,7 +68,10 @@ Created 11/5/1995 Heikki Tuuri position of the block. */ /* @} */ -#define MAX_BUFFER_POOLS 64 /*!< The maximum number of buffer +#define MAX_BUFFER_POOLS_BITS 6 /*!< Number of bits to representing + a buffer pool ID */ +#define MAX_BUFFER_POOLS (1 << MAX_BUFFER_POOLS_BITS) + /*!< The maximum number of buffer pools that can be defined */ #define BUF_POOL_WATCH_SIZE 1 /*!< Maximum number of concurrent @@ -758,6 +761,18 @@ void buf_print_io( /*=========*/ FILE* file); /*!< in: file where to print */ +/*******************************************************************//** +Collect buffer pool stats information for a buffer pool. Also +record aggregated stats if there are more than one buffer pool +in the server */ +UNIV_INTERN +void +buf_stats_get_pool_info( +/*====================*/ + buf_pool_t* buf_pool, /*!< in: buffer pool */ + ulint pool_id, /*!< in: buffer pool ID */ + buf_pool_info_t* all_pool_info); /*!< in/out: buffer pool info + to fill */ /*********************************************************************//** Returns the ratio in percents of modified pages in the buffer pool / database pages in the buffer pool. @@ -1325,12 +1340,25 @@ void buf_get_total_stat( /*===============*/ buf_pool_stat_t*tot_stat); /*!< out: buffer pool stats */ +/*********************************************************************//** +Get the nth chunk's buffer block in the specified buffer pool. +@return the nth chunk's buffer block. */ +UNIV_INLINE +buf_block_t* +buf_get_nth_chunk_block( +/*====================*/ + const buf_pool_t* buf_pool, /*!< in: buffer pool instance */ + ulint n, /*!< in: nth chunk in the buffer pool */ + ulint* chunk_size); /*!< in: chunk size */ #endif /* !UNIV_HOTBACKUP */ /** The common buffer control block structure for compressed and uncompressed frames */ +/** Number of bits used for buffer page states. */ +#define BUF_PAGE_STATE_BITS 3 + struct buf_page_struct{ /** @name General fields None of these bit-fields must be modified without holding @@ -1345,7 +1373,8 @@ struct buf_page_struct{ unsigned offset:32; /*!< page number; also protected by buf_pool->mutex. */ - unsigned state:3; /*!< state of the control block; also + unsigned state:BUF_PAGE_STATE_BITS; + /*!< state of the control block; also protected by buf_pool->mutex. State transitions from BUF_BLOCK_READY_FOR_USE to diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index 0d9687e6b2a..84c0ab9d610 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -36,6 +36,15 @@ Created 11/5/1995 Heikki Tuuri #include "buf0lru.h" #include "buf0rea.h" +/** A chunk of buffers. The buffer pool is allocated in chunks. */ +struct buf_chunk_struct{ + ulint mem_size; /*!< allocated size of the chunk */ + ulint size; /*!< size of frames[] and blocks[] */ + void* mem; /*!< pointer to the memory area which + was allocated for the frames */ + buf_block_t* blocks; /*!< array of buffer control blocks */ +}; + /*********************************************************************//** Gets the current size of buffer buf_pool in bytes. @return size in bytes */ @@ -1276,4 +1285,21 @@ buf_pool_mutex_exit_all(void) buf_pool_mutex_exit(buf_pool); } } +/*********************************************************************//** +Get the nth chunk's buffer block in the specified buffer pool. +@return the nth chunk's buffer block. */ +UNIV_INLINE +buf_block_t* +buf_get_nth_chunk_block( +/*====================*/ + const buf_pool_t* buf_pool, /*!< in: buffer pool instance */ + ulint n, /*!< in: nth chunk in the buffer pool */ + ulint* chunk_size) /*!< in: chunk size */ +{ + const buf_chunk_t* chunk; + + chunk = buf_pool->chunks + n; + *chunk_size = chunk->size; + return(chunk->blocks); +} #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 610bd4b0e5c..ed47ccff052 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -142,6 +142,8 @@ extern fil_addr_t fil_addr_null; #define FIL_PAGE_TYPE_BLOB 10 /*!< Uncompressed BLOB page */ #define FIL_PAGE_TYPE_ZBLOB 11 /*!< First compressed BLOB page */ #define FIL_PAGE_TYPE_ZBLOB2 12 /*!< Subsequent compressed BLOB page */ +#define FIL_PAGE_TYPE_LAST FIL_PAGE_TYPE_ZBLOB2 + /*!< Last page type */ /* @} */ /** Space types @{ */ diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 30250d4fd27..5524272d811 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -41,6 +41,9 @@ Created 12/9/1995 Heikki Tuuri #include "sync0rw.h" #endif /* !UNIV_HOTBACKUP */ +/* Type used for all log sequence number storage and arithmetics */ +typedef ib_uint64_t lsn_t; + /** Redo log buffer */ typedef struct log_struct log_t; /** Redo log group */ -- cgit v1.2.1 From 138366002421bd3597d200c6e93ea2c40b774f3e Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Wed, 25 Jul 2012 13:51:39 +0530 Subject: Bug #13113026 INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRUFROM 5.6 BACKPORT Backporting the WL#5716, "Information schema table for InnoDB buffer pool information". Backporting revisions 2876.244.113, 2876.244.102 from mysql-trunk. rb://1175 approved by Jimmy Yang. --- mysql-test/lib/mtr_cases.pm | 3 + .../r/innodb_information_schema_buffer.result | 127 ++ .../t/innodb_information_schema_buffer.test | 76 + storage/innodb_plugin/buf/buf0buf.c | 137 +- storage/innodb_plugin/handler/ha_innodb.cc | 5 +- storage/innodb_plugin/handler/i_s.cc | 1752 ++++++++++++++++++++ storage/innodb_plugin/handler/i_s.h | 3 + storage/innodb_plugin/include/buf0buf.h | 103 +- storage/innodb_plugin/include/buf0buf.ic | 29 + storage/innodb_plugin/include/fil0fil.h | 2 + storage/innodb_plugin/include/log0log.h | 3 + .../scripts/install_innodb_plugins.sql | 3 + .../scripts/install_innodb_plugins_win.sql | 3 + 13 files changed, 2236 insertions(+), 10 deletions(-) create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_information_schema_buffer.result create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_information_schema_buffer.test diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 19eaac6747c..522e516c6e7 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -1001,6 +1001,9 @@ sub collect_one_test_case { "innodb_cmp=$plugin_filename$sep" . "innodb_cmp_reset=$plugin_filename$sep" . "innodb_cmpmem=$plugin_filename$sep" . + "innodb_buffer_page=$plugin_filename$sep" . + "innodb_buffer_page_lru=$plugin_filename$sep" . + "innodb_buffer_pool_stats=$plugin_filename$sep" . "innodb_cmpmem_reset=$plugin_filename"; foreach my $k ('master_opt', 'slave_opt') diff --git a/mysql-test/suite/innodb_plugin/r/innodb_information_schema_buffer.result b/mysql-test/suite/innodb_plugin/r/innodb_information_schema_buffer.result new file mode 100644 index 00000000000..bfda2c72757 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_information_schema_buffer.result @@ -0,0 +1,127 @@ +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; +SELECT count(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; +SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; +CREATE TABLE infoschema_buffer_test (col1 INT) ENGINE = INNODB; +INSERT INTO infoschema_buffer_test VALUES(9); +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test" + and PAGE_STATE="file_page" and PAGE_TYPE="index"; +TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE +test/infoschema_buffer_test GEN_CLUST_INDEX 1 29 FILE_PAGE INDEX +INSERT INTO infoschema_buffer_test VALUES(19); +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test" +and PAGE_STATE="file_page" and PAGE_TYPE="index"; +TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE +test/infoschema_buffer_test GEN_CLUST_INDEX 2 58 FILE_PAGE INDEX +CREATE INDEX idx ON infoschema_buffer_test(col1); +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test" +and PAGE_STATE="file_page" and INDEX_NAME = "idx" and PAGE_TYPE="index"; +TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE +test/infoschema_buffer_test idx 2 32 FILE_PAGE INDEX +DROP TABLE infoschema_buffer_test; +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test"; +TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE PAGE_STATE PAGE_TYPE +CREATE TABLE infoschema_parent (id INT NOT NULL, PRIMARY KEY (id)) +ENGINE=INNODB; +CREATE TABLE infoschema_child (id INT, parent_id INT, INDEX par_ind (parent_id), +FOREIGN KEY (parent_id) +REFERENCES infoschema_parent(id) +ON DELETE CASCADE) +ENGINE=INNODB; +SELECT count(*) +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_child" and PAGE_STATE="file_page" +and PAGE_TYPE="index"; +count(*) +2 +DROP TABLE infoschema_child; +DROP TABLE infoschema_parent; +show create table information_schema.innodb_buffer_page; +Table Create Table +INNODB_BUFFER_PAGE CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE` ( + `BLOCK_ID` bigint(21) unsigned NOT NULL DEFAULT '0', + `SPACE` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGE_NUMBER` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGE_TYPE` varchar(64) DEFAULT NULL, + `FLUSH_TYPE` bigint(21) unsigned NOT NULL DEFAULT '0', + `FIX_COUNT` bigint(21) unsigned NOT NULL DEFAULT '0', + `IS_HASHED` varchar(3) DEFAULT NULL, + `NEWEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT '0', + `OLDEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT '0', + `ACCESS_TIME` bigint(21) unsigned NOT NULL DEFAULT '0', + `TABLE_NAME` varchar(1024) DEFAULT NULL, + `INDEX_NAME` varchar(1024) DEFAULT NULL, + `NUMBER_RECORDS` bigint(21) unsigned NOT NULL DEFAULT '0', + `DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0', + `COMPRESSED_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGE_STATE` varchar(64) DEFAULT NULL, + `IO_FIX` varchar(64) DEFAULT NULL, + `IS_OLD` varchar(3) DEFAULT NULL, + `FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT '0' +) ENGINE=MEMORY DEFAULT CHARSET=utf8 +show create table information_schema.innodb_buffer_page_lru; +Table Create Table +INNODB_BUFFER_PAGE_LRU CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE_LRU` ( + `LRU_POSITION` bigint(21) unsigned NOT NULL DEFAULT '0', + `SPACE` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGE_NUMBER` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGE_TYPE` varchar(64) DEFAULT NULL, + `FLUSH_TYPE` bigint(21) unsigned NOT NULL DEFAULT '0', + `FIX_COUNT` bigint(21) unsigned NOT NULL DEFAULT '0', + `IS_HASHED` varchar(3) DEFAULT NULL, + `NEWEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT '0', + `OLDEST_MODIFICATION` bigint(21) unsigned NOT NULL DEFAULT '0', + `ACCESS_TIME` bigint(21) unsigned NOT NULL DEFAULT '0', + `TABLE_NAME` varchar(1024) DEFAULT NULL, + `INDEX_NAME` varchar(1024) DEFAULT NULL, + `NUMBER_RECORDS` bigint(21) unsigned NOT NULL DEFAULT '0', + `DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0', + `COMPRESSED_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0', + `COMPRESSED` varchar(3) DEFAULT NULL, + `IO_FIX` varchar(64) DEFAULT NULL, + `IS_OLD` varchar(3) DEFAULT NULL, + `FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT '0' +) ENGINE=MEMORY DEFAULT CHARSET=utf8 +show create table information_schema.innodb_buffer_pool_stats; +Table Create Table +INNODB_BUFFER_POOL_STATS CREATE TEMPORARY TABLE `INNODB_BUFFER_POOL_STATS` ( + `POOL_SIZE` bigint(21) unsigned NOT NULL DEFAULT '0', + `FREE_BUFFERS` bigint(21) unsigned NOT NULL DEFAULT '0', + `DATABASE_PAGES` bigint(21) unsigned NOT NULL DEFAULT '0', + `OLD_DATABASE_PAGES` bigint(21) unsigned NOT NULL DEFAULT '0', + `MODIFIED_DATABASE_PAGES` bigint(21) unsigned NOT NULL DEFAULT '0', + `PENDING_DECOMPRESS` bigint(21) unsigned NOT NULL DEFAULT '0', + `PENDING_READS` bigint(21) unsigned NOT NULL DEFAULT '0', + `PENDING_FLUSH_LRU` bigint(21) unsigned NOT NULL DEFAULT '0', + `PENDING_FLUSH_LIST` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGES_MADE_YOUNG` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGES_NOT_MADE_YOUNG` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGES_MADE_YOUNG_RATE` double NOT NULL DEFAULT '0', + `PAGES_MADE_NOT_YOUNG_RATE` double NOT NULL DEFAULT '0', + `NUMBER_PAGES_READ` bigint(21) unsigned NOT NULL DEFAULT '0', + `NUMBER_PAGES_CREATED` bigint(21) unsigned NOT NULL DEFAULT '0', + `NUMBER_PAGES_WRITTEN` bigint(21) unsigned NOT NULL DEFAULT '0', + `PAGES_READ_RATE` double NOT NULL DEFAULT '0', + `PAGES_CREATE_RATE` double NOT NULL DEFAULT '0', + `PAGES_WRITTEN_RATE` double NOT NULL DEFAULT '0', + `NUMBER_PAGES_GET` bigint(21) unsigned NOT NULL DEFAULT '0', + `HIT_RATE` bigint(21) unsigned NOT NULL DEFAULT '0', + `YOUNG_MAKE_PER_THOUSAND_GETS` bigint(21) unsigned NOT NULL DEFAULT '0', + `NOT_YOUNG_MAKE_PER_THOUSAND_GETS` bigint(21) unsigned NOT NULL DEFAULT '0', + `NUMBER_PAGES_READ_AHEAD` bigint(21) unsigned NOT NULL DEFAULT '0', + `NUMBER_READ_AHEAD_EVICTED` bigint(21) unsigned NOT NULL DEFAULT '0', + `READ_AHEAD_RATE` double NOT NULL DEFAULT '0', + `READ_AHEAD_EVICTED_RATE` double NOT NULL DEFAULT '0', + `LRU_IO_TOTAL` bigint(21) unsigned NOT NULL DEFAULT '0', + `LRU_IO_CURRENT` bigint(21) unsigned NOT NULL DEFAULT '0', + `UNCOMPRESS_TOTAL` bigint(21) unsigned NOT NULL DEFAULT '0', + `UNCOMPRESS_CURRENT` bigint(21) unsigned NOT NULL DEFAULT '0' +) ENGINE=MEMORY DEFAULT CHARSET=utf8 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_information_schema_buffer.test b/mysql-test/suite/innodb_plugin/t/innodb_information_schema_buffer.test new file mode 100644 index 00000000000..e0543a954f9 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_information_schema_buffer.test @@ -0,0 +1,76 @@ +# Exercise the code path for INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS +# and INFORMATION_SCHEMA.INNODB_BUFFER_PAGE + +-- source include/have_innodb_plugin.inc + +-- disable_result_log +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; + +# How many buffer pools we have +SELECT count(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS; + +SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; + +# This gives the over all buffer pool size +SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE; + +-- enable_result_log + +# Create a table and check its page info behave correctly in the pool +CREATE TABLE infoschema_buffer_test (col1 INT) ENGINE = INNODB; + +INSERT INTO infoschema_buffer_test VALUES(9); + +# We should be able to see this table in the buffer pool if we check +# right away +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test" + and PAGE_STATE="file_page" and PAGE_TYPE="index"; + +# The NUMBER_RECORDS and DATA_SIZE should check with each insertion +INSERT INTO infoschema_buffer_test VALUES(19); + +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test" +and PAGE_STATE="file_page" and PAGE_TYPE="index"; + +CREATE INDEX idx ON infoschema_buffer_test(col1); + +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test" +and PAGE_STATE="file_page" and INDEX_NAME = "idx" and PAGE_TYPE="index"; + + +# Check the buffer after dropping the table +DROP TABLE infoschema_buffer_test; + +SELECT TABLE_NAME, INDEX_NAME, NUMBER_RECORDS, DATA_SIZE, PAGE_STATE, PAGE_TYPE +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_buffer_test"; + +# Do one more test +#--replace_regex /'*[0-9]*'/'NUM'/ +CREATE TABLE infoschema_parent (id INT NOT NULL, PRIMARY KEY (id)) +ENGINE=INNODB; + +CREATE TABLE infoschema_child (id INT, parent_id INT, INDEX par_ind (parent_id), + FOREIGN KEY (parent_id) + REFERENCES infoschema_parent(id) + ON DELETE CASCADE) +ENGINE=INNODB; + +SELECT count(*) +FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +WHERE TABLE_NAME like "%infoschema_child" and PAGE_STATE="file_page" +and PAGE_TYPE="index"; + +DROP TABLE infoschema_child; +DROP TABLE infoschema_parent; + +show create table information_schema.innodb_buffer_page; +show create table information_schema.innodb_buffer_page_lru; +show create table information_schema.innodb_buffer_pool_stats; + diff --git a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c index c2000d67303..3ec9ba246d2 100644 --- a/storage/innodb_plugin/buf/buf0buf.c +++ b/storage/innodb_plugin/buf/buf0buf.c @@ -269,14 +269,6 @@ read-ahead or flush occurs */ UNIV_INTERN ibool buf_debug_prints = FALSE; #endif /* UNIV_DEBUG */ -/** A chunk of buffers. The buffer pool is allocated in chunks. */ -struct buf_chunk_struct{ - ulint mem_size; /*!< allocated size of the chunk */ - ulint size; /*!< size of frames[] and blocks[] */ - void* mem; /*!< pointer to the memory area which - was allocated for the frames */ - buf_block_t* blocks; /*!< array of buffer control blocks */ -}; #endif /* !UNIV_HOTBACKUP */ /********************************************************************//** @@ -3623,6 +3615,133 @@ buf_get_free_list_len(void) return(len); } + +/*******************************************************************//** +Collect buffer pool stats information for a buffer pool. Also +record aggregated stats if there are more than one buffer pool +in the server */ +UNIV_INTERN +void +buf_stats_get_pool_info( +/*====================*/ + buf_pool_info_t* pool_info) /*!< in/out: buffer pool info + to fill */ +{ + time_t current_time; + double time_elapsed; + + buf_pool_mutex_enter(); + + pool_info->pool_size = buf_pool->curr_size; + + pool_info->lru_len = UT_LIST_GET_LEN(buf_pool->LRU); + + pool_info->old_lru_len = buf_pool->LRU_old_len; + + pool_info->free_list_len = UT_LIST_GET_LEN(buf_pool->free); + + pool_info->flush_list_len = UT_LIST_GET_LEN(buf_pool->flush_list); + + pool_info->n_pend_unzip = UT_LIST_GET_LEN(buf_pool->unzip_LRU); + + pool_info->n_pend_reads = buf_pool->n_pend_reads; + + pool_info->n_pending_flush_lru = + (buf_pool->n_flush[BUF_FLUSH_LRU] + + buf_pool->init_flush[BUF_FLUSH_LRU]); + + pool_info->n_pending_flush_list = + (buf_pool->n_flush[BUF_FLUSH_LIST] + + buf_pool->init_flush[BUF_FLUSH_LIST]); + + pool_info->n_pending_flush_single_page = + (buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] + + buf_pool->init_flush[BUF_FLUSH_SINGLE_PAGE]); + + current_time = time(NULL); + time_elapsed = 0.001 + difftime(current_time, + buf_pool->last_printout_time); + + pool_info->n_pages_made_young = buf_pool->stat.n_pages_made_young; + + pool_info->n_pages_not_made_young = + buf_pool->stat.n_pages_not_made_young; + + pool_info->n_pages_read = buf_pool->stat.n_pages_read; + + pool_info->n_pages_created = buf_pool->stat.n_pages_created; + + pool_info->n_pages_written = buf_pool->stat.n_pages_written; + + pool_info->n_page_gets = buf_pool->stat.n_page_gets; + + pool_info->n_ra_pages_read_rnd = buf_pool->stat.n_ra_pages_read_rnd; + pool_info->n_ra_pages_read = buf_pool->stat.n_ra_pages_read; + + pool_info->n_ra_pages_evicted = buf_pool->stat.n_ra_pages_evicted; + + pool_info->page_made_young_rate = + (buf_pool->stat.n_pages_made_young + - buf_pool->old_stat.n_pages_made_young) / time_elapsed; + + pool_info->page_not_made_young_rate = + (buf_pool->stat.n_pages_not_made_young + - buf_pool->old_stat.n_pages_not_made_young) / time_elapsed; + + pool_info->pages_read_rate = + (buf_pool->stat.n_pages_read + - buf_pool->old_stat.n_pages_read) / time_elapsed; + + pool_info->pages_created_rate = + (buf_pool->stat.n_pages_created + - buf_pool->old_stat.n_pages_created) / time_elapsed; + + pool_info->pages_written_rate = + (buf_pool->stat.n_pages_written + - buf_pool->old_stat.n_pages_written) / time_elapsed; + + pool_info->n_page_get_delta = buf_pool->stat.n_page_gets + - buf_pool->old_stat.n_page_gets; + + if (pool_info->n_page_get_delta) { + pool_info->page_read_delta = buf_pool->stat.n_pages_read + - buf_pool->old_stat.n_pages_read; + + pool_info->young_making_delta = + buf_pool->stat.n_pages_made_young + - buf_pool->old_stat.n_pages_made_young; + + pool_info->not_young_making_delta = + buf_pool->stat.n_pages_not_made_young + - buf_pool->old_stat.n_pages_not_made_young; + } + pool_info->pages_readahead_rnd_rate = + (buf_pool->stat.n_ra_pages_read_rnd + - buf_pool->old_stat.n_ra_pages_read_rnd) / time_elapsed; + + + pool_info->pages_readahead_rate = + (buf_pool->stat.n_ra_pages_read + - buf_pool->old_stat.n_ra_pages_read) / time_elapsed; + + pool_info->pages_evicted_rate = + (buf_pool->stat.n_ra_pages_evicted + - buf_pool->old_stat.n_ra_pages_evicted) / time_elapsed; + + pool_info->unzip_lru_len = UT_LIST_GET_LEN(buf_pool->unzip_LRU); + + pool_info->io_sum = buf_LRU_stat_sum.io; + + pool_info->io_cur = buf_LRU_stat_cur.io; + + pool_info->unzip_sum = buf_LRU_stat_sum.unzip; + + pool_info->unzip_cur = buf_LRU_stat_cur.unzip; + + buf_refresh_io_stats(); + buf_pool_mutex_exit(); +} + #else /* !UNIV_HOTBACKUP */ /********************************************************************//** Inits a page to the buffer buf_pool, for use in ibbackup --restore. */ @@ -3653,3 +3772,5 @@ buf_page_init_for_backup_restore( } } #endif /* !UNIV_HOTBACKUP */ + + diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 412346e8349..fef49d23624 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -11341,7 +11341,10 @@ i_s_innodb_lock_waits, i_s_innodb_cmp, i_s_innodb_cmp_reset, i_s_innodb_cmpmem, -i_s_innodb_cmpmem_reset +i_s_innodb_cmpmem_reset, +i_s_innodb_buffer_page, +i_s_innodb_buffer_page_lru, +i_s_innodb_buffer_stats mysql_declare_plugin_end; /** @brief Initialize the default value of innodb_commit_concurrency. diff --git a/storage/innodb_plugin/handler/i_s.cc b/storage/innodb_plugin/handler/i_s.cc index b0149967e9b..4992cbc9c21 100644 --- a/storage/innodb_plugin/handler/i_s.cc +++ b/storage/innodb_plugin/handler/i_s.cc @@ -41,10 +41,90 @@ extern "C" { #include "buf0buf.h" /* for buf_pool and PAGE_ZIP_MIN_SIZE */ #include "ha_prototypes.h" /* for innobase_convert_name() */ #include "srv0start.h" /* for srv_was_started */ +#include "btr0btr.h" +#include "log0log.h" } static const char plugin_author[] = "Innobase Oy"; +/** structure associates a name string with a file page type and/or buffer +page state. */ +struct buffer_page_desc_str_struct{ + const char* type_str; /*!< String explain the page + type/state */ + ulint type_value; /*!< Page type or page state */ +}; + +typedef struct buffer_page_desc_str_struct buf_page_desc_str_t; + +/** Any states greater than FIL_PAGE_TYPE_LAST would be treated as unknown. */ +#define I_S_PAGE_TYPE_UNKNOWN (FIL_PAGE_TYPE_LAST + 1) + +/** We also define I_S_PAGE_TYPE_INDEX as the Index Page's position +in i_s_page_type[] array */ +#define I_S_PAGE_TYPE_INDEX 1 + +/** Name string for File Page Types */ +static buf_page_desc_str_t i_s_page_type[] = { + {"ALLOCATED", FIL_PAGE_TYPE_ALLOCATED}, + {"INDEX", FIL_PAGE_INDEX}, + {"UNDO_LOG", FIL_PAGE_UNDO_LOG}, + {"INODE", FIL_PAGE_INODE}, + {"IBUF_FREE_LIST", FIL_PAGE_IBUF_FREE_LIST}, + {"IBUF_BITMAP", FIL_PAGE_IBUF_BITMAP}, + {"SYSTEM", FIL_PAGE_TYPE_SYS}, + {"TRX_SYSTEM", FIL_PAGE_TYPE_TRX_SYS}, + {"FILE_SPACE_HEADER", FIL_PAGE_TYPE_FSP_HDR}, + {"EXTENT_DESCRIPTOR", FIL_PAGE_TYPE_XDES}, + {"BLOB", FIL_PAGE_TYPE_BLOB}, + {"COMPRESSED_BLOB", FIL_PAGE_TYPE_ZBLOB}, + {"COMPRESSED_BLOB2", FIL_PAGE_TYPE_ZBLOB2}, + {"UNKNOWN", I_S_PAGE_TYPE_UNKNOWN} +}; + +/* Check if we can hold all page type in a 4 bit value */ +#if I_S_PAGE_TYPE_UNKNOWN > 1<<4 +# error "i_s_page_type[] is too large" +#endif + +/** This structure defines information we will fetch from pages +currently cached in the buffer pool. It will be used to populate +table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE */ +struct buffer_page_info_struct{ + ulint block_id; /*!< Buffer Pool block ID */ + unsigned space_id:32; /*!< Tablespace ID */ + unsigned page_num:32; /*!< Page number/offset */ + unsigned access_time:32; /*!< Time of first access */ + unsigned flush_type:2; /*!< Flush type */ + unsigned io_fix:2; /*!< type of pending I/O operation */ + unsigned fix_count:19; /*!< Count of how manyfold this block + is bufferfixed */ + unsigned hashed:1; /*!< Whether hash index has been + built on this page */ + unsigned is_old:1; /*!< TRUE if the block is in the old + blocks in buf_pool->LRU_old */ + unsigned freed_page_clock:31; /*!< the value of + buf_pool->freed_page_clock */ + unsigned zip_ssize:PAGE_ZIP_SSIZE_BITS; + /*!< Compressed page size */ + unsigned page_state:BUF_PAGE_STATE_BITS; /*!< Page state */ + unsigned page_type:4; /*!< Page type */ + unsigned num_recs:UNIV_PAGE_SIZE_SHIFT-2; + /*!< Number of records on Page */ + unsigned data_size:UNIV_PAGE_SIZE_SHIFT; + /*!< Sum of the sizes of the records */ + lsn_t newest_mod; /*!< Log sequence number of + the youngest modification */ + lsn_t oldest_mod; /*!< Log sequence number of + the oldest modification */ + dulint index_id; /*!< Index ID if a index page */ +}; + +typedef struct buffer_page_info_struct buf_page_info_t; + +/** maximum number of buffer page info we would cache. */ +#define MAX_BUF_INFO_CACHED 10000 + #define OK(expr) \ if ((expr) != 0) { \ DBUG_RETURN(1); \ @@ -1576,3 +1656,1675 @@ i_s_common_deinit( DBUG_RETURN(0); } + + +/* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */ +static ST_FIELD_INFO i_s_innodb_buffer_stats_fields_info[] = +{ +#define IDX_BUF_STATS_POOL_SIZE 0 + {STRUCT_FLD(field_name, "POOL_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_FREE_BUFFERS 1 + {STRUCT_FLD(field_name, "FREE_BUFFERS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_LRU_LEN 2 + {STRUCT_FLD(field_name, "DATABASE_PAGES"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_OLD_LRU_LEN 3 + {STRUCT_FLD(field_name, "OLD_DATABASE_PAGES"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_FLUSH_LIST_LEN 4 + {STRUCT_FLD(field_name, "MODIFIED_DATABASE_PAGES"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PENDING_ZIP 5 + {STRUCT_FLD(field_name, "PENDING_DECOMPRESS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PENDING_READ 6 + {STRUCT_FLD(field_name, "PENDING_READS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_FLUSH_LRU 7 + {STRUCT_FLD(field_name, "PENDING_FLUSH_LRU"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_FLUSH_LIST 8 + {STRUCT_FLD(field_name, "PENDING_FLUSH_LIST"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_YOUNG 9 + {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_NOT_YOUNG 10 + {STRUCT_FLD(field_name, "PAGES_NOT_MADE_YOUNG"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_YOUNG_RATE 11 + {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 12 + {STRUCT_FLD(field_name, "PAGES_MADE_NOT_YOUNG_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_READ 13 + {STRUCT_FLD(field_name, "NUMBER_PAGES_READ"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_CREATED 14 + {STRUCT_FLD(field_name, "NUMBER_PAGES_CREATED"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_WRITTEN 15 + {STRUCT_FLD(field_name, "NUMBER_PAGES_WRITTEN"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_READ_RATE 16 + {STRUCT_FLD(field_name, "PAGES_READ_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_CREATE_RATE 17 + {STRUCT_FLD(field_name, "PAGES_CREATE_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_WRITTEN_RATE 18 + {STRUCT_FLD(field_name, "PAGES_WRITTEN_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_GET 19 + {STRUCT_FLD(field_name, "NUMBER_PAGES_GET"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_HIT_RATE 20 + {STRUCT_FLD(field_name, "HIT_RATE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_MADE_YOUNG_PCT 21 + {STRUCT_FLD(field_name, "YOUNG_MAKE_PER_THOUSAND_GETS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 22 + {STRUCT_FLD(field_name, "NOT_YOUNG_MAKE_PER_THOUSAND_GETS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_READ_AHREAD 23 + {STRUCT_FLD(field_name, "NUMBER_PAGES_READ_AHEAD"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_READ_AHEAD_EVICTED 24 + {STRUCT_FLD(field_name, "NUMBER_READ_AHEAD_EVICTED"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_READ_AHEAD_RATE 25 + {STRUCT_FLD(field_name, "READ_AHEAD_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 26 + {STRUCT_FLD(field_name, "READ_AHEAD_EVICTED_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_LRU_IO_SUM 27 + {STRUCT_FLD(field_name, "LRU_IO_TOTAL"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_LRU_IO_CUR 28 + {STRUCT_FLD(field_name, "LRU_IO_CURRENT"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_UNZIP_SUM 29 + {STRUCT_FLD(field_name, "UNCOMPRESS_TOTAL"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_UNZIP_CUR 30 + {STRUCT_FLD(field_name, "UNCOMPRESS_CURRENT"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + END_OF_ST_FIELD_INFO +}; + +/*******************************************************************//** +Fill Information Schema table INNODB_BUFFER_POOL_STATS for a particular +buffer pool +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_stats_fill( +/*==================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + const buf_pool_info_t* info) /*!< in: buffer pool + information */ +{ + TABLE* table; + Field** fields; + + DBUG_ENTER("i_s_innodb_stats_fill"); + + table = tables->table; + + fields = table->field; + + OK(fields[IDX_BUF_STATS_POOL_SIZE]->store(info->pool_size)); + + OK(fields[IDX_BUF_STATS_LRU_LEN]->store(info->lru_len)); + + OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store(info->old_lru_len)); + + OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store(info->free_list_len)); + + OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store( + info->flush_list_len)); + + OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store(info->n_pend_unzip)); + + OK(fields[IDX_BUF_STATS_PENDING_READ]->store(info->n_pend_reads)); + + OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store(info->n_pending_flush_lru)); + + OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store(info->n_pending_flush_list)); + + OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store(info->n_pages_made_young)); + + OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store( + info->n_pages_not_made_young)); + + OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store( + info->page_made_young_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store( + info->page_not_made_young_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_READ]->store(info->n_pages_read)); + + OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store(info->n_pages_created)); + + OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store(info->n_pages_written)); + + OK(fields[IDX_BUF_STATS_GET]->store(info->n_page_gets)); + + OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store(info->pages_read_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store(info->pages_created_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store(info->pages_written_rate)); + + if (info->n_page_get_delta) { + OK(fields[IDX_BUF_STATS_HIT_RATE]->store( + 1000 - (1000 * info->page_read_delta + / info->n_page_get_delta))); + + OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store( + 1000 * info->young_making_delta + / info->n_page_get_delta)); + + OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store( + 1000 * info->not_young_making_delta + / info->n_page_get_delta)); + } else { + OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0)); + OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0)); + OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0)); + } + + OK(fields[IDX_BUF_STATS_READ_AHREAD]->store(info->n_ra_pages_read)); + + OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store( + info->n_ra_pages_evicted)); + + OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store( + info->pages_readahead_rate)); + + OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store( + info->pages_evicted_rate)); + + OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store(info->io_sum)); + + OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store(info->io_cur)); + + OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store(info->unzip_sum)); + + OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store( info->unzip_cur)); + + DBUG_RETURN(schema_table_store_record(thd, table)); +} + +/*******************************************************************//** +This is the function that loops through each buffer pool and fetch buffer +pool stats to information schema table: I_S_INNODB_BUFFER_POOL_STATS +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_stats_fill_table( +/*===============================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + Item* ) /*!< in: condition (ignored) */ +{ + int status = 0; + buf_pool_info_t* pool_info; + + DBUG_ENTER("i_s_innodb_buffer_fill_general"); + + /* Only allow the PROCESS privilege holder to access the stats */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + pool_info = (buf_pool_info_t*) mem_zalloc(sizeof *pool_info); + + /* Fetch individual buffer pool info */ + buf_stats_get_pool_info(pool_info); + status = i_s_innodb_stats_fill(thd, tables, pool_info); + + mem_free(pool_info); + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_pool_stats_init( +/*==============================*/ + void* p) /*!< in/out: table schema object */ +{ + ST_SCHEMA_TABLE* schema; + + DBUG_ENTER("i_s_innodb_buffer_pool_stats_init"); + + schema = reinterpret_cast(p); + + schema->fields_info = i_s_innodb_buffer_stats_fields_info; + schema->fill_table = i_s_innodb_buffer_stats_fill_table; + + DBUG_RETURN(0); +} + +UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_stats = +{ + /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + /* int */ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + + /* pointer to type-specific plugin descriptor */ + /* void* */ + STRUCT_FLD(info, &i_s_info), + + /* plugin name */ + /* const char* */ + STRUCT_FLD(name, "INNODB_BUFFER_POOL_STATS"), + + /* plugin author (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(author, plugin_author), + + /* general descriptive text (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(descr, "InnoDB Buffer Pool Statistics Information "), + + /* the plugin license (PLUGIN_LICENSE_XXX) */ + /* int */ + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + + /* the function to invoke when plugin is loaded */ + /* int (*)(void*); */ + STRUCT_FLD(init, i_s_innodb_buffer_pool_stats_init), + + /* the function to invoke when plugin is unloaded */ + /* int (*)(void*); */ + STRUCT_FLD(deinit, i_s_common_deinit), + + /* plugin version (for SHOW PLUGINS) */ + /* unsigned int */ + STRUCT_FLD(version, INNODB_VERSION_SHORT), + + /* struct st_mysql_show_var* */ + STRUCT_FLD(status_vars, NULL), + + /* struct st_mysql_sys_var** */ + STRUCT_FLD(system_vars, NULL), + + /* reserved for dependency checking */ + /* void* */ + STRUCT_FLD(__reserved1, NULL), +}; + +/* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */ +static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = +{ +#define IDX_BUFFER_BLOCK_ID 0 + {STRUCT_FLD(field_name, "BLOCK_ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_SPACE 1 + {STRUCT_FLD(field_name, "SPACE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_NUM 2 + {STRUCT_FLD(field_name, "PAGE_NUMBER"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_TYPE 3 + {STRUCT_FLD(field_name, "PAGE_TYPE"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_FLUSH_TYPE 4 + {STRUCT_FLD(field_name, "FLUSH_TYPE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_FIX_COUNT 5 + {STRUCT_FLD(field_name, "FIX_COUNT"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_HASHED 6 + {STRUCT_FLD(field_name, "IS_HASHED"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_NEWEST_MOD 7 + {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_OLDEST_MOD 8 + {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_ACCESS_TIME 9 + {STRUCT_FLD(field_name, "ACCESS_TIME"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_TABLE_NAME 10 + {STRUCT_FLD(field_name, "TABLE_NAME"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_INDEX_NAME 11 + {STRUCT_FLD(field_name, "INDEX_NAME"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_NUM_RECS 12 + {STRUCT_FLD(field_name, "NUMBER_RECORDS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_DATA_SIZE 13 + {STRUCT_FLD(field_name, "DATA_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_ZIP_SIZE 14 + {STRUCT_FLD(field_name, "COMPRESSED_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_STATE 15 + {STRUCT_FLD(field_name, "PAGE_STATE"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_IO_FIX 16 + {STRUCT_FLD(field_name, "IO_FIX"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_IS_OLD 17 + {STRUCT_FLD(field_name, "IS_OLD"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_FREE_CLOCK 18 + {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + END_OF_ST_FIELD_INFO +}; + +/*******************************************************************//** +Fill Information Schema table INNODB_BUFFER_PAGE with information +cached in the buf_page_info_t array +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_page_fill( +/*========================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + const buf_page_info_t* info_array, /*!< in: array cached page + info */ + ulint num_page, /*!< in: number of page info + cached */ + mem_heap_t* heap) /*!< in: temp heap memory */ +{ + TABLE* table; + Field** fields; + + DBUG_ENTER("i_s_innodb_buffer_page_fill"); + + table = tables->table; + + fields = table->field; + + /* Iterate through the cached array and fill the I_S table rows */ + for (ulint i = 0; i < num_page; i++) { + const buf_page_info_t* page_info; + const char* table_name; + const char* index_name; + const char* state_str; + enum buf_page_state state; + + page_info = info_array + i; + + table_name = NULL; + index_name = NULL; + state_str = NULL; + + OK(fields[IDX_BUFFER_BLOCK_ID]->store(page_info->block_id)); + + OK(fields[IDX_BUFFER_PAGE_SPACE]->store(page_info->space_id)); + + OK(fields[IDX_BUFFER_PAGE_NUM]->store(page_info->page_num)); + + OK(field_store_string( + fields[IDX_BUFFER_PAGE_TYPE], + i_s_page_type[page_info->page_type].type_str)); + + OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store( + page_info->flush_type)); + + OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store( + page_info->fix_count)); + + if (page_info->hashed) { + OK(field_store_string( + fields[IDX_BUFFER_PAGE_HASHED], "YES")); + } else { + OK(field_store_string( + fields[IDX_BUFFER_PAGE_HASHED], "NO")); + } + + OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store( + (longlong) page_info->newest_mod, true)); + + OK(fields[IDX_BUFFER_PAGE_OLDEST_MOD]->store( + (longlong) page_info->oldest_mod, true)); + + OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store( + page_info->access_time)); + + /* If this is an index page, fetch the index name + and table name */ + if (page_info->page_type == I_S_PAGE_TYPE_INDEX) { + const dict_index_t* index; + + mutex_enter(&dict_sys->mutex); + index = dict_index_get_if_in_cache_low( + page_info->index_id); + + /* Copy the index/table name under mutex. We + do not want to hold the InnoDB mutex while + filling the IS table */ + if (index) { + const char* name_ptr = index->name; + + if (name_ptr[0] == TEMP_INDEX_PREFIX) { + name_ptr++; + } + + index_name = mem_heap_strdup(heap, name_ptr); + + table_name = mem_heap_strdup(heap, + index->table_name); + + } + + mutex_exit(&dict_sys->mutex); + } + + OK(field_store_string( + fields[IDX_BUFFER_PAGE_TABLE_NAME], table_name)); + + OK(field_store_string( + fields[IDX_BUFFER_PAGE_INDEX_NAME], index_name)); + + OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store( + page_info->num_recs)); + + OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store( + page_info->data_size)); + + OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store( + page_info->zip_ssize + ? (PAGE_ZIP_MIN_SIZE >> 1) << page_info->zip_ssize + : 0)); + +#if BUF_PAGE_STATE_BITS > 3 +# error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<(page_info->page_state); + + switch (state) { + /* First three states are for compression pages and + are not states we would get as we scan pages through + buffer blocks */ + case BUF_BLOCK_ZIP_FREE: + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_ZIP_DIRTY: + state_str = NULL; + break; + case BUF_BLOCK_NOT_USED: + state_str = "NOT_USED"; + break; + case BUF_BLOCK_READY_FOR_USE: + state_str = "READY_FOR_USE"; + break; + case BUF_BLOCK_FILE_PAGE: + state_str = "FILE_PAGE"; + break; + case BUF_BLOCK_MEMORY: + state_str = "MEMORY"; + break; + case BUF_BLOCK_REMOVE_HASH: + state_str = "REMOVE_HASH"; + break; + }; + + OK(field_store_string(fields[IDX_BUFFER_PAGE_STATE], + state_str)); + + switch (page_info->io_fix) { + case BUF_IO_NONE: + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + "IO_NONE")); + break; + case BUF_IO_READ: + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + "IO_READ")); + break; + case BUF_IO_WRITE: + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + "IO_WRITE")); + break; + } + + OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD], + (page_info->is_old) ? "YES" : "NO")); + + OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store( + page_info->freed_page_clock)); + + if (schema_table_store_record(thd, table)) { + DBUG_RETURN(1); + } + } + + DBUG_RETURN(0); +} + +/*******************************************************************//** +Set appropriate page type to a buf_page_info_t structure */ +static +void +i_s_innodb_set_page_type( +/*=====================*/ + buf_page_info_t*page_info, /*!< in/out: structure to fill with + scanned info */ + ulint page_type, /*!< in: page type */ + const byte* frame) /*!< in: buffer frame */ +{ + if (page_type == FIL_PAGE_INDEX) { + const page_t* page = (const page_t*) frame; + + /* FIL_PAGE_INDEX is a bit special, its value + is defined as 17855, so we cannot use FIL_PAGE_INDEX + to index into i_s_page_type[] array, its array index + in the i_s_page_type[] array is I_S_PAGE_TYPE_INDEX + (1) */ + page_info->page_type = I_S_PAGE_TYPE_INDEX; + + page_info->index_id = btr_page_get_index_id(page); + + page_info->data_size = (ulint)(page_header_get_field( + page, PAGE_HEAP_TOP) - (page_is_comp(page) + ? PAGE_NEW_SUPREMUM_END + : PAGE_OLD_SUPREMUM_END) + - page_header_get_field(page, PAGE_GARBAGE)); + + page_info->num_recs = page_get_n_recs(page); + } else if (page_type >= I_S_PAGE_TYPE_UNKNOWN) { + /* Encountered an unknown page type */ + page_info->page_type = I_S_PAGE_TYPE_UNKNOWN; + } else { + /* Make sure we get the right index into the + i_s_page_type[] array */ + ut_a(page_type == i_s_page_type[page_type].type_value); + + page_info->page_type = page_type; + } + + if (page_info->page_type == FIL_PAGE_TYPE_ZBLOB + || page_info->page_type == FIL_PAGE_TYPE_ZBLOB2) { + page_info->page_num = mach_read_from_4( + frame + FIL_PAGE_OFFSET); + page_info->space_id = mach_read_from_4( + frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); + } +} + +/*******************************************************************//** +Scans pages in the buffer cache, and collect their general information +into the buf_page_info_t array which is zero-filled. So any fields +that are not initialized in the function will default to 0 */ +static +void +i_s_innodb_buffer_page_get_info( +/*============================*/ + const buf_page_t*bpage, /*!< in: buffer pool page to scan */ + ulint pos, /*!< in: buffer block position in + buffer pool or in the LRU list */ + buf_page_info_t*page_info) /*!< in: zero filled info structure; + out: structure filled with scanned + info */ +{ + page_info->block_id = pos; + + page_info->page_state = buf_page_get_state(bpage); + + /* Only fetch information for buffers that map to a tablespace, + that is, buffer page with state BUF_BLOCK_ZIP_PAGE, + BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_FILE_PAGE */ + if (buf_page_in_file(bpage)) { + const byte* frame; + ulint page_type; + + page_info->space_id = buf_page_get_space(bpage); + + page_info->page_num = buf_page_get_page_no(bpage); + + page_info->flush_type = bpage->flush_type; + + page_info->fix_count = bpage->buf_fix_count; + + page_info->newest_mod = bpage->newest_modification; + + page_info->oldest_mod = bpage->oldest_modification; + + page_info->access_time = bpage->access_time; + + page_info->zip_ssize = bpage->zip.ssize; + + page_info->io_fix = bpage->io_fix; + + page_info->is_old = bpage->old; + + page_info->freed_page_clock = bpage->freed_page_clock; + + if (page_info->page_state == BUF_BLOCK_FILE_PAGE) { + const buf_block_t*block; + + block = reinterpret_cast(bpage); + frame = block->frame; + page_info->hashed = (block->index != NULL); + } else { + ut_ad(page_info->zip_ssize); + frame = bpage->zip.data; + } + + page_type = fil_page_get_type(frame); + + i_s_innodb_set_page_type(page_info, page_type, frame); + } else { + page_info->page_type = I_S_PAGE_TYPE_UNKNOWN; + } +} + +/*******************************************************************//** +This is the function that goes through each block of the buffer pool +and fetch information to information schema tables: INNODB_BUFFER_PAGE. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_fill_buffer_pool( +/*========================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables) /*!< in/out: tables to fill */ +{ + int status = 0; + mem_heap_t* heap; + + DBUG_ENTER("i_s_innodb_fill_buffer_pool"); + + heap = mem_heap_create(10000); + + /* Go through each chunk of buffer pool. Currently, we only + have one single chunk for each buffer pool */ + for (ulint n = 0; n < buf_pool->n_chunks; n++) { + const buf_block_t* block; + ulint n_blocks; + buf_page_info_t* info_buffer; + ulint num_page; + ulint mem_size; + ulint chunk_size; + ulint num_to_process = 0; + ulint block_id = 0; + + /* Get buffer block of the nth chunk */ + block = buf_get_nth_chunk_block(buf_pool, n, &chunk_size); + num_page = 0; + + while (chunk_size > 0) { + /* we cache maximum MAX_BUF_INFO_CACHED number of + buffer page info */ + num_to_process = ut_min(chunk_size, + MAX_BUF_INFO_CACHED); + + mem_size = num_to_process * sizeof(buf_page_info_t); + + /* For each chunk, we'll pre-allocate information + structures to cache the page information read from + the buffer pool. Doing so before obtain any mutex */ + info_buffer = (buf_page_info_t*) mem_heap_zalloc( + heap, mem_size); + + /* Obtain appropriate mutexes. Since this is diagnostic + buffer pool info printout, we are not required to + preserve the overall consistency, so we can + release mutex periodically */ + buf_pool_mutex_enter(); + + /* GO through each block in the chunk */ + for (n_blocks = num_to_process; n_blocks--; block++) { + i_s_innodb_buffer_page_get_info( + &block->page, block_id, + info_buffer + num_page); + block_id++; + num_page++; + } + + buf_pool_mutex_exit(); + + /* Fill in information schema table with information + just collected from the buffer chunk scan */ + status = i_s_innodb_buffer_page_fill( + thd, tables, info_buffer, + num_page, heap); + + /* If something goes wrong, break and return */ + if (status) { + break; + } + + mem_heap_empty(heap); + chunk_size -= num_to_process; + num_page = 0; + } + } + + mem_heap_free(heap); + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Fill page information for pages in InnoDB buffer pool to the +dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_page_fill_table( +/*==============================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + Item* ) /*!< in: condition (ignored) */ +{ + int status = 0; + + DBUG_ENTER("i_s_innodb_buffer_page_fill_table"); + + /* deny access to user without PROCESS privilege */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + /* Fetch information from pages in this buffer pool, + and fill the corresponding I_S table */ + status = i_s_innodb_fill_buffer_pool(thd, tables); + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_page_init( +/*========================*/ + void* p) /*!< in/out: table schema object */ +{ + ST_SCHEMA_TABLE* schema; + + DBUG_ENTER("i_s_innodb_buffer_page_init"); + + schema = reinterpret_cast(p); + + schema->fields_info = i_s_innodb_buffer_page_fields_info; + schema->fill_table = i_s_innodb_buffer_page_fill_table; + + DBUG_RETURN(0); +} + +UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page = +{ + /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + /* int */ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + + /* pointer to type-specific plugin descriptor */ + /* void* */ + STRUCT_FLD(info, &i_s_info), + + /* plugin name */ + /* const char* */ + STRUCT_FLD(name, "INNODB_BUFFER_PAGE"), + + /* plugin author (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(author, plugin_author), + + /* general descriptive text (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(descr, "InnoDB Buffer Page Information"), + + /* the plugin license (PLUGIN_LICENSE_XXX) */ + /* int */ + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + + /* the function to invoke when plugin is loaded */ + /* int (*)(void*); */ + STRUCT_FLD(init, i_s_innodb_buffer_page_init), + + /* the function to invoke when plugin is unloaded */ + /* int (*)(void*); */ + STRUCT_FLD(deinit, i_s_common_deinit), + + /* plugin version (for SHOW PLUGINS) */ + /* unsigned int */ + STRUCT_FLD(version, INNODB_VERSION_SHORT), + + /* struct st_mysql_show_var* */ + STRUCT_FLD(status_vars, NULL), + + /* struct st_mysql_sys_var** */ + STRUCT_FLD(system_vars, NULL), + + /* reserved for dependency checking */ + /* void* */ + STRUCT_FLD(__reserved1, NULL), +}; + +static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = +{ +#define IDX_BUF_LRU_POS 0 + {STRUCT_FLD(field_name, "LRU_POSITION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_SPACE 1 + {STRUCT_FLD(field_name, "SPACE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_NUM 2 + {STRUCT_FLD(field_name, "PAGE_NUMBER"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_TYPE 3 + {STRUCT_FLD(field_name, "PAGE_TYPE"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_FLUSH_TYPE 4 + {STRUCT_FLD(field_name, "FLUSH_TYPE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_FIX_COUNT 5 + {STRUCT_FLD(field_name, "FIX_COUNT"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_HASHED 6 + {STRUCT_FLD(field_name, "IS_HASHED"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_NEWEST_MOD 7 + {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_OLDEST_MOD 8 + {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_ACCESS_TIME 9 + {STRUCT_FLD(field_name, "ACCESS_TIME"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_TABLE_NAME 10 + {STRUCT_FLD(field_name, "TABLE_NAME"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_INDEX_NAME 11 + {STRUCT_FLD(field_name, "INDEX_NAME"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_NUM_RECS 12 + {STRUCT_FLD(field_name, "NUMBER_RECORDS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_DATA_SIZE 13 + {STRUCT_FLD(field_name, "DATA_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_ZIP_SIZE 14 + {STRUCT_FLD(field_name, "COMPRESSED_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_STATE 15 + {STRUCT_FLD(field_name, "COMPRESSED"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_IO_FIX 16 + {STRUCT_FLD(field_name, "IO_FIX"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_IS_OLD 17 + {STRUCT_FLD(field_name, "IS_OLD"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_FREE_CLOCK 18 + {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + END_OF_ST_FIELD_INFO +}; + +/*******************************************************************//** +Fill Information Schema table INNODB_BUFFER_PAGE_LRU with information +cached in the buf_page_info_t array +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buf_page_lru_fill( +/*=========================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + const buf_page_info_t* info_array, /*!< in: array cached page + info */ + ulint num_page) /*!< in: number of page info + cached */ +{ + TABLE* table; + Field** fields; + mem_heap_t* heap; + + DBUG_ENTER("i_s_innodb_buf_page_lru_fill"); + + table = tables->table; + + fields = table->field; + + heap = mem_heap_create(1000); + + /* Iterate through the cached array and fill the I_S table rows */ + for (ulint i = 0; i < num_page; i++) { + const buf_page_info_t* page_info; + const char* table_name; + const char* index_name; + const char* state_str; + enum buf_page_state state; + + table_name = NULL; + index_name = NULL; + state_str = NULL; + + page_info = info_array + i; + + OK(fields[IDX_BUF_LRU_POS]->store(page_info->block_id)); + + OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store(page_info->space_id)); + + OK(fields[IDX_BUF_LRU_PAGE_NUM]->store(page_info->page_num)); + + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_TYPE], + i_s_page_type[page_info->page_type].type_str)); + + OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store( + page_info->flush_type)); + + OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store( + page_info->fix_count)); + + if (page_info->hashed) { + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_HASHED], "YES")); + } else { + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_HASHED], "NO")); + } + + OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store( + page_info->newest_mod, true)); + + OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store( + page_info->oldest_mod, true)); + + OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store( + page_info->access_time)); + + /* If this is an index page, fetch the index name + and table name */ + if (page_info->page_type == I_S_PAGE_TYPE_INDEX) { + const dict_index_t* index; + + mutex_enter(&dict_sys->mutex); + index = dict_index_get_if_in_cache_low( + page_info->index_id); + + /* Copy the index/table name under mutex. We + do not want to hold the InnoDB mutex while + filling the IS table */ + if (index) { + const char* name_ptr = index->name; + + if (name_ptr[0] == TEMP_INDEX_PREFIX) { + name_ptr++; + } + + index_name = mem_heap_strdup(heap, name_ptr); + + table_name = mem_heap_strdup(heap, + index->table_name); + } + + mutex_exit(&dict_sys->mutex); + } + + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_TABLE_NAME], table_name)); + + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_INDEX_NAME], index_name)); + OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store( + page_info->num_recs)); + + OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store( + page_info->data_size)); + + OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store( + page_info->zip_ssize ? + 512 << page_info->zip_ssize : 0)); + + state = static_cast(page_info->page_state); + + switch (state) { + /* Compressed page */ + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_ZIP_DIRTY: + state_str = "YES"; + break; + /* Uncompressed page */ + case BUF_BLOCK_FILE_PAGE: + state_str = "NO"; + break; + /* We should not see following states */ + case BUF_BLOCK_ZIP_FREE: + case BUF_BLOCK_READY_FOR_USE: + case BUF_BLOCK_NOT_USED: + case BUF_BLOCK_MEMORY: + case BUF_BLOCK_REMOVE_HASH: + state_str = NULL; + break; + }; + + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE], + state_str)); + + switch (page_info->io_fix) { + case BUF_IO_NONE: + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], + "IO_NONE")); + break; + case BUF_IO_READ: + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], + "IO_READ")); + break; + case BUF_IO_WRITE: + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], + "IO_WRITE")); + break; + } + + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD], + (page_info->is_old) ? "YES" : "NO")); + + OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store( + page_info->freed_page_clock)); + + if (schema_table_store_record(thd, table)) { + mem_heap_free(heap); + DBUG_RETURN(1); + } + + mem_heap_empty(heap); + } + + mem_heap_free(heap); + + DBUG_RETURN(0); +} + +/*******************************************************************//** +This is the function that goes through buffer pool's LRU list +and fetch information to INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_fill_buffer_lru( +/*=======================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables) /*!< in/out: tables to fill */ +{ + int status = 0; + buf_page_info_t* info_buffer; + ulint lru_pos = 0; + const buf_page_t* bpage; + ulint lru_len; + + DBUG_ENTER("i_s_innodb_fill_buffer_lru"); + + /* Obtain buf_pool mutex before allocate info_buffer, since + UT_LIST_GET_LEN(buf_pool->LRU) could change */ + buf_pool_mutex_enter(); + + lru_len = UT_LIST_GET_LEN(buf_pool->LRU); + + /* Print error message if malloc fail */ + info_buffer = (buf_page_info_t*) my_malloc( + lru_len * sizeof *info_buffer, MYF(MY_WME)); + + if (!info_buffer) { + status = 1; + goto exit; + } + + memset(info_buffer, 0, lru_len * sizeof *info_buffer); + + /* Walk through Pool's LRU list and print the buffer page + information */ + bpage = UT_LIST_GET_LAST(buf_pool->LRU); + + while (bpage != NULL) { + /* Use the same function that collect buffer info for + INNODB_BUFFER_PAGE to get buffer page info */ + i_s_innodb_buffer_page_get_info(bpage, lru_pos, + (info_buffer + lru_pos)); + + bpage = UT_LIST_GET_PREV(LRU, bpage); + + lru_pos++; + } + + ut_ad(lru_pos == lru_len); + ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU)); + +exit: + buf_pool_mutex_exit(); + + if (info_buffer) { + status = i_s_innodb_buf_page_lru_fill( + thd, tables, info_buffer, lru_len); + + my_free(info_buffer, MYF(MY_ALLOW_ZERO_PTR)); + } + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Fill page information for pages in InnoDB buffer pool to the +dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buf_page_lru_fill_table( +/*===============================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + Item* ) /*!< in: condition (ignored) */ +{ + int status = 0; + + DBUG_ENTER("i_s_innodb_buf_page_lru_fill_table"); + + /* deny access to any users that do not hold PROCESS_ACL */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + /* Fetch information from pages in this buffer pool's LRU list, + and fill the corresponding I_S table */ + status = i_s_innodb_fill_buffer_lru(thd, tables); + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_page_lru_init( +/*============================*/ + void* p) /*!< in/out: table schema object */ +{ + ST_SCHEMA_TABLE* schema; + + DBUG_ENTER("i_s_innodb_buffer_page_lru_init"); + + schema = reinterpret_cast(p); + + schema->fields_info = i_s_innodb_buf_page_lru_fields_info; + schema->fill_table = i_s_innodb_buf_page_lru_fill_table; + + DBUG_RETURN(0); +} + +UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page_lru = +{ + /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + /* int */ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + + /* pointer to type-specific plugin descriptor */ + /* void* */ + STRUCT_FLD(info, &i_s_info), + + /* plugin name */ + /* const char* */ + STRUCT_FLD(name, "INNODB_BUFFER_PAGE_LRU"), + + /* plugin author (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(author, plugin_author), + + /* general descriptive text (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(descr, "InnoDB Buffer Page in LRU"), + + /* the plugin license (PLUGIN_LICENSE_XXX) */ + /* int */ + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + + /* the function to invoke when plugin is loaded */ + /* int (*)(void*); */ + STRUCT_FLD(init, i_s_innodb_buffer_page_lru_init), + + /* the function to invoke when plugin is unloaded */ + /* int (*)(void*); */ + STRUCT_FLD(deinit, i_s_common_deinit), + + /* plugin version (for SHOW PLUGINS) */ + /* unsigned int */ + STRUCT_FLD(version, INNODB_VERSION_SHORT), + + /* struct st_mysql_show_var* */ + STRUCT_FLD(status_vars, NULL), + + /* struct st_mysql_sys_var** */ + STRUCT_FLD(system_vars, NULL), + + /* reserved for dependency checking */ + /* void* */ + STRUCT_FLD(__reserved1, NULL), +}; diff --git a/storage/innodb_plugin/handler/i_s.h b/storage/innodb_plugin/handler/i_s.h index 402c88bbedb..3a8770d73fb 100644 --- a/storage/innodb_plugin/handler/i_s.h +++ b/storage/innodb_plugin/handler/i_s.h @@ -33,5 +33,8 @@ extern struct st_mysql_plugin i_s_innodb_cmp; extern struct st_mysql_plugin i_s_innodb_cmp_reset; extern struct st_mysql_plugin i_s_innodb_cmpmem; extern struct st_mysql_plugin i_s_innodb_cmpmem_reset; +extern struct st_mysql_plugin i_s_innodb_buffer_page; +extern struct st_mysql_plugin i_s_innodb_buffer_page_lru; +extern struct st_mysql_plugin i_s_innodb_buffer_stats; #endif /* i_s_h */ diff --git a/storage/innodb_plugin/include/buf0buf.h b/storage/innodb_plugin/include/buf0buf.h index de009a4c670..fd286f6c26c 100644 --- a/storage/innodb_plugin/include/buf0buf.h +++ b/storage/innodb_plugin/include/buf0buf.h @@ -103,6 +103,81 @@ enum buf_page_state { before putting to the free list */ }; +/** This structure defines information we will fetch from each buffer pool. It +will be used to print table IO stats */ +struct buf_pool_info_struct{ + /* General buffer pool info */ + ulint pool_size; /*!< Buffer Pool size in pages */ + ulint lru_len; /*!< Length of buf_pool->LRU */ + ulint old_lru_len; /*!< buf_pool->LRU_old_len */ + ulint free_list_len; /*!< Length of buf_pool->free list */ + ulint flush_list_len; /*!< Length of buf_pool->flush_list */ + ulint n_pend_unzip; /*!< buf_pool->n_pend_unzip, pages + pending decompress */ + ulint n_pend_reads; /*!< buf_pool->n_pend_reads, pages + pending read */ + ulint n_pending_flush_lru; /*!< Pages pending flush in LRU */ + ulint n_pending_flush_single_page;/*!< Pages pending to be + flushed as part of single page + flushes issued by various user + threads */ + ulint n_pending_flush_list; /*!< Pages pending flush in FLUSH + LIST */ + ulint n_pages_made_young; /*!< number of pages made young */ + ulint n_pages_not_made_young; /*!< number of pages not made young */ + ulint n_pages_read; /*!< buf_pool->n_pages_read */ + ulint n_pages_created; /*!< buf_pool->n_pages_created */ + ulint n_pages_written; /*!< buf_pool->n_pages_written */ + ulint n_page_gets; /*!< buf_pool->n_page_gets */ + ulint n_ra_pages_read_rnd; /*!< buf_pool->n_ra_pages_read_rnd, + number of pages readahead */ + ulint n_ra_pages_read; /*!< buf_pool->n_ra_pages_read, number + of pages readahead */ + ulint n_ra_pages_evicted; /*!< buf_pool->n_ra_pages_evicted, + number of readahead pages evicted + without access */ + ulint n_page_get_delta; /*!< num of buffer pool page gets since + last printout */ + + /* Buffer pool access stats */ + double page_made_young_rate; /*!< page made young rate in pages + per second */ + double page_not_made_young_rate;/*!< page not made young rate + in pages per second */ + double pages_read_rate; /*!< num of pages read per second */ + double pages_created_rate; /*!< num of pages create per second */ + double pages_written_rate; /*!< num of pages written per second */ + ulint page_read_delta; /*!< num of pages read since last + printout */ + ulint young_making_delta; /*!< num of pages made young since + last printout */ + ulint not_young_making_delta; /*!< num of pages not make young since + last printout */ + + /* Statistics about read ahead algorithm. */ + double pages_readahead_rnd_rate;/*!< random readahead rate in pages per + second */ + double pages_readahead_rate; /*!< readahead rate in pages per + second */ + double pages_evicted_rate; /*!< rate of readahead page evicted + without access, in pages per second */ + + /* Stats about LRU eviction */ + ulint unzip_lru_len; /*!< length of buf_pool->unzip_LRU + list */ + /* Counters for LRU policy */ + ulint io_sum; /*!< buf_LRU_stat_sum.io */ + ulint io_cur; /*!< buf_LRU_stat_cur.io, num of IO + for current interval */ + ulint unzip_sum; /*!< buf_LRU_stat_sum.unzip */ + ulint unzip_cur; /*!< buf_LRU_stat_cur.unzip, num + pages decompressed in current + interval */ +}; + +typedef struct buf_pool_info_struct buf_pool_info_t; + + #ifndef UNIV_HOTBACKUP /********************************************************************//** Creates the buffer pool. @@ -618,6 +693,16 @@ void buf_print_io( /*=========*/ FILE* file); /*!< in: file where to print */ +/*******************************************************************//** +Collect buffer pool stats information for a buffer pool. Also +record aggregated stats if there are more than one buffer pool +in the server */ +UNIV_INTERN +void +buf_stats_get_pool_info( +/*====================*/ + buf_pool_info_t* pool_info); /*!< in/out: buffer pool info + to fill */ /*********************************************************************//** Returns the ratio in percents of modified pages in the buffer pool / database pages in the buffer pool. @@ -1037,12 +1122,27 @@ UNIV_INTERN ulint buf_get_free_list_len(void); /*=======================*/ + +/*********************************************************************//** +Get the nth chunk's buffer block in the specified buffer pool. +@return the nth chunk's buffer block. */ +UNIV_INLINE +buf_block_t* +buf_get_nth_chunk_block( +/*====================*/ + const buf_pool_t* buf_pool, /*!< in: buffer pool instance */ + ulint n, /*!< in: nth chunk in the buffer pool */ + ulint* chunk_size); /*!< in: chunk size */ + #endif /* !UNIV_HOTBACKUP */ /** The common buffer control block structure for compressed and uncompressed frames */ +/** Number of bits used for buffer page states. */ +#define BUF_PAGE_STATE_BITS 3 + struct buf_page_struct{ /** @name General fields None of these bit-fields must be modified without holding @@ -1057,7 +1157,8 @@ struct buf_page_struct{ unsigned offset:32; /*!< page number; also protected by buf_pool_mutex. */ - unsigned state:3; /*!< state of the control block; also + unsigned state:BUF_PAGE_STATE_BITS; + /*!< state of the control block; also protected by buf_pool_mutex. State transitions from BUF_BLOCK_READY_FOR_USE to diff --git a/storage/innodb_plugin/include/buf0buf.ic b/storage/innodb_plugin/include/buf0buf.ic index e7308d77983..39135a2ece1 100644 --- a/storage/innodb_plugin/include/buf0buf.ic +++ b/storage/innodb_plugin/include/buf0buf.ic @@ -36,6 +36,16 @@ Created 11/5/1995 Heikki Tuuri #include "buf0lru.h" #include "buf0rea.h" +/** A chunk of buffers. The buffer pool is allocated in chunks. */ +struct buf_chunk_struct{ + ulint mem_size; /*!< allocated size of the chunk */ + ulint size; /*!< size of frames[] and blocks[] */ + void* mem; /*!< pointer to the memory area which + was allocated for the frames */ + buf_block_t* blocks; /*!< array of buffer control blocks */ +}; + + /********************************************************************//** Reads the freed_page_clock of a buffer block. @return freed_page_clock */ @@ -1106,4 +1116,23 @@ buf_block_dbg_add_level( sync_thread_add_level(&block->lock, level, FALSE); } #endif /* UNIV_SYNC_DEBUG */ + +/*********************************************************************//** +Get the nth chunk's buffer block in the specified buffer pool. +@return the nth chunk's buffer block. */ +UNIV_INLINE +buf_block_t* +buf_get_nth_chunk_block( +/*====================*/ + const buf_pool_t* buf_pool, /*!< in: buffer pool instance */ + ulint n, /*!< in: nth chunk in the buffer pool */ + ulint* chunk_size) /*!< in: chunk size */ +{ + const buf_chunk_t* chunk; + + chunk = buf_pool->chunks + n; + *chunk_size = chunk->size; + return(chunk->blocks); +} #endif /* !UNIV_HOTBACKUP */ + diff --git a/storage/innodb_plugin/include/fil0fil.h b/storage/innodb_plugin/include/fil0fil.h index c95038b9231..05217168764 100644 --- a/storage/innodb_plugin/include/fil0fil.h +++ b/storage/innodb_plugin/include/fil0fil.h @@ -141,6 +141,8 @@ extern fil_addr_t fil_addr_null; #define FIL_PAGE_TYPE_BLOB 10 /*!< Uncompressed BLOB page */ #define FIL_PAGE_TYPE_ZBLOB 11 /*!< First compressed BLOB page */ #define FIL_PAGE_TYPE_ZBLOB2 12 /*!< Subsequent compressed BLOB page */ +#define FIL_PAGE_TYPE_LAST FIL_PAGE_TYPE_ZBLOB2 + /*!< Last page type */ /* @} */ /** Space types @{ */ diff --git a/storage/innodb_plugin/include/log0log.h b/storage/innodb_plugin/include/log0log.h index 8c61244a38d..0295ac4ee35 100644 --- a/storage/innodb_plugin/include/log0log.h +++ b/storage/innodb_plugin/include/log0log.h @@ -41,6 +41,9 @@ Created 12/9/1995 Heikki Tuuri #include "sync0rw.h" #endif /* !UNIV_HOTBACKUP */ +/* Type used for all log sequence number storage and arithmetics */ +typedef ib_uint64_t lsn_t; + /** Redo log buffer */ typedef struct log_struct log_t; /** Redo log group */ diff --git a/storage/innodb_plugin/scripts/install_innodb_plugins.sql b/storage/innodb_plugin/scripts/install_innodb_plugins.sql index 3fdb8f11e22..8833d9c023c 100644 --- a/storage/innodb_plugin/scripts/install_innodb_plugins.sql +++ b/storage/innodb_plugin/scripts/install_innodb_plugins.sql @@ -7,3 +7,6 @@ INSTALL PLUGIN innodb_cmp SONAME 'ha_innodb.so'; INSTALL PLUGIN innodb_cmp_reset SONAME 'ha_innodb.so'; INSTALL PLUGIN innodb_cmpmem SONAME 'ha_innodb.so'; INSTALL PLUGIN innodb_cmpmem_reset SONAME 'ha_innodb.so'; +INSTALL PLUGIN innodb_buffer_pool_stats SONAME 'ha_innodb.so'; +INSTALL PLUGIN innodb_buffer_page SONAME 'ha_innodb.so'; +INSTALL PLUGIN innodb_buffer_page_lru SONAME 'ha_innodb.so'; diff --git a/storage/innodb_plugin/scripts/install_innodb_plugins_win.sql b/storage/innodb_plugin/scripts/install_innodb_plugins_win.sql index 8c94b4e240d..023b13132c3 100644 --- a/storage/innodb_plugin/scripts/install_innodb_plugins_win.sql +++ b/storage/innodb_plugin/scripts/install_innodb_plugins_win.sql @@ -7,3 +7,6 @@ INSTALL PLUGIN innodb_cmp SONAME 'ha_innodb.dll'; INSTALL PLUGIN innodb_cmp_reset SONAME 'ha_innodb.dll'; INSTALL PLUGIN innodb_cmpmem SONAME 'ha_innodb.dll'; INSTALL PLUGIN innodb_cmpmem_reset SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_buffer_pool_stats SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_buffer_page SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_buffer_page_lru SONAME 'ha_innodb.dll'; -- cgit v1.2.1 From aca566d79888293ad5e0a6bad10c35d0a9b36893 Mon Sep 17 00:00:00 2001 From: Sujatha Sivakumar Date: Wed, 25 Jul 2012 14:56:37 +0530 Subject: Follow up patch for BUG#13961678. Fixing compilation warning given below. "warning: integer constant is too large for 'long' type" --- mysys/mf_iocache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 8c91befe905..7aa0934096f 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -1532,7 +1532,7 @@ int _my_b_write(register IO_CACHE *info, const uchar *Buffer, size_t Count) DBUG_EXECUTE_IF("simulate_huge_load_data_file", { - pos_in_file=5000000000; + pos_in_file=(my_off_t)(5000000000ULL); }); if (pos_in_file+info->buffer_length > info->end_of_file) { -- cgit v1.2.1 From fa0d2df5ff6915427b907450939e6ef3cef9408a Mon Sep 17 00:00:00 2001 From: Thayumanavar Date: Wed, 25 Jul 2012 16:24:18 +0530 Subject: Bug#13699303 - THREAD POOL PLUGIN IGNORES TIMEOUT. PROBLEM: mysql provides a feature where in a session which is idle for a period specified by the wait_timeout variable (whose value is in seconds), the session is closed This feature is not present when we use thread pool. FIX: This patch implements the interface functions which is required to implement the wait_timeout functionality in the thread pool plugin. --- include/mysql/thread_pool_priv.h | 22 ++++++++++++++++++++++ sql/sql_class.cc | 23 +++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index b4b68e6880d..d649655bb8e 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -35,6 +35,7 @@ #include #include #include +#include /* Needed to get access to scheduler variables */ void* thd_get_scheduler_data(THD *thd); @@ -56,9 +57,30 @@ void thd_unlock_data(THD *thd); bool thd_is_transaction_active(THD *thd); int thd_connection_has_data(THD *thd); void thd_set_net_read_write(THD *thd, uint val); +uint thd_get_net_read_write(THD *thd); void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var); +ulong thd_get_net_wait_timeout(THD *thd); my_socket thd_get_fd(THD *thd); +/* Interface class for global thread list iteration */ +class Thread_iterator +{ + public: + Thread_iterator() : m_iterator(threads) {} + THD* next() + { + THD* tmp = m_iterator++; + return tmp; + } + private: + /* + Don't allow copying of this class. + */ + Thread_iterator(const Thread_iterator&); + void operator=(const Thread_iterator&); + I_List_iterator m_iterator; +}; + /* Print to the MySQL error log */ void sql_print_error(const char *format, ...); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8931d67dd25..b0d7cac1864 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -254,6 +254,18 @@ PSI_thread *thd_get_psi(THD *thd) return thd->scheduler.m_psi; } +/** + Get net_wait_timeout for THD object + + @param thd THD object + + @retval net_wait_timeout value for thread on THD +*/ +ulong thd_get_net_wait_timeout(THD* thd) +{ + return thd->variables.net_wait_timeout; +} + /** Set reference to Performance Schema object for THD object @@ -422,6 +434,17 @@ void thd_set_net_read_write(THD *thd, uint val) thd->net.reading_or_writing= val; } +/** + Get reading/writing on socket from THD object + @param thd THD object + + @retval net.reading_or_writing value for thread on THD. +*/ +uint thd_get_net_read_write(THD *thd) +{ + return thd->net.reading_or_writing; +} + /** Set reference to mysys variable in THD object -- cgit v1.2.1 From aef1982be0a5ff5bd25fb7658d8792fd9ab40c3f Mon Sep 17 00:00:00 2001 From: Venkata Sidagam Date: Thu, 26 Jul 2012 15:09:22 +0530 Subject: Bug #12876932 - INCORRECT SELECT RESULT ON FEDERATED TABLE Problem description: Table 't' created with two colums having compound index on both the columns under innodb/myisam engine at remote machine. In the local machine same table is created undet the federated engine. A select having where clause with along 'AND' operation gives wrong results on local machine. Analysis: The given query at federated engine is wrongly transformed by federated::create_where_from_key() function and the same was sent to the remote machine. Hence the local machine is showing wrong results. Given query "select c1 from t where c1 <= 2 and c2 = 1;" Query transformed, after ha_federated::create_where_from_key() function is: SELECT `c1`, `c2` FROM `t` WHERE (`c1` IS NOT NULL ) AND ( (`c1` >= 2) AND (`c2` <= 1) ) and the same sent to real_query(). In the above the '<=' and '=' conditions were transformed to '>=' and '<=' respectively. ha_federated::create_where_from_key() function behaving as below: The key_range is having both the start_key and end_key. The start_key is used to get "(`c1` IS NOT NULL )" part of the where clause, this transformation is correct. The end_key is used to get "( (`c1` >= 2) AND (`c2` <= 1) )", which is wrong, here the given conditions('<=' and '=') are changed as wrong conditions('>=' and '<='). The end_key is having {key = 0x39fa6d0 "", length = 10, keypart_map = 3, flag = HA_READ_AFTER_KEY} The store_length is having value '5'. Based on store_length and length values the condition values is applied in HA_READ_AFTER_KEY switch case. The switch case 'HA_READ_AFTER_KEY' is applicable to only the last part of the end_key and for previous parts it is going to 'HA_READ_KEY_OR_NEXT' case, here the '>=' is getting added as a condition instead of '<='. Fix: Updated the 'if' condition in 'HA_READ_AFTER_KEY' case to affect for all parts of the end_key. i.e 'i > 0' will used for end_key, Hence added it in the if condition. mysql-test/suite/federated/federated.test: modified the federated.inc file location mysql-test/suite/federated/federated_archive.test: modified the federated.inc file location mysql-test/suite/federated/federated_bug_13118.test: modified the federated.inc file location mysql-test/suite/federated/federated_bug_25714.test: modified the federated.inc file location mysql-test/suite/federated/federated_bug_35333.test: modified the federated.inc file location mysql-test/suite/federated/federated_debug.test: modified the federated.inc file location mysql-test/suite/federated/federated_innodb.test: modified the federated.inc file location mysql-test/suite/federated/federated_server.test: modified the federated.inc file location mysql-test/suite/federated/federated_transactions.test: modified the federated.inc file location mysql-test/suite/federated/include/federated.inc: moved the file from federated suite to federated/include folder mysql-test/suite/federated/include/federated_cleanup.inc: moved the file from federated suite to federated/include folder mysql-test/suite/federated/include/have_federated_db.inc: moved the file from federated suite to federated/include folder storage/federated/ha_federated.cc: updated the 'if condition' in ha_federated::create_where_from_key() function. --- mysql-test/suite/federated/federated.inc | 11 ----------- mysql-test/suite/federated/federated.test | 4 ++-- mysql-test/suite/federated/federated_archive.test | 4 ++-- mysql-test/suite/federated/federated_bug_13118.test | 4 ++-- mysql-test/suite/federated/federated_bug_25714.test | 4 ++-- mysql-test/suite/federated/federated_bug_35333.test | 4 ++-- mysql-test/suite/federated/federated_cleanup.inc | 9 --------- mysql-test/suite/federated/federated_debug.test | 4 ++-- mysql-test/suite/federated/federated_innodb.test | 4 ++-- mysql-test/suite/federated/federated_server.test | 4 ++-- mysql-test/suite/federated/federated_transactions.test | 4 ++-- mysql-test/suite/federated/have_federated_db.inc | 6 ------ mysql-test/suite/federated/include/federated.inc | 11 +++++++++++ mysql-test/suite/federated/include/federated_cleanup.inc | 9 +++++++++ mysql-test/suite/federated/include/have_federated_db.inc | 6 ++++++ mysql-test/t/partition_federated.test | 2 +- storage/federated/ha_federated.cc | 2 +- 17 files changed, 46 insertions(+), 46 deletions(-) delete mode 100644 mysql-test/suite/federated/federated.inc delete mode 100644 mysql-test/suite/federated/federated_cleanup.inc delete mode 100644 mysql-test/suite/federated/have_federated_db.inc create mode 100644 mysql-test/suite/federated/include/federated.inc create mode 100644 mysql-test/suite/federated/include/federated_cleanup.inc create mode 100644 mysql-test/suite/federated/include/have_federated_db.inc diff --git a/mysql-test/suite/federated/federated.inc b/mysql-test/suite/federated/federated.inc deleted file mode 100644 index ad640dcbb61..00000000000 --- a/mysql-test/suite/federated/federated.inc +++ /dev/null @@ -1,11 +0,0 @@ ---source include/not_embedded.inc ---source have_federated_db.inc - -connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,); -connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,); - -connection master; -CREATE DATABASE federated; - -connection slave; -CREATE DATABASE federated; diff --git a/mysql-test/suite/federated/federated.test b/mysql-test/suite/federated/federated.test index a1d86462c11..55a672587c8 100644 --- a/mysql-test/suite/federated/federated.test +++ b/mysql-test/suite/federated/federated.test @@ -6,7 +6,7 @@ # should work with embedded server after mysqltest is fixed --source include/not_embedded.inc ---source federated.inc +--source suite/federated/include/federated.inc connection default; @@ -1999,4 +1999,4 @@ connection slave; SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT; connection default; -source federated_cleanup.inc; +source suite/federated/include/federated_cleanup.inc; diff --git a/mysql-test/suite/federated/federated_archive.test b/mysql-test/suite/federated/federated_archive.test index 1bde23889be..b35b82c6fa6 100644 --- a/mysql-test/suite/federated/federated_archive.test +++ b/mysql-test/suite/federated/federated_archive.test @@ -1,5 +1,5 @@ source include/have_archive.inc; -source federated.inc; +source suite/federated/include/federated.inc; connection slave; @@ -54,5 +54,5 @@ connection slave; DROP TABLE federated.archive_table; -source federated_cleanup.inc; +source suite/federated/include/federated_cleanup.inc; diff --git a/mysql-test/suite/federated/federated_bug_13118.test b/mysql-test/suite/federated/federated_bug_13118.test index fad6be75dac..78115a7959f 100644 --- a/mysql-test/suite/federated/federated_bug_13118.test +++ b/mysql-test/suite/federated/federated_bug_13118.test @@ -1,4 +1,4 @@ -source federated.inc; +source suite/federated/include/federated.inc; connection slave; --disable_warnings @@ -37,5 +37,5 @@ connection slave; DROP TABLE federated.bug_13118_table; -source federated_cleanup.inc; +source suite/federated/include/federated_cleanup.inc; diff --git a/mysql-test/suite/federated/federated_bug_25714.test b/mysql-test/suite/federated/federated_bug_25714.test index 82745b2a094..0d5ecb7d99f 100644 --- a/mysql-test/suite/federated/federated_bug_25714.test +++ b/mysql-test/suite/federated/federated_bug_25714.test @@ -4,7 +4,7 @@ if (`select LENGTH("$MYSQL_BUG25714") = 0`) skip Need bug25714 test program; } -source federated.inc; +source suite/federated/include/federated.inc; connection master; # Disable concurrent inserts to avoid test failures when reading @@ -59,4 +59,4 @@ SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT; -source federated_cleanup.inc; +source suite/federated/include/federated_cleanup.inc; diff --git a/mysql-test/suite/federated/federated_bug_35333.test b/mysql-test/suite/federated/federated_bug_35333.test index 58c217d24f2..cea8d5b36b9 100644 --- a/mysql-test/suite/federated/federated_bug_35333.test +++ b/mysql-test/suite/federated/federated_bug_35333.test @@ -9,7 +9,7 @@ --echo # to complete while still indicating a problem. This fix applies to any non-fatal system --echo # error that occurs during a query against I_S.TABLES.de ---source federated.inc +--source suite/federated/include/federated.inc --disable_warnings CREATE DATABASE IF NOT EXISTS realdb; @@ -71,4 +71,4 @@ DROP TABLE IF EXISTS federated.t0; DROP DATABASE realdb; --enable_warnings ---source federated_cleanup.inc +--source suite/federated/include/federated_cleanup.inc diff --git a/mysql-test/suite/federated/federated_cleanup.inc b/mysql-test/suite/federated/federated_cleanup.inc deleted file mode 100644 index e96a7cd2cee..00000000000 --- a/mysql-test/suite/federated/federated_cleanup.inc +++ /dev/null @@ -1,9 +0,0 @@ -connection master; ---disable_warnings -DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; - -connection slave; -DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; ---enable_warnings diff --git a/mysql-test/suite/federated/federated_debug.test b/mysql-test/suite/federated/federated_debug.test index 4152d2975b3..ba6688e1dc0 100644 --- a/mysql-test/suite/federated/federated_debug.test +++ b/mysql-test/suite/federated/federated_debug.test @@ -1,5 +1,5 @@ --source include/have_debug.inc ---source federated.inc +--source suite/federated/include/federated.inc --echo # --echo # Bug#47525: MySQL crashed (Federated) @@ -36,4 +36,4 @@ DROP TABLE t1; connection default; --echo # Federated cleanup -source federated_cleanup.inc; +source suite/federated/include/federated_cleanup.inc; diff --git a/mysql-test/suite/federated/federated_innodb.test b/mysql-test/suite/federated/federated_innodb.test index 278c5b18661..9212ba12b81 100644 --- a/mysql-test/suite/federated/federated_innodb.test +++ b/mysql-test/suite/federated/federated_innodb.test @@ -4,7 +4,7 @@ # See Bug #40645 Test main.federated_innodb does not always clean up after itself source include/have_innodb.inc; -source federated.inc; +source suite/federated/include/federated.inc; # # Bug#25513 Federated transaction failures @@ -36,4 +36,4 @@ connection slave; drop table federated.t1; -source federated_cleanup.inc; +source suite/federated/include/federated_cleanup.inc; diff --git a/mysql-test/suite/federated/federated_server.test b/mysql-test/suite/federated/federated_server.test index 64ee74edb16..47a2e72b54b 100644 --- a/mysql-test/suite/federated/federated_server.test +++ b/mysql-test/suite/federated/federated_server.test @@ -1,6 +1,6 @@ # WL #3031 This test tests the new servers table as well as # if federated can utilise the servers table --- source federated.inc +-- source suite/federated/include/federated.inc connection slave; create database first_db; @@ -333,4 +333,4 @@ drop procedure p1; drop server if exists s; -source federated_cleanup.inc; +source suite/federated/include/federated_cleanup.inc; diff --git a/mysql-test/suite/federated/federated_transactions.test b/mysql-test/suite/federated/federated_transactions.test index cd08d310273..3cf41a849d6 100644 --- a/mysql-test/suite/federated/federated_transactions.test +++ b/mysql-test/suite/federated/federated_transactions.test @@ -1,5 +1,5 @@ source include/have_innodb.inc; -source federated.inc; +source suite/federated/include/federated.inc; connection slave; DROP TABLE IF EXISTS federated.t1; @@ -35,4 +35,4 @@ INSERT INTO federated.t1 (id, name) VALUES (6, 'fig'); SELECT * FROM federated.t1; DELETE FROM federated.t1; -source federated_cleanup.inc; +source suite/federated/include/federated_cleanup.inc; diff --git a/mysql-test/suite/federated/have_federated_db.inc b/mysql-test/suite/federated/have_federated_db.inc deleted file mode 100644 index 81f49aaa48e..00000000000 --- a/mysql-test/suite/federated/have_federated_db.inc +++ /dev/null @@ -1,6 +0,0 @@ -if (!`SELECT count(*) FROM information_schema.engines WHERE - (support = 'YES' OR support = 'DEFAULT') AND - engine = 'federated'`) -{ - skip Need federated engine; -} diff --git a/mysql-test/suite/federated/include/federated.inc b/mysql-test/suite/federated/include/federated.inc new file mode 100644 index 00000000000..53846dfa7d8 --- /dev/null +++ b/mysql-test/suite/federated/include/federated.inc @@ -0,0 +1,11 @@ +--source include/not_embedded.inc +--source suite/federated/include/have_federated_db.inc + +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,); +connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,); + +connection master; +CREATE DATABASE federated; + +connection slave; +CREATE DATABASE federated; diff --git a/mysql-test/suite/federated/include/federated_cleanup.inc b/mysql-test/suite/federated/include/federated_cleanup.inc new file mode 100644 index 00000000000..e96a7cd2cee --- /dev/null +++ b/mysql-test/suite/federated/include/federated_cleanup.inc @@ -0,0 +1,9 @@ +connection master; +--disable_warnings +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE federated; + +connection slave; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE federated; +--enable_warnings diff --git a/mysql-test/suite/federated/include/have_federated_db.inc b/mysql-test/suite/federated/include/have_federated_db.inc new file mode 100644 index 00000000000..81f49aaa48e --- /dev/null +++ b/mysql-test/suite/federated/include/have_federated_db.inc @@ -0,0 +1,6 @@ +if (!`SELECT count(*) FROM information_schema.engines WHERE + (support = 'YES' OR support = 'DEFAULT') AND + engine = 'federated'`) +{ + skip Need federated engine; +} diff --git a/mysql-test/t/partition_federated.test b/mysql-test/t/partition_federated.test index 0fe692ecd01..3993aeafd31 100644 --- a/mysql-test/t/partition_federated.test +++ b/mysql-test/t/partition_federated.test @@ -3,7 +3,7 @@ # -- source include/have_partition.inc -- source include/not_embedded.inc --- source suite/federated/have_federated_db.inc +-- source suite/federated/include/have_federated_db.inc --disable_warnings drop table if exists t1; diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index ae65aeb4cbb..7dd4f6b7149 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -1364,7 +1364,7 @@ bool ha_federated::create_where_from_key(String *to, break; } DBUG_PRINT("info", ("federated HA_READ_AFTER_KEY %d", i)); - if (store_length >= length) /* end key */ + if ((store_length >= length) || (i > 0)) /* for all parts of end key*/ { if (emit_key_part_name(&tmp, key_part)) goto err; -- cgit v1.2.1 From d24a78d1ea2b07cd1b3863190b371c7c8ea39a3c Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Thu, 26 Jul 2012 15:05:24 +0200 Subject: Backport of Bug#14171740 65562: STRING::SHRINK SHOULD BE A NO-OP WHEN ALLOCED=0 --- client/sql_string.h | 10 +++++++--- sql/sql_string.h | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/client/sql_string.h b/client/sql_string.h index 020bf78a6de..57d4d196e8c 100644 --- a/client/sql_string.h +++ b/client/sql_string.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -195,8 +195,12 @@ public: } bool real_alloc(uint32 arg_length); // Empties old string bool realloc(uint32 arg_length); - inline void shrink(uint32 arg_length) // Shrink buffer + + // Shrink the buffer, but only if it is allocated on the heap. + inline void shrink(uint32 arg_length) { + if (!is_alloced()) + return; if (arg_length < Alloced_length) { char *new_ptr; @@ -212,7 +216,7 @@ public: } } } - bool is_alloced() { return alloced; } + bool is_alloced() const { return alloced; } inline String& operator = (const String &s) { if (&s != this) diff --git a/sql/sql_string.h b/sql/sql_string.h index e5a41352992..6d5e8c46c55 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -225,8 +225,12 @@ public: } bool real_alloc(uint32 arg_length); // Empties old string bool realloc(uint32 arg_length); - inline void shrink(uint32 arg_length) // Shrink buffer + + // Shrink the buffer, but only if it is allocated on the heap. + inline void shrink(uint32 arg_length) { + if (!is_alloced()) + return; if (arg_length < Alloced_length) { char *new_ptr; @@ -242,7 +246,7 @@ public: } } } - bool is_alloced() { return alloced; } + bool is_alloced() const { return alloced; } inline String& operator = (const String &s) { if (&s != this) -- cgit v1.2.1 From 55f3fd4d635a5f7fa643ef87556ed0547ded4ae9 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 26 Jul 2012 21:47:03 +0530 Subject: Bug#13741677 MYSQL_SECURE_INSTALLATION DOES NOT WORK + SAVES ROOT PASSWORD TO DISK! The secure installation scripts connect to the server by storing the password in a temporary option file. Now, if the script gets killed or fails for some reason, the removal of the option file may not take place. This patch introduces following enhancements : * (.sh) Made sure that cleanup happens at every call to 'exit 1'. This is performed implicitly by END{} in pl.in. * (.pl.in) Added a warning in case unlink fails to delete the option/query files. * (.sh/.pl.in) Added more signals to the signal handler list. SIG# 1, 3, 6, 15 --- scripts/mysql_secure_installation.pl.in | 10 +++++++--- scripts/mysql_secure_installation.sh | 18 +++++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/scripts/mysql_secure_installation.pl.in b/scripts/mysql_secure_installation.pl.in index 543b8d1b1c0..278fffe7322 100755 --- a/scripts/mysql_secure_installation.pl.in +++ b/scripts/mysql_secure_installation.pl.in @@ -1,7 +1,7 @@ #!/usr/bin/perl # -*- cperl -*- # -# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ my $mysql; # How to call the mysql client my $rootpass = ""; -$SIG{QUIT} = $SIG{INT} = sub { +$SIG{QUIT} = $SIG{INT} = $SIG{TERM} = $SIG{ABRT} = $SIG{HUP} = sub { print "\nAborting!\n\n"; echo_on(); cleanup(); @@ -242,7 +242,11 @@ sub reload_privilege_tables { } sub cleanup { - unlink($config,$command); + print "Cleaning up...\n"; + + foreach my $file ($config, $command) { + unlink $file or warn "Warning: Could not unlink $file: $!\n"; + } } diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh index 5e84a92a76c..c92cb1262df 100644 --- a/scripts/mysql_secure_installation.sh +++ b/scripts/mysql_secure_installation.sh @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,7 +19,7 @@ config=".my.cnf.$$" command=".mysql.$$" mysql_client="" -trap "interrupt" 2 +trap "interrupt" 1 2 3 6 15 rootpass="" echo_n= @@ -139,13 +139,16 @@ set_root_password() { if [ $? -eq 0 ]; then echo "Password updated successfully!" echo "Reloading privilege tables.." - reload_privilege_tables || exit 1 + reload_privilege_tables + if [ $? -eq 1 ]; then + clean_and_exit + fi echo rootpass=$password1 make_config else echo "Password update failed!" - exit 1 + clean_and_exit fi return 0 @@ -157,7 +160,7 @@ remove_anonymous_users() { echo " ... Success!" else echo " ... Failed!" - exit 1 + clean_and_exit fi return 0 @@ -217,6 +220,11 @@ cleanup() { rm -f $config $command } +# Remove the files before exiting. +clean_and_exit() { + cleanup + exit 1 +} # The actual script starts here -- cgit v1.2.1 From b6ecca263cc0b1bc974b2917e61b66793276396c Mon Sep 17 00:00:00 2001 From: Venkata Sidagam Date: Thu, 26 Jul 2012 23:23:04 +0530 Subject: Bug #12876932 - INCORRECT SELECT RESULT ON FEDERATED TABLE Fix for pb2 test failure. --- mysql-test/suite/funcs_1/t/is_engines_federated.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/funcs_1/t/is_engines_federated.test b/mysql-test/suite/funcs_1/t/is_engines_federated.test index 81eac89c0d2..061df1db76a 100644 --- a/mysql-test/suite/funcs_1/t/is_engines_federated.test +++ b/mysql-test/suite/funcs_1/t/is_engines_federated.test @@ -9,7 +9,7 @@ # let $engine_type= FEDERATED; ---source suite/federated/have_federated_db.inc +--source suite/federated/include/have_federated_db.inc --vertical_results eval SELECT * FROM information_schema.engines WHERE ENGINE = '$engine_type'; -- cgit v1.2.1 From 44cd81da86e41c6ac7114ef8dbd31c738eba095d Mon Sep 17 00:00:00 2001 From: Praveenkumar Hulakund Date: Thu, 26 Jul 2012 23:44:43 +0530 Subject: BUG#13868860 - LIMIT '5' IS EXECUTED WITHOUT ERROR WHEN '5' IS PLACE HOLDER AND USE SERVER-SIDE Analysis: LIMIT always takes nonnegative integer constant values. http://dev.mysql.com/doc/refman/5.6/en/select.html So parsing of value '5' for LIMIT in SELECT fails. But, within prepared statement, LIMIT parameters can be specified using '?' markers. Value for the parameter can be supplied while executing the prepared statement. Passing string values, float or double value for LIMIT works well from CLI. Because, while setting the value for the parameters from the variable list (added using SET), if the value is for parameter LIMIT then its converted to integer value. But, when prepared statement is executed from the other interfaces as J connectors, or C applications etc. The value for the parameters are sent to the server with execute command. Each item in log has value and the data TYPE. So, While setting parameter value from this log, value is set to all the parameters with the same data type as passed. But here logic to convert value to integer type if its for LIMIT parameter is missing. Because of this,string '5' is set to LIMIT. And the same is logged into the binlog file too. Fix: When executing prepared statement having parameter for CLI it worked fine, as the value set for the parameter is converted to integer. And this failed in other interfaces as J connector,C Applications etc as this conversion is missing. So, as a fix added check while setting value for the parameters. If the parameter is for LIMIT value then its converted to integer value. --- sql/sql_prepare.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 27e70aaf843..2afd4085c51 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -785,6 +785,14 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, param->set_param_func(param, &read_pos, (uint) (data_end - read_pos)); if (param->state == Item_param::NO_VALUE) DBUG_RETURN(1); + + if (param->limit_clause_param && param->item_type != Item::INT_ITEM) + { + param->set_int(param->val_int(), MY_INT64_NUM_DECIMAL_DIGITS); + param->item_type= Item::INT_ITEM; + if (!param->unsigned_flag && param->value.integer < 0) + DBUG_RETURN(1); + } } } /* -- cgit v1.2.1 From e130d9efbfe7c6231d8912fadb329f279b5787da Mon Sep 17 00:00:00 2001 From: Venkata Sidagam Date: Fri, 27 Jul 2012 12:05:37 +0530 Subject: Bug #12876932 - INCORRECT SELECT RESULT ON FEDERATED TABLE Fixed the missing of federated/include folder at the time of preparing package distribution, issue happens only in 5.1 --- mysql-test/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index e5783d33a88..9d61aa98764 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -81,6 +81,7 @@ TEST_DIRS = t r include std_data std_data/parts collections \ extra/binlog_tests/ extra/rpl_tests \ suite/binlog suite/binlog/t suite/binlog/r suite/binlog/std_data \ suite/federated \ + suite/federated/include \ suite/funcs_1 suite/funcs_1/bitdata \ suite/funcs_1/include suite/funcs_1/lib suite/funcs_1/r \ suite/funcs_1/t suite/funcs_1/views suite/funcs_1/cursors \ -- cgit v1.2.1 From 5f2f37cd4164a9e883d3b385e9ba6842c49a1d29 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Fri, 27 Jul 2012 09:13:10 +0200 Subject: Bug#14111180 HANDLE_FATAL_SIGNAL IN PTR_COMPARE_1 / QUEUE_INSERT Space available for merging was calculated incorrectly. --- sql/filesort.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sql/filesort.cc b/sql/filesort.cc index e6842cec4a2..3a2102fa62b 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -295,8 +295,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, Use also the space previously used by string pointers in sort_buffer for temporary key storage. */ - param.keys=((param.keys*(param.rec_length+sizeof(char*))) / - param.rec_length-1); + param.keys= table_sort.sort_keys_size / param.rec_length; maxbuffer--; // Offset from 0 if (merge_many_buff(¶m,(uchar*) sort_keys,buffpek,&maxbuffer, &tempfile)) -- cgit v1.2.1 From d0f2e1b0d1216ece14bc7b60d7d6bc4b35207bd7 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Tue, 31 Jul 2012 20:41:46 +0200 Subject: INSTALL-BINARY placeholder: change invalid URLs (request from Kristofer) --- Docs/INSTALL-BINARY | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Docs/INSTALL-BINARY b/Docs/INSTALL-BINARY index d1c409acd67..e592e05a46d 100644 --- a/Docs/INSTALL-BINARY +++ b/Docs/INSTALL-BINARY @@ -1,8 +1,8 @@ -You can find information about how to install binary distributions at +You can find information about installing MySQL at - http://dev.mysql.com/doc/refman/5.1/en/quick-standard-installation.html + http://dev.mysql.com/doc/refman/5.1/en/installing.html The MySQL Reference Manual is also available in various formats on http://dev.mysql.com/doc; if you're interested in the DocBook XML -sources go to http://svn.mysql.com. +sources go to http://dev.mysql.com/doc/index-other.html. -- cgit v1.2.1 -- cgit v1.2.1 From c61abdadcfd977b624c6623f395521369aabb63a Mon Sep 17 00:00:00 2001 From: Chaithra Gopalareddy Date: Sun, 5 Aug 2012 16:29:28 +0530 Subject: Bug #14099846: EXPORT_SET CRASHES DUE TO OVERALLOCATION OF MEMORY Backport the fix from 5.6 to 5.1 Base bug number : 11765562 sql/item_strfunc.cc: In Item_func_export_set::val_str, verify that the size of the end result is within reasonable bounds. --- sql/item_strfunc.cc | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index ed14f7f01e9..27483ede032 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3047,23 +3047,21 @@ err: String* Item_func_export_set::val_str(String* str) { DBUG_ASSERT(fixed == 1); - ulonglong the_set = (ulonglong) args[0]->val_int(); - String yes_buf, *yes; - yes = args[1]->val_str(&yes_buf); - String no_buf, *no; - no = args[2]->val_str(&no_buf); - String *sep = NULL, sep_buf ; + String yes_buf, no_buf, sep_buf; + const ulonglong the_set = (ulonglong) args[0]->val_int(); + const String *yes= args[1]->val_str(&yes_buf); + const String *no= args[2]->val_str(&no_buf); + const String *sep= NULL; uint num_set_values = 64; - ulonglong mask = 0x1; str->length(0); str->set_charset(collation.collation); /* Check if some argument is a NULL value */ if (args[0]->null_value || args[1]->null_value || args[2]->null_value) { - null_value=1; - return 0; + null_value= true; + return NULL; } /* Arg count can only be 3, 4 or 5 here. This is guaranteed from the @@ -3076,37 +3074,56 @@ String* Item_func_export_set::val_str(String* str) num_set_values=64; if (args[4]->null_value) { - null_value=1; - return 0; + null_value= true; + return NULL; } /* Fall through */ case 4: if (!(sep = args[3]->val_str(&sep_buf))) // Only true if NULL { - null_value=1; - return 0; + null_value= true; + return NULL; } break; case 3: { /* errors is not checked - assume "," can always be converted */ uint errors; - sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin, collation.collation, &errors); + sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin, + collation.collation, &errors); sep = &sep_buf; } break; default: DBUG_ASSERT(0); // cannot happen } - null_value=0; + null_value= false; + + const ulong max_allowed_packet= current_thd->variables.max_allowed_packet; + const uint num_separators= num_set_values > 0 ? num_set_values - 1 : 0; + const ulonglong max_total_length= + num_set_values * max(yes->length(), no->length()) + + num_separators * sep->length(); + + if (unlikely(max_total_length > max_allowed_packet)) + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_ALLOWED_PACKET_OVERFLOWED, + ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), + func_name(), max_allowed_packet); + null_value= true; + return NULL; + } - for (uint i = 0; i < num_set_values; i++, mask = (mask << 1)) + uint ix; + ulonglong mask; + for (ix= 0, mask=0x1; ix < num_set_values; ++ix, mask = (mask << 1)) { if (the_set & mask) str->append(*yes); else str->append(*no); - if (i != num_set_values - 1) + if (ix != num_separators) str->append(*sep); } return str; -- cgit v1.2.1 From d0766534bd67554d6be36bf00a8dbd5fdf385042 Mon Sep 17 00:00:00 2001 From: Praveenkumar Hulakund Date: Tue, 7 Aug 2012 11:48:36 +0530 Subject: Bug#13058122 - DML, LOCK/UNLOCK TABLES AND SELECT LEAD TO FOREVER MDL LOCK Analysis: ---------- While granting MDL lock for the lock requests in wait queue, first the lock is granted to the high priority lock types and then to the low priority lock types. MDL Priority Matrix, +-------------+----+---+---+---+----+-----+ | Locks | | | | | | | | has Priority| | | | | | | | over ---> | S | SR| SW| SU| SNW| SNRW| +-------------+----+---+---+---+----+-----+ | X | + | + | + | + | + | + | +-------------|----|---|---|---|----|-----| | SNRW | - | + | + | - | - | - | +-------------|----|---|---|---|----|-----| | SNW | - | - | + | - | - | - | +-------------+----+---+---+---+----+-----+ Here '+' means, Lock priority is higher. '-' means, Has same priority In the scenario where, *. Lock wait queue has requests of type S/SR/SW/SU. *. And locks of high priority X/SNRW/SNW are requested continuously. In this case, while granting lock, always first high priority lock requests(X/SNRW/SNW) are considered. Low priority locks(S/SR/SW/SU) will not get chance and they will wait forever. In the scenario for which this bug is reported, application executed many LOCK TABLES ... WRITE statements concurrently. These statements request SNRW lock. Also there were some connections trying to execute DML statements requesting SR lock. Since SNRW lock request has higher priority (and as they were too many waiting SNRW requests) lock is always granted to it. So, lock request SR will wait forever, resulting in DML starvation. How is this handled in 5.1? --------------------------- Even in 5.1 we have low priority lock starvation issue. But, in 5.1 thread locking, system variable "max_write_lock_count" can be configured to grant some pending read lock requests. After "max_write_lock_count" of write lock grants all the low priority locks are granted. Why this issue is seen in 5.5/trunk? --------------------------------- In 5.5/trunk MDL locking, "max_write_lock_count" system variable exists but not used in MDL, only thread lock uses it. So no effect of "max_write_lock_count" in MDL locking. This means that starvation of metadata locks is possible even if max_write_lock_count is used. Looks like, customer was using "max_write_lock_count" in 5.1 and when upgraded to 5.5, starvation is seen because of not having effect of "max_write_lock_count" in MDL. Fix: ---------- As a fix, support for max_write_lock_count is added to MDL. To maintain write lock counter per MDL_lock object, new member "m_hog_lock_count" is added in MDL_lock. And following logic is added to increment the counter in function reschedule_waiters, (reschedule_waiters function is called while thread is releasing the lock) - After granting lock request from the wait queue. - Check if there are any S/SR/SU/SW exists in the wait queue - If yes then increment the "m_hog_lock_count" And following logic is added in the same function to handle pending S/SU/SR/SW locks - Before granting locks - Check if max_write_lock_count <= m_hog_lock_count - If Yes, then try to grant S/SR/SW/SU locks. (Since all of these has same priority, all locks are granted together. But some lock grant may fail because of grant incompatibility) - Reset m_hog_lock_count if there no low priority lock requests in wait queue. - return Note: -------------------------- In the lock priority matrix explained above, though X has priority over the SNW and SNRW. X locks is taken mostly for RENAME, TRUNCATE, CREATE ... operations. So lock type X may not be requested in loop continuously in real world applications, as compared to other lock request types. So, lock request of type SNW and SNRW are not starved. So, we can grant all S/SR/SU/SW in one shot, without considering SNW & SNRW lock request starvation. ALTER table operations take SU lock first and then upgrade to SNW if required. All S, SR, SW, SU have same lock priority. So while granting SU, request of types SR, SW, S are also granted in one shot. So, lock request of type SU->SNW in loop will not make other low priority lock request to starve. But, when there is request for lock of type SNRW, lock requests of lower priority types are not granted. And if SNRW is requested in loop continuously then all S, SR, SW, SU are starved. This patch addresses the latter scenario. When we have S/SR/SW/SU in wait queue and if there are - Continuous SNRW lock requests - OR one or more X and Continuous SNRW lock requests. - OR one SNW and Continuous SNRW lock requests. - OR one SNW, one or more X and continuous SNRW lock requests. in wait queue then, S/SR/SW/SU lock request are starved. --- sql/mdl.cc | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- sql/mdl.h | 6 ++++ 2 files changed, 118 insertions(+), 8 deletions(-) diff --git a/sql/mdl.cc b/sql/mdl.cc index 81d6c69dca4..1a968f27841 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -378,7 +378,8 @@ public: bool has_pending_conflicting_lock(enum_mdl_type type); - bool can_grant_lock(enum_mdl_type type, MDL_context *requstor_ctx) const; + bool can_grant_lock(enum_mdl_type type, MDL_context *requstor_ctx, + bool ignore_lock_priority) const; inline static MDL_lock *create(const MDL_key *key); @@ -392,14 +393,24 @@ public: virtual bool needs_notification(const MDL_ticket *ticket) const = 0; virtual void notify_conflicting_locks(MDL_context *ctx) = 0; + virtual bitmap_t hog_lock_types_bitmap() const = 0; + /** List of granted tickets for this lock. */ Ticket_list m_granted; /** Tickets for contexts waiting to acquire a lock. */ Ticket_list m_waiting; + + /** + Number of times high priority lock requests have been granted while + low priority lock requests were waiting. + */ + ulong m_hog_lock_count; + public: MDL_lock(const MDL_key *key_arg) : key(key_arg), + m_hog_lock_count(0), m_ref_usage(0), m_ref_release(0), m_is_destroyed(FALSE), @@ -484,6 +495,15 @@ public: } virtual void notify_conflicting_locks(MDL_context *ctx); + /* + In scoped locks, only IX lock request would starve because of X/S. But that + is practically very rare case. So just return 0 from this function. + */ + virtual bitmap_t hog_lock_types_bitmap() const + { + return 0; + } + private: static const bitmap_t m_granted_incompatible[MDL_TYPE_END]; static const bitmap_t m_waiting_incompatible[MDL_TYPE_END]; @@ -536,6 +556,18 @@ public: } virtual void notify_conflicting_locks(MDL_context *ctx); + /* + To prevent starvation, these lock types that are only granted + max_write_lock_count times in a row while other lock types are + waiting. + */ + virtual bitmap_t hog_lock_types_bitmap() const + { + return (MDL_BIT(MDL_SHARED_NO_WRITE) | + MDL_BIT(MDL_SHARED_NO_READ_WRITE) | + MDL_BIT(MDL_EXCLUSIVE)); + } + private: static const bitmap_t m_granted_incompatible[MDL_TYPE_END]; static const bitmap_t m_waiting_incompatible[MDL_TYPE_END]; @@ -1267,6 +1299,41 @@ void MDL_lock::reschedule_waiters() { MDL_lock::Ticket_iterator it(m_waiting); MDL_ticket *ticket; + bool skip_high_priority= false; + bitmap_t hog_lock_types= hog_lock_types_bitmap(); + + if (m_hog_lock_count >= max_write_lock_count) + { + /* + If number of successively granted high-prio, strong locks has exceeded + max_write_lock_count give a way to low-prio, weak locks to avoid their + starvation. + */ + + if ((m_waiting.bitmap() & ~hog_lock_types) != 0) + { + /* + Even though normally when m_hog_lock_count is non-0 there is + some pending low-prio lock, we still can encounter situation + when m_hog_lock_count is non-0 and there are no pending low-prio + locks. This, for example, can happen when a ticket for pending + low-prio lock was removed from waiters list due to timeout, + and reschedule_waiters() is called after that to update the + waiters queue. m_hog_lock_count will be reset to 0 at the + end of this call in such case. + + Note that it is not an issue if we fail to wake up any pending + waiters for weak locks in the loop below. This would mean that + all of them are either killed, timed out or chosen as a victim + by deadlock resolver, but have not managed to remove ticket + from the waiters list yet. After tickets will be removed from + the waiters queue there will be another call to + reschedule_waiters() with pending bitmap updated to reflect new + state of waiters queue. + */ + skip_high_priority= true; + } + } /* Find the first (and hence the oldest) waiting request which @@ -1288,7 +1355,16 @@ void MDL_lock::reschedule_waiters() */ while ((ticket= it++)) { - if (can_grant_lock(ticket->get_type(), ticket->get_ctx())) + /* + Skip high-prio, strong locks if earlier we have decided to give way to + low-prio, weaker locks. + */ + if (skip_high_priority && + ((MDL_BIT(ticket->get_type()) & hog_lock_types) != 0)) + continue; + + if (can_grant_lock(ticket->get_type(), ticket->get_ctx(), + skip_high_priority)) { if (! ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED)) { @@ -1302,6 +1378,13 @@ void MDL_lock::reschedule_waiters() */ m_waiting.remove_ticket(ticket); m_granted.add_ticket(ticket); + + /* + Increase counter of successively granted high-priority strong locks, + if we have granted one. + */ + if ((MDL_BIT(ticket->get_type()) & hog_lock_types) != 0) + m_hog_lock_count++; } /* If we could not update the wait slot of the waiter, @@ -1313,6 +1396,24 @@ void MDL_lock::reschedule_waiters() */ } } + + if ((m_waiting.bitmap() & ~hog_lock_types) == 0) + { + /* + Reset number of successively granted high-prio, strong locks + if there are no pending low-prio, weak locks. + This ensures: + - That m_hog_lock_count is correctly reset after strong lock + is released and weak locks are granted (or there are no + other lock requests). + - That situation when SNW lock is granted along with some SR + locks, but SW locks are still blocked are handled correctly. + - That m_hog_lock_count is zero in most cases when there are no pending + weak locks (see comment at the start of this method for example of + exception). This allows to save on checks at the start of this method. + */ + m_hog_lock_count= 0; + } } @@ -1467,8 +1568,9 @@ MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END] = Check if request for the metadata lock can be satisfied given its current state. - @param type_arg The requested lock type. - @param requestor_ctx The MDL context of the requestor. + @param type_arg The requested lock type. + @param requestor_ctx The MDL context of the requestor. + @param ignore_lock_priority Ignore lock priority. @retval TRUE Lock request can be satisfied @retval FALSE There is some conflicting lock. @@ -1480,19 +1582,21 @@ MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END] = bool MDL_lock::can_grant_lock(enum_mdl_type type_arg, - MDL_context *requestor_ctx) const + MDL_context *requestor_ctx, + bool ignore_lock_priority) const { bool can_grant= FALSE; bitmap_t waiting_incompat_map= incompatible_waiting_types_bitmap()[type_arg]; bitmap_t granted_incompat_map= incompatible_granted_types_bitmap()[type_arg]; + /* New lock request can be satisfied iff: - There are no incompatible types of satisfied requests in other contexts - There are no waiting requests which have higher priority - than this request. + than this request when priority was not ignored. */ - if (! (m_waiting.bitmap() & waiting_incompat_map)) + if (ignore_lock_priority || !(m_waiting.bitmap() & waiting_incompat_map)) { if (! (m_granted.bitmap() & granted_incompat_map)) can_grant= TRUE; @@ -1788,7 +1892,7 @@ MDL_context::try_acquire_lock_impl(MDL_request *mdl_request, ticket->m_lock= lock; - if (lock->can_grant_lock(mdl_request->type, this)) + if (lock->can_grant_lock(mdl_request->type, this, false)) { lock->m_granted.add_ticket(ticket); diff --git a/sql/mdl.h b/sql/mdl.h index 5c1af23f5e2..d30d30ac2fa 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -859,4 +859,10 @@ extern mysql_mutex_t LOCK_open; extern ulong mdl_locks_cache_size; static const ulong MDL_LOCKS_CACHE_SIZE_DEFAULT = 1024; +/* + Metadata locking subsystem tries not to grant more than + max_write_lock_count high-prio, strong locks successively, + to avoid starving out weak, low-prio locks. +*/ +extern "C" ulong max_write_lock_count; #endif -- cgit v1.2.1 From d86d06345b7cb46bce30b34e74a1d39a8df4677b Mon Sep 17 00:00:00 2001 From: Harin Vadodaria Date: Tue, 7 Aug 2012 16:23:53 +0530 Subject: Bug#14068244: INCOMPATIBILITY BETWEEN LIBMYSQLCLIENT/LIBMYSQLCLIENT_R AND LIBCRYPTO Problem: libmysqlclient_r exports symbols from yaSSL library which conflict with openSSL symbols. This issue is related to symbols used by CURL library and are defined in taocrypt. Taocrypt has dummy implementation of these functions. Due to this when a program which uses libcurl library functions is compiled using libmysqlclient_r and libcurl, it hits segmentation fault in execution phase. Solution: MySQL should not be exporting such symbols. However, these functions are not used by MySQL code at all. So avoid compiling them in the first place. --- extra/yassl/taocrypt/src/Makefile.am | 2 +- extra/yassl/taocrypt/src/crypto.cpp | 37 ------------------------------------ 2 files changed, 1 insertion(+), 38 deletions(-) delete mode 100644 extra/yassl/taocrypt/src/crypto.cpp diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am index 9fa0861babf..bdfa156d5e9 100644 --- a/extra/yassl/taocrypt/src/Makefile.am +++ b/extra/yassl/taocrypt/src/Makefile.am @@ -21,7 +21,7 @@ libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp \ asn.cpp bftables.cpp blowfish.cpp coding.cpp des.cpp dh.cpp \ dsa.cpp file.cpp hash.cpp integer.cpp md2.cpp md4.cpp md5.cpp misc.cpp \ random.cpp ripemd.cpp rsa.cpp sha.cpp template_instnt.cpp \ - tftables.cpp twofish.cpp crypto.cpp rabbit.cpp hc128.cpp + tftables.cpp twofish.cpp rabbit.cpp hc128.cpp libtaocrypt_la_CXXFLAGS = @yassl_taocrypt_extra_cxxflags@ -DYASSL_PURE_C \ @yassl_thread_cxxflags@ diff --git a/extra/yassl/taocrypt/src/crypto.cpp b/extra/yassl/taocrypt/src/crypto.cpp deleted file mode 100644 index 90d406bf0c2..00000000000 --- a/extra/yassl/taocrypt/src/crypto.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - Copyright (C) 2000-2007 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - MA 02110-1301 USA. -*/ - -/* put features that other apps expect from OpenSSL type crypto */ - - - -extern "C" { - - // for libcurl configure test, these are the signatures they use - // locking handled internally by library - char CRYPTO_lock() { return 0;} - char CRYPTO_add_lock() { return 0;} - - - // for openvpn, test are the signatures they use - char EVP_CIPHER_CTX_init() { return 0; } - char CRYPTO_mem_ctrl() { return 0; } -} // extern "C" - - - -- cgit v1.2.1 From 5ad8292c63a89db63a54f9cfed6ceb3a35656f7b Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 7 Aug 2012 18:58:19 +0530 Subject: Bug#13928675 MYSQL CLIENT COPYRIGHT NOTICE MUST SHOW 2012 INSTEAD OF 2011 * Added a new macro to hold the current year : COPYRIGHT_NOTICE_CURRENT_YEAR * Modified ORACLE_WELCOME_COPYRIGHT_NOTICE macro to take the initial year as parameter and pick current year from the above mentioned macro. --- client/mysql.cc | 6 +++--- client/mysql_upgrade.c | 4 ++-- client/mysqladmin.cc | 6 +++--- client/mysqlbinlog.cc | 2 +- client/mysqlcheck.c | 4 ++-- client/mysqldump.c | 2 +- client/mysqlimport.c | 4 ++-- client/mysqlshow.c | 4 ++-- client/mysqlslap.c | 6 +++--- client/mysqltest.cc | 2 +- extra/perror.c | 5 +++-- include/welcome_copyright_notice.h | 21 +++++++++++++-------- sql/gen_lex_hash.cc | 6 +++--- sql/mysqld.cc | 2 +- 14 files changed, 40 insertions(+), 34 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 595d5e1d969..3cb28e81164 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1170,7 +1170,7 @@ int main(int argc,char *argv[]) mysql_thread_id(&mysql), server_version_string(&mysql)); put_info((char*) glob_buffer.ptr(),INFO_INFO); - put_info(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011"), INFO_INFO); + put_info(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"), INFO_INFO); #ifdef HAVE_READLINE initialize_readline((char*) my_progname); @@ -1589,7 +1589,7 @@ static void usage(int version) if (version) return; - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); printf("Usage: %s [OPTIONS] [database]\n", my_progname); my_print_help(my_long_options); print_defaults("my", load_default_groups); diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 88e893701fb..2512f5269ab 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -230,7 +230,7 @@ get_one_option(int optid, const struct my_option *opt, switch (optid) { case '?': - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); printf("%s Ver %s Distrib %s, for %s (%s)\n", my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); puts("MySQL utility for upgrading databases to new MySQL versions.\n"); diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 1613e1a42c3..d5d6ad9ff6a 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -693,7 +693,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) case ADMIN_VER: new_line=1; print_version(); - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); printf("Server version\t\t%s\n", mysql_get_server_info(mysql)); printf("Protocol version\t%d\n", mysql_get_proto_info(mysql)); printf("Connection\t\t%s\n",mysql_get_host_info(mysql)); @@ -1072,7 +1072,7 @@ static void print_version(void) static void usage(void) { print_version(); - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); puts("Administration program for the mysqld daemon."); printf("Usage: %s [OPTIONS] command command....\n", my_progname); my_print_help(my_long_options); diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index b5acfc5c169..ef67e0ffba9 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -1274,7 +1274,7 @@ static void print_version() static void usage() { print_version(); - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); printf("\ Dumps a MySQL binary log in a format usable for viewing or for piping to\n\ the mysql command line client.\n\n"); diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index be1fbf1a020..ec9ee50868b 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -222,7 +222,7 @@ static void print_version(void) static void usage(void) { print_version(); - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); puts("This program can be used to CHECK (-c, -m, -C), REPAIR (-r), ANALYZE (-a),"); puts("or OPTIMIZE (-o) tables. Some of the options (like -e or -q) can be"); puts("used at the same time. Not all options are supported by all storage engines."); diff --git a/client/mysqldump.c b/client/mysqldump.c index dc124f1b335..3fda1fafc24 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -585,7 +585,7 @@ static void short_usage_sub(void) static void usage(void) { print_version(); - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); puts("Dumping structure and contents of MySQL databases and tables."); short_usage_sub(); print_defaults("my",load_default_groups); diff --git a/client/mysqlimport.c b/client/mysqlimport.c index f1a05c76513..a739c5aded0 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -196,7 +196,7 @@ static void print_version(void) static void usage(void) { print_version(); - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); printf("\ Loads tables from text files in various formats. The base name of the\n\ text file must be the name of the table that should be used.\n\ diff --git a/client/mysqlshow.c b/client/mysqlshow.c index dec31868c0c..1656ec71af8 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -256,7 +256,7 @@ static void print_version(void) static void usage(void) { print_version(); - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011)")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); puts("Shows the structure of a MySQL database (databases, tables, and columns).\n"); printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname); puts("\n\ diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 35c36806769..4c4dbafc24d 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -95,6 +95,7 @@ TODO: #include #endif #include +#include /* ORACLE_WELCOME_COPYRIGHT_NOTICE */ #ifdef __WIN__ #define srandom srand @@ -691,8 +692,7 @@ static void print_version(void) static void usage(void) { print_version(); - puts("Copyright (C) 2005 MySQL AB"); - puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license.\n"); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2005")); puts("Run a query multiple times against the server.\n"); printf("Usage: %s [OPTIONS]\n",my_progname); print_defaults("my",load_default_groups); diff --git a/client/mysqltest.cc b/client/mysqltest.cc index e595493ccf0..89fcb56825e 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6135,7 +6135,7 @@ void print_version(void) void usage() { print_version(); - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); printf("Runs a test against the mysql server and compares output with a results file.\n\n"); printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname); my_print_help(my_long_options); diff --git a/extra/perror.c b/extra/perror.c index b76f3fd8e55..d8e3c3a59a8 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include "../storage/ndb/src/kernel/error/ndbd_exit_codes.c" #include "../storage/ndb/include/mgmapi/mgmapi_error.h" #endif +#include /* ORACLE_WELCOME_COPYRIGHT_NOTICE */ static my_bool verbose, print_all_codes; @@ -115,7 +116,7 @@ static void print_version(void) static void usage(void) { print_version(); - puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n"); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); printf("Print a description for a system error code or a MySQL error code.\n"); printf("If you want to get the error for a negative error code, you should use\n-- before the first error code to tell perror that there was no more options.\n\n"); printf("Usage: %s [OPTIONS] [ERRORCODE [ERRORCODE...]]\n",my_progname); diff --git a/include/welcome_copyright_notice.h b/include/welcome_copyright_notice.h index 5a96da4ceb4..ef4b08d4c0d 100644 --- a/include/welcome_copyright_notice.h +++ b/include/welcome_copyright_notice.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,16 +16,21 @@ #ifndef _welcome_copyright_notice_h_ #define _welcome_copyright_notice_h_ +#define COPYRIGHT_NOTICE_CURRENT_YEAR "2012" + /* This define specifies copyright notice which is displayed by every MySQL program on start, or on help screen. */ - -#define ORACLE_WELCOME_COPYRIGHT_NOTICE(years) \ - "Copyright (c) " years ", Oracle and/or its affiliates. All rights reserved.\n" \ - "\n" \ - "Oracle is a registered trademark of Oracle Corporation and/or its\n" \ - "affiliates. Other names may be trademarks of their respective\n" \ - "owners.\n" +#define ORACLE_WELCOME_COPYRIGHT_NOTICE(first_year) \ + (strcmp(first_year, COPYRIGHT_NOTICE_CURRENT_YEAR) ? \ + "Copyright (c) " first_year ", " COPYRIGHT_NOTICE_CURRENT_YEAR ", " \ + "Oracle and/or its affiliates. All rights reserved.\n\nOracle is a " \ + "registered trademark of Oracle Corporation and/or its\naffiliates. " \ + "Other names may be trademarks of their respective\nowners.\n" : \ + "Copyright (c) " first_year ", Oracle and/or its affiliates. " \ + "All rights reserved.\n\nOracle is a registered trademark of " \ + "Oracle Corporation and/or its\naffiliates. Other names may be " \ + "trademarks of their respective\nowners.\n") #endif /* _welcome_copyright_notice_h_ */ diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 9814814e8db..f126afb9015 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -350,7 +350,7 @@ static void usage(int version) my_progname, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); if (version) return; - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); puts("This program generates a perfect hashing function for the sql_lex.cc"); printf("Usage: %s [OPTIONS]\n\n", my_progname); my_print_help(my_long_options); @@ -453,7 +453,7 @@ int main(int argc,char **argv) printf("/*\n\n Do " "not " "edit " "this " "file " "directly!\n\n*/\n"); puts("/*"); - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); puts("*/"); /* Broken up to indicate that it's not advice to you, gentle reader. */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d6397280e0d..bc8d4162272 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7652,7 +7652,7 @@ static void usage(void) if (!default_collation_name) default_collation_name= (char*) default_charset_info->name; print_version(); - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); puts("Starts the MySQL database server.\n"); printf("Usage: %s [OPTIONS]\n", my_progname); if (!opt_verbose) -- cgit v1.2.1 From ff04c5bd6e753a7afd8f209918e900267ba2544f Mon Sep 17 00:00:00 2001 From: Rohit Kalhans Date: Wed, 8 Aug 2012 22:15:46 +0530 Subject: BUG#11757312: MYSQLBINLOG DOES NOT ACCEPT INPUT FROM STDIN WHEN STDIN IS A PIPE Problem: Mysqlbinlog does not accept the input from STDIN when STDIN is a pipe. This prevents the users from passing the input file through a shell pipe. Background: The my_seek() function does not check if the file descriptor passed to it is regular (seekable) file. The check_header() function in mysqlbinlog calls the my_b_seek() unconditionally and it fails when the underlying file is a PIPE. Resolution: We resolve this problem by checking if the underlying file is a regular file by using my_fstat() before calling my_b_seek(). If the underlying file is not seekable we skip the call to my_b_seek() in check_header(). client/mysqlbinlog.cc: Added a check to avoid the my_b_seek() call if the underlying file is a PIPE. --- client/mysqlbinlog.cc | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index ef67e0ffba9..c32f92ae149 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -36,6 +36,7 @@ #include "mysql_priv.h" #include "log_event.h" #include "sql_common.h" +#include "my_dir.h" #include // ORACLE_WELCOME_COPYRIGHT_NOTICE #define BIN_LOG_HEADER_SIZE 4 @@ -1767,6 +1768,7 @@ static Exit_status check_header(IO_CACHE* file, uchar header[BIN_LOG_HEADER_SIZE]; uchar buf[PROBE_HEADER_LEN]; my_off_t tmp_pos, pos; + MY_STAT my_file_stat; delete glob_description_event; if (!(glob_description_event= new Format_description_log_event(3))) @@ -1776,7 +1778,16 @@ static Exit_status check_header(IO_CACHE* file, } pos= my_b_tell(file); - my_b_seek(file, (my_off_t)0); + + /* fstat the file to check if the file is a regular file. */ + if (my_fstat(file->file, &my_file_stat, MYF(0)) == -1) + { + error("Unable to stat the file."); + return ERROR_STOP; + } + if ((my_file_stat.st_mode & S_IFMT) == S_IFREG) + my_b_seek(file, (my_off_t)0); + if (my_b_read(file, header, sizeof(header))) { error("Failed reading header; probably an empty file."); -- cgit v1.2.1 From bb8494796966f40d6a2346e32f5a4646af92f2ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 9 Aug 2012 09:55:29 +0300 Subject: Bug#14399148 INNODB TABLES UNDER LOAD PRODUCE DUPLICATE COPIES OF ROWS IN QUERIES This bug was caused by an incorrect fix of Bug#13807811 BTR_PCUR_RESTORE_POSITION() CAN SKIP A RECORD There was nothing wrong with btr_pcur_restore_position(), but with the use of it in the table scan during index creation. rb:1206 approved by Jimmy Yang --- storage/innobase/btr/btr0pcur.c | 69 ++++++++++++++++------------------- storage/innodb_plugin/ChangeLog | 6 +++ storage/innodb_plugin/btr/btr0pcur.c | 67 ++++++++++++++++------------------ storage/innodb_plugin/row/row0merge.c | 14 +++++++ 4 files changed, 83 insertions(+), 73 deletions(-) diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c index 50aef035f2e..fe7878b6b0e 100644 --- a/storage/innobase/btr/btr0pcur.c +++ b/storage/innobase/btr/btr0pcur.c @@ -312,45 +312,40 @@ btr_pcur_restore_position( /* Restore the old search mode */ cursor->search_mode = old_mode; - if (btr_pcur_is_on_user_rec(cursor, mtr)) { - switch (cursor->rel_pos) { - case BTR_PCUR_ON: - if (!cmp_dtuple_rec( - tuple, btr_pcur_get_rec(cursor), - rec_get_offsets(btr_pcur_get_rec(cursor), - index, NULL, - ULINT_UNDEFINED, &heap))) { - - /* We have to store the NEW value for - the modify clock, since the cursor can - now be on a different page! But we can - retain the value of old_rec */ - - cursor->block_when_stored = - buf_block_align( - btr_pcur_get_page(cursor)); - cursor->modify_clock = - buf_block_get_modify_clock( - cursor->block_when_stored); - cursor->old_stored = BTR_PCUR_OLD_STORED; - - mem_heap_free(heap); - - return(TRUE); - } - - break; - case BTR_PCUR_BEFORE: - page_cur_move_to_next(btr_pcur_get_page_cur(cursor)); - break; - case BTR_PCUR_AFTER: - page_cur_move_to_prev(btr_pcur_get_page_cur(cursor)); - break; + switch (cursor->rel_pos) { + case BTR_PCUR_ON: + if (btr_pcur_is_on_user_rec(cursor, mtr) + && !cmp_dtuple_rec( + tuple, btr_pcur_get_rec(cursor), + rec_get_offsets(btr_pcur_get_rec(cursor), + index, NULL, + ULINT_UNDEFINED, &heap))) { + + /* We have to store the NEW value for + the modify clock, since the cursor can + now be on a different page! But we can + retain the value of old_rec */ + + cursor->block_when_stored = + buf_block_align( + btr_pcur_get_page(cursor)); + cursor->modify_clock = + buf_block_get_modify_clock( + cursor->block_when_stored); + cursor->old_stored = BTR_PCUR_OLD_STORED; + + mem_heap_free(heap); + + return(TRUE); + } #ifdef UNIV_DEBUG - default: - ut_error; + /* fall through */ + case BTR_PCUR_BEFORE: + case BTR_PCUR_AFTER: + break; + default: + ut_error; #endif /* UNIV_DEBUG */ - } } mem_heap_free(heap); diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 1588132fc8b..4eceaeaed0a 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2012-08-07 The InnoDB Team + + * btr/btr0pcur.c, row/row0merge.c: + Fix Bug#14399148 INNODB TABLES UNDER LOAD PRODUCE DUPLICATE COPIES + OF ROWS IN QUERIES + 2012-03-15 The InnoDB Team * fil/fil0fil.c, ibuf/ibuf0ibuf.c, include/fil0fil.h, diff --git a/storage/innodb_plugin/btr/btr0pcur.c b/storage/innodb_plugin/btr/btr0pcur.c index 33700501bc5..92500d4fb10 100644 --- a/storage/innodb_plugin/btr/btr0pcur.c +++ b/storage/innodb_plugin/btr/btr0pcur.c @@ -336,44 +336,39 @@ btr_pcur_restore_position_func( /* Restore the old search mode */ cursor->search_mode = old_mode; - if (btr_pcur_is_on_user_rec(cursor)) { - switch (cursor->rel_pos) { - case BTR_PCUR_ON: - if (!cmp_dtuple_rec( - tuple, btr_pcur_get_rec(cursor), - rec_get_offsets(btr_pcur_get_rec(cursor), - index, NULL, - ULINT_UNDEFINED, &heap))) { - - /* We have to store the NEW value for - the modify clock, since the cursor can - now be on a different page! But we can - retain the value of old_rec */ - - cursor->block_when_stored = - btr_pcur_get_block(cursor); - cursor->modify_clock = - buf_block_get_modify_clock( - cursor->block_when_stored); - cursor->old_stored = BTR_PCUR_OLD_STORED; - - mem_heap_free(heap); - - return(TRUE); - } - - break; - case BTR_PCUR_BEFORE: - page_cur_move_to_next(btr_pcur_get_page_cur(cursor)); - break; - case BTR_PCUR_AFTER: - page_cur_move_to_prev(btr_pcur_get_page_cur(cursor)); - break; + switch (cursor->rel_pos) { + case BTR_PCUR_ON: + if (btr_pcur_is_on_user_rec(cursor) + && !cmp_dtuple_rec( + tuple, btr_pcur_get_rec(cursor), + rec_get_offsets(btr_pcur_get_rec(cursor), + index, NULL, + ULINT_UNDEFINED, &heap))) { + + /* We have to store the NEW value for + the modify clock, since the cursor can + now be on a different page! But we can + retain the value of old_rec */ + + cursor->block_when_stored = + btr_pcur_get_block(cursor); + cursor->modify_clock = + buf_block_get_modify_clock( + cursor->block_when_stored); + cursor->old_stored = BTR_PCUR_OLD_STORED; + + mem_heap_free(heap); + + return(TRUE); + } #ifdef UNIV_DEBUG - default: - ut_error; + /* fall through */ + case BTR_PCUR_BEFORE: + case BTR_PCUR_AFTER: + break; + default: + ut_error; #endif /* UNIV_DEBUG */ - } } mem_heap_free(heap); diff --git a/storage/innodb_plugin/row/row0merge.c b/storage/innodb_plugin/row/row0merge.c index 7f59d7cf9e9..5da2a4b8534 100644 --- a/storage/innodb_plugin/row/row0merge.c +++ b/storage/innodb_plugin/row/row0merge.c @@ -1214,11 +1214,25 @@ row_merge_read_clustered_index( goto err_exit; } + /* Store the cursor position on the last user + record on the page. */ + btr_pcur_move_to_prev_on_page(&pcur); + /* Leaf pages must never be empty, unless + this is the only page in the index tree. */ + ut_ad(btr_pcur_is_on_user_rec(&pcur) + || buf_block_get_page_no( + btr_pcur_get_block(&pcur)) + == clust_index->page); + btr_pcur_store_position(&pcur, &mtr); mtr_commit(&mtr); mtr_start(&mtr); + /* Restore position on the record, or its + predecessor if the record was purged + meanwhile. */ btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr); + /* Move to the successor of the original record. */ has_next = btr_pcur_move_to_next_user_rec(&pcur, &mtr); } -- cgit v1.2.1 -- cgit v1.2.1 From 6592afd5c28c0e7519d76c8c894658a4a17515c0 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Thu, 9 Aug 2012 12:51:37 +0200 Subject: Bug#14342883: SELECT QUERY RETURNS NOT ALL ROWS THAT ARE EXPECTED For non range/list partitioned tables (i.e. HASH/KEY): When prune_partitions finds a multi-range list (or in this test '<>') for a field of the partition index, even if it cannot make any use of the multi-range, it will continue with the next field of the partition index and use that for pruning (even if it the previous field could not be used). This results in partitions is pruned away, leaving partitions that only matches the last field in the partition index, and will exclude partitions which might match any previous fields. Fixed by skipping rest of partitioning key fields/parts if current key field/part could not be used. Also notice it is the order of the fields in the CREATE TABLE statement that triggers this bug, not the order of fields in primary/unique key or PARTITION BY KEY (). It must not be the last field in the partitioning expression that is not equal (or have a non single point range). I.e. the partitioning index is created with the same field order as in the CREATE TABLE. And for the bug to appear the last field must be a single point and some previous field must be a multi-point range. --- sql/opt_range.cc | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 03f444c22b5..8d221af392b 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3071,27 +3071,28 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree) ppar->cur_subpart_fields+= ppar->is_subpart_keypart[key_tree_part]; *(ppar->arg_stack_end++)= key_tree; + if (ignore_part_fields) + { + /* + We come here when a condition on the first partitioning + fields led to evaluating the partitioning condition + (due to finding a condition of the type a < const or + b > const). Thus we must ignore the rest of the + partitioning fields but we still want to analyse the + subpartitioning fields. + */ + if (key_tree->next_key_part) + res= find_used_partitions(ppar, key_tree->next_key_part); + else + res= -1; + goto pop_and_go_right; + } + if (key_tree->type == SEL_ARG::KEY_RANGE) { if (ppar->part_info->get_part_iter_for_interval && key_tree->part <= ppar->last_part_partno) { - if (ignore_part_fields) - { - /* - We come here when a condition on the first partitioning - fields led to evaluating the partitioning condition - (due to finding a condition of the type a < const or - b > const). Thus we must ignore the rest of the - partitioning fields but we still want to analyse the - subpartitioning fields. - */ - if (key_tree->next_key_part) - res= find_used_partitions(ppar, key_tree->next_key_part); - else - res= -1; - goto pop_and_go_right; - } /* Collect left and right bound, their lengths and flags */ uchar *min_key= ppar->cur_min_key; uchar *max_key= ppar->cur_max_key; @@ -3332,6 +3333,13 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree) res= -1; goto pop_and_go_right; } + /* + No meaning in continuing with rest of partitioning key parts. + Will try to continue with subpartitioning key parts. + */ + ppar->ignore_part_fields= true; + did_set_ignore_part_fields= true; + goto process_next_key_part; } } -- cgit v1.2.1 From 2f30b34095e286877cda7156ae9622a4154147bd Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 9 Aug 2012 15:34:52 +0400 Subject: Bug #14409015 MEMORY LEAK WHEN REFERENCING OUTER FIELD IN HAVING When resolving outer fields, Item_field::fix_outer_fields() creates new Item_refs for each execution of a prepared statement, so these must be allocated in the runtime memroot. The memroot switching before resolving JOIN::having causes these to be allocated in the statement root, leaking memory for each PS execution. sql/item_subselect.cc: addon, fix for 11829691, item could be created in runtime memroot, so we need to use real_item instead. --- sql/item.cc | 7 ++++++- sql/item_subselect.cc | 2 +- sql/sql_select.cc | 4 ---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 356fe4827c8..63215179ac6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6010,7 +6010,12 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) if (from_field != not_found_field) { Item_field* fld; - if (!(fld= new Item_field(thd, last_checked_context, from_field))) + Query_arena backup, *arena; + arena= thd->activate_stmt_arena_if_needed(&backup); + fld= new Item_field(thd, last_checked_context, from_field); + if (arena) + thd->restore_active_arena(arena, &backup); + if (!fld) goto error; thd->change_item_tree(reference, fld); mark_as_dependent(thd, last_checked_context->select_lex, diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 46d49797b9c..2c91d0573c1 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1135,7 +1135,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, } else { - Item *item= (Item*) select_lex->item_list.head(); + Item *item= (Item*) select_lex->item_list.head()->real_item(); if (select_lex->table_list.elements) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c097c4d16ef..042e7563d42 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -528,8 +528,6 @@ JOIN::prepare(Item ***rref_pointer_array, if (having) { - Query_arena backup, *arena; - arena= thd->activate_stmt_arena_if_needed(&backup); nesting_map save_allow_sum_func= thd->lex->allow_sum_func; thd->where="having clause"; thd->lex->allow_sum_func|= 1 << select_lex_arg->nest_level; @@ -539,8 +537,6 @@ JOIN::prepare(Item ***rref_pointer_array, having->check_cols(1))); select_lex->having_fix_field= 0; select_lex->having= having; - if (arena) - thd->restore_active_arena(arena, &backup); if (having_fix_rc || thd->is_error()) DBUG_RETURN(-1); /* purecov: inspected */ -- cgit v1.2.1 From 18087b049eeadfc07f49b65fc227a6ebd5d12e10 Mon Sep 17 00:00:00 2001 From: Venkata Sidagam Date: Sat, 11 Aug 2012 15:43:04 +0530 Subject: Bug #13115401: -SSL-KEY VALUE IS NOT VALIDATED AND IT ALLOWS INSECURE CONNECTIONS IF SPE Problem description: -ssl-key value is not validated, you can assign any bogus text to --ssl-key and it is not verified that it exists, and more importantly, it allows the client to connect to mysqld. Fix: Added proper validations checks for --ssl-key. Note: 1) Documentation changes require for 5.1, 5.5, 5.6 and trunk in the sections listed below and the details are : http://dev.mysql.com/doc/refman/5.6/en/ssl-options.html#option_general_ssl and REQUIRE SSL section of http://dev.mysql.com/doc/refman/5.6/en/grant.html 2) Client having with option '--ssl', should able to get ssl connection. This will be implemented as part of separate fix in 5.6 and trunk. --- extra/yassl/src/ssl.cpp | 2 +- mysql-test/r/openssl_1.result | 6 +-- mysql-test/t/openssl_1.test | 6 +++ vio/viosslfactories.c | 92 ++++++++++++++++++++++++++----------------- 4 files changed, 65 insertions(+), 41 deletions(-) diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 00a3b885f88..3b1fc43bc94 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -747,7 +747,7 @@ void SSL_CTX_set_verify(SSL_CTX* ctx, int mode, VerifyCallback vc) int SSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file, const char* path) { - int ret = SSL_SUCCESS; + int ret = SSL_FAILURE; const int HALF_PATH = 128; if (file) ret = read_file(ctx, file, SSL_FILETYPE_PEM, CA); diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result index 6389438c993..b95c4bb0e76 100644 --- a/mysql-test/r/openssl_1.result +++ b/mysql-test/r/openssl_1.result @@ -44,9 +44,9 @@ ERROR 42000: DELETE command denied to user 'ssl_user4'@'localhost' for table 't1 drop user ssl_user1@localhost, ssl_user2@localhost, ssl_user3@localhost, ssl_user4@localhost, ssl_user5@localhost; drop table t1; -mysqltest: Could not open connection 'default': 2026 SSL connection error -mysqltest: Could not open connection 'default': 2026 SSL connection error -mysqltest: Could not open connection 'default': 2026 SSL connection error +mysqltest: Could not open connection 'default': 2026 SSL connection error: xxxx +mysqltest: Could not open connection 'default': 2026 SSL connection error: xxxx +mysqltest: Could not open connection 'default': 2026 SSL connection error: xxxx SSL error: Unable to get private key from '' mysqltest: Could not open connection 'default': 2026 SSL connection error SSL error: Unable to get certificate from '' diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test index 8ca70258bc0..d5fbde1d9d4 100644 --- a/mysql-test/t/openssl_1.test +++ b/mysql-test/t/openssl_1.test @@ -73,22 +73,28 @@ drop table t1; # a different cacert # --exec echo "this query should not execute;" > $MYSQLTEST_VARDIR/tmp/test.sql +--replace_regex /2026 SSL connection error.*/2026 SSL connection error: xxxx/ --error 1 --exec $MYSQL_TEST --ssl-ca=$MYSQL_TEST_DIR/std_data/untrusted-cacert.pem --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 +--echo # # Test that we can't open connection to server if we are using # a blank ca # +--replace_regex /2026 SSL connection error.*/2026 SSL connection error: xxxx/ --error 1 --exec $MYSQL_TEST --ssl-ca= --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 +--echo # # Test that we can't open connection to server if we are using # a nonexistent ca file # +--replace_regex /2026 SSL connection error.*/2026 SSL connection error: xxxx/ --error 1 --exec $MYSQL_TEST --ssl-ca=nonexisting_file.pem --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 +--echo # # Test that we can't open connection to server if we are using diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 945e288a799..037c34802e9 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -101,47 +101,51 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file, DBUG_ENTER("vio_set_cert_stuff"); DBUG_PRINT("enter", ("ctx: 0x%lx cert_file: %s key_file: %s", (long) ctx, cert_file, key_file)); - if (cert_file) - { - if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) - { - *error= SSL_INITERR_CERT; - DBUG_PRINT("error",("%s from file '%s'", sslGetErrString(*error), cert_file)); - DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE);); - fprintf(stderr, "SSL error: %s from '%s'\n", sslGetErrString(*error), - cert_file); - fflush(stderr); - DBUG_RETURN(1); - } - if (!key_file) - key_file= cert_file; + if (!cert_file && key_file) + cert_file= key_file; + + if (!key_file && cert_file) + key_file= cert_file; - if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) - { - *error= SSL_INITERR_KEY; - DBUG_PRINT("error", ("%s from file '%s'", sslGetErrString(*error), key_file)); - DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE);); - fprintf(stderr, "SSL error: %s from '%s'\n", sslGetErrString(*error), - key_file); - fflush(stderr); - DBUG_RETURN(1); - } + if (cert_file && + SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) + { + *error= SSL_INITERR_CERT; + DBUG_PRINT("error",("%s from file '%s'", sslGetErrString(*error), cert_file)); + DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE);); + fprintf(stderr, "SSL error: %s from '%s'\n", sslGetErrString(*error), + cert_file); + fflush(stderr); + DBUG_RETURN(1); + } - /* - If we are using DSA, we can copy the parameters from the private key - Now we know that a key and cert have been set against the SSL context - */ - if (!SSL_CTX_check_private_key(ctx)) - { - *error= SSL_INITERR_NOMATCH; - DBUG_PRINT("error", ("%s",sslGetErrString(*error))); - DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE);); - fprintf(stderr, "SSL error: %s\n", sslGetErrString(*error)); - fflush(stderr); - DBUG_RETURN(1); - } + if (key_file && + SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) + { + *error= SSL_INITERR_KEY; + DBUG_PRINT("error", ("%s from file '%s'", sslGetErrString(*error), key_file)); + DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE);); + fprintf(stderr, "SSL error: %s from '%s'\n", sslGetErrString(*error), + key_file); + fflush(stderr); + DBUG_RETURN(1); + } + + /* + If we are using DSA, we can copy the parameters from the private key + Now we know that a key and cert have been set against the SSL context + */ + if (cert_file && !SSL_CTX_check_private_key(ctx)) + { + *error= SSL_INITERR_NOMATCH; + DBUG_PRINT("error", ("%s",sslGetErrString(*error))); + DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE);); + fprintf(stderr, "SSL error: %s\n", sslGetErrString(*error)); + fflush(stderr); + DBUG_RETURN(1); } + DBUG_RETURN(0); } @@ -253,6 +257,20 @@ new_VioSSLFd(const char *key_file, const char *cert_file, if (SSL_CTX_load_verify_locations(ssl_fd->ssl_context, ca_file, ca_path) == 0) { DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed")); + if (ca_file || ca_path) + { + /* fail only if ca file or ca path were supplied and looking into + them fails. */ + *error= SSL_INITERR_BAD_PATHS; + DBUG_PRINT("error", ("SSL_CTX_load_verify_locations failed : %s", + sslGetErrString(*error))); + report_errors(); + SSL_CTX_free(ssl_fd->ssl_context); + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); + } + + /* otherwise go use the defaults */ if (SSL_CTX_set_default_verify_paths(ssl_fd->ssl_context) == 0) { *error= SSL_INITERR_BAD_PATHS; -- cgit v1.2.1 From 03bfc41bb83210ae4bdf16e6650f6168a2111ac0 Mon Sep 17 00:00:00 2001 From: Sujatha Sivakumar Date: Tue, 14 Aug 2012 14:11:01 +0530 Subject: Bug#13596613:SHOW SLAVE STATUS GIVES WRONG OUTPUT WITH MASTER-MASTER AND USING SET USE Problem: ======= In a master-master set-up, a master can show a wrong 'SHOW SLAVE STATUS' output. Requirements: - master-master - log_slave_updates This is caused when using SET user-variables and then using it to perform writes. From then on the master that performed the insert will have a SHOW SLAVE STATUS that is wrong and it will never get updated until a write happens on the other master. On"Master A" the "exec_master_log_pos" is not getting updated. Analysis: ======== Slave receives a "User_var" event from the master and after applying the event, when "log_slave_updates" option is enabled the slave tries to write this applied event into its own binary log. At the time of writing this event the slave should use the "originating server-id". But in the above case the sever always logs the "user var events" by using its global server-id. Due to this in a "master-master" replication when the event comes back to the originating server the "User_var_event" doesn't get skipped. "User_var_events" are context based events and they always follow with a query event which marks their end of group. Due to the above mentioned problem with "User_var_event" logging the "User_var_event" never gets skipped where as its corresponding "query_event" gets skipped. Hence the "User_var" event always waits for the next "query event" and the "Exec_master_log_position" does not get updated properly. Fix: === `MYSQL_BIN_LOG::write' function is used to write events into binary log. Within this function a new object for "User_var_log_event" is created and this new object is used to write the "User_var" event in the binlog. "User var" event is inherited from "Log_event". This "Log_event" has different overloaded constructors. When a "THD" object is present "Log_event(thd,...)" constructor should be used to initialise the objects and in the absence of a valid "THD" object "Log_event()" minimal constructor should be used. In the above mentioned problem always default minimal constructor was used which is incorrect. This minimal constructor is replaced with "Log_event(thd,...)". sql/log_event.h: Replaced the default constructor with another constructor which takes "THD" object as an argument. --- sql/log_event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/log_event.h b/sql/log_event.h index e755b6a5a41..5030e1c6f3d 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -2487,7 +2487,7 @@ public: User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg, char *val_arg, ulong val_len_arg, Item_result type_arg, uint charset_number_arg) - :Log_event(), name(name_arg), name_len(name_len_arg), val(val_arg), + :Log_event(thd_arg,0,0), name(name_arg), name_len(name_len_arg), val(val_arg), val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg), deferred(false) { is_null= !val; } -- cgit v1.2.1 From 94bd7bd6b7687cf654df90b22a85425cf72af55c Mon Sep 17 00:00:00 2001 From: Venkata Sidagam Date: Tue, 14 Aug 2012 15:13:30 +0530 Subject: Bug #12992993 MYSQLHOTCOPY FAILS IF VIEW EXISTS Problem description: mysqlhotcopy fails if a view presents in the database. Analysis: Before 5.5 'FLUSH TABLES ... WITH READ LOCK' will able to get lock for all tables (i.e. base tables and view tables). In 5.5 onwards 'FLUSH TABLES ... WITH READ LOCK' for 'view tables' will not work, because taking flush locks on view tables is not valid. Fix: Take flush lock for 'base tables' and read lock for 'view table' separately. Note: most of the patch has been backported from bug#13006947's patch --- scripts/mysqlhotcopy.sh | 88 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 19 deletions(-) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index aaa77ec181c..a7f465dc891 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -272,23 +272,28 @@ if ( defined $opt{regexp} ) { } } -# --- get list of tables to hotcopy --- +# --- get list of tables and views to hotcopy --- my $hc_locks = ""; my $hc_tables = ""; +my $hc_base_tables = ""; +my $hc_views = ""; +my $num_base_tables = 0; +my $num_views = 0; my $num_tables = 0; my $num_files = 0; foreach my $rdb ( @db_desc ) { my $db = $rdb->{src}; - my @dbh_tables = get_list_of_tables( $db ); + my @dbh_base_tables = get_list_of_tables( $db ); + my @dbh_views = get_list_of_views( $db ); ## filter out certain system non-lockable tables. ## keep in sync with mysqldump. if ($db =~ m/^mysql$/i) { - @dbh_tables = grep - { !/^(apply_status|schema|general_log|slow_log)$/ } @dbh_tables + @dbh_base_tables = grep + { !/^(apply_status|schema|general_log|slow_log)$/ } @dbh_base_tables } ## generate regex for tables/files @@ -303,11 +308,20 @@ foreach my $rdb ( @db_desc ) { ## filter (out) tables specified in t_regex print "Filtering tables with '$t_regex'\n" if $opt{debug}; - @dbh_tables = ( $negated - ? grep { $_ !~ $t_regex } @dbh_tables - : grep { $_ =~ $t_regex } @dbh_tables ); + @dbh_base_tables = ( $negated + ? grep { $_ !~ $t_regex } @dbh_base_tables + : grep { $_ =~ $t_regex } @dbh_base_tables ); + + ## filter (out) views specified in t_regex + print "Filtering tables with '$t_regex'\n" if $opt{debug}; + @dbh_views = ( $negated + ? grep { $_ !~ $t_regex } @dbh_views + : grep { $_ =~ $t_regex } @dbh_views ); } + ## Now concatenate the base table and view arrays. + my @dbh_tables = (@dbh_base_tables, @dbh_views); + ## get list of files to copy my $db_dir = "$datadir/$db"; opendir(DBDIR, $db_dir ) @@ -347,15 +361,25 @@ foreach my $rdb ( @db_desc ) { $rdb->{files} = [ @db_files ]; $rdb->{index} = [ @index_files ]; - my @hc_tables = map { quote_names("$db.$_") } @dbh_tables; + my @hc_base_tables = map { quote_names("$db.$_") } @dbh_base_tables; + my @hc_views = map { quote_names("$db.$_") } @dbh_views; + + my @hc_tables = (@hc_base_tables, @hc_views); $rdb->{tables} = [ @hc_tables ]; $hc_locks .= ", " if ( length $hc_locks && @hc_tables ); $hc_locks .= join ", ", map { "$_ READ" } @hc_tables; - $hc_tables .= ", " if ( length $hc_tables && @hc_tables ); - $hc_tables .= join ", ", @hc_tables; - $num_tables += scalar @hc_tables; + $hc_base_tables .= ", " if ( length $hc_base_tables && @hc_base_tables ); + $hc_base_tables .= join ", ", @hc_base_tables; + $hc_views .= ", " if ( length $hc_views && @hc_views ); + $hc_views .= join " READ, ", @hc_views; + + @hc_tables = (@hc_base_tables, @hc_views); + + $num_base_tables += scalar @hc_base_tables; + $num_views += scalar @hc_views; + $num_tables += $num_base_tables + $num_views; $num_files += scalar @{$rdb->{files}}; } @@ -467,7 +491,10 @@ if ( $opt{dryrun} ) { print "FLUSH TABLES /*!32323 $hc_tables */\n"; } else { - print "FLUSH TABLES $hc_tables WITH READ LOCK\n"; + # Lock base tables and views separately. + print "FLUSH TABLES $hc_base_tables WITH READ LOCK\n" + if ( $hc_base_tables ); + print "LOCK TABLES $hc_views READ\n" if ( $hc_views ); } print "FLUSH LOGS\n" if ( $opt{flushlog} ); @@ -484,16 +511,24 @@ else { # flush tables to make on-disk copy up to date $start = time; $dbh->do("FLUSH TABLES /*!32323 $hc_tables */"); + printf "Flushed tables ($hc_tables) in %d seconds.\n", time-$start unless $opt{quiet}; } else { - $dbh->do("FLUSH TABLES $hc_tables WITH READ LOCK"); - printf "Locked $num_tables tables in %d seconds.\n", time-$start unless $opt{quiet}; - $hc_started = time; # count from time lock is granted + # Lock base tables and views separately, as 'FLUSH TABLES + # ... WITH READ LOCK' (introduced in 5.5) would fail for views. + # Also, flush tables to make on-disk copy up to date + $dbh->do("FLUSH TABLES $hc_base_tables WITH READ LOCK") + if ( $hc_base_tables ); + printf "Flushed $num_base_tables tables with read lock ($hc_base_tables) in %d seconds.\n", + time-$start unless $opt{quiet}; - # flush tables to make on-disk copy up to date $start = time; + $dbh->do("LOCK TABLES $hc_views READ") if ( $hc_views ); + printf "Locked $num_views views ($hc_views) in %d seconds.\n", + time-$start unless $opt{quiet}; + + $hc_started = time; # count from time lock is granted } - printf "Flushed tables ($hc_tables) in %d seconds.\n", time-$start unless $opt{quiet}; $dbh->do( "FLUSH LOGS" ) if ( $opt{flushlog} ); $dbh->do( "RESET MASTER" ) if ( $opt{resetmaster} ); $dbh->do( "RESET SLAVE" ) if ( $opt{resetslave} ); @@ -802,14 +837,29 @@ sub get_list_of_tables { my $tables = eval { - $dbh->selectall_arrayref('SHOW TABLES FROM ' . - $dbh->quote_identifier($db)) + $dbh->selectall_arrayref('SHOW FULL TABLES FROM ' . + $dbh->quote_identifier($db) . + ' WHERE Table_type = \'BASE TABLE\'') } || []; warn "Unable to retrieve list of tables in $db: $@" if $@; return (map { $_->[0] } @$tables); } +sub get_list_of_views { + my ( $db ) = @_; + + my $views = + eval { + $dbh->selectall_arrayref('SHOW FULL TABLES FROM ' . + $dbh->quote_identifier($db) . + ' WHERE Table_type = \'VIEW\'') + } || []; + warn "Unable to retrieve list of views in $db: $@" if $@; + + return (map { $_->[0] } @$views); +} + sub quote_names { my ( $name ) = @_; # given a db.table name, add quotes -- cgit v1.2.1 From bcee9f1896ab6015e77ea88fde5317f50edaead7 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Wed, 15 Aug 2012 14:31:26 +0200 Subject: Bug#13025132 - PARTITIONS USE TOO MUCH MEMORY The buffer for the current read row from each partition (m_ordered_rec_buffer) used for sorted reads was allocated on open and freed when the ha_partition handler was closed or destroyed. For tables with many partitions and big records this could take up too much valuable memory. Solution is to only allocate the memory when it is needed and free it when nolonger needed. I.e. allocate it in index_init and free it in index_end (and to handle failures also free it on reset, close etc.) Also only allocating needed memory, according to partitioning pruning. Manually tested that it does not use as much memory and releases it after queries. --- sql/ha_partition.cc | 126 +++++++++++++++++++++++++++++++++++++--------------- sql/ha_partition.h | 13 +++++- 2 files changed, 100 insertions(+), 39 deletions(-) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 77eb8285245..a60a5b2d6dd 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -320,7 +320,7 @@ ha_partition::~ha_partition() for (i= 0; i < m_tot_parts; i++) delete m_file[i]; } - my_free((char*) m_ordered_rec_buffer, MYF(MY_ALLOW_ZERO_PTR)); + destroy_record_priority_queue(); clear_handler_file(); DBUG_VOID_RETURN; @@ -2594,7 +2594,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) { char *name_buffer_ptr; int error= HA_ERR_INITIALIZATION; - uint alloc_len; handler **file; char name_buff[FN_REFLEN]; bool is_not_tmp_table= (table_share->tmp_table == NO_TMP_TABLE); @@ -2612,32 +2611,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) m_start_key.length= 0; m_rec0= table->record[0]; m_rec_length= table_share->reclength; - alloc_len= m_tot_parts * (m_rec_length + PARTITION_BYTES_IN_POS); - alloc_len+= table_share->max_key_length; - if (!m_ordered_rec_buffer) - { - if (!(m_ordered_rec_buffer= (uchar*)my_malloc(alloc_len, MYF(MY_WME)))) - { - DBUG_RETURN(error); - } - { - /* - We set-up one record per partition and each record has 2 bytes in - front where the partition id is written. This is used by ordered - index_read. - We also set-up a reference to the first record for temporary use in - setting up the scan. - */ - char *ptr= (char*)m_ordered_rec_buffer; - uint i= 0; - do - { - int2store(ptr, i); - ptr+= m_rec_length + PARTITION_BYTES_IN_POS; - } while (++i < m_tot_parts); - m_start_key.key= (const uchar*)ptr; - } - } /* Initialize the bitmap we use to minimize ha_start_bulk_insert calls */ if (bitmap_init(&m_bulk_insert_started, NULL, m_tot_parts + 1, FALSE)) @@ -2657,7 +2630,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) if (m_is_clone_of) { - uint i; + uint i, alloc_len; DBUG_ASSERT(m_clone_mem_root); /* Allocate an array of handler pointers for the partitions handlers. */ alloc_len= (m_tot_parts + 1) * sizeof(handler*); @@ -2733,12 +2706,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) being opened once. */ clear_handler_file(); - /* - Initialize priority queue, initialized to reading forward. - */ - if ((error= init_queue(&m_queue, m_tot_parts, (uint) PARTITION_BYTES_IN_POS, - 0, key_rec_cmp, (void*)this))) - goto err_handler; /* Use table_share->ha_data to share auto_increment_value among all handlers @@ -2861,7 +2828,7 @@ int ha_partition::close(void) DBUG_ENTER("ha_partition::close"); DBUG_ASSERT(table->s == table_share); - delete_queue(&m_queue); + destroy_record_priority_queue(); bitmap_free(&m_bulk_insert_started); if (!m_is_clone_of) bitmap_free(&(m_part_info->used_partitions)); @@ -4073,6 +4040,87 @@ int ha_partition::rnd_pos_by_record(uchar *record) subset of the partitions are used, then only use those partitions. */ + +/** + Setup the ordered record buffer and the priority queue. +*/ + +bool ha_partition::init_record_priority_queue() +{ + DBUG_ENTER("ha_partition::init_record_priority_queue"); + DBUG_ASSERT(!m_ordered_rec_buffer); + /* + Initialize the ordered record buffer. + */ + if (!m_ordered_rec_buffer) + { + uint map_len, alloc_len; + uint used_parts= 0; + /* Allocate an array for mapping used partitions to their record buffer. */ + map_len= m_tot_parts * PARTITION_BYTES_IN_POS; + alloc_len= map_len; + /* Allocate record buffer for each used partition. */ + alloc_len+= bitmap_bits_set(&m_part_info->used_partitions) * + (m_rec_length + PARTITION_BYTES_IN_POS); + /* Allocate a key for temporary use when setting up the scan. */ + alloc_len+= table_share->max_key_length; + + if (!(m_ordered_rec_buffer= (uchar*)my_malloc(alloc_len, MYF(MY_WME)))) + DBUG_RETURN(true); + + /* + We set-up one record per partition and each record has 2 bytes in + front where the partition id is written. This is used by ordered + index_read. + We also set-up a reference to the first record for temporary use in + setting up the scan. + No need to initialize the full map, it should only be used partitions + that will be read, so it is better to not set them to find possible + bugs through valgrind. + */ + uint16 *map= (uint16*) m_ordered_rec_buffer; + char *ptr= (char*) m_ordered_rec_buffer + map_len; + uint16 i= 0; + do + { + if (bitmap_is_set(&m_part_info->used_partitions, i)) + { + map[i]= used_parts++; + int2store(ptr, i); + ptr+= m_rec_length + PARTITION_BYTES_IN_POS; + } + } while (++i < m_tot_parts); + m_start_key.key= (const uchar*)ptr; + /* Initialize priority queue, initialized to reading forward. */ + if (init_queue(&m_queue, used_parts, (uint) PARTITION_BYTES_IN_POS, + 0, key_rec_cmp, (void*)m_curr_key_info)) + { + my_free(m_ordered_rec_buffer, MYF(0)); + m_ordered_rec_buffer= NULL; + DBUG_RETURN(true); + } + } + DBUG_RETURN(false); +} + + +/** + Destroy the ordered record buffer and the priority queue. +*/ + +void ha_partition::destroy_record_priority_queue() +{ + DBUG_ENTER("ha_partition::destroy_record_priority_queue"); + if (m_ordered_rec_buffer) + { + delete_queue(&m_queue); + my_free(m_ordered_rec_buffer, MYF(0)); + m_ordered_rec_buffer= NULL; + } + DBUG_VOID_RETURN; +} + + /* Initialize handler before start of index scan @@ -4114,6 +4162,10 @@ int ha_partition::index_init(uint inx, bool sorted) } else m_curr_key_info[1]= NULL; + + if (init_record_priority_queue()) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + /* Some handlers only read fields as specified by the bitmap for the read set. For partitioned handlers we always require that the @@ -4188,11 +4240,11 @@ int ha_partition::index_end() do { int tmp; - /* TODO RONM: Change to index_end() when code is stable */ if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file))) if ((tmp= (*file)->ha_index_end())) error= tmp; } while (*(++file)); + destroy_record_priority_queue(); DBUG_RETURN(error); } diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 7e6b062846a..a7e072a3b77 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -517,6 +517,8 @@ public: virtual int read_range_next(); private: + bool init_record_priority_queue(); + void destroy_record_priority_queue(); int common_index_read(uchar * buf, bool have_start_key); int common_first_last(uchar * buf); int partition_scan_set_up(uchar * buf, bool idx_read_flag); @@ -524,8 +526,15 @@ private: int handle_unordered_scan_next_partition(uchar * buf); uchar *queue_buf(uint part_id) { - return (m_ordered_rec_buffer + - (part_id * (m_rec_length + PARTITION_BYTES_IN_POS))); + uint16 *part_id_map= (uint16*) m_ordered_rec_buffer; + /* Offset to the partition's record buffer in number of partitions. */ + uint offset= part_id_map[part_id]; + /* + Return the pointer to the partition's record buffer. + First skip the partition id map, and then add the offset. + */ + return (m_ordered_rec_buffer + m_tot_parts * PARTITION_BYTES_IN_POS + + (offset * (m_rec_length + PARTITION_BYTES_IN_POS))); } uchar *rec_buf(uint part_id) { -- cgit v1.2.1 From 95247de26028a23e34f12697f62076cf753c6084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 16 Aug 2012 17:31:23 +0300 Subject: Bug#13523839 ASSERTION FAILURES ON COMPRESSED INNODB TABLES btr_cur_optimistic_insert(): Remove a bogus assertion. The insert may fail after reorganizing the page. btr_cur_optimistic_update(): Do not attempt to reorganize compressed pages, because compression may fail after reorganization. page_copy_rec_list_start(): Use page_rec_get_nth() to restore to the ret_pos, which may also be the page infimum. rb:1221 --- storage/innodb_plugin/ChangeLog | 5 +++++ storage/innodb_plugin/btr/btr0cur.c | 15 ++++++++++++--- storage/innodb_plugin/page/page0page.c | 21 +++++++++++---------- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 4eceaeaed0a..2c7828b15a0 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,8 @@ +2012-08-16 The InnoDB Team + + * btr/btr0cur.c, page/page0page.c: + Fix Bug#13523839 ASSERTION FAILURES ON COMPRESSED INNODB TABLES + 2012-08-07 The InnoDB Team * btr/btr0pcur.c, row/row0merge.c: diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c index 223b976dea7..0416ce24b2b 100644 --- a/storage/innodb_plugin/btr/btr0cur.c +++ b/storage/innodb_plugin/btr/btr0cur.c @@ -1220,7 +1220,12 @@ fail_err: if (UNIV_UNLIKELY(reorg)) { ut_a(zip_size); - ut_a(*rec); + /* It's possible for rec to be NULL if the + page is compressed. This is because a + reorganized page may become incompressible. */ + if (!*rec) { + goto fail; + } } } @@ -1973,8 +1978,12 @@ any_extern: goto err_exit; } - max_size = old_rec_size - + page_get_max_insert_size_after_reorganize(page, 1); + /* We do not attempt to reorganize if the page is compressed. + This is because the page may fail to compress after reorganization. */ + max_size = page_zip + ? page_get_max_insert_size(page, 1) + : (old_rec_size + + page_get_max_insert_size_after_reorganize(page, 1)); if (!(((max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT) && (max_size >= new_rec_size)) diff --git a/storage/innodb_plugin/page/page0page.c b/storage/innodb_plugin/page/page0page.c index 7b72a22fd1c..108c3e0805c 100644 --- a/storage/innodb_plugin/page/page0page.c +++ b/storage/innodb_plugin/page/page0page.c @@ -780,12 +780,18 @@ page_copy_rec_list_start( if (UNIV_LIKELY_NULL(new_page_zip)) { mtr_set_log_mode(mtr, log_mode); + DBUG_EXECUTE_IF("page_copy_rec_list_start_compress_fail", + goto zip_reorganize;); + if (UNIV_UNLIKELY (!page_zip_compress(new_page_zip, new_page, index, mtr))) { + ulint ret_pos; +#ifndef DBUG_OFF +zip_reorganize: +#endif /* DBUG_OFF */ /* Before trying to reorganize the page, store the number of preceding records on the page. */ - ulint ret_pos - = page_rec_get_n_recs_before(ret); + ret_pos = page_rec_get_n_recs_before(ret); /* Before copying, "ret" was the predecessor of the predefined supremum record. If it was the predefined infimum record, then it would @@ -806,15 +812,10 @@ page_copy_rec_list_start( btr_blob_dbg_add(new_page, index, "copy_start_reorg_fail"); return(NULL); - } else { - /* The page was reorganized: - Seek to ret_pos. */ - ret = new_page + PAGE_NEW_INFIMUM; - - do { - ret = rec_get_next_ptr(ret, TRUE); - } while (--ret_pos); } + + /* The page was reorganized: Seek to ret_pos. */ + ret = page_rec_get_nth(new_page, ret_pos); } } -- cgit v1.2.1 From 6d7f6baa22c8e98fc0651c118e715cb27727a6e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 16 Aug 2012 17:37:52 +0300 Subject: Bug#12845774 OPTIMISTIC INSERT/UPDATE USES WRONG HEURISTICS FOR COMPRESSED PAGE SIZE This was submitted as MySQL Bug 61456 and a patch provided by Facebook. This patch follows the same idea, but instead of adding a parameter to btr_cur_pessimistic_insert(), we simply remove the btr_cur_optimistic_insert() call there and add it to the only caller that needs it. btr_cur_pessimistic_insert(): Do not try btr_cur_optimistic_insert(). btr_insert_on_non_leaf_level_func(): Invoke btr_cur_optimistic_insert() before invoking btr_cur_pessimistic_insert(). btr_cur_pessimistic_update(): Clarify in a comment why it is not necessary to invoke btr_cur_optimistic_insert(). btr_root_raise_and_insert(): Assert that the root page is not empty. This could happen if a pessimistic insert (involving a split or merge) is performed without first attempting an optimistic (intra-page) insert. rb:1219 approved by Sunny Bains --- storage/innodb_plugin/ChangeLog | 6 ++++++ storage/innodb_plugin/btr/btr0btr.c | 21 +++++++++++++++------ storage/innodb_plugin/btr/btr0cur.c | 19 +++++-------------- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 2c7828b15a0..cbdefc84e19 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2012-08-16 The InnoDB Team + + * btr/btr0btr.c, btr/btr0cur.c: + Fix Bug#12845774 OPTIMISTIC INSERT/UPDATE USES WRONG HEURISTICS FOR + COMPRESSED PAGE SIZE + 2012-08-16 The InnoDB Team * btr/btr0cur.c, page/page0page.c: diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c index 05723c26e2f..c042fb2ff87 100644 --- a/storage/innodb_plugin/btr/btr0btr.c +++ b/storage/innodb_plugin/btr/btr0btr.c @@ -1822,6 +1822,7 @@ btr_root_raise_and_insert( root = btr_cur_get_page(cursor); root_block = btr_cur_get_block(cursor); root_page_zip = buf_block_get_page_zip(root_block); + ut_ad(page_get_n_recs(root) > 0); #ifdef UNIV_ZIP_DEBUG ut_a(!root_page_zip || page_zip_validate(root_page_zip, root)); #endif /* UNIV_ZIP_DEBUG */ @@ -2302,12 +2303,20 @@ btr_insert_on_non_leaf_level_func( BTR_CONT_MODIFY_TREE, &cursor, 0, file, line, mtr); - err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG - | BTR_KEEP_SYS_FLAG - | BTR_NO_UNDO_LOG_FLAG, - &cursor, tuple, &rec, - &dummy_big_rec, 0, NULL, mtr); - ut_a(err == DB_SUCCESS); + ut_ad(cursor.flag == BTR_CUR_BINARY); + + err = btr_cur_optimistic_insert( + BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG + | BTR_NO_UNDO_LOG_FLAG, &cursor, tuple, &rec, + &dummy_big_rec, 0, NULL, mtr); + + if (err == DB_FAIL) { + err = btr_cur_pessimistic_insert( + BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG + | BTR_NO_UNDO_LOG_FLAG, + &cursor, tuple, &rec, &dummy_big_rec, 0, NULL, mtr); + ut_a(err == DB_SUCCESS); + } } /**************************************************************//** diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c index 0416ce24b2b..91cbba54308 100644 --- a/storage/innodb_plugin/btr/btr0cur.c +++ b/storage/innodb_plugin/btr/btr0cur.c @@ -1361,20 +1361,9 @@ btr_cur_pessimistic_insert( ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), MTR_MEMO_PAGE_X_FIX)); - /* Try first an optimistic insert; reset the cursor flag: we do not - assume anything of how it was positioned */ - cursor->flag = BTR_CUR_BINARY; - err = btr_cur_optimistic_insert(flags, cursor, entry, rec, - big_rec, n_ext, thr, mtr); - if (err != DB_FAIL) { - - return(err); - } - - /* Retry with a pessimistic insert. Check locks and write to undo log, - if specified */ + /* Check locks and write to undo log, if specified */ err = btr_cur_ins_lock_and_undo(flags, cursor, entry, thr, mtr, &dummy_inh); @@ -2365,8 +2354,10 @@ make_external: record on its page? */ was_first = page_cur_is_before_first(page_cursor); - /* The first parameter means that no lock checking and undo logging - is made in the insert */ + /* Lock checks and undo logging were already performed by + btr_cur_upd_lock_and_undo(). We do not try + btr_cur_optimistic_insert() because + btr_cur_insert_if_possible() already failed above. */ err = btr_cur_pessimistic_insert(BTR_NO_UNDO_LOG_FLAG | BTR_NO_LOCKING_FLAG -- cgit v1.2.1 From e288e649c5157765f192bde3790e5a863807a112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 16 Aug 2012 17:45:39 +0300 Subject: Bug#12595091 POSSIBLY INVALID ASSERTION IN BTR_CUR_PESSIMISTIC_UPDATE() Facebook got a case where the page compresses really well so that btr_cur_optimistic_update() returns DB_UNDERFLOW, but when a record gets updated, the compression rate radically changes so that btr_cur_insert_if_possible() can not insert in place despite reorganizing/recompressing the page, leading to the assertion failing. rb:1220 approved by Sunny Bains --- storage/innodb_plugin/ChangeLog | 6 ++++++ storage/innodb_plugin/btr/btr0cur.c | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index cbdefc84e19..576a67a0106 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2012-08-16 The InnoDB Team + + * btr/btr0cur.c: + Fix Bug#12595091 POSSIBLY INVALID ASSERTION IN + BTR_CUR_PESSIMISTIC_UPDATE() + 2012-08-16 The InnoDB Team * btr/btr0btr.c, btr/btr0cur.c: diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c index 91cbba54308..8fb4366d894 100644 --- a/storage/innodb_plugin/btr/btr0cur.c +++ b/storage/innodb_plugin/btr/btr0cur.c @@ -2326,7 +2326,12 @@ make_external: err = DB_SUCCESS; goto return_after_reservations; } else { - ut_a(optim_err != DB_UNDERFLOW); + /* If the page is compressed and it initially + compresses very well, and there is a subsequent insert + of a badly-compressing record, it is possible for + btr_cur_optimistic_update() to return DB_UNDERFLOW and + btr_cur_insert_if_possible() to return FALSE. */ + ut_a(page_zip || optim_err != DB_UNDERFLOW); /* Out of space: reset the free bits. */ if (!dict_index_is_clust(index) -- cgit v1.2.1 From 5aec4e2b3bbcaea33d719e2e4e94665c4856e413 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 17 Aug 2012 13:14:04 +0400 Subject: Backporting Bug 14100466 from 5.6. --- sql/spatial.cc | 11 ++++++----- sql/spatial.h | 8 ++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/sql/spatial.cc b/sql/spatial.cc index 0d2dd81c71e..07f28855987 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -525,12 +525,13 @@ uint Gis_line_string::init_from_wkb(const char *wkb, uint len, const char *wkb_end; Gis_point p; - if (len < 4) + if (len < 4 || + (n_points= wkb_get_uint(wkb, bo)) < 1 || + n_points > max_n_points) return 0; - n_points= wkb_get_uint(wkb, bo); proper_length= 4 + n_points * POINT_DATA_SIZE; - if (!n_points || len < proper_length || res->reserve(proper_length)) + if (len < proper_length || res->reserve(proper_length)) return 0; res->q_append(n_points); @@ -1072,9 +1073,9 @@ uint Gis_multi_point::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, Gis_point p; const char *wkb_end; - if (len < 4) + if (len < 4 || + (n_points= wkb_get_uint(wkb, bo)) > max_n_points) return 0; - n_points= wkb_get_uint(wkb, bo); proper_size= 4 + n_points * (WKB_HEADER_SIZE + POINT_DATA_SIZE); if (len < proper_size || res->reserve(proper_size)) diff --git a/sql/spatial.h b/sql/spatial.h index 4159d93c7a7..68a6c889615 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -379,6 +379,10 @@ public: class Gis_line_string: public Geometry { + // Maximum number of points in LineString that can fit into String + static const uint32 max_n_points= + (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) / + POINT_DATA_SIZE; public: Gis_line_string() {} /* Remove gcc warning */ virtual ~Gis_line_string() {} /* Remove gcc warning */ @@ -435,6 +439,10 @@ public: class Gis_multi_point: public Geometry { + // Maximum number of points in MultiPoint that can fit into String + static const uint32 max_n_points= + (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) / + (WKB_HEADER_SIZE + POINT_DATA_SIZE); public: Gis_multi_point() {} /* Remove gcc warning */ virtual ~Gis_multi_point() {} /* Remove gcc warning */ -- cgit v1.2.1 From 1ffecedfc3e6ecdfa068c01a588cbe1ceca14ec2 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Fri, 17 Aug 2012 14:25:32 +0200 Subject: Bug#13025132 - PARTITIONS USE TOO MUCH MEMORY Additional patch to remove the part_id -> ref_buffer offset. The partitioning id and the associate record buffer can be found without having to calculate it. By initializing it for each used partition, and then reuse the key-buffer from the queue, it is not needed to have such map. --- sql/ha_partition.cc | 31 +++++++++++++------------------ sql/ha_partition.h | 17 ----------------- 2 files changed, 13 insertions(+), 35 deletions(-) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index a60a5b2d6dd..e7629681e02 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4055,13 +4055,9 @@ bool ha_partition::init_record_priority_queue() if (!m_ordered_rec_buffer) { uint map_len, alloc_len; - uint used_parts= 0; - /* Allocate an array for mapping used partitions to their record buffer. */ - map_len= m_tot_parts * PARTITION_BYTES_IN_POS; - alloc_len= map_len; + uint used_parts= bitmap_bits_set(&m_part_info->used_partitions); /* Allocate record buffer for each used partition. */ - alloc_len+= bitmap_bits_set(&m_part_info->used_partitions) * - (m_rec_length + PARTITION_BYTES_IN_POS); + alloc_len= used_parts * (m_rec_length + PARTITION_BYTES_IN_POS); /* Allocate a key for temporary use when setting up the scan. */ alloc_len+= table_share->max_key_length; @@ -4074,18 +4070,13 @@ bool ha_partition::init_record_priority_queue() index_read. We also set-up a reference to the first record for temporary use in setting up the scan. - No need to initialize the full map, it should only be used partitions - that will be read, so it is better to not set them to find possible - bugs through valgrind. */ - uint16 *map= (uint16*) m_ordered_rec_buffer; - char *ptr= (char*) m_ordered_rec_buffer + map_len; + char *ptr= (char*) m_ordered_rec_buffer; uint16 i= 0; do { if (bitmap_is_set(&m_part_info->used_partitions, i)) { - map[i]= used_parts++; int2store(ptr, i); ptr+= m_rec_length + PARTITION_BYTES_IN_POS; } @@ -4984,6 +4975,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) uint i; uint j= 0; bool found= FALSE; + uchar *part_rec_buf_ptr= m_ordered_rec_buffer; DBUG_ENTER("ha_partition::handle_ordered_index_scan"); m_top_entry= NO_CURRENT_PART_ID; @@ -4994,7 +4986,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) { if (!(bitmap_is_set(&(m_part_info->used_partitions), i))) continue; - uchar *rec_buf_ptr= rec_buf(i); + uchar *rec_buf_ptr= part_rec_buf_ptr + PARTITION_BYTES_IN_POS; int error; handler *file= m_file[i]; @@ -5041,12 +5033,13 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) /* Initialize queue without order first, simply insert */ - queue_element(&m_queue, j++)= (uchar*)queue_buf(i); + queue_element(&m_queue, j++)= part_rec_buf_ptr; } else if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) { DBUG_RETURN(error); } + part_rec_buf_ptr+= m_rec_length + PARTITION_BYTES_IN_POS; } if (found) { @@ -5109,18 +5102,19 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same) { int error; uint part_id= m_top_entry; + uchar *rec_buf= queue_top(&m_queue) + PARTITION_BYTES_IN_POS; handler *file= m_file[part_id]; DBUG_ENTER("ha_partition::handle_ordered_next"); if (m_index_scan_type == partition_read_range) { error= file->read_range_next(); - memcpy(rec_buf(part_id), table->record[0], m_rec_length); + memcpy(rec_buf, table->record[0], m_rec_length); } else if (!is_next_same) - error= file->index_next(rec_buf(part_id)); + error= file->index_next(rec_buf); else - error= file->index_next_same(rec_buf(part_id), m_start_key.key, + error= file->index_next_same(rec_buf, m_start_key.key, m_start_key.length); if (error) { @@ -5163,10 +5157,11 @@ int ha_partition::handle_ordered_prev(uchar *buf) { int error; uint part_id= m_top_entry; + uchar *rec_buf= queue_top(&m_queue) + PARTITION_BYTES_IN_POS; handler *file= m_file[part_id]; DBUG_ENTER("ha_partition::handle_ordered_prev"); - if ((error= file->index_prev(rec_buf(part_id)))) + if ((error= file->index_prev(rec_buf))) { if (error == HA_ERR_END_OF_FILE) { diff --git a/sql/ha_partition.h b/sql/ha_partition.h index a7e072a3b77..16d8f27bd71 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -524,23 +524,6 @@ private: int partition_scan_set_up(uchar * buf, bool idx_read_flag); int handle_unordered_next(uchar * buf, bool next_same); int handle_unordered_scan_next_partition(uchar * buf); - uchar *queue_buf(uint part_id) - { - uint16 *part_id_map= (uint16*) m_ordered_rec_buffer; - /* Offset to the partition's record buffer in number of partitions. */ - uint offset= part_id_map[part_id]; - /* - Return the pointer to the partition's record buffer. - First skip the partition id map, and then add the offset. - */ - return (m_ordered_rec_buffer + m_tot_parts * PARTITION_BYTES_IN_POS + - (offset * (m_rec_length + PARTITION_BYTES_IN_POS))); - } - uchar *rec_buf(uint part_id) - { - return (queue_buf(part_id) + - PARTITION_BYTES_IN_POS); - } int handle_ordered_index_scan(uchar * buf, bool reverse_order); int handle_ordered_next(uchar * buf, bool next_same); int handle_ordered_prev(uchar * buf); -- cgit v1.2.1 From 5d83889791c138955ec0ab61967e8d0dcdede871 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Mon, 20 Aug 2012 12:39:36 +0200 Subject: Bug#13025132 - PARTITIONS USE TOO MUCH MEMORY pre-push fix, removed unused variable. --- sql/ha_partition.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index e7629681e02..4e6f5984934 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4054,7 +4054,7 @@ bool ha_partition::init_record_priority_queue() */ if (!m_ordered_rec_buffer) { - uint map_len, alloc_len; + uint alloc_len; uint used_parts= bitmap_bits_set(&m_part_info->used_partitions); /* Allocate record buffer for each used partition. */ alloc_len= used_parts * (m_rec_length + PARTITION_BYTES_IN_POS); -- cgit v1.2.1 From 3f249921f81bec183ef2da02b839fc2f10577218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 21 Aug 2012 10:47:17 +0300 Subject: Fix regression from Bug#12845774 OPTIMISTIC INSERT/UPDATE USES WRONG HEURISTICS FOR COMPRESSED PAGE SIZE The fix of Bug#12845774 was supposed to skip known-to-fail btr_cur_optimistic_insert() calls. There was only one such call, in btr_cur_pessimistic_update(). All other callers of btr_cur_pessimistic_insert() would release and reacquire the B-tree page latch before attempting the pessimistic insert. This would allow other threads to restructure the B-tree, allowing (and requiring) the insert to succeed as an optimistic (single-page) operation. Failure to attempt an optimistic insert before a pessimistic one would trigger an attempt to split an empty page. rb:1234 approved by Sunny Bains --- storage/innodb_plugin/ibuf/ibuf0ibuf.c | 18 +++++++++++++----- storage/innodb_plugin/row/row0ins.c | 9 ++++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/storage/innodb_plugin/ibuf/ibuf0ibuf.c b/storage/innodb_plugin/ibuf/ibuf0ibuf.c index f1da399167c..965d8df7d0c 100644 --- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c +++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c @@ -2752,11 +2752,19 @@ ibuf_insert_low( root = ibuf_tree_root_get(&mtr); - err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG - | BTR_NO_UNDO_LOG_FLAG, - cursor, - ibuf_entry, &ins_rec, - &dummy_big_rec, 0, thr, &mtr); + err = btr_cur_optimistic_insert( + BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG, + cursor, ibuf_entry, &ins_rec, + &dummy_big_rec, 0, thr, &mtr); + + if (err == DB_FAIL) { + err = btr_cur_pessimistic_insert( + BTR_NO_LOCKING_FLAG + | BTR_NO_UNDO_LOG_FLAG, + cursor, ibuf_entry, &ins_rec, + &dummy_big_rec, 0, thr, &mtr); + } + if (err == DB_SUCCESS) { /* Update the page max trx id field */ page_update_max_trx_id(btr_cur_get_block(cursor), NULL, diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c index 4994a91dd23..92ce04774ea 100644 --- a/storage/innodb_plugin/row/row0ins.c +++ b/storage/innodb_plugin/row/row0ins.c @@ -2179,9 +2179,16 @@ row_ins_index_entry_low( goto function_exit; } - err = btr_cur_pessimistic_insert( + + err = btr_cur_optimistic_insert( 0, &cursor, entry, &insert_rec, &big_rec, n_ext, thr, &mtr); + + if (err == DB_FAIL) { + err = btr_cur_pessimistic_insert( + 0, &cursor, entry, &insert_rec, + &big_rec, n_ext, thr, &mtr); + } } } -- cgit v1.2.1 From 61f064eb6d69e4c5116ee1f7d56c67c5fad9477c Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 17 Aug 2012 18:02:44 +0300 Subject: Bug #14399795 : ISSUES RELATED TO SETTING AUDIT_LOG_STRATEGY DURING SERVER STARTUP The options parser now correctly checks for ambiguous prefixes in enumerated variables and emits an error when the value supplied is ambiguous. No test added since mysql-test-run.pl can't handle server startup failures as an expected state. --- mysys/my_getopt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index ac4ae46eab5..2ab9d44893c 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -710,6 +710,11 @@ static int setval(const struct my_option *opts, void *value, char *argument, } *(ulong*)value= arg; } + else if (type < 0) + { + res= EXIT_AMBIGUOUS_OPTION; + goto ret; + } else *(ulong*)value= type - 1; } -- cgit v1.2.1 From a16e00a6c4bcb4308ce07e56438151a5ad135027 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Thu, 23 Aug 2012 16:29:41 +0200 Subject: Bug#14463247 ORDER BY SUBQUERY REFERENCING OUTER ALIAS FAILS Documentation for class Item_outer_ref was wrong: (*ref) may point to Item_field as well (see e.g. Item_outer_ref::fix_fields) So this casting in get_store_key() was wrong: (*(Item_ref**)((Item_ref*)keyuse->val)->ref)->ref_type() --- sql/item.h | 1 + sql/sql_select.cc | 38 ++++++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/sql/item.h b/sql/item.h index bd43689e91b..71eb725e76e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2676,6 +2676,7 @@ public: resolved is a grouping one. After it has been fixed the ref field will point to either an Item_ref or an Item_direct_ref object which will be used to access the field. + The ref field may also point to an Item_field instance. See also comments for the fix_inner_refs() and the Item_field::fix_outer_field() functions. */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7169a834ff7..808af9d69ab 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6019,19 +6019,33 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables, key_part->length, keyuse->val); } - else if (keyuse->val->type() == Item::FIELD_ITEM || - (keyuse->val->type() == Item::REF_ITEM && - ((Item_ref*)keyuse->val)->ref_type() == Item_ref::OUTER_REF && - (*(Item_ref**)((Item_ref*)keyuse->val)->ref)->ref_type() == - Item_ref::DIRECT_REF && - keyuse->val->real_item()->type() == Item::FIELD_ITEM)) + + Item_field *field_item= NULL; + if (keyuse->val->type() == Item::FIELD_ITEM) + field_item= static_cast(keyuse->val->real_item()); + else if (keyuse->val->type() == Item::REF_ITEM) + { + Item_ref *item_ref= static_cast(keyuse->val); + if (item_ref->ref_type() == Item_ref::OUTER_REF) + { + if ((*item_ref->ref)->type() == Item::FIELD_ITEM) + field_item= static_cast(item_ref->real_item()); + else if ((*(Item_ref**)(item_ref)->ref)->ref_type() + == Item_ref::DIRECT_REF + && + item_ref->real_item()->type() == Item::FIELD_ITEM) + field_item= static_cast(item_ref->real_item()); + } + } + if (field_item) return new store_key_field(thd, - key_part->field, - key_buff + maybe_null, - maybe_null ? key_buff : 0, - key_part->length, - ((Item_field*) keyuse->val->real_item())->field, - keyuse->val->full_name()); + key_part->field, + key_buff + maybe_null, + maybe_null ? key_buff : 0, + key_part->length, + field_item->field, + keyuse->val->full_name()); + return new store_key_item(thd, key_part->field, key_buff + maybe_null, -- cgit v1.2.1 From 17695cb4ffcddb9634a9e27c459eab943ceae36e Mon Sep 17 00:00:00 2001 From: Gopal Shankar Date: Fri, 24 Aug 2012 09:51:42 +0530 Subject: Bug#14364558 ASSERT `TABLE_LIST->PRELOCKING_PLACEHOLDER==FALSE' FAILED IN CHECK_LOCK_AND_ST Problem: -------- lock_tables() is supposed to invoke check_lock_and_start_stmt() for TABLE_LIST which are directly used by top level statement. TABLE_LIST->prelocking_placeholder is set only for TABLE_LIST which are used indirectly by stored programs invoked by top level statement. Hence check_lock_and_start_stmt() should have TABLE_LIST->prelocking_placeholder==false always, but it is observed that this assert fails. The failure is found during RQG test rqg_signal_resignal. Analysis: --------- open_tables() invokes open_and_process_routines() where it finds all the TABLE_LIST that belong to the routine and adds it to thd->lex->query_tables. During this process if the open_and_process_routines() fail for some reason, we are supposed to chop-off all the TABLE_LIST found during calls to open_and_process_routines(). But, in practice this is not happening. thd->lex->query_tables_own_last is supposed to point to a node in thd->lex->query_tables, which would be a first TABLE_LIST used indirectly by stored programs invoked by top level statement. This is found to be not-set correctly when we plan to chop-off TABLE_LIST's, when open_and_process_routines() failed. close_tables_for_reopen() does chop-off all the TABLE_LIST added after thd->lex->query_table_own_last. This is invoked upon error in open_and_process_routines(). This call would not work as expected as thd->lex->query_tables_own_last is not set, or is not set to correctly. Further, when open_tables() restarts the process of finding TABLE_LIST belonging to stored programs, and as the thd->lex->query_tables_own_last points to in-correct node, there is possibility of new iteration setting the thd->lex->query_tables_own_last past some old nodes that belong to stored programs, added earlier and not removed. Later when open_tables() completes, lock_tables() ends up invoking check_lock_and_start_stmt() for TABLE_LIST which belong to stored programs, which is not expected behavior and hence we hit the assert TABLE_LIST->prelocking_placeholder==false. Due to above behavior, if a user application tries to execute a SQL statement which invokes some stored function and if the lock grant on stored function fails due to a deadlock, then mysqld crashes. Fix: ---- open_tables() remembers save_query_tables_last which points to thd-lex->query_tables_last before calls to open_and_process_routines(). If there is no known thd->lex->query_tables_own_last set, we are now setting thd->lex->query_tables_own_last to save_query_tables_last. This will make sure that the call to close_tables_for_reopen() will chop-off the list correctly, in other words we now remove all the nodes added to thd->lex->query_tables, by previous calls to open_and_process_routines(). Further, it is found that the problem exists starting from 5.5, due to a code refactoring effort related to open_tables(). Hence, the fix will be pushed in 5.5, 5.6 and trunk. --- sql/sql_base.cc | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index efd9c4dfd4a..a7d04f12341 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4955,8 +4955,6 @@ restart: */ if (thd->locked_tables_mode <= LTM_LOCK_TABLES) { - bool need_prelocking= FALSE; - TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last; /* Process elements of the prelocking set which are present there since parsing stage or were added to it by invocations of @@ -4969,10 +4967,19 @@ restart: for (Sroutine_hash_entry *rt= *sroutine_to_open; rt; sroutine_to_open= &rt->next, rt= rt->next) { + bool need_prelocking= false; + TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last; + error= open_and_process_routine(thd, thd->lex, rt, prelocking_strategy, has_prelocking_list, &ot_ctx, &need_prelocking); + if (need_prelocking && ! thd->lex->requires_prelocking()) + thd->lex->mark_as_requiring_prelocking(save_query_tables_last); + + if (need_prelocking && ! *start) + *start= thd->lex->query_tables; + if (error) { if (ot_ctx.can_recover_from_failed_open()) @@ -4993,12 +5000,6 @@ restart: goto err; } } - - if (need_prelocking && ! thd->lex->requires_prelocking()) - thd->lex->mark_as_requiring_prelocking(save_query_tables_last); - - if (need_prelocking && ! *start) - *start= thd->lex->query_tables; } } @@ -5271,6 +5272,12 @@ static bool check_lock_and_start_stmt(THD *thd, thr_lock_type lock_type; DBUG_ENTER("check_lock_and_start_stmt"); + /* + Prelocking placeholder is not set for TABLE_LIST that + are directly used by TOP level statement. + */ + DBUG_ASSERT(table_list->prelocking_placeholder == false); + /* TL_WRITE_DEFAULT and TL_READ_DEFAULT are supposed to be parser only types of locks so they should be converted to appropriate other types -- cgit v1.2.1 From 9bc328a41ae6c7fbdde4167168206dfa9912ece0 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Fri, 24 Aug 2012 10:01:59 +0200 Subject: Bug#13417440 : 63340: ARCHIVE FILE IO NOT INSTRUMENTED WARNING This patch is for mysql-5.5 only, to be null-merged to mysql-5.6 and mysql-trunk. This is a partial rollback of the file io instrumentation, removing the instrumentation for mysql_file_stat in the archive engine. See the bug comments for details. --- mysql-test/suite/perfschema/t/disabled.def | 1 - storage/archive/ha_archive.cc | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/perfschema/t/disabled.def b/mysql-test/suite/perfschema/t/disabled.def index 8a843692d2a..888298bbb09 100644 --- a/mysql-test/suite/perfschema/t/disabled.def +++ b/mysql-test/suite/perfschema/t/disabled.def @@ -9,4 +9,3 @@ # Do not use any TAB characters for whitespace. # ############################################################################## -misc : bug#14113704 24/04/2012 Mayank issue reported causing failure. diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index 24dbaefce27..0e186cb8513 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -277,7 +277,7 @@ int archive_discover(handlerton *hton, THD* thd, const char *db, build_table_filename(az_file, sizeof(az_file) - 1, db, name, ARZ, 0); - if (!(mysql_file_stat(arch_key_file_data, az_file, &file_stat, MYF(0)))) + if (!(mysql_file_stat(/* arch_key_file_data */ 0, az_file, &file_stat, MYF(0)))) goto err; if (!(azopen(&frm_stream, az_file, O_RDONLY|O_BINARY))) @@ -727,7 +727,7 @@ int ha_archive::create(const char *name, TABLE *table_arg, There is a chance that the file was "discovered". In this case just use whatever file is there. */ - if (!(mysql_file_stat(arch_key_file_data, name_buff, &file_stat, MYF(0)))) + if (!(mysql_file_stat(/* arch_key_file_data */ 0, name_buff, &file_stat, MYF(0)))) { my_errno= 0; if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR|O_BINARY))) @@ -1622,7 +1622,7 @@ int ha_archive::info(uint flag) { MY_STAT file_stat; // Stat information for the data file - (void) mysql_file_stat(arch_key_file_data, share->data_file_name, &file_stat, MYF(MY_WME)); + (void) mysql_file_stat(/* arch_key_file_data */ 0, share->data_file_name, &file_stat, MYF(MY_WME)); if (flag & HA_STATUS_TIME) stats.update_time= (ulong) file_stat.st_mtime; -- cgit v1.2.1 From df2bdd6063e1a9a05be0048a309288dc4d7a8ce4 Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Fri, 24 Aug 2012 10:17:08 +0200 Subject: Bug#14498355: DEPRECATION WARNINGS SHOULD NOT CONTAIN MYSQL VERSION NUMBERS If a system variable was declared as deprecated without mention of an alternative, the message would look funny, e.g. for @@delayed_insert_limit: Warning 1287 '@@delayed_insert_limit' is deprecated and will be removed in MySQL . The message was meant to display the version number, but it's not possible to give one when declaring a system variable. The fix does two things: 1) The definition of the message ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT is changed so that it does not display a version number. I.e. in English the message now reads: Warning 1287 The syntax '@@delayed_insert_limit' is deprecated and will be removed in a future version. 2) The message ER_WARN_DEPRECATED_SYNTAX_WITH_VER is discontinued in favor of ER_WARN_DEPRECATED_SYNTAX for system variables. This change was already done in versions 5.6 and above as part of wl#5265. This part is simply back-ported from the worklog. --- mysql-test/r/log_state.result | 12 ++-- mysql-test/r/variables.result | 4 +- .../r/engine_condition_pushdown_basic.result | 56 +++++++-------- mysql-test/suite/sys_vars/r/log_basic.result | 6 +- .../suite/sys_vars/r/log_slow_queries_basic.result | 18 ++--- .../sys_vars/r/rpl_recovery_rank_basic_32.result | 34 ++++----- .../sys_vars/r/rpl_recovery_rank_basic_64.result | 34 ++++----- .../suite/sys_vars/r/sql_big_selects_func.result | 2 +- .../sys_vars/r/sql_max_join_size_basic.result | 10 +-- .../suite/sys_vars/r/sql_max_join_size_func.result | 14 ++-- sql/set_var.cc | 37 +++++----- sql/set_var.h | 4 +- sql/share/errmsg-utf8.txt | 4 +- sql/sql_plugin.cc | 2 +- sql/sys_vars.cc | 12 ++-- sql/sys_vars.h | 80 +++++++++++----------- 16 files changed, 163 insertions(+), 166 deletions(-) diff --git a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result index 4c54f12b34f..65406870f86 100644 --- a/mysql-test/r/log_state.result +++ b/mysql-test/r/log_state.result @@ -199,7 +199,7 @@ SELECT @@general_log, @@log; 1 1 SET GLOBAL log = 0; Warnings: -Warning 1287 The syntax '@@log' is deprecated and will be removed in MySQL 7.0. Please use '@@general_log' instead +Warning 1287 '@@log' is deprecated and will be removed in a future release. Please use '@@general_log' instead SHOW VARIABLES LIKE 'general_log'; Variable_name Value general_log OFF @@ -230,7 +230,7 @@ SELECT @@slow_query_log, @@log_slow_queries; 0 0 SET GLOBAL log_slow_queries = 0; Warnings: -Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MySQL 7.0. Please use '@@slow_query_log' instead +Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead SHOW VARIABLES LIKE 'slow_query_log'; Variable_name Value slow_query_log OFF @@ -283,16 +283,16 @@ SET GLOBAL slow_query_log_file = @old_slow_query_log_file; deprecated: SET GLOBAL log = 0; Warnings: -Warning 1287 The syntax '@@log' is deprecated and will be removed in MySQL 7.0. Please use '@@general_log' instead +Warning 1287 '@@log' is deprecated and will be removed in a future release. Please use '@@general_log' instead SET GLOBAL log_slow_queries = 0; Warnings: -Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MySQL 7.0. Please use '@@slow_query_log' instead +Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead SET GLOBAL log = DEFAULT; Warnings: -Warning 1287 The syntax '@@log' is deprecated and will be removed in MySQL 7.0. Please use '@@general_log' instead +Warning 1287 '@@log' is deprecated and will be removed in a future release. Please use '@@general_log' instead SET GLOBAL log_slow_queries = DEFAULT; Warnings: -Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MySQL 7.0. Please use '@@slow_query_log' instead +Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead not deprecated: SELECT @@global.general_log_file INTO @my_glf; SELECT @@global.slow_query_log_file INTO @my_sqlf; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 2b71117f789..802476b3f76 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -545,7 +545,7 @@ Warning 1292 Truncated incorrect read_buffer_size value: '100' set read_rnd_buffer_size=100; set global rpl_recovery_rank=100; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. set global server_id=100; set global slow_launch_time=100; set sort_buffer_size=100; @@ -1068,7 +1068,7 @@ set global query_cache_limit =@my_query_cache_limit; set global query_cache_type =@my_query_cache_type; set global rpl_recovery_rank =@my_rpl_recovery_rank; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. set global server_id =@my_server_id; set global slow_launch_time =@my_slow_launch_time; set global default_storage_engine =@my_storage_engine; diff --git a/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result b/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result index 2b0b57d5b33..a3a95e94ad9 100644 --- a/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result +++ b/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result @@ -13,26 +13,26 @@ index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_inters '#--------------------FN_DYNVARS_028_01------------------------#' SET @@session.engine_condition_pushdown = 0; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SET @@session.engine_condition_pushdown = DEFAULT; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@session.engine_condition_pushdown; @@session.engine_condition_pushdown 1 SET @@global.engine_condition_pushdown = 0; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SET @@global.engine_condition_pushdown = DEFAULT; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@global.engine_condition_pushdown; @@global.engine_condition_pushdown 1 '#---------------------FN_DYNVARS_028_02-------------------------#' SET engine_condition_pushdown = 1; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@engine_condition_pushdown; @@engine_condition_pushdown 1 @@ -44,38 +44,38 @@ SELECT global.engine_condition_pushdown; ERROR 42S02: Unknown table 'global' in field list SET session engine_condition_pushdown = 0; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@session.engine_condition_pushdown; @@session.engine_condition_pushdown 0 SET global engine_condition_pushdown = 0; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@global.engine_condition_pushdown; @@global.engine_condition_pushdown 0 '#--------------------FN_DYNVARS_028_03------------------------#' SET @@session.engine_condition_pushdown = 0; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@session.engine_condition_pushdown; @@session.engine_condition_pushdown 0 SET @@session.engine_condition_pushdown = 1; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@session.engine_condition_pushdown; @@session.engine_condition_pushdown 1 SET @@global.engine_condition_pushdown = 0; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@global.engine_condition_pushdown; @@global.engine_condition_pushdown 0 SET @@global.engine_condition_pushdown = 1; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@global.engine_condition_pushdown; @@global.engine_condition_pushdown 1 @@ -115,16 +115,16 @@ ERROR 42000: Variable 'engine_condition_pushdown' can't be set to the value of ' '#-------------------FN_DYNVARS_028_05----------------------------#' SET @@global.engine_condition_pushdown = 0; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SET @@session.engine_condition_pushdown = 1; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@global.engine_condition_pushdown AS res_is_0; res_is_0 0 SET @@global.engine_condition_pushdown = 0; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@session.engine_condition_pushdown AS res_is_1; res_is_1 1 @@ -159,50 +159,50 @@ ON '#---------------------FN_DYNVARS_028_08-------------------------#' SET @@session.engine_condition_pushdown = OFF; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@session.engine_condition_pushdown; @@session.engine_condition_pushdown 0 SET @@session.engine_condition_pushdown = ON; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@session.engine_condition_pushdown; @@session.engine_condition_pushdown 1 SET @@global.engine_condition_pushdown = OFF; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@global.engine_condition_pushdown; @@global.engine_condition_pushdown 0 SET @@global.engine_condition_pushdown = ON; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@global.engine_condition_pushdown; @@global.engine_condition_pushdown 1 '#---------------------FN_DYNVARS_028_09----------------------#' SET @@session.engine_condition_pushdown = TRUE; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@session.engine_condition_pushdown; @@session.engine_condition_pushdown 1 SET @@session.engine_condition_pushdown = FALSE; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@session.engine_condition_pushdown; @@session.engine_condition_pushdown 0 SET @@global.engine_condition_pushdown = TRUE; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@global.engine_condition_pushdown; @@global.engine_condition_pushdown 1 SET @@global.engine_condition_pushdown = FALSE; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@global.engine_condition_pushdown; @@global.engine_condition_pushdown 0 @@ -215,7 +215,7 @@ select @@session.engine_condition_pushdown, 0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=off index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=off set @@session.engine_condition_pushdown = TRUE; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead select @@session.engine_condition_pushdown, @@global.engine_condition_pushdown, @@session.optimizer_switch, @@global.optimizer_switch; @@ -223,7 +223,7 @@ select @@session.engine_condition_pushdown, 1 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=off set @@session.engine_condition_pushdown = FALSE; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead select @@session.engine_condition_pushdown, @@global.engine_condition_pushdown, @@session.optimizer_switch, @@global.optimizer_switch; @@ -231,7 +231,7 @@ select @@session.engine_condition_pushdown, 0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=off index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=off set @@global.engine_condition_pushdown = TRUE; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead select @@session.engine_condition_pushdown, @@global.engine_condition_pushdown, @@session.optimizer_switch, @@global.optimizer_switch; @@ -239,7 +239,7 @@ select @@session.engine_condition_pushdown, 0 1 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=off index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on set @@global.engine_condition_pushdown = FALSE; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead select @@session.engine_condition_pushdown, @@global.engine_condition_pushdown, @@session.optimizer_switch, @@global.optimizer_switch; @@ -271,13 +271,13 @@ select @@session.engine_condition_pushdown, 0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=off index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=off SET @@session.engine_condition_pushdown = @session_start_value; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@session.engine_condition_pushdown; @@session.engine_condition_pushdown 1 SET @@global.engine_condition_pushdown = @global_start_value; Warnings: -Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead +Warning 1287 '@@engine_condition_pushdown' is deprecated and will be removed in a future release. Please use '@@optimizer_switch' instead SELECT @@global.engine_condition_pushdown; @@global.engine_condition_pushdown 1 diff --git a/mysql-test/suite/sys_vars/r/log_basic.result b/mysql-test/suite/sys_vars/r/log_basic.result index 5574d49514d..381fa523133 100644 --- a/mysql-test/suite/sys_vars/r/log_basic.result +++ b/mysql-test/suite/sys_vars/r/log_basic.result @@ -8,10 +8,10 @@ INIT_VALUE 1 SET @@global.log = ON; Warnings: -Warning 1287 The syntax '@@log' is deprecated and will be removed in MySQL 7.0. Please use '@@general_log' instead +Warning 1287 '@@log' is deprecated and will be removed in a future release. Please use '@@general_log' instead SET global log = 0; Warnings: -Warning 1287 The syntax '@@log' is deprecated and will be removed in MySQL 7.0. Please use '@@general_log' instead +Warning 1287 '@@log' is deprecated and will be removed in a future release. Please use '@@general_log' instead '#--------------------FN_DYNVARS_062_02-------------------------#' SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -20,4 +20,4 @@ VARIABLE_VALUE OFF SET @@global.log= @start_log; Warnings: -Warning 1287 The syntax '@@log' is deprecated and will be removed in MySQL 7.0. Please use '@@general_log' instead +Warning 1287 '@@log' is deprecated and will be removed in a future release. Please use '@@general_log' instead diff --git a/mysql-test/suite/sys_vars/r/log_slow_queries_basic.result b/mysql-test/suite/sys_vars/r/log_slow_queries_basic.result index 1748406b74b..648b3651a4f 100644 --- a/mysql-test/suite/sys_vars/r/log_slow_queries_basic.result +++ b/mysql-test/suite/sys_vars/r/log_slow_queries_basic.result @@ -5,20 +5,20 @@ SELECT @start_value; '#---------------------FN_DYNVARS_004_01-------------------------#' SET @@global.log_slow_queries = DEFAULT; Warnings: -Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MySQL 7.0. Please use '@@slow_query_log' instead +Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead SELECT @@global.log_slow_queries = 0; @@global.log_slow_queries = 0 1 '#--------------------FN_DYNVARS_004_02------------------------#' SET @@global.log_slow_queries = ON; Warnings: -Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MySQL 7.0. Please use '@@slow_query_log' instead +Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead SELECT @@global.log_slow_queries; @@global.log_slow_queries 1 SET @@global.log_slow_queries = OFF; Warnings: -Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MySQL 7.0. Please use '@@slow_query_log' instead +Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead SELECT @@global.log_slow_queries; @@global.log_slow_queries 0 @@ -61,7 +61,7 @@ IF(@@global.log_slow_queries, "ON", "OFF") = VARIABLE_VALUE '#---------------------FN_DYNVARS_004_06----------------------#' SET @@global.log_slow_queries = 0; Warnings: -Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MySQL 7.0. Please use '@@slow_query_log' instead +Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead SELECT @@global.log_slow_queries; @@global.log_slow_queries 0 @@ -72,7 +72,7 @@ IF(@@global.log_slow_queries, "ON", "OFF") = VARIABLE_VALUE 1 SET @@global.log_slow_queries = 1; Warnings: -Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MySQL 7.0. Please use '@@slow_query_log' instead +Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead SELECT @@global.log_slow_queries; @@global.log_slow_queries 1 @@ -84,7 +84,7 @@ IF(@@global.log_slow_queries, "ON", "OFF") = VARIABLE_VALUE '#---------------------FN_DYNVARS_004_07----------------------#' SET @@global.log_slow_queries = TRUE; Warnings: -Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MySQL 7.0. Please use '@@slow_query_log' instead +Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead SELECT @@global.log_slow_queries; @@global.log_slow_queries 1 @@ -95,7 +95,7 @@ IF(@@global.log_slow_queries, "ON", "OFF") = VARIABLE_VALUE 1 SET @@global.log_slow_queries = FALSE; Warnings: -Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MySQL 7.0. Please use '@@slow_query_log' instead +Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead SELECT @@global.log_slow_queries; @@global.log_slow_queries 0 @@ -107,7 +107,7 @@ IF(@@global.log_slow_queries, "ON", "OFF") = VARIABLE_VALUE '#---------------------FN_DYNVARS_004_08----------------------#' SET @@global.log_slow_queries = ON; Warnings: -Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MySQL 7.0. Please use '@@slow_query_log' instead +Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead SELECT @@log_slow_queries = @@global.log_slow_queries; @@log_slow_queries = @@global.log_slow_queries 1 @@ -126,7 +126,7 @@ SELECT log_slow_queries = @@session.log_slow_queries; ERROR 42S22: Unknown column 'log_slow_queries' in 'field list' SET @@global.log_slow_queries = @start_value; Warnings: -Warning 1287 The syntax '@@log_slow_queries' is deprecated and will be removed in MySQL 7.0. Please use '@@slow_query_log' instead +Warning 1287 '@@log_slow_queries' is deprecated and will be removed in a future release. Please use '@@slow_query_log' instead SELECT @@global.log_slow_queries; @@global.log_slow_queries 1 diff --git a/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic_32.result b/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic_32.result index f5b771c47cc..4bb362736c8 100644 --- a/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic_32.result +++ b/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic_32.result @@ -5,42 +5,42 @@ SELECT @start_global_value; '#--------------------FN_DYNVARS_142_01-------------------------#' SET @@global.rpl_recovery_rank = 500000; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SET @@global.rpl_recovery_rank = DEFAULT; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 '#--------------------FN_DYNVARS_142_02-------------------------#' SET @@global.rpl_recovery_rank = 0; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 SET @@global.rpl_recovery_rank = 1024; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 1024 SET @@global.rpl_recovery_rank = 123456789; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 123456789 SET @@global.rpl_recovery_rank = 2147483648*2; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. Warning 1292 Truncated incorrect rpl_recovery_rank value: '4294967296' SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 4294967295 SET @@global.rpl_recovery_rank = 2147483648*1024; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. Warning 1292 Truncated incorrect rpl_recovery_rank value: '2199023255552' SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank @@ -50,7 +50,7 @@ SELECT @@global.rpl_recovery_rank; 4294967295 SET @@global.rpl_recovery_rank = 2147483648*2147483648; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. Warning 1292 Truncated incorrect rpl_recovery_rank value: '4611686018427387904' SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank @@ -65,21 +65,21 @@ ERROR HY000: Variable 'rpl_recovery_rank' is a GLOBAL variable and should be set '#------------------FN_DYNVARS_142_04-----------------------#' SET @@global.rpl_recovery_rank = -1; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. Warning 1292 Truncated incorrect rpl_recovery_rank value: '-1' SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 SET @@global.rpl_recovery_rank = -2147483648; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. Warning 1292 Truncated incorrect rpl_recovery_rank value: '-2147483648' SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 SET @@global.rpl_recovery_rank = -2147483649; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. Warning 1292 Truncated incorrect rpl_recovery_rank value: '-2147483649' SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank @@ -93,7 +93,7 @@ ERROR 42000: Incorrect argument type to variable 'rpl_recovery_rank' '#------------------FN_DYNVARS_142_05-----------------------#' SET @@global.rpl_recovery_rank = 3000; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='rpl_recovery_rank'; @@ -108,20 +108,20 @@ count(VARIABLE_VALUE) '#------------------FN_DYNVARS_142_07-----------------------#' SET @@global.rpl_recovery_rank = TRUE; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 1 SET @@global.rpl_recovery_rank = FALSE; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 '#---------------------FN_DYNVARS_001_08----------------------#' SET @@global.rpl_recovery_rank = 512; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@rpl_recovery_rank = @@global.rpl_recovery_rank; @@rpl_recovery_rank = @@global.rpl_recovery_rank 1 @@ -135,10 +135,10 @@ SELECT @@rpl_recovery_rank; 512 SET global rpl_recovery_rank = 64; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SET @@global.rpl_recovery_rank = @start_global_value; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 diff --git a/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic_64.result b/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic_64.result index 14a7cdd0046..411dfc865bb 100644 --- a/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic_64.result +++ b/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic_64.result @@ -5,41 +5,41 @@ SELECT @start_global_value; '#--------------------FN_DYNVARS_142_01-------------------------#' SET @@global.rpl_recovery_rank = 500000; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SET @@global.rpl_recovery_rank = DEFAULT; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 '#--------------------FN_DYNVARS_142_02-------------------------#' SET @@global.rpl_recovery_rank = 0; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 SET @@global.rpl_recovery_rank = 1024; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 1024 SET @@global.rpl_recovery_rank = 123456789; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 123456789 SET @@global.rpl_recovery_rank = 2147483648*2; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 4294967296 SET @@global.rpl_recovery_rank = 2147483648*1024; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 2199023255552 @@ -48,7 +48,7 @@ SELECT @@global.rpl_recovery_rank; 2199023255552 SET @@global.rpl_recovery_rank = 2147483648*2147483648; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 4611686018427387904 @@ -62,21 +62,21 @@ ERROR HY000: Variable 'rpl_recovery_rank' is a GLOBAL variable and should be set '#------------------FN_DYNVARS_142_04-----------------------#' SET @@global.rpl_recovery_rank = -1; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. Warning 1292 Truncated incorrect rpl_recovery_rank value: '-1' SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 SET @@global.rpl_recovery_rank = -2147483648; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. Warning 1292 Truncated incorrect rpl_recovery_rank value: '-2147483648' SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 SET @@global.rpl_recovery_rank = -2147483649; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. Warning 1292 Truncated incorrect rpl_recovery_rank value: '-2147483649' SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank @@ -90,7 +90,7 @@ ERROR 42000: Incorrect argument type to variable 'rpl_recovery_rank' '#------------------FN_DYNVARS_142_05-----------------------#' SET @@global.rpl_recovery_rank = 3000; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='rpl_recovery_rank'; @@ -105,20 +105,20 @@ count(VARIABLE_VALUE) '#------------------FN_DYNVARS_142_07-----------------------#' SET @@global.rpl_recovery_rank = TRUE; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 1 SET @@global.rpl_recovery_rank = FALSE; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 '#---------------------FN_DYNVARS_001_08----------------------#' SET @@global.rpl_recovery_rank = 512; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@rpl_recovery_rank = @@global.rpl_recovery_rank; @@rpl_recovery_rank = @@global.rpl_recovery_rank 1 @@ -132,10 +132,10 @@ SELECT @@rpl_recovery_rank; 512 SET global rpl_recovery_rank = 64; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SET @@global.rpl_recovery_rank = @start_global_value; Warnings: -Warning 1287 The syntax '@@rpl_recovery_rank' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@rpl_recovery_rank' is deprecated and will be removed in a future release. SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 diff --git a/mysql-test/suite/sys_vars/r/sql_big_selects_func.result b/mysql-test/suite/sys_vars/r/sql_big_selects_func.result index 56364607982..5c35797292b 100644 --- a/mysql-test/suite/sys_vars/r/sql_big_selects_func.result +++ b/mysql-test/suite/sys_vars/r/sql_big_selects_func.result @@ -5,7 +5,7 @@ SET @session_max_join_size = @@SESSION.max_join_size; SET @global_max_join_size = @@GLOBAL.max_join_size; SET SQL_MAX_JOIN_SIZE=9; Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. CREATE TEMPORARY TABLE t1(a varchar(20) not null, b varchar(20)); CREATE TEMPORARY TABLE t2(a varchar(20) null, b varchar(20)); INSERT INTO t1 VALUES('aa','bb'); diff --git a/mysql-test/suite/sys_vars/r/sql_max_join_size_basic.result b/mysql-test/suite/sys_vars/r/sql_max_join_size_basic.result index 8ec2a60887f..6685ef74938 100644 --- a/mysql-test/suite/sys_vars/r/sql_max_join_size_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_max_join_size_basic.result @@ -22,10 +22,10 @@ VARIABLE_NAME VARIABLE_VALUE SQL_MAX_JOIN_SIZE 18446744073709551615 set global sql_max_join_size=10; Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. set session sql_max_join_size=20; Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. select @@global.sql_max_join_size; @@global.sql_max_join_size 10 @@ -55,19 +55,19 @@ select @@sql_big_selects; 0 set sql_max_join_size=cast(-1 as unsigned int); Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. select @@sql_big_selects; @@sql_big_selects 1 set sql_max_join_size=100; Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. select @@sql_big_selects; @@sql_big_selects 0 SET @@global.sql_max_join_size = @start_global_value; Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. SELECT @@global.sql_max_join_size; @@global.sql_max_join_size 18446744073709551615 diff --git a/mysql-test/suite/sys_vars/r/sql_max_join_size_func.result b/mysql-test/suite/sys_vars/r/sql_max_join_size_func.result index 38941be0ba4..5380307ecd9 100644 --- a/mysql-test/suite/sys_vars/r/sql_max_join_size_func.result +++ b/mysql-test/suite/sys_vars/r/sql_max_join_size_func.result @@ -17,7 +17,7 @@ INSERT INTO t2 VALUES('aa4','bb'); '#--------------------FN_DYNVARS_161_01-------------------------#' SET SESSION sql_max_join_size=9; Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. SELECT * FROM t1 INNER JOIN t2 ON t1.a = t2.a; ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay Expected error The SELECT would examine more than MAX_JOIN_SIZE rows. @@ -33,7 +33,7 @@ aa4 bb aa4 bb This should work SET SESSION sql_max_join_size=DEFAULT; Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. DELETE FROM t2 WHERE a = 'aa4'; SELECT * FROM t1 INNER JOIN t2 ON t1.a = t2.a; a b a b @@ -45,7 +45,7 @@ This should work '#----------------------------FN_DYNVARS_136_05-------------------------#' SET GLOBAL sql_max_join_size = 4; Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. ** Connecting con_int1 using root ** ** Connection con_int1 ** SELECT @@SESSION.sql_max_join_size; @@ -54,7 +54,7 @@ SELECT @@SESSION.sql_max_join_size; 4 Expected SET SESSION sql_max_join_size = 2; Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. ** Connecting con_int2 using root ** ** Connection con_int2 ** SELECT @@SESSION.sql_max_join_size; @@ -63,7 +63,7 @@ SELECT @@SESSION.sql_max_join_size; 4 Expected SET SESSION sql_max_join_size = 10; Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. ** Connection con_int2 ** SELECT @@SESSION.sql_max_join_size; @@SESSION.sql_max_join_size @@ -82,10 +82,10 @@ SELECT @@GLOBAL.sql_max_join_size; Disconnecting Connections con_int1, con_int2 SET @@SESSION.sql_max_join_size = @session_max_join_size; Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. SET @@GLOBAL.sql_max_join_size = @global_max_join_size ; Warnings: -Warning 1287 The syntax '@@sql_max_join_size' is deprecated and will be removed in MySQL 7.0. +Warning 1287 '@@sql_max_join_size' is deprecated and will be removed in a future release. SET @@SESSION.sql_big_selects = @session_sql_big_selects; DROP TABLE t1; DROP TABLE t2; diff --git a/sql/set_var.cc b/sql/set_var.cc index 4cdee8e1258..231fbb47d35 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -134,9 +134,9 @@ void sys_var_end() put your additional checks here @param on_update_func a function to be called at the end of sys_var::update, any post-update activity should happen here - @param deprecated_version if not 0 - when this variable will go away - @param substitute if not 0 - what one should use instead when this - deprecated variable + @param substitute If non-NULL, this variable is deprecated and the + string describes what one should use instead. If an empty string, + the variable is deprecated but no replacement is offered. @param parse_flag either PARSE_EARLY or PARSE_NORMAL */ sys_var::sys_var(sys_var_chain *chain, const char *name_arg, @@ -146,12 +146,12 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg, PolyLock *lock, enum binlog_status_enum binlog_status_arg, on_check_function on_check_func, on_update_function on_update_func, - uint deprecated_version, const char *substitute, - int parse_flag) : + const char *substitute, int parse_flag) : next(0), binlog_status(binlog_status_arg), flags(flags_arg), m_parse_flag(parse_flag), show_val_type(show_val_type_arg), guard(lock), offset(off), on_check(on_check_func), on_update(on_update_func), + deprecation_substitute(substitute), is_os_charset(FALSE) { /* @@ -177,12 +177,6 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg, option.value= (uchar **)global_var_ptr(); option.def_value= def_val; - deprecated.version= deprecated_version; - deprecated.substitute= substitute; - DBUG_ASSERT((deprecated_version != 0) || (substitute == 0)); - DBUG_ASSERT(deprecated_version % 100 == 0); - DBUG_ASSERT(!deprecated_version || MYSQL_VERSION_ID < deprecated_version); - if (chain->last) chain->last->next= this; else @@ -277,21 +271,24 @@ bool sys_var::set_default(THD *thd, enum_var_type type) void sys_var::do_deprecated_warning(THD *thd) { - if (deprecated.version) + if (deprecation_substitute != NULL) { - char buf1[NAME_CHAR_LEN + 3], buf2[10]; + char buf1[NAME_CHAR_LEN + 3]; strxnmov(buf1, sizeof(buf1)-1, "@@", name.str, 0); - my_snprintf(buf2, sizeof(buf2), "%d.%d", deprecated.version/100/100, - deprecated.version/100%100); - uint errmsg= deprecated.substitute - ? ER_WARN_DEPRECATED_SYNTAX_WITH_VER - : ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT; + + /* + if deprecation_substitute is an empty string, + there is no replacement for the syntax + */ + uint errmsg= deprecation_substitute[0] == '\0' + ? ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT + : ER_WARN_DEPRECATED_SYNTAX; if (thd) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DEPRECATED_SYNTAX, ER(errmsg), - buf1, buf2, deprecated.substitute); + buf1, deprecation_substitute); else - sql_print_warning(ER_DEFAULT(errmsg), buf1, buf2, deprecated.substitute); + sql_print_warning(ER_DEFAULT(errmsg), buf1, deprecation_substitute); } } diff --git a/sql/set_var.h b/sql/set_var.h index 041c40fdca4..f0d90cb0d63 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -82,7 +82,7 @@ protected: ptrdiff_t offset; ///< offset to the value from global_system_variables on_check_function on_check; on_update_function on_update; - struct { uint version; const char *substitute; } deprecated; + const char *const deprecation_substitute; bool is_os_charset; ///< true if the value is in character_set_filesystem public: @@ -91,7 +91,7 @@ public: enum get_opt_arg_type getopt_arg_type, SHOW_TYPE show_val_type_arg, longlong def_val, PolyLock *lock, enum binlog_status_enum binlog_status_arg, on_check_function on_check_func, on_update_function on_update_func, - uint deprecated_version, const char *substitute, int parse_flag); + const char *substitute, int parse_flag); virtual ~sys_var() {} diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 263dd0ffeb7..e7ef0f74f1e 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6343,8 +6343,8 @@ ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT ER_PATH_LENGTH eng "The path specified for %.64s is too long." ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT - eng "The syntax '%s' is deprecated and will be removed in MySQL %s." - ger "Die Syntax '%s' ist veraltet und wird in MySQL %s entfernt." + eng "'%s' is deprecated and will be removed in a future release." + ger "'%s' ist veraltet und wird in einer zukünftigen Version entfernt werden." ER_WRONG_NATIVE_TABLE_STRUCTURE eng "Native table '%-.64s'.'%-.64s' has the wrong structure" diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 47827e0e567..1dbc76537da 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -223,7 +223,7 @@ public: (plugin_var_arg->flags & PLUGIN_VAR_THDLOCAL ? SESSION : GLOBAL) | (plugin_var_arg->flags & PLUGIN_VAR_READONLY ? READONLY : 0), 0, -1, NO_ARG, pluginvar_show_type(plugin_var_arg), 0, 0, - VARIABLE_NOT_IN_BINLOG, 0, 0, 0, 0, PARSE_NORMAL), + VARIABLE_NOT_IN_BINLOG, NULL, NULL, NULL, PARSE_NORMAL), plugin_var(plugin_var_arg), orig_pluginvar_name(plugin_var_arg->name) { plugin_var->name= name_arg; } sys_var_pluginvar *cast_pluginvar() { return this; } diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index e0523989f9d..06f97af2ade 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -142,7 +142,7 @@ static bool update_keycache_param(THD *thd, KEY_CACHE *key_cache, #define PFS_TRAILING_PROPERTIES \ NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL), ON_UPDATE(NULL), \ - 0, NULL, sys_var::PARSE_EARLY + NULL, sys_var::PARSE_EARLY static Sys_var_mybool Sys_pfs_enabled( "performance_schema", @@ -1288,7 +1288,7 @@ static Sys_var_harows Sys_sql_max_join_size( SESSION_VAR(max_join_size), NO_CMD_LINE, VALID_RANGE(1, HA_POS_ERROR), DEFAULT(HA_POS_ERROR), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), - ON_UPDATE(fix_max_join_size), DEPRECATED(70000, 0)); + ON_UPDATE(fix_max_join_size), DEPRECATED("")); static Sys_var_ulong Sys_max_long_data_size( "max_long_data_size", @@ -1707,7 +1707,7 @@ static Sys_var_ulong Sys_rpl_recovery_rank( GLOBAL_VAR(rpl_recovery_rank), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0), - DEPRECATED(70000, 0)); + DEPRECATED("")); static Sys_var_ulong Sys_range_alloc_block_size( "range_alloc_block_size", @@ -2288,7 +2288,7 @@ static Sys_var_mybool Sys_engine_condition_pushdown( CMD_LINE(OPT_ARG, OPT_ENGINE_CONDITION_PUSHDOWN), DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL), ON_UPDATE(fix_engine_condition_pushdown), - DEPRECATED(70000, "'@@optimizer_switch'")); + DEPRECATED("'@@optimizer_switch'")); static Sys_var_plugin Sys_default_storage_engine( "default_storage_engine", "The default storage engine for new tables", @@ -2963,7 +2963,7 @@ static Sys_var_mybool Sys_log( "log", "Alias for --general-log. Deprecated", GLOBAL_VAR(opt_log), NO_CMD_LINE, DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), - ON_UPDATE(fix_log_state), DEPRECATED(70000, "'@@general_log'")); + ON_UPDATE(fix_log_state), DEPRECATED("'@@general_log'")); static Sys_var_mybool Sys_slow_query_log( "slow_query_log", @@ -2980,7 +2980,7 @@ static Sys_var_mybool Sys_log_slow( "Alias for --slow-query-log. Deprecated", GLOBAL_VAR(opt_slow_log), NO_CMD_LINE, DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), - ON_UPDATE(fix_log_state), DEPRECATED(70000, "'@@slow_query_log'")); + ON_UPDATE(fix_log_state), DEPRECATED("'@@slow_query_log'")); static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type) { diff --git a/sql/sys_vars.h b/sql/sys_vars.h index a69a91f7eb7..ca6e7d40b0e 100644 --- a/sql/sys_vars.h +++ b/sql/sys_vars.h @@ -58,7 +58,7 @@ @@foreign_key_checks <-> OPTION_NO_FOREIGN_KEY_CHECKS */ #define REVERSE(X) ~(X) -#define DEPRECATED(X, Y) X, Y +#define DEPRECATED(X) X #define session_var(THD, TYPE) (*(TYPE*)session_var_ptr(THD)) #define global_var(TYPE) (*(TYPE*)global_var_ptr()) @@ -108,11 +108,11 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0, + const char *substitute=0, int parse_flag= PARSE_NORMAL) : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg, - on_check_func, on_update_func, deprecated_version, + on_check_func, on_update_func, substitute, parse_flag) { option.var_type= ARGT; @@ -196,11 +196,11 @@ public: ulonglong def_val, PolyLock *lock, enum binlog_status_enum binlog_status_arg, on_check_function on_check_func, on_update_function on_update_func, - uint deprecated_version, const char *substitute, int parse_flag= PARSE_NORMAL) + const char *substitute, int parse_flag= PARSE_NORMAL) : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, getopt.arg_type, show_val_type_arg, def_val, lock, binlog_status_arg, on_check_func, - on_update_func, deprecated_version, substitute, parse_flag) + on_update_func, substitute, parse_flag) { for (typelib.count= 0; values[typelib.count]; typelib.count++) /*no-op */; typelib.name=""; @@ -263,11 +263,11 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0) + const char *substitute=0) : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, SHOW_CHAR, values, def_val, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute) + substitute) { option.var_type= GET_ENUM; global_var(ulong)= def_val; @@ -310,12 +310,12 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0, + const char *substitute=0, int parse_flag= PARSE_NORMAL) : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, SHOW_MY_BOOL, bool_values, def_val, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute, parse_flag) + substitute, parse_flag) { option.var_type= GET_BOOL; global_var(my_bool)= def_val; @@ -366,12 +366,12 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0, + const char *substitute=0, int parse_flag= PARSE_NORMAL) : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, getopt.arg_type, SHOW_CHAR_PTR, (intptr)def_val, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute, parse_flag) + substitute, parse_flag) { is_os_charset= is_os_charset_arg == IN_FS_CHARSET; /* @@ -460,7 +460,7 @@ public: : sys_var(&all_sys_vars, name_arg, comment, sys_var::READONLY+sys_var::ONLY_SESSION, 0, -1, NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, - NULL, NULL, 0, NULL, PARSE_NORMAL) + NULL, NULL, NULL, PARSE_NORMAL) { is_os_charset= is_os_charset_arg == IN_FS_CHARSET; option.var_type= GET_STR; @@ -533,10 +533,10 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0) + const char *substitute=0) : Sys_var_charptr(name_arg, comment, flag_args, off, sizeof(char*), getopt, is_os_charset_arg, def_val, lock, binlog_status_arg, - on_check_func, on_update_func, deprecated_version, substitute) + on_check_func, on_update_func, substitute) { global_var(LEX_STRING).length= strlen(def_val); DBUG_ASSERT(size == sizeof(LEX_STRING)); @@ -573,12 +573,12 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0, + const char *substitute=0, int parse_flag= PARSE_NORMAL) : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, getopt.arg_type, SHOW_CHAR, (intptr)def_val, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute, parse_flag) + substitute, parse_flag) { option.var_type= GET_NO_ARG; } bool do_check(THD *thd, set_var *var) { @@ -658,11 +658,11 @@ public: enum binlog_status_enum binlog_status_arg, on_check_function on_check_func, keycache_update_function on_update_func, - uint deprecated_version=0, const char *substitute=0) + const char *substitute=0) : Sys_var_ulonglong(name_arg, comment, flag_args, off, size, getopt, min_val, max_val, def_val, block_size, lock, binlog_status_arg, on_check_func, 0, - deprecated_version, substitute), + substitute), keycache_update(on_update_func) { option.var_type|= GET_ASK_ADDR; @@ -726,12 +726,12 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0, + const char *substitute=0, int parse_flag= PARSE_NORMAL) : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, getopt.arg_type, SHOW_DOUBLE, (longlong) double2ulonglong(def_val), lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute, parse_flag) + substitute, parse_flag) { option.var_type= GET_DOUBLE; option.min_value= (longlong) double2ulonglong(min_val); @@ -791,11 +791,11 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0) + const char *substitute=0) : Sys_var_uint(name_arg, comment, SESSION, off, size, getopt, min_val, max_val, def_val, block_size, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute) + substitute) { } uchar *session_value_ptr(THD *thd, LEX_STRING *base) { @@ -833,11 +833,11 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0) + const char *substitute=0) : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, SHOW_CHAR, values, def_val, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute) + substitute) { option.var_type= GET_FLAGSET; global_var(ulonglong)= def_val; @@ -944,11 +944,11 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0) + const char *substitute=0) : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, SHOW_CHAR, values, def_val, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute) + substitute) { option.var_type= GET_SET; global_var(ulonglong)= def_val; @@ -1050,12 +1050,12 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0, + const char *substitute=0, int parse_flag= PARSE_NORMAL) : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, getopt.arg_type, SHOW_CHAR, (intptr)def_val, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute, parse_flag), + substitute, parse_flag), plugin_type(plugin_type_arg) { option.var_type= GET_STR; @@ -1164,12 +1164,12 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0, + const char *substitute=0, int parse_flag= PARSE_NORMAL) : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, getopt.arg_type, SHOW_CHAR, (intptr)def_val, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute, parse_flag) + substitute, parse_flag) { DBUG_ASSERT(scope() == ONLY_SESSION); option.var_type= GET_NO_ARG; @@ -1257,11 +1257,11 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0) + const char *substitute=0) : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, SHOW_MY_BOOL, bool_values, def_val, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute) + substitute) { option.var_type= GET_BOOL; reverse_semantics= my_count_bits(bitmask_arg) > 1; @@ -1330,11 +1330,11 @@ public: on_check_function on_check_func, session_special_update_function update_func_arg, session_special_read_function read_func_arg, - uint deprecated_version=0, const char *substitute=0) + const char *substitute=0) : Sys_var_ulonglong(name_arg, comment, flag_args, 0, sizeof(ulonglong), getopt, min_val, max_val, 0, block_size, lock, binlog_status_arg, on_check_func, 0, - deprecated_version, substitute), + substitute), read_func(read_func_arg), update_func(update_func_arg) { DBUG_ASSERT(scope() == ONLY_SESSION); @@ -1383,12 +1383,12 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0, + const char *substitute=0, int parse_flag= PARSE_NORMAL) : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, getopt.arg_type, SHOW_CHAR, 0, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute, parse_flag) + substitute, parse_flag) { DBUG_ASSERT(scope() == GLOBAL); DBUG_ASSERT(getopt.id == -1); @@ -1452,12 +1452,12 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0, + const char *substitute=0, int parse_flag= PARSE_NORMAL) : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, getopt.arg_type, SHOW_CHAR, (intptr)def_val, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute, parse_flag), + substitute, parse_flag), name_offset(name_off) { option.var_type= GET_STR; @@ -1525,12 +1525,12 @@ public: enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, on_check_function on_check_func=0, on_update_function on_update_func=0, - uint deprecated_version=0, const char *substitute=0, + const char *substitute=0, int parse_flag= PARSE_NORMAL) : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, getopt.arg_type, SHOW_CHAR, (intptr)def_val, lock, binlog_status_arg, on_check_func, on_update_func, - deprecated_version, substitute, parse_flag) + substitute, parse_flag) { DBUG_ASSERT(getopt.id == -1); DBUG_ASSERT(size == sizeof(Time_zone *)); -- cgit v1.2.1 From 8c239b09a27c3510b675e6a8b9370a25ffb6986d Mon Sep 17 00:00:00 2001 From: Ashish Agarwal Date: Fri, 24 Aug 2012 14:55:47 +0530 Subject: Bug#14363985: MYSQLD CRASHED WHEN DISABL AND ENABLE AUDI PLUGIN WHEN DDL OPERATION HAPPENING PROBLEM: While unloading the plugin, state is not checked before it is to be reaped. This can lead to simultaneous free of plugin memory by more than one thread. Multiple deallocation leads to server crash. In the present bug two threads deallocate the alog_log plugin. SOLUTION: A check is added to ensure that only one thread is unloading the plugin. NOTE: No mtr test is added as it requires multiple threads to access critical section. debug_sync cannot be used in the current senario because we dont have access to thread pointer in some of the plugin functions. IMHO no test case in the current time frame. --- sql/sql_plugin.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 47827e0e567..14668125599 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1900,7 +1900,8 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) mysql_audit_acquire_plugins(thd, MYSQL_AUDIT_GENERAL_CLASS); mysql_mutex_lock(&LOCK_plugin); - if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN))) + if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)) || + plugin->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_DYING)) { my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str); goto err; -- cgit v1.2.1 From a619bfad30c13207fb0453a85af5740846186900 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Tue, 28 Aug 2012 16:13:03 +0200 Subject: Bug#14549809 LINKING PROBLEM IN 5.5.28 BUILDS WITH THREADPOOL PLUGIN The use of Thread_iterator did not work on windows (linking problems). Solution: Change the interface between the thread_pool and the server to only use simple free functions. This patch is for 5.5 only (mimicks similar solution in 5.6) --- include/mysql/thread_pool_priv.h | 20 ++------------------ sql/mysqld.cc | 15 +++++++++++++++ sql/sql_list.h | 4 ++++ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index d649655bb8e..babe0ab6c08 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -62,24 +62,8 @@ void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var); ulong thd_get_net_wait_timeout(THD *thd); my_socket thd_get_fd(THD *thd); -/* Interface class for global thread list iteration */ -class Thread_iterator -{ - public: - Thread_iterator() : m_iterator(threads) {} - THD* next() - { - THD* tmp = m_iterator++; - return tmp; - } - private: - /* - Don't allow copying of this class. - */ - Thread_iterator(const Thread_iterator&); - void operator=(const Thread_iterator&); - I_List_iterator m_iterator; -}; +THD *first_global_thread(); +THD *next_global_thread(THD *thd); /* Print to the MySQL error log */ void sql_print_error(const char *format, ...); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d391918c42c..cfc74804f4e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -601,6 +601,21 @@ I_List threads; Rpl_filter* rpl_filter; Rpl_filter* binlog_filter; +THD *first_global_thread() +{ + if (threads.is_empty()) + return NULL; + return threads.head(); +} + +THD *next_global_thread(THD *thd) +{ + if (threads.is_last(thd)) + return NULL; + struct ilink *next= thd->next; + return static_cast(next); +} + struct system_variables global_system_variables; struct system_variables max_system_variables; struct system_status_var global_status_var; diff --git a/sql/sql_list.h b/sql/sql_list.h index 769f44274de..c68ecc07e11 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -585,6 +585,9 @@ public: inline void empty() { first= &last; last.prev= &first; } base_ilist() { empty(); } inline bool is_empty() { return first == &last; } + // Returns true if p is the last "real" object in the list, + // i.e. p->next points to the sentinel. + inline bool is_last(ilink *p) { return p->next == NULL || p->next == &last; } inline void append(ilink *a) { first->prev= &a->next; @@ -660,6 +663,7 @@ class I_List :private base_ilist { public: I_List() :base_ilist() {} + inline bool is_last(T *p) { return base_ilist::is_last(p); } inline void empty() { base_ilist::empty(); } inline bool is_empty() { return base_ilist::is_empty(); } inline void append(T* a) { base_ilist::append(a); } -- cgit v1.2.1