Merge zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.0-enterprise-formergecomm

into  zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-unified02


BitKeeper/etc/collapsed:
  auto-union
configure.in:
  Auto merged
BitKeeper/deleted/.del-CMakeLists.txt~3:
  Auto merged
BitKeeper/deleted/.del-ha_berkeley.cc:
  Auto merged
client/mysqlcheck.c:
  Auto merged
include/config-win.h:
  Auto merged
libmysqld/Makefile.am:
  Auto merged
mysql-test/r/func_in.result:
  Auto merged
mysql-test/r/mysqlcheck.result:
  Auto merged
mysql-test/t/func_in.test:
  Auto merged
mysql-test/t/information_schema.test:
  Auto merged
mysql-test/t/mysqlcheck.test:
  Auto merged
sql/ha_ndbcluster.cc:
  Auto merged
sql/item_cmpfunc.cc:
  Auto merged
sql/item_func.cc:
  Auto merged
sql/log_event.cc:
  Auto merged
sql/repl_failsafe.cc:
  Auto merged
sql/set_var.h:
  Auto merged
sql/sp_head.cc:
  Auto merged
sql/sql_cache.cc:
  Auto merged
sql/sql_class.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_lex.cc:
  Auto merged
sql/sql_prepare.cc:
  Auto merged
sql/sql_repl.cc:
  Auto merged
sql/sql_view.cc:
  Auto merged
storage/myisam/ha_myisam.cc:
  Auto merged
storage/myisam/mi_open.c:
  Auto merged
storage/myisammrg/ha_myisammrg.cc:
  Auto merged
include/my_dbug.h:
  Manual merge.
mysql-test/r/information_schema.result:
  Manual merge.
mysql-test/r/information_schema_db.result:
  Manual merge.
mysql-test/r/mysqlshow.result:
  Manual merge.
sql/Makefile.am:
  Manual merge.
sql/lex.h:
  Manual merge.
sql/lock.cc:
  Manual merge.
sql/mysql_priv.h:
  Manual merge.
sql/mysqld.cc:
  Manual merge.
sql/set_var.cc:
  Manual merge.
sql/slave.cc:
  Manual merge.
sql/sql_base.cc:
  Manual merge.
sql/sql_delete.cc:
  Manual merge.
sql/sql_insert.cc:
  Manual merge.
sql/sql_lex.h:
  Manual merge.
sql/sql_parse.cc:
  Manual merge.
sql/sql_select.cc:
  Manual merge.
sql/sql_show.cc:
  Manual merge.
sql/sql_table.cc:
  Manual merge.
sql/sql_update.cc:
  Manual merge.
sql/sql_yacc.yy:
  Manual merge.
sql/structs.h:
  Manual merge.
sql/table.h:
  Manual merge.
storage/archive/ha_archive.cc:
  Manual merge.
storage/ndb/src/common/util/File.cpp:
  Manual merge.
storage/ndb/src/ndbapi/DictCache.cpp:
  Manual merge.
support-files/mysql.spec.sh:
  Manual merge.
This commit is contained in:
unknown 2007-04-27 16:45:01 -04:00
commit 4687fe01d7
48 changed files with 2285 additions and 192 deletions

View file

@ -38,9 +38,25 @@
459a70691aYIfU2ohV0a3P5iTLpO2A
459a7422KF_P7PuU3YQ5qG6ZLEVpiA
459a74e4nRcXppMSBYeQQ5efDkTADg
459c03b9N_mqF2XJKK6DwSrIt7e6_g
459c1965_BQMBzBO8S_gVqjTHYQrmw
459c2098XoAUsUn8N07IVRDD6CTM-A
459ea845XenN-uWqEM5LFvUT60tW_A
45ae6628gqKTsUFfnoNExadETVIkbA
45af88c9RIIJWPfBxs3o7zekI-ELPQ
45ba4faf2oqu6eR8fqecR3LfSNcYUg
45ba5238-NKl80QVXzdGo8hO9M75Xg
45c0fdfb2mz6NdOIsLenJtf6_ZelTA
45c38d90tNwOTSaYKHXd3ccLtnytlQ
45c390d6BbWrwyEi5T5VsWKYxl06Rg
45c39d31g0iik6UE_oTK5N55ry-ycA
45d1ffcd-r3v8A7uh92hQaMfQM9UPQ
45d21437Vg_-i4uOWyvzYWHESXDP6A
45da6370nnZlAAIieMCrXkxF9toOyQ
45da6551zUuplwxuqcT2fhRgceC0CQ
45db0d4bkGtxBk21sZFJgbCV1FcNRg
45db468b-DKE8kUTV42eYMYmk8_g9g
45dd21d1rVPnDfvZTNVHLalcjnbsZw
45ddaf15_Ld7IAEpUUP3FJjJ-oSEFg
45ddc763DodLG1BqH_wRBJXMbCSB5A
45ddc8282KnaNGuijqCTphlXV_eeog

View file

@ -472,14 +472,17 @@ static int process_all_tables_in_db(char *database)
{
MYSQL_RES *res;
MYSQL_ROW row;
uint num_columns;
LINT_INIT(res);
if (use_db(database))
return 1;
if (mysql_query(sock, "SHOW TABLE STATUS") ||
if (mysql_query(sock, "SHOW /*!50002 FULL*/ TABLES") ||
!((res= mysql_store_result(sock))))
return 1;
num_columns= mysql_num_fields(res);
if (opt_all_in_1)
{
/*
@ -502,12 +505,11 @@ static int process_all_tables_in_db(char *database)
}
for (end = tables + 1; (row = mysql_fetch_row(res)) ;)
{
/* Skip tables with an engine of NULL (probably a view). */
if (row[1])
{
end= fix_table_name(end, row[0]);
*end++= ',';
}
if ((num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
continue;
end= fix_table_name(end, row[0]);
*end++= ',';
}
*--end = 0;
if (tot_length)
@ -517,11 +519,12 @@ static int process_all_tables_in_db(char *database)
else
{
while ((row = mysql_fetch_row(res)))
/* Skip tables with an engine of NULL (probably a view). */
if (row[1])
{
handle_request_for_tables(row[0], strlen(row[0]));
}
{
if ((num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
continue;
handle_request_for_tables(row[0], strlen(row[0]));
}
}
mysql_free_result(res);
return 0;

View file

@ -12,6 +12,7 @@ AC_CANONICAL_SYSTEM
# in mysqlbinlog::check_master_version().
AM_INIT_AUTOMAKE(mysql, 5.1.18-beta)
AM_CONFIG_HEADER(config.h)
is_this_community_tree=no
PROTOCOL_VERSION=10
DOT_FRM_VERSION=6
@ -578,6 +579,23 @@ then
fi
fi
AC_MSG_CHECKING(whether features provided by the user community should be included.)
AC_ARG_ENABLE(community-features,
AC_HELP_STRING(
[--enable-community-features],
[Enable additional features provided by the user community.]),
[ ENABLE_COMMUNITY_FEATURES=$enableval ],
[ ENABLE_COMMUNITY_FEATURES=$is_this_community_tree ]
)
if test "$ENABLE_COMMUNITY_FEATURES" = "yes"
then
AC_DEFINE([COMMUNITY_SERVER], [1],
[Whether features provided by the user community should be included])
AC_MSG_RESULT([yes, community server])
else
AC_MSG_RESULT([no, enterprise server])
fi
AC_ARG_WITH(server-suffix,
[ --with-server-suffix Append value to the version string.],
@ -641,6 +659,27 @@ else
AC_MSG_RESULT([no])
fi
# Add query profiler
AC_MSG_CHECKING(if SHOW PROFILE should be enabled.)
AC_ARG_ENABLE(profiling,
AS_HELP_STRING([--disable-profiling], [Build a version without query profiling code]),
[ ENABLED_PROFILING=$enableval ],
[ ENABLED_PROFILING=$is_this_community_tree ])
if test "$ENABLED_PROFILING" = "yes"
then
if test "$ENABLE_COMMUNITY_FEATURES" = "yes";
then
AC_DEFINE([ENABLED_PROFILING], [1],
[If SHOW PROFILE should be enabled])
AC_MSG_RESULT([yes])
else
ENABLED_PROFILING="no"
AC_MSG_RESULT([no, overridden by community-features disabled])
fi
else
AC_MSG_RESULT([no])
fi
# Use this to set the place used for unix socket used to local communication.
AC_ARG_WITH(unix-socket-path,
@ -745,6 +784,7 @@ AC_CHECK_FUNC(p2open, , AC_CHECK_LIB(gen, p2open))
AC_CHECK_FUNC(bind, , AC_CHECK_LIB(bind, bind))
# Check if crypt() exists in libc or libcrypt, sets LIBS if needed
AC_SEARCH_LIBS(crypt, crypt, AC_DEFINE(HAVE_CRYPT, 1, [crypt]))
AC_SEARCH_LIBS(inet_aton, [socket nsl resolv])
# For the sched_yield() function on Solaris
AC_CHECK_FUNC(sched_yield, , AC_CHECK_LIB(posix4, sched_yield))
@ -988,7 +1028,6 @@ case $SYSTEM_TYPE in
fi
;;
*darwin*)
AC_DEFINE([DEFAULT_SKIP_THREAD_PRIORITY], [1], [default to skip thread priority])
if test "$ac_cv_prog_gcc" = "yes"
then
FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT -DDONT_DECLARE_CXA_PURE_VIRTUAL"
@ -2457,15 +2496,13 @@ thread_dirs=
dnl This probably should be cleaned up more - for now the threaded
dnl client is just using plain-old libs.
sql_client_dirs=
sql_client_dirs="strings regex mysys libmysql client"
AM_CONDITIONAL(THREAD_SAFE_CLIENT, test "$THREAD_SAFE_CLIENT" != "no")
if test "$THREAD_SAFE_CLIENT" = "no"
if test "$THREAD_SAFE_CLIENT" != "no"
then
sql_client_dirs="strings regex mysys dbug extra libmysql client"
else
sql_client_dirs="strings regex mysys dbug extra libmysql libmysql_r client"
sql_client_dirs="libmysql_r $sql_client_dirs"
AC_CONFIG_FILES(libmysql_r/Makefile)
AC_DEFINE([THREAD_SAFE_CLIENT], [1], [Should the client be thread safe])
fi
@ -2487,17 +2524,13 @@ fi
AC_SUBST(netware_dir)
AM_CONDITIONAL(HAVE_NETWARE, test "$netware_dir" = "netware")
if test "$with_server" != "no" -o "$THREAD_SAFE_CLIENT" != "no"
if test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no"
then
AC_DEFINE([THREAD], [1],
[Define if you want to have threaded code. This may be undef on client code])
# Avoid _PROGRAMS names
THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o mf_keycache.o"
AC_SUBST(THREAD_LOBJECTS)
fi
if test "$with_server" != "no"
then
server_scripts="mysqld_safe mysql_install_db"
sql_server_dirs="strings mysys dbug extra regex"

View file

@ -206,6 +206,9 @@ typedef uint rf_SetTimer;
/* If LOAD DATA LOCAL INFILE should be enabled by default */
#define ENABLED_LOCAL_INFILE 1
/* If query profiling should be enabled by default */
#define ENABLED_PROFILING 1
/* Convert some simple functions to Posix */
#define my_sigset(A,B) signal((A),(B))

View file

@ -59,6 +59,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
protocol.cc net_serv.cc opt_range.cc \
opt_sum.cc procedure.cc records.cc sql_acl.cc \
sql_load.cc discover.cc sql_locale.cc \
sql_profile.cc \
sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc \

View file

@ -0,0 +1,4 @@
-- require r/profiling.require
disable_query_log;
show variables like "profiling";
enable_query_log;

View file

@ -50,6 +50,7 @@ KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
PROCESSLIST
PROFILING
REFERENTIAL_CONSTRAINTS
ROUTINES
SCHEMATA
@ -852,7 +853,7 @@ delete from mysql.db where user='mysqltest_4';
flush privileges;
SELECT table_schema, count(*) FROM information_schema.TABLES where table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
table_schema count(*)
information_schema 27
information_schema 28
mysql 22
create table t1 (i int, j int);
create trigger trg1 before insert on t1 for each row
@ -1146,7 +1147,7 @@ table_schema='information_schema' and
group by column_type order by num;
column_type group_concat(table_schema, '.', table_name) num
varchar(7) information_schema.ROUTINES,information_schema.VIEWS 2
varchar(20) information_schema.COLUMNS,information_schema.FILES,information_schema.FILES,information_schema.PLUGINS,information_schema.PLUGINS,information_schema.PLUGINS 6
varchar(20) information_schema.COLUMNS,information_schema.FILES,information_schema.FILES,information_schema.PLUGINS,information_schema.PLUGINS,information_schema.PLUGINS,information_schema.PROFILING 7
create table t1(f1 char(1) not null, f2 char(9) not null)
default character set utf8;
select CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH from
@ -1251,6 +1252,7 @@ KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
PROCESSLIST ID
PROFILING QUERY_ID
REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA
ROUTINES ROUTINE_SCHEMA
SCHEMATA SCHEMA_NAME
@ -1293,6 +1295,7 @@ KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
PROCESSLIST ID
PROFILING QUERY_ID
REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA
ROUTINES ROUTINE_SCHEMA
SCHEMATA SCHEMA_NAME
@ -1386,6 +1389,7 @@ KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
PARTITIONS information_schema.PARTITIONS 1
PLUGINS information_schema.PLUGINS 1
PROCESSLIST information_schema.PROCESSLIST 1
PROFILING information_schema.PROFILING 1
REFERENTIAL_CONSTRAINTS information_schema.REFERENTIAL_CONSTRAINTS 1
ROUTINES information_schema.ROUTINES 1
SCHEMATA information_schema.SCHEMATA 1
@ -1399,6 +1403,13 @@ TABLE_PRIVILEGES information_schema.TABLE_PRIVILEGES 1
TRIGGERS information_schema.TRIGGERS 1
USER_PRIVILEGES information_schema.USER_PRIVILEGES 1
VIEWS information_schema.VIEWS 1
show global status like "Uptime_%";
Variable_name Value
Uptime_since_flush_status #
flush status;
show global status like "Uptime_%";
Variable_name Value
Uptime_since_flush_status #
End of 5.0 tests.
select * from information_schema.engines WHERE ENGINE="MyISAM";
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS

View file

@ -19,6 +19,7 @@ KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
PROCESSLIST
PROFILING
REFERENTIAL_CONSTRAINTS
ROUTINES
SCHEMATA

View file

@ -57,4 +57,39 @@ test.t1 OK
test.t1 OK
drop view v1;
drop table t1;
create database d_bug25347;
use d_bug25347;
create table t_bug25347 (a int);
create view v_bug25347 as select * from t_bug25347;
insert into t_bug25347 values (1),(2),(3);
flush tables;
removing and creating
d_bug25347.t_bug25347
error : Incorrect file format 't_bug25347'
insert into t_bug25347 values (4),(5),(6);
ERROR HY000: Incorrect file format 't_bug25347'
d_bug25347.t_bug25347
warning : Number of rows changed from 0 to 3
status : OK
insert into t_bug25347 values (7),(8),(9);
select * from t_bug25347;
a
1
2
3
7
8
9
select * from v_bug25347;
a
1
2
3
7
8
9
drop view v_bug25347;
drop table t_bug25347;
drop database d_bug25347;
use test;
End of 5.0 tests

View file

@ -93,6 +93,7 @@ Database: information_schema
| PARTITIONS |
| PLUGINS |
| PROCESSLIST |
| PROFILING |
| REFERENTIAL_CONSTRAINTS |
| ROUTINES |
| SCHEMATA |
@ -125,6 +126,7 @@ Database: INFORMATION_SCHEMA
| PARTITIONS |
| PLUGINS |
| PROCESSLIST |
| PROFILING |
| REFERENTIAL_CONSTRAINTS |
| ROUTINES |
| SCHEMATA |

View file

@ -0,0 +1,2 @@
Variable_name Value
profiling OFF

View file

@ -0,0 +1,364 @@
show session variables like 'profil%';
Variable_name Value
profiling OFF
profiling_history_size 15
select @@profiling;
@@profiling
0
set global profiling = ON;
ERROR HY000: Variable 'profiling' is a SESSION variable and can't be used with SET GLOBAL
set global profiling_history_size=100;
show global variables like 'profil%';
Variable_name Value
profiling OFF
profiling_history_size 100
set session profiling = ON;
set session profiling_history_size=30;
show session variables like 'profil%';
Variable_name Value
profiling ON
profiling_history_size 30
select @@profiling;
@@profiling
1
create table t1 (
a int,
b int
);
insert into t1 values (1,1), (2,null), (3, 4);
insert into t1 values (5,1), (6,null), (7, 4);
insert into t1 values (1,1), (2,null), (3, 4);
insert into t1 values (5,1), (6,null), (7, 4);
select max(x) from (select sum(a) as x from t1 group by b) as teeone;
max(x)
20
insert into t1 select * from t1;
select count(*) from t1;
count(*)
24
insert into t1 select * from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
select count(*) from t1;
count(*)
192
insert into t1 select * from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
select count(*) from t1;
count(*)
1536
select sum(a) from t1;
sum(a)
6144
select sum(a) from t1 group by b;
sum(a)
2048
1536
2560
select sum(a) + sum(b) from t1 group by b;
sum(a) + sum(b)
NULL
2048
4608
select max(x) from (select sum(a) as x from t1 group by b) as teeone;
max(x)
2560
select '012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890' as big_string;
big_string
012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890
show profiles;
Query_ID Duration Query
1 # set session profiling_history_size=30
2 # show session variables like 'profil%'
3 # select @@profiling
4 # create table t1 (
a int,
b int
)
5 # insert into t1 values (1,1), (2,null), (3, 4)
6 # insert into t1 values (5,1), (6,null), (7, 4)
7 # insert into t1 values (1,1), (2,null), (3, 4)
8 # insert into t1 values (5,1), (6,null), (7, 4)
9 # select max(x) from (select sum(a) as x from t1 group by b) as teeone
10 # insert into t1 select * from t1
11 # select count(*) from t1
12 # insert into t1 select * from t1
13 # insert into t1 select * from t1
14 # insert into t1 select * from t1
15 # select count(*) from t1
16 # insert into t1 select * from t1
17 # insert into t1 select * from t1
18 # insert into t1 select * from t1
19 # select count(*) from t1
20 # select sum(a) from t1
21 # select sum(a) from t1 group by b
22 # select sum(a) + sum(b) from t1 group by b
23 # select max(x) from (select sum(a) as x from t1 group by b) as teeone
24 # select '0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345
show profile for query 15;
show profile cpu for query 15;
show profile cpu, block io for query 15;
show profile cpu for query 9 limit 2 offset 2;
show profile cpu for query 10 limit 0;
show profile cpu for query 65534;
show profile memory;
show profile block io;
show profile context switches;
show profile page faults;
show profile ipc;
show profile swaps limit 1 offset 2;
show profile source;
show profile all for query 0 limit 0;
show profile all for query 15;
select * from information_schema.profiling;
select query_id, state, duration from information_schema.profiling;
select query_id, sum(duration) from information_schema.profiling group by query_id;
select query_id, count(*) from information_schema.profiling group by query_id;
select sum(duration) from information_schema.profiling;
select query_id, count(*), sum(duration) from information_schema.profiling group by query_id;
select CPU_user, CPU_system, Context_voluntary, Context_involuntary, Block_ops_in, Block_ops_out, Messages_sent, Messages_received, Page_faults_major, Page_faults_minor, Swaps, Source_function, Source_file, Source_line from information_schema.profiling;
drop table if exists t1, t2, t3;
Warnings:
Note 1051 Unknown table 't2'
Note 1051 Unknown table 't3'
create table t1 (id int );
create table t2 (id int not null);
create table t3 (id int not null primary key);
insert into t1 values (1), (2), (3);
insert into t2 values (1), (2), (3);
insert into t3 values (1), (2), (3);
show profiles;
Query_ID Duration Query
10 # insert into t1 select * from t1
11 # select count(*) from t1
12 # insert into t1 select * from t1
13 # insert into t1 select * from t1
14 # insert into t1 select * from t1
15 # select count(*) from t1
16 # insert into t1 select * from t1
17 # insert into t1 select * from t1
18 # insert into t1 select * from t1
19 # select count(*) from t1
20 # select sum(a) from t1
21 # select sum(a) from t1 group by b
22 # select sum(a) + sum(b) from t1 group by b
23 # select max(x) from (select sum(a) as x from t1 group by b) as teeone
24 # select '0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345
25 # select * from information_schema.profiling
26 # select query_id, state, duration from information_schema.profiling
27 # select query_id, sum(duration) from information_schema.profiling group by query_id
28 # select query_id, count(*) from information_schema.profiling group by query_id
29 # select sum(duration) from information_schema.profiling
30 # select query_id, count(*), sum(duration) from information_schema.profiling group by query_id
31 # select CPU_user, CPU_system, Context_voluntary, Context_involuntary, Block_ops_in, Block_ops_out, Messages_sent, Messages_received, Page_faults_major, Page_faults_minor, Swaps, Source_function, Source_file, Source_line from information_schema.profiling
32 # drop table if exists t1, t2, t3
33 # SHOW WARNINGS
34 # create table t1 (id int )
35 # create table t2 (id int not null)
36 # create table t3 (id int not null primary key)
37 # insert into t1 values (1), (2), (3)
38 # insert into t2 values (1), (2), (3)
39 # insert into t3 values (1), (2), (3)
select * from t1;
id
1
2
3
show profiles;
Query_ID Duration Query
11 # select count(*) from t1
12 # insert into t1 select * from t1
13 # insert into t1 select * from t1
14 # insert into t1 select * from t1
15 # select count(*) from t1
16 # insert into t1 select * from t1
17 # insert into t1 select * from t1
18 # insert into t1 select * from t1
19 # select count(*) from t1
20 # select sum(a) from t1
21 # select sum(a) from t1 group by b
22 # select sum(a) + sum(b) from t1 group by b
23 # select max(x) from (select sum(a) as x from t1 group by b) as teeone
24 # select '0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345
25 # select * from information_schema.profiling
26 # select query_id, state, duration from information_schema.profiling
27 # select query_id, sum(duration) from information_schema.profiling group by query_id
28 # select query_id, count(*) from information_schema.profiling group by query_id
29 # select sum(duration) from information_schema.profiling
30 # select query_id, count(*), sum(duration) from information_schema.profiling group by query_id
31 # select CPU_user, CPU_system, Context_voluntary, Context_involuntary, Block_ops_in, Block_ops_out, Messages_sent, Messages_received, Page_faults_major, Page_faults_minor, Swaps, Source_function, Source_file, Source_line from information_schema.profiling
32 # drop table if exists t1, t2, t3
33 # SHOW WARNINGS
34 # create table t1 (id int )
35 # create table t2 (id int not null)
36 # create table t3 (id int not null primary key)
37 # insert into t1 values (1), (2), (3)
38 # insert into t2 values (1), (2), (3)
39 # insert into t3 values (1), (2), (3)
40 # select * from t1
This ^^ should end in "select * from t1;"
delete from t1;
insert into t1 values (1), (2), (3);
insert into t1 values (1), (2), (3);
select * from t1;
id
1
2
3
1
2
3
show profiles;
Query_ID Duration Query
15 # select count(*) from t1
16 # insert into t1 select * from t1
17 # insert into t1 select * from t1
18 # insert into t1 select * from t1
19 # select count(*) from t1
20 # select sum(a) from t1
21 # select sum(a) from t1 group by b
22 # select sum(a) + sum(b) from t1 group by b
23 # select max(x) from (select sum(a) as x from t1 group by b) as teeone
24 # select '0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345
25 # select * from information_schema.profiling
26 # select query_id, state, duration from information_schema.profiling
27 # select query_id, sum(duration) from information_schema.profiling group by query_id
28 # select query_id, count(*) from information_schema.profiling group by query_id
29 # select sum(duration) from information_schema.profiling
30 # select query_id, count(*), sum(duration) from information_schema.profiling group by query_id
31 # select CPU_user, CPU_system, Context_voluntary, Context_involuntary, Block_ops_in, Block_ops_out, Messages_sent, Messages_received, Page_faults_major, Page_faults_minor, Swaps, Source_function, Source_file, Source_line from information_schema.profiling
32 # drop table if exists t1, t2, t3
33 # SHOW WARNINGS
34 # create table t1 (id int )
35 # create table t2 (id int not null)
36 # create table t3 (id int not null primary key)
37 # insert into t1 values (1), (2), (3)
38 # insert into t2 values (1), (2), (3)
39 # insert into t3 values (1), (2), (3)
40 # select * from t1
41 # delete from t1
42 # insert into t1 values (1), (2), (3)
43 # insert into t1 values (1), (2), (3)
44 # select * from t1
set session profiling = OFF;
select sum(id) from t1;
sum(id)
12
show profiles;
Query_ID Duration Query
15 # select count(*) from t1
16 # insert into t1 select * from t1
17 # insert into t1 select * from t1
18 # insert into t1 select * from t1
19 # select count(*) from t1
20 # select sum(a) from t1
21 # select sum(a) from t1 group by b
22 # select sum(a) + sum(b) from t1 group by b
23 # select max(x) from (select sum(a) as x from t1 group by b) as teeone
24 # select '0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345
25 # select * from information_schema.profiling
26 # select query_id, state, duration from information_schema.profiling
27 # select query_id, sum(duration) from information_schema.profiling group by query_id
28 # select query_id, count(*) from information_schema.profiling group by query_id
29 # select sum(duration) from information_schema.profiling
30 # select query_id, count(*), sum(duration) from information_schema.profiling group by query_id
31 # select CPU_user, CPU_system, Context_voluntary, Context_involuntary, Block_ops_in, Block_ops_out, Messages_sent, Messages_received, Page_faults_major, Page_faults_minor, Swaps, Source_function, Source_file, Source_line from information_schema.profiling
32 # drop table if exists t1, t2, t3
33 # SHOW WARNINGS
34 # create table t1 (id int )
35 # create table t2 (id int not null)
36 # create table t3 (id int not null primary key)
37 # insert into t1 values (1), (2), (3)
38 # insert into t2 values (1), (2), (3)
39 # insert into t3 values (1), (2), (3)
40 # select * from t1
41 # delete from t1
42 # insert into t1 values (1), (2), (3)
43 # insert into t1 values (1), (2), (3)
44 # select * from t1
set session profiling = ON;
select @@profiling;
@@profiling
1
create function f1() returns varchar(50) return 'hello';
select @@profiling;
@@profiling
1
select * from t1 where id <> f1();
id
1
2
3
1
2
3
select @@profiling;
@@profiling
1
set session profiling = ON;
drop table if exists t2;
create table t2 (id int not null);
create trigger t2_bi before insert on t2 for each row set @x=0;
select @@profiling;
@@profiling
1
insert into t2 values (1), (2), (3);
select @@profiling;
@@profiling
1
set session profiling = ON;
drop table if exists t1, t2;
create table t1 (id int not null primary key);
create table t2 (id int not null primary key, id1 int not null);
select @@profiling;
@@profiling
1
alter table t2 add foreign key (id1) references t1 (id) on delete cascade;
select @@profiling;
@@profiling
1
lock table t1 write;
select @@profiling;
@@profiling
1
unlock table;
select @@profiling;
@@profiling
1
set autocommit=0;
select @@profiling, @@autocommit;
@@profiling @@autocommit
1 0
begin;
select @@profiling;
@@profiling
1
insert into t1 values (1);
insert into t2 values (1,1);
testing referential integrity cascade
delete from t1 where id = 1;
select @@profiling;
@@profiling
1
testing rollback
rollback;
select @@profiling;
@@profiling
1
testing commit
begin;
select @@profiling;
@@profiling
1
commit;
select @@profiling;
@@profiling
1
drop table if exists t1, t2, t3;
drop view if exists v1;
Warnings:
Note 1051 Unknown table 'test.v1'
drop function if exists f1;
set session profiling = OFF;
End of 5.0 tests

View file

@ -1023,6 +1023,14 @@ where t.table_schema = 'information_schema' and
(c2.column_type = 'varchar(7)' or c2.column_type = 'varchar(20)')
group by c2.column_type order by num limit 1)
group by t.table_name order by num1, t.table_name;
# Bug#24822: Patch: uptime_since_flush_status
#
--replace_column 2 #
show global status like "Uptime_%";
flush status;
--replace_column 2 #
show global status like "Uptime_%"; # Almost certainly zero
--echo End of 5.0 tests.
#

View file

@ -37,4 +37,29 @@ create view v1 as select * from t1;
drop view v1;
drop table t1;
#
# Bug#25347: mysqlcheck -A -r doesn't repair table marked as crashed
#
create database d_bug25347;
use d_bug25347;
create table t_bug25347 (a int);
create view v_bug25347 as select * from t_bug25347;
insert into t_bug25347 values (1),(2),(3);
flush tables;
--echo removing and creating
--remove_file $MYSQLTEST_VARDIR/master-data/d_bug25347/t_bug25347.MYI
--write_file $MYSQLTEST_VARDIR/master-data/d_bug25347/t_bug25347.MYI EOF
EOF
--exec $MYSQL_CHECK --repair --databases d_bug25347
--error 130
insert into t_bug25347 values (4),(5),(6);
--exec $MYSQL_CHECK --repair --use-frm --databases d_bug25347
insert into t_bug25347 values (7),(8),(9);
select * from t_bug25347;
select * from v_bug25347;
drop view v_bug25347;
drop table t_bug25347;
drop database d_bug25347;
use test;
--echo End of 5.0 tests

197
mysql-test/t/profiling.test Normal file
View file

@ -0,0 +1,197 @@
--source include/profiling.inc
# default is OFF
show session variables like 'profil%';
select @@profiling;
# setting global variable is an error
--error ER_LOCAL_VARIABLE
set global profiling = ON;
# But size is okay
set global profiling_history_size=100;
show global variables like 'profil%';
# turn on for testing
set session profiling = ON;
set session profiling_history_size=30; # small enough to overflow
# verify it is active
show session variables like 'profil%';
select @@profiling;
# Profiling is a descriptive look into the way the server operated
# in retrospect. Chad doesn't think it's wise to include the result
# log, as this creates a proscriptive specification about how the
# server should work in the future -- or it forces everyone who
# changes the server significantly to record the test results again,
# and that violates the spirit of our tests. Please don't include
# execution-specific data here, as in all of the "show profile" and
# information_schema.profiling results.
create table t1 (
a int,
b int
);
insert into t1 values (1,1), (2,null), (3, 4);
insert into t1 values (5,1), (6,null), (7, 4);
insert into t1 values (1,1), (2,null), (3, 4);
insert into t1 values (5,1), (6,null), (7, 4);
select max(x) from (select sum(a) as x from t1 group by b) as teeone;
insert into t1 select * from t1;
select count(*) from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
select count(*) from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
select count(*) from t1;
select sum(a) from t1;
select sum(a) from t1 group by b;
select sum(a) + sum(b) from t1 group by b;
select max(x) from (select sum(a) as x from t1 group by b) as teeone;
select '012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890' as big_string;
--enable_result_log
--replace_column 2 #
show profiles;
--disable_result_log
###--replace_column 2 # 3 # 4 #
show profile for query 15;
###--replace_column 2 # 3 # 4 #
show profile cpu for query 15;
###--replace_column 2 # 3 # 4 # 5 # 6 #
show profile cpu, block io for query 15;
###--replace_column 2 # 3 # 4 #
show profile cpu for query 9 limit 2 offset 2;
show profile cpu for query 10 limit 0;
--error 0,ER_WRONG_ARGUMENTS
show profile cpu for query 65534;
###--replace_column 2 #
show profile memory;
###--replace_column 2 # 3 # 4 #
show profile block io;
###--replace_column 2 # 3 # 4 #
show profile context switches;
###--replace_column 2 # 3 # 4 #
show profile page faults;
###--replace_column 2 # 3 # 4 #
show profile ipc;
###--replace_column 2 #
show profile swaps limit 1 offset 2;
###--replace_column 2 # 5 #
show profile source;
show profile all for query 0 limit 0;
###--replace_column 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 # 10 # 11 # 12 # 13 # 16 #
show profile all for query 15;
###--replace_column 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 # 10 # 11 # 12 # 13 # 16 #
select * from information_schema.profiling;
select query_id, state, duration from information_schema.profiling;
select query_id, sum(duration) from information_schema.profiling group by query_id;
select query_id, count(*) from information_schema.profiling group by query_id;
select sum(duration) from information_schema.profiling;
# Broken down into number of stages and duration of each query.
select query_id, count(*), sum(duration) from information_schema.profiling group by query_id;
select CPU_user, CPU_system, Context_voluntary, Context_involuntary, Block_ops_in, Block_ops_out, Messages_sent, Messages_received, Page_faults_major, Page_faults_minor, Swaps, Source_function, Source_file, Source_line from information_schema.profiling;
--enable_result_log
drop table if exists t1, t2, t3;
create table t1 (id int );
create table t2 (id int not null);
create table t3 (id int not null primary key);
insert into t1 values (1), (2), (3);
insert into t2 values (1), (2), (3);
insert into t3 values (1), (2), (3);
--replace_column 2 #
show profiles;
select * from t1;
--replace_column 2 #
show profiles;
--echo This ^^ should end in "select * from t1;"
delete from t1;
insert into t1 values (1), (2), (3);
insert into t1 values (1), (2), (3);
select * from t1;
--replace_column 2 #
show profiles;
# Turning profiling off does freeze it
set session profiling = OFF;
select sum(id) from t1;
--replace_column 2 #
show profiles;
## Verify that the various juggling of THD contexts doesn't affect profiling.
## Functions
set session profiling = ON;
select @@profiling;
create function f1() returns varchar(50) return 'hello';
select @@profiling;
select * from t1 where id <> f1();
select @@profiling;
## Triggers
set session profiling = ON;
drop table if exists t2;
create table t2 (id int not null);
create trigger t2_bi before insert on t2 for each row set @x=0;
select @@profiling;
insert into t2 values (1), (2), (3);
select @@profiling;
## ALTER TABLE
set session profiling = ON;
drop table if exists t1, t2;
create table t1 (id int not null primary key);
create table t2 (id int not null primary key, id1 int not null);
select @@profiling;
alter table t2 add foreign key (id1) references t1 (id) on delete cascade;
select @@profiling;
## Table LOCKing
lock table t1 write;
select @@profiling;
unlock table;
select @@profiling;
## Transactions
set autocommit=0;
select @@profiling, @@autocommit;
begin;
select @@profiling;
insert into t1 values (1);
insert into t2 values (1,1);
--echo testing referential integrity cascade
delete from t1 where id = 1;
select @@profiling;
--echo testing rollback
--disable_warnings
rollback;
--enable_warnings
select @@profiling;
--echo testing commit
begin;
select @@profiling;
commit;
select @@profiling;
drop table if exists t1, t2, t3;
drop view if exists v1;
drop function if exists f1;
## last thing in the file
set session profiling = OFF;
##
--echo End of 5.0 tests

View file

@ -48,6 +48,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
procedure.h sql_class.h sql_lex.h sql_list.h \
sql_map.h sql_string.h unireg.h \
sql_error.h field.h handler.h mysqld_suffix.h \
sql_profile.h \
ha_partition.h \
ha_ndbcluster.h ha_ndbcluster_binlog.h \
ha_ndbcluster_tables.h rpl_constants.h \
@ -83,6 +84,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
sql_connect.cc scheduler.cc sql_parse.cc \
set_var.cc sql_yacc.yy \
sql_base.cc table.cc sql_select.cc sql_insert.cc \
sql_profile.cc \
sql_prepare.cc sql_error.cc sql_locale.cc \
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
procedure.cc sql_test.cc \

View file

@ -3228,7 +3228,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
Structure is now initialized. Try to get the lock.
Set up control struct to allow others to abort locks
*/
thd->proc_info="User lock";
thd_proc_info(thd, "User lock");
thd->mysys_var->current_mutex= &LOCK_user_locks;
thd->mysys_var->current_cond= &ull->cond;
@ -3253,7 +3253,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
}
pthread_mutex_unlock(&LOCK_user_locks);
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->proc_info=0;
thd_proc_info(thd, 0);
thd->mysys_var->current_mutex= 0;
thd->mysys_var->current_cond= 0;
pthread_mutex_unlock(&thd->mysys_var->mutex);
@ -3334,7 +3334,7 @@ longlong Item_func_get_lock::val_int()
Structure is now initialized. Try to get the lock.
Set up control struct to allow others to abort locks.
*/
thd->proc_info="User lock";
thd_proc_info(thd, "User lock");
thd->mysys_var->current_mutex= &LOCK_user_locks;
thd->mysys_var->current_cond= &ull->cond;
@ -3372,7 +3372,7 @@ longlong Item_func_get_lock::val_int()
pthread_mutex_unlock(&LOCK_user_locks);
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->proc_info=0;
thd_proc_info(thd, 0);
thd->mysys_var->current_mutex= 0;
thd->mysys_var->current_cond= 0;
pthread_mutex_unlock(&thd->mysys_var->mutex);

View file

@ -84,6 +84,7 @@ static SYMBOL symbols[] = {
{ "BINLOG", SYM(BINLOG_SYM)},
{ "BIT", SYM(BIT_SYM)},
{ "BLOB", SYM(BLOB_SYM)},
{ "BLOCK", SYM(BLOCK_SYM)},
{ "BOOL", SYM(BOOL_SYM)},
{ "BOOLEAN", SYM(BOOLEAN_SYM)},
{ "BOTH", SYM(BOTH)},
@ -124,9 +125,11 @@ static SYMBOL symbols[] = {
{ "CONSISTENT", SYM(CONSISTENT_SYM)},
{ "CONSTRAINT", SYM(CONSTRAINT)},
{ "CONTAINS", SYM(CONTAINS_SYM)},
{ "CONTEXT", SYM(CONTEXT_SYM)},
{ "CONTINUE", SYM(CONTINUE_SYM)},
{ "CONTRIBUTORS", SYM(CONTRIBUTORS_SYM)},
{ "CONVERT", SYM(CONVERT_SYM)},
{ "CPU", SYM(CPU_SYM)},
{ "CREATE", SYM(CREATE)},
{ "CROSS", SYM(CROSS)},
{ "CUBE", SYM(CUBE_SYM)},
@ -198,6 +201,7 @@ static SYMBOL symbols[] = {
{ "EXTENT_SIZE", SYM(EXTENT_SIZE_SYM)},
{ "FALSE", SYM(FALSE_SYM)},
{ "FAST", SYM(FAST_SYM)},
{ "FAULTS", SYM(FAULTS_SYM)},
{ "FETCH", SYM(FETCH_SYM)},
{ "FIELDS", SYM(COLUMNS)},
{ "FILE", SYM(FILE_SYM)},
@ -260,7 +264,9 @@ static SYMBOL symbols[] = {
{ "INTEGER", SYM(INT_SYM)},
{ "INTERVAL", SYM(INTERVAL_SYM)},
{ "INTO", SYM(INTO)},
{ "IO", SYM(IO_SYM)},
{ "IO_THREAD", SYM(RELAY_THREAD)},
{ "IPC", SYM(IPC_SYM)},
{ "IS", SYM(IS)},
{ "ISOLATION", SYM(ISOLATION)},
{ "ISSUER", SYM(ISSUER_SYM)},
@ -400,6 +406,8 @@ static SYMBOL symbols[] = {
{ "PROCEDURE", SYM(PROCEDURE)},
{ "PROCESS" , SYM(PROCESS)},
{ "PROCESSLIST", SYM(PROCESSLIST_SYM)},
{ "PROFILE", SYM(PROFILE_SYM)},
{ "PROFILES", SYM(PROFILES_SYM)},
{ "PURGE", SYM(PURGE)},
{ "QUARTER", SYM(QUARTER_SYM)},
{ "QUERY", SYM(QUERY_SYM)},
@ -474,6 +482,7 @@ static SYMBOL symbols[] = {
{ "SOME", SYM(ANY_SYM)},
{ "SONAME", SYM(SONAME_SYM)},
{ "SOUNDS", SYM(SOUNDS_SYM)},
{ "SOURCE", SYM(SOURCE_SYM)},
{ "SPATIAL", SYM(SPATIAL_SYM)},
{ "SPECIFIC", SYM(SPECIFIC_SYM)},
{ "SQL", SYM(SQL_SYM)},
@ -510,6 +519,8 @@ static SYMBOL symbols[] = {
{ "SUBPARTITIONS", SYM(SUBPARTITIONS_SYM)},
{ "SUPER", SYM(SUPER_SYM)},
{ "SUSPEND", SYM(SUSPEND_SYM)},
{ "SWAPS", SYM(SWAPS_SYM)},
{ "SWITCHES", SYM(SWITCHES_SYM)},
{ "TABLE", SYM(TABLE_SYM)},
{ "TABLES", SYM(TABLES)},
{ "TABLESPACE", SYM(TABLESPACE)},

View file

@ -167,7 +167,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
break;
}
thd->proc_info="System lock";
thd_proc_info(thd, "System lock");
DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info));
if (lock_external(thd, tables, count))
{
@ -177,7 +177,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
sql_lock=0;
break;
}
thd->proc_info="Table lock";
thd_proc_info(thd, "Table lock");
DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info));
thd->locked=1;
/* Copy the lock data array. thr_multi_lock() reorders its contens. */
@ -212,7 +212,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
thd->locked=0;
break;
}
thd->proc_info=0;
thd_proc_info(thd, 0);
/* some table was altered or deleted. reopen tables marked deleted */
mysql_unlock_tables(thd,sql_lock);
@ -227,7 +227,7 @@ retry:
if (wait_for_tables(thd))
break; // Couldn't open tables
}
thd->proc_info=0;
thd_proc_info(thd, 0);
if (thd->killed)
{
thd->send_kill_message();

View file

@ -4793,7 +4793,7 @@ int Create_file_log_event::do_apply_event(RELAY_LOG_INFO const *rli)
bzero((char*)&file, sizeof(file));
fname_buf= strmov(proc_info, "Making temp file ");
ext= slave_load_file_stem(fname_buf, file_id, server_id, ".info");
thd->proc_info= proc_info;
thd_proc_info(thd, proc_info);
my_delete(fname_buf, MYF(0)); // old copy may exist already
if ((fd= my_create(fname_buf, CREATE_MODE,
O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
@ -4843,7 +4843,7 @@ err:
end_io_cache(&file);
if (fd >= 0)
my_close(fd, MYF(0));
thd->proc_info= 0;
thd_proc_info(thd, 0);
return error == 0;
}
#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
@ -4964,7 +4964,7 @@ int Append_block_log_event::do_apply_event(RELAY_LOG_INFO const *rli)
fname= strmov(proc_info, "Making temp file ");
slave_load_file_stem(fname, file_id, server_id, ".data");
thd->proc_info= proc_info;
thd_proc_info(thd, proc_info);
if (get_create_or_append())
{
my_delete(fname, MYF(0)); // old copy may exist already
@ -4998,7 +4998,7 @@ int Append_block_log_event::do_apply_event(RELAY_LOG_INFO const *rli)
err:
if (fd >= 0)
my_close(fd, MYF(0));
thd->proc_info= 0;
thd_proc_info(thd, 0);
DBUG_RETURN(error);
}
#endif

View file

@ -194,6 +194,8 @@ MY_LOCALE *my_locale_by_number(uint number);
#define BDB_LOG_ALLOC_BLOCK_SIZE 1024
#define WARN_ALLOC_BLOCK_SIZE 2048
#define WARN_ALLOC_PREALLOC_SIZE 1024
#define PROFILE_ALLOC_BLOCK_SIZE 2048
#define PROFILE_ALLOC_PREALLOC_SIZE 1024
/*
The following parameters is to decide when to use an extra cache to
@ -356,6 +358,8 @@ MY_LOCALE *my_locale_by_number(uint number);
fulltext functions when reading from it.
*/
#define TMP_TABLE_FORCE_MYISAM (ULL(1) << 32)
#define OPTION_PROFILING (ULL(1) << 33)
/*
@ -548,7 +552,14 @@ inline THD *_current_thd(void)
/* below functions are required for plugins as THD class is opaque */
my_bool thd_in_lock_tables(const THD *thd);
my_bool thd_tablespace_op(const THD *thd);
const char *thd_proc_info(THD *thd, const char *info);
/**
The meat of thd_proc_info(THD*, char*), a macro that packs the last
three calling-info parameters.
*/
const char *set_thd_proc_info(THD *thd, const char *info,
const char *calling_func,
const char *calling_file,
const unsigned int calling_line);
void **thd_ha_data(const THD *thd, const struct handlerton *hton);
/*
@ -572,6 +583,7 @@ typedef my_bool (*qc_engine_callback)(THD *thd, char *table_key,
#include "field.h" /* Field definitions */
#include "protocol.h"
#include "sql_udf.h"
#include "sql_profile.h"
#include "sql_partition.h"
class user_var_entry;
@ -1597,7 +1609,7 @@ extern int creating_table; // How many mysql_create_table() are running
External variables
*/
extern time_t server_start_time;
extern time_t server_start_time, flush_status_time;
extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[],
def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];

View file

@ -514,7 +514,7 @@ const char *log_output_str= "TABLE";
double log_10[32]; /* 10 potences */
double log_01[32];
time_t server_start_time;
time_t server_start_time, flush_status_time;
char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
char *default_tz_name;
@ -2720,7 +2720,7 @@ static int init_common_variables(const char *conf_file_name, int argc,
tzset(); // Set tzname
max_system_variables.pseudo_thread_id= (ulong)~0;
server_start_time= time((time_t*) 0);
server_start_time= flush_status_time= time((time_t*) 0);
rpl_filter= new Rpl_filter;
binlog_filter= new Rpl_filter;
if (!rpl_filter || !binlog_filter)
@ -5048,6 +5048,7 @@ enum options_mysqld
OPT_PLUGIN_DIR,
OPT_LOG_OUTPUT,
OPT_PORT_OPEN_TIMEOUT,
OPT_PROFILING,
OPT_GENERAL_LOG,
OPT_SLOW_LOG,
OPT_MERGE,
@ -5688,6 +5689,12 @@ Disable with --skip-ndbcluster (will save memory).",
"Maximum time in seconds to wait for the port to become free. "
"(Default: no wait)", (gptr*) &mysqld_port_timeout,
(gptr*) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
{"profiling_history_size", OPT_PROFILING, "Limit of query profiling memory",
(gptr*) &global_system_variables.profiling_history_size,
(gptr*) &max_system_variables.profiling_history_size,
0, GET_ULONG, REQUIRED_ARG, 15, 0, 100, 0, 0, 0},
#endif
{"relay-log", OPT_RELAY_LOG,
"The location and name to use for relay logs.",
(gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0,
@ -6522,6 +6529,14 @@ static int show_starttime(THD *thd, SHOW_VAR *var, char *buff)
return 0;
}
static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff)
{
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (long) (thd->query_start() - flush_status_time);
return 0;
}
#ifdef HAVE_REPLICATION
static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff)
{
@ -7074,6 +7089,7 @@ SHOW_VAR status_vars[]= {
{"Threads_created", (char*) &thread_created, SHOW_LONG_NOFLUSH},
{"Threads_running", (char*) &thread_running, SHOW_INT},
{"Uptime", (char*) &show_starttime, SHOW_FUNC},
{"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_FUNC},
{NullS, NullS, SHOW_LONG}
};
@ -8346,6 +8362,9 @@ void refresh_status(THD *thd)
/* Reset the counters of all key caches (default and named). */
process_key_caches(reset_key_cache_counters);
#ifdef COMMUNITY_SERVER
flush_status_time= time((time_t*) 0);
#endif
pthread_mutex_unlock(&LOCK_status);
/*

View file

@ -91,7 +91,7 @@ static int init_failsafe_rpl_thread(THD* thd)
if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options|= OPTION_BIG_SELECTS;
thd->proc_info="Thread initialized";
thd_proc_info(thd, "Thread initialized");
thd->version=refresh_version;
thd->set_time();
DBUG_RETURN(0);
@ -599,7 +599,7 @@ pthread_handler_t handle_failsafe_rpl(void *arg)
{
bool break_req_chain = 0;
pthread_cond_wait(&COND_rpl_status, &LOCK_rpl_status);
thd->proc_info="Processing request";
thd_proc_info(thd, "Processing request");
while (!break_req_chain)
{
switch (rpl_status) {
@ -947,7 +947,7 @@ bool load_master_data(THD* thd)
goto err;
}
}
thd->proc_info="purging old relay logs";
thd_proc_info(thd, "purging old relay logs");
if (purge_relay_logs(&active_mi->rli,thd,
0 /* not only reset, but also reinit */,
&errmsg))
@ -974,7 +974,7 @@ bool load_master_data(THD* thd)
flush_relay_log_info(&active_mi->rli);
pthread_cond_broadcast(&active_mi->rli.data_cond);
pthread_mutex_unlock(&active_mi->rli.data_lock);
thd->proc_info = "starting slave";
thd_proc_info(thd, "starting slave");
if (restart_thread_mask)
{
error=start_slave_threads(0 /* mutex not needed */,
@ -986,7 +986,7 @@ bool load_master_data(THD* thd)
err:
unlock_slave_threads(active_mi);
pthread_mutex_unlock(&LOCK_active_mi);
thd->proc_info = 0;
thd_proc_info(thd, 0);
mysql_close(&mysql); // safe to call since we always do mysql_init()
if (!error)

View file

@ -629,6 +629,12 @@ static sys_var_thd_bit sys_unique_checks("unique_checks", 0,
set_option_bit,
OPTION_RELAXED_UNIQUE_CHECKS,
1);
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
static sys_var_thd_bit sys_profiling("profiling", NULL, set_option_bit,
ulonglong(OPTION_PROFILING));
static sys_var_thd_ulong sys_profiling_history_size("profiling_history_size",
&SV::profiling_history_size);
#endif
/* Local state variables */
@ -957,6 +963,10 @@ SHOW_VAR init_vars[]= {
{"plugin_dir", (char*) opt_plugin_dir, SHOW_CHAR},
{"port", (char*) &mysqld_port, SHOW_INT},
{sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS},
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
{sys_profiling.name, (char*) &sys_profiling, SHOW_SYS},
{sys_profiling_history_size.name, (char*) &sys_profiling_history_size, SHOW_SYS},
#endif
{"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size,
SHOW_SYS},

View file

@ -966,8 +966,8 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
/* Create the table. We do not want to log the "create table" statement */
save_options = thd->options;
thd->options &= ~(ulong) (OPTION_BIN_LOG);
thd->proc_info = "Creating table from master dump";
thd->options &= ~ (OPTION_BIN_LOG);
thd_proc_info(thd, "Creating table from master dump");
// save old db in case we are creating in a different database
save_db = thd->db;
save_db_length= thd->db_length;
@ -982,7 +982,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
if (thd->query_error)
goto err; // mysql_parse took care of the error send
thd->proc_info = "Opening master dump table";
thd_proc_info(thd, "Opening master dump table");
tables.lock_type = TL_WRITE;
if (!open_ltable(thd, &tables, TL_WRITE))
{
@ -991,7 +991,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
}
file = tables.table->file;
thd->proc_info = "Reading master dump table data";
thd_proc_info(thd, "Reading master dump table data");
/* Copy the data file */
if (file->net_read_dump(net))
{
@ -1003,7 +1003,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
check_opt.init();
check_opt.flags|= T_VERY_SILENT | T_CALC_CHECKSUM | T_QUICK;
thd->proc_info = "Rebuilding the index on master dump table";
thd_proc_info(thd, "Rebuilding the index on master dump table");
/*
We do not want repair() to spam us with messages
just send them to the error log, and report the failure in case of
@ -1455,9 +1455,9 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
}
if (thd_type == SLAVE_THD_SQL)
thd->proc_info= "Waiting for the next event in relay log";
thd_proc_info(thd, "Waiting for the next event in relay log");
else
thd->proc_info= "Waiting for master update";
thd_proc_info(thd, "Waiting for master update");
thd->version=refresh_version;
thd->set_time();
DBUG_RETURN(0);
@ -1980,7 +1980,7 @@ pthread_handler_t handle_slave_io(void *arg)
goto err;
}
thd->proc_info = "Connecting to master";
thd_proc_info(thd, "Connecting to master");
// we can get killed during safe_connect
if (!safe_connect(thd, mysql, mi))
{
@ -2007,7 +2007,7 @@ connected:
// TODO: the assignment below should be under mutex (5.0)
mi->slave_running= MYSQL_SLAVE_RUN_CONNECT;
thd->slave_net = &mysql->net;
thd->proc_info = "Checking master version";
thd_proc_info(thd, "Checking master version");
if (get_master_version_and_clock(mysql, mi))
goto err;
@ -2018,7 +2018,7 @@ connected:
If fails, this is not fatal - we just print the error message and go
on with life.
*/
thd->proc_info = "Registering slave on master";
thd_proc_info(thd, "Registering slave on master");
if (register_slave_on_master(mysql) || update_slave_list(mysql, mi))
goto err;
}
@ -2027,7 +2027,7 @@ connected:
while (!io_slave_killed(thd,mi))
{
bool suppress_warnings= 0;
thd->proc_info = "Requesting binlog dump";
thd_proc_info(thd, "Requesting binlog dump");
if (request_dump(mysql, mi, &suppress_warnings))
{
sql_print_error("Failed on request_dump()");
@ -2039,7 +2039,7 @@ dump");
}
mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT;
thd->proc_info= "Waiting to reconnect after a failed binlog dump request";
thd_proc_info(thd, "Waiting to reconnect after a failed binlog dump request");
#ifdef SIGNAL_WITH_VIO_CLOSE
thd->clear_active_vio();
#endif
@ -2063,7 +2063,7 @@ dump");
goto err;
}
thd->proc_info = "Reconnecting after a failed binlog dump request";
thd_proc_info(thd, "Reconnecting after a failed binlog dump request");
if (!suppress_warnings)
sql_print_error("Slave I/O thread: failed dump request, \
reconnecting to try again, log '%s' at postion %s", IO_RPL_LOG_NAME,
@ -2089,7 +2089,7 @@ after reconnect");
important thing is to not confuse users by saying "reading" whereas
we're in fact receiving nothing.
*/
thd->proc_info= "Waiting for master to send event";
thd_proc_info(thd, "Waiting for master to send event");
event_len= read_event(mysql, mi, &suppress_warnings);
if (io_slave_killed(thd,mi))
{
@ -2117,7 +2117,7 @@ max_allowed_packet",
goto err;
}
mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT;
thd->proc_info = "Waiting to reconnect after a failed master event read";
thd_proc_info(thd, "Waiting to reconnect after a failed master event read");
#ifdef SIGNAL_WITH_VIO_CLOSE
thd->clear_active_vio();
#endif
@ -2136,7 +2136,7 @@ max_allowed_packet",
reconnect after a failed read");
goto err;
}
thd->proc_info = "Reconnecting after a failed master event read";
thd_proc_info(thd, "Reconnecting after a failed master event read");
if (!suppress_warnings)
sql_print_information("Slave I/O thread: Failed reading log event, \
reconnecting to retry, log '%s' position %s", IO_RPL_LOG_NAME,
@ -2153,7 +2153,7 @@ reconnect done to recover from failed read");
} // if (event_len == packet_error)
retry_count=0; // ok event, reset retry counter
thd->proc_info = "Queueing master event to the relay log";
thd_proc_info(thd, "Queueing master event to the relay log");
if (queue_event(mi,(const char*)mysql->net.read_pos + 1,
event_len))
{
@ -2226,7 +2226,7 @@ err:
mi->mysql=0;
}
write_ignored_events_info_to_relay_log(thd, mi);
thd->proc_info = "Waiting for slave mutex on exit";
thd_proc_info(thd, "Waiting for slave mutex on exit");
pthread_mutex_lock(&mi->run_lock);
/* Forget the relay log's format */
@ -2396,7 +2396,7 @@ Slave SQL thread aborted. Can't execute init_slave query");
while (!sql_slave_killed(thd,rli))
{
thd->proc_info = "Reading event from the relay log";
thd_proc_info(thd, "Reading event from the relay log");
DBUG_ASSERT(rli->sql_thd == thd);
THD_CHECK_SENTRY(thd);
if (exec_relay_log_event(thd,rli))
@ -2482,7 +2482,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
thd->query= thd->db= thd->catalog= 0;
thd->query_length= thd->db_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->proc_info = "Waiting for slave mutex on exit";
thd_proc_info(thd, "Waiting for slave mutex on exit");
pthread_mutex_lock(&rli->run_lock);
/* We need data_lock, at least to wake up any waiting master_pos_wait() */
pthread_mutex_lock(&rli->data_lock);

View file

@ -2470,9 +2470,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
m_lex->unit.cleanup();
thd->proc_info="closing tables";
thd_proc_info(thd, "closing tables");
close_thread_tables(thd);
thd->proc_info= 0;
thd_proc_info(thd, 0);
if (m_lex->query_tables_own_last)
{

View file

@ -919,7 +919,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
*/
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
thd->proc_info="Flushing tables";
thd_proc_info(thd, "Flushing tables");
close_old_data_files(thd,thd->open_tables,1,1);
mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL,
@ -963,7 +963,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= 0;
thd->mysys_var->current_cond= 0;
thd->proc_info=0;
thd_proc_info(thd, 0);
pthread_mutex_unlock(&thd->mysys_var->mutex);
}
DBUG_RETURN(result);
@ -1234,7 +1234,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
good idea to turn off OPTION_TABLE_LOCK flag.
*/
DBUG_ASSERT(thd->lex->requires_prelocking());
thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
thd->options&= ~(OPTION_TABLE_LOCK);
}
DBUG_VOID_RETURN;
@ -1832,7 +1832,7 @@ void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond)
thd->mysys_var->current_mutex= mutex;
thd->mysys_var->current_cond= cond;
proc_info=thd->proc_info;
thd->proc_info="Waiting for table";
thd_proc_info(thd, "Waiting for table");
DBUG_ENTER("wait_for_condition");
if (!thd->killed)
(void) pthread_cond_wait(cond, mutex);
@ -1852,7 +1852,7 @@ void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond)
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= 0;
thd->mysys_var->current_cond= 0;
thd->proc_info= proc_info;
thd_proc_info(thd, proc_info);
pthread_mutex_unlock(&thd->mysys_var->mutex);
DBUG_VOID_RETURN;
}
@ -2665,7 +2665,7 @@ bool wait_for_tables(THD *thd)
bool result;
DBUG_ENTER("wait_for_tables");
thd->proc_info="Waiting for tables";
thd_proc_info(thd, "Waiting for tables");
pthread_mutex_lock(&LOCK_open);
while (!thd->killed)
{
@ -2681,12 +2681,12 @@ bool wait_for_tables(THD *thd)
else
{
/* Now we can open all tables without any interference */
thd->proc_info="Reopen tables";
thd_proc_info(thd, "Reopen tables");
thd->version= refresh_version;
result=reopen_tables(thd,0,0);
}
pthread_mutex_unlock(&LOCK_open);
thd->proc_info=0;
thd_proc_info(thd, 0);
DBUG_RETURN(result);
}
@ -3088,7 +3088,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
restart:
*counter= 0;
query_tables_last_own= 0;
thd->proc_info="Opening tables";
thd_proc_info(thd, "Opening tables");
/*
If we are not already executing prelocked statement and don't have
@ -3303,7 +3303,7 @@ process_view_routines:
}
err:
thd->proc_info=0;
thd_proc_info(thd, 0);
free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block
if (query_tables_last_own)
@ -3377,7 +3377,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
bool refresh;
DBUG_ENTER("open_ltable");
thd->proc_info="Opening table";
thd_proc_info(thd, "Opening table");
thd->current_tablenr= 0;
/* open_ltable can be used only for BASIC TABLEs */
table_list->required_type= FRMTYPE_TABLE;
@ -3411,7 +3411,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
table= 0;
}
}
thd->proc_info=0;
thd_proc_info(thd, 0);
DBUG_RETURN(table);
}
@ -3643,7 +3643,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
{
if (thd->lex->requires_prelocking())
{
thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
thd->options&= ~(OPTION_TABLE_LOCK);
thd->in_lock_tables=0;
}
DBUG_RETURN(-1);
@ -3676,7 +3676,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
ha_rollback_stmt(thd);
mysql_unlock_tables(thd, thd->locked_tables);
thd->locked_tables= 0;
thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
thd->options&= ~(OPTION_TABLE_LOCK);
DBUG_RETURN(-1);
}
}
@ -6757,7 +6757,7 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order)
List_iterator<Item_func_match> li(*(select_lex->ftfunc_list));
Item_func_match *ifm;
DBUG_PRINT("info",("Performing FULLTEXT search"));
thd->proc_info="FULLTEXT initialization";
thd_proc_info(thd, "FULLTEXT initialization");
while ((ifm=li++))
ifm->init_search(no_order);

View file

@ -665,6 +665,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
void query_cache_abort(NET *net)
{
DBUG_ENTER("query_cache_abort");
THD *thd= current_thd;
/* See the comment on double-check locking usage above. */
if (net->query_cache_query == 0)
@ -683,6 +684,7 @@ void query_cache_abort(NET *net)
net->query_cache_query);
if (query_block) // Test if changed by other thread
{
thd_proc_info(thd, "storing result in query cache");
DUMP(&query_cache);
BLOCK_LOCK_WR(query_block);
// The following call will remove the lock on query_block
@ -720,6 +722,7 @@ void query_cache_end_of_result(THD *thd)
query_block= ((Query_cache_block*) thd->net.query_cache_query);
if (query_block)
{
thd_proc_info(thd, "storing result in query cache");
DUMP(&query_cache);
BLOCK_LOCK_WR(query_block);
Query_cache_query *header= query_block->query();
@ -1092,6 +1095,8 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
DBUG_PRINT("qcache", ("No active database"));
}
thd_proc_info(thd, "checking query cache for query");
// fill all gaps between fields with 0 to get repeatable key
bzero(&flags, QUERY_CACHE_FLAGS_SIZE);
flags.client_long_flag= test(thd->client_capabilities & CLIENT_LONG_FLAG);
@ -1169,6 +1174,7 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
}
// Check access;
thd_proc_info(thd, "checking privileges on cached query");
block_table= query_block->table(0);
block_table_end= block_table+query_block->n_tables;
for (; block_table != block_table_end; block_table++)
@ -1261,6 +1267,7 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
Send cached result to client
*/
#ifndef EMBEDDED_LIBRARY
thd_proc_info(thd, "sending cached result to client");
do
{
DBUG_PRINT("qcache", ("Results (len: %lu used: %lu headers: %lu)",
@ -1338,9 +1345,11 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
{
THD *thd= current_thd;
DBUG_ENTER("Query_cache::invalidate (changed table list)");
if (tables_used)
{
thd_proc_info(thd, "invalidating query cache entries (table list)");
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size > 0 && !flush_in_progress)
{
@ -1371,9 +1380,11 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
*/
void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used)
{
THD *thd= current_thd;
DBUG_ENTER("Query_cache::invalidate_locked_for_write");
if (tables_used)
{
thd_proc_info(thd, "invalidating query cache entries (table)");
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size > 0 && !flush_in_progress)
{
@ -1423,6 +1434,7 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length,
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size > 0 && !flush_in_progress)
{
thd_proc_info(thd, "invalidating query cache entries (key)");
using_transactions= using_transactions &&
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
if (using_transactions) // used for innodb => has_transactions() is TRUE

View file

@ -289,6 +289,9 @@ THD::THD()
init();
/* Initialize sub structures */
init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
profiling.set_thd(this);
#endif
user_connect=(USER_CONN *)0;
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,

View file

@ -211,6 +211,7 @@ struct system_variables
ulong optimizer_prune_level;
ulong optimizer_search_depth;
ulong preload_buff_size;
ulong profiling_history_size;
ulong query_cache_type;
ulong read_buff_size;
ulong read_rnd_buff_size;
@ -968,6 +969,9 @@ public:
Points to info-string that we show in SHOW PROCESSLIST
You are supposed to update thd->proc_info only if you have coded
a time-consuming piece that MySQL can get stuck in for a long time.
Set it using the thd_proc_info(THD *thread, const char *message)
macro/function.
*/
const char *proc_info;
@ -1314,6 +1318,10 @@ public:
List <MYSQL_ERROR> warn_list;
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
uint total_warn_count;
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
PROFILING profiling;
#endif
/*
Id of current query. Statement can be reused to execute several queries
query_id is global in context of the whole MySQL server.

View file

@ -48,7 +48,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(TRUE);
}
thd->proc_info="init";
thd_proc_info(thd, "init");
table->map=1;
if (mysql_prepare_delete(thd, table_list, &conds))
@ -220,7 +220,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
init_read_record_idx(&info, thd, table, 1, usable_index);
init_ftfuncs(thd, select_lex, 1);
thd->proc_info="updating";
thd_proc_info(thd, "updating");
if (table->triggers &&
table->triggers->has_triggers(TRG_EVENT_DELETE,
TRG_ACTION_AFTER))
@ -296,7 +296,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
table->file->print_error(loc_error,MYF(0));
error=1;
}
thd->proc_info= "end";
thd_proc_info(thd, "end");
end_read_record(&info);
if (options & OPTION_QUICK)
(void) table->file->extra(HA_EXTRA_NORMAL);
@ -539,7 +539,7 @@ multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
DBUG_ENTER("multi_delete::prepare");
unit= u;
do_delete= 1;
thd->proc_info="deleting from main table";
thd_proc_info(thd, "deleting from main table");
DBUG_RETURN(0);
}
@ -823,7 +823,7 @@ int multi_delete::do_deletes()
bool multi_delete::send_eof()
{
thd->proc_info="deleting from reference tables";
thd_proc_info(thd, "deleting from reference tables");
/* Does deletes for the last n - 1 tables, returns 0 if ok */
int local_error= do_deletes(); // returns 0 if success
@ -832,7 +832,7 @@ bool multi_delete::send_eof()
local_error= local_error || error;
/* reset used flags */
thd->proc_info="end";
thd_proc_info(thd, "end");
/*
We must invalidate the query cache before binlog writing and
@ -1014,7 +1014,7 @@ trunc_by_del:
/* Probably InnoDB table */
ulonglong save_options= thd->options;
table_list->lock_type= TL_WRITE;
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
thd->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
ha_enable_transaction(thd, FALSE);
mysql_init_select(thd->lex);
bool save_binlog_row_based= thd->current_stmt_binlog_row_based;

View file

@ -507,7 +507,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
if (res || thd->is_fatal_error)
DBUG_RETURN(TRUE);
thd->proc_info="init";
thd_proc_info(thd, "init");
thd->used_tables=0;
values= its++;
value_count= values->elements;
@ -591,7 +591,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
#endif
error=0;
thd->proc_info="update";
thd_proc_info(thd, "update");
if (duplic != DUP_ERROR || ignore)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
if (duplic == DUP_REPLACE &&
@ -777,7 +777,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->lock=0;
}
}
thd->proc_info="end";
thd_proc_info(thd, "end");
/*
We'll report to the client this id:
- if the table contains an autoincrement column and we successfully
@ -1600,7 +1600,7 @@ I_List<delayed_insert> delayed_threads;
delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list)
{
thd->proc_info="waiting for delay_list";
thd_proc_info(thd, "waiting for delay_list");
pthread_mutex_lock(&LOCK_delayed_insert); // Protect master list
I_List_iterator<delayed_insert> it(delayed_threads);
delayed_insert *tmp;
@ -1637,7 +1637,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
*/
if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads)
DBUG_RETURN(0);
thd->proc_info="Creating delayed handler";
thd_proc_info(thd, "Creating delayed handler");
pthread_mutex_lock(&LOCK_delayed_create);
/*
The first search above was done without LOCK_delayed_create.
@ -1679,13 +1679,13 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
}
/* Wait until table is open */
thd->proc_info="waiting for handler open";
thd_proc_info(thd, "waiting for handler open");
while (!tmp->thd.killed && !tmp->table && !thd->killed)
{
pthread_cond_wait(&tmp->cond_client,&tmp->mutex);
}
pthread_mutex_unlock(&tmp->mutex);
thd->proc_info="got old table";
thd_proc_info(thd, "got old table");
if (tmp->thd.killed)
{
if (tmp->thd.is_fatal_error)
@ -1747,13 +1747,13 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
tables_in_use++;
if (!thd.lock) // Table is not locked
{
client_thd->proc_info="waiting for handler lock";
thd_proc_info(client_thd, "waiting for handler lock");
pthread_cond_signal(&cond); // Tell handler to lock table
while (!dead && !thd.lock && ! client_thd->killed)
{
pthread_cond_wait(&cond_client,&mutex);
}
client_thd->proc_info="got handler lock";
thd_proc_info(client_thd, "got handler lock");
if (client_thd->killed)
goto error;
if (dead)
@ -1771,7 +1771,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
bytes. Since the table copy is used for creating one record only,
the other record buffers and alignment are unnecessary.
*/
client_thd->proc_info="allocating local table";
thd_proc_info(client_thd, "allocating local table");
copy= (TABLE*) client_thd->alloc(sizeof(*copy)+
(share->fields+1)*sizeof(Field**)+
share->reclength +
@ -1855,11 +1855,11 @@ write_delayed(THD *thd,TABLE *table, enum_duplicates duplic,
DBUG_ENTER("write_delayed");
DBUG_PRINT("enter", ("query = '%s' length %u", query.str, query.length));
thd->proc_info="waiting for handler insert";
thd_proc_info(thd, "waiting for handler insert");
pthread_mutex_lock(&di->mutex);
while (di->stacked_inserts >= delayed_queue_size && !thd->killed)
pthread_cond_wait(&di->cond_client,&di->mutex);
thd->proc_info="storing row into queue";
thd_proc_info(thd, "storing row into queue");
if (thd->killed)
goto err;
@ -2075,7 +2075,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
/* Information for pthread_kill */
di->thd.mysys_var->current_mutex= &di->mutex;
di->thd.mysys_var->current_cond= &di->cond;
di->thd.proc_info="Waiting for INSERT";
thd_proc_info(&(di->thd), "Waiting for INSERT");
DBUG_PRINT("info",("Waiting for someone to insert rows"));
while (!thd->killed)
@ -2110,7 +2110,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
pthread_mutex_unlock(&di->thd.mysys_var->mutex);
pthread_mutex_lock(&di->mutex);
}
di->thd.proc_info=0;
thd_proc_info(&(di->thd), 0);
if (di->tables_in_use && ! thd->lock)
{
@ -2251,7 +2251,7 @@ bool delayed_insert::handle_inserts(void)
table->next_number_field=table->found_next_number_field;
table->use_all_columns();
thd.proc_info="upgrading lock";
thd_proc_info(&thd, "upgrading lock");
if (thr_upgrade_write_delay_lock(*thd.lock->locks))
{
/* This can only happen if thread is killed by shutdown */
@ -2259,7 +2259,7 @@ bool delayed_insert::handle_inserts(void)
goto err;
}
thd.proc_info="insert";
thd_proc_info(&thd, "insert");
max_rows= delayed_insert_limit;
if (thd.killed || table->s->version != refresh_version)
{
@ -2391,7 +2391,7 @@ bool delayed_insert::handle_inserts(void)
{
if (tables_in_use)
pthread_cond_broadcast(&cond_client); // If waiting clients
thd.proc_info="reschedule";
thd_proc_info(&thd, "reschedule");
pthread_mutex_unlock(&mutex);
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
{
@ -2411,13 +2411,13 @@ bool delayed_insert::handle_inserts(void)
if (!using_bin_log)
table->file->extra(HA_EXTRA_WRITE_CACHE);
pthread_mutex_lock(&mutex);
thd.proc_info="insert";
thd_proc_info(&thd, "insert");
}
if (tables_in_use)
pthread_cond_broadcast(&cond_client); // If waiting clients
}
}
thd.proc_info=0;
thd_proc_info(&thd, 0);
pthread_mutex_unlock(&mutex);
/*

View file

@ -199,7 +199,7 @@ void lex_start(THD *thd, const char *buf, uint length)
lex->name.str= 0;
lex->name.length= 0;
lex->event_parse_data= NULL;
lex->profile_options= PROFILE_NONE;
lex->nest_level=0 ;
lex->allow_sum_func= 0;
lex->in_sum_func= NULL;

View file

@ -113,9 +113,13 @@ enum enum_sql_command {
SQLCOM_CREATE_SERVER, SQLCOM_DROP_SERVER, SQLCOM_ALTER_SERVER,
SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT,
SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS,
SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
/*
When a command is added here, be sure it's also added in mysqld.cc
in "struct show_var_st status_vars[]= {" ...
*/
/* This should be the last !!! */
SQLCOM_END
};
@ -1112,6 +1116,9 @@ typedef struct st_lex : public Query_tables_list
enum enum_var_type option_type;
enum enum_view_create_mode create_view_mode;
enum enum_drop_mode drop_mode;
uint profile_query_id;
uint profile_options;
uint uint_geom_type;
uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option;

View file

@ -110,7 +110,7 @@ bool end_active_trans(THD *thd)
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
OPTION_TABLE_LOCK))
{
DBUG_PRINT("info",("options: 0x%lx", (ulong) thd->options));
DBUG_PRINT("info",("options: 0x%llx", thd->options));
/* Safety if one did "drop table" on locked tables */
if (!thd->locked_tables)
thd->options&= ~OPTION_TABLE_LOCK;
@ -265,7 +265,7 @@ void execute_init_command(THD *thd, sys_var_str *init_command_var,
Vio* save_vio;
ulong save_client_capabilities;
thd->proc_info= "Execution of init_command";
thd_proc_info(thd, "Execution of init_command");
/*
We need to lock init_command_var because
during execution of init_command_var query
@ -321,7 +321,7 @@ pthread_handler_t handle_bootstrap(void *arg)
if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
thd->proc_info=0;
thd_proc_info(thd, 0);
thd->version=refresh_version;
thd->security_ctx->priv_user=
thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
@ -550,7 +550,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion)
*/
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
res= ha_commit(thd);
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_KEEP_LOG);
thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
thd->no_trans_update.all= FALSE;
break;
case COMMIT_RELEASE:
@ -568,7 +568,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion)
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (ha_rollback(thd))
res= -1;
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_KEEP_LOG);
thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
thd->no_trans_update.all= FALSE;
if (!res && (completion == ROLLBACK_AND_CHAIN))
res= begin_trans(thd);
@ -1257,7 +1257,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (thd->lock || thd->open_tables || thd->derived_tables ||
thd->prelocked_mode)
{
thd->proc_info="closing tables";
thd_proc_info(thd, "closing tables");
close_thread_tables(thd); /* Free tables */
}
/*
@ -1280,9 +1280,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
log_slow_statement(thd);
thd->proc_info="cleaning up";
thd_proc_info(thd, "cleaning up");
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list
thd->proc_info=0;
thd_proc_info(thd, 0);
thd->command=COM_SLEEP;
thd->query=0;
thd->query_length=0;
@ -1316,7 +1316,7 @@ void log_slow_statement(THD *thd)
*/
if (thd->enable_slow_log && !thd->user_time)
{
thd->proc_info="logging slow query";
thd_proc_info(thd, "logging slow query");
if ((ulong) (thd->start_time - thd->time_after_lock) >
thd->variables.long_query_time ||
@ -1324,6 +1324,7 @@ void log_slow_statement(THD *thd)
(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
(specialflag & SPECIAL_LOG_QUERIES_NOT_USING_INDEXES)))
{
thd_proc_info(thd, "logging slow query");
thd->status_var.long_query_count++;
slow_log_print(thd, thd->query, thd->query_length, start_of_query);
}
@ -1915,6 +1916,37 @@ mysql_execute_command(THD *thd)
(1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR));
break;
}
case SQLCOM_SHOW_PROFILES:
{
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.store();
thd->profiling.discard();
res= thd->profiling.show_profiles();
if (res)
goto error;
#else
my_error(ER_FEATURE_DISABLED, MYF(0), "SHOW PROFILES", "enable-profiling");
goto error;
#endif
break;
}
case SQLCOM_SHOW_PROFILE:
{
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.store();
thd->profiling.discard(); // will get re-enabled by reset()
if (lex->profile_query_id != 0)
res= thd->profiling.show(lex->profile_options, lex->profile_query_id);
else
res= thd->profiling.show_last(lex->profile_options);
if (res)
goto error;
#else
my_error(ER_FEATURE_DISABLED, MYF(0), "SHOW PROFILE", "enable-profiling");
goto error;
#endif
break;
}
case SQLCOM_SHOW_NEW_MASTER:
{
if (check_global_access(thd, REPL_SLAVE_ACL))
@ -2791,7 +2823,7 @@ end_with_restore_list:
if (add_item_to_list(thd, new Item_null()))
goto error;
thd->proc_info="init";
thd_proc_info(thd, "init");
if ((res= open_and_lock_tables(thd, all_tables)))
break;
@ -2965,7 +2997,7 @@ end_with_restore_list:
if (thd->options & OPTION_TABLE_LOCK)
{
end_active_trans(thd);
thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
thd->options&= ~(OPTION_TABLE_LOCK);
}
if (thd->global_read_lock)
unlock_global_read_lock(thd);
@ -2991,7 +3023,7 @@ end_with_restore_list:
send_ok(thd);
}
else
thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
thd->options&= ~(OPTION_TABLE_LOCK);
thd->in_lock_tables=0;
break;
case SQLCOM_CREATE_DB:
@ -4332,8 +4364,7 @@ create_sp_error:
send_ok(thd);
break;
}
thd->proc_info="query end";
thd_proc_info(thd, "query end");
/*
Binlog-related cleanup:
@ -4559,6 +4590,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
else
save_priv= &dummy;
thd_proc_info(thd, "checking permissions");
if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
{
DBUG_PRINT("error",("No database"));
@ -5053,6 +5085,9 @@ mysql_init_query(THD *thd, const char *buf, uint length)
DBUG_ENTER("mysql_init_query");
lex_start(thd, buf, length);
mysql_reset_thd_for_next_command(thd);
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.reset();
#endif
DBUG_VOID_RETURN;
}
@ -5112,6 +5147,9 @@ void mysql_reset_thd_for_next_command(THD *thd)
thd->total_warn_count=0; // Warnings for this query
thd->rand_used= 0;
thd->sent_row_count= thd->examined_row_count= 0;
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.reset();
#endif
}
/*
Because we come here only for start of top-statements, binlog format is
@ -5329,7 +5367,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
thd->lex->sphead= 0;
}
lex->unit.cleanup();
thd->proc_info="freeing items";
thd_proc_info(thd, "freeing items");
thd->end_statement();
thd->cleanup_after_query();
DBUG_ASSERT(thd->change_list.is_empty());

View file

@ -2271,6 +2271,9 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute")))
DBUG_VOID_RETURN;
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.set_query_source(stmt->query, stmt->query_length);
#endif
DBUG_PRINT("exec_query", ("%s", stmt->query));
DBUG_PRINT("info",("stmt: 0x%lx", (long) stmt));

804
sql/sql_profile.cc Normal file
View file

@ -0,0 +1,804 @@
/* Copyright (C) 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; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysql_priv.h"
#include "my_sys.h"
#define TIME_FLOAT_DIGITS 9
#define MAX_QUERY_LENGTH 300
bool schema_table_store_record(THD *thd, TABLE *table);
/* Reserved for systems that can't record the function name in source. */
const char * const _unknown_func_ = "<unknown>";
/**
Connects Information_Schema and Profiling.
*/
int fill_query_profile_statistics_info(THD *thd, struct st_table_list *tables,
Item *cond)
{
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
return(thd->profiling.fill_statistics_info(thd, tables, cond));
#else
return(1);
#endif
}
ST_FIELD_INFO query_profile_statistics_info[]=
{
/* name, length, type, value, maybe_null, old_name */
{"QUERY_ID", 20, MYSQL_TYPE_LONG, 0, false, NULL},
{"SEQ", 20, MYSQL_TYPE_LONG, 0, false, NULL},
{"STATE", 30, MYSQL_TYPE_STRING, 0, false, NULL},
{"DURATION", TIME_FLOAT_DIGITS, MYSQL_TYPE_DOUBLE, 0, false, NULL},
{"CPU_USER", TIME_FLOAT_DIGITS, MYSQL_TYPE_DOUBLE, 0, true, NULL},
{"CPU_SYSTEM", TIME_FLOAT_DIGITS, MYSQL_TYPE_DOUBLE, 0, true, NULL},
{"CONTEXT_VOLUNTARY", 20, MYSQL_TYPE_LONG, 0, true, NULL},
{"CONTEXT_INVOLUNTARY", 20, MYSQL_TYPE_LONG, 0, true, NULL},
{"BLOCK_OPS_IN", 20, MYSQL_TYPE_LONG, 0, true, NULL},
{"BLOCK_OPS_OUT", 20, MYSQL_TYPE_LONG, 0, true, NULL},
{"MESSAGES_SENT", 20, MYSQL_TYPE_LONG, 0, true, NULL},
{"MESSAGES_RECEIVED", 20, MYSQL_TYPE_LONG, 0, true, NULL},
{"PAGE_FAULTS_MAJOR", 20, MYSQL_TYPE_LONG, 0, true, NULL},
{"PAGE_FAULTS_MINOR", 20, MYSQL_TYPE_LONG, 0, true, NULL},
{"SWAPS", 20, MYSQL_TYPE_LONG, 0, true, NULL},
{"SOURCE_FUNCTION", 30, MYSQL_TYPE_STRING, 0, true, NULL},
{"SOURCE_FILE", 20, MYSQL_TYPE_STRING, 0, true, NULL},
{"SOURCE_LINE", 20, MYSQL_TYPE_LONG, 0, true, NULL},
{NULL, 0, MYSQL_TYPE_STRING, 0, true, NULL}
};
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
#define RUSAGE_USEC(tv) ((tv).tv_sec*1000*1000 + (tv).tv_usec)
#define RUSAGE_DIFF_USEC(tv1, tv2) (RUSAGE_USEC((tv1))-RUSAGE_USEC((tv2)))
PROFILE_ENTRY::PROFILE_ENTRY()
:profile(NULL), status(NULL), function(NULL), file(NULL), line(0),
time_usecs(0.0), allocated_status_memory(NULL)
{
collect();
/* The beginning of the query, before any state is set. */
set_status("(initialization)", NULL, NULL, 0);
}
PROFILE_ENTRY::PROFILE_ENTRY(QUERY_PROFILE *profile_arg, const char *status_arg)
:profile(profile_arg)
{
collect();
set_status(status_arg, NULL, NULL, 0);
}
PROFILE_ENTRY::PROFILE_ENTRY(QUERY_PROFILE *profile_arg, const char *status_arg,
const char *function_arg,
const char *file_arg, unsigned int line_arg)
:profile(profile_arg)
{
collect();
set_status(status_arg, function_arg, file_arg, line_arg);
}
PROFILE_ENTRY::~PROFILE_ENTRY()
{
if (allocated_status_memory != NULL)
my_free(allocated_status_memory, MYF(0));
status= function= file= NULL;
}
void PROFILE_ENTRY::set_status(const char *status_arg, const char *function_arg, const char *file_arg, unsigned int line_arg)
{
size_t sizes[3]; /* 3 == status+function+file */
char *cursor;
/*
Compute all the space we'll need to allocate one block for everything
we'll need, instead of N mallocs.
*/
sizes[0]= (status_arg == NULL) ? 0 : strlen(status_arg) + 1;
sizes[1]= (function_arg == NULL) ? 0 : strlen(function_arg) + 1;
sizes[2]= (file_arg == NULL) ? 0 : strlen(file_arg) + 1;
allocated_status_memory= (char *) my_malloc(sizes[0] + sizes[1] + sizes[2], MYF(0));
DBUG_ASSERT(allocated_status_memory != NULL);
cursor= allocated_status_memory;
if (status_arg != NULL)
{
strcpy(cursor, status_arg);
status= cursor;
cursor+= sizes[0];
}
else
status= NULL;
if (function_arg != NULL)
{
strcpy(cursor, function_arg);
function= cursor;
cursor+= sizes[1];
}
else
function= NULL;
if (file_arg != NULL)
{
strcpy(cursor, file_arg);
file= cursor;
cursor+= sizes[2];
}
else
file= NULL;
line= line_arg;
}
void PROFILE_ENTRY::collect()
{
time_usecs= (double) my_getsystime() / 10.0; /* 1 sec was 1e7, now is 1e6 */
#ifdef HAVE_GETRUSAGE
getrusage(RUSAGE_SELF, &rusage);
#endif
}
QUERY_PROFILE::QUERY_PROFILE(PROFILING *profiling_arg, char *query_source_arg,
uint query_length_arg)
:profiling(profiling_arg), server_query_id(0), profiling_query_id(0),
query_source(NULL)
{
profile_end= &profile_start;
set_query_source(query_source_arg, query_length_arg);
}
void QUERY_PROFILE::set_query_source(char *query_source_arg,
uint query_length_arg)
{
if (! profiling->enabled)
return;
/* Truncate to avoid DoS attacks. */
uint length= min(MAX_QUERY_LENGTH, query_length_arg);
/* TODO?: Provide a way to include the full text, as in SHOW PROCESSLIST. */
DBUG_ASSERT(query_source == NULL);
if (query_source_arg != NULL)
query_source= my_strdup_with_length(query_source_arg, length, MYF(0));
}
QUERY_PROFILE::~QUERY_PROFILE()
{
while (! entries.is_empty())
delete entries.pop();
if (query_source != NULL)
my_free(query_source, MYF(0));
}
void QUERY_PROFILE::status(const char *status_arg,
const char *function_arg= NULL,
const char *file_arg= NULL, unsigned int line_arg= 0)
{
THD *thd= profiling->thd;
PROFILE_ENTRY *prof;
DBUG_ENTER("QUERY_PROFILE::status");
/* Blank status. Just return, and thd->proc_info will be set blank later. */
if (unlikely(status_arg == NULL))
DBUG_VOID_RETURN;
/* If thd->proc_info is currently set to status_arg, don't profile twice. */
if (likely((thd->proc_info != NULL) &&
((thd->proc_info == status_arg) ||
(strcmp(thd->proc_info, status_arg) == 0))))
{
DBUG_VOID_RETURN;
}
/* Is this the same query as our profile currently contains? */
if (unlikely((thd->query_id != server_query_id) && !thd->spcont))
reset();
if (function_arg && file_arg)
{
if ((profile_end= prof= new PROFILE_ENTRY(this, status_arg, function_arg,
file_arg, line_arg)))
entries.push_back(prof);
}
else
{
if ((profile_end= prof= new PROFILE_ENTRY(this, status_arg)))
entries.push_back(prof);
}
DBUG_VOID_RETURN;
}
void QUERY_PROFILE::reset()
{
DBUG_ENTER("QUERY_PROFILE::reset");
if (likely(profiling->thd->query_id != server_query_id))
{
server_query_id= profiling->thd->query_id; /* despite name, is global */
profile_start.collect();
while (! entries.is_empty())
delete entries.pop();
}
DBUG_VOID_RETURN;
}
bool QUERY_PROFILE::show(uint options)
{
THD *thd= profiling->thd;
List<Item> field_list;
DBUG_ENTER("QUERY_PROFILE::show");
field_list.push_back(new Item_empty_string("Status", MYSQL_ERRMSG_SIZE));
field_list.push_back(new Item_return_int("Duration", TIME_FLOAT_DIGITS,
MYSQL_TYPE_DOUBLE));
if (options & PROFILE_CPU)
{
field_list.push_back(new Item_return_int("CPU_user", TIME_FLOAT_DIGITS,
MYSQL_TYPE_DOUBLE));
field_list.push_back(new Item_return_int("CPU_system", TIME_FLOAT_DIGITS,
MYSQL_TYPE_DOUBLE));
}
if (options & PROFILE_MEMORY)
{
}
if (options & PROFILE_CONTEXT)
{
field_list.push_back(new Item_return_int("Context_voluntary", 10,
MYSQL_TYPE_LONG));
field_list.push_back(new Item_return_int("Context_involuntary", 10,
MYSQL_TYPE_LONG));
}
if (options & PROFILE_BLOCK_IO)
{
field_list.push_back(new Item_return_int("Block_ops_in", 10,
MYSQL_TYPE_LONG));
field_list.push_back(new Item_return_int("Block_ops_out", 10,
MYSQL_TYPE_LONG));
}
if (options & PROFILE_IPC)
{
field_list.push_back(new Item_return_int("Messages_sent", 10,
MYSQL_TYPE_LONG));
field_list.push_back(new Item_return_int("Messages_received", 10,
MYSQL_TYPE_LONG));
}
if (options & PROFILE_PAGE_FAULTS)
{
field_list.push_back(new Item_return_int("Page_faults_major", 10,
MYSQL_TYPE_LONG));
field_list.push_back(new Item_return_int("Page_faults_minor", 10,
MYSQL_TYPE_LONG));
}
if (options & PROFILE_SWAPS)
{
field_list.push_back(new Item_return_int("Swaps", 10, MYSQL_TYPE_LONG));
}
if (options & PROFILE_SOURCE)
{
field_list.push_back(new Item_empty_string("Source_function",
MYSQL_ERRMSG_SIZE));
field_list.push_back(new Item_empty_string("Source_file",
MYSQL_ERRMSG_SIZE));
field_list.push_back(new Item_return_int("Source_line", 10,
MYSQL_TYPE_LONG));
}
if (thd->protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
Protocol *protocol= thd->protocol;
SELECT_LEX *sel= &thd->lex->select_lex;
SELECT_LEX_UNIT *unit= &thd->lex->unit;
ha_rows idx= 0;
unit->set_limit(sel);
PROFILE_ENTRY *previous= &profile_start;
PROFILE_ENTRY *entry;
void *iterator;
for (iterator= entries.new_iterator();
iterator != NULL;
iterator= entries.iterator_next(iterator))
{
entry= entries.iterator_value(iterator);
#ifdef HAVE_GETRUSAGE
struct rusage *rusage= &(entry->rusage);
#endif
String elapsed;
if (++idx <= unit->offset_limit_cnt)
continue;
if (idx > unit->select_limit_cnt)
break;
protocol->prepare_for_resend();
/*
This entry, n, has a point in time, T(n), and a status phrase, S(n). The
status phrase S(n) describes the period of time that begins at T(n). The
previous status phrase S(n-1) describes the period of time that starts at
T(n-1) and ends at T(n). Since we want to describe the time that a status
phrase took T(n)-T(n-1), this line must describe the previous status.
*/
protocol->store(previous->status, strlen(previous->status),
system_charset_info);
protocol->store((double)(entry->time_usecs -
previous->time_usecs)/(1000.0*1000),
(uint32) TIME_FLOAT_DIGITS-1, &elapsed);
if (options & PROFILE_CPU)
{
#ifdef HAVE_GETRUSAGE
String cpu_utime, cpu_stime;
protocol->store((double)(RUSAGE_DIFF_USEC(rusage->ru_utime,
previous->rusage.ru_utime))/(1000.0*1000),
(uint32) TIME_FLOAT_DIGITS-1, &cpu_utime);
protocol->store((double)(RUSAGE_DIFF_USEC(rusage->ru_stime,
previous->rusage.ru_stime))/(1000.0*1000),
(uint32) TIME_FLOAT_DIGITS-1, &cpu_stime);
#else
protocol->store_null();
protocol->store_null();
#endif
}
if (options & PROFILE_CONTEXT)
{
#ifdef HAVE_GETRUSAGE
protocol->store((uint32)(rusage->ru_nvcsw - previous->rusage.ru_nvcsw));
protocol->store((uint32)(rusage->ru_nivcsw - previous->rusage.ru_nivcsw));
#else
protocol->store_null();
protocol->store_null();
#endif
}
if (options & PROFILE_BLOCK_IO)
{
#ifdef HAVE_GETRUSAGE
protocol->store((uint32)(rusage->ru_inblock - previous->rusage.ru_inblock));
protocol->store((uint32)(rusage->ru_oublock - previous->rusage.ru_oublock));
#else
protocol->store_null();
protocol->store_null();
#endif
}
if (options & PROFILE_IPC)
{
#ifdef HAVE_GETRUSAGE
protocol->store((uint32)(rusage->ru_msgsnd - previous->rusage.ru_msgsnd));
protocol->store((uint32)(rusage->ru_msgrcv - previous->rusage.ru_msgrcv));
#else
protocol->store_null();
protocol->store_null();
#endif
}
if (options & PROFILE_PAGE_FAULTS)
{
#ifdef HAVE_GETRUSAGE
protocol->store((uint32)(rusage->ru_majflt - previous->rusage.ru_majflt));
protocol->store((uint32)(rusage->ru_minflt - previous->rusage.ru_minflt));
#else
protocol->store_null();
protocol->store_null();
#endif
}
if (options & PROFILE_SWAPS)
{
#ifdef HAVE_GETRUSAGE
protocol->store((uint32)(rusage->ru_nswap - previous->rusage.ru_nswap));
#else
protocol->store_null();
#endif
}
if (options & PROFILE_SOURCE)
{
if ((entry->function != NULL) && (entry->file != NULL))
{
protocol->store(entry->function, strlen(entry->function),
system_charset_info);
protocol->store(entry->file, strlen(entry->file), system_charset_info);
protocol->store((uint32) entry->line);
} else {
protocol->store_null();
protocol->store_null();
protocol->store_null();
}
}
if (protocol->write())
DBUG_RETURN(TRUE);
previous= entry;
}
send_eof(thd);
DBUG_RETURN(FALSE);
}
PROFILING::PROFILING()
:profile_id_counter(1), keeping(TRUE), enabled(FALSE), current(NULL), last(NULL)
{
}
PROFILING::~PROFILING()
{
while (! history.is_empty())
delete history.pop();
if (current != NULL)
delete current;
}
void PROFILING::status_change(const char *status_arg,
const char *function_arg,
const char *file_arg, unsigned int line_arg)
{
DBUG_ENTER("PROFILING::status_change");
if (unlikely(enabled))
{
if (unlikely(current == NULL))
reset();
DBUG_ASSERT(current != NULL);
current->status(status_arg, function_arg, file_arg, line_arg);
}
thd->proc_info= status_arg;
DBUG_VOID_RETURN;
}
void PROFILING::store()
{
DBUG_ENTER("PROFILING::store");
/* Already stored */
if (unlikely((last != NULL) &&
(current != NULL) &&
(last->server_query_id == current->server_query_id)))
{
DBUG_VOID_RETURN;
}
while (history.elements > thd->variables.profiling_history_size)
delete history.pop();
if (likely(((thd)->options & OPTION_PROFILING) == 0))
DBUG_VOID_RETURN;
if (current != NULL)
{
if (keeping &&
(enabled) && /* ON at start? */
(((thd)->options & OPTION_PROFILING) != 0) && /* and ON at end? */
(current->query_source != NULL) &&
(current->query_source[0] != '\0') &&
(!current->entries.is_empty()))
{
current->profiling_query_id= next_profile_id(); /* assign an id */
last= current; /* never contains something that is not in the history. */
history.push_back(current);
current= NULL;
}
else
{
delete current;
current= NULL;
}
}
DBUG_ASSERT(current == NULL);
if (enabled)
current= new QUERY_PROFILE(this, thd->query, thd->query_length);
DBUG_VOID_RETURN;
}
/**
Store and clean up the old information and get ready to hold info about this
new query. This is called very often so it must be very lightweight if
profiling is not active.
*/
void PROFILING::reset()
{
DBUG_ENTER("PROFILING::reset");
store();
if (likely(((thd)->options & OPTION_PROFILING) == 0))
{
enabled= FALSE;
DBUG_VOID_RETURN;
}
else
enabled= TRUE;
if (current != NULL)
current->reset();
keep();
DBUG_VOID_RETURN;
}
bool PROFILING::show_profiles()
{
DBUG_ENTER("PROFILING::show_profiles");
QUERY_PROFILE *prof;
List<Item> field_list;
field_list.push_back(new Item_return_int("Query_ID", 10,
MYSQL_TYPE_LONG));
field_list.push_back(new Item_return_int("Duration", TIME_FLOAT_DIGITS-1,
MYSQL_TYPE_DOUBLE));
field_list.push_back(new Item_empty_string("Query", 40));
if (thd->protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
SELECT_LEX *sel= &thd->lex->select_lex;
SELECT_LEX_UNIT *unit= &thd->lex->unit;
ha_rows idx= 0;
Protocol *protocol= thd->protocol;
unit->set_limit(sel);
void *iterator;
for (iterator= history.new_iterator();
iterator != NULL;
iterator= history.iterator_next(iterator))
{
prof= history.iterator_value(iterator);
String elapsed;
PROFILE_ENTRY *ps= &prof->profile_start;
PROFILE_ENTRY *pe= prof->profile_end;
if (++idx <= unit->offset_limit_cnt)
continue;
if (idx > unit->select_limit_cnt)
break;
protocol->prepare_for_resend();
protocol->store((uint32)(prof->profiling_query_id));
protocol->store((double)(pe->time_usecs - ps->time_usecs)/(1000.0*1000),
(uint32) TIME_FLOAT_DIGITS-1, &elapsed);
if (prof->query_source != NULL)
protocol->store(prof->query_source, strlen(prof->query_source),
system_charset_info);
else
protocol->store_null();
if (protocol->write())
DBUG_RETURN(TRUE);
}
send_eof(thd);
DBUG_RETURN(FALSE);
}
/*
This is an awful hack to let prepared statements tell us the query
that they're executing.
*/
void PROFILING::set_query_source(char *query_source_arg, uint query_length_arg)
{
DBUG_ENTER("PROFILING::set_query_source");
/* We can't get this query source through normal means. */
DBUG_ASSERT((thd->query == NULL) || (thd->query_length == 0));
if (current != NULL)
current->set_query_source(query_source_arg, query_length_arg);
else
DBUG_PRINT("info", ("no current profile to send query source to"));
DBUG_VOID_RETURN;
}
bool PROFILING::show(uint options, uint profiling_query_id)
{
DBUG_ENTER("PROFILING::show");
QUERY_PROFILE *prof;
void *iterator;
for (iterator= history.new_iterator();
iterator != NULL;
iterator= history.iterator_next(iterator))
{
prof= history.iterator_value(iterator);
if(prof->profiling_query_id == profiling_query_id)
DBUG_RETURN(prof->show(options));
}
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SHOW PROFILE");
DBUG_RETURN(TRUE);
}
bool PROFILING::show_last(uint options)
{
DBUG_ENTER("PROFILING::show_last");
if (!history.is_empty()) {
DBUG_RETURN(last->show(options));
}
DBUG_RETURN(TRUE);
}
/**
Fill the information schema table, "query_profile", as defined in show.cc .
*/
int PROFILING::fill_statistics_info(THD *thd, struct st_table_list *tables, Item *cond)
{
DBUG_ENTER("PROFILING::fill_statistics_info");
TABLE *table= tables->table;
ulonglong row_number= 0;
QUERY_PROFILE *query;
/* Go through each query in this thread's stored history... */
void *history_iterator;
for (history_iterator= history.new_iterator();
history_iterator != NULL;
history_iterator= history.iterator_next(history_iterator))
{
query= history.iterator_value(history_iterator);
PROFILE_ENTRY *previous= &(query->profile_start);
/*
Because we put all profiling info into a table that may be reordered, let
us also include a numbering of each state per query. The query_id and
the "seq" together are unique.
*/
ulonglong seq;
void *entry_iterator;
PROFILE_ENTRY *entry;
/* ...and for each query, go through all its state-change steps. */
for (seq= 0, entry_iterator= query->entries.new_iterator();
entry_iterator != NULL;
entry_iterator= query->entries.iterator_next(entry_iterator),
seq++, previous=entry, row_number++)
{
entry= query->entries.iterator_value(entry_iterator);
/* Set default values for this row. */
restore_record(table, s->default_values);
/*
The order of these fields is set by the query_profile_statistics_info
array.
*/
table->field[0]->store((ulonglong) query->profiling_query_id);
table->field[1]->store((ulonglong) seq); /* the step in the sequence */
/*
This entry, n, has a point in time, T(n), and a status phrase, S(n).
The status phrase S(n) describes the period of time that begins at
T(n). The previous status phrase S(n-1) describes the period of time
that starts at T(n-1) and ends at T(n). Since we want to describe the
time that a status phrase took T(n)-T(n-1), this line must describe the
previous status.
*/
table->field[2]->store(previous->status, strlen(previous->status),
system_charset_info);
table->field[3]->store((double)(entry->time_usecs -
previous->time_usecs)/(1000*1000));
#ifdef HAVE_GETRUSAGE
table->field[4]->store((double)RUSAGE_DIFF_USEC(entry->rusage.ru_utime,
previous->rusage.ru_utime)/(1000.0*1000));
table->field[4]->set_notnull();
table->field[5]->store((double)RUSAGE_DIFF_USEC(entry->rusage.ru_stime,
previous->rusage.ru_stime)/(1000.0*1000));
table->field[5]->set_notnull();
#else
/* TODO: Add CPU-usage info for non-BSD systems */
#endif
#ifdef HAVE_GETRUSAGE
table->field[6]->store((uint32)(entry->rusage.ru_nvcsw -
previous->rusage.ru_nvcsw));
table->field[6]->set_notnull();
table->field[7]->store((uint32)(entry->rusage.ru_nivcsw -
previous->rusage.ru_nivcsw));
table->field[7]->set_notnull();
#else
/* TODO: Add context switch info for non-BSD systems */
#endif
#ifdef HAVE_GETRUSAGE
table->field[8]->store((uint32)(entry->rusage.ru_inblock -
previous->rusage.ru_inblock));
table->field[8]->set_notnull();
table->field[9]->store((uint32)(entry->rusage.ru_oublock -
previous->rusage.ru_oublock));
table->field[9]->set_notnull();
#else
/* TODO: Add block IO info for non-BSD systems */
#endif
#ifdef HAVE_GETRUSAGE
table->field[10]->store((uint32)(entry->rusage.ru_msgsnd -
previous->rusage.ru_msgsnd), true);
table->field[10]->set_notnull();
table->field[11]->store((uint32)(entry->rusage.ru_msgrcv -
previous->rusage.ru_msgrcv), true);
table->field[11]->set_notnull();
#else
/* TODO: Add message info for non-BSD systems */
#endif
#ifdef HAVE_GETRUSAGE
table->field[12]->store((uint32)(entry->rusage.ru_majflt -
previous->rusage.ru_majflt), true);
table->field[12]->set_notnull();
table->field[13]->store((uint32)(entry->rusage.ru_minflt -
previous->rusage.ru_minflt), true);
table->field[13]->set_notnull();
#else
/* TODO: Add page fault info for non-BSD systems */
#endif
#ifdef HAVE_GETRUSAGE
table->field[14]->store((uint32)(entry->rusage.ru_nswap -
previous->rusage.ru_nswap), true);
table->field[14]->set_notnull();
#else
/* TODO: Add swap info for non-BSD systems */
#endif
if ((entry->function != NULL) && (entry->file != NULL))
{
table->field[15]->store(entry->function, strlen(entry->function),
system_charset_info);
table->field[15]->set_notnull();
table->field[16]->store(entry->file, strlen(entry->file), system_charset_info);
table->field[16]->set_notnull();
table->field[17]->store(entry->line, true);
table->field[17]->set_notnull();
}
if (schema_table_store_record(thd, table))
DBUG_RETURN(1);
}
}
DBUG_RETURN(0);
}
#endif /* ENABLED_PROFILING */

346
sql/sql_profile.h Normal file
View file

@ -0,0 +1,346 @@
/* Copyright (C) 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; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _SQL_PROFILE_H
#define _SQL_PROFILE_H
#if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2
# define __func__ __FUNCTION__
# else
# define __func__ _unknown_func_
extern const char * const _unknown_func_;
# endif
#elif defined(_MSC_VER)
# if _MSC_VER < 1300
# define __func__ _unknown_func_
extern const char * const _unknown_func_;
# else
# define __func__ __FUNCTION__
# endif
#elif defined(__BORLANDC__)
# define __func__ __FUNC__
#else
# define __func__ _unknown_func_
extern const char * const _unknown_func_;
#endif
extern ST_FIELD_INFO query_profile_statistics_info[];
int fill_query_profile_statistics_info(THD *thd, struct st_table_list *tables, Item *cond);
#define PROFILE_NONE 0
#define PROFILE_CPU (1<<0)
#define PROFILE_MEMORY (1<<1)
#define PROFILE_BLOCK_IO (1<<2)
#define PROFILE_CONTEXT (1<<3)
#define PROFILE_PAGE_FAULTS (1<<4)
#define PROFILE_IPC (1<<5)
#define PROFILE_SWAPS (1<<6)
#define PROFILE_SOURCE (1<<16)
#define PROFILE_ALL (~0)
#if !defined(ENABLED_PROFILING) || !defined(COMMUNITY_SERVER)
# define thd_proc_info(thd, msg) do { (thd)->proc_info= (msg); } while (0)
#else
# define thd_proc_info(thd, msg) \
do { \
if (unlikely(((thd)->options & OPTION_PROFILING) != 0)) \
{ \
(thd)->profiling.status_change((msg), __func__, __FILE__, __LINE__); \
} \
else \
{ \
(thd)->proc_info= (msg); \
} \
} while (0)
#include "mysql_priv.h"
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
class PROFILE_ENTRY;
class QUERY_PROFILE;
class PROFILING;
/**
Implements a persistent FIFO using server List method names. Not
thread-safe. Intended to be used on thread-local data only.
*/
template <class T> class Queue
{
private:
struct queue_item
{
T *payload;
struct queue_item *next, *previous;
};
struct queue_item *first, *last;
public:
Queue()
{
elements= 0;
first= last= NULL;
}
void empty()
{
struct queue_item *i, *after_i;
for (i= first; i != NULL; i= after_i)
{
after_i= i->next;
my_free((char *) i, MYF(0));
}
elements= 0;
}
ulong elements; /* The count of items in the Queue */
void push_back(T *payload)
{
struct queue_item *new_item;
new_item= (struct queue_item *) my_malloc(sizeof(struct queue_item), MYF(0));
new_item->payload= payload;
if (first == NULL)
first= new_item;
if (last != NULL)
{
DBUG_ASSERT(last->next == NULL);
last->next= new_item;
}
new_item->previous= last;
new_item->next= NULL;
last= new_item;
elements++;
}
T *pop()
{
struct queue_item *old_item= first;
T *ret= NULL;
if (first == NULL)
{
DBUG_PRINT("warning", ("tried to pop nonexistent item from Queue"));
return NULL;
}
ret= old_item->payload;
if (first->next != NULL)
first->next->previous= NULL;
else
last= NULL;
first= first->next;
my_free((char *)old_item, MYF(0));
elements--;
return ret;
}
bool is_empty()
{
DBUG_ASSERT(((elements > 0) && (first != NULL)) || ((elements == 0) || (first == NULL)));
return (elements == 0);
}
void *new_iterator()
{
return first;
}
void *iterator_next(void *current)
{
return ((struct queue_item *) current)->next;
}
T *iterator_value(void *current)
{
return ((struct queue_item *) current)->payload;
}
};
/**
A single entry in a single profile.
*/
class PROFILE_ENTRY
{
private:
friend class QUERY_PROFILE;
friend class PROFILING;
QUERY_PROFILE *profile;
char *status;
#ifdef HAVE_GETRUSAGE
struct rusage rusage;
#endif
char *function;
char *file;
unsigned int line;
double time_usecs;
char *allocated_status_memory;
void set_status(const char *status_arg, const char *function_arg,
const char *file_arg, unsigned int line_arg);
void clean_up();
PROFILE_ENTRY();
PROFILE_ENTRY(QUERY_PROFILE *profile_arg, const char *status_arg);
PROFILE_ENTRY(QUERY_PROFILE *profile_arg, const char *status_arg,
const char *function_arg,
const char *file_arg, unsigned int line_arg);
~PROFILE_ENTRY();
void collect();
};
/**
The full profile for a single query, and includes multiple PROFILE_ENTRY
objects.
*/
class QUERY_PROFILE
{
private:
friend class PROFILING;
PROFILING *profiling;
query_id_t server_query_id; /* Global id. */
query_id_t profiling_query_id; /* Session-specific id. */
char *query_source;
PROFILE_ENTRY profile_start;
PROFILE_ENTRY *profile_end;
Queue<PROFILE_ENTRY> entries;
QUERY_PROFILE(PROFILING *profiling_arg, char *query_source_arg, uint query_length_arg);
~QUERY_PROFILE();
void set_query_source(char *query_source_arg, uint query_length_arg);
/* Add a profile status change to the current profile. */
void status(const char *status_arg,
const char *function_arg,
const char *file_arg, unsigned int line_arg);
/* Reset the contents of this profile entry. */
void reset();
/* Show this profile. This is called by PROFILING. */
bool show(uint options);
};
/**
Profiling state for a single THD; contains multiple QUERY_PROFILE objects.
*/
class PROFILING
{
private:
friend class PROFILE_ENTRY;
friend class QUERY_PROFILE;
/*
Not the system query_id, but a counter unique to profiling.
*/
query_id_t profile_id_counter;
THD *thd;
bool keeping;
bool enabled;
QUERY_PROFILE *current;
QUERY_PROFILE *last;
Queue<QUERY_PROFILE> history;
query_id_t next_profile_id() { return(profile_id_counter++); }
public:
PROFILING();
~PROFILING();
void set_query_source(char *query_source_arg, uint query_length_arg);
/** Reset the current profile and state of profiling for the next query. */
void reset();
/**
Do we intend to keep the currently collected profile?
We don't keep profiles for some commands, such as SHOW PROFILE, SHOW
PROFILES, and some SQLCOM commands which aren't useful to profile. The
keep() and discard() functions can be called many times, only the final
setting when the query finishes is used to decide whether to discard the
profile.
The default is to keep the profile for all queries.
*/
inline void keep() { keeping= true; };
/**
Do we intend to keep the currently collected profile?
@see keep()
*/
inline void discard() { keeping= false; };
/**
Stash this profile in the profile history and remove the oldest
profile if the history queue is full, as defined by the
profiling_history_size system variable.
*/
void store();
/**
Called with every update of the status via thd_proc_info() , and is
therefore the main hook into the profiling code.
*/
void status_change(const char *status_arg,
const char *function_arg,
const char *file_arg, unsigned int line_arg);
inline void set_thd(THD *thd_arg) { thd= thd_arg; };
/* SHOW PROFILES */
bool show_profiles();
/* SHOW PROFILE FOR QUERY query_id */
bool show(uint options, uint profiling_query_id);
/* SHOW PROFILE */
bool show_last(uint options);
/* ... from INFORMATION_SCHEMA.PROFILING ... */
int fill_statistics_info(THD *thd, struct st_table_list *tables, Item *cond);
};
# endif /* HAVE_PROFILING */
#endif /* _SQL_PROFILE_H */

View file

@ -650,7 +650,7 @@ impossible position";
if (read_packet)
{
thd->proc_info = "Sending binlog event to slave";
thd_proc_info(thd, "Sending binlog event to slave");
if (my_net_write(net, (char*)packet->ptr(), packet->length()) )
{
errmsg = "Failed on my_net_write()";
@ -688,7 +688,7 @@ impossible position";
bool loop_breaker = 0;
/* need this to break out of the for loop from switch */
thd->proc_info = "Finished reading one binlog; switching to next binlog";
thd_proc_info(thd, "Finished reading one binlog; switching to next binlog");
switch (mysql_bin_log.find_next_log(&linfo, 1)) {
case LOG_INFO_EOF:
loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK);
@ -734,14 +734,14 @@ end:
(void)my_close(file, MYF(MY_WME));
send_eof(thd);
thd->proc_info = "Waiting to finalize termination";
thd_proc_info(thd, "Waiting to finalize termination");
pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count);
DBUG_VOID_RETURN;
err:
thd->proc_info = "Waiting to finalize termination";
thd_proc_info(thd, "Waiting to finalize termination");
end_io_cache(&log);
/*
Exclude iteration through thread list
@ -895,7 +895,7 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
if (check_access(thd, SUPER_ACL, any_db,0,0,0,0))
DBUG_RETURN(1);
thd->proc_info = "Killing slave";
thd_proc_info(thd, "Killing slave");
int thread_mask;
lock_slave_threads(mi);
// Get a mask of _running_ threads
@ -922,7 +922,7 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
ER(ER_SLAVE_WAS_NOT_RUNNING));
}
unlock_slave_threads(mi);
thd->proc_info = 0;
thd_proc_info(thd, 0);
if (slave_errno)
{
@ -1081,7 +1081,7 @@ bool change_master(THD* thd, MASTER_INFO* mi)
DBUG_RETURN(TRUE);
}
thd->proc_info = "Changing master";
thd_proc_info(thd, "Changing master");
LEX_MASTER_INFO* lex_mi= &thd->lex->mi;
// TODO: see if needs re-write
if (init_master_info(mi, master_info_file, relay_log_info_file, 0,
@ -1212,7 +1212,7 @@ bool change_master(THD* thd, MASTER_INFO* mi)
if (need_relay_log_purge)
{
relay_log_purge= 1;
thd->proc_info="Purging old relay logs";
thd_proc_info(thd, "Purging old relay logs");
if (purge_relay_logs(&mi->rli, thd,
0 /* not only reset, but also reinit */,
&errmsg))
@ -1275,7 +1275,7 @@ bool change_master(THD* thd, MASTER_INFO* mi)
pthread_mutex_unlock(&mi->rli.data_lock);
unlock_slave_threads(mi);
thd->proc_info = 0;
thd_proc_info(thd, 0);
send_ok(thd);
DBUG_RETURN(FALSE);
}

View file

@ -733,6 +733,7 @@ JOIN::optimize()
DBUG_RETURN(0);
optimized= 1;
thd_proc_info(thd, "optimizing");
row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
unit->select_limit_cnt);
/* select_limit is used to decide if we are likely to scan the whole table */
@ -868,7 +869,14 @@ JOIN::optimize()
thd->fatal_error();
error= res;
DBUG_PRINT("error",("Error from opt_sum_query"));
DBUG_RETURN(1);
DBUG_RETURN(1);
}
if (res < 0)
{
DBUG_PRINT("info",("No matching min/max row"));
zero_result_cause= "No matching min/max row";
error=0;
DBUG_RETURN(0);
}
DBUG_PRINT("info",("Select tables optimized away"));
zero_result_cause= "Select tables optimized away";
@ -904,7 +912,7 @@ JOIN::optimize()
sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables);
/* Calculate how to do the join */
thd->proc_info= "statistics";
thd_proc_info(thd, "statistics");
if (make_join_statistics(this, select_lex->leaf_tables, conds, &keyuse) ||
thd->is_fatal_error)
{
@ -914,7 +922,7 @@ JOIN::optimize()
/* Remove distinct if only const tables */
select_distinct= select_distinct && (const_tables != tables);
thd->proc_info= "preparing";
thd_proc_info(thd, "preparing");
if (result->initialize_tables(this))
{
DBUG_PRINT("error",("Error: initialize_tables() failed"));
@ -1272,8 +1280,9 @@ JOIN::optimize()
join_tab[const_tables].type != JT_REF_OR_NULL &&
(order && simple_order || group_list && simple_group))
{
if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
if (add_ref_to_table_cond(thd,&join_tab[const_tables])) {
DBUG_RETURN(1);
}
}
if (!(select_options & SELECT_BIG_RESULT) &&
@ -1333,7 +1342,7 @@ JOIN::optimize()
if (need_tmp)
{
DBUG_PRINT("info",("Creating tmp table"));
thd->proc_info="Creating tmp table";
thd_proc_info(thd, "Creating tmp table");
init_items_ref_array();
@ -1362,7 +1371,9 @@ JOIN::optimize()
select_options,
tmp_rows_limit,
(char *) "")))
{
DBUG_RETURN(1);
}
/*
We don't have to store rows in temp table that doesn't match HAVING if:
@ -1382,28 +1393,34 @@ JOIN::optimize()
if (group_list && simple_group)
{
DBUG_PRINT("info",("Sorting for group"));
thd->proc_info="Sorting for group";
thd_proc_info(thd, "Sorting for group");
if (create_sort_index(thd, this, group_list,
HA_POS_ERROR, HA_POS_ERROR, FALSE) ||
alloc_group_fields(this, group_list) ||
make_sum_func_list(all_fields, fields_list, 1) ||
setup_sum_funcs(thd, sum_funcs))
DBUG_RETURN(1);
{
DBUG_RETURN(1);
}
group_list=0;
}
else
{
if (make_sum_func_list(all_fields, fields_list, 0) ||
setup_sum_funcs(thd, sum_funcs))
DBUG_RETURN(1);
{
DBUG_RETURN(1);
}
if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
{
DBUG_PRINT("info",("Sorting for order"));
thd->proc_info="Sorting for order";
if (create_sort_index(thd, this, order,
thd_proc_info(thd, "Sorting for order");
if (create_sort_index(thd, this, order,
HA_POS_ERROR, HA_POS_ERROR, TRUE))
DBUG_RETURN(1);
order=0;
{
DBUG_RETURN(1);
}
order=0;
}
}
@ -1528,6 +1545,7 @@ JOIN::exec()
int tmp_error;
DBUG_ENTER("JOIN::exec");
thd_proc_info(thd, "executing");
error= 0;
if (procedure)
{
@ -1669,7 +1687,7 @@ JOIN::exec()
curr_tmp_table= exec_tmp_table1;
/* Copy data to the temporary table */
thd->proc_info= "Copying to tmp table";
thd_proc_info(thd, "Copying to tmp table");
DBUG_PRINT("info", ("%s", thd->proc_info));
if (!curr_join->sort_and_group &&
curr_join->const_tables != curr_join->tables)
@ -1795,7 +1813,7 @@ JOIN::exec()
}
if (curr_join->group_list)
{
thd->proc_info= "Creating sort index";
thd_proc_info(thd, "Creating sort index");
if (curr_join->join_tab == join_tab && save_join_tab())
{
DBUG_VOID_RETURN;
@ -1809,7 +1827,7 @@ JOIN::exec()
sortorder= curr_join->sortorder;
}
thd->proc_info="Copying to group table";
thd_proc_info(thd, "Copying to group table");
DBUG_PRINT("info", ("%s", thd->proc_info));
tmp_error= -1;
if (curr_join != this)
@ -1868,7 +1886,7 @@ JOIN::exec()
curr_join->join_free(); /* Free quick selects */
if (curr_join->select_distinct && ! curr_join->group_list)
{
thd->proc_info="Removing duplicates";
thd_proc_info(thd, "Removing duplicates");
if (curr_join->tmp_having)
curr_join->tmp_having->update_used_tables();
if (remove_duplicates(curr_join, curr_tmp_table,
@ -1929,7 +1947,7 @@ JOIN::exec()
if (curr_join->group_list || curr_join->order)
{
DBUG_PRINT("info",("Sorting for send_fields"));
thd->proc_info="Sorting result";
thd_proc_info(thd, "Sorting result");
/* If we have already done the group, add HAVING to sorted table */
if (curr_join->tmp_having && ! curr_join->group_list &&
! curr_join->sort_and_group)
@ -2064,7 +2082,7 @@ JOIN::exec()
}
else
{
thd->proc_info="Sending data";
thd_proc_info(thd, "Sending data");
DBUG_PRINT("info", ("%s", thd->proc_info));
result->send_fields((procedure ? curr_join->procedure_fields_list :
*curr_fields_list),
@ -2210,7 +2228,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
{
if (!(join= new JOIN(thd, fields, select_options, result)))
DBUG_RETURN(TRUE);
thd->proc_info="init";
thd_proc_info(thd, "init");
thd->used_tables=0; // Updated by setup_fields
if (err= join->prepare(rref_pointer_array, tables, wild_num,
conds, og_num, order, group, having, proc_param,
@ -2255,8 +2273,9 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
err:
if (free_join)
{
thd->proc_info="end";
thd_proc_info(thd, "end");
err|= select_lex->cleanup();
thd_proc_info(thd, "end");
DBUG_RETURN(err || thd->net.report_error);
}
DBUG_RETURN(join->error);
@ -10237,7 +10256,7 @@ free_tmp_table(THD *thd, TABLE *entry)
DBUG_PRINT("enter",("table: %s",entry->alias));
save_proc_info=thd->proc_info;
thd->proc_info="removing tmp table";
thd_proc_info(thd, "removing tmp table");
if (entry->file)
{
@ -10257,7 +10276,7 @@ free_tmp_table(THD *thd, TABLE *entry)
bitmap_lock_clear_bit(&temp_pool, entry->temp_pool_slot);
free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
thd->proc_info=save_proc_info;
thd_proc_info(thd, save_proc_info);
DBUG_VOID_RETURN;
}
@ -10290,7 +10309,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
DBUG_RETURN(1); // End of memory
save_proc_info=thd->proc_info;
thd->proc_info="converting HEAP to MyISAM";
thd_proc_info(thd, "converting HEAP to MyISAM");
if (create_myisam_tmp_table(&new_table, param,
thd->lex->select_lex.options | thd->options))
@ -10350,8 +10369,8 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
table->file->change_table_ptr(table, table->s);
table->use_all_columns();
if (save_proc_info)
thd->proc_info= (!strcmp(save_proc_info,"Copying to tmp table") ?
"Copying to tmp table on disk" : save_proc_info);
thd_proc_info(thd, (!strcmp(save_proc_info,"Copying to tmp table") ?
"Copying to tmp table on disk" : save_proc_info));
DBUG_RETURN(0);
err:
@ -10363,7 +10382,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
new_table.file->delete_table(new_table.s->table_name.str);
err2:
delete new_table.file;
thd->proc_info=save_proc_info;
thd_proc_info(thd, save_proc_info);
DBUG_RETURN(1);
}

View file

@ -5870,6 +5870,8 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_plugins, make_old_format, 0, -1, -1, 0},
{"PROCESSLIST", processlist_fields_info, create_schema_table,
fill_schema_processlist, make_old_format, 0, -1, -1, 0},
{"PROFILING", query_profile_statistics_info, create_schema_table,
fill_query_profile_statistics_info, NULL, NULL, -1, -1, false},
{"REFERENTIAL_CONSTRAINTS", referential_constraints_fields_info,
create_schema_table, get_all_tables, 0, get_referential_constraints_record,
1, 9, 0},

View file

@ -3525,7 +3525,7 @@ bool mysql_create_table_internal(THD *thd,
}
}
thd->proc_info="creating table";
thd_proc_info(thd, "creating table");
create_info->table_existed= 0; // Mark that table is created
if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)
@ -3565,7 +3565,7 @@ unlock_and_end:
VOID(pthread_mutex_unlock(&LOCK_open));
err:
thd->proc_info="After create";
thd_proc_info(thd, "After create");
delete file;
DBUG_RETURN(error);
@ -4949,7 +4949,7 @@ mysql_discard_or_import_tablespace(THD *thd,
ALTER TABLE
*/
thd->proc_info="discard_or_import_tablespace";
thd_proc_info(thd, "discard_or_import_tablespace");
discard= test(tablespace_op == DISCARD_TABLESPACE);
@ -4966,7 +4966,7 @@ mysql_discard_or_import_tablespace(THD *thd,
error=table->file->discard_or_import_tablespace(discard);
thd->proc_info="end";
thd_proc_info(thd, "end");
if (error)
goto err;
@ -5413,7 +5413,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
}
thd->proc_info="init";
thd_proc_info(thd, "init");
if (!(create_info= copy_create_info(lex_create_info)))
{
DBUG_RETURN(TRUE);
@ -5585,7 +5585,7 @@ view_err:
DBUG_RETURN(TRUE);
}
thd->proc_info="setup";
thd_proc_info(thd, "setup");
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
!table->s->tmp_table) // no need to touch frm
{
@ -5640,7 +5640,7 @@ view_err:
if (!error && (new_name != table_name || new_db != db))
{
thd->proc_info="rename";
thd_proc_info(thd, "rename");
/* Then do a 'simple' rename of the table */
if (!access(new_name_buff,F_OK))
{
@ -6291,7 +6291,7 @@ view_err:
/* Copy the data if necessary. */
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
thd->cuted_fields=0L;
thd->proc_info="copy to tmp table";
thd_proc_info(thd, "copy to tmp table");
copied=deleted=0;
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
{
@ -6516,7 +6516,7 @@ view_err:
from the cache, free all locks, close the old table and remove it.
*/
thd->proc_info="rename result table";
thd_proc_info(thd, "rename result table");
my_snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
current_pid, thd->thread_id);
if (lower_case_table_names)
@ -6691,7 +6691,7 @@ view_err:
if (error)
goto err;
}
thd->proc_info="end";
thd_proc_info(thd, "end");
ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
thd->query, thd->query_length,

View file

@ -162,7 +162,7 @@ int mysql_update(THD *thd,
mysql_handle_derived(thd->lex, &mysql_derived_filling)))
DBUG_RETURN(1);
thd->proc_info="init";
thd_proc_info(thd, "init");
table= table_list->table;
/* Calculate "table->covering_keys" based on the WHERE */
@ -379,7 +379,7 @@ int mysql_update(THD *thd,
else
init_read_record_idx(&info, thd, table, 1, used_index);
thd->proc_info="Searching rows for update";
thd_proc_info(thd, "Searching rows for update");
uint tmp_limit= limit;
while (!(error=info.read_record(&info)) && !thd->killed)
@ -446,7 +446,7 @@ int mysql_update(THD *thd,
updated= found= 0;
thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */
thd->cuted_fields=0L;
thd->proc_info="Updating";
thd_proc_info(thd, "Updating");
transactional_table= table->file->has_transactions();
thd->no_trans_update.stmt= FALSE;
@ -644,7 +644,7 @@ int mysql_update(THD *thd,
table->file->try_semi_consistent_read(0);
end_read_record(&info);
delete select;
thd->proc_info= "end";
thd_proc_info(thd, "end");
VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
/*
@ -1096,7 +1096,7 @@ int multi_update::prepare(List<Item> &not_used_values,
thd->count_cuted_fields= CHECK_FIELD_WARN;
thd->cuted_fields=0L;
thd->proc_info="updating main table";
thd_proc_info(thd, "updating main table");
tables_to_update= get_table_map(fields);
@ -1665,11 +1665,11 @@ bool multi_update::send_eof()
{
char buff[STRING_BUFFER_USUAL_SIZE];
ulonglong id;
thd->proc_info="updating reference tables";
thd_proc_info(thd, "updating reference tables");
/* Does updates for the last n - 1 tables, returns 0 if ok */
int local_error = (table_count) ? do_updates(0) : 0;
thd->proc_info= "end";
thd_proc_info(thd, "end");
/* We must invalidate the query cache before binlog writing and
ha_autocommit_... */

View file

@ -602,7 +602,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
DBUG_RETURN(0);
err:
thd->proc_info= "end";
thd_proc_info(thd, "end");
lex->link_first_table_back(view, link_to_local);
unit->cleanup();
DBUG_RETURN(res || thd->net.report_error);

View file

@ -550,6 +550,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token BIT_SYM /* MYSQL-FUNC */
%token BIT_XOR /* MYSQL-FUNC */
%token BLOB_SYM /* SQL-2003-R */
%token BLOCK_SYM
%token BOOLEAN_SYM /* SQL-2003-R */
%token BOOL_SYM
%token BOTH /* SQL-2003-R */
@ -590,10 +591,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CONSISTENT_SYM
%token CONSTRAINT /* SQL-2003-R */
%token CONTAINS_SYM /* SQL-2003-N */
%token CONTEXT_SYM
%token CONTINUE_SYM /* SQL-2003-R */
%token CONTRIBUTORS_SYM
%token CONVERT_SYM /* SQL-2003-N */
%token COUNT_SYM /* SQL-2003-N */
%token CPU_SYM
%token CREATE /* SQL-2003-R */
%token CROSS /* SQL-2003-R */
%token CUBE_SYM /* SQL-2003-R */
@ -668,6 +671,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token EXTRACT_SYM /* SQL-2003-N */
%token FALSE_SYM /* SQL-2003-R */
%token FAST_SYM
%token FAULTS_SYM
%token FETCH_SYM /* SQL-2003-R */
%token FILE_SYM
%token FIRST_SYM /* SQL-2003-N */
@ -728,6 +732,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token INT_SYM /* SQL-2003-R */
%token INVOKER_SYM
%token IN_SYM /* SQL-2003-R */
%token IO_SYM
%token IPC_SYM
%token IS /* SQL-2003-R */
%token ISOLATION /* SQL-2003-R */
%token ISSUER_SYM
@ -856,6 +862,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token OUT_SYM /* SQL-2003-R */
%token OWNER_SYM
%token PACK_KEYS_SYM
%token PAGE_SYM
%token PARAM_MARKER
%token PARSER_SYM
%token PARTIAL /* SQL-2003-N */
@ -879,6 +886,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token PROCEDURE /* SQL-2003-R */
%token PROCESS
%token PROCESSLIST_SYM
%token PROFILE_SYM
%token PROFILES_SYM
%token PURGE
%token QUARTER_SYM
%token QUERY_SYM
@ -954,6 +963,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token SOCKET_SYM
%token SONAME_SYM
%token SOUNDS_SYM
%token SOURCE_SYM
%token SPATIAL_SYM
%token SPECIFIC_SYM /* SQL-2003-R */
%token SQLEXCEPTION_SYM /* SQL-2003-R */
@ -986,6 +996,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token SUM_SYM /* SQL-2003-N */
%token SUPER_SYM
%token SUSPEND_SYM
%token SWAPS_SYM
%token SWITCHES_SYM
%token SYSDATE
%token TABLES
%token TABLESPACE
@ -8548,6 +8560,64 @@ opt_table_sym:
/* empty */
| TABLE_SYM;
opt_profile_defs:
/* empty */
| profile_defs
profile_defs:
profile_def
| profile_defs ',' profile_def
profile_def:
CPU_SYM
{
Lex->profile_options|= PROFILE_CPU;
}
| MEMORY_SYM
{
Lex->profile_options|= PROFILE_MEMORY;
}
| BLOCK_SYM IO_SYM
{
Lex->profile_options|= PROFILE_BLOCK_IO;
}
| CONTEXT_SYM SWITCHES_SYM
{
Lex->profile_options|= PROFILE_CONTEXT;
}
| PAGE_SYM FAULTS_SYM
{
Lex->profile_options|= PROFILE_PAGE_FAULTS;
}
| IPC_SYM
{
Lex->profile_options|= PROFILE_IPC;
}
| SWAPS_SYM
{
Lex->profile_options|= PROFILE_SWAPS;
}
| SOURCE_SYM
{
Lex->profile_options|= PROFILE_SOURCE;
}
| ALL
{
Lex->profile_options|= PROFILE_ALL;
}
;
opt_profile_args:
/* empty */
{
Lex->profile_query_id= 0;
}
| FOR_SYM QUERY_SYM NUM
{
Lex->profile_query_id= atoi($3.str);
}
;
/* Show things */
show: SHOW
@ -8712,6 +8782,10 @@ show_param:
{ Lex->sql_command = SQLCOM_SHOW_WARNS;}
| ERRORS opt_limit_clause_init
{ Lex->sql_command = SQLCOM_SHOW_ERRORS;}
| PROFILES_SYM
{ Lex->sql_command = SQLCOM_SHOW_PROFILES; }
| PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause_init
{ Lex->sql_command = SQLCOM_SHOW_PROFILE; }
| opt_var_type STATUS_SYM wild_and_where
{
LEX *lex= Lex;
@ -9826,6 +9900,7 @@ keyword_sp:
| AVG_SYM {}
| BINLOG_SYM {}
| BIT_SYM {}
| BLOCK_SYM {}
| BOOL_SYM {}
| BOOLEAN_SYM {}
| BTREE_SYM {}
@ -9845,7 +9920,9 @@ keyword_sp:
| CONCURRENT {}
| CONNECTION_SYM {}
| CONSISTENT_SYM {}
| CONTEXT_SYM {}
| CONTRIBUTORS_SYM {}
| CPU_SYM {}
| CUBE_SYM {}
| DATA_SYM {}
| DATAFILE_SYM {}
@ -9875,6 +9952,7 @@ keyword_sp:
| EXTENDED_SYM {}
| EXTENT_SIZE_SYM {}
| FAST_SYM {}
| FAULTS_SYM {}
| FOUND_SYM {}
| ENABLE_SYM {}
| FULL {}
@ -9899,6 +9977,8 @@ keyword_sp:
| ISSUER_SYM {}
| INNOBASE_SYM {}
| INSERT_METHOD {}
| IO_SYM {}
| IPC_SYM {}
| KEY_BLOCK_SIZE {}
| LAST_SYM {}
| LEAVES {}
@ -9962,6 +10042,7 @@ keyword_sp:
| ONE_SHOT_SYM {}
| ONE_SYM {}
| PACK_KEYS_SYM {}
| PAGE_SYM {}
| PARTIAL {}
| PARTITIONING_SYM {}
| PARTITIONS_SYM {}
@ -9976,6 +10057,8 @@ keyword_sp:
| PRIVILEGES {}
| PROCESS {}
| PROCESSLIST_SYM {}
| PROFILE_SYM {}
| PROFILES_SYM {}
| QUARTER_SYM {}
| QUERY_SYM {}
| QUICK {}
@ -10010,6 +10093,7 @@ keyword_sp:
| SHUTDOWN {}
| SNAPSHOT_SYM {}
| SOUNDS_SYM {}
| SOURCE_SYM {}
| SQL_CACHE_SYM {}
| SQL_BUFFER_RESULT {}
| SQL_NO_CACHE_SYM {}
@ -10024,6 +10108,8 @@ keyword_sp:
| SUBPARTITIONS_SYM {}
| SUPER_SYM {}
| SUSPEND_SYM {}
| SWAPS_SYM {}
| SWITCHES_SYM {}
| TABLES {}
| TABLESPACE {}
| TEMPORARY {}

View file

@ -535,6 +535,7 @@ enum enum_schema_tables
SCH_PARTITIONS,
SCH_PLUGINS,
SCH_PROCESSLIST,
SCH_PROFILING,
SCH_REFERENTIAL_CONSTRAINTS,
SCH_PROCEDURES,
SCH_SCHEMATA,

View file

@ -750,7 +750,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
MYISAM_SHARE* share = file->s;
const char *old_proc_info=thd->proc_info;
thd->proc_info="Checking table";
thd_proc_info(thd, "Checking table");
myisamchk_init(&param);
param.thd = thd;
param.op_name = "check";
@ -824,7 +824,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
}
thd->proc_info=old_proc_info;
thd_proc_info(thd, old_proc_info);
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
}
@ -1110,22 +1110,22 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool do_optimize)
char buf[40];
/* TODO: respect myisam_repair_threads variable */
my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
thd->proc_info=buf;
thd_proc_info(thd, buf);
error = mi_repair_parallel(&param, file, fixed_name,
param.testflag & T_QUICK);
thd->proc_info="Repair done"; // to reset proc_info, as
thd_proc_info(thd, "Repair done"); // to reset proc_info, as
// it was pointing to local buffer
}
else
{
thd->proc_info="Repair by sorting";
thd_proc_info(thd, "Repair by sorting");
error = mi_repair_by_sort(&param, file, fixed_name,
param.testflag & T_QUICK);
}
}
else
{
thd->proc_info="Repair with keycache";
thd_proc_info(thd, "Repair with keycache");
param.testflag &= ~T_REP_BY_SORT;
error= mi_repair(&param, file, fixed_name,
param.testflag & T_QUICK);
@ -1139,7 +1139,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool do_optimize)
(share->state.changed & STATE_NOT_SORTED_PAGES))
{
optimize_done=1;
thd->proc_info="Sorting index";
thd_proc_info(thd, "Sorting index");
error=mi_sort_index(&param,file,fixed_name);
}
if (!statistics_done && (local_testflag & T_STATISTICS))
@ -1147,14 +1147,14 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool do_optimize)
if (share->state.changed & STATE_NOT_ANALYZED)
{
optimize_done=1;
thd->proc_info="Analyzing";
thd_proc_info(thd, "Analyzing");
error = chk_key(&param, file);
}
else
local_testflag&= ~T_STATISTICS; // Don't update statistics
}
}
thd->proc_info="Saving state";
thd_proc_info(thd, "Saving state");
if (!error)
{
if ((share->state.changed & STATE_CHANGED) || mi_is_crashed(file))
@ -1192,7 +1192,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool do_optimize)
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
update_state_info(&param, file, 0);
}
thd->proc_info=old_proc_info;
thd_proc_info(thd, old_proc_info);
if (!thd->locked_tables)
mi_lock_database(file,F_UNLCK);
DBUG_RETURN(error ? HA_ADMIN_FAILED :
@ -1416,7 +1416,7 @@ int ha_myisam::enable_indexes(uint mode)
THD *thd=current_thd;
MI_CHECK param;
const char *save_proc_info=thd->proc_info;
thd->proc_info="Creating index";
thd_proc_info(thd, "Creating index");
myisamchk_init(&param);
param.op_name= "recreating_index";
param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
@ -1441,7 +1441,7 @@ int ha_myisam::enable_indexes(uint mode)
thd->clear_error();
}
info(HA_STATUS_CONST);
thd->proc_info=save_proc_info;
thd_proc_info(thd, save_proc_info);
}
else
{

View file

@ -490,6 +490,11 @@ chmod -R og-rw $mysql_datadir/mysql
# Allow mysqld_safe to start mysqld and print a message before we exit
sleep 2
#echo "Thank you for installing the MySQL Community Server! For Production
#systems, we recommend MySQL Enterprise, which contains enterprise-ready
#software, intelligent advisory services, and full production support with
#scheduled service packs and more. Visit www.mysql.com/enterprise for more
#information."
%post ndb-storage
mysql_clusterdir=/var/lib/mysql-cluster