summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/information_schema_all_engines.result120
-rw-r--r--mysql-test/suite/pbxt/r/mysqlshow.result48
-rw-r--r--mysql-test/suite/percona/disabled.def3
-rw-r--r--mysql-test/suite/percona/log_connection_error.patch/percona_log_connection_error.result3
-rw-r--r--mysql-test/suite/percona/log_connection_error.patch/percona_log_connection_error.test12
-rw-r--r--mysql-test/suite/percona/percona_innodb_expand_fast_index_creation.result64
-rw-r--r--mysql-test/suite/percona/percona_innodb_expand_fast_index_creation.test45
-rw-r--r--mysql-test/suite/percona/percona_innodb_fake_changes.result55
-rw-r--r--mysql-test/suite/percona/percona_innodb_fake_changes.test49
-rw-r--r--mysql-test/suite/percona/percona_innodb_fake_changes_locks.result19
-rw-r--r--mysql-test/suite/percona/percona_innodb_fake_changes_locks.test24
-rw-r--r--mysql-test/suite/percona/percona_innodb_kill_idle_trx.result41
-rw-r--r--mysql-test/suite/percona/percona_innodb_kill_idle_trx.test28
-rw-r--r--mysql-test/suite/percona/percona_innodb_kill_idle_trx_locks.result45
-rw-r--r--mysql-test/suite/percona/percona_innodb_kill_idle_trx_locks.test31
-rw-r--r--mysql-test/suite/percona/percona_processlist_row_stats.result52
-rw-r--r--mysql-test/suite/percona/percona_processlist_row_stats.test63
-rw-r--r--mysql-test/suite/percona/percona_query_response_time-replication.result761
-rw-r--r--mysql-test/suite/percona/percona_query_response_time-replication.test79
-rw-r--r--mysql-test/suite/percona/percona_query_response_time-stored.result768
-rw-r--r--mysql-test/suite/percona/percona_query_response_time-stored.test111
-rw-r--r--mysql-test/suite/percona/percona_query_response_time.result1604
-rw-r--r--mysql-test/suite/percona/percona_query_response_time.test85
-rw-r--r--mysql-test/suite/percona/percona_server_variables_debug.result9
-rw-r--r--mysql-test/suite/percona/percona_server_variables_release.result8
-rw-r--r--mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.result24
-rw-r--r--mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.test32
-rw-r--r--mysql-test/suite/percona/query_response_time-replication.inc57
-rw-r--r--mysql-test/suite/percona/query_response_time-stored.inc37
-rw-r--r--mysql-test/suite/percona/query_response_time.inc43
-rw-r--r--mysql-test/suite/percona/show_slave_status_nolock.patch/percona_show_slave_status_nolock.result70
-rw-r--r--mysql-test/suite/percona/show_slave_status_nolock.patch/percona_show_slave_status_nolock.test105
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_blocking_buffer_pool_restore_basic.result1
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_fake_changes_basic.result1
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_kill_idle_transaction_basic.result1
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_blocking_buffer_pool_restore_basic.test1
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_fake_changes_basic.test1
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_kill_idle_transaction_basic.test1
-rw-r--r--storage/xtradb/btr/btr0btr.c102
-rw-r--r--storage/xtradb/btr/btr0cur.c172
-rw-r--r--storage/xtradb/btr/btr0pcur.c38
-rw-r--r--storage/xtradb/btr/btr0sea.c3
-rw-r--r--storage/xtradb/buf/buf0buddy.c482
-rw-r--r--storage/xtradb/buf/buf0buf.c694
-rw-r--r--storage/xtradb/buf/buf0flu.c4
-rw-r--r--storage/xtradb/buf/buf0lru.c274
-rw-r--r--storage/xtradb/buf/buf0rea.c174
-rw-r--r--storage/xtradb/dict/dict0crea.c4
-rw-r--r--storage/xtradb/dict/dict0dict.c192
-rw-r--r--storage/xtradb/dict/dict0load.c93
-rw-r--r--storage/xtradb/fil/fil0fil.c4
-rw-r--r--storage/xtradb/handler/ha_innodb.cc311
-rw-r--r--storage/xtradb/handler/handler0alter.cc21
-rw-r--r--storage/xtradb/ibuf/ibuf0ibuf.c46
-rw-r--r--storage/xtradb/include/btr0btr.h32
-rw-r--r--storage/xtradb/include/btr0btr.ic10
-rw-r--r--storage/xtradb/include/btr0pcur.h21
-rw-r--r--storage/xtradb/include/btr0pcur.ic9
-rw-r--r--storage/xtradb/include/buf0buddy.h50
-rw-r--r--storage/xtradb/include/buf0buddy.ic70
-rw-r--r--storage/xtradb/include/buf0buf.h47
-rw-r--r--storage/xtradb/include/buf0buf.ic59
-rw-r--r--storage/xtradb/include/buf0lru.h52
-rw-r--r--storage/xtradb/include/buf0rea.h26
-rw-r--r--storage/xtradb/include/buf0types.h17
-rw-r--r--storage/xtradb/include/db0err.h6
-rw-r--r--storage/xtradb/include/dict0boot.h6
-rw-r--r--storage/xtradb/include/dict0dict.h82
-rw-r--r--storage/xtradb/include/dict0dict.ic46
-rw-r--r--storage/xtradb/include/dict0mem.h14
-rw-r--r--storage/xtradb/include/dict0types.h3
-rw-r--r--storage/xtradb/include/ha_prototypes.h1
-rw-r--r--storage/xtradb/include/mtr0mtr.h10
-rw-r--r--storage/xtradb/include/os0file.h3
-rw-r--r--storage/xtradb/include/page0page.h5
-rw-r--r--storage/xtradb/include/row0row.h28
-rw-r--r--storage/xtradb/include/row0row.ic25
-rw-r--r--storage/xtradb/include/row0upd.ic9
-rw-r--r--storage/xtradb/include/srv0srv.h10
-rw-r--r--storage/xtradb/include/sync0sync.h10
-rw-r--r--storage/xtradb/include/sync0sync.ic5
-rw-r--r--storage/xtradb/include/trx0sys.h13
-rw-r--r--storage/xtradb/include/trx0sys.ic24
-rw-r--r--storage/xtradb/include/trx0trx.h3
-rw-r--r--storage/xtradb/include/trx0undo.h46
-rw-r--r--storage/xtradb/include/ut0mem.h39
-rw-r--r--storage/xtradb/include/ut0mem.ic23
-rw-r--r--storage/xtradb/lock/lock0lock.c25
-rw-r--r--storage/xtradb/mtr/mtr0mtr.c38
-rw-r--r--storage/xtradb/page/page0zip.c186
-rw-r--r--storage/xtradb/pars/pars0opt.c2
-rw-r--r--storage/xtradb/que/que0que.c6
-rw-r--r--storage/xtradb/rem/rem0rec.c10
-rw-r--r--storage/xtradb/row/row0ins.c36
-rw-r--r--storage/xtradb/row/row0merge.c6
-rw-r--r--storage/xtradb/row/row0mysql.c105
-rw-r--r--storage/xtradb/row/row0purge.c33
-rw-r--r--storage/xtradb/row/row0row.c55
-rw-r--r--storage/xtradb/row/row0sel.c116
-rw-r--r--storage/xtradb/row/row0uins.c4
-rw-r--r--storage/xtradb/row/row0umod.c25
-rw-r--r--storage/xtradb/row/row0upd.c23
-rw-r--r--storage/xtradb/srv/srv0srv.c57
-rw-r--r--storage/xtradb/srv/srv0start.c6
-rw-r--r--storage/xtradb/sync/sync0sync.c35
-rw-r--r--storage/xtradb/trx/trx0rec.c69
-rw-r--r--storage/xtradb/trx/trx0trx.c5
-rw-r--r--storage/xtradb/trx/trx0undo.c66
-rw-r--r--storage/xtradb/ut/ut0mem.c49
-rw-r--r--storage/xtradb/ut/ut0ut.c6
110 files changed, 5935 insertions, 2947 deletions
diff --git a/mysql-test/r/information_schema_all_engines.result b/mysql-test/r/information_schema_all_engines.result
index 9ea7c947100..e8fafccd0b2 100644
--- a/mysql-test/r/information_schema_all_engines.result
+++ b/mysql-test/r/information_schema_all_engines.result
@@ -36,29 +36,29 @@ TRIGGERS
USER_PRIVILEGES
USER_STATISTICS
VIEWS
-INNODB_CMPMEM_RESET
-PBXT_STATISTICS
-INNODB_CMPMEM
+INNODB_SYS_COLUMNS
INNODB_RSEG
+INNODB_CMP
+INNODB_TRX
INNODB_SYS_TABLESTATS
INNODB_LOCK_WAITS
-INNODB_INDEX_STATS
-INNODB_CMP
+INNODB_BUFFER_POOL_PAGES_INDEX
+INNODB_LOCKS
INNODB_SYS_FOREIGN_COLS
INNODB_CMP_RESET
INNODB_BUFFER_POOL_PAGES
-INNODB_TRX
-INNODB_BUFFER_POOL_PAGES_INDEX
-INNODB_LOCKS
-INNODB_BUFFER_POOL_PAGES_BLOB
INNODB_SYS_TABLES
+PBXT_STATISTICS
+INNODB_CMPMEM
+INNODB_BUFFER_POOL_PAGES_BLOB
+INNODB_CMPMEM_RESET
INNODB_SYS_FIELDS
-INNODB_SYS_COLUMNS
-INNODB_SYS_STATS
+INNODB_TABLE_STATS
INNODB_SYS_FOREIGN
INNODB_SYS_INDEXES
+INNODB_INDEX_STATS
XTRADB_ADMIN_COMMAND
-INNODB_TABLE_STATS
+INNODB_SYS_STATS
SELECT t.table_name, c1.column_name
FROM information_schema.tables t
INNER JOIN
@@ -109,29 +109,29 @@ TRIGGERS TRIGGER_SCHEMA
USER_PRIVILEGES GRANTEE
USER_STATISTICS USER
VIEWS TABLE_SCHEMA
-INNODB_CMPMEM_RESET page_size
-PBXT_STATISTICS ID
-INNODB_CMPMEM page_size
+INNODB_SYS_COLUMNS TABLE_ID
INNODB_RSEG rseg_id
+INNODB_CMP page_size
+INNODB_TRX trx_id
INNODB_SYS_TABLESTATS SCHEMA
INNODB_LOCK_WAITS requesting_trx_id
-INNODB_INDEX_STATS table_schema
-INNODB_CMP page_size
+INNODB_BUFFER_POOL_PAGES_INDEX index_id
+INNODB_LOCKS lock_id
INNODB_SYS_FOREIGN_COLS ID
INNODB_CMP_RESET page_size
INNODB_BUFFER_POOL_PAGES page_type
-INNODB_TRX trx_id
-INNODB_BUFFER_POOL_PAGES_INDEX index_id
-INNODB_LOCKS lock_id
-INNODB_BUFFER_POOL_PAGES_BLOB space_id
INNODB_SYS_TABLES SCHEMA
+PBXT_STATISTICS ID
+INNODB_CMPMEM page_size
+INNODB_BUFFER_POOL_PAGES_BLOB space_id
+INNODB_CMPMEM_RESET page_size
INNODB_SYS_FIELDS INDEX_ID
-INNODB_SYS_COLUMNS TABLE_ID
-INNODB_SYS_STATS INDEX_ID
+INNODB_TABLE_STATS table_schema
INNODB_SYS_FOREIGN ID
INNODB_SYS_INDEXES INDEX_ID
+INNODB_INDEX_STATS table_schema
XTRADB_ADMIN_COMMAND result_message
-INNODB_TABLE_STATS table_schema
+INNODB_SYS_STATS INDEX_ID
SELECT t.table_name, c1.column_name
FROM information_schema.tables t
INNER JOIN
@@ -182,29 +182,29 @@ TRIGGERS TRIGGER_SCHEMA
USER_PRIVILEGES GRANTEE
USER_STATISTICS USER
VIEWS TABLE_SCHEMA
-INNODB_CMPMEM_RESET page_size
-PBXT_STATISTICS ID
-INNODB_CMPMEM page_size
+INNODB_SYS_COLUMNS TABLE_ID
INNODB_RSEG rseg_id
+INNODB_CMP page_size
+INNODB_TRX trx_id
INNODB_SYS_TABLESTATS SCHEMA
INNODB_LOCK_WAITS requesting_trx_id
-INNODB_INDEX_STATS table_schema
-INNODB_CMP page_size
+INNODB_BUFFER_POOL_PAGES_INDEX index_id
+INNODB_LOCKS lock_id
INNODB_SYS_FOREIGN_COLS ID
INNODB_CMP_RESET page_size
INNODB_BUFFER_POOL_PAGES page_type
-INNODB_TRX trx_id
-INNODB_BUFFER_POOL_PAGES_INDEX index_id
-INNODB_LOCKS lock_id
-INNODB_BUFFER_POOL_PAGES_BLOB space_id
INNODB_SYS_TABLES SCHEMA
+PBXT_STATISTICS ID
+INNODB_CMPMEM page_size
+INNODB_BUFFER_POOL_PAGES_BLOB space_id
+INNODB_CMPMEM_RESET page_size
INNODB_SYS_FIELDS INDEX_ID
-INNODB_SYS_COLUMNS TABLE_ID
-INNODB_SYS_STATS INDEX_ID
+INNODB_TABLE_STATS table_schema
INNODB_SYS_FOREIGN ID
INNODB_SYS_INDEXES INDEX_ID
+INNODB_INDEX_STATS table_schema
XTRADB_ADMIN_COMMAND result_message
-INNODB_TABLE_STATS table_schema
+INNODB_SYS_STATS INDEX_ID
select 1 as f1 from information_schema.tables where "CHARACTER_SETS"=
(select cast(table_name as char) from information_schema.tables
order by table_name limit 1) limit 1;
@@ -322,29 +322,29 @@ Database: information_schema
| USER_PRIVILEGES |
| USER_STATISTICS |
| VIEWS |
-| INNODB_CMPMEM_RESET |
-| PBXT_STATISTICS |
-| INNODB_CMPMEM |
+| INNODB_SYS_COLUMNS |
| INNODB_RSEG |
+| INNODB_CMP |
+| INNODB_TRX |
| INNODB_SYS_TABLESTATS |
| INNODB_LOCK_WAITS |
-| INNODB_INDEX_STATS |
-| INNODB_CMP |
+| INNODB_BUFFER_POOL_PAGES_INDEX |
+| INNODB_LOCKS |
| INNODB_SYS_FOREIGN_COLS |
| INNODB_CMP_RESET |
| INNODB_BUFFER_POOL_PAGES |
-| INNODB_TRX |
-| INNODB_BUFFER_POOL_PAGES_INDEX |
-| INNODB_LOCKS |
-| INNODB_BUFFER_POOL_PAGES_BLOB |
| INNODB_SYS_TABLES |
+| PBXT_STATISTICS |
+| INNODB_CMPMEM |
+| INNODB_BUFFER_POOL_PAGES_BLOB |
+| INNODB_CMPMEM_RESET |
| INNODB_SYS_FIELDS |
-| INNODB_SYS_COLUMNS |
-| INNODB_SYS_STATS |
+| INNODB_TABLE_STATS |
| INNODB_SYS_FOREIGN |
| INNODB_SYS_INDEXES |
+| INNODB_INDEX_STATS |
| XTRADB_ADMIN_COMMAND |
-| INNODB_TABLE_STATS |
+| INNODB_SYS_STATS |
+---------------------------------------+
Database: INFORMATION_SCHEMA
+---------------------------------------+
@@ -385,29 +385,29 @@ Database: INFORMATION_SCHEMA
| USER_PRIVILEGES |
| USER_STATISTICS |
| VIEWS |
-| INNODB_CMPMEM_RESET |
-| PBXT_STATISTICS |
-| INNODB_CMPMEM |
+| INNODB_SYS_COLUMNS |
| INNODB_RSEG |
+| INNODB_CMP |
+| INNODB_TRX |
| INNODB_SYS_TABLESTATS |
| INNODB_LOCK_WAITS |
-| INNODB_INDEX_STATS |
-| INNODB_CMP |
+| INNODB_BUFFER_POOL_PAGES_INDEX |
+| INNODB_LOCKS |
| INNODB_SYS_FOREIGN_COLS |
| INNODB_CMP_RESET |
| INNODB_BUFFER_POOL_PAGES |
-| INNODB_TRX |
-| INNODB_BUFFER_POOL_PAGES_INDEX |
-| INNODB_LOCKS |
-| INNODB_BUFFER_POOL_PAGES_BLOB |
| INNODB_SYS_TABLES |
+| PBXT_STATISTICS |
+| INNODB_CMPMEM |
+| INNODB_BUFFER_POOL_PAGES_BLOB |
+| INNODB_CMPMEM_RESET |
| INNODB_SYS_FIELDS |
-| INNODB_SYS_COLUMNS |
-| INNODB_SYS_STATS |
+| INNODB_TABLE_STATS |
| INNODB_SYS_FOREIGN |
| INNODB_SYS_INDEXES |
+| INNODB_INDEX_STATS |
| XTRADB_ADMIN_COMMAND |
-| INNODB_TABLE_STATS |
+| INNODB_SYS_STATS |
+---------------------------------------+
Wildcard: inf_rmation_schema
+--------------------+
diff --git a/mysql-test/suite/pbxt/r/mysqlshow.result b/mysql-test/suite/pbxt/r/mysqlshow.result
index a8bd5904600..b378b972410 100644
--- a/mysql-test/suite/pbxt/r/mysqlshow.result
+++ b/mysql-test/suite/pbxt/r/mysqlshow.result
@@ -114,29 +114,29 @@ Database: information_schema
| USER_PRIVILEGES |
| USER_STATISTICS |
| VIEWS |
-| INNODB_CMPMEM_RESET |
-| PBXT_STATISTICS |
-| INNODB_CMPMEM |
+| INNODB_SYS_COLUMNS |
| INNODB_RSEG |
+| INNODB_CMP |
+| INNODB_TRX |
| INNODB_SYS_TABLESTATS |
| INNODB_LOCK_WAITS |
-| INNODB_INDEX_STATS |
-| INNODB_CMP |
+| INNODB_BUFFER_POOL_PAGES_INDEX |
+| INNODB_LOCKS |
| INNODB_SYS_FOREIGN_COLS |
| INNODB_CMP_RESET |
| INNODB_BUFFER_POOL_PAGES |
-| INNODB_TRX |
-| INNODB_BUFFER_POOL_PAGES_INDEX |
-| INNODB_LOCKS |
-| INNODB_BUFFER_POOL_PAGES_BLOB |
| INNODB_SYS_TABLES |
+| PBXT_STATISTICS |
+| INNODB_CMPMEM |
+| INNODB_BUFFER_POOL_PAGES_BLOB |
+| INNODB_CMPMEM_RESET |
| INNODB_SYS_FIELDS |
-| INNODB_SYS_COLUMNS |
-| INNODB_SYS_STATS |
+| INNODB_TABLE_STATS |
| INNODB_SYS_FOREIGN |
| INNODB_SYS_INDEXES |
+| INNODB_INDEX_STATS |
| XTRADB_ADMIN_COMMAND |
-| INNODB_TABLE_STATS |
+| INNODB_SYS_STATS |
+---------------------------------------+
Database: INFORMATION_SCHEMA
+---------------------------------------+
@@ -177,29 +177,29 @@ Database: INFORMATION_SCHEMA
| USER_PRIVILEGES |
| USER_STATISTICS |
| VIEWS |
-| INNODB_CMPMEM_RESET |
-| PBXT_STATISTICS |
-| INNODB_CMPMEM |
+| INNODB_SYS_COLUMNS |
| INNODB_RSEG |
+| INNODB_CMP |
+| INNODB_TRX |
| INNODB_SYS_TABLESTATS |
| INNODB_LOCK_WAITS |
-| INNODB_INDEX_STATS |
-| INNODB_CMP |
+| INNODB_BUFFER_POOL_PAGES_INDEX |
+| INNODB_LOCKS |
| INNODB_SYS_FOREIGN_COLS |
| INNODB_CMP_RESET |
| INNODB_BUFFER_POOL_PAGES |
-| INNODB_TRX |
-| INNODB_BUFFER_POOL_PAGES_INDEX |
-| INNODB_LOCKS |
-| INNODB_BUFFER_POOL_PAGES_BLOB |
| INNODB_SYS_TABLES |
+| PBXT_STATISTICS |
+| INNODB_CMPMEM |
+| INNODB_BUFFER_POOL_PAGES_BLOB |
+| INNODB_CMPMEM_RESET |
| INNODB_SYS_FIELDS |
-| INNODB_SYS_COLUMNS |
-| INNODB_SYS_STATS |
+| INNODB_TABLE_STATS |
| INNODB_SYS_FOREIGN |
| INNODB_SYS_INDEXES |
+| INNODB_INDEX_STATS |
| XTRADB_ADMIN_COMMAND |
-| INNODB_TABLE_STATS |
+| INNODB_SYS_STATS |
+---------------------------------------+
Wildcard: inf_rmation_schema
+--------------------+
diff --git a/mysql-test/suite/percona/disabled.def b/mysql-test/suite/percona/disabled.def
index b0dc0a2a84d..eb9df7f4118 100644
--- a/mysql-test/suite/percona/disabled.def
+++ b/mysql-test/suite/percona/disabled.def
@@ -38,3 +38,6 @@ percona_show_slave_status_nolock: Feature not merged into MariaDB
percona_slow_extended-slave_innodb_stats: Feature not merged into MariaDB
percona_slow_extended-slave_statements-and-use_global_long_query_time: Feature not merged into MariaDB
userstat_bug602047: Feature not merged into MariaDB
+percona_innodb_expand_fast_index_creation: Feature not merged into MariaDB
+percona_innodb_kill_idle_trx: Feature not merged into MariaDB
+percona_innodb_kill_idle_trx_locks: Feature not merged into MariaDB
diff --git a/mysql-test/suite/percona/log_connection_error.patch/percona_log_connection_error.result b/mysql-test/suite/percona/log_connection_error.patch/percona_log_connection_error.result
index 3c6c67f770c..352c9ca2a99 100644
--- a/mysql-test/suite/percona/log_connection_error.patch/percona_log_connection_error.result
+++ b/mysql-test/suite/percona/log_connection_error.patch/percona_log_connection_error.result
@@ -12,4 +12,5 @@ connect(localhost,root,,test,port,socket);
ERROR HY000: Too many connections
SET GLOBAL max_connections = @old_max_connections;
SET GLOBAL log_warnings = @old_log_warnings;
-1
+[log_grep.inc] file: percona.log_connection_error.err pattern: Too many connections
+[log_grep.inc] lines: 1
diff --git a/mysql-test/suite/percona/log_connection_error.patch/percona_log_connection_error.test b/mysql-test/suite/percona/log_connection_error.patch/percona_log_connection_error.test
index 677da047354..048102d0499 100644
--- a/mysql-test/suite/percona/log_connection_error.patch/percona_log_connection_error.test
+++ b/mysql-test/suite/percona/log_connection_error.patch/percona_log_connection_error.test
@@ -45,10 +45,10 @@ if(!`select LENGTH('$log_error_')`)
# does not know the location of its .err log, use default location
let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err;
}
-# Assign env variable LOG_ERROR
-let LOG_ERROR=$log_error_;
---let grep_file = $log_error
---let grep_pattern = Too many connections
---source grep.inc
-exec $cmd;
+--let log_error=$log_error_
+--let log_file=percona.log_connection_error.err
+--let log_file_full_path=$log_error
+--let grep_pattern= Too many connections
+--source log_grep.inc
+
diff --git a/mysql-test/suite/percona/percona_innodb_expand_fast_index_creation.result b/mysql-test/suite/percona/percona_innodb_expand_fast_index_creation.result
new file mode 100644
index 00000000000..b8cec3d4398
--- /dev/null
+++ b/mysql-test/suite/percona/percona_innodb_expand_fast_index_creation.result
@@ -0,0 +1,64 @@
+CREATE TABLE t1(
+id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+a CHAR(1) NOT NULL,
+b CHAR(36) NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1(a,b) VALUES ('a','b');
+INSERT INTO t1(a,b) SELECT a,b FROM t1;
+INSERT INTO t1(a,b) SELECT a,b FROM t1;
+INSERT INTO t1(a,b) SELECT a,b FROM t1;
+INSERT INTO t1(a,b) SELECT a,b FROM t1;
+ALTER TABLE t1 ADD KEY (a);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b;
+id 1
+select_type SIMPLE
+table t1
+type ALL
+possible_keys a
+key NULL
+key_len NULL
+ref NULL
+rows 16
+Extra
+id 1
+select_type SIMPLE
+table t2
+type ref
+possible_keys a
+key a
+key_len 1
+ref test.t1.a
+rows 1
+Extra Using where
+ALTER TABLE t1 DROP KEY a;
+SET expand_fast_index_creation = 1;
+SELECT @@expand_fast_index_creation;
+@@expand_fast_index_creation
+1
+ALTER TABLE t1 ADD KEY (a);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b;
+id 1
+select_type SIMPLE
+table t1
+type ALL
+possible_keys a
+key NULL
+key_len NULL
+ref NULL
+rows 16
+Extra
+id 1
+select_type SIMPLE
+table t2
+type ALL
+possible_keys a
+key NULL
+key_len NULL
+ref NULL
+rows 16
+Extra Using where; Using join buffer
+SET expand_fast_index_creation = 0;
+DROP TABLE t1;
diff --git a/mysql-test/suite/percona/percona_innodb_expand_fast_index_creation.test b/mysql-test/suite/percona/percona_innodb_expand_fast_index_creation.test
new file mode 100644
index 00000000000..06e6c719c17
--- /dev/null
+++ b/mysql-test/suite/percona/percona_innodb_expand_fast_index_creation.test
@@ -0,0 +1,45 @@
+--source include/have_innodb.inc
+
+########################################################################
+# Bug #857590: Fast index creation does not update index statistics
+########################################################################
+
+CREATE TABLE t1(
+ id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ a CHAR(1) NOT NULL,
+ b CHAR(36) NOT NULL) ENGINE=InnoDB;
+
+INSERT INTO t1(a,b) VALUES ('a','b');
+INSERT INTO t1(a,b) SELECT a,b FROM t1;
+INSERT INTO t1(a,b) SELECT a,b FROM t1;
+INSERT INTO t1(a,b) SELECT a,b FROM t1;
+INSERT INTO t1(a,b) SELECT a,b FROM t1;
+
+# Check that fast index creation is used
+--enable_info
+ALTER TABLE t1 ADD KEY (a);
+--disable_info
+
+# The default (wrong) plan due to bogus statistics
+--vertical_results
+EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b;
+--horizontal_results
+
+ALTER TABLE t1 DROP KEY a;
+
+SET expand_fast_index_creation = 1;
+SELECT @@expand_fast_index_creation;
+
+# Check that stats are updated with the option enabled
+
+--enable_info
+ALTER TABLE t1 ADD KEY (a);
+--disable_info
+
+--vertical_results
+EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b;
+--horizontal_results
+
+SET expand_fast_index_creation = 0;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/percona/percona_innodb_fake_changes.result b/mysql-test/suite/percona/percona_innodb_fake_changes.result
new file mode 100644
index 00000000000..7f00c687c54
--- /dev/null
+++ b/mysql-test/suite/percona/percona_innodb_fake_changes.result
@@ -0,0 +1,55 @@
+DROP TABLE IF EXISTS t1;
+# Checking variables
+SHOW VARIABLES LIKE 'innodb_fake_changes';
+Variable_name Value
+innodb_fake_changes OFF
+SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
+VARIABLE_VALUE
+OFF
+SET innodb_fake_changes=1;
+SHOW VARIABLES LIKE 'innodb_fake_changes';
+Variable_name Value
+innodb_fake_changes ON
+SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
+VARIABLE_VALUE
+ON
+SET innodb_fake_changes=default;
+SHOW VARIABLES LIKE 'innodb_fake_changes';
+Variable_name Value
+innodb_fake_changes OFF
+SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
+VARIABLE_VALUE
+OFF
+# Explicit COMMIT should fail when innodb_fake_changes is enabled
+# DML should be fine
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET autocommit=0;
+SET innodb_fake_changes=1;
+BEGIN;
+INSERT INTO t1 VALUES (2);
+UPDATE t1 SET a=0;
+DELETE FROM t1 LIMIT 1;
+SELECT * FROM t1;
+a
+1
+COMMIT;
+ERROR HY000: Got error 131 during COMMIT
+SET innodb_fake_changes=default;
+DROP TABLE t1;
+# DDL must result in error
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+SET autocommit=0;
+SET innodb_fake_changes=1;
+BEGIN;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+ERROR HY000: Can't create table 'test.t2' (errno: 131)
+DROP TABLE t1;
+ERROR 42S02: Unknown table 't1'
+TRUNCATE TABLE t1;
+ERROR HY000: Got error 131 during COMMIT
+ALTER TABLE t1 ENGINE=MyISAM;
+ERROR HY000: Got error 131 during COMMIT
+ROLLBACK;
+SET innodb_fake_changes=default;
+DROP TABLE t1;
diff --git a/mysql-test/suite/percona/percona_innodb_fake_changes.test b/mysql-test/suite/percona/percona_innodb_fake_changes.test
new file mode 100644
index 00000000000..fd231ae096f
--- /dev/null
+++ b/mysql-test/suite/percona/percona_innodb_fake_changes.test
@@ -0,0 +1,49 @@
+--source include/have_innodb.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+
+--echo # Checking variables
+SHOW VARIABLES LIKE 'innodb_fake_changes';
+SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
+SET innodb_fake_changes=1;
+SHOW VARIABLES LIKE 'innodb_fake_changes';
+SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
+SET innodb_fake_changes=default;
+SHOW VARIABLES LIKE 'innodb_fake_changes';
+SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
+
+--echo # Explicit COMMIT should fail when innodb_fake_changes is enabled
+--echo # DML should be fine
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET autocommit=0;
+SET innodb_fake_changes=1;
+BEGIN;
+INSERT INTO t1 VALUES (2);
+UPDATE t1 SET a=0;
+DELETE FROM t1 LIMIT 1;
+SELECT * FROM t1;
+--error 1180
+COMMIT;
+SET innodb_fake_changes=default;
+DROP TABLE t1;
+
+--echo # DDL must result in error
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+SET autocommit=0;
+SET innodb_fake_changes=1;
+BEGIN;
+--error 1005
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+--error 1051
+DROP TABLE t1;
+--error 1180
+TRUNCATE TABLE t1;
+--error 1180
+ALTER TABLE t1 ENGINE=MyISAM;
+ROLLBACK;
+SET innodb_fake_changes=default;
+DROP TABLE t1;
diff --git a/mysql-test/suite/percona/percona_innodb_fake_changes_locks.result b/mysql-test/suite/percona/percona_innodb_fake_changes_locks.result
new file mode 100644
index 00000000000..c2b533ca9f3
--- /dev/null
+++ b/mysql-test/suite/percona/percona_innodb_fake_changes_locks.result
@@ -0,0 +1,19 @@
+DROP TABLE IF EXISTS t1;
+# Verifying that X_LOCK not acquired
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET autocommit=0;
+SET innodb_fake_changes=1;
+BEGIN;
+SELECT * FROM t1 FOR UPDATE;
+a
+1
+SET innodb_lock_wait_timeout=3;
+UPDATE t1 SET a=2;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SELECT * FROM t1 LOCK IN SHARE MODE;
+a
+1
+ROLLBACK;
+SET innodb_fake_changes=default;
+DROP TABLE t1;
diff --git a/mysql-test/suite/percona/percona_innodb_fake_changes_locks.test b/mysql-test/suite/percona/percona_innodb_fake_changes_locks.test
new file mode 100644
index 00000000000..e298405cd43
--- /dev/null
+++ b/mysql-test/suite/percona/percona_innodb_fake_changes_locks.test
@@ -0,0 +1,24 @@
+--source include/have_innodb.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--echo # Verifying that X_LOCK not acquired
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+--connect (conn1,localhost,root,,)
+--connection conn1
+SET autocommit=0;
+SET innodb_fake_changes=1;
+BEGIN;
+SELECT * FROM t1 FOR UPDATE;
+--connection default
+SET innodb_lock_wait_timeout=3;
+--error 1205
+UPDATE t1 SET a=2;
+SELECT * FROM t1 LOCK IN SHARE MODE;
+--connection conn1
+ROLLBACK;
+SET innodb_fake_changes=default;
+DROP TABLE t1;
diff --git a/mysql-test/suite/percona/percona_innodb_kill_idle_trx.result b/mysql-test/suite/percona/percona_innodb_kill_idle_trx.result
new file mode 100644
index 00000000000..a05b5a912fe
--- /dev/null
+++ b/mysql-test/suite/percona/percona_innodb_kill_idle_trx.result
@@ -0,0 +1,41 @@
+DROP TABLE IF EXISTS t1;
+SET autocommit=0;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
+Variable_name Value
+innodb_kill_idle_transaction 0
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_KILL_IDLE_TRANSACTION 0
+SET GLOBAL innodb_kill_idle_transaction=1;
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
+Variable_name Value
+innodb_kill_idle_transaction 1
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_KILL_IDLE_TRANSACTION 1
+BEGIN;
+INSERT INTO t1 VALUES (1),(2),(3);
+COMMIT;
+SELECT * FROM t1;
+a
+1
+2
+3
+BEGIN;
+INSERT INTO t1 VALUES (4),(5),(6);
+SELECT * FROM t1;
+ERROR HY000: MySQL server has gone away
+SELECT * FROM t1;
+a
+1
+2
+3
+DROP TABLE t1;
+SET GLOBAL innodb_kill_idle_transaction=0;
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
+Variable_name Value
+innodb_kill_idle_transaction 0
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_KILL_IDLE_TRANSACTION 0
diff --git a/mysql-test/suite/percona/percona_innodb_kill_idle_trx.test b/mysql-test/suite/percona/percona_innodb_kill_idle_trx.test
new file mode 100644
index 00000000000..e1b7b778a31
--- /dev/null
+++ b/mysql-test/suite/percona/percona_innodb_kill_idle_trx.test
@@ -0,0 +1,28 @@
+--source include/have_innodb.inc
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+SET autocommit=0;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+
+--source percona_innodb_kill_idle_trx_show.inc
+SET GLOBAL innodb_kill_idle_transaction=1;
+--source percona_innodb_kill_idle_trx_show.inc
+
+BEGIN;
+INSERT INTO t1 VALUES (1),(2),(3);
+COMMIT;
+SELECT * FROM t1;
+
+BEGIN;
+INSERT INTO t1 VALUES (4),(5),(6);
+sleep 3;
+
+--enable_reconnect
+--error 2006 --error CR_SERVER_GONE_ERROR
+SELECT * FROM t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET GLOBAL innodb_kill_idle_transaction=0;
+--source percona_innodb_kill_idle_trx_show.inc
diff --git a/mysql-test/suite/percona/percona_innodb_kill_idle_trx_locks.result b/mysql-test/suite/percona/percona_innodb_kill_idle_trx_locks.result
new file mode 100644
index 00000000000..6bdd2617805
--- /dev/null
+++ b/mysql-test/suite/percona/percona_innodb_kill_idle_trx_locks.result
@@ -0,0 +1,45 @@
+DROP TABLE IF EXISTS t1;
+SET autocommit=0;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
+Variable_name Value
+innodb_kill_idle_transaction 0
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_KILL_IDLE_TRANSACTION 0
+SET GLOBAL innodb_kill_idle_transaction=5;
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
+Variable_name Value
+innodb_kill_idle_transaction 5
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_KILL_IDLE_TRANSACTION 5
+BEGIN;
+INSERT INTO t1 VALUES (1),(2),(3);
+COMMIT;
+SELECT * FROM t1;
+a
+1
+2
+3
+### Locking rows. Lock should be released when idle trx is killed.
+BEGIN;
+SELECT * FROM t1 FOR UPDATE;
+a
+1
+2
+3
+UPDATE t1 set a=4;
+SELECT * FROM t1;
+a
+4
+4
+4
+DROP TABLE t1;
+SET GLOBAL innodb_kill_idle_transaction=0;
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
+Variable_name Value
+innodb_kill_idle_transaction 0
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
+VARIABLE_NAME VARIABLE_VALUE
+INNODB_KILL_IDLE_TRANSACTION 0
diff --git a/mysql-test/suite/percona/percona_innodb_kill_idle_trx_locks.test b/mysql-test/suite/percona/percona_innodb_kill_idle_trx_locks.test
new file mode 100644
index 00000000000..c283f38de42
--- /dev/null
+++ b/mysql-test/suite/percona/percona_innodb_kill_idle_trx_locks.test
@@ -0,0 +1,31 @@
+--source include/have_innodb.inc
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+SET autocommit=0;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+
+--source percona_innodb_kill_idle_trx_show.inc
+SET GLOBAL innodb_kill_idle_transaction=5;
+--source percona_innodb_kill_idle_trx_show.inc
+
+connect (conn1,localhost,root,,);
+connection conn1;
+
+BEGIN;
+INSERT INTO t1 VALUES (1),(2),(3);
+COMMIT;
+SELECT * FROM t1;
+
+--echo ### Locking rows. Lock should be released when idle trx is killed.
+BEGIN;
+SELECT * FROM t1 FOR UPDATE;
+
+connection default;
+UPDATE t1 set a=4;
+
+SELECT * FROM t1;
+DROP TABLE t1;
+SET GLOBAL innodb_kill_idle_transaction=0;
+--source percona_innodb_kill_idle_trx_show.inc
diff --git a/mysql-test/suite/percona/percona_processlist_row_stats.result b/mysql-test/suite/percona/percona_processlist_row_stats.result
index e9b07b2eaea..109b6a912d9 100644
--- a/mysql-test/suite/percona/percona_processlist_row_stats.result
+++ b/mysql-test/suite/percona/percona_processlist_row_stats.result
@@ -6,69 +6,65 @@ INSERT INTO t2 VALUES(10);
INSERT INTO t2 VALUES(20);
INSERT INTO t2 VALUES(10);
INSERT INTO t2 VALUES(20);
-Issuing operation that should not return any rows and stopping the thread #1
SET DEBUG_SYNC= 'locked_table_name SIGNAL thread1_ready WAIT_FOR threads_dumped';
CREATE TABLE t1 (a INT);
SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready';
-Thread #1 stopped
-Issuing row-returning query and stopping the thread #2 at the end of query
SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread2_ready WAIT_FOR threads_dumped';
SELECT a FROM t2 WHERE a > 15;
SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready';
-Thread #2 stopped
-Look at thread states
SHOW PROCESSLIST;
Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read
### root ### test Query ### ### SHOW PROCESSLIST 0 0 2
### root ### test Query ### ### CREATE TABLE t1 (a INT) 0 0 1
### root ### test Query ### ### SELECT a FROM t2 WHERE a > 15 2 5 6
-SELECT id, info, rows_sent, rows_examined, rows_read FROM information_schema.processlist
-ORDER BY id;
+SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id;
id info rows_sent rows_examined rows_read
-### SELECT id, info, rows_sent, rows_examined, rows_read FROM information_schema.processlist
-ORDER BY id 0 0 1
+### SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id 0 0 1
### CREATE TABLE t1 (a INT) 0 0 1
### SELECT a FROM t2 WHERE a > 15 2 5 6
-Let threads #1 and #2 finish their job
SET DEBUG_SYNC= 'now SIGNAL threads_dumped';
a
20
20
-Issuing row-returning query and stopping the thread #2 in the middle of query
+SET DEBUG_SYNC= 'sent_row SIGNAL thread1_ready WAIT_FOR threads_dumped';
+SELECT a FROM t2 WHERE a < 15;
+SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready';
SET DEBUG_SYNC= 'sent_row SIGNAL thread2_ready WAIT_FOR threads_dumped';
SELECT a FROM t2 WHERE a > 15;
SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready';
-Thread #2 stopped, look at its state
SHOW PROCESSLIST;
Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read
### root ### test Query ### ### SHOW PROCESSLIST 0 0 4
-### root ### test Sleep ### ### NULL 0 0 1
+### root ### test Query ### ### SELECT a FROM t2 WHERE a < 15 1 0 1
### root ### test Query ### ### SELECT a FROM t2 WHERE a > 15 1 0 3
-SELECT id,rows_sent,rows_examined,rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY Id;
-id rows_sent rows_examined rows_read
-### 0 0 1
-### 0 0 1
-### 1 0 3
+SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id;
+id info rows_sent rows_examined rows_read
+### SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id 0 0 1
+### SELECT a FROM t2 WHERE a < 15 1 0 1
+### SELECT a FROM t2 WHERE a > 15 1 0 3
SET DEBUG_SYNC= 'now SIGNAL threads_dumped';
-Let thread #2 finish its job
+a
+10
+10
+10
a
20
20
-Issuing an UPDATE and stopping thread #2
+SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread1_ready WAIT_FOR threads_dumped';
+UPDATE t2 SET a = 15 WHERE a = 20;
+SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready';
SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread2_ready WAIT_FOR threads_dumped';
UPDATE t2 SET a = 15 WHERE a = 10;
SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready';
-Thread #2 stopped, look at its state
SHOW PROCESSLIST;
Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read
### root ### test Query ### ### SHOW PROCESSLIST 0 0 4
-### root ### test Sleep ### ### NULL 0 0 1
+### root ### test Query ### ### UPDATE t2 SET a = 15 WHERE a = 20 0 5 6
### root ### test Query ### ### UPDATE t2 SET a = 15 WHERE a = 10 0 5 6
-SELECT id,rows_sent,rows_examined,rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY Id;
-id rows_sent rows_examined rows_read
-### 0 0 1
-### 0 0 1
-### 0 5 6
+SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id;
+id info rows_sent rows_examined rows_read
+### SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id 0 0 1
+### UPDATE t2 SET a = 15 WHERE a = 20 0 5 6
+### UPDATE t2 SET a = 15 WHERE a = 10 0 5 6
SET DEBUG_SYNC= 'now SIGNAL threads_dumped';
-Let thread #2 finish its job
DROP TABLES t1, t2;
diff --git a/mysql-test/suite/percona/percona_processlist_row_stats.test b/mysql-test/suite/percona/percona_processlist_row_stats.test
index 230a9f4c311..17ebfedfa40 100644
--- a/mysql-test/suite/percona/percona_processlist_row_stats.test
+++ b/mysql-test/suite/percona/percona_processlist_row_stats.test
@@ -13,76 +13,63 @@ INSERT INTO t2 VALUES(20);
INSERT INTO t2 VALUES(10);
INSERT INTO t2 VALUES(20);
-connect (conn1, localhost, root, ,);
-connect (conn2, localhost, root, ,);
+--connect (conn1, localhost, root, ,)
+--connect (conn2, localhost, root, ,)
--connection conn1
-echo Issuing operation that should not return any rows and stopping the thread #1;
SET DEBUG_SYNC= 'locked_table_name SIGNAL thread1_ready WAIT_FOR threads_dumped';
send CREATE TABLE t1 (a INT);
-
--connection default
SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready';
---echo Thread #1 stopped
--connection conn2
-echo Issuing row-returning query and stopping the thread #2 at the end of query;
SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread2_ready WAIT_FOR threads_dumped';
send SELECT a FROM t2 WHERE a > 15;
-
--connection default
SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready';
---echo Thread #2 stopped
---echo Look at thread states
-
---replace_column 1 ### 3 ### 6 ### 7 ###
-SHOW PROCESSLIST;
-# The running threads are different between SHOW above and SELECT below. Thus select info too to
-# show the difference. Results are in the same order as in SHOW.
---replace_column 1 ###
-SELECT id, info, rows_sent, rows_examined, rows_read FROM information_schema.processlist
-ORDER BY id;
-echo Let threads #1 and #2 finish their job;
-SET DEBUG_SYNC= 'now SIGNAL threads_dumped';
+--source include/percona_processlist_row_stats_show.inc
--connection conn1
reap;
-
--connection conn2
reap;
-echo Issuing row-returning query and stopping the thread #2 in the middle of query;
+
+--connection conn1
+SET DEBUG_SYNC= 'sent_row SIGNAL thread1_ready WAIT_FOR threads_dumped';
+send SELECT a FROM t2 WHERE a < 15;
+--connection default
+SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready';
+
+--connection conn2
SET DEBUG_SYNC= 'sent_row SIGNAL thread2_ready WAIT_FOR threads_dumped';
send SELECT a FROM t2 WHERE a > 15;
-
--connection default
SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready';
-echo Thread #2 stopped, look at its state;
---replace_column 1 ### 3 ### 6 ### 7 ###
-SHOW PROCESSLIST;
---replace_column 1 ###
-SELECT id,rows_sent,rows_examined,rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY Id;
-SET DEBUG_SYNC= 'now SIGNAL threads_dumped';
-echo Let thread #2 finish its job;
+--source include/percona_processlist_row_stats_show.inc
+--connection conn1
+reap;
--connection conn2
reap;
-echo Issuing an UPDATE and stopping thread #2;
+
+--connection conn1
+SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread1_ready WAIT_FOR threads_dumped';
+send UPDATE t2 SET a = 15 WHERE a = 20;
+--connection default
+SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready';
+
+--connection conn2
SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread2_ready WAIT_FOR threads_dumped';
send UPDATE t2 SET a = 15 WHERE a = 10;
-
--connection default
SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready';
-echo Thread #2 stopped, look at its state;
---replace_column 1 ### 3 ### 6 ### 7 ###
-SHOW PROCESSLIST;
---replace_column 1 ###
-SELECT id,rows_sent,rows_examined,rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY Id;
-SET DEBUG_SYNC= 'now SIGNAL threads_dumped';
-echo Let thread #2 finish its job;
+--source include/percona_processlist_row_stats_show.inc
+--connection conn1
+reap;
--connection conn2
reap;
diff --git a/mysql-test/suite/percona/percona_query_response_time-replication.result b/mysql-test/suite/percona/percona_query_response_time-replication.result
index fd06d07b4d8..c00520110c2 100644
--- a/mysql-test/suite/percona/percona_query_response_time-replication.result
+++ b/mysql-test/suite/percona/percona_query_response_time-replication.result
@@ -1,66 +1,727 @@
+SET GLOBAL query_exec_time=0.1;
include/master-slave.inc
[connection master]
-DROP TABLE IF EXISTS t;
CREATE TABLE t(id INT);
-SELECT * from t;
-id
-SELECT * from t;
-id
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1;
+SET GLOBAL query_exec_time = 0.1;
+include/restart_slave.inc
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1;
Warnings:
Warning 1292 Truncated incorrect query_response_time_range_base value: '1'
+FLUSH QUERY_RESPONSE_TIME;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+SET SESSION query_exec_time = 0.31;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.32;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.33;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.34;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.35;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.36;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.37;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.38;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.39;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.2;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 3.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 4.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 5.1;
+INSERT INTO t VALUES(1);
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
+Variable_name Value
+query_response_time_range_base 2
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 1 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 1 0.100000
+ 0.250000 0 0.000000
+ 0.500000 30 10.650000
+ 1.000000 3 1.500000
+ 2.000000 15 19.500000
+ 4.000000 12 30.000000
+ 8.000000 6 27.599997
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 1 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 1 0.100000
+ 0.250000 0 0.000000
+ 0.500000 30 10.650000
+ 1.000000 3 1.500000
+ 2.000000 15 19.500000
+ 4.000000 12 30.000000
+ 8.000000 6 27.599997
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
+DROP TABLE t;
+CREATE TABLE t(id INT);
+SET GLOBAL query_exec_time = 0.1;
+include/restart_slave.inc
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=2;
+FLUSH QUERY_RESPONSE_TIME;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+SET SESSION query_exec_time = 0.31;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.32;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.33;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.34;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.35;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.36;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.37;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.38;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.39;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.2;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 3.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 4.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 5.1;
+INSERT INTO t VALUES(1);
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 2
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10;
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 1 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 1 0.100000
+ 0.250000 0 0.000000
+ 0.500000 30 10.650000
+ 1.000000 3 1.500000
+ 2.000000 15 19.500000
+ 4.000000 12 30.000000
+ 8.000000 6 27.599997
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 1 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 1 0.100000
+ 0.250000 0 0.000000
+ 0.500000 30 10.650000
+ 1.000000 3 1.500000
+ 2.000000 15 19.500000
+ 4.000000 12 30.000000
+ 8.000000 6 27.599997
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
+DROP TABLE t;
+CREATE TABLE t(id INT);
+SET GLOBAL query_exec_time = 0.1;
+include/restart_slave.inc
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=10;
+FLUSH QUERY_RESPONSE_TIME;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+SET SESSION query_exec_time = 0.31;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.32;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.33;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.34;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.35;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.36;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.37;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.38;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.39;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.2;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 3.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 4.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 5.1;
+INSERT INTO t VALUES(1);
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 10
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 1 0.000000
+ 0.000010 0 0.000000
+ 0.000100 0 0.000000
+ 0.001000 0 0.000000
+ 0.010000 0 0.000000
+ 0.100000 0 0.000000
+ 1.000000 34 12.250000
+ 10.000000 33 77.099997
+ 100.000000 0 0.000000
+ 1000.000000 0 0.000000
+ 10000.000000 0 0.000000
+ 100000.000000 0 0.000000
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 1 0.000000
+ 0.000010 0 0.000000
+ 0.000100 0 0.000000
+ 0.001000 0 0.000000
+ 0.010000 0 0.000000
+ 0.100000 0 0.000000
+ 1.000000 34 12.250000
+ 10.000000 33 77.099997
+ 100.000000 0 0.000000
+ 1000.000000 0 0.000000
+ 10000.000000 0 0.000000
+ 100000.000000 0 0.000000
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
+DROP TABLE t;
+CREATE TABLE t(id INT);
+SET GLOBAL query_exec_time = 0.1;
+include/restart_slave.inc
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=7;
FLUSH QUERY_RESPONSE_TIME;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=ON;
-INSERT INTO t SELECT SLEEP(0.4);
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count)
-0
-INSERT INTO t SELECT SLEEP(0.4);
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count)
-0
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count)
-2
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count)
-3
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 2;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+SET SESSION query_exec_time = 0.31;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.32;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.33;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.34;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.35;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.36;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.37;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.38;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.39;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.2;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 3.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 4.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 5.1;
+INSERT INTO t VALUES(1);
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
-query_response_time_range_base 2
+query_response_time_range_base 7
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 1 0.000000
+ 0.000008 0 0.000000
+ 0.000059 0 0.000000
+ 0.000416 0 0.000000
+ 0.002915 0 0.000000
+ 0.020408 0 0.000000
+ 0.142857 1 0.100000
+ 1.000000 33 12.150000
+ 7.000000 33 77.099997
+ 49.000000 0 0.000000
+ 343.000000 0 0.000000
+ 2401.000000 0 0.000000
+ 16807.000000 0 0.000000
+ 117649.000000 0 0.000000
+ 823543.000000 0 0.000000
+ 5764801.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 1 0.000000
+ 0.000008 0 0.000000
+ 0.000059 0 0.000000
+ 0.000416 0 0.000000
+ 0.002915 0 0.000000
+ 0.020408 0 0.000000
+ 0.142857 1 0.100000
+ 1.000000 33 12.150000
+ 7.000000 33 77.099997
+ 49.000000 0 0.000000
+ 343.000000 0 0.000000
+ 2401.000000 0 0.000000
+ 16807.000000 0 0.000000
+ 117649.000000 0 0.000000
+ 823543.000000 0 0.000000
+ 5764801.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
+DROP TABLE t;
+CREATE TABLE t(id INT);
+SET GLOBAL query_exec_time = 0.1;
+include/restart_slave.inc
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=156;
FLUSH QUERY_RESPONSE_TIME;
-INSERT INTO t SELECT SLEEP(0.4);
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count)
-0
-INSERT INTO t SELECT SLEEP(0.4);
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+SET SESSION query_exec_time = 0.31;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.32;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.33;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.34;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.35;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.36;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.37;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.38;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.39;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.2;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 3.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 4.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 5.1;
+INSERT INTO t VALUES(1);
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
+Variable_name Value
+query_response_time_range_base 156
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000041 1 0.000000
+ 0.006410 0 0.000000
+ 1.000000 34 12.250000
+ 156.000000 33 77.099997
+ 24336.000000 0 0.000000
+ 3796416.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000041 1 0.000000
+ 0.006410 0 0.000000
+ 1.000000 34 12.250000
+ 156.000000 33 77.099997
+ 24336.000000 0 0.000000
+ 3796416.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
+DROP TABLE t;
+CREATE TABLE t(id INT);
+SET GLOBAL query_exec_time = 0.1;
+include/restart_slave.inc
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1000;
+FLUSH QUERY_RESPONSE_TIME;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+SET SESSION query_exec_time = 0.31;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.32;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.33;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.34;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.35;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.36;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.37;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.38;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.39;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.2;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 3.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 4.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 5.1;
+INSERT INTO t VALUES(1);
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
+Variable_name Value
+query_response_time_range_base 1000
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 1 0.000000
+ 0.001000 0 0.000000
+ 1.000000 34 12.250000
+ 1000.000000 33 77.099997
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 1 0.000000
+ 0.001000 0 0.000000
+ 1.000000 34 12.250000
+ 1000.000000 33 77.099997
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
+DROP TABLE t;
+CREATE TABLE t(id INT);
+SET GLOBAL query_exec_time = 0.1;
+include/restart_slave.inc
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1001;
Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count)
-0
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count)
-2
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count)
-3
-DROP TABLE IF EXISTS t;
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=OFF;
-STOP SLAVE;
-include/wait_for_slave_to_stop.inc
+Warning 1292 Truncated incorrect query_response_time_range_base value: '1001'
+FLUSH QUERY_RESPONSE_TIME;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+SET SESSION query_exec_time = 0.31;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.32;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.33;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.34;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.35;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.36;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.37;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.38;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.39;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.2;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.4;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.3;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.5;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 3.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 4.1;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 5.1;
+INSERT INTO t VALUES(1);
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
+Variable_name Value
+query_response_time_range_base 1000
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 1 0.000000
+ 0.001000 0 0.000000
+ 1.000000 34 12.250000
+ 1000.000000 33 77.099997
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 1 0.000000
+ 0.001000 0 0.000000
+ 1.000000 34 12.250000
+ 1000.000000 33 77.099997
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
+DROP TABLE t;
+include/rpl_end.inc
+SET GLOBAL query_exec_time=default;
+SET GLOBAL query_exec_time=default;
diff --git a/mysql-test/suite/percona/percona_query_response_time-replication.test b/mysql-test/suite/percona/percona_query_response_time-replication.test
index 199ecce0977..1207e5d1c3d 100644
--- a/mysql-test/suite/percona/percona_query_response_time-replication.test
+++ b/mysql-test/suite/percona/percona_query_response_time-replication.test
@@ -1,61 +1,28 @@
+SET GLOBAL query_exec_time=0.1;
+
--source include/have_response_time_distribution.inc
---source include/master-slave.inc
---source include/have_binlog_format_statement.inc
--source include/have_debug.inc
---disable_query_log
-call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. Statement:");
---enable_query_log
-
-connection master;
--- disable_warnings
-DROP TABLE IF EXISTS t;
--- enable_warnings
-CREATE TABLE t(id INT);
-SELECT * from t;
-
-sync_slave_with_master;
-
-connection slave;
-SELECT * from t;
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-source include/percona_query_response_time_flush.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=ON;
-
-connection master;
-INSERT INTO t SELECT SLEEP(0.4);
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-INSERT INTO t SELECT SLEEP(0.4);
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-sync_slave_with_master;
-
-connection slave;
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 2;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-source include/percona_query_response_time_flush.inc;
-
-connection master;
-INSERT INTO t SELECT SLEEP(0.4);
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-INSERT INTO t SELECT SLEEP(0.4);
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-sync_slave_with_master;
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
-connection slave;
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+--let base=1
+--source include/query_response_time-replication.inc
+--let base=2
+--source include/query_response_time-replication.inc
+--let base=10
+--source include/query_response_time-replication.inc
+--let base=7
+--source include/query_response_time-replication.inc
+--let base=156
+--source include/query_response_time-replication.inc
+--let base=1000
+--source include/query_response_time-replication.inc
+--let base=1001
+--source include/query_response_time-replication.inc
+
+--source include/rpl_end.inc
+
+SET GLOBAL query_exec_time=default;
-connection master;
-DROP TABLE IF EXISTS t;
-sync_slave_with_master;
connection slave;
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=OFF;
-
-STOP SLAVE;
--- source include/wait_for_slave_to_stop.inc
+SET GLOBAL query_exec_time=default;
diff --git a/mysql-test/suite/percona/percona_query_response_time-stored.result b/mysql-test/suite/percona/percona_query_response_time-stored.result
index 0168c4630be..7385231241e 100644
--- a/mysql-test/suite/percona/percona_query_response_time-stored.result
+++ b/mysql-test/suite/percona/percona_query_response_time-stored.result
@@ -1,306 +1,544 @@
-SET GLOBAL debug="d,query_exec_time_debug";
-CREATE FUNCTION test_f()
-RETURNS CHAR(30) DETERMINISTIC
+CREATE TABLE t(a INT);
+CREATE PROCEDURE test_f(t DECIMAL(3,2))
BEGIN
-SET SESSION debug="+d,query_exec_time_1.1";
-RETURN 'Hello, world!';
-END/
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1;
+SET SESSION query_exec_time=t;
+INSERT INTO t VALUES(1);
+SET SESSION query_exec_time=0.1;
+DELETE FROM t;
+END^
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1;
Warnings:
Warning 1292 Truncated incorrect query_response_time_range_base value: '1'
+FLUSH QUERY_RESPONSE_TIME;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+CALL test_f(0.31);
+CALL test_f(0.32);
+CALL test_f(0.33);
+CALL test_f(0.34);
+CALL test_f(0.35);
+CALL test_f(0.36);
+CALL test_f(0.37);
+CALL test_f(0.38);
+CALL test_f(0.39);
+CALL test_f(0.4);
+CALL test_f(1.1);
+CALL test_f(1.2);
+CALL test_f(1.3);
+CALL test_f(1.5);
+CALL test_f(1.4);
+CALL test_f(0.5);
+CALL test_f(2.1);
+CALL test_f(2.3);
+CALL test_f(2.5);
+CALL test_f(3.1);
+CALL test_f(4.1);
+CALL test_f(5.1);
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 2
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 2;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-Variable_name Value
-query_response_time_range_base 2
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 45 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 44 4.400000
+ 0.250000 0 0.000000
+ 0.500000 10 3.550000
+ 1.000000 1 0.500000
+ 2.000000 5 6.500000
+ 4.000000 4 10.000000
+ 8.000000 2 9.199999
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 45 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 44 4.400000
+ 0.250000 0 0.000000
+ 0.500000 10 3.550000
+ 1.000000 1 0.500000
+ 2.000000 5 6.500000
+ 4.000000 4 10.000000
+ 8.000000 2 9.199999
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=2;
FLUSH QUERY_RESPONSE_TIME;
-SELECT d.count,
-(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count,
-(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count
-FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0;
-count query_count query_total not_zero_region_count region_count
-SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-region_count
-44
-SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-time
- 0.000001
- 0.000003
- 0.000007
- 0.000015
- 0.000030
- 0.000061
- 0.000122
- 0.000244
- 0.000488
- 0.000976
- 0.001953
- 0.003906
- 0.007812
- 0.015625
- 0.031250
- 0.062500
- 0.125000
- 0.250000
- 0.500000
- 1.000000
- 2.000000
- 4.000000
- 8.000000
- 16.000000
- 32.000000
- 64.000000
- 128.000000
- 256.000000
- 512.000000
- 1024.000000
- 2048.000000
- 4096.000000
- 8192.000000
- 16384.000000
- 32768.000000
- 65536.000000
- 131072.000000
- 262144.000000
- 524288.000000
- 1048576.00000
- 2097152.00000
- 4194304.00000
- 8388608.00000
-TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SELECT test_f();
-test_f()
-Hello, world!
-SELECT test_f();
-test_f()
-Hello, world!
-SELECT test_f();
-test_f()
-Hello, world!
-SELECT test_f();
-test_f()
-Hello, world!
+CALL test_f(0.31);
+CALL test_f(0.32);
+CALL test_f(0.33);
+CALL test_f(0.34);
+CALL test_f(0.35);
+CALL test_f(0.36);
+CALL test_f(0.37);
+CALL test_f(0.38);
+CALL test_f(0.39);
+CALL test_f(0.4);
+CALL test_f(1.1);
+CALL test_f(1.2);
+CALL test_f(1.3);
+CALL test_f(1.5);
+CALL test_f(1.4);
+CALL test_f(0.5);
+CALL test_f(2.1);
+CALL test_f(2.3);
+CALL test_f(2.5);
+CALL test_f(3.1);
+CALL test_f(4.1);
+CALL test_f(5.1);
SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SELECT d.count,
-(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count,
-(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count
-FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0;
-count query_count query_total not_zero_region_count region_count
-4 4 4 1 44
-SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-region_count
-44
-SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-time
- 0.000001
- 0.000003
- 0.000007
- 0.000015
- 0.000030
- 0.000061
- 0.000122
- 0.000244
- 0.000488
- 0.000976
- 0.001953
- 0.003906
- 0.007812
- 0.015625
- 0.031250
- 0.062500
- 0.125000
- 0.250000
- 0.500000
- 1.000000
- 2.000000
- 4.000000
- 8.000000
- 16.000000
- 32.000000
- 64.000000
- 128.000000
- 256.000000
- 512.000000
- 1024.000000
- 2048.000000
- 4096.000000
- 8192.000000
- 16384.000000
- 32768.000000
- 65536.000000
- 131072.000000
- 262144.000000
- 524288.000000
- 1048576.00000
- 2097152.00000
- 4194304.00000
- 8388608.00000
-TOO LONG
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 2
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-Variable_name Value
-query_response_time_range_base 10
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 45 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 44 4.400000
+ 0.250000 0 0.000000
+ 0.500000 10 3.550000
+ 1.000000 1 0.500000
+ 2.000000 5 6.500000
+ 4.000000 4 10.000000
+ 8.000000 2 9.199999
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 45 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 44 4.400000
+ 0.250000 0 0.000000
+ 0.500000 10 3.550000
+ 1.000000 1 0.500000
+ 2.000000 5 6.500000
+ 4.000000 4 10.000000
+ 8.000000 2 9.199999
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=10;
FLUSH QUERY_RESPONSE_TIME;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SELECT test_f();
-test_f()
-Hello, world!
+CALL test_f(0.31);
+CALL test_f(0.32);
+CALL test_f(0.33);
+CALL test_f(0.34);
+CALL test_f(0.35);
+CALL test_f(0.36);
+CALL test_f(0.37);
+CALL test_f(0.38);
+CALL test_f(0.39);
+CALL test_f(0.4);
+CALL test_f(1.1);
+CALL test_f(1.2);
+CALL test_f(1.3);
+CALL test_f(1.5);
+CALL test_f(1.4);
+CALL test_f(0.5);
+CALL test_f(2.1);
+CALL test_f(2.3);
+CALL test_f(2.5);
+CALL test_f(3.1);
+CALL test_f(4.1);
+CALL test_f(5.1);
SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SELECT d.count,
-(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count,
-(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count
-FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0;
-count query_count query_total not_zero_region_count region_count
-1 1 1 1 14
-SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-region_count
-14
-SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-time
- 0.000001
- 0.000010
- 0.000100
- 0.001000
- 0.010000
- 0.100000
- 1.000000
- 10.000000
- 100.000000
- 1000.000000
- 10000.000000
- 100000.000000
- 1000000.00000
-TOO LONG
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 10
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 7;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-Variable_name Value
-query_response_time_range_base 7
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 45 0.000000
+ 0.000010 0 0.000000
+ 0.000100 0 0.000000
+ 0.001000 0 0.000000
+ 0.010000 0 0.000000
+ 0.100000 0 0.000000
+ 1.000000 55 8.450000
+ 10.000000 11 25.699999
+ 100.000000 0 0.000000
+ 1000.000000 0 0.000000
+ 10000.000000 0 0.000000
+ 100000.000000 0 0.000000
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 45 0.000000
+ 0.000010 0 0.000000
+ 0.000100 0 0.000000
+ 0.001000 0 0.000000
+ 0.010000 0 0.000000
+ 0.100000 0 0.000000
+ 1.000000 55 8.450000
+ 10.000000 11 25.699999
+ 100.000000 0 0.000000
+ 1000.000000 0 0.000000
+ 10000.000000 0 0.000000
+ 100000.000000 0 0.000000
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=7;
FLUSH QUERY_RESPONSE_TIME;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SELECT test_f();
-test_f()
-Hello, world!
+CALL test_f(0.31);
+CALL test_f(0.32);
+CALL test_f(0.33);
+CALL test_f(0.34);
+CALL test_f(0.35);
+CALL test_f(0.36);
+CALL test_f(0.37);
+CALL test_f(0.38);
+CALL test_f(0.39);
+CALL test_f(0.4);
+CALL test_f(1.1);
+CALL test_f(1.2);
+CALL test_f(1.3);
+CALL test_f(1.5);
+CALL test_f(1.4);
+CALL test_f(0.5);
+CALL test_f(2.1);
+CALL test_f(2.3);
+CALL test_f(2.5);
+CALL test_f(3.1);
+CALL test_f(4.1);
+CALL test_f(5.1);
SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SELECT d.count,
-(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count,
-(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count
-FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0;
-count query_count query_total not_zero_region_count region_count
-1 1 1 1 17
-SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-region_count
-17
-SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-time
- 0.000001
- 0.000008
- 0.000059
- 0.000416
- 0.002915
- 0.020408
- 0.142857
- 1.000000
- 7.000000
- 49.000000
- 343.000000
- 2401.000000
- 16807.000000
- 117649.000000
- 823543.000000
- 5764801.00000
-TOO LONG
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 7
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 156;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-Variable_name Value
-query_response_time_range_base 156
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 45 0.000000
+ 0.000008 0 0.000000
+ 0.000059 0 0.000000
+ 0.000416 0 0.000000
+ 0.002915 0 0.000000
+ 0.020408 0 0.000000
+ 0.142857 44 4.400000
+ 1.000000 11 4.050000
+ 7.000000 11 25.699999
+ 49.000000 0 0.000000
+ 343.000000 0 0.000000
+ 2401.000000 0 0.000000
+ 16807.000000 0 0.000000
+ 117649.000000 0 0.000000
+ 823543.000000 0 0.000000
+ 5764801.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 45 0.000000
+ 0.000008 0 0.000000
+ 0.000059 0 0.000000
+ 0.000416 0 0.000000
+ 0.002915 0 0.000000
+ 0.020408 0 0.000000
+ 0.142857 44 4.400000
+ 1.000000 11 4.050000
+ 7.000000 11 25.699999
+ 49.000000 0 0.000000
+ 343.000000 0 0.000000
+ 2401.000000 0 0.000000
+ 16807.000000 0 0.000000
+ 117649.000000 0 0.000000
+ 823543.000000 0 0.000000
+ 5764801.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=156;
FLUSH QUERY_RESPONSE_TIME;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SELECT test_f();
-test_f()
-Hello, world!
+CALL test_f(0.31);
+CALL test_f(0.32);
+CALL test_f(0.33);
+CALL test_f(0.34);
+CALL test_f(0.35);
+CALL test_f(0.36);
+CALL test_f(0.37);
+CALL test_f(0.38);
+CALL test_f(0.39);
+CALL test_f(0.4);
+CALL test_f(1.1);
+CALL test_f(1.2);
+CALL test_f(1.3);
+CALL test_f(1.5);
+CALL test_f(1.4);
+CALL test_f(0.5);
+CALL test_f(2.1);
+CALL test_f(2.3);
+CALL test_f(2.5);
+CALL test_f(3.1);
+CALL test_f(4.1);
+CALL test_f(5.1);
SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SELECT d.count,
-(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count,
-(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count
-FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0;
-count query_count query_total not_zero_region_count region_count
-1 1 1 1 7
-SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-region_count
-7
-SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-time
- 0.000041
- 0.006410
- 1.000000
- 156.000000
- 24336.000000
- 3796416.00000
-TOO LONG
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 156
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1000;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-Variable_name Value
-query_response_time_range_base 1000
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000041 45 0.000000
+ 0.006410 0 0.000000
+ 1.000000 55 8.450000
+ 156.000000 11 25.699999
+ 24336.000000 0 0.000000
+ 3796416.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000041 45 0.000000
+ 0.006410 0 0.000000
+ 1.000000 55 8.450000
+ 156.000000 11 25.699999
+ 24336.000000 0 0.000000
+ 3796416.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1000;
FLUSH QUERY_RESPONSE_TIME;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SELECT test_f();
-test_f()
-Hello, world!
+CALL test_f(0.31);
+CALL test_f(0.32);
+CALL test_f(0.33);
+CALL test_f(0.34);
+CALL test_f(0.35);
+CALL test_f(0.36);
+CALL test_f(0.37);
+CALL test_f(0.38);
+CALL test_f(0.39);
+CALL test_f(0.4);
+CALL test_f(1.1);
+CALL test_f(1.2);
+CALL test_f(1.3);
+CALL test_f(1.5);
+CALL test_f(1.4);
+CALL test_f(0.5);
+CALL test_f(2.1);
+CALL test_f(2.3);
+CALL test_f(2.5);
+CALL test_f(3.1);
+CALL test_f(4.1);
+CALL test_f(5.1);
SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SELECT d.count,
-(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count,
-(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count
-FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0;
-count query_count query_total not_zero_region_count region_count
-1 1 1 1 6
-SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-region_count
-6
-SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-time
- 0.000001
- 0.001000
- 1.000000
- 1000.000000
- 1000000.00000
-TOO LONG
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 1000
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1001;
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 45 0.000000
+ 0.001000 0 0.000000
+ 1.000000 55 8.450000
+ 1000.000000 11 25.699999
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 45 0.000000
+ 0.001000 0 0.000000
+ 1.000000 55 8.450000
+ 1000.000000 11 25.699999
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1001;
Warnings:
Warning 1292 Truncated incorrect query_response_time_range_base value: '1001'
+FLUSH QUERY_RESPONSE_TIME;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+CALL test_f(0.31);
+CALL test_f(0.32);
+CALL test_f(0.33);
+CALL test_f(0.34);
+CALL test_f(0.35);
+CALL test_f(0.36);
+CALL test_f(0.37);
+CALL test_f(0.38);
+CALL test_f(0.39);
+CALL test_f(0.4);
+CALL test_f(1.1);
+CALL test_f(1.2);
+CALL test_f(1.3);
+CALL test_f(1.5);
+CALL test_f(1.4);
+CALL test_f(0.5);
+CALL test_f(2.1);
+CALL test_f(2.3);
+CALL test_f(2.5);
+CALL test_f(3.1);
+CALL test_f(4.1);
+CALL test_f(5.1);
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 1000
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE =10;
-DROP FUNCTION test_f;
-SET GLOBAL debug=default;
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 45 0.000000
+ 0.001000 0 0.000000
+ 1.000000 55 8.450000
+ 1000.000000 11 25.699999
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 45 0.000000
+ 0.001000 0 0.000000
+ 1.000000 55 8.450000
+ 1000.000000 11 25.699999
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
+DROP PROCEDURE test_f;
+DROP TABLE t;
diff --git a/mysql-test/suite/percona/percona_query_response_time-stored.test b/mysql-test/suite/percona/percona_query_response_time-stored.test
index e80fc3dd3c0..847ff223b3f 100644
--- a/mysql-test/suite/percona/percona_query_response_time-stored.test
+++ b/mysql-test/suite/percona/percona_query_response_time-stored.test
@@ -1,85 +1,36 @@
--source include/have_response_time_distribution.inc
--source include/have_debug.inc
-SET GLOBAL debug="d,query_exec_time_debug";
+CREATE TABLE t(a INT);
-delimiter /;
-CREATE FUNCTION test_f()
-RETURNS CHAR(30) DETERMINISTIC
+delimiter ^;
+CREATE PROCEDURE test_f(t DECIMAL(3,2))
BEGIN
- SET SESSION debug="+d,query_exec_time_1.1";
- RETURN 'Hello, world!';
-END/
-delimiter ;/
-
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 2;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-
-source include/percona_query_response_time_flush.inc;
-source include/percona_query_response_time_show.inc;
-
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SELECT test_f();
-SELECT test_f();
-SELECT test_f();
-SELECT test_f();
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-
-source include/percona_query_response_time_show.inc;
-
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-
-source include/percona_query_response_time_flush.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SELECT test_f();
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-
-source include/percona_query_response_time_show.inc;
-
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 7;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-
-source include/percona_query_response_time_flush.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SELECT test_f();
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-
-source include/percona_query_response_time_show.inc;
-
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 156;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-
-source include/percona_query_response_time_flush.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SELECT test_f();
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-
-source include/percona_query_response_time_show.inc;
-
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1000;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-
-source include/percona_query_response_time_flush.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SELECT test_f();
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-
-source include/percona_query_response_time_show.inc;
-
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1001;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE =10;
-
-DROP FUNCTION test_f;
-
-SET GLOBAL debug=default;
+ SET SESSION query_exec_time=t;
+ INSERT INTO t VALUES(1);
+ SET SESSION query_exec_time=0.1;
+ DELETE FROM t;
+END^
+delimiter ;^
+
+--let base=1
+--source include/query_response_time-stored.inc
+--let base=2
+--source include/query_response_time-stored.inc
+--let base=10
+--source include/query_response_time-stored.inc
+--let base=7
+--source include/query_response_time-stored.inc
+--let base=156
+--source include/query_response_time-stored.inc
+--let base=1000
+--source include/query_response_time-stored.inc
+--let base=1001
+--source include/query_response_time-stored.inc
+
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
+
+DROP PROCEDURE test_f;
+
+DROP TABLE t;
diff --git a/mysql-test/suite/percona/percona_query_response_time.result b/mysql-test/suite/percona/percona_query_response_time.result
index 2243c155e39..4c4d50319c0 100644
--- a/mysql-test/suite/percona/percona_query_response_time.result
+++ b/mysql-test/suite/percona/percona_query_response_time.result
@@ -1,377 +1,1307 @@
-SET GLOBAL debug="d,query_exec_time_debug";
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1;
Warnings:
Warning 1292 Truncated incorrect query_response_time_range_base value: '1'
+FLUSH QUERY_RESPONSE_TIME;
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 0 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 0 0.000000
+ 0.250000 0 0.000000
+ 0.500000 0 0.000000
+ 1.000000 0 0.000000
+ 2.000000 0 0.000000
+ 4.000000 0 0.000000
+ 8.000000 0 0.000000
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 0 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 0 0.000000
+ 0.250000 0 0.000000
+ 0.500000 0 0.000000
+ 1.000000 0 0.000000
+ 2.000000 0 0.000000
+ 4.000000 0 0.000000
+ 8.000000 0 0.000000
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+SET SESSION query_exec_time=0.31;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.32;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.33;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.34;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.35;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.36;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.37;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.38;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.39;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.2;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=3.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=4.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=5.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 2
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 2;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-Variable_name Value
-query_response_time_range_base 2
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 24 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 0 0.000000
+ 0.250000 0 0.000000
+ 0.500000 10 3.550000
+ 1.000000 1 0.500000
+ 2.000000 5 6.500000
+ 4.000000 4 10.000000
+ 8.000000 2 9.199999
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 24 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 0 0.000000
+ 0.250000 0 0.000000
+ 0.500000 10 3.550000
+ 1.000000 1 0.500000
+ 2.000000 5 6.500000
+ 4.000000 4 10.000000
+ 8.000000 2 9.199999
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=2;
FLUSH QUERY_RESPONSE_TIME;
-SELECT d.count,
-(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count,
-(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count
-FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0;
-count query_count query_total not_zero_region_count region_count
-SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-region_count
-44
-SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-time
- 0.000001
- 0.000003
- 0.000007
- 0.000015
- 0.000030
- 0.000061
- 0.000122
- 0.000244
- 0.000488
- 0.000976
- 0.001953
- 0.003906
- 0.007812
- 0.015625
- 0.031250
- 0.062500
- 0.125000
- 0.250000
- 0.500000
- 1.000000
- 2.000000
- 4.000000
- 8.000000
- 16.000000
- 32.000000
- 64.000000
- 128.000000
- 256.000000
- 512.000000
- 1024.000000
- 2048.000000
- 4096.000000
- 8192.000000
- 16384.000000
- 32768.000000
- 65536.000000
- 131072.000000
- 262144.000000
- 524288.000000
- 1048576.00000
- 2097152.00000
- 4194304.00000
- 8388608.00000
-TOO LONG
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 0 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 0 0.000000
+ 0.250000 0 0.000000
+ 0.500000 0 0.000000
+ 1.000000 0 0.000000
+ 2.000000 0 0.000000
+ 4.000000 0 0.000000
+ 8.000000 0 0.000000
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 0 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 0 0.000000
+ 0.250000 0 0.000000
+ 0.500000 0 0.000000
+ 1.000000 0 0.000000
+ 2.000000 0 0.000000
+ 4.000000 0 0.000000
+ 8.000000 0 0.000000
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SET SESSION debug="+d,query_exec_time_0.31";
-SET SESSION debug="+d,query_exec_time_0.32";
-SET SESSION debug="+d,query_exec_time_0.33";
-SET SESSION debug="+d,query_exec_time_0.34";
-SET SESSION debug="+d,query_exec_time_0.35";
-SET SESSION debug="+d,query_exec_time_0.36";
-SET SESSION debug="+d,query_exec_time_0.37";
-SET SESSION debug="+d,query_exec_time_0.38";
-SET SESSION debug="+d,query_exec_time_0.39";
-SET SESSION debug="+d,query_exec_time_0.4";
-SET SESSION debug="+d,query_exec_time_1.1";
-SET SESSION debug="+d,query_exec_time_1.2";
-SET SESSION debug="+d,query_exec_time_1.3";
-SET SESSION debug="+d,query_exec_time_1.5";
-SET SESSION debug="+d,query_exec_time_1.4";
-SET SESSION debug="+d,query_exec_time_0.5";
-SET SESSION debug="+d,query_exec_time_2.1";
-SET SESSION debug="+d,query_exec_time_2.3";
-SET SESSION debug="+d,query_exec_time_2.5";
+SET SESSION query_exec_time=0.31;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.32;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.33;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.34;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.35;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.36;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.37;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.38;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.39;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.2;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=3.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=4.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=5.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.1;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SELECT d.count,
-(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count,
-(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count
-FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0;
-count query_count query_total not_zero_region_count region_count
-10 19 15 4 44
-1 19 15 4 44
-5 19 15 4 44
-3 19 15 4 44
-SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-region_count
-44
-SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-time
- 0.000001
- 0.000003
- 0.000007
- 0.000015
- 0.000030
- 0.000061
- 0.000122
- 0.000244
- 0.000488
- 0.000976
- 0.001953
- 0.003906
- 0.007812
- 0.015625
- 0.031250
- 0.062500
- 0.125000
- 0.250000
- 0.500000
- 1.000000
- 2.000000
- 4.000000
- 8.000000
- 16.000000
- 32.000000
- 64.000000
- 128.000000
- 256.000000
- 512.000000
- 1024.000000
- 2048.000000
- 4096.000000
- 8192.000000
- 16384.000000
- 32768.000000
- 65536.000000
- 131072.000000
- 262144.000000
- 524288.000000
- 1048576.00000
- 2097152.00000
- 4194304.00000
- 8388608.00000
-TOO LONG
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 2
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-Variable_name Value
-query_response_time_range_base 10
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 24 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 0 0.000000
+ 0.250000 0 0.000000
+ 0.500000 10 3.550000
+ 1.000000 1 0.500000
+ 2.000000 5 6.500000
+ 4.000000 4 10.000000
+ 8.000000 2 9.199999
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 24 0.000000
+ 0.000003 0 0.000000
+ 0.000007 0 0.000000
+ 0.000015 0 0.000000
+ 0.000030 0 0.000000
+ 0.000061 0 0.000000
+ 0.000122 0 0.000000
+ 0.000244 0 0.000000
+ 0.000488 0 0.000000
+ 0.000976 0 0.000000
+ 0.001953 0 0.000000
+ 0.003906 0 0.000000
+ 0.007812 0 0.000000
+ 0.015625 0 0.000000
+ 0.031250 0 0.000000
+ 0.062500 0 0.000000
+ 0.125000 0 0.000000
+ 0.250000 0 0.000000
+ 0.500000 10 3.550000
+ 1.000000 1 0.500000
+ 2.000000 5 6.500000
+ 4.000000 4 10.000000
+ 8.000000 2 9.199999
+ 16.000000 0 0.000000
+ 32.000000 0 0.000000
+ 64.000000 0 0.000000
+ 128.000000 0 0.000000
+ 256.000000 0 0.000000
+ 512.000000 0 0.000000
+ 1024.000000 0 0.000000
+ 2048.000000 0 0.000000
+ 4096.000000 0 0.000000
+ 8192.000000 0 0.000000
+ 16384.000000 0 0.000000
+ 32768.000000 0 0.000000
+ 65536.000000 0 0.000000
+ 131072.000000 0 0.000000
+ 262144.000000 0 0.000000
+ 524288.000000 0 0.000000
+ 1048576.00000 0 0.000000
+ 2097152.00000 0 0.000000
+ 4194304.00000 0 0.000000
+ 8388608.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=10;
FLUSH QUERY_RESPONSE_TIME;
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 0 0.000000
+ 0.000010 0 0.000000
+ 0.000100 0 0.000000
+ 0.001000 0 0.000000
+ 0.010000 0 0.000000
+ 0.100000 0 0.000000
+ 1.000000 0 0.000000
+ 10.000000 0 0.000000
+ 100.000000 0 0.000000
+ 1000.000000 0 0.000000
+ 10000.000000 0 0.000000
+ 100000.000000 0 0.000000
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 0 0.000000
+ 0.000010 0 0.000000
+ 0.000100 0 0.000000
+ 0.001000 0 0.000000
+ 0.010000 0 0.000000
+ 0.100000 0 0.000000
+ 1.000000 0 0.000000
+ 10.000000 0 0.000000
+ 100.000000 0 0.000000
+ 1000.000000 0 0.000000
+ 10000.000000 0 0.000000
+ 100000.000000 0 0.000000
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SET SESSION debug="+d,query_exec_time_0.31";
-SET SESSION debug="+d,query_exec_time_0.32";
-SET SESSION debug="+d,query_exec_time_0.33";
-SET SESSION debug="+d,query_exec_time_0.34";
-SET SESSION debug="+d,query_exec_time_0.35";
-SET SESSION debug="+d,query_exec_time_0.36";
-SET SESSION debug="+d,query_exec_time_0.37";
-SET SESSION debug="+d,query_exec_time_0.38";
-SET SESSION debug="+d,query_exec_time_0.39";
-SET SESSION debug="+d,query_exec_time_0.4";
-SET SESSION debug="+d,query_exec_time_1.1";
-SET SESSION debug="+d,query_exec_time_1.2";
-SET SESSION debug="+d,query_exec_time_1.3";
-SET SESSION debug="+d,query_exec_time_1.5";
-SET SESSION debug="+d,query_exec_time_1.4";
-SET SESSION debug="+d,query_exec_time_0.5";
-SET SESSION debug="+d,query_exec_time_2.1";
-SET SESSION debug="+d,query_exec_time_2.3";
-SET SESSION debug="+d,query_exec_time_2.5";
+SET SESSION query_exec_time=0.31;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.32;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.33;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.34;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.35;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.36;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.37;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.38;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.39;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.2;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=3.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=4.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=5.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.1;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SELECT d.count,
-(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count,
-(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count
-FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0;
-count query_count query_total not_zero_region_count region_count
-11 19 17 2 14
-8 19 17 2 14
-SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-region_count
-14
-SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-time
- 0.000001
- 0.000010
- 0.000100
- 0.001000
- 0.010000
- 0.100000
- 1.000000
- 10.000000
- 100.000000
- 1000.000000
- 10000.000000
- 100000.000000
- 1000000.00000
-TOO LONG
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 10
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 7;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-Variable_name Value
-query_response_time_range_base 7
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 24 0.000000
+ 0.000010 0 0.000000
+ 0.000100 0 0.000000
+ 0.001000 0 0.000000
+ 0.010000 0 0.000000
+ 0.100000 0 0.000000
+ 1.000000 11 4.050000
+ 10.000000 11 25.699999
+ 100.000000 0 0.000000
+ 1000.000000 0 0.000000
+ 10000.000000 0 0.000000
+ 100000.000000 0 0.000000
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 24 0.000000
+ 0.000010 0 0.000000
+ 0.000100 0 0.000000
+ 0.001000 0 0.000000
+ 0.010000 0 0.000000
+ 0.100000 0 0.000000
+ 1.000000 11 4.050000
+ 10.000000 11 25.699999
+ 100.000000 0 0.000000
+ 1000.000000 0 0.000000
+ 10000.000000 0 0.000000
+ 100000.000000 0 0.000000
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=7;
FLUSH QUERY_RESPONSE_TIME;
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 0 0.000000
+ 0.000008 0 0.000000
+ 0.000059 0 0.000000
+ 0.000416 0 0.000000
+ 0.002915 0 0.000000
+ 0.020408 0 0.000000
+ 0.142857 0 0.000000
+ 1.000000 0 0.000000
+ 7.000000 0 0.000000
+ 49.000000 0 0.000000
+ 343.000000 0 0.000000
+ 2401.000000 0 0.000000
+ 16807.000000 0 0.000000
+ 117649.000000 0 0.000000
+ 823543.000000 0 0.000000
+ 5764801.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 0 0.000000
+ 0.000008 0 0.000000
+ 0.000059 0 0.000000
+ 0.000416 0 0.000000
+ 0.002915 0 0.000000
+ 0.020408 0 0.000000
+ 0.142857 0 0.000000
+ 1.000000 0 0.000000
+ 7.000000 0 0.000000
+ 49.000000 0 0.000000
+ 343.000000 0 0.000000
+ 2401.000000 0 0.000000
+ 16807.000000 0 0.000000
+ 117649.000000 0 0.000000
+ 823543.000000 0 0.000000
+ 5764801.00000 0 0.000000
+TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SET SESSION debug="+d,query_exec_time_0.31";
-SET SESSION debug="+d,query_exec_time_0.32";
-SET SESSION debug="+d,query_exec_time_0.33";
-SET SESSION debug="+d,query_exec_time_0.34";
-SET SESSION debug="+d,query_exec_time_0.35";
-SET SESSION debug="+d,query_exec_time_0.36";
-SET SESSION debug="+d,query_exec_time_0.37";
-SET SESSION debug="+d,query_exec_time_0.38";
-SET SESSION debug="+d,query_exec_time_0.39";
-SET SESSION debug="+d,query_exec_time_0.4";
-SET SESSION debug="+d,query_exec_time_1.1";
-SET SESSION debug="+d,query_exec_time_1.2";
-SET SESSION debug="+d,query_exec_time_1.3";
-SET SESSION debug="+d,query_exec_time_1.5";
-SET SESSION debug="+d,query_exec_time_1.4";
-SET SESSION debug="+d,query_exec_time_0.5";
-SET SESSION debug="+d,query_exec_time_2.1";
-SET SESSION debug="+d,query_exec_time_2.3";
-SET SESSION debug="+d,query_exec_time_2.5";
+SET SESSION query_exec_time=0.31;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.32;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.33;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.34;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.35;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.36;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.37;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.38;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.39;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.2;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=3.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=4.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=5.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.1;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SELECT d.count,
-(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count,
-(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count
-FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0;
-count query_count query_total not_zero_region_count region_count
-11 19 17 2 17
-8 19 17 2 17
-SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-region_count
-17
-SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-time
- 0.000001
- 0.000008
- 0.000059
- 0.000416
- 0.002915
- 0.020408
- 0.142857
- 1.000000
- 7.000000
- 49.000000
- 343.000000
- 2401.000000
- 16807.000000
- 117649.000000
- 823543.000000
- 5764801.00000
-TOO LONG
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 7
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 156;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-Variable_name Value
-query_response_time_range_base 156
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 24 0.000000
+ 0.000008 0 0.000000
+ 0.000059 0 0.000000
+ 0.000416 0 0.000000
+ 0.002915 0 0.000000
+ 0.020408 0 0.000000
+ 0.142857 0 0.000000
+ 1.000000 11 4.050000
+ 7.000000 11 25.699999
+ 49.000000 0 0.000000
+ 343.000000 0 0.000000
+ 2401.000000 0 0.000000
+ 16807.000000 0 0.000000
+ 117649.000000 0 0.000000
+ 823543.000000 0 0.000000
+ 5764801.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 24 0.000000
+ 0.000008 0 0.000000
+ 0.000059 0 0.000000
+ 0.000416 0 0.000000
+ 0.002915 0 0.000000
+ 0.020408 0 0.000000
+ 0.142857 0 0.000000
+ 1.000000 11 4.050000
+ 7.000000 11 25.699999
+ 49.000000 0 0.000000
+ 343.000000 0 0.000000
+ 2401.000000 0 0.000000
+ 16807.000000 0 0.000000
+ 117649.000000 0 0.000000
+ 823543.000000 0 0.000000
+ 5764801.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=156;
FLUSH QUERY_RESPONSE_TIME;
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000041 0 0.000000
+ 0.006410 0 0.000000
+ 1.000000 0 0.000000
+ 156.000000 0 0.000000
+ 24336.000000 0 0.000000
+ 3796416.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000041 0 0.000000
+ 0.006410 0 0.000000
+ 1.000000 0 0.000000
+ 156.000000 0 0.000000
+ 24336.000000 0 0.000000
+ 3796416.00000 0 0.000000
+TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SET SESSION debug="+d,query_exec_time_0.31";
-SET SESSION debug="+d,query_exec_time_0.32";
-SET SESSION debug="+d,query_exec_time_0.33";
-SET SESSION debug="+d,query_exec_time_0.34";
-SET SESSION debug="+d,query_exec_time_0.35";
-SET SESSION debug="+d,query_exec_time_0.36";
-SET SESSION debug="+d,query_exec_time_0.37";
-SET SESSION debug="+d,query_exec_time_0.38";
-SET SESSION debug="+d,query_exec_time_0.39";
-SET SESSION debug="+d,query_exec_time_0.4";
-SET SESSION debug="+d,query_exec_time_1.1";
-SET SESSION debug="+d,query_exec_time_1.2";
-SET SESSION debug="+d,query_exec_time_1.3";
-SET SESSION debug="+d,query_exec_time_1.5";
-SET SESSION debug="+d,query_exec_time_1.4";
-SET SESSION debug="+d,query_exec_time_0.5";
-SET SESSION debug="+d,query_exec_time_2.1";
-SET SESSION debug="+d,query_exec_time_2.3";
-SET SESSION debug="+d,query_exec_time_2.5";
+SET SESSION query_exec_time=0.31;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.32;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.33;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.34;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.35;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.36;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.37;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.38;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.39;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.2;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=3.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=4.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=5.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.1;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SELECT d.count,
-(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count,
-(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count
-FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0;
-count query_count query_total not_zero_region_count region_count
-11 19 17 2 7
-8 19 17 2 7
-SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-region_count
-7
-SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-time
- 0.000041
- 0.006410
- 1.000000
- 156.000000
- 24336.000000
- 3796416.00000
-TOO LONG
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 156
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1000;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-Variable_name Value
-query_response_time_range_base 1000
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000041 24 0.000000
+ 0.006410 0 0.000000
+ 1.000000 11 4.050000
+ 156.000000 11 25.699999
+ 24336.000000 0 0.000000
+ 3796416.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000041 24 0.000000
+ 0.006410 0 0.000000
+ 1.000000 11 4.050000
+ 156.000000 11 25.699999
+ 24336.000000 0 0.000000
+ 3796416.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1000;
FLUSH QUERY_RESPONSE_TIME;
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 0 0.000000
+ 0.001000 0 0.000000
+ 1.000000 0 0.000000
+ 1000.000000 0 0.000000
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 0 0.000000
+ 0.001000 0 0.000000
+ 1.000000 0 0.000000
+ 1000.000000 0 0.000000
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-SET SESSION debug="+d,query_exec_time_0.31";
-SET SESSION debug="+d,query_exec_time_0.32";
-SET SESSION debug="+d,query_exec_time_0.33";
-SET SESSION debug="+d,query_exec_time_0.34";
-SET SESSION debug="+d,query_exec_time_0.35";
-SET SESSION debug="+d,query_exec_time_0.36";
-SET SESSION debug="+d,query_exec_time_0.37";
-SET SESSION debug="+d,query_exec_time_0.38";
-SET SESSION debug="+d,query_exec_time_0.39";
-SET SESSION debug="+d,query_exec_time_0.4";
-SET SESSION debug="+d,query_exec_time_1.1";
-SET SESSION debug="+d,query_exec_time_1.2";
-SET SESSION debug="+d,query_exec_time_1.3";
-SET SESSION debug="+d,query_exec_time_1.5";
-SET SESSION debug="+d,query_exec_time_1.4";
-SET SESSION debug="+d,query_exec_time_0.5";
-SET SESSION debug="+d,query_exec_time_2.1";
-SET SESSION debug="+d,query_exec_time_2.3";
-SET SESSION debug="+d,query_exec_time_2.5";
+SET SESSION query_exec_time=0.31;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.32;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.33;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.34;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.35;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.36;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.37;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.38;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.39;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.2;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=3.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=4.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=5.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.1;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SELECT d.count,
-(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count,
-(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count,
-(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count
-FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0;
-count query_count query_total not_zero_region_count region_count
-11 19 17 2 6
-8 19 17 2 6
-SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-region_count
-6
-SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-time
- 0.000001
- 0.001000
- 1.000000
- 1000.000000
- 1000000.00000
-TOO LONG
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 1000
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1001;
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 24 0.000000
+ 0.001000 0 0.000000
+ 1.000000 11 4.050000
+ 1000.000000 11 25.699999
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 24 0.000000
+ 0.001000 0 0.000000
+ 1.000000 11 4.050000
+ 1000.000000 11 25.699999
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1001;
Warnings:
Warning 1292 Truncated incorrect query_response_time_range_base value: '1001'
+FLUSH QUERY_RESPONSE_TIME;
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 0 0.000000
+ 0.001000 0 0.000000
+ 1.000000 0 0.000000
+ 1000.000000 0 0.000000
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 0 0.000000
+ 0.001000 0 0.000000
+ 1.000000 0 0.000000
+ 1000.000000 0 0.000000
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+SET SESSION query_exec_time=0.31;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.32;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.33;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.34;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.35;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.36;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.37;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.38;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.39;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.2;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=1.4;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.3;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=2.5;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=3.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=4.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=5.1;
+SELECT 1;
+1
+1
+SET SESSION query_exec_time=0.1;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
Variable_name Value
query_response_time_range_base 1000
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE =10;
-SET GLOBAL debug=default;
+SHOW QUERY_RESPONSE_TIME;
+
+ 0.000001 24 0.000000
+ 0.001000 0 0.000000
+ 1.000000 11 4.050000
+ 1000.000000 11 25.699999
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+time count total
+ 0.000001 24 0.000000
+ 0.001000 0 0.000000
+ 1.000000 11 4.050000
+ 1000.000000 11 25.699999
+ 1000000.00000 0 0.000000
+TOO LONG 0 TOO LONG
+SET SESSION query_exec_time=default;
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
diff --git a/mysql-test/suite/percona/percona_query_response_time.test b/mysql-test/suite/percona/percona_query_response_time.test
index f2df156b13d..d4fb9c61388 100644
--- a/mysql-test/suite/percona/percona_query_response_time.test
+++ b/mysql-test/suite/percona/percona_query_response_time.test
@@ -1,71 +1,20 @@
--source include/have_response_time_distribution.inc
--source include/have_debug.inc
-SET GLOBAL debug="d,query_exec_time_debug";
-
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 2;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-
-source include/percona_query_response_time_flush.inc;
-source include/percona_query_response_time_show.inc;
-
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-source include/percona_query_response_time_sleep.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-
-source include/percona_query_response_time_show.inc;
-
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-
-source include/percona_query_response_time_flush.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-source include/percona_query_response_time_sleep.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-
-source include/percona_query_response_time_show.inc;
-
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 7;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-
-source include/percona_query_response_time_flush.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-source include/percona_query_response_time_sleep.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-
-source include/percona_query_response_time_show.inc;
-
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 156;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-
-source include/percona_query_response_time_flush.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-source include/percona_query_response_time_sleep.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-
-source include/percona_query_response_time_show.inc;
-
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1000;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-
-source include/percona_query_response_time_flush.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-source include/percona_query_response_time_sleep.inc;
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-
-source include/percona_query_response_time_show.inc;
-
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1001;
-SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-
-SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE =10;
-
-SET GLOBAL debug=default;
+--let base=1
+--source include/query_response_time.inc
+--let base=2
+--source include/query_response_time.inc
+--let base=10
+--source include/query_response_time.inc
+--let base=7
+--source include/query_response_time.inc
+--let base=156
+--source include/query_response_time.inc
+--let base=1000
+--source include/query_response_time.inc
+--let base=1001
+--source include/query_response_time.inc
+
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
diff --git a/mysql-test/suite/percona/percona_server_variables_debug.result b/mysql-test/suite/percona/percona_server_variables_debug.result
index 1ffaa6a7704..ea1c02e7716 100644
--- a/mysql-test/suite/percona/percona_server_variables_debug.result
+++ b/mysql-test/suite/percona/percona_server_variables_debug.result
@@ -41,6 +41,7 @@ DIV_PRECISION_INCREMENT
ENGINE_CONDITION_PUSHDOWN
ERROR_COUNT
EVENT_SCHEDULER
+EXPAND_FAST_INDEX_CREATION
EXPIRE_LOGS_DAYS
EXTERNAL_USER
FAST_INDEX_CREATION
@@ -83,6 +84,7 @@ INNODB_ADAPTIVE_HASH_INDEX_PARTITIONS
INNODB_ADDITIONAL_MEM_POOL_SIZE
INNODB_AUTOEXTEND_INCREMENT
INNODB_AUTOINC_LOCK_MODE
+INNODB_BLOCKING_BUFFER_POOL_RESTORE
INNODB_BUFFER_POOL_INSTANCES
INNODB_BUFFER_POOL_RESTORE_AT_STARTUP
INNODB_BUFFER_POOL_SHM_CHECKSUM
@@ -100,6 +102,7 @@ INNODB_DATA_HOME_DIR
INNODB_DICT_SIZE_LIMIT
INNODB_DOUBLEWRITE
INNODB_DOUBLEWRITE_FILE
+INNODB_FAKE_CHANGES
INNODB_FAST_CHECKSUM
INNODB_FAST_SHUTDOWN
INNODB_FILE_FORMAT
@@ -109,12 +112,15 @@ INNODB_FILE_PER_TABLE
INNODB_FLUSH_LOG_AT_TRX_COMMIT
INNODB_FLUSH_METHOD
INNODB_FLUSH_NEIGHBOR_PAGES
+INNODB_FORCE_LOAD_CORRUPTED
INNODB_FORCE_RECOVERY
INNODB_IBUF_ACCEL_RATE
INNODB_IBUF_ACTIVE_CONTRACT
INNODB_IBUF_MAX_SIZE
INNODB_IMPORT_TABLE_FROM_XTRABACKUP
INNODB_IO_CAPACITY
+INNODB_KILL_IDLE_TRANSACTION
+INNODB_LARGE_PREFIX
INNODB_LAZY_DROP_TABLE
INNODB_LOCKS_UNSAFE_FOR_BINLOG
INNODB_LOCK_WAIT_TIMEOUT
@@ -132,6 +138,7 @@ INNODB_OPEN_FILES
INNODB_PAGE_SIZE
INNODB_PURGE_BATCH_SIZE
INNODB_PURGE_THREADS
+INNODB_RANDOM_READ_AHEAD
INNODB_READ_AHEAD
INNODB_READ_AHEAD_THRESHOLD
INNODB_READ_IO_THREADS
@@ -187,6 +194,7 @@ LOG_ERROR
LOG_OUTPUT
LOG_QUERIES_NOT_USING_INDEXES
LOG_SLAVE_UPDATES
+LOG_SLOW_ADMIN_STATEMENTS
LOG_SLOW_FILTER
LOG_SLOW_QUERIES
LOG_SLOW_RATE_LIMIT
@@ -275,6 +283,7 @@ QUERY_CACHE_SIZE
QUERY_CACHE_STRIP_COMMENTS
QUERY_CACHE_TYPE
QUERY_CACHE_WLOCK_INVALIDATE
+QUERY_EXEC_TIME
QUERY_PREALLOC_SIZE
QUERY_RESPONSE_TIME_RANGE_BASE
QUERY_RESPONSE_TIME_STATS
diff --git a/mysql-test/suite/percona/percona_server_variables_release.result b/mysql-test/suite/percona/percona_server_variables_release.result
index cabd69b19a6..e5965cf7e5e 100644
--- a/mysql-test/suite/percona/percona_server_variables_release.result
+++ b/mysql-test/suite/percona/percona_server_variables_release.result
@@ -39,6 +39,7 @@ DIV_PRECISION_INCREMENT
ENGINE_CONDITION_PUSHDOWN
ERROR_COUNT
EVENT_SCHEDULER
+EXPAND_FAST_INDEX_CREATION
EXPIRE_LOGS_DAYS
EXTERNAL_USER
FAST_INDEX_CREATION
@@ -81,6 +82,7 @@ INNODB_ADAPTIVE_HASH_INDEX_PARTITIONS
INNODB_ADDITIONAL_MEM_POOL_SIZE
INNODB_AUTOEXTEND_INCREMENT
INNODB_AUTOINC_LOCK_MODE
+INNODB_BLOCKING_BUFFER_POOL_RESTORE
INNODB_BUFFER_POOL_INSTANCES
INNODB_BUFFER_POOL_RESTORE_AT_STARTUP
INNODB_BUFFER_POOL_SHM_CHECKSUM
@@ -97,6 +99,7 @@ INNODB_DATA_HOME_DIR
INNODB_DICT_SIZE_LIMIT
INNODB_DOUBLEWRITE
INNODB_DOUBLEWRITE_FILE
+INNODB_FAKE_CHANGES
INNODB_FAST_CHECKSUM
INNODB_FAST_SHUTDOWN
INNODB_FILE_FORMAT
@@ -106,12 +109,15 @@ INNODB_FILE_PER_TABLE
INNODB_FLUSH_LOG_AT_TRX_COMMIT
INNODB_FLUSH_METHOD
INNODB_FLUSH_NEIGHBOR_PAGES
+INNODB_FORCE_LOAD_CORRUPTED
INNODB_FORCE_RECOVERY
INNODB_IBUF_ACCEL_RATE
INNODB_IBUF_ACTIVE_CONTRACT
INNODB_IBUF_MAX_SIZE
INNODB_IMPORT_TABLE_FROM_XTRABACKUP
INNODB_IO_CAPACITY
+INNODB_KILL_IDLE_TRANSACTION
+INNODB_LARGE_PREFIX
INNODB_LAZY_DROP_TABLE
INNODB_LOCKS_UNSAFE_FOR_BINLOG
INNODB_LOCK_WAIT_TIMEOUT
@@ -129,6 +135,7 @@ INNODB_OPEN_FILES
INNODB_PAGE_SIZE
INNODB_PURGE_BATCH_SIZE
INNODB_PURGE_THREADS
+INNODB_RANDOM_READ_AHEAD
INNODB_READ_AHEAD
INNODB_READ_AHEAD_THRESHOLD
INNODB_READ_IO_THREADS
@@ -184,6 +191,7 @@ LOG_ERROR
LOG_OUTPUT
LOG_QUERIES_NOT_USING_INDEXES
LOG_SLAVE_UPDATES
+LOG_SLOW_ADMIN_STATEMENTS
LOG_SLOW_FILTER
LOG_SLOW_QUERIES
LOG_SLOW_RATE_LIMIT
diff --git a/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.result b/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.result
index f951428abc7..678ed685a5b 100644
--- a/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.result
+++ b/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.result
@@ -1,4 +1,4 @@
-set GLOBAL query_cache_size=1355776;
+SET GLOBAL query_cache_size=1355776;
flush query cache;
flush query cache;
reset query cache;
@@ -8,20 +8,16 @@ CREATE TABLE t(id INT, number INT);
INSERT INTO t VALUES (0,1);
INSERT INTO t VALUES (1,2);
INSERT INTO t VALUES (2,3);
+SET SESSION debug="+d,status_waiting_on_query_cache_mutex_sleep";
+SET DEBUG_SYNC='status_waiting_on_query_cache_mutex SIGNAL thread_ready';
SELECT number from t where id > 0;
-number
-2
-3
-SET SESSION debug="+d,status_wait_query_cache_mutex_sleep";
-SELECT number from t where id > 0;
-SET SESSION debug="+d,status_wait_query_cache_mutex_sleep";
-SELECT number from t where id > 0;
-SET SESSION debug="+d,status_wait_query_cache_mutex_sleep";
SHOW PROCESSLIST;
Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read
-Id root localhost test Sleep Time NULL Rows_sent Rows_examined Rows_read
-Id root localhost test Query Time Waiting on query cache mutex SELECT number from t where id > 0 Rows_sent Rows_examined Rows_read
-Id root localhost test Query Time Waiting on query cache mutex SELECT number from t where id > 0 Rows_sent Rows_examined Rows_read
-Id root localhost test Query Time NULL SHOW PROCESSLIST Rows_sent Rows_examined Rows_read
+### root ### test Query ### NULL SHOW PROCESSLIST ### ### ###
+### root ### test Query ### Waiting on query cache mutex SELECT number from t where id > 0 ### ### ###
+SELECT id, info, state FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id;
+id info state
+### SELECT id, info, state FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id executing
+### SELECT number from t where id > 0 Waiting on query cache mutex
DROP TABLE t;
-set GLOBAL query_cache_size=0;
+SET GLOBAL query_cache_size=0;
diff --git a/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.test b/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.test
index 35e2d0ac549..1e586ca4e7a 100644
--- a/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.test
+++ b/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.test
@@ -1,6 +1,7 @@
--source include/have_query_cache.inc
--source include/have_debug.inc
-set GLOBAL query_cache_size=1355776;
+--source include/have_debug_sync.inc
+SET GLOBAL query_cache_size=1355776;
--source include/percona_query_cache_with_comments_clear.inc
-- disable_warnings
@@ -10,28 +11,21 @@ CREATE TABLE t(id INT, number INT);
INSERT INTO t VALUES (0,1);
INSERT INTO t VALUES (1,2);
INSERT INTO t VALUES (2,3);
-SELECT number from t where id > 0;
---connect (conn0,localhost,root,,)
---connect (conn1,localhost,root,,)
---connect (conn2,localhost,root,,)
---connection conn0
---error 0, ER_UNKNOWN_SYSTEM_VARIABLE
-SET SESSION debug="+d,status_wait_query_cache_mutex_sleep";
-SEND SELECT number from t where id > 0;
-SLEEP 1.0;
+--connect (conn,localhost,root,,)
---connection conn1
---error 0, ER_UNKNOWN_SYSTEM_VARIABLE
-SET SESSION debug="+d,status_wait_query_cache_mutex_sleep";
+--connection conn
+SET SESSION debug="+d,status_waiting_on_query_cache_mutex_sleep";
+SET DEBUG_SYNC='status_waiting_on_query_cache_mutex SIGNAL thread_ready';
SEND SELECT number from t where id > 0;
-SLEEP 1.0;
---connection conn2
---error 0, ER_UNKNOWN_SYSTEM_VARIABLE
-SET SESSION debug="+d,status_wait_query_cache_mutex_sleep";
---replace_column 1 Id 6 Time 9 Rows_sent 10 Rows_examined 11 Rows_read
+--connection default
+--replace_column 1 ### 3 ### 6 ### 9 ### 10 ### 11 ###
SHOW PROCESSLIST;
+--replace_column 1 ###
+SELECT id, info, state FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id;
+
+--disconnect conn
DROP TABLE t;
-set GLOBAL query_cache_size=0;
+SET GLOBAL query_cache_size=0;
diff --git a/mysql-test/suite/percona/query_response_time-replication.inc b/mysql-test/suite/percona/query_response_time-replication.inc
new file mode 100644
index 00000000000..9bd811a9a1b
--- /dev/null
+++ b/mysql-test/suite/percona/query_response_time-replication.inc
@@ -0,0 +1,57 @@
+connection master;
+
+CREATE TABLE t(id INT);
+
+connection slave;
+SET GLOBAL query_exec_time = 0.1;
+--source include/restart_slave_sql.inc
+
+connection slave;
+
+SET SESSION query_exec_time=0.1;
+
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+--eval SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=$base
+FLUSH QUERY_RESPONSE_TIME;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+
+connection master;
+
+SET SESSION query_exec_time = 0.31; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.32; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.33; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.34; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.35; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.36; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.37; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.38; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.39; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.4; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.1; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.2; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.3; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.5; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 1.4; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 0.5; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.1; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.3; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 2.5; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 3.1; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 4.1; INSERT INTO t VALUES(1);
+SET SESSION query_exec_time = 5.1; INSERT INTO t VALUES(1);
+
+sync_slave_with_master;
+
+connection slave;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
+SHOW QUERY_RESPONSE_TIME;
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+
+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
+
+connection master;
+DROP TABLE t;
+
+sync_slave_with_master;
diff --git a/mysql-test/suite/percona/query_response_time-stored.inc b/mysql-test/suite/percona/query_response_time-stored.inc
new file mode 100644
index 00000000000..a1fc8912aab
--- /dev/null
+++ b/mysql-test/suite/percona/query_response_time-stored.inc
@@ -0,0 +1,37 @@
+SET SESSION query_exec_time=0.1;
+
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+EVAL SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=$base;
+FLUSH QUERY_RESPONSE_TIME;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+
+CALL test_f(0.31);
+CALL test_f(0.32);
+CALL test_f(0.33);
+CALL test_f(0.34);
+CALL test_f(0.35);
+CALL test_f(0.36);
+CALL test_f(0.37);
+CALL test_f(0.38);
+CALL test_f(0.39);
+CALL test_f(0.4);
+CALL test_f(1.1);
+CALL test_f(1.2);
+CALL test_f(1.3);
+CALL test_f(1.5);
+CALL test_f(1.4);
+CALL test_f(0.5);
+CALL test_f(2.1);
+CALL test_f(2.3);
+CALL test_f(2.5);
+CALL test_f(3.1);
+CALL test_f(4.1);
+CALL test_f(5.1);
+
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+
+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
+SHOW QUERY_RESPONSE_TIME;
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+
+SET SESSION query_exec_time=default;
diff --git a/mysql-test/suite/percona/query_response_time.inc b/mysql-test/suite/percona/query_response_time.inc
new file mode 100644
index 00000000000..734d3f5a262
--- /dev/null
+++ b/mysql-test/suite/percona/query_response_time.inc
@@ -0,0 +1,43 @@
+SET SESSION query_exec_time=0.1;
+
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+EVAL SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=$base;
+FLUSH QUERY_RESPONSE_TIME;
+# Following two queries check works of FLUSH and
+# respecting of "QUERY_RESPONSE_TIME_STATS" variable (see launchpad bug #855312)
+SHOW QUERY_RESPONSE_TIME;
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
+
+SET SESSION query_exec_time=0.31; SELECT 1;
+SET SESSION query_exec_time=0.32; SELECT 1;
+SET SESSION query_exec_time=0.33; SELECT 1;
+SET SESSION query_exec_time=0.34; SELECT 1;
+SET SESSION query_exec_time=0.35; SELECT 1;
+SET SESSION query_exec_time=0.36; SELECT 1;
+SET SESSION query_exec_time=0.37; SELECT 1;
+SET SESSION query_exec_time=0.38; SELECT 1;
+SET SESSION query_exec_time=0.39; SELECT 1;
+SET SESSION query_exec_time=0.4; SELECT 1;
+SET SESSION query_exec_time=1.1; SELECT 1;
+SET SESSION query_exec_time=1.2; SELECT 1;
+SET SESSION query_exec_time=1.3; SELECT 1;
+SET SESSION query_exec_time=1.5; SELECT 1;
+SET SESSION query_exec_time=1.4; SELECT 1;
+SET SESSION query_exec_time=0.5; SELECT 1;
+SET SESSION query_exec_time=2.1; SELECT 1;
+SET SESSION query_exec_time=2.3; SELECT 1;
+SET SESSION query_exec_time=2.5; SELECT 1;
+SET SESSION query_exec_time=3.1; SELECT 1;
+SET SESSION query_exec_time=4.1; SELECT 1;
+SET SESSION query_exec_time=5.1; SELECT 1;
+
+SET SESSION query_exec_time=0.1;
+
+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
+
+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
+SHOW QUERY_RESPONSE_TIME;
+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+
+SET SESSION query_exec_time=default;
diff --git a/mysql-test/suite/percona/show_slave_status_nolock.patch/percona_show_slave_status_nolock.result b/mysql-test/suite/percona/show_slave_status_nolock.patch/percona_show_slave_status_nolock.result
index 1d6114a001e..b98e4a93953 100644
--- a/mysql-test/suite/percona/show_slave_status_nolock.patch/percona_show_slave_status_nolock.result
+++ b/mysql-test/suite/percona/show_slave_status_nolock.patch/percona_show_slave_status_nolock.result
@@ -1,21 +1,69 @@
include/master-slave.inc
[connection master]
+call mtr.add_suppression("Slave SQL: Request to stop slave SQL Thread received while applying a group that has non-transactional changes");
+include/rpl_connect.inc [creating slave_lock]
+include/rpl_connect.inc [creating slave_nolock]
+[master]
DROP TABLE IF EXISTS t;
CREATE TABLE t(id INT);
-INSERT INTO t SELECT SLEEP(10);
+[slave]
+SET DEBUG_SYNC='RESET';
+SET GLOBAL DEBUG="+d,after_mysql_insert,after_show_slave_status";
+[master]
+INSERT INTO t VALUES(0);
+[slave]
+check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine
+
+[slave_lock]
+SHOW SLAVE STATUS;
+SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
+SIGNAL after SHOW SLAVE STATUS is 'signal.after_show_slave_status'
+[slave]
+SET DEBUG_SYNC='now SIGNAL signal.empty';
+[slave_nolock]
+SHOW SLAVE STATUS NOLOCK;
+SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
+# should be 'signal.after_show_slave_status'
+SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status'
+[slave]
+SET DEBUG_SYNC='now SIGNAL signal.continue';
+[slave]
+SET DEBUG_SYNC='now SIGNAL signal.empty';
+
+[master]
+INSERT INTO t VALUES(1);
+[slave]
+include/rpl_connect.inc [creating slave_stop]
+[slave_stop]
STOP SLAVE;
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
-master count(*)
-master 1
-slave count(*)
-slave 0
+[slave]
+check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine
+
+[slave_lock]
+SHOW SLAVE STATUS;
+SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
+SIGNAL after SHOW SLAVE STATUS is 'signal.empty'
+[slave]
+SET DEBUG_SYNC='now SIGNAL signal.empty';
+[slave_nolock]
SHOW SLAVE STATUS NOLOCK;
+SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
+# should be 'signal.after_show_slave_status'
+SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status'
+[slave]
+SET DEBUG_SYNC='now SIGNAL signal.continue';
+[slave]
+SET DEBUG_SYNC='now SIGNAL signal.empty';
+
+[slave_stop]
include/wait_for_slave_to_stop.inc
START SLAVE;
include/wait_for_slave_to_start.inc
-slave count(*)
-slave 1
+[master]
+SET DEBUG_SYNC='RESET';
+[slave]
+SET GLOBAL DEBUG='';
+SET DEBUG_SYNC='RESET';
+[master]
DROP TABLE t;
-STOP SLAVE;
-include/wait_for_slave_to_stop.inc
+include/rpl_end.inc
diff --git a/mysql-test/suite/percona/show_slave_status_nolock.patch/percona_show_slave_status_nolock.test b/mysql-test/suite/percona/show_slave_status_nolock.patch/percona_show_slave_status_nolock.test
index dcb2eb26a3e..df595214ff7 100644
--- a/mysql-test/suite/percona/show_slave_status_nolock.patch/percona_show_slave_status_nolock.test
+++ b/mysql-test/suite/percona/show_slave_status_nolock.patch/percona_show_slave_status_nolock.test
@@ -1,53 +1,90 @@
--source include/master-slave.inc
+--source include/have_debug_sync.inc
--source include/have_binlog_format_statement.inc
---disable_query_log
-call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. Statement:");
-call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group");
---enable_query_log
+
+call mtr.add_suppression("Slave SQL: Request to stop slave SQL Thread received while applying a group that has non-transactional changes");
+
+--let $rpl_connection_name=slave_lock
+--let $rpl_server_number=2
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name=slave_nolock
+--let $rpl_server_number=2
+--source include/rpl_connect.inc
+
+--let $show_statement= SHOW PROCESSLIST
+--let $field= Info
+
connection master;
- --disable_warnings
- DROP TABLE IF EXISTS t;
- --enable_warnings
- CREATE TABLE t(id INT);
- sync_slave_with_master;
+--echo [master]
+--disable_warnings
+DROP TABLE IF EXISTS t;
+--enable_warnings
+CREATE TABLE t(id INT);
+sync_slave_with_master;
+
+connection slave;
+--echo [slave]
+SET DEBUG_SYNC='RESET';
+SET GLOBAL DEBUG="+d,after_mysql_insert,after_show_slave_status";
connection master;
- send INSERT INTO t SELECT SLEEP(10);
+--echo [master]
+INSERT INTO t VALUES(0);
connection slave;
- sleep 15;
- send STOP SLAVE;
+--echo [slave]
+--let $condition= 'INSERT INTO t VALUES(0)'
+--source include/wait_show_condition.inc
+
+--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine
+--source include/percona_show_slave_status_nolock.inc
connection master;
- reap;
+--echo [master]
+INSERT INTO t VALUES(1);
- --disable_query_log
- select "master",count(*) from t;
- --enable_query_log
+connection slave;
+--echo [slave]
+--let $condition= 'INSERT INTO t VALUES(1)'
+--source include/wait_show_condition.inc
-connection slave1;
- --disable_query_log
- select "slave",count(*) from t;
- --enable_query_log
+--let $rpl_connection_name=slave_stop
+--let $rpl_server_number=2
+--source include/rpl_connect.inc
- --disable_result_log
- SHOW SLAVE STATUS NOLOCK;
- --enable_result_log
+connection slave_stop;
+--echo [slave_stop]
+send STOP SLAVE;
connection slave;
- reap;
+--echo [slave]
+--let $condition= 'STOP SLAVE'
+--source include/wait_show_condition.inc
+
+--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine
+--source include/percona_show_slave_status_nolock.inc
- --source include/wait_for_slave_to_stop.inc
- START SLAVE;
- --source include/wait_for_slave_to_start.inc
- --disable_query_log
- select "slave",count(*) from t;
- --enable_query_log
+connection slave_stop;
+--echo [slave_stop]
+reap;
+--source include/wait_for_slave_to_stop.inc
+START SLAVE;
+--source include/wait_for_slave_to_start.inc
connection master;
- DROP TABLE t;
+--echo [master]
+SET DEBUG_SYNC='RESET';
+
+connection slave;
+--echo [slave]
+SET GLOBAL DEBUG='';
+SET DEBUG_SYNC='RESET';
+
+connection master;
+--echo [master]
+DROP TABLE t;
sync_slave_with_master;
-STOP SLAVE;
---source include/wait_for_slave_to_stop.inc
-
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/sys_vars/r/innodb_blocking_buffer_pool_restore_basic.result b/mysql-test/suite/sys_vars/r/innodb_blocking_buffer_pool_restore_basic.result
new file mode 100644
index 00000000000..d9d067c2cf9
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/innodb_blocking_buffer_pool_restore_basic.result
@@ -0,0 +1 @@
+XtraDB extension
diff --git a/mysql-test/suite/sys_vars/r/innodb_fake_changes_basic.result b/mysql-test/suite/sys_vars/r/innodb_fake_changes_basic.result
new file mode 100644
index 00000000000..d9d067c2cf9
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/innodb_fake_changes_basic.result
@@ -0,0 +1 @@
+XtraDB extension
diff --git a/mysql-test/suite/sys_vars/r/innodb_kill_idle_transaction_basic.result b/mysql-test/suite/sys_vars/r/innodb_kill_idle_transaction_basic.result
new file mode 100644
index 00000000000..d9d067c2cf9
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/innodb_kill_idle_transaction_basic.result
@@ -0,0 +1 @@
+XtraDB extension
diff --git a/mysql-test/suite/sys_vars/t/innodb_blocking_buffer_pool_restore_basic.test b/mysql-test/suite/sys_vars/t/innodb_blocking_buffer_pool_restore_basic.test
new file mode 100644
index 00000000000..00aa476e8d2
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_blocking_buffer_pool_restore_basic.test
@@ -0,0 +1 @@
+--echo XtraDB extension
diff --git a/mysql-test/suite/sys_vars/t/innodb_fake_changes_basic.test b/mysql-test/suite/sys_vars/t/innodb_fake_changes_basic.test
new file mode 100644
index 00000000000..00aa476e8d2
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_fake_changes_basic.test
@@ -0,0 +1 @@
+--echo XtraDB extension
diff --git a/mysql-test/suite/sys_vars/t/innodb_kill_idle_transaction_basic.test b/mysql-test/suite/sys_vars/t/innodb_kill_idle_transaction_basic.test
new file mode 100644
index 00000000000..00aa476e8d2
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_kill_idle_transaction_basic.test
@@ -0,0 +1 @@
+--echo XtraDB extension
diff --git a/storage/xtradb/btr/btr0btr.c b/storage/xtradb/btr/btr0btr.c
index c0c27128441..ca98afc04ad 100644
--- a/storage/xtradb/btr/btr0btr.c
+++ b/storage/xtradb/btr/btr0btr.c
@@ -690,7 +690,8 @@ btr_root_block_get(
zip_size = dict_table_zip_size(index->table);
root_page_no = dict_index_get_page(index);
- block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
+ index, mtr);
if (srv_pass_corrupt_table && !block) {
return(0);
@@ -897,7 +898,7 @@ btr_page_alloc_for_ibuf(
dict_table_zip_size(index->table),
node_addr.page, RW_X_LATCH, mtr);
new_page = buf_block_get_frame(new_block);
- buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
+ buf_block_dbg_add_level(new_block, SYNC_IBUF_TREE_NODE_NEW);
flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
@@ -1151,7 +1152,7 @@ btr_node_ptr_get_child(
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
return(btr_block_get(space, dict_table_zip_size(index->table),
- page_no, RW_X_LATCH, mtr));
+ page_no, RW_X_LATCH, index, mtr));
}
/************************************************************//**
@@ -1324,7 +1325,8 @@ btr_create(
space, 0,
IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr);
- buf_block_dbg_add_level(ibuf_hdr_block, SYNC_TREE_NODE_NEW);
+ buf_block_dbg_add_level(
+ ibuf_hdr_block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(buf_block_get_page_no(ibuf_hdr_block)
== IBUF_HEADER_PAGE_NO);
@@ -1362,10 +1364,9 @@ btr_create(
page_no = buf_block_get_page_no(block);
frame = buf_block_get_frame(block);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
-
if (type & DICT_IBUF) {
/* It is an insert buffer tree: initialize the free list */
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
@@ -1373,6 +1374,8 @@ btr_create(
} else {
/* It is a non-ibuf tree: create a file segment for leaf
pages */
+ buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
+
if (!fseg_create(space, page_no,
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) {
/* Not enough space for new segment, free root
@@ -1444,14 +1447,15 @@ btr_free_but_not_root(
leaf_loop:
mtr_start(&mtr);
- root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr);
+ root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
+ NULL, &mtr);
if (srv_pass_corrupt_table && !root) {
mtr_commit(&mtr);
return;
}
ut_a(root);
-
+
#ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
+ root, space));
@@ -1473,7 +1477,8 @@ leaf_loop:
top_loop:
mtr_start(&mtr);
- root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr);
+ root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
+ NULL, &mtr);
if (srv_pass_corrupt_table && !root) {
mtr_commit(&mtr);
@@ -1505,13 +1510,13 @@ btr_free_root(
ulint zip_size, /*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint root_page_no, /*!< in: root page number */
- mtr_t* mtr) /*!< in: a mini-transaction which has already
- been started */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
buf_block_t* block;
fseg_header_t* header;
- block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
+ NULL, mtr);
if (srv_pass_corrupt_table && !block) {
return;
@@ -2395,9 +2400,8 @@ btr_attach_half_pages(
/* Update page links of the level */
if (prev_page_no != FIL_NULL) {
- buf_block_t* prev_block = btr_block_get(space, zip_size,
- prev_page_no,
- RW_X_LATCH, mtr);
+ buf_block_t* prev_block = btr_block_get(
+ space, zip_size, prev_page_no, RW_X_LATCH, index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(prev_block->frame) == page_is_comp(page));
ut_a(btr_page_get_next(prev_block->frame, mtr)
@@ -2410,9 +2414,8 @@ btr_attach_half_pages(
}
if (next_page_no != FIL_NULL) {
- buf_block_t* next_block = btr_block_get(space, zip_size,
- next_page_no,
- RW_X_LATCH, mtr);
+ buf_block_t* next_block = btr_block_get(
+ space, zip_size, next_page_no, RW_X_LATCH, index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_block->frame) == page_is_comp(page));
ut_a(btr_page_get_prev(next_block->frame, mtr)
@@ -2834,17 +2837,42 @@ func_exit:
return(rec);
}
+#ifdef UNIV_SYNC_DEBUG
+/*************************************************************//**
+Removes a page from the level list of pages.
+@param space in: space where removed
+@param zip_size in: compressed page size in bytes, or 0 for uncompressed
+@param page in/out: page to remove
+@param index in: index tree
+@param mtr in/out: mini-transaction */
+# define btr_level_list_remove(space,zip_size,page,index,mtr) \
+ btr_level_list_remove_func(space,zip_size,page,index,mtr)
+#else /* UNIV_SYNC_DEBUG */
+/*************************************************************//**
+Removes a page from the level list of pages.
+@param space in: space where removed
+@param zip_size in: compressed page size in bytes, or 0 for uncompressed
+@param page in/out: page to remove
+@param index in: index tree
+@param mtr in/out: mini-transaction */
+# define btr_level_list_remove(space,zip_size,page,index,mtr) \
+ btr_level_list_remove_func(space,zip_size,page,mtr)
+#endif /* UNIV_SYNC_DEBUG */
+
/*************************************************************//**
Removes a page from the level list of pages. */
-static
+static __attribute__((nonnull))
void
-btr_level_list_remove(
-/*==================*/
- ulint space, /*!< in: space where removed */
- ulint zip_size,/*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- page_t* page, /*!< in: page to remove */
- mtr_t* mtr) /*!< in: mtr */
+btr_level_list_remove_func(
+/*=======================*/
+ ulint space, /*!< in: space where removed */
+ ulint zip_size,/*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ page_t* page, /*!< in/out: page to remove */
+#ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree */
+#endif /* UNIV_SYNC_DEBUG */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint prev_page_no;
ulint next_page_no;
@@ -2862,7 +2890,7 @@ btr_level_list_remove(
if (prev_page_no != FIL_NULL) {
buf_block_t* prev_block
= btr_block_get(space, zip_size, prev_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
page_t* prev_page
= buf_block_get_frame(prev_block);
#ifdef UNIV_BTR_DEBUG
@@ -2879,7 +2907,7 @@ btr_level_list_remove(
if (next_page_no != FIL_NULL) {
buf_block_t* next_block
= btr_block_get(space, zip_size, next_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
page_t* next_page
= buf_block_get_frame(next_block);
#ifdef UNIV_BTR_DEBUG
@@ -3194,7 +3222,7 @@ btr_compress(
if (is_left) {
merge_block = btr_block_get(space, zip_size, left_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(merge_page, mtr)
@@ -3203,7 +3231,7 @@ btr_compress(
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_prev(merge_page, mtr)
@@ -3292,7 +3320,7 @@ err_exit:
btr_search_drop_page_hash_index(block, index);
/* Remove the page from the level list */
- btr_level_list_remove(space, zip_size, page, mtr);
+ btr_level_list_remove(space, zip_size, page, index, mtr);
btr_node_ptr_delete(index, block, mtr);
lock_update_merge_left(merge_block, orig_pred, block);
@@ -3345,7 +3373,7 @@ err_exit:
#endif /* UNIV_BTR_DEBUG */
/* Remove the page from the level list */
- btr_level_list_remove(space, zip_size, page, mtr);
+ btr_level_list_remove(space, zip_size, page, index, mtr);
/* Replace the address of the old child node (= page) with the
address of the merge page to the right */
@@ -3528,7 +3556,7 @@ btr_discard_page(
if (left_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, left_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(merge_page, mtr)
@@ -3536,7 +3564,7 @@ btr_discard_page(
#endif /* UNIV_BTR_DEBUG */
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_prev(merge_page, mtr)
@@ -3571,7 +3599,7 @@ btr_discard_page(
btr_node_ptr_delete(index, block, mtr);
/* Remove the page from the level list */
- btr_level_list_remove(space, zip_size, page, mtr);
+ btr_level_list_remove(space, zip_size, page, index, mtr);
#ifdef UNIV_ZIP_DEBUG
{
page_zip_des_t* merge_page_zip
@@ -4089,7 +4117,7 @@ loop:
if (right_page_no != FIL_NULL) {
const rec_t* right_rec;
right_block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, &mtr);
+ RW_X_LATCH, index, &mtr);
right_page = buf_block_get_frame(right_block);
if (UNIV_UNLIKELY(btr_page_get_prev(right_page, &mtr)
!= page_get_page_no(page))) {
@@ -4315,7 +4343,7 @@ node_ptr_fails:
mtr_start(&mtr);
block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, &mtr);
+ RW_X_LATCH, index, &mtr);
page = buf_block_get_frame(block);
goto loop;
diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c
index 20876e73da0..717663a123a 100644
--- a/storage/xtradb/btr/btr0cur.c
+++ b/storage/xtradb/btr/btr0cur.c
@@ -249,7 +249,8 @@ btr_cur_latch_leaves(
case BTR_SEARCH_LEAF:
case BTR_MODIFY_LEAF:
mode = latch_mode == BTR_SEARCH_LEAF ? RW_S_LATCH : RW_X_LATCH;
- get_block = btr_block_get(space, zip_size, page_no, mode, mtr);
+ get_block = btr_block_get(
+ space, zip_size, page_no, mode, cursor->index, mtr);
if (srv_pass_corrupt_table && !get_block) {
return;
@@ -265,9 +266,9 @@ btr_cur_latch_leaves(
left_page_no = btr_page_get_prev(page, mtr);
if (left_page_no != FIL_NULL) {
- get_block = btr_block_get(space, zip_size,
- left_page_no,
- RW_X_LATCH, mtr);
+ get_block = btr_block_get(
+ space, zip_size, left_page_no,
+ RW_X_LATCH, cursor->index, mtr);
if (srv_pass_corrupt_table && !get_block) {
return;
@@ -282,8 +283,9 @@ btr_cur_latch_leaves(
get_block->check_index_page_at_flush = TRUE;
}
- get_block = btr_block_get(space, zip_size, page_no,
- RW_X_LATCH, mtr);
+ get_block = btr_block_get(
+ space, zip_size, page_no,
+ RW_X_LATCH, cursor->index, mtr);
if (srv_pass_corrupt_table && !get_block) {
return;
@@ -297,9 +299,9 @@ btr_cur_latch_leaves(
right_page_no = btr_page_get_next(page, mtr);
if (right_page_no != FIL_NULL) {
- get_block = btr_block_get(space, zip_size,
- right_page_no,
- RW_X_LATCH, mtr);
+ get_block = btr_block_get(
+ space, zip_size, right_page_no,
+ RW_X_LATCH, cursor->index, mtr);
if (srv_pass_corrupt_table && !get_block) {
return;
@@ -323,8 +325,9 @@ btr_cur_latch_leaves(
left_page_no = btr_page_get_prev(page, mtr);
if (left_page_no != FIL_NULL) {
- get_block = btr_block_get(space, zip_size,
- left_page_no, mode, mtr);
+ get_block = btr_block_get(
+ space, zip_size,
+ left_page_no, mode, cursor->index, mtr);
cursor->left_block = get_block;
if (srv_pass_corrupt_table && !get_block) {
@@ -340,7 +343,8 @@ btr_cur_latch_leaves(
get_block->check_index_page_at_flush = TRUE;
}
- get_block = btr_block_get(space, zip_size, page_no, mode, mtr);
+ get_block = btr_block_get(
+ space, zip_size, page_no, mode, cursor->index, mtr);
if (srv_pass_corrupt_table && !get_block) {
return;
@@ -722,7 +726,9 @@ retry_page_get:
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(
+ block, dict_index_is_ibuf(index)
+ ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
}
ut_ad(index->id == btr_page_get_index_id(page));
@@ -820,7 +826,7 @@ retry_page_get:
if (level != 0) {
/* x-latch the page */
page = btr_page_get(
- space, zip_size, page_no, RW_X_LATCH, mtr);
+ space, zip_size, page_no, RW_X_LATCH, index, mtr);
ut_a((ibool)!!page_is_comp(page)
== dict_table_is_comp(index->table));
@@ -1167,6 +1173,11 @@ btr_cur_ins_lock_and_undo(
rec_t* rec;
roll_ptr_t roll_ptr;
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip LOCK, UNDO */
+ return(DB_SUCCESS);
+ }
+
/* Check if we have to wait for a lock: enqueue an explicit lock
request if yes */
@@ -1298,7 +1309,7 @@ btr_cur_optimistic_insert(
}
#endif /* UNIV_DEBUG */
- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
max_size = page_get_max_insert_size_after_reorganize(page, 1);
leaf = page_is_leaf(page);
@@ -1393,6 +1404,12 @@ fail_err:
goto fail_err;
}
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip CHANGE, LOG */
+ *big_rec = big_rec_vec;
+ return(err); /* == DB_SUCCESS */
+ }
+
page_cursor = btr_cur_get_page_cur(cursor);
/* Now, try the insert */
@@ -1535,10 +1552,10 @@ btr_cur_pessimistic_insert(
*big_rec = NULL;
- ut_ad(mtr_memo_contains(mtr,
+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr,
dict_index_get_lock(btr_cur_get_index(cursor)),
MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, btr_cur_get_block(cursor),
MTR_MEMO_PAGE_X_FIX));
/* Try first an optimistic insert; reset the cursor flag: we do not
@@ -1604,6 +1621,16 @@ btr_cur_pessimistic_insert(
}
}
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip CHANGE, LOG */
+ if (n_extents > 0) {
+ fil_space_release_free_extents(index->space,
+ n_reserved);
+ }
+ *big_rec = big_rec_vec;
+ return(DB_SUCCESS);
+ }
+
if (dict_index_get_page(index)
== buf_block_get_page_no(btr_cur_get_block(cursor))) {
@@ -1660,6 +1687,11 @@ btr_cur_upd_lock_and_undo(
ut_ad(cursor && update && thr && roll_ptr);
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip LOCK, UNDO */
+ return(DB_SUCCESS);
+ }
+
rec = btr_cur_get_rec(cursor);
index = cursor->index;
@@ -1917,6 +1949,7 @@ btr_cur_update_in_place(
roll_ptr_t roll_ptr = 0;
trx_t* trx;
ulint was_delete_marked;
+ ibool is_hashed;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@@ -1958,7 +1991,29 @@ btr_cur_update_in_place(
return(err);
}
- if (block->is_hashed) {
+ if (trx->fake_changes) {
+ /* skip CHANGE, LOG */
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ return(err); /* == DB_SUCCESS */
+ }
+
+ if (!(flags & BTR_KEEP_SYS_FLAG)) {
+ row_upd_rec_sys_fields(rec, NULL,
+ index, offsets, trx, roll_ptr);
+ }
+
+ was_delete_marked = rec_get_deleted_flag(
+ rec, page_is_comp(buf_block_get_frame(block)));
+
+ is_hashed = block->is_hashed;
+
+ if (is_hashed) {
+ /* TO DO: Can we skip this if none of the fields
+ index->search_info->curr_n_fields
+ are being updated? */
+
/* The function row_upd_changes_ord_field_binary works only
if the update vector was built for a clustered index, we must
NOT call it if index is secondary */
@@ -1974,17 +2029,9 @@ btr_cur_update_in_place(
rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
}
- if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_rec_sys_fields(rec, NULL,
- index, offsets, trx, roll_ptr);
- }
-
- was_delete_marked = rec_get_deleted_flag(
- rec, page_is_comp(buf_block_get_frame(block)));
-
row_upd_rec_in_place(rec, index, offsets, update, page_zip);
- if (block->is_hashed) {
+ if (is_hashed) {
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
}
@@ -2061,7 +2108,7 @@ btr_cur_optimistic_update(
rec = btr_cur_get_rec(cursor);
index = cursor->index;
ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
/* The insert buffer tree should never be updated in place. */
ut_ad(!dict_index_is_ibuf(index));
@@ -2174,6 +2221,11 @@ any_extern:
goto err_exit;
}
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip CHANGE, LOG */
+ goto err_exit; /* == DB_SUCCESS */
+ }
+
/* Ok, we may do the replacement. Store on the page infimum the
explicit locks on rec, before deleting rec (see the comment in
btr_cur_pessimistic_update). */
@@ -2324,9 +2376,9 @@ btr_cur_pessimistic_update(
rec = btr_cur_get_rec(cursor);
index = cursor->index;
- ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
@@ -2414,6 +2466,9 @@ btr_cur_pessimistic_update(
ut_ad(big_rec_vec == NULL);
+ /* fake_changes should not cause undo. so never reaches here */
+ ut_ad(!(trx->fake_changes));
+
btr_rec_free_updated_extern_fields(
index, rec, page_zip, offsets, update,
trx_is_recv(trx) ? RB_RECOVERY : RB_NORMAL, mtr);
@@ -2448,6 +2503,12 @@ make_external:
}
}
+ if (trx->fake_changes) {
+ /* skip CHANGE, LOG */
+ err = DB_SUCCESS;
+ goto return_after_reservations;
+ }
+
/* Store state of explicit locks on rec on the page infimum record,
before deleting rec. The page infimum acts as a dummy carrier of the
locks, taking care also of lock releases, before we can move the locks
@@ -2685,7 +2746,8 @@ btr_cur_parse_del_mark_set_clust_rec(
/* We do not need to reserve btr_search_latch, as the page
is only being recovered, and there cannot be a hash index to
- it. */
+ it. Besides, these fields are being updated in place
+ and the adaptive hash index does not depend on them. */
btr_rec_set_deleted_flag(rec, page_zip, val);
@@ -2749,6 +2811,11 @@ btr_cur_del_mark_set_clust_rec(
ut_ad(dict_index_is_clust(index));
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip LOCK, UNDO, CHANGE, LOG */
+ return(DB_SUCCESS);
+ }
+
err = lock_clust_rec_modify_check_and_lock(flags, block,
rec, index, offsets, thr);
@@ -2765,9 +2832,9 @@ btr_cur_del_mark_set_clust_rec(
return(err);
}
- if (block->is_hashed) {
- rw_lock_x_lock(btr_search_get_latch(index->id));
- }
+ /* The btr_search_latch is not needed here, because
+ the adaptive hash index does not depend on the delete-mark
+ and the delete-mark is being updated in place. */
page_zip = buf_block_get_page_zip(block);
@@ -2781,10 +2848,6 @@ btr_cur_del_mark_set_clust_rec(
index, offsets, trx, roll_ptr);
}
- if (block->is_hashed) {
- rw_lock_x_unlock(btr_search_get_latch(index->id));
- }
-
btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
roll_ptr, mtr);
@@ -2860,7 +2923,8 @@ btr_cur_parse_del_mark_set_sec_rec(
/* We do not need to reserve btr_search_latch, as the page
is only being recovered, and there cannot be a hash index to
- it. */
+ it. Besides, the delete-mark flag is being updated in place
+ and the adaptive hash index does not depend on it. */
btr_rec_set_deleted_flag(rec, page_zip, val);
}
@@ -2886,6 +2950,11 @@ btr_cur_del_mark_set_sec_rec(
rec_t* rec;
ulint err;
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ /* skip LOCK, CHANGE, LOG */
+ return(DB_SUCCESS);
+ }
+
block = btr_cur_get_block(cursor);
rec = btr_cur_get_rec(cursor);
@@ -2908,16 +2977,11 @@ btr_cur_del_mark_set_sec_rec(
ut_ad(!!page_rec_is_comp(rec)
== dict_table_is_comp(cursor->index->table));
- if (block->is_hashed) {
- rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
- }
-
+ /* We do not need to reserve btr_search_latch, as the
+ delete-mark flag is being updated in place and the adaptive
+ hash index does not depend on it. */
btr_rec_set_deleted_flag(rec, buf_block_get_page_zip(block), val);
- if (block->is_hashed) {
- rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
- }
-
btr_cur_del_mark_set_sec_rec_log(rec, val, mtr);
return(DB_SUCCESS);
@@ -2938,8 +3002,11 @@ btr_cur_set_deleted_flag_for_ibuf(
ibool val, /*!< in: value to set */
mtr_t* mtr) /*!< in: mtr */
{
- /* We do not need to reserve btr_search_latch, as the page has just
- been read to the buffer pool and there cannot be a hash index to it. */
+ /* We do not need to reserve btr_search_latch, as the page
+ has just been read to the buffer pool and there cannot be
+ a hash index to it. Besides, the delete-mark flag is being
+ updated in place and the adaptive hash index does not depend
+ on it. */
btr_rec_set_deleted_flag(rec, page_zip, val);
@@ -3598,7 +3665,6 @@ static
void
btr_record_not_null_field_in_rec(
/*=============================*/
- rec_t* rec __attribute__ ((unused)),/*!< in: physical record */
ulint n_unique, /*!< in: dict_index_get_n_unique(index),
number of columns uniquely determine
an index entry */
@@ -3739,7 +3805,7 @@ btr_estimate_number_of_different_key_vals(
if (n_not_null) {
btr_record_not_null_field_in_rec(
- rec, n_cols, offsets_rec, n_not_null);
+ n_cols, offsets_rec, n_not_null);
}
}
@@ -3774,7 +3840,7 @@ btr_estimate_number_of_different_key_vals(
if (n_not_null) {
btr_record_not_null_field_in_rec(
- next_rec, n_cols, offsets_next_rec,
+ n_cols, offsets_next_rec,
n_not_null);
}
@@ -4183,7 +4249,7 @@ btr_blob_free(
&& buf_block_get_space(block) == space
&& buf_block_get_page_no(block) == page_no) {
- if (buf_LRU_free_block(&block->page, all, TRUE) != BUF_LRU_FREED
+ if (!buf_LRU_free_block(&block->page, all, TRUE)
&& all && block->page.zip.data
/* Now, buf_LRU_free_block() may release mutex temporarily */
&& buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE
diff --git a/storage/xtradb/btr/btr0pcur.c b/storage/xtradb/btr/btr0pcur.c
index f95a5487c94..081ef9c9457 100644
--- a/storage/xtradb/btr/btr0pcur.c
+++ b/storage/xtradb/btr/btr0pcur.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -272,8 +272,10 @@ btr_pcur_restore_position_func(
file, line, mtr))) {
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
- buf_block_dbg_add_level(btr_pcur_get_block(cursor),
- SYNC_TREE_NODE);
+ buf_block_dbg_add_level(
+ btr_pcur_get_block(cursor),
+ dict_index_is_ibuf(index)
+ ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
if (cursor->rel_pos == BTR_PCUR_ON) {
#ifdef UNIV_DEBUG
@@ -362,33 +364,6 @@ btr_pcur_restore_position_func(
return(FALSE);
}
-/**************************************************************//**
-If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
-releases the page latch and bufferfix reserved by the cursor.
-NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
-made by the current mini-transaction to the data protected by the
-cursor latch, as then the latch must not be released until mtr_commit. */
-UNIV_INTERN
-void
-btr_pcur_release_leaf(
-/*==================*/
- btr_pcur_t* cursor, /*!< in: persistent cursor */
- mtr_t* mtr) /*!< in: mtr */
-{
- buf_block_t* block;
-
- ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
- ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
-
- block = btr_pcur_get_block(cursor);
-
- btr_leaf_page_release(block, cursor->latch_mode, mtr);
-
- cursor->latch_mode = BTR_NO_LATCHES;
-
- cursor->pos_state = BTR_PCUR_WAS_POSITIONED;
-}
-
/*********************************************************//**
Moves the persistent cursor to the first record on the next page. Releases the
latch on the current page, and bufferunfixes it. Note that there must not be
@@ -423,7 +398,8 @@ btr_pcur_move_to_next_page(
ut_ad(next_page_no != FIL_NULL);
next_block = btr_block_get(space, zip_size, next_page_no,
- cursor->latch_mode, mtr);
+ cursor->latch_mode,
+ btr_pcur_get_btr_cur(cursor)->index, mtr);
next_page = buf_block_get_frame(next_block);
if (srv_pass_corrupt_table && !next_page) {
diff --git a/storage/xtradb/btr/btr0sea.c b/storage/xtradb/btr/btr0sea.c
index 0630b634b53..f27afe216ec 100644
--- a/storage/xtradb/btr/btr0sea.c
+++ b/storage/xtradb/btr/btr0sea.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -878,6 +878,7 @@ btr_search_guess_on_hash(
btr_pcur_t pcur;
#endif
ut_ad(index && info && tuple && cursor && mtr);
+ ut_ad(!dict_index_is_ibuf(index));
ut_ad((latch_mode == BTR_SEARCH_LEAF)
|| (latch_mode == BTR_MODIFY_LEAF));
diff --git a/storage/xtradb/buf/buf0buddy.c b/storage/xtradb/buf/buf0buddy.c
index 07898950fab..9c1ff645260 100644
--- a/storage/xtradb/buf/buf0buddy.c
+++ b/storage/xtradb/buf/buf0buddy.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -56,6 +56,14 @@ buf_buddy_get(
}
}
+/** Validate a given zip_free list. */
+#define BUF_BUDDY_LIST_VALIDATE(b, i) \
+ UT_LIST_VALIDATE(zip_list, buf_page_t, \
+ b->zip_free[i], \
+ ut_ad(buf_page_get_state( \
+ ut_list_node_313) \
+ == BUF_BLOCK_ZIP_FREE))
+
/**********************************************************************//**
Add a block to the head of the appropriate buddy free list. */
UNIV_INLINE
@@ -67,22 +75,11 @@ buf_buddy_add_to_free(
ulint i) /*!< in: index of
buf_pool->zip_free[] */
{
-#ifdef UNIV_DEBUG_VALGRIND
- buf_page_t* b = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
-
- if (b) UNIV_MEM_VALID(b, BUF_BUDDY_LOW << i);
-#endif /* UNIV_DEBUG_VALGRIND */
-
//ut_ad(buf_pool_mutex_own(buf_pool));
ut_ad(mutex_own(&buf_pool->zip_free_mutex));
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
ut_ad(buf_pool->zip_free[i].start != bpage);
UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_free[i], bpage);
-
-#ifdef UNIV_DEBUG_VALGRIND
- if (b) UNIV_MEM_FREE(b, BUF_BUDDY_LOW << i);
- UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i);
-#endif /* UNIV_DEBUG_VALGRIND */
}
/**********************************************************************//**
@@ -96,26 +93,18 @@ buf_buddy_remove_from_free(
ulint i) /*!< in: index of
buf_pool->zip_free[] */
{
-#ifdef UNIV_DEBUG_VALGRIND
+#ifdef UNIV_DEBUG
buf_page_t* prev = UT_LIST_GET_PREV(zip_list, bpage);
buf_page_t* next = UT_LIST_GET_NEXT(zip_list, bpage);
- if (prev) UNIV_MEM_VALID(prev, BUF_BUDDY_LOW << i);
- if (next) UNIV_MEM_VALID(next, BUF_BUDDY_LOW << i);
-
ut_ad(!prev || buf_page_get_state(prev) == BUF_BLOCK_ZIP_FREE);
ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE);
-#endif /* UNIV_DEBUG_VALGRIND */
+#endif /* UNIV_DEBUG */
//ut_ad(buf_pool_mutex_own(buf_pool));
ut_ad(mutex_own(&buf_pool->zip_free_mutex));
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
UT_LIST_REMOVE(zip_list, buf_pool->zip_free[i], bpage);
-
-#ifdef UNIV_DEBUG_VALGRIND
- if (prev) UNIV_MEM_FREE(prev, BUF_BUDDY_LOW << i);
- if (next) UNIV_MEM_FREE(next, BUF_BUDDY_LOW << i);
-#endif /* UNIV_DEBUG_VALGRIND */
}
/**********************************************************************//**
@@ -133,17 +122,13 @@ buf_buddy_alloc_zip(
//ut_ad(buf_pool_mutex_own(buf_pool));
ut_ad(mutex_own(&buf_pool->zip_free_mutex));
ut_a(i < BUF_BUDDY_SIZES);
+ ut_a(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
+
+ ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i));
-#ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing free memory. */
- ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i],
- ut_ad(buf_page_get_state(ut_list_node_313)
- == BUF_BLOCK_ZIP_FREE)));
-#endif /* !UNIV_DEBUG_VALGRIND */
bpage = UT_LIST_GET_LAST(buf_pool->zip_free[i]);
if (bpage) {
- UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
buf_buddy_remove_from_free(buf_pool, bpage, i);
@@ -162,13 +147,10 @@ buf_buddy_alloc_zip(
}
}
-#ifdef UNIV_DEBUG
if (bpage) {
- memset(bpage, ~i, BUF_BUDDY_LOW << i);
+ ut_d(memset(bpage, ~i, BUF_BUDDY_LOW << i));
+ UNIV_MEM_ALLOC(bpage, BUF_BUDDY_SIZES << i);
}
-#endif /* UNIV_DEBUG */
-
- UNIV_MEM_ALLOC(bpage, BUF_BUDDY_SIZES << i);
return(bpage);
}
@@ -264,6 +246,7 @@ buf_buddy_alloc_from(
{
ulint offs = BUF_BUDDY_LOW << j;
ut_ad(j <= BUF_BUDDY_SIZES);
+ ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
ut_ad(j >= i);
ut_ad(!ut_align_offset(buf, offs));
@@ -277,13 +260,7 @@ buf_buddy_alloc_from(
bpage = (buf_page_t*) ((byte*) buf + offs);
ut_d(memset(bpage, j, BUF_BUDDY_LOW << j));
bpage->state = BUF_BLOCK_ZIP_FREE;
-#ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing free memory. */
- ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i],
- ut_ad(buf_page_get_state(
- ut_list_node_313)
- == BUF_BLOCK_ZIP_FREE)));
-#endif /* !UNIV_DEBUG_VALGRIND */
+ ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i));
buf_buddy_add_to_free(buf_pool, bpage, j);
}
@@ -293,28 +270,29 @@ buf_buddy_alloc_from(
/**********************************************************************//**
Allocate a block. The thread calling this function must hold
buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex.
-The buf_pool->mutex may only be released and reacquired if lru != NULL.
-@return allocated block, possibly NULL if lru==NULL */
+The buf_pool_mutex may be released and reacquired.
+@return allocated block, never NULL */
UNIV_INTERN
void*
buf_buddy_alloc_low(
/*================*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
+ buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
ulint i, /*!< in: index of buf_pool->zip_free[],
or BUF_BUDDY_SIZES */
ibool* lru, /*!< in: pointer to a variable that
will be assigned TRUE if storage was
allocated from the LRU list and
buf_pool->mutex was temporarily
- released, or NULL if the LRU list
- should not be used */
+ released */
ibool have_page_hash_mutex)
{
buf_block_t* block;
+ ut_ad(lru);
//ut_ad(buf_pool_mutex_own(buf_pool));
ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
ut_ad(!mutex_own(&buf_pool->zip_mutex));
+ ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
if (i < BUF_BUDDY_SIZES) {
/* Try to allocate from the buddy system. */
@@ -335,11 +313,6 @@ buf_buddy_alloc_low(
goto alloc_big;
}
- if (!lru) {
-
- return(NULL);
- }
-
/* Try replacing an uncompressed page in the buffer pool. */
//buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->LRU_list_mutex);
@@ -369,76 +342,6 @@ func_exit:
}
/**********************************************************************//**
-Try to relocate the control block of a compressed page.
-@return TRUE if relocated */
-static
-ibool
-buf_buddy_relocate_block(
-/*=====================*/
- buf_page_t* bpage, /*!< in: block to relocate */
- buf_page_t* dpage) /*!< in: free block to relocate to */
-{
- buf_page_t* b;
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-
- //ut_ad(buf_pool_mutex_own(buf_pool));
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX));
-#endif
-
- switch (buf_page_get_state(bpage)) {
- case BUF_BLOCK_ZIP_FREE:
- case BUF_BLOCK_NOT_USED:
- case BUF_BLOCK_READY_FOR_USE:
- case BUF_BLOCK_FILE_PAGE:
- case BUF_BLOCK_MEMORY:
- case BUF_BLOCK_REMOVE_HASH:
- /* ut_error; */ /* optimistic */
- case BUF_BLOCK_ZIP_DIRTY:
- /* Cannot relocate dirty pages. */
- return(FALSE);
-
- case BUF_BLOCK_ZIP_PAGE:
- break;
- }
-
- mutex_enter(&buf_pool->zip_mutex);
- mutex_enter(&buf_pool->zip_free_mutex);
-
- if (!buf_page_can_relocate(bpage)) {
- mutex_exit(&buf_pool->zip_mutex);
- mutex_exit(&buf_pool->zip_free_mutex);
- return(FALSE);
- }
-
- if (bpage != buf_page_hash_get(buf_pool,
- bpage->space, bpage->offset)) {
- mutex_exit(&buf_pool->zip_mutex);
- mutex_exit(&buf_pool->zip_free_mutex);
- return(FALSE);
- }
-
- buf_relocate(bpage, dpage);
- ut_d(bpage->state = BUF_BLOCK_ZIP_FREE);
-
- /* relocate buf_pool->zip_clean */
- b = UT_LIST_GET_PREV(zip_list, dpage);
- UT_LIST_REMOVE(zip_list, buf_pool->zip_clean, dpage);
-
- if (b) {
- UT_LIST_INSERT_AFTER(zip_list, buf_pool->zip_clean, b, dpage);
- } else {
- UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_clean, dpage);
- }
-
- UNIV_MEM_INVALID(bpage, sizeof *bpage);
-
- mutex_exit(&buf_pool->zip_mutex);
- mutex_exit(&buf_pool->zip_free_mutex);
- return(TRUE);
-}
-
-/**********************************************************************//**
Try to relocate a block.
@return TRUE if relocated */
static
@@ -454,164 +357,122 @@ buf_buddy_relocate(
{
buf_page_t* bpage;
const ulint size = BUF_BUDDY_LOW << i;
- ullint usec = ut_time_us(NULL);
+ mutex_t* mutex;
+ ulint space;
+ ulint page_no;
//ut_ad(buf_pool_mutex_own(buf_pool));
ut_ad(mutex_own(&buf_pool->zip_free_mutex));
ut_ad(!mutex_own(&buf_pool->zip_mutex));
ut_ad(!ut_align_offset(src, size));
ut_ad(!ut_align_offset(dst, size));
+ ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
UNIV_MEM_ASSERT_W(dst, size);
+ if (!have_page_hash_mutex) {
+ mutex_exit(&buf_pool->zip_free_mutex);
+ mutex_enter(&buf_pool->LRU_list_mutex);
+ rw_lock_x_lock(&buf_pool->page_hash_latch);
+ }
+
/* We assume that all memory from buf_buddy_alloc()
- is used for either compressed pages or buf_page_t
- objects covering compressed pages. */
+ is used for compressed page frames. */
/* We look inside the allocated objects returned by
- buf_buddy_alloc() and assume that anything of
- PAGE_ZIP_MIN_SIZE or larger is a compressed page that contains
- a valid space_id and page_no in the page header. Should the
- fields be invalid, we will be unable to relocate the block.
- We also assume that anything that fits sizeof(buf_page_t)
- actually is a properly initialized buf_page_t object. */
-
- if (size >= PAGE_ZIP_MIN_SIZE) {
- /* This is a compressed page. */
- mutex_t* mutex;
- ulint space, page_no;
+ buf_buddy_alloc() and assume that each block is a compressed
+ page that contains a valid space_id and page_no in the page
+ header. Should the fields be invalid, we will be unable to
+ relocate the block. */
+
+ /* The src block may be split into smaller blocks,
+ some of which may be free. Thus, the
+ mach_read_from_4() calls below may attempt to read
+ from free memory. The memory is "owned" by the buddy
+ allocator (and it has been allocated from the buffer
+ pool), so there is nothing wrong about this. The
+ mach_read_from_4() calls here will only trigger bogus
+ Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
+ space = mach_read_from_4((const byte *) src
+ + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
+ page_no = mach_read_from_4((const byte *) src
+ + FIL_PAGE_OFFSET);
+ /* Suppress Valgrind warnings about conditional jump
+ on uninitialized value. */
+ UNIV_MEM_VALID(&space, sizeof space);
+ UNIV_MEM_VALID(&page_no, sizeof page_no);
+ bpage = buf_page_hash_get(buf_pool, space, page_no);
+
+ if (!bpage || bpage->zip.data != src) {
+ /* The block has probably been freshly
+ allocated by buf_LRU_get_free_block() but not
+ added to buf_pool->page_hash yet. Obviously,
+ it cannot be relocated. */
if (!have_page_hash_mutex) {
- mutex_exit(&buf_pool->zip_free_mutex);
- mutex_enter(&buf_pool->LRU_list_mutex);
- rw_lock_x_lock(&buf_pool->page_hash_latch);
- }
-
- /* The src block may be split into smaller blocks,
- some of which may be free. Thus, the
- mach_read_from_4() calls below may attempt to read
- from free memory. The memory is "owned" by the buddy
- allocator (and it has been allocated from the buffer
- pool), so there is nothing wrong about this. The
- mach_read_from_4() calls here will only trigger bogus
- Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
- space = mach_read_from_4(
- (const byte*) src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
- page_no = mach_read_from_4(
- (const byte*) src + FIL_PAGE_OFFSET);
- /* Suppress Valgrind warnings about conditional jump
- on uninitialized value. */
- UNIV_MEM_VALID(&space, sizeof space);
- UNIV_MEM_VALID(&page_no, sizeof page_no);
- bpage = buf_page_hash_get(buf_pool, space, page_no);
-
- if (!bpage || bpage->zip.data != src) {
- /* The block has probably been freshly
- allocated by buf_LRU_get_free_block() but not
- added to buf_pool->page_hash yet. Obviously,
- it cannot be relocated. */
-
- if (!have_page_hash_mutex) {
- mutex_enter(&buf_pool->zip_free_mutex);
- mutex_exit(&buf_pool->LRU_list_mutex);
- rw_lock_x_unlock(&buf_pool->page_hash_latch);
- }
- return(FALSE);
- }
-
- ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
-
- if (page_zip_get_size(&bpage->zip) != size) {
- /* The block is of different size. We would
- have to relocate all blocks covered by src.
- For the sake of simplicity, give up. */
- ut_ad(page_zip_get_size(&bpage->zip) < size);
-
- if (!have_page_hash_mutex) {
- mutex_enter(&buf_pool->zip_free_mutex);
- mutex_exit(&buf_pool->LRU_list_mutex);
- rw_lock_x_unlock(&buf_pool->page_hash_latch);
- }
- return(FALSE);
+ mutex_enter(&buf_pool->zip_free_mutex);
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
}
+ return(FALSE);
+ }
- /* To keep latch order */
- if (have_page_hash_mutex)
- mutex_exit(&buf_pool->zip_free_mutex);
-
- /* The block must have been allocated, but it may
- contain uninitialized data. */
- UNIV_MEM_ASSERT_W(src, size);
-
- mutex = buf_page_get_mutex_enter(bpage);
-
- mutex_enter(&buf_pool->zip_free_mutex);
-
- if (mutex && buf_page_can_relocate(bpage)) {
- /* Relocate the compressed page. */
- ut_a(bpage->zip.data == src);
- memcpy(dst, src, size);
- bpage->zip.data = dst;
- mutex_exit(mutex);
-success:
- UNIV_MEM_INVALID(src, size);
- {
- buf_buddy_stat_t* buddy_stat
- = &buf_pool->buddy_stat[i];
- buddy_stat->relocated++;
- buddy_stat->relocated_usec
- += ut_time_us(NULL) - usec;
- }
-
- if (!have_page_hash_mutex) {
- mutex_exit(&buf_pool->LRU_list_mutex);
- rw_lock_x_unlock(&buf_pool->page_hash_latch);
- }
- return(TRUE);
- }
+ if (page_zip_get_size(&bpage->zip) != size) {
+ /* The block is of different size. We would
+ have to relocate all blocks covered by src.
+ For the sake of simplicity, give up. */
+ ut_ad(page_zip_get_size(&bpage->zip) < size);
if (!have_page_hash_mutex) {
+ mutex_enter(&buf_pool->zip_free_mutex);
mutex_exit(&buf_pool->LRU_list_mutex);
rw_lock_x_unlock(&buf_pool->page_hash_latch);
}
+ return(FALSE);
+ }
- if (mutex) {
- mutex_exit(mutex);
- }
- } else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) {
- /* This must be a buf_page_t object. */
-#if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in
- buf_page_t. On other systems, Valgrind could complain
- about uninitialized pad bytes. */
- UNIV_MEM_ASSERT_RW(src, size);
-#endif
-
+ /* To keep latch order */
+ if (have_page_hash_mutex)
mutex_exit(&buf_pool->zip_free_mutex);
- if (!have_page_hash_mutex) {
- mutex_enter(&buf_pool->LRU_list_mutex);
- rw_lock_x_lock(&buf_pool->page_hash_latch);
- }
+ /* The block must have been allocated, but it may
+ contain uninitialized data. */
+ UNIV_MEM_ASSERT_W(src, size);
- if (buf_buddy_relocate_block(src, dst)) {
- mutex_enter(&buf_pool->zip_free_mutex);
+ mutex = buf_page_get_mutex_enter(bpage);
- if (!have_page_hash_mutex) {
- mutex_exit(&buf_pool->LRU_list_mutex);
- rw_lock_x_unlock(&buf_pool->page_hash_latch);
- }
+ mutex_enter(&buf_pool->zip_free_mutex);
- goto success;
+ if (mutex && buf_page_can_relocate(bpage)) {
+ /* Relocate the compressed page. */
+ ullint usec = ut_time_us(NULL);
+ ut_a(bpage->zip.data == src);
+ memcpy(dst, src, size);
+ bpage->zip.data = dst;
+ mutex_exit(mutex);
+ UNIV_MEM_INVALID(src, size);
+ {
+ buf_buddy_stat_t* buddy_stat
+ = &buf_pool->buddy_stat[i];
+ buddy_stat->relocated++;
+ buddy_stat->relocated_usec
+ += ut_time_us(NULL) - usec;
}
- mutex_enter(&buf_pool->zip_free_mutex);
-
if (!have_page_hash_mutex) {
mutex_exit(&buf_pool->LRU_list_mutex);
rw_lock_x_unlock(&buf_pool->page_hash_latch);
}
+ return(TRUE);
}
+ if (!have_page_hash_mutex) {
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
+ }
+
+ if (mutex) {
+ mutex_exit(mutex);
+ }
return(FALSE);
}
@@ -635,12 +496,13 @@ buf_buddy_free_low(
ut_ad(mutex_own(&buf_pool->zip_free_mutex));
ut_ad(!mutex_own(&buf_pool->zip_mutex));
ut_ad(i <= BUF_BUDDY_SIZES);
+ ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
ut_ad(buf_pool->buddy_stat[i].used > 0);
buf_pool->buddy_stat[i].used--;
recombine:
UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i);
- ut_d(((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE);
+ ((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE;
if (i == BUF_BUDDY_SIZES) {
mutex_exit(&buf_pool->zip_free_mutex);
@@ -653,32 +515,36 @@ recombine:
ut_ad(buf == ut_align_down(buf, BUF_BUDDY_LOW << i));
ut_ad(!buf_pool_contains_zip(buf_pool, buf));
- /* Try to combine adjacent blocks. */
+ /* Do not recombine blocks if there are few free blocks.
+ We may waste up to 15360*max_len bytes to free blocks
+ (1024 + 2048 + 4096 + 8192 = 15360) */
+ if (UT_LIST_GET_LEN(buf_pool->zip_free[i]) < 16) {
+ goto func_exit;
+ }
+ /* Try to combine adjacent blocks. */
buddy = (buf_page_t*) buf_buddy_get(((byte*) buf), BUF_BUDDY_LOW << i);
#ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing free memory. */
+ /* When Valgrind instrumentation is not enabled, we can read
+ buddy->state to quickly determine that a block is not free.
+ When the block is not free, buddy->state belongs to a compressed
+ page frame that may be flagged uninitialized in our Valgrind
+ instrumentation. */
if (buddy->state != BUF_BLOCK_ZIP_FREE) {
goto buddy_nonfree;
}
-
- /* The field buddy->state can only be trusted for free blocks.
- If buddy->state == BUF_BLOCK_ZIP_FREE, the block is free if
- it is in the free list. */
#endif /* !UNIV_DEBUG_VALGRIND */
for (bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); bpage; ) {
- UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
if (bpage == buddy) {
-buddy_free:
/* The buddy is free: recombine */
buf_buddy_remove_from_free(buf_pool, bpage, i);
-buddy_free2:
+buddy_is_free:
ut_ad(buf_page_get_state(buddy) == BUF_BLOCK_ZIP_FREE);
ut_ad(!buf_pool_contains_zip(buf_pool, buddy));
i++;
@@ -688,122 +554,42 @@ buddy_free2:
}
ut_a(bpage != buf);
-
- {
- buf_page_t* next = UT_LIST_GET_NEXT(zip_list, bpage);
- UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i);
- bpage = next;
- }
+ UNIV_MEM_ASSERT_W(bpage, BUF_BUDDY_LOW << i);
+ bpage = UT_LIST_GET_NEXT(zip_list, bpage);
}
#ifndef UNIV_DEBUG_VALGRIND
buddy_nonfree:
- /* Valgrind would complain about accessing free memory. */
- ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i],
- ut_ad(buf_page_get_state(ut_list_node_313)
- == BUF_BLOCK_ZIP_FREE)));
-#endif /* UNIV_DEBUG_VALGRIND */
+#endif /* !UNIV_DEBUG_VALGRIND */
+
+ ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i));
/* The buddy is not free. Is there a free block of this size? */
bpage = UT_LIST_GET_LAST(buf_pool->zip_free[i]);
if (bpage) {
+
/* Remove the block from the free list, because a successful
buf_buddy_relocate() will overwrite bpage->list. */
-
- UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
buf_buddy_remove_from_free(buf_pool, bpage, i);
/* Try to relocate the buddy of buf to the free block. */
if (buf_buddy_relocate(buf_pool, buddy, bpage, i, have_page_hash_mutex)) {
- ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
- goto buddy_free2;
+ buddy->state = BUF_BLOCK_ZIP_FREE;
+ goto buddy_is_free;
}
buf_buddy_add_to_free(buf_pool, bpage, i);
-
- /* Try to relocate the buddy of the free block to buf. */
- buddy = (buf_page_t*) buf_buddy_get(((byte*) bpage),
- BUF_BUDDY_LOW << i);
-
-#ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing free memory. */
-
- /* The buddy must not be (completely) free, because we
- always recombine adjacent free blocks.
-
- (Parts of the buddy can be free in
- buf_pool->zip_free[j] with j < i.) */
- ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i],
- ut_ad(buf_page_get_state(
- ut_list_node_313)
- == BUF_BLOCK_ZIP_FREE
- && ut_list_node_313 != buddy)));
-#endif /* !UNIV_DEBUG_VALGRIND */
-
- if (buf_buddy_relocate(buf_pool, buddy, buf, i, have_page_hash_mutex)) {
-
- buf = bpage;
- UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
- ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
- goto buddy_free;
- }
}
+func_exit:
/* Free the block to the buddy list. */
bpage = buf;
-#ifdef UNIV_DEBUG
- if (i < buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)) {
- /* This area has most likely been allocated for at
- least one compressed-only block descriptor. Check
- that there are no live objects in the area. This is
- not a complete check: it may yield false positives as
- well as false negatives. Also, due to buddy blocks
- being recombined, it is possible (although unlikely)
- that this branch is never reached. */
-
- char* c;
-
-# ifndef UNIV_DEBUG_VALGRIND
- /* Valgrind would complain about accessing
- uninitialized memory. Besides, Valgrind performs a
- more exhaustive check, at every memory access. */
- const buf_page_t* b = buf;
- const buf_page_t* const b_end = (buf_page_t*)
- ((char*) b + (BUF_BUDDY_LOW << i));
-
- for (; b < b_end; b++) {
- /* Avoid false positives (and cause false
- negatives) by checking for b->space < 1000. */
-
- if ((b->state == BUF_BLOCK_ZIP_PAGE
- || b->state == BUF_BLOCK_ZIP_DIRTY)
- && b->space > 0 && b->space < 1000) {
- fprintf(stderr,
- "buddy dirty %p %u (%u,%u) %p,%lu\n",
- (void*) b,
- b->state, b->space, b->offset,
- buf, i);
- }
- }
-# endif /* !UNIV_DEBUG_VALGRIND */
-
- /* Scramble the block. This should make any pointers
- invalid and trigger a segmentation violation. Because
- the scrambling can be reversed, it may be possible to
- track down the object pointing to the freed data by
- dereferencing the unscrambled bpage->LRU or
- bpage->list pointers. */
- for (c = (char*) buf + (BUF_BUDDY_LOW << i);
- c-- > (char*) buf; ) {
- *c = ~*c ^ i;
- }
- } else {
- /* Fill large blocks with a constant pattern. */
- memset(bpage, i, BUF_BUDDY_LOW << i);
- }
-#endif /* UNIV_DEBUG */
+
+ /* Fill large blocks with a constant pattern. */
+ ut_d(memset(bpage, i, BUF_BUDDY_LOW << i));
+ UNIV_MEM_INVALID(bpage, BUF_BUDDY_LOW << i);
bpage->state = BUF_BLOCK_ZIP_FREE;
buf_buddy_add_to_free(buf_pool, bpage, i);
}
diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c
index aed76e8121c..7b228eaa11f 100644
--- a/storage/xtradb/buf/buf0buf.c
+++ b/storage/xtradb/buf/buf0buf.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -442,6 +442,7 @@ buf_get_total_stat(
tot_stat->n_pages_read += buf_stat->n_pages_read;
tot_stat->n_pages_written += buf_stat->n_pages_written;
tot_stat->n_pages_created += buf_stat->n_pages_created;
+ tot_stat->n_ra_pages_read_rnd += buf_stat->n_ra_pages_read_rnd;
tot_stat->n_ra_pages_read += buf_stat->n_ra_pages_read;
tot_stat->n_ra_pages_evicted += buf_stat->n_ra_pages_evicted;
tot_stat->n_pages_made_young += buf_stat->n_pages_made_young;
@@ -1196,72 +1197,6 @@ buf_chunk_not_freed(
return(NULL);
}
-/*********************************************************************//**
-Checks that all blocks in the buffer chunk are in BUF_BLOCK_NOT_USED state.
-@return TRUE if all freed */
-static
-ibool
-buf_chunk_all_free(
-/*===============*/
- const buf_chunk_t* chunk) /*!< in: chunk being checked */
-{
- const buf_block_t* block;
- ulint i;
-
- block = chunk->blocks;
-
- for (i = chunk->size; i--; block++) {
-
- if (buf_block_get_state(block) != BUF_BLOCK_NOT_USED) {
-
- return(FALSE);
- }
- }
-
- return(TRUE);
-}
-
-/********************************************************************//**
-Frees a chunk of buffer frames. */
-static
-void
-buf_chunk_free(
-/*===========*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
- buf_chunk_t* chunk) /*!< out: chunk of buffers */
-{
- buf_block_t* block;
- const buf_block_t* block_end;
-
- //ut_ad(buf_pool_mutex_own(buf_pool)); /* but we need all mutex here */
-
- block_end = chunk->blocks + chunk->size;
-
- for (block = chunk->blocks; block < block_end; block++) {
- ut_a(buf_block_get_state(block) == BUF_BLOCK_NOT_USED);
- ut_a(!block->page.zip.data);
-
- ut_ad(!block->page.in_LRU_list);
- ut_ad(!block->in_unzip_LRU_list);
- ut_ad(!block->page.in_flush_list);
- /* Remove the block from the free list. */
- mutex_enter(&buf_pool->free_list_mutex);
- ut_ad(block->page.in_free_list);
- UT_LIST_REMOVE(free, buf_pool->free, (&block->page));
- mutex_exit(&buf_pool->free_list_mutex);
-
- /* Free the latches. */
- mutex_free(&block->mutex);
- rw_lock_free(&block->lock);
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_free(&block->debug_latch);
-#endif /* UNIV_SYNC_DEBUG */
- UNIV_MEM_UNDESC(block);
- }
-
- os_mem_free_large(chunk->mem, chunk->mem_size);
-}
-
/********************************************************************//**
Set buffer pool size variables after resizing it */
static
@@ -1387,8 +1322,6 @@ buf_pool_free_instance(
chunk = chunks + buf_pool->n_chunks;
while (--chunk >= chunks) {
- /* Bypass the checks of buf_chunk_free(), since they
- would fail at shutdown. */
os_mem_free_large(chunk->mem, chunk->mem_size);
}
@@ -1656,290 +1589,6 @@ buf_relocate(
}
/********************************************************************//**
-Shrinks a buffer pool instance. */
-static
-void
-buf_pool_shrink_instance(
-/*=====================*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
- ulint chunk_size) /*!< in: number of pages to remove */
-{
- buf_chunk_t* chunks;
- buf_chunk_t* chunk;
- ulint max_size;
- ulint max_free_size;
- buf_chunk_t* max_chunk;
- buf_chunk_t* max_free_chunk;
-
- ut_ad(!buf_pool_mutex_own(buf_pool));
-
-try_again:
- btr_search_disable(); /* Empty the adaptive hash index again */
- //buf_pool_mutex_enter(buf_pool);
- mutex_enter(&buf_pool->LRU_list_mutex);
-
-shrink_again:
- if (buf_pool->n_chunks <= 1) {
-
- /* Cannot shrink if there is only one chunk */
- goto func_done;
- }
-
- /* Search for the largest free chunk
- not larger than the size difference */
- chunks = buf_pool->chunks;
- chunk = chunks + buf_pool->n_chunks;
- max_size = max_free_size = 0;
- max_chunk = max_free_chunk = NULL;
-
- while (--chunk >= chunks) {
- if (chunk->size <= chunk_size
- && chunk->size > max_free_size) {
- if (chunk->size > max_size) {
- max_size = chunk->size;
- max_chunk = chunk;
- }
-
- if (buf_chunk_all_free(chunk)) {
- max_free_size = chunk->size;
- max_free_chunk = chunk;
- }
- }
- }
-
- if (!max_free_size) {
-
- ulint dirty = 0;
- ulint nonfree = 0;
- buf_block_t* block;
- buf_block_t* bend;
-
- /* Cannot shrink: try again later
- (do not assign srv_buf_pool_old_size) */
- if (!max_chunk) {
-
- goto func_exit;
- }
-
- block = max_chunk->blocks;
- bend = block + max_chunk->size;
-
- /* Move the blocks of chunk to the end of the
- LRU list and try to flush them. */
- for (; block < bend; block++) {
- switch (buf_block_get_state(block)) {
- case BUF_BLOCK_NOT_USED:
- continue;
- case BUF_BLOCK_FILE_PAGE:
- break;
- default:
- nonfree++;
- continue;
- }
-
- mutex_enter(&block->mutex);
- /* The following calls will temporarily
- release block->mutex and buf_pool->mutex.
- Therefore, we have to always retry,
- even if !dirty && !nonfree. */
-
- if (!buf_flush_ready_for_replace(&block->page)) {
-
- buf_LRU_make_block_old(&block->page);
- dirty++;
- } else if (buf_LRU_free_block(&block->page, TRUE, TRUE)
- != BUF_LRU_FREED) {
- nonfree++;
- }
-
- mutex_exit(&block->mutex);
- }
-
- //buf_pool_mutex_exit(buf_pool);
- mutex_exit(&buf_pool->LRU_list_mutex);
-
- /* Request for a flush of the chunk if it helps.
- Do not flush if there are non-free blocks, since
- flushing will not make the chunk freeable. */
- if (nonfree) {
- /* Avoid busy-waiting. */
- os_thread_sleep(100000);
- } else if (dirty
- && buf_flush_LRU(buf_pool, dirty)
- == ULINT_UNDEFINED) {
-
- buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU);
- }
-
- goto try_again;
- }
-
- max_size = max_free_size;
- max_chunk = max_free_chunk;
-
- buf_pool->old_pool_size = buf_pool->curr_pool_size;
-
- /* Rewrite buf_pool->chunks. Copy everything but max_chunk. */
- chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
- memcpy(chunks, buf_pool->chunks,
- (max_chunk - buf_pool->chunks) * sizeof *chunks);
- memcpy(chunks + (max_chunk - buf_pool->chunks),
- max_chunk + 1,
- buf_pool->chunks + buf_pool->n_chunks
- - (max_chunk + 1));
- ut_a(buf_pool->curr_size > max_chunk->size);
- buf_pool->curr_size -= max_chunk->size;
- buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
- chunk_size -= max_chunk->size;
- buf_chunk_free(buf_pool, max_chunk);
- mem_free(buf_pool->chunks);
- buf_pool->chunks = chunks;
- buf_pool->n_chunks--;
-
- /* Allow a slack of one megabyte. */
- if (chunk_size > 1048576 / UNIV_PAGE_SIZE) {
-
- goto shrink_again;
- }
- goto func_exit;
-
-func_done:
- buf_pool->old_pool_size = buf_pool->curr_pool_size;
-func_exit:
- //buf_pool_mutex_exit(buf_pool);
- mutex_exit(&buf_pool->LRU_list_mutex);
- btr_search_enable();
-}
-
-/********************************************************************//**
-Shrinks the buffer pool. */
-static
-void
-buf_pool_shrink(
-/*============*/
- ulint chunk_size) /*!< in: number of pages to remove */
-{
- ulint i;
-
- for (i = 0; i < srv_buf_pool_instances; i++) {
- buf_pool_t* buf_pool;
- ulint instance_chunk_size;
-
- instance_chunk_size = chunk_size / srv_buf_pool_instances;
- buf_pool = buf_pool_from_array(i);
- buf_pool_shrink_instance(buf_pool, instance_chunk_size);
- }
-
- buf_pool_set_sizes();
-}
-
-/********************************************************************//**
-Rebuild buf_pool->page_hash for a buffer pool instance. */
-static
-void
-buf_pool_page_hash_rebuild_instance(
-/*================================*/
- buf_pool_t* buf_pool) /*!< in: buffer pool instance */
-{
- ulint i;
- buf_page_t* b;
- buf_chunk_t* chunk;
- ulint n_chunks;
- hash_table_t* zip_hash;
- hash_table_t* page_hash;
-
- //buf_pool_mutex_enter(buf_pool);
- mutex_enter(&buf_pool->LRU_list_mutex);
- rw_lock_x_lock(&buf_pool->page_hash_latch);
-
- /* Free, create, and populate the hash table. */
- hash_table_free(buf_pool->page_hash);
- buf_pool->page_hash = page_hash = hash_create(2 * buf_pool->curr_size);
- zip_hash = hash_create(2 * buf_pool->curr_size);
-
- HASH_MIGRATE(buf_pool->zip_hash, zip_hash, buf_page_t, hash,
- BUF_POOL_ZIP_FOLD_BPAGE);
-
- hash_table_free(buf_pool->zip_hash);
- buf_pool->zip_hash = zip_hash;
-
- /* Insert the uncompressed file pages to buf_pool->page_hash. */
-
- chunk = buf_pool->chunks;
- n_chunks = buf_pool->n_chunks;
-
- for (i = 0; i < n_chunks; i++, chunk++) {
- ulint j;
- buf_block_t* block = chunk->blocks;
-
- for (j = 0; j < chunk->size; j++, block++) {
- if (buf_block_get_state(block)
- == BUF_BLOCK_FILE_PAGE) {
- ut_ad(!block->page.in_zip_hash);
- ut_ad(block->page.in_page_hash);
-
- HASH_INSERT(buf_page_t, hash, page_hash,
- buf_page_address_fold(
- block->page.space,
- block->page.offset),
- &block->page);
- }
- }
- }
-
- /* Insert the compressed-only pages to buf_pool->page_hash.
- All such blocks are either in buf_pool->zip_clean or
- in buf_pool->flush_list. */
-
- mutex_enter(&buf_pool->zip_mutex);
- for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
- b = UT_LIST_GET_NEXT(zip_list, b)) {
- ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
- ut_ad(!b->in_flush_list);
- ut_ad(b->in_LRU_list);
- ut_ad(b->in_page_hash);
- ut_ad(!b->in_zip_hash);
-
- HASH_INSERT(buf_page_t, hash, page_hash,
- buf_page_address_fold(b->space, b->offset), b);
- }
- mutex_exit(&buf_pool->zip_mutex);
-
- buf_flush_list_mutex_enter(buf_pool);
- for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
- b = UT_LIST_GET_NEXT(flush_list, b)) {
- ut_ad(b->in_flush_list);
- ut_ad(b->in_LRU_list);
- ut_ad(b->in_page_hash);
- ut_ad(!b->in_zip_hash);
-
- switch (buf_page_get_state(b)) {
- case BUF_BLOCK_ZIP_DIRTY:
- HASH_INSERT(buf_page_t, hash, page_hash,
- buf_page_address_fold(b->space,
- b->offset), b);
- break;
- case BUF_BLOCK_FILE_PAGE:
- /* uncompressed page */
- break;
- case BUF_BLOCK_ZIP_FREE:
- case BUF_BLOCK_ZIP_PAGE:
- case BUF_BLOCK_NOT_USED:
- case BUF_BLOCK_READY_FOR_USE:
- case BUF_BLOCK_MEMORY:
- case BUF_BLOCK_REMOVE_HASH:
- ut_error;
- break;
- }
- }
-
- buf_flush_list_mutex_exit(buf_pool);
- //buf_pool_mutex_exit(buf_pool);
- mutex_exit(&buf_pool->LRU_list_mutex);
- rw_lock_x_unlock(&buf_pool->page_hash_latch);
-}
-
-/********************************************************************
Determine if a block is a sentinel for a buffer pool watch.
@return TRUE if a sentinel for a buffer pool watch, FALSE if not */
UNIV_INTERN
@@ -2060,127 +1709,6 @@ buf_pool_watch_set(
return(NULL);
}
-/********************************************************************//**
-Rebuild buf_pool->page_hash. */
-static
-void
-buf_pool_page_hash_rebuild(void)
-/*============================*/
-{
- ulint i;
-
- for (i = 0; i < srv_buf_pool_instances; i++) {
- buf_pool_page_hash_rebuild_instance(buf_pool_from_array(i));
- }
-}
-
-/********************************************************************//**
-Increase the buffer pool size of one buffer pool instance. */
-static
-void
-buf_pool_increase_instance(
-/*=======================*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instane */
- ulint change_size) /*!< in: new size of the pool */
-{
- buf_chunk_t* chunks;
- buf_chunk_t* chunk;
-
- mutex_enter(&buf_pool->LRU_list_mutex);
- rw_lock_x_lock(&buf_pool->page_hash_latch);
- buf_pool_mutex_enter(buf_pool);
- chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
-
- memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks * sizeof *chunks);
-
- chunk = &chunks[buf_pool->n_chunks];
-
- if (!buf_chunk_init(buf_pool, chunk, change_size)) {
- mem_free(chunks);
- } else {
- buf_pool->old_pool_size = buf_pool->curr_pool_size;
- buf_pool->curr_size += chunk->size;
- buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
- mem_free(buf_pool->chunks);
- buf_pool->chunks = chunks;
- buf_pool->n_chunks++;
- }
-
- mutex_exit(&buf_pool->LRU_list_mutex);
- rw_lock_x_unlock(&buf_pool->page_hash_latch);
- buf_pool_mutex_exit(buf_pool);
-}
-
-/********************************************************************//**
-Increase the buffer pool size. */
-static
-void
-buf_pool_increase(
-/*==============*/
- ulint change_size)
-{
- ulint i;
-
- for (i = 0; i < srv_buf_pool_instances; i++) {
- buf_pool_increase_instance(
- buf_pool_from_array(i),
- change_size / srv_buf_pool_instances);
- }
-
- buf_pool_set_sizes();
-}
-
-/********************************************************************//**
-Resizes the buffer pool. */
-UNIV_INTERN
-void
-buf_pool_resize(void)
-/*=================*/
-{
- ulint change_size;
- ulint min_change_size = 1048576 * srv_buf_pool_instances;
-
- buf_pool_mutex_enter_all();
-
- if (srv_buf_pool_old_size == srv_buf_pool_size) {
-
- buf_pool_mutex_exit_all();
-
- return;
-
- } else if (srv_buf_pool_curr_size + min_change_size
- > srv_buf_pool_size) {
-
- change_size = (srv_buf_pool_curr_size - srv_buf_pool_size)
- / UNIV_PAGE_SIZE;
-
- buf_pool_mutex_exit_all();
-
- /* Disable adaptive hash indexes and empty the index
- in order to free up memory in the buffer pool chunks. */
- buf_pool_shrink(change_size);
-
- } else if (srv_buf_pool_curr_size + min_change_size
- < srv_buf_pool_size) {
-
- /* Enlarge the buffer pool by at least one megabyte */
-
- change_size = srv_buf_pool_size - srv_buf_pool_curr_size;
-
- buf_pool_mutex_exit_all();
-
- buf_pool_increase(change_size);
- } else {
- srv_buf_pool_size = srv_buf_pool_old_size;
-
- buf_pool_mutex_exit_all();
-
- return;
- }
-
- buf_pool_page_hash_rebuild();
-}
-
/****************************************************************//**
Remove the sentinel block for the watch before replacing it with a real block.
buf_page_watch_clear() or buf_page_watch_occurred() will notice that
@@ -2524,6 +2052,27 @@ lookup:
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
}
+ if (UNIV_UNLIKELY(bpage->space_was_being_deleted)) {
+ /* This page is obsoleted, should discard and retry */
+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
+
+ mutex_enter(&buf_pool->LRU_list_mutex);
+ block_mutex = buf_page_get_mutex_enter(bpage);
+
+ if (UNIV_UNLIKELY(!block_mutex)) {
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ goto lookup;
+ }
+
+ buf_LRU_free_block(bpage, TRUE, TRUE);
+
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ mutex_exit(block_mutex);
+ block_mutex = NULL;
+
+ goto lookup;
+ }
+
if (UNIV_UNLIKELY(!bpage->zip.data)) {
/* There is no compressed page. */
err_exit:
@@ -2580,7 +2129,7 @@ err_exit:
}
/* Discard the uncompressed page frame if possible. */
- if (buf_LRU_free_block(bpage, FALSE, TRUE) == BUF_LRU_FREED) {
+ if (buf_LRU_free_block(bpage, FALSE, TRUE)) {
mutex_exit(&buf_pool->LRU_list_mutex);
mutex_exit(block_mutex);
goto lookup;
@@ -3010,12 +2559,8 @@ loop:
block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
/* If the guess is a compressed page descriptor that
- has been allocated by buf_buddy_alloc(), it may have
- been invalidated by buf_buddy_relocate(). In that
- case, block could point to something that happens to
- contain the expected bits in block->page. Similarly,
- the guess may be pointing to a buffer pool chunk that
- has been released when resizing the buffer pool. */
+ has been allocated by buf_page_alloc_descriptor(),
+ it may have been freed by buf_relocate(). */
if (!block_mutex) {
block = guess = NULL;
@@ -3038,6 +2583,27 @@ loop:
block = (buf_block_t*) buf_page_hash_get_low(
buf_pool, space, offset, fold);
if (block) {
+ if (UNIV_UNLIKELY(block->page.space_was_being_deleted)) {
+ /* This page is obsoleted, should discard and retry */
+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
+
+ mutex_enter(&buf_pool->LRU_list_mutex);
+ block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
+
+ if (UNIV_UNLIKELY(!block_mutex)) {
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ goto loop;
+ }
+
+ buf_LRU_free_block((buf_page_t*)block, TRUE, TRUE);
+
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ mutex_exit(block_mutex);
+ block_mutex = NULL;
+
+ goto loop;
+ }
+
block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
ut_a(block_mutex);
}
@@ -3075,6 +2641,9 @@ loop2:
}
if (buf_read_page(space, zip_size, offset, trx)) {
+ buf_read_ahead_random(space, zip_size, offset,
+ ibuf_inside(mtr), trx);
+
retries = 0;
} else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
++retries;
@@ -3237,8 +2806,10 @@ wait_until_unfixed:
if (buf_page_get_state(&block->page)
== BUF_BLOCK_ZIP_PAGE) {
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
UT_LIST_REMOVE(zip_list, buf_pool->zip_clean,
&block->page);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
ut_ad(!block->page.in_flush_list);
} else {
/* Relocate buf_pool->flush_list. */
@@ -3269,11 +2840,10 @@ wait_until_unfixed:
buf_pool->n_pend_unzip++;
buf_pool_mutex_exit(buf_pool);
- bpage->state = BUF_BLOCK_ZIP_FREE;
- buf_buddy_free(buf_pool, bpage, sizeof *bpage, FALSE);
-
//buf_pool_mutex_exit(buf_pool);
+ buf_page_free_descriptor(bpage);
+
/* Decompress the page and apply buffered operations
while not holding buf_pool->mutex or block->mutex. */
success = buf_zip_decompress(block, srv_use_checksums);
@@ -3322,7 +2892,7 @@ wait_until_unfixed:
/* Try to evict the block from the buffer pool, to use the
insert buffer (change buffer) as much as possible. */
- if (buf_LRU_free_block(&block->page, TRUE, FALSE) == BUF_LRU_FREED) {
+ if (buf_LRU_free_block(&block->page, TRUE, FALSE)) {
mutex_exit(block_mutex);
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
/* Set the watch, as it would have
@@ -3809,19 +3379,20 @@ buf_page_init_low(
/********************************************************************//**
Inits a page to the buffer buf_pool. */
-static
+static __attribute__((nonnull))
void
buf_page_init(
/*==========*/
+ buf_pool_t* buf_pool,/*!< in/out: buffer pool */
ulint space, /*!< in: space id */
ulint offset, /*!< in: offset of the page within space
in units of a page */
ulint fold, /*!< in: buf_page_address_fold(space,offset) */
- buf_block_t* block) /*!< in: block to init */
+ buf_block_t* block) /*!< in/out: block to init */
{
buf_page_t* hash_page;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
+ ut_ad(buf_pool == buf_pool_get(space, offset));
//ut_ad(buf_pool_mutex_own(buf_pool));
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX));
@@ -3955,11 +3526,28 @@ buf_page_init_for_read(
fold = buf_page_address_fold(space, offset);
+retry:
//buf_pool_mutex_enter(buf_pool);
mutex_enter(&buf_pool->LRU_list_mutex);
rw_lock_x_lock(&buf_pool->page_hash_latch);
watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
+
+ if (UNIV_UNLIKELY(watch_page && watch_page->space_was_being_deleted)) {
+ mutex_t* block_mutex = buf_page_get_mutex_enter(watch_page);
+
+ /* This page is obsoleted, should discard and retry */
+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
+ ut_a(block_mutex);
+
+ buf_LRU_free_block(watch_page, TRUE, TRUE);
+
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ mutex_exit(block_mutex);
+
+ goto retry;
+ }
+
if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
/* The page is already in the buffer pool. */
watch_page = NULL;
@@ -3995,7 +3583,7 @@ err_exit:
ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
- buf_page_init(space, offset, fold, block);
+ buf_page_init(buf_pool, space, offset, fold, block);
rw_lock_x_unlock(&buf_pool->page_hash_latch);
@@ -4042,20 +3630,11 @@ err_exit:
mutex_exit(&buf_pool->LRU_list_mutex);
mutex_exit(&block->mutex);
} else {
- /* Defer buf_buddy_alloc() until after the block has
- been found not to exist. The buf_buddy_alloc() and
- buf_buddy_free() calls may be expensive because of
- buf_buddy_relocate(). */
-
/* The compressed page must be allocated before the
control block (bpage), in order to avoid the
invocation of buf_buddy_relocate_block() on
uninitialized data. */
data = buf_buddy_alloc(buf_pool, zip_size, &lru, TRUE);
- bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru, TRUE);
-
- /* Initialize the buf_pool pointer. */
- bpage->buf_pool_index = buf_pool_index(buf_pool);
/* If buf_buddy_alloc() allocated storage from the LRU list,
it released and reacquired buf_pool->mutex. Thus, we must
@@ -4071,8 +3650,6 @@ err_exit:
/* The block was added by some other thread. */
watch_page = NULL;
- bpage->state = BUF_BLOCK_ZIP_FREE;
- buf_buddy_free(buf_pool, bpage, sizeof *bpage, TRUE);
buf_buddy_free(buf_pool, data, zip_size, TRUE);
mutex_exit(&buf_pool->LRU_list_mutex);
@@ -4083,6 +3660,11 @@ err_exit:
}
}
+ bpage = buf_page_alloc_descriptor();
+
+ /* Initialize the buf_pool pointer. */
+ bpage->buf_pool_index = buf_pool_index(buf_pool);
+
page_zip_des_init(&bpage->zip);
page_zip_set_size(&bpage->zip, zip_size);
bpage->zip.data = data;
@@ -4098,7 +3680,6 @@ err_exit:
bpage->offset = offset;
bpage->space_was_being_deleted = FALSE;
-
#ifdef UNIV_DEBUG
bpage->in_page_hash = FALSE;
bpage->in_zip_hash = FALSE;
@@ -4125,7 +3706,9 @@ err_exit:
/* The block must be put to the LRU list, to the old blocks */
buf_LRU_add_block(bpage, TRUE/* to old blocks */);
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
buf_LRU_insert_zip_clean(bpage);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
mutex_exit(&buf_pool->LRU_list_mutex);
@@ -4180,6 +3763,7 @@ buf_page_create(
fold = buf_page_address_fold(space, offset);
+retry:
//buf_pool_mutex_enter(buf_pool);
mutex_enter(&buf_pool->LRU_list_mutex);
rw_lock_x_lock(&buf_pool->page_hash_latch);
@@ -4187,6 +3771,21 @@ buf_page_create(
block = (buf_block_t*) buf_page_hash_get_low(
buf_pool, space, offset, fold);
+ if (UNIV_UNLIKELY(block && block->page.space_was_being_deleted)) {
+ mutex_t* block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
+
+ /* This page is obsoleted, should discard and retry */
+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
+ ut_a(block_mutex);
+
+ buf_LRU_free_block((buf_page_t*)block, TRUE, TRUE);
+
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ mutex_exit(block_mutex);
+
+ goto retry;
+ }
+
if (block
&& buf_page_in_file(&block->page)
&& !buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
@@ -4221,7 +3820,7 @@ buf_page_create(
mutex_enter(&block->mutex);
- buf_page_init(space, offset, fold, block);
+ buf_page_init(buf_pool, space, offset, fold, block);
rw_lock_x_unlock(&buf_pool->page_hash_latch);
/* The block must be put to the LRU list */
@@ -4307,6 +3906,59 @@ buf_page_create(
}
/********************************************************************//**
+Mark a table with the specified space pointed by bpage->space corrupted.
+Also remove the bpage from LRU list.
+@return TRUE if successful */
+static
+ibool
+buf_mark_space_corrupt(
+/*===================*/
+ buf_page_t* bpage) /*!< in: pointer to the block in question */
+{
+ buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
+ const ibool uncompressed = (buf_page_get_state(bpage)
+ == BUF_BLOCK_FILE_PAGE);
+ ulint space = bpage->space;
+ ibool ret = TRUE;
+
+ /* First unfix and release lock on the bpage */
+ //buf_pool_mutex_enter(buf_pool);
+ mutex_enter(&buf_pool->LRU_list_mutex);
+ rw_lock_x_lock(&buf_pool->page_hash_latch);
+ mutex_enter(buf_page_get_mutex(bpage));
+ ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
+ ut_ad(bpage->buf_fix_count == 0);
+
+ /* Set BUF_IO_NONE before we remove the block from LRU list */
+ buf_page_set_io_fix(bpage, BUF_IO_NONE);
+
+ if (uncompressed) {
+ rw_lock_x_unlock_gen(
+ &((buf_block_t*) bpage)->lock,
+ BUF_IO_READ);
+ }
+
+ /* Find the table with specified space id, and mark it corrupted */
+ if (dict_set_corrupted_by_space(space)) {
+ buf_LRU_free_one_page(bpage);
+ } else {
+ ret = FALSE;
+ }
+
+ buf_pool_mutex_enter(buf_pool);
+ ut_ad(buf_pool->n_pend_reads > 0);
+ buf_pool->n_pend_reads--;
+ buf_pool_mutex_exit(buf_pool);
+
+ mutex_exit(buf_page_get_mutex(bpage));
+ //buf_pool_mutex_exit(buf_pool);
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
+
+ return(ret);
+}
+
+/********************************************************************//**
Completes an asynchronous read or write request of a file page to or from
the buffer pool. */
UNIV_INTERN
@@ -4452,10 +4104,19 @@ corrupt:
bpage->is_corrupt = TRUE;
} else
if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
- fputs("InnoDB: Ending processing because of"
- " a corrupt database page.\n",
- stderr);
- exit(1);
+ /* If page space id is larger than TRX_SYS_SPACE
+ (0), we will attempt to mark the corresponding
+ table as corrupted instead of crashing server */
+ if (bpage->space > TRX_SYS_SPACE
+ && buf_mark_space_corrupt(bpage)) {
+ return;
+ } else {
+ fputs("InnoDB: Ending processing"
+ " because of"
+ " a corrupt database page.\n",
+ stderr);
+ ut_error;
+ }
}
}
} /**/
@@ -4478,8 +4139,11 @@ corrupt:
}
if (io_type == BUF_IO_WRITE
- && (buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY
- || buf_page_get_flush_type(bpage) == BUF_FLUSH_LRU)) {
+ && (
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
+ buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY ||
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
+ buf_page_get_flush_type(bpage) == BUF_FLUSH_LRU)) {
/* to keep consistency at buf_LRU_insert_zip_clean() */
have_LRU_mutex = TRUE; /* optimistic */
}
@@ -5314,6 +4978,7 @@ buf_stats_aggregate_pool_info(
total_info->n_pages_created += pool_info->n_pages_created;
total_info->n_pages_written += pool_info->n_pages_written;
total_info->n_page_gets += pool_info->n_page_gets;
+ total_info->n_ra_pages_read_rnd += pool_info->n_ra_pages_read_rnd;
total_info->n_ra_pages_read += pool_info->n_ra_pages_read;
total_info->n_ra_pages_evicted += pool_info->n_ra_pages_evicted;
total_info->page_made_young_rate += pool_info->page_made_young_rate;
@@ -5326,6 +4991,7 @@ buf_stats_aggregate_pool_info(
total_info->page_read_delta += pool_info->page_read_delta;
total_info->young_making_delta += pool_info->young_making_delta;
total_info->not_young_making_delta += pool_info->not_young_making_delta;
+ total_info->pages_readahead_rnd_rate += pool_info->pages_readahead_rnd_rate;
total_info->pages_readahead_rate += pool_info->pages_readahead_rate;
total_info->pages_evicted_rate += pool_info->pages_evicted_rate;
total_info->unzip_lru_len += pool_info->unzip_lru_len;
@@ -5407,6 +5073,7 @@ buf_stats_get_pool_info(
pool_info->n_page_gets = buf_pool->stat.n_page_gets;
+ pool_info->n_ra_pages_read_rnd = buf_pool->stat.n_ra_pages_read_rnd;
pool_info->n_ra_pages_read = buf_pool->stat.n_ra_pages_read;
pool_info->n_ra_pages_evicted = buf_pool->stat.n_ra_pages_evicted;
@@ -5446,6 +5113,10 @@ buf_stats_get_pool_info(
buf_pool->stat.n_pages_not_made_young
- buf_pool->old_stat.n_pages_not_made_young;
}
+ pool_info->pages_readahead_rnd_rate =
+ (buf_pool->stat.n_ra_pages_read_rnd
+ - buf_pool->old_stat.n_ra_pages_read_rnd) / time_elapsed;
+
pool_info->pages_readahead_rate =
(buf_pool->stat.n_ra_pages_read
@@ -5535,9 +5206,12 @@ buf_print_io_instance(
/* Statistics about read ahead algorithm */
fprintf(file, "Pages read ahead %.2f/s,"
- " evicted without access %.2f/s\n",
+ " evicted without access %.2f/s,"
+ " Random read ahead %.2f/s\n",
+
pool_info->pages_readahead_rate,
- pool_info->pages_evicted_rate);
+ pool_info->pages_evicted_rate,
+ pool_info->pages_readahead_rnd_rate);
/* Print some values to help us with visualizing what is
happening with LRU eviction. */
diff --git a/storage/xtradb/buf/buf0flu.c b/storage/xtradb/buf/buf0flu.c
index 09d11dd21db..73a9ff96289 100644
--- a/storage/xtradb/buf/buf0flu.c
+++ b/storage/xtradb/buf/buf0flu.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -534,7 +534,9 @@ buf_flush_remove(
case BUF_BLOCK_ZIP_DIRTY:
buf_page_set_state(bpage, BUF_BLOCK_ZIP_PAGE);
UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage);
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
buf_LRU_insert_zip_clean(bpage);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
break;
case BUF_BLOCK_FILE_PAGE:
UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage);
diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c
index 49f3b09c817..a5a811f7afe 100644
--- a/storage/xtradb/buf/buf0lru.c
+++ b/storage/xtradb/buf/buf0lru.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -390,39 +390,41 @@ scan_again:
while (bpage != NULL) {
buf_page_t* prev_bpage;
- ibool prev_bpage_buf_fix = FALSE;
+ mutex_t* block_mutex = NULL;
ut_a(buf_page_in_file(bpage));
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
/* bpage->space and bpage->io_fix are protected by
- buf_pool->mutex and block_mutex. It is safe to check
- them while holding buf_pool->mutex only. */
+ buf_pool_mutex and block_mutex. It is safe to check
+ them while holding buf_pool_mutex only. */
if (buf_page_get_space(bpage) != id) {
/* Skip this block, as it does not belong to
the space that is being invalidated. */
+ goto next_page;
} else if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
/* We cannot remove this page during this scan
yet; maybe the system is currently reading it
in, or flushing the modifications to the file */
all_freed = FALSE;
+ goto next_page;
} else {
- mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
+ block_mutex = buf_page_get_mutex_enter(bpage);
if (!block_mutex) {
/* It may be impossible case...
Something wrong, so will be scan_again */
all_freed = FALSE;
-
- goto next_page_no_mutex;
+ goto next_page;
}
if (bpage->buf_fix_count > 0) {
+ mutex_exit(block_mutex);
/* We cannot remove this page during
this scan yet; maybe the system is
currently reading it in, or flushing
@@ -432,108 +434,61 @@ scan_again:
goto next_page;
}
+ }
+
+ ut_ad(mutex_own(block_mutex));
#ifdef UNIV_DEBUG
- if (buf_debug_prints) {
- fprintf(stderr,
- "Dropping space %lu page %lu\n",
- (ulong) buf_page_get_space(bpage),
- (ulong) buf_page_get_page_no(bpage));
- }
+ if (buf_debug_prints) {
+ fprintf(stderr,
+ "Dropping space %lu page %lu\n",
+ (ulong) buf_page_get_space(bpage),
+ (ulong) buf_page_get_page_no(bpage));
+ }
#endif
- if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
- /* This is a compressed-only block
- descriptor. Ensure that prev_bpage
- cannot be relocated when bpage is freed. */
- if (UNIV_LIKELY(prev_bpage != NULL)) {
- switch (buf_page_get_state(
- prev_bpage)) {
- case BUF_BLOCK_FILE_PAGE:
- /* Descriptors of uncompressed
- blocks will not be relocated,
- because we are holding the
- buf_pool->mutex. */
- break;
- case BUF_BLOCK_ZIP_PAGE:
- case BUF_BLOCK_ZIP_DIRTY:
- /* Descriptors of compressed-
- only blocks can be relocated,
- unless they are buffer-fixed.
- Because both bpage and
- prev_bpage are protected by
- buf_pool_zip_mutex, it is
- not necessary to acquire
- further mutexes. */
- ut_ad(&buf_pool->zip_mutex
- == block_mutex);
- ut_ad(mutex_own(block_mutex));
- prev_bpage_buf_fix = TRUE;
- prev_bpage->buf_fix_count++;
- break;
- default:
- ut_error;
- }
- }
- } else if (((buf_block_t*) bpage)->is_hashed) {
- ulint page_no;
- ulint zip_size;
-
- //buf_pool_mutex_exit(buf_pool);
- mutex_exit(&buf_pool->LRU_list_mutex);
- rw_lock_x_unlock(&buf_pool->page_hash_latch);
+ if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
+ /* This is a compressed-only block
+ descriptor. Do nothing. */
+ } else if (((buf_block_t*) bpage)->is_hashed) {
+ ulint page_no;
+ ulint zip_size;
- zip_size = buf_page_get_zip_size(bpage);
- page_no = buf_page_get_page_no(bpage);
+ //buf_pool_mutex_exit(buf_pool);
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
- mutex_exit(block_mutex);
+ zip_size = buf_page_get_zip_size(bpage);
+ page_no = buf_page_get_page_no(bpage);
- /* Note that the following call will acquire
- an S-latch on the page */
+ mutex_exit(block_mutex);
- btr_search_drop_page_hash_when_freed(
- id, zip_size, page_no);
- goto scan_again;
- }
+ /* Note that the following call will acquire
+ an S-latch on the page */
- if (bpage->oldest_modification != 0) {
+ btr_search_drop_page_hash_when_freed(
+ id, zip_size, page_no);
+ goto scan_again;
+ }
- buf_flush_remove(bpage);
- }
+ if (bpage->oldest_modification != 0) {
- /* Remove from the LRU list. */
+ buf_flush_remove(bpage);
+ }
- if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
- != BUF_BLOCK_ZIP_FREE) {
- buf_LRU_block_free_hashed_page((buf_block_t*)
- bpage, TRUE);
- } else {
- /* The block_mutex should have been
- released by buf_LRU_block_remove_hashed_page()
- when it returns BUF_BLOCK_ZIP_FREE. */
- ut_ad(block_mutex == &buf_pool->zip_mutex);
- ut_ad(!mutex_own(block_mutex));
-
- if (prev_bpage_buf_fix) {
- /* We temporarily buffer-fixed
- prev_bpage, so that
- buf_buddy_free() could not
- relocate it, in case it was a
- compressed-only block
- descriptor. */
-
- mutex_enter(block_mutex);
- ut_ad(prev_bpage->buf_fix_count > 0);
- prev_bpage->buf_fix_count--;
- mutex_exit(block_mutex);
- }
+ /* Remove from the LRU list. */
- goto next_page_no_mutex;
- }
-next_page:
+ if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
+ != BUF_BLOCK_ZIP_FREE) {
+ buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE);
mutex_exit(block_mutex);
+ } else {
+ /* The block_mutex should have been released
+ by buf_LRU_block_remove_hashed_page() when it
+ returns BUF_BLOCK_ZIP_FREE. */
+ ut_ad(block_mutex == &buf_pool->zip_mutex);
+ ut_ad(!mutex_own(block_mutex));
}
-
-next_page_no_mutex:
+next_page:
bpage = prev_bpage;
}
@@ -587,6 +542,8 @@ buf_LRU_mark_space_was_deleted(
for (i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_page_t* bpage;
+ buf_chunk_t* chunk;
+ ulint j, k;
buf_pool = buf_pool_from_array(i);
@@ -602,9 +559,33 @@ buf_LRU_mark_space_was_deleted(
}
mutex_exit(&buf_pool->LRU_list_mutex);
+
+ btr_search_s_lock_all();
+ chunk = buf_pool->chunks;
+ for (j = buf_pool->n_chunks; j--; chunk++) {
+ buf_block_t* block = chunk->blocks;
+ for (k = chunk->size; k--; block++) {
+ if (buf_block_get_state(block)
+ != BUF_BLOCK_FILE_PAGE
+ || !block->is_hashed
+ || buf_page_get_space(&block->page) != id) {
+ continue;
+ }
+
+ btr_search_s_unlock_all();
+
+ rw_lock_x_lock(&block->lock);
+ btr_search_drop_page_hash_index(block, NULL);
+ rw_lock_x_unlock(&block->lock);
+
+ btr_search_s_lock_all();
+ }
+ }
+ btr_search_s_unlock_all();
}
}
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/********************************************************************//**
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
UNIV_INTERN
@@ -639,6 +620,7 @@ buf_LRU_insert_zip_clean(
UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_clean, bpage);
}
}
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
/******************************************************************//**
Try to free an uncompressed page of a compressed block from the unzip
@@ -684,7 +666,7 @@ restart:
UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0);
block = UT_LIST_GET_PREV(unzip_LRU, block), distance--) {
- enum buf_lru_free_block_status freed;
+ ibool freed;
mutex_enter(&block->mutex);
if (!block->in_unzip_LRU_list || !block->page.in_LRU_list
@@ -700,24 +682,9 @@ restart:
freed = buf_LRU_free_block(&block->page, FALSE, have_LRU_mutex);
mutex_exit(&block->mutex);
- switch (freed) {
- case BUF_LRU_FREED:
+ if (freed) {
return(TRUE);
-
- case BUF_LRU_CANNOT_RELOCATE:
- /* If we failed to relocate, try
- regular LRU eviction. */
- return(FALSE);
-
- case BUF_LRU_NOT_FREED:
- /* The block was buffer-fixed or I/O-fixed.
- Keep looking. */
- continue;
}
-
- /* inappropriate return value from
- buf_LRU_free_block() */
- ut_error;
}
return(FALSE);
@@ -752,10 +719,9 @@ restart:
UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0);
bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) {
- enum buf_lru_free_block_status freed;
- unsigned accessed;
- mutex_t* block_mutex
- = buf_page_get_mutex_enter(bpage);
+ ibool freed;
+ unsigned accessed;
+ mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
if (!block_mutex) {
goto restart;
@@ -774,8 +740,7 @@ restart:
freed = buf_LRU_free_block(bpage, TRUE, have_LRU_mutex);
mutex_exit(block_mutex);
- switch (freed) {
- case BUF_LRU_FREED:
+ if (freed) {
/* Keep track of pages that are evicted without
ever being accessed. This gives us a measure of
the effectiveness of readahead */
@@ -783,21 +748,7 @@ restart:
++buf_pool->stat.n_ra_pages_evicted;
}
return(TRUE);
-
- case BUF_LRU_NOT_FREED:
- /* The block was dirty, buffer-fixed, or I/O-fixed.
- Keep looking. */
- continue;
-
- case BUF_LRU_CANNOT_RELOCATE:
- /* This should never occur, because we
- want to discard the compressed page too. */
- break;
}
-
- /* inappropriate return value from
- buf_LRU_free_block() */
- ut_error;
}
return(FALSE);
@@ -1549,17 +1500,16 @@ buf_LRU_make_block_old(
Try to free a block. If bpage is a descriptor of a compressed-only
page, the descriptor object will be freed as well.
-NOTE: If this function returns BUF_LRU_FREED, it will temporarily
+NOTE: If this function returns TRUE, it will temporarily
release buf_pool->mutex. Furthermore, the page frame will no longer be
accessible via bpage.
The caller must hold buf_pool->mutex and buf_page_get_mutex(bpage) and
release these two mutexes after the call. No other
buf_page_get_mutex() may be held when calling this function.
-@return BUF_LRU_FREED if freed, BUF_LRU_CANNOT_RELOCATE or
-BUF_LRU_NOT_FREED otherwise. */
+@return TRUE if freed, FALSE otherwise. */
UNIV_INTERN
-enum buf_lru_free_block_status
+ibool
buf_LRU_free_block(
/*===============*/
buf_page_t* bpage, /*!< in: block to be freed */
@@ -1586,7 +1536,7 @@ buf_LRU_free_block(
if (!bpage->in_LRU_list || !block_mutex || !buf_page_can_relocate(bpage)) {
/* Do not free buffer-fixed or I/O-fixed blocks. */
- return(BUF_LRU_NOT_FREED);
+ return(FALSE);
}
if (bpage->space_was_being_deleted && bpage->oldest_modification != 0) {
@@ -1602,7 +1552,7 @@ buf_LRU_free_block(
/* Do not completely free dirty blocks. */
if (bpage->oldest_modification) {
- return(BUF_LRU_NOT_FREED);
+ return(FALSE);
}
} else if (bpage->oldest_modification) {
/* Do not completely free dirty blocks. */
@@ -1610,7 +1560,7 @@ buf_LRU_free_block(
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
ut_ad(buf_page_get_state(bpage)
== BUF_BLOCK_ZIP_DIRTY);
- return(BUF_LRU_NOT_FREED);
+ return(FALSE);
}
goto alloc;
@@ -1619,14 +1569,8 @@ buf_LRU_free_block(
If it cannot be allocated (without freeing a block
from the LRU list), refuse to free bpage. */
alloc:
- //buf_pool_mutex_exit_forbid(buf_pool);
- b = buf_buddy_alloc(buf_pool, sizeof *b, NULL, FALSE);
- //buf_pool_mutex_exit_allow(buf_pool);
-
- if (UNIV_UNLIKELY(!b)) {
- return(BUF_LRU_CANNOT_RELOCATE);
- }
-
+ b = buf_page_alloc_descriptor();
+ ut_a(b);
//memcpy(b, bpage, sizeof *b);
}
@@ -1656,7 +1600,7 @@ not_freed:
if (!have_LRU_mutex)
mutex_exit(&buf_pool->LRU_list_mutex);
rw_lock_x_unlock(&buf_pool->page_hash_latch);
- return(BUF_LRU_NOT_FREED);
+ return(FALSE);
} else if (zip || !bpage->zip.data) {
if (bpage->oldest_modification)
goto not_freed;
@@ -1768,7 +1712,9 @@ not_freed:
mutex_enter(&buf_pool->zip_mutex);
if (b->state == BUF_BLOCK_ZIP_PAGE) {
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
buf_LRU_insert_zip_clean(b);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
} else {
/* Relocate on buf_pool->flush_list. */
buf_flush_relocate_on_flush_list(bpage, b);
@@ -1844,7 +1790,7 @@ not_freed:
rw_lock_x_unlock(&buf_pool->page_hash_latch);
}
- return(BUF_LRU_FREED);
+ return(TRUE);
}
/******************************************************************//**
@@ -2073,7 +2019,9 @@ buf_LRU_block_remove_hashed_page(
ut_a(bpage->zip.data);
ut_a(buf_page_get_zip_size(bpage));
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
UT_LIST_REMOVE(zip_list, buf_pool->zip_clean, bpage);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
mutex_exit(&buf_pool->zip_mutex);
//buf_pool_mutex_exit_forbid(buf_pool);
@@ -2082,11 +2030,8 @@ buf_LRU_block_remove_hashed_page(
buf_pool, bpage->zip.data,
page_zip_get_size(&bpage->zip), TRUE);
- bpage->state = BUF_BLOCK_ZIP_FREE;
- buf_buddy_free(buf_pool, bpage, sizeof(*bpage), TRUE);
//buf_pool_mutex_exit_allow(buf_pool);
-
- UNIV_MEM_UNDESC(bpage);
+ buf_page_free_descriptor(bpage);
return(BUF_BLOCK_ZIP_FREE);
case BUF_BLOCK_FILE_PAGE:
@@ -2154,6 +2099,22 @@ buf_LRU_block_free_hashed_page(
buf_LRU_block_free_non_file_page(block, have_page_hash_mutex);
}
+/******************************************************************//**
+Remove one page from LRU list and put it to free list */
+UNIV_INTERN
+void
+buf_LRU_free_one_page(
+/*==================*/
+ buf_page_t* bpage) /*!< in/out: block, must contain a file page and
+ be in a state where it can be freed; there
+ may or may not be a hash index to the page */
+{
+ if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
+ != BUF_BLOCK_ZIP_FREE) {
+ buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE);
+ }
+}
+
/**********************************************************************//**
Updates buf_pool->LRU_old_ratio for one buffer pool instance.
@return updated old_pct */
@@ -2445,6 +2406,11 @@ buf_LRU_file_restore(void)
" InnoDB: cannot open %s\n", LRU_DUMP_FILE);
goto end;
}
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Restoring buffer pool pages from %s\n",
+ LRU_DUMP_FILE);
+
if (size == 0 || size_high > 0 || size % 8) {
fprintf(stderr, " InnoDB: broken LRU dump file\n");
goto end;
@@ -2546,7 +2512,7 @@ buf_LRU_file_restore(void)
ut_print_timestamp(stderr);
fprintf(stderr,
- " InnoDB: reading pages based on the dumped LRU list was done."
+ " InnoDB: Completed reading buffer pool pages"
" (requested: %lu, read: %lu)\n", req, reads);
ret = TRUE;
end:
diff --git a/storage/xtradb/buf/buf0rea.c b/storage/xtradb/buf/buf0rea.c
index 587b982b3e0..645d5fdc2f3 100644
--- a/storage/xtradb/buf/buf0rea.c
+++ b/storage/xtradb/buf/buf0rea.c
@@ -40,8 +40,10 @@ Created 11/5/1995 Heikki Tuuri
#include "mysql/plugin.h"
#include "mysql/service_thd_wait.h"
-/** The linear read-ahead area size */
-#define BUF_READ_AHEAD_LINEAR_AREA BUF_READ_AHEAD_AREA
+/** There must be at least this many pages in buf_pool in the area to start
+a random read-ahead */
+#define BUF_READ_AHEAD_RANDOM_THRESHOLD(b) \
+ (5 + BUF_READ_AHEAD_AREA(b) / 8)
/** If there are buf_pool->curr_size per the number below pending reads, then
read-ahead is not done: this is to prevent flooding the buffer pool with
@@ -212,6 +214,172 @@ not_to_recover:
}
/********************************************************************//**
+Applies a random read-ahead in buf_pool if there are at least a threshold
+value of accessed pages from the random read-ahead area. Does not read any
+page, not even the one at the position (space, offset), if the read-ahead
+mechanism is not activated. NOTE 1: the calling thread may own latches on
+pages: to avoid deadlocks this function must be written such that it cannot
+end up waiting for these latches! NOTE 2: the calling thread must want
+access to the page given: this rule is set to prevent unintended read-aheads
+performed by ibuf routines, a situation which could result in a deadlock if
+the OS does not support asynchronous i/o.
+@return number of page read requests issued; NOTE that if we read ibuf
+pages, it may happen that the page at the given page number does not
+get read even if we return a positive value!
+@return number of page read requests issued */
+UNIV_INTERN
+ulint
+buf_read_ahead_random(
+/*==================*/
+ ulint space, /*!< in: space id */
+ ulint zip_size, /*!< in: compressed page size in bytes,
+ or 0 */
+ ulint offset, /*!< in: page number of a page which
+ the current thread wants to access */
+ ibool inside_ibuf, /*!< in: TRUE if we are inside ibuf
+ routine */
+ trx_t* trx)
+{
+ buf_pool_t* buf_pool = buf_pool_get(space, offset);
+ ib_int64_t tablespace_version;
+ ulint recent_blocks = 0;
+ ulint ibuf_mode;
+ ulint count;
+ ulint low, high;
+ ulint err;
+ ulint i;
+ const ulint buf_read_ahead_random_area
+ = BUF_READ_AHEAD_AREA(buf_pool);
+
+ if (!srv_random_read_ahead) {
+ /* Disabled by user */
+ return(0);
+ }
+
+ if (srv_startup_is_before_trx_rollback_phase) {
+ /* No read-ahead to avoid thread deadlocks */
+ return(0);
+ }
+
+ if (ibuf_bitmap_page(zip_size, offset)
+ || trx_sys_hdr_page(space, offset)) {
+
+ /* If it is an ibuf bitmap page or trx sys hdr, we do
+ no read-ahead, as that could break the ibuf page access
+ order */
+
+ return(0);
+ }
+
+ /* Remember the tablespace version before we ask te tablespace size
+ below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
+ do not try to read outside the bounds of the tablespace! */
+
+ tablespace_version = fil_space_get_version(space);
+
+ low = (offset / buf_read_ahead_random_area)
+ * buf_read_ahead_random_area;
+ high = (offset / buf_read_ahead_random_area + 1)
+ * buf_read_ahead_random_area;
+ if (high > fil_space_get_size(space)) {
+
+ high = fil_space_get_size(space);
+ }
+
+ buf_pool_mutex_enter(buf_pool);
+
+ if (buf_pool->n_pend_reads
+ > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
+ buf_pool_mutex_exit(buf_pool);
+
+ return(0);
+ }
+
+ /* Count how many blocks in the area have been recently accessed,
+ that is, reside near the start of the LRU list. */
+
+ for (i = low; i < high; i++) {
+ const buf_page_t* bpage =
+ buf_page_hash_get(buf_pool, space, i);
+
+ if (bpage
+ && buf_page_is_accessed(bpage)
+ && buf_page_peek_if_young(bpage)) {
+
+ recent_blocks++;
+
+ if (recent_blocks
+ >= BUF_READ_AHEAD_RANDOM_THRESHOLD(buf_pool)) {
+
+ buf_pool_mutex_exit(buf_pool);
+ goto read_ahead;
+ }
+ }
+ }
+
+ buf_pool_mutex_exit(buf_pool);
+ /* Do nothing */
+ return(0);
+
+read_ahead:
+ /* Read all the suitable blocks within the area */
+
+ if (inside_ibuf) {
+ ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
+ } else {
+ ibuf_mode = BUF_READ_ANY_PAGE;
+ }
+
+ count = 0;
+
+ for (i = low; i < high; i++) {
+ /* It is only sensible to do read-ahead in the non-sync aio
+ mode: hence FALSE as the first parameter */
+
+ if (!ibuf_bitmap_page(zip_size, i)) {
+ count += buf_read_page_low(
+ &err, FALSE,
+ ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
+ space, zip_size, FALSE,
+ tablespace_version, i, trx);
+ if (err == DB_TABLESPACE_DELETED) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Warning: in random"
+ " readahead trying to access\n"
+ "InnoDB: tablespace %lu page %lu,\n"
+ "InnoDB: but the tablespace does not"
+ " exist or is just being dropped.\n",
+ (ulong) space, (ulong) i);
+ }
+ }
+ }
+
+ /* In simulated aio we wake the aio handler threads only after
+ queuing all aio requests, in native aio the following call does
+ nothing: */
+
+ os_aio_simulated_wake_handler_threads();
+
+#ifdef UNIV_DEBUG
+ if (buf_debug_prints && (count > 0)) {
+ fprintf(stderr,
+ "Random read-ahead space %lu offset %lu pages %lu\n",
+ (ulong) space, (ulong) offset,
+ (ulong) count);
+ }
+#endif /* UNIV_DEBUG */
+
+ /* Read ahead is considered one I/O operation for the purpose of
+ LRU policy decision. */
+ buf_LRU_stat_inc_io();
+
+ buf_pool->stat.n_ra_pages_read_rnd += count;
+ srv_buf_pool_reads += count;
+ return(count);
+}
+
+/********************************************************************//**
High-level function which reads a page asynchronously from a file to the
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
@@ -309,7 +477,7 @@ buf_read_ahead_linear(
ulint err;
ulint i;
const ulint buf_read_ahead_linear_area
- = BUF_READ_AHEAD_LINEAR_AREA(buf_pool);
+ = BUF_READ_AHEAD_AREA(buf_pool);
ulint threshold;
if (!(srv_read_ahead & 2)) {
diff --git a/storage/xtradb/dict/dict0crea.c b/storage/xtradb/dict/dict0crea.c
index 1d1a8714de0..90e5e7eb7f6 100644
--- a/storage/xtradb/dict/dict0crea.c
+++ b/storage/xtradb/dict/dict0crea.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -898,7 +898,7 @@ dict_truncate_index_tree(
appropriate field in the SYS_INDEXES record: this mini-transaction
marks the B-tree totally truncated */
- btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, NULL, mtr);
btr_free_root(space, zip_size, root_page_no, mtr);
create:
diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c
index e1b29fa02b0..93334747c8e 100644
--- a/storage/xtradb/dict/dict0dict.c
+++ b/storage/xtradb/dict/dict0dict.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -54,6 +54,7 @@ UNIV_INTERN dict_index_t* dict_ind_compact;
#include "row0merge.h"
#include "m_ctype.h" /* my_isspace() */
#include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/
+#include "row0upd.h"
#include "srv0start.h" /* SRV_LOG_SPACE_FIRST_ID */
#include <ctype.h>
@@ -615,8 +616,7 @@ dict_table_get_on_id(
{
dict_table_t* table;
- if (table_id <= DICT_FIELDS_ID
- || trx->dict_operation_lock_mode == RW_X_LATCH) {
+ if (trx->dict_operation_lock_mode == RW_X_LATCH) {
/* Note: An X latch implies that the transaction
already owns the dictionary mutex. */
@@ -1780,7 +1780,8 @@ undo_size_ok:
new_index->page = page_no;
rw_lock_create(index_tree_rw_lock_key, &new_index->lock,
- SYNC_INDEX_TREE);
+ dict_index_is_ibuf(index)
+ ? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE);
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
@@ -5525,6 +5526,189 @@ dict_close(void)
}
}
+/**********************************************************************//**
+Find a table in dict_sys->table_LRU list with specified space id
+@return table if found, NULL if not */
+static
+dict_table_t*
+dict_find_table_by_space(
+/*=====================*/
+ ulint space_id) /*!< in: space ID */
+{
+ dict_table_t* table;
+ ulint num_item;
+ ulint count = 0;
+
+ ut_ad(space_id > 0);
+
+ table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
+ num_item = UT_LIST_GET_LEN(dict_sys->table_LRU);
+
+ /* This function intentionally does not acquire mutex as it is used
+ by error handling code in deep call stack as last means to avoid
+ killing the server, so it worth to risk some consequencies for
+ the action. */
+ while (table && count < num_item) {
+ if (table->space == space_id) {
+ return(table);
+ }
+
+ table = UT_LIST_GET_NEXT(table_LRU, table);
+ count++;
+ }
+
+ return(NULL);
+}
+
+/**********************************************************************//**
+Flags a table with specified space_id corrupted in the data dictionary
+cache
+@return TRUE if successful */
+UNIV_INTERN
+ibool
+dict_set_corrupted_by_space(
+/*========================*/
+ ulint space_id) /*!< in: space ID */
+{
+ dict_table_t* table;
+
+ table = dict_find_table_by_space(space_id);
+
+ if (!table) {
+ return(FALSE);
+ }
+
+ /* mark the table->corrupted bit only, since the caller
+ could be too deep in the stack for SYS_INDEXES update */
+ table->corrupted = TRUE;
+
+ return(TRUE);
+}
+
+/**********************************************************************//**
+Flags an index corrupted both in the data dictionary cache
+and in the SYS_INDEXES */
+UNIV_INTERN
+void
+dict_set_corrupted(
+/*===============*/
+ dict_index_t* index) /*!< in/out: index */
+{
+ mem_heap_t* heap;
+ mtr_t mtr;
+ dict_index_t* sys_index;
+ dtuple_t* tuple;
+ dfield_t* dfield;
+ byte* buf;
+ const char* status;
+ btr_cur_t cursor;
+
+ ut_ad(index);
+ ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(!dict_table_is_comp(dict_sys->sys_tables));
+ ut_ad(!dict_table_is_comp(dict_sys->sys_indexes));
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(sync_thread_levels_empty_except_dict());
+#endif
+
+ /* Mark the table as corrupted only if the clustered index
+ is corrupted */
+ if (dict_index_is_clust(index)) {
+ index->table->corrupted = TRUE;
+ }
+
+ if (UNIV_UNLIKELY(dict_index_is_corrupted(index))) {
+ /* The index was already flagged corrupted. */
+ ut_ad(index->table->corrupted);
+ return;
+ }
+
+ heap = mem_heap_create(sizeof(dtuple_t) + 2 * (sizeof(dfield_t)
+ + sizeof(que_fork_t) + sizeof(upd_node_t)
+ + sizeof(upd_t) + 12));
+ mtr_start(&mtr);
+ index->type |= DICT_CORRUPT;
+
+ sys_index = UT_LIST_GET_FIRST(dict_sys->sys_indexes->indexes);
+
+ /* Find the index row in SYS_INDEXES */
+ tuple = dtuple_create(heap, 2);
+
+ dfield = dtuple_get_nth_field(tuple, 0);
+ buf = mem_heap_alloc(heap, 8);
+ mach_write_to_8(buf, index->table->id);
+ dfield_set_data(dfield, buf, 8);
+
+ dfield = dtuple_get_nth_field(tuple, 1);
+ buf = mem_heap_alloc(heap, 8);
+ mach_write_to_8(buf, index->id);
+ dfield_set_data(dfield, buf, 8);
+
+ dict_index_copy_types(tuple, sys_index, 2);
+
+ btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE,
+ BTR_MODIFY_LEAF,
+ &cursor, 0, __FILE__, __LINE__, &mtr);
+
+ if (cursor.up_match == dtuple_get_n_fields(tuple)) {
+ /* UPDATE SYS_INDEXES SET TYPE=index->type
+ WHERE TABLE_ID=index->table->id AND INDEX_ID=index->id */
+ ulint len;
+ byte* field = rec_get_nth_field_old(
+ btr_cur_get_rec(&cursor),
+ DICT_SYS_INDEXES_TYPE_FIELD, &len);
+ if (len != 4) {
+ goto fail;
+ }
+ mlog_write_ulint(field, index->type, MLOG_4BYTES, &mtr);
+ status = " InnoDB: Flagged corruption of ";
+ } else {
+fail:
+ status = " InnoDB: Unable to flag corruption of ";
+ }
+
+ mtr_commit(&mtr);
+ mem_heap_free(heap);
+
+ ut_print_timestamp(stderr);
+ fputs(status, stderr);
+ dict_index_name_print(stderr, NULL, index);
+ putc('\n', stderr);
+}
+
+/**********************************************************************//**
+Flags an index corrupted in the data dictionary cache only. This
+is used mostly to mark a corrupted index when index's own dictionary
+is corrupted, and we force to load such index for repair purpose */
+UNIV_INTERN
+void
+dict_set_corrupted_index_cache_only(
+/*================================*/
+ dict_index_t* index, /*!< in/out: index */
+ dict_table_t* table) /*!< in/out: table */
+{
+ ut_ad(index);
+ ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(!dict_table_is_comp(dict_sys->sys_tables));
+ ut_ad(!dict_table_is_comp(dict_sys->sys_indexes));
+
+ /* Mark the table as corrupted only if the clustered index
+ is corrupted */
+ if (dict_index_is_clust(index)) {
+ dict_table_t* corrupt_table;
+
+ corrupt_table = table ? table : index->table;
+ ut_ad(!index->table || !table || index->table == table);
+
+ if (corrupt_table) {
+ corrupt_table->corrupted = TRUE;
+ }
+ }
+
+ index->type |= DICT_CORRUPT;
+}
+
/*************************************************************************
set is_corrupt flag by space_id*/
diff --git a/storage/xtradb/dict/dict0load.c b/storage/xtradb/dict/dict0load.c
index 0ec810430a4..47f969727fb 100644
--- a/storage/xtradb/dict/dict0load.c
+++ b/storage/xtradb/dict/dict0load.c
@@ -54,6 +54,10 @@ static const char* SYSTEM_TABLE_NAME[] = {
"SYS_STATS"
};
+/* If this flag is TRUE, then we will load the cluster index's (and tables')
+metadata even if it is marked as "corrupted". */
+UNIV_INTERN my_bool srv_load_corrupted = FALSE;
+
/****************************************************************//**
Compare the name of an index column.
@return TRUE if the i'th column of index is 'name'. */
@@ -1396,6 +1400,9 @@ err_len:
goto err_len;
}
type = mach_read_from_4(field);
+ if (UNIV_UNLIKELY(type & (~0 << DICT_IT_BITS))) {
+ return("unknown SYS_INDEXES.TYPE bits");
+ }
field = rec_get_nth_field_old(rec, 7/*SPACE*/, &len);
if (UNIV_UNLIKELY(len != 4)) {
@@ -1495,16 +1502,47 @@ dict_load_indexes(
goto next_rec;
} else if (err_msg) {
fprintf(stderr, "InnoDB: %s\n", err_msg);
+ if (ignore_err & DICT_ERR_IGNORE_CORRUPT) {
+ goto next_rec;
+ }
error = DB_CORRUPTION;
goto func_exit;
}
ut_ad(index);
+ /* Check whether the index is corrupted */
+ if (dict_index_is_corrupted(index)) {
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: ", stderr);
+ dict_index_name_print(stderr, NULL, index);
+ fputs(" is corrupted\n", stderr);
+
+ if (!srv_load_corrupted
+ && !(ignore_err & DICT_ERR_IGNORE_CORRUPT)
+ && dict_index_is_clust(index)) {
+ dict_mem_index_free(index);
+
+ error = DB_INDEX_CORRUPT;
+ goto func_exit;
+ } else {
+ /* We will load the index if
+ 1) srv_load_corrupted is TRUE
+ 2) ignore_err is set with
+ DICT_ERR_IGNORE_CORRUPT
+ 3) if the index corrupted is a secondary
+ index */
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: load corrupted index ", stderr);
+ dict_index_name_print(stderr, NULL, index);
+ putc('\n', stderr);
+ }
+ }
+
/* We check for unsupported types first, so that the
subsequent checks are relevant for the supported types. */
- if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
-
+ if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE
+ | DICT_CORRUPT)) {
fprintf(stderr,
"InnoDB: Error: unknown type %lu"
" of index %s of table %s\n",
@@ -1525,9 +1563,14 @@ dict_load_indexes(
/* If caller can tolerate this error,
we will continue to load the index and
let caller deal with this error. However
- mark the index and table corrupted */
- index->corrupted = TRUE;
- table->corrupted = TRUE;
+ mark the index and table corrupted. We
+ only need to mark such in the index
+ dictionary cache for such metadata corruption,
+ since we would always be able to set it
+ when loading the dictionary cache */
+ dict_set_corrupted_index_cache_only(
+ index, table);
+
fprintf(stderr,
"InnoDB: Index is corrupt but forcing"
" load into data dictionary\n");
@@ -1567,9 +1610,10 @@ corrupted:
index->name, table->name);
/* If the force recovery flag is set, and
- if the failed index is not the primary index, we
- will continue and open other indexes */
- if (srv_force_recovery
+ if the failed index is not the clustered index,
+ we will continue and open other indexes */
+ if ((srv_force_recovery
+ || srv_load_corrupted)
&& !dict_index_is_clust(index)) {
error = DB_SUCCESS;
goto next_rec;
@@ -1884,6 +1928,30 @@ err_exit:
err = dict_load_indexes(table, heap, ignore_err);
+ if (err == DB_INDEX_CORRUPT) {
+ /* Refuse to load the table if the table has a corrupted
+ cluster index */
+ if (!srv_load_corrupted) {
+ fprintf(stderr, "InnoDB: Error: Load table ");
+ ut_print_name(stderr, NULL, TRUE, table->name);
+ fprintf(stderr, " failed, the table has corrupted"
+ " clustered indexes. Turn on"
+ " 'innodb_force_load_corrupted'"
+ " to drop it\n");
+
+ dict_table_remove_from_cache(table);
+ table = NULL;
+ goto func_exit;
+ } else {
+ dict_index_t* clust_index;
+ clust_index = dict_table_get_first_index(table);
+
+ if (dict_index_is_corrupted(clust_index)) {
+ table->corrupted = TRUE;
+ }
+ }
+ }
+
/* Initialize table foreign_child value. Its value could be
changed when dict_load_foreigns() is called below */
table->fk_max_recusive_level = 0;
@@ -1910,9 +1978,15 @@ err_exit:
index = dict_table_get_first_index(table);
if (!srv_force_recovery || !index
- || !dict_index_is_clust(index)) {
+ || !dict_index_is_clust(index)) {
dict_table_remove_from_cache(table);
table = NULL;
+ } else if (dict_index_is_corrupted(index)) {
+
+ /* It is possible we force to load a corrupted
+ clustered index if srv_load_corrupted is set.
+ Mark the table as corrupted in this case */
+ table->corrupted = TRUE;
}
}
#if 0
@@ -1939,6 +2013,7 @@ err_exit:
mutex_exit(&dict_foreign_err_mutex);
}
#endif /* 0 */
+func_exit:
mem_heap_free(heap);
return(table);
diff --git a/storage/xtradb/fil/fil0fil.c b/storage/xtradb/fil/fil0fil.c
index e244985d096..c3d85a77f3c 100644
--- a/storage/xtradb/fil/fil0fil.c
+++ b/storage/xtradb/fil/fil0fil.c
@@ -3541,7 +3541,7 @@ skip_info:
ULINT_UNDEFINED, &heap);
n_fields = rec_offs_n_fields(offsets);
if (!offset) {
- offset = row_get_trx_id_offset(rec, index, offsets);
+ offset = row_get_trx_id_offset(index, offsets);
}
trx_write_trx_id(rec + offset, 1);
@@ -3826,7 +3826,7 @@ convert_err_exit:
ULINT_UNDEFINED, &heap);
n_fields = rec_offs_n_fields(offsets);
if (!offset) {
- offset = row_get_trx_id_offset(rec, index, offsets);
+ offset = row_get_trx_id_offset(index, offsets);
}
trx_write_trx_id(rec + offset, 1);
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index f70dc7a0f8a..b89fb4f9c7e 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2011, MySQL AB & Innobase Oy. All Rights Reserved.
+Copyright (c) 2000, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
@@ -192,16 +192,18 @@ static my_bool innobase_overwrite_relay_log_info = FALSE;
static my_bool innobase_rollback_on_timeout = FALSE;
static my_bool innobase_create_status_file = FALSE;
static my_bool innobase_stats_on_metadata = TRUE;
+static my_bool innobase_large_prefix = FALSE;
static my_bool innobase_use_sys_stats_table = FALSE;
static my_bool innobase_buffer_pool_shm_checksum = TRUE;
static uint innobase_buffer_pool_shm_key = 0;
-static my_bool innobase_large_prefix = FALSE;
static char* internal_innobase_data_file_path = NULL;
static char* innodb_version_str = (char*) INNODB_VERSION_STR;
+static my_bool innobase_blocking_lru_restore = FALSE;
+
/** Possible values for system variable "innodb_stats_method". The values
are defined the same as its corresponding MyISAM system variable
"myisam_stats_method"(see "myisam_stats_method_names"), for better usability */
@@ -483,6 +485,12 @@ static MYSQL_THDVAR_ULONG(flush_log_at_trx_commit, PLUGIN_VAR_OPCMDARG,
" or 2 (write at commit, flush once per second).",
NULL, NULL, 1, 0, 2, 0);
+static MYSQL_THDVAR_BOOL(fake_changes, PLUGIN_VAR_OPCMDARG,
+ "In the transaction after enabled, UPDATE, INSERT and DELETE only move the cursor to the records "
+ "and do nothing other operations (no changes, no ibuf, no undo, no transaction log) in the transaction. "
+ "This is to cause replication prefetch IO. ATTENTION: the transaction started after enabled is affected.",
+ NULL, NULL, FALSE);
+
static handler *innobase_create_handler(handlerton *hton,
TABLE_SHARE *table,
@@ -681,6 +689,8 @@ static SHOW_VAR innodb_status_variables[]= {
(char*) &export_vars.innodb_buffer_pool_pages_old, SHOW_LONG},
{"buffer_pool_pages_total",
(char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG},
+ {"buffer_pool_read_ahead_rnd",
+ (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
{"buffer_pool_read_ahead",
(char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG},
{"buffer_pool_read_ahead_evicted",
@@ -1153,7 +1163,6 @@ convert_error_code_to_mysql(
misleading, a new MySQL error
code should be introduced */
- case DB_COL_APPEARS_TWICE_IN_INDEX:
case DB_CORRUPTION:
return(HA_ERR_CRASHED);
@@ -1205,6 +1214,10 @@ convert_error_code_to_mysql(
#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
case DB_UNSUPPORTED:
return(HA_ERR_UNSUPPORTED);
+ case DB_INDEX_CORRUPT:
+ return(HA_ERR_INDEX_CORRUPT);
+ case DB_UNDO_RECORD_TOO_BIG:
+ return(HA_ERR_UNDO_REC_TOO_BIG);
}
}
@@ -1692,6 +1705,8 @@ innobase_trx_init(
trx->check_unique_secondary = !thd_test_options(
thd, OPTION_RELAXED_UNIQUE_CHECKS);
+ trx->fake_changes = THDVAR(thd, fake_changes);
+
#ifdef EXTENDED_SLOWLOG
if (thd_log_slow_verbosity(thd) & SLOG_V_INNODB) {
trx->take_stats = TRUE;
@@ -2272,6 +2287,29 @@ no_db_name:
}
+/*****************************************************************//**
+A wrapper function of innobase_convert_name(), convert a table or
+index name to the MySQL system_charset_info (UTF-8) and quote it if needed.
+@return pointer to the end of buf */
+static inline
+void
+innobase_format_name(
+/*==================*/
+ char* buf, /*!< out: buffer for converted identifier */
+ ulint buflen, /*!< in: length of buf, in bytes */
+ const char* name, /*!< in: index or table name to format */
+ ibool is_index_name) /*!< in: index name */
+{
+ const char* bufend;
+
+ bufend = innobase_convert_name(buf, buflen, name, strlen(name),
+ NULL, !is_index_name);
+
+ ut_ad((ulint) (bufend - buf) < buflen);
+
+ buf[bufend - buf] = '\0';
+}
+
/**********************************************************************//**
Determines if the currently running transaction has been interrupted.
@return TRUE if interrupted */
@@ -2814,6 +2852,8 @@ innobase_change_buffering_inited_ok:
srv_use_checksums = (ibool) innobase_use_checksums;
srv_fast_checksum = (ibool) innobase_fast_checksum;
+ srv_blocking_lru_restore = (ibool) innobase_blocking_lru_restore;
+
#ifdef HAVE_LARGE_PAGES
if ((os_use_large_pages = (ibool) my_use_large_pages))
os_large_page_size = (ulint) opt_large_page_size;
@@ -2847,6 +2887,10 @@ innobase_change_buffering_inited_ok:
innobase_commit_concurrency_init_default();
+#ifndef EXTENDED_FOR_KILLIDLE
+ srv_kill_idle_transaction = 0;
+#endif
+
#ifdef HAVE_PSI_INTERFACE
/* Register keys with MySQL performance schema */
if (PSI_server) {
@@ -3280,6 +3324,11 @@ innobase_commit(
trx_search_latch_release_if_reserved(trx);
}
+ if (trx->fake_changes && (all || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
+ innobase_rollback(hton, thd, all); /* rollback implicitly */
+ thd->stmt_da->reset_diagnostics_area(); /* because debug assertion code complains, if something left */
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
/* Transaction is deregistered only in a commit or a rollback. If
it is deregistered we know there cannot be resources to be freed
and we could return immediately. For the time being, we play safe
@@ -4261,11 +4310,11 @@ retry:
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
}
- if (share->ib_table) {
- ut_a(share->ib_table == ib_table);
- } else {
- share->ib_table = ib_table;
- }
+ share->ib_table = ib_table;
+
+
+
+
if (NULL == ib_table) {
if (is_part && retries < 10) {
@@ -4566,25 +4615,6 @@ field_in_record_is_null(
return(0);
}
-/**************************************************************//**
-Sets a field in a record to SQL NULL. Uses the record format
-information in table to track the null bit in record. */
-static inline
-void
-set_field_in_record_to_null(
-/*========================*/
- TABLE* table, /*!< in: MySQL table object */
- Field* field, /*!< in: MySQL field object */
- char* record) /*!< in: a row in MySQL format */
-{
- int null_offset;
-
- null_offset = (uint) ((char*) field->null_ptr
- - (char*) table->record[0]);
-
- record[null_offset] = record[null_offset] | field->null_bit;
-}
-
/*************************************************************//**
InnoDB uses this function to compare two data fields for which the data type
is such that we must use MySQL code to compare them. NOTE that the prototype
@@ -6455,12 +6485,14 @@ ha_innobase::index_read(
index = prebuilt->index;
- if (UNIV_UNLIKELY(index == NULL)) {
+ if (UNIV_UNLIKELY(index == NULL) || dict_index_is_corrupted(index)) {
prebuilt->index_usable = FALSE;
DBUG_RETURN(HA_ERR_CRASHED);
}
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
- DBUG_RETURN(HA_ERR_TABLE_DEF_CHANGED);
+ DBUG_RETURN(dict_index_is_corrupted(index)
+ ? HA_ERR_INDEX_CORRUPT
+ : HA_ERR_TABLE_DEF_CHANGED);
}
/* Note that if the index for which the search template is built is not
@@ -6528,7 +6560,7 @@ ha_innobase::index_read(
table->status = 0;
#ifdef EXTENDED_FOR_USERSTAT
rows_read++;
- if (active_index >= 0 && active_index < MAX_KEY)
+ if (active_index < MAX_KEY)
index_rows_read[active_index]++;
#endif
break;
@@ -6659,10 +6691,33 @@ ha_innobase::change_active_index(
prebuilt->index);
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
- push_warning_printf(user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- HA_ERR_TABLE_DEF_CHANGED,
- "InnoDB: insufficient history for index %u",
- keynr);
+ if (dict_index_is_corrupted(prebuilt->index)) {
+ char index_name[MAX_FULL_NAME_LEN + 1];
+ char table_name[MAX_FULL_NAME_LEN + 1];
+
+ innobase_format_name(
+ index_name, sizeof index_name,
+ prebuilt->index->name, TRUE);
+
+ innobase_format_name(
+ table_name, sizeof table_name,
+ prebuilt->index->table->name, FALSE);
+
+ push_warning_printf(
+ user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ HA_ERR_INDEX_CORRUPT,
+ "InnoDB: Index %s for table %s is"
+ " marked as corrupted",
+ index_name, table_name);
+ DBUG_RETURN(1);
+ } else {
+ push_warning_printf(
+ user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ HA_ERR_TABLE_DEF_CHANGED,
+ "InnoDB: insufficient history for index %u",
+ keynr);
+ }
+
/* The caller seems to ignore this. Thus, we must check
this again in row_search_for_mysql(). */
DBUG_RETURN(convert_error_code_to_mysql(DB_MISSING_HISTORY,
@@ -6755,7 +6810,7 @@ ha_innobase::general_fetch(
table->status = 0;
#ifdef EXTENDED_FOR_USERSTAT
rows_read++;
- if (active_index >= 0 && active_index < MAX_KEY)
+ if (active_index < MAX_KEY)
index_rows_read[active_index]++;
#endif
break;
@@ -7801,6 +7856,12 @@ ha_innobase::create(
trx = innobase_trx_allocate(thd);
+ if (trx->fake_changes) {
+ innobase_commit_low(trx);
+ trx_free_for_mysql(trx);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+
/* Latch the InnoDB data dictionary exclusively so that no deadlocks
or lock waits can happen in it during a table create operation.
Drop table etc. do this latching in row0mysql.c. */
@@ -8021,6 +8082,10 @@ ha_innobase::truncate(void)
DBUG_RETURN(HA_ERR_CRASHED);
}
+ if (prebuilt->trx->fake_changes) {
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+
/* Truncate the table in InnoDB */
error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
@@ -8077,6 +8142,12 @@ ha_innobase::delete_table(
trx = innobase_trx_allocate(thd);
+ if (trx->fake_changes) {
+ innobase_commit_low(trx);
+ trx_free_for_mysql(trx);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+
name_len = strlen(name);
ut_a(name_len < 1000);
@@ -8163,6 +8234,12 @@ innobase_drop_database(
trx->mysql_thd = NULL;
#else
trx = innobase_trx_allocate(thd);
+ if (trx->fake_changes) {
+ my_free(namebuf);
+ innobase_commit_low(trx);
+ trx_free_for_mysql(trx);
+ return; /* ignore */
+ }
#endif
row_drop_database_for_mysql(namebuf, trx);
my_free(namebuf);
@@ -8270,6 +8347,11 @@ ha_innobase::rename_table(
trx_search_latch_release_if_reserved(parent_trx);
trx = innobase_trx_allocate(thd);
+ if (trx->fake_changes) {
+ innobase_commit_low(trx);
+ trx_free_for_mysql(trx);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
error = innobase_rename_table(trx, from, to, TRUE);
@@ -8356,6 +8438,10 @@ ha_innobase::records_in_range(
n_rows = HA_POS_ERROR;
goto func_exit;
}
+ if (dict_index_is_corrupted(index)) {
+ n_rows = HA_ERR_INDEX_CORRUPT;
+ goto func_exit;
+ }
if (UNIV_UNLIKELY(!row_merge_is_index_usable(prebuilt->trx, index))) {
n_rows = HA_ERR_TABLE_DEF_CHANGED;
goto func_exit;
@@ -9065,6 +9151,7 @@ ha_innobase::check(
ulint n_rows_in_table = ULINT_UNDEFINED;
ibool is_ok = TRUE;
ulint old_isolation_level;
+ ibool table_corrupted;
DBUG_ENTER("ha_innobase::check");
DBUG_ASSERT(thd == ha_thd());
@@ -9106,6 +9193,14 @@ ha_innobase::check(
prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
+ /* Check whether the table is already marked as corrupted
+ before running the check table */
+ table_corrupted = prebuilt->table->corrupted;
+
+ /* Reset table->corrupted bit so that check table can proceed to
+ do additional check */
+ prebuilt->table->corrupted = FALSE;
+
/* Enlarge the fatal lock wait timeout during CHECK TABLE. */
mutex_enter(&kernel_mutex);
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
@@ -9114,6 +9209,7 @@ ha_innobase::check(
for (index = dict_table_get_first_index(prebuilt->table);
index != NULL;
index = dict_table_get_next_index(index)) {
+ char index_name[MAX_FULL_NAME_LEN + 1];
#if 0
fputs("Validating index ", stderr);
ut_print_name(stderr, trx, FALSE, index->name);
@@ -9122,11 +9218,16 @@ ha_innobase::check(
if (!btr_validate_index(index, prebuilt->trx)) {
is_ok = FALSE;
+
+ innobase_format_name(
+ index_name, sizeof index_name,
+ prebuilt->index->name, TRUE);
+
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_NOT_KEYFILE,
"InnoDB: The B-tree of"
- " index '%-.200s' is corrupted.",
- index->name);
+ " index %s is corrupted.",
+ index_name);
continue;
}
@@ -9139,11 +9240,26 @@ ha_innobase::check(
prebuilt->trx, prebuilt->index);
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- HA_ERR_TABLE_DEF_CHANGED,
- "InnoDB: Insufficient history for"
- " index '%-.200s'",
- index->name);
+ innobase_format_name(
+ index_name, sizeof index_name,
+ prebuilt->index->name, TRUE);
+
+ if (dict_index_is_corrupted(prebuilt->index)) {
+ push_warning_printf(
+ user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ HA_ERR_INDEX_CORRUPT,
+ "InnoDB: Index %s is marked as"
+ " corrupted",
+ index_name);
+ is_ok = FALSE;
+ } else {
+ push_warning_printf(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ HA_ERR_TABLE_DEF_CHANGED,
+ "InnoDB: Insufficient history for"
+ " index %s",
+ index_name);
+ }
continue;
}
@@ -9157,12 +9273,19 @@ ha_innobase::check(
prebuilt->select_lock_type = LOCK_NONE;
if (!row_check_index_for_mysql(prebuilt, index, &n_rows)) {
+ innobase_format_name(
+ index_name, sizeof index_name,
+ index->name, TRUE);
+
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_NOT_KEYFILE,
"InnoDB: The B-tree of"
- " index '%-.200s' is corrupted.",
- index->name);
+ " index %s is corrupted.",
+ index_name);
is_ok = FALSE;
+ row_mysql_lock_data_dictionary(prebuilt->trx);
+ dict_set_corrupted(index);
+ row_mysql_unlock_data_dictionary(prebuilt->trx);
}
if (thd_killed(user_thd)) {
@@ -9189,6 +9312,20 @@ ha_innobase::check(
}
}
+ if (table_corrupted) {
+ /* If some previous operation has marked the table as
+ corrupted in memory, and has not propagated such to
+ clustered index, we will do so here */
+ index = dict_table_get_first_index(prebuilt->table);
+
+ if (!dict_index_is_corrupted(index)) {
+ mutex_enter(&dict_sys->mutex);
+ dict_set_corrupted(index);
+ mutex_exit(&dict_sys->mutex);
+ }
+ prebuilt->table->corrupted = TRUE;
+ }
+
/* Restore the original isolation level */
prebuilt->trx->isolation_level = old_isolation_level;
@@ -11077,6 +11214,10 @@ innobase_xa_prepare(
return(0);
}
+ if (trx->fake_changes) {
+ return(0);
+ }
+
thd_get_xid(thd, (MYSQL_XID*) &trx->xid);
/* Release a possible FIFO ticket and search latch. Since we will
@@ -11886,6 +12027,57 @@ innobase_index_name_is_reserved(
return(false);
}
+/***********************************************************************
+functions for kill session of idle transaction */
+extern "C"
+ibool
+innobase_thd_is_idle(
+/*=================*/
+ const void* thd) /*!< in: thread handle (THD*) */
+{
+#ifdef EXTENDED_FOR_KILLIDLE
+ return(thd_command((const THD*) thd) == COM_SLEEP);
+#else
+ return(FALSE);
+#endif
+}
+
+extern "C"
+ib_int64_t
+innobase_thd_get_start_time(
+/*========================*/
+ const void* thd) /*!< in: thread handle (THD*) */
+{
+#ifdef EXTENDED_FOR_KILLIDLE
+ return((ib_int64_t)thd_start_time((const THD*) thd));
+#else
+ return(0); /*dummy value*/
+#endif
+}
+
+extern "C"
+void
+innobase_thd_kill(
+/*==============*/
+ ulong thd_id)
+{
+#ifdef EXTENDED_FOR_KILLIDLE
+ thd_kill(thd_id);
+#else
+ return;
+#endif
+}
+
+extern "C"
+ulong
+innobase_thd_get_thread_id(
+/*=======================*/
+ const void* thd)
+{
+ return(thd_get_thread_id((const THD*) thd));
+}
+
+
static SHOW_VAR innodb_status_variables_export[]= {
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
{NullS, NullS, SHOW_LONG}
@@ -12031,6 +12223,11 @@ static MYSQL_SYSVAR_BOOL(large_prefix, innobase_large_prefix,
"Support large index prefix length of REC_VERSION_56_MAX_INDEX_COL_LEN (3072) bytes.",
NULL, NULL, FALSE);
+static MYSQL_SYSVAR_BOOL(force_load_corrupted, srv_load_corrupted,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "Force InnoDB to load metadata of corrupted table.",
+ NULL, NULL, FALSE);
+
static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Force InnoDB to not use next-key locking, to use only row-level locking.",
@@ -12172,6 +12369,15 @@ static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
NULL, NULL, 500L, 1L, ~0L, 0);
+static MYSQL_SYSVAR_LONG(kill_idle_transaction, srv_kill_idle_transaction,
+ PLUGIN_VAR_RQCMDARG,
+#ifdef EXTENDED_FOR_KILLIDLE
+ "If non-zero value, the idle session with transaction which is idle over the value in seconds is killed by InnoDB.",
+#else
+ "No effect for this build.",
+#endif
+ NULL, NULL, 0, 0, LONG_MAX, 0);
+
static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR,
"Number of file I/O threads in InnoDB.",
@@ -12312,6 +12518,11 @@ static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug,
NULL, NULL, 0, 0, 1, 0);
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+static MYSQL_SYSVAR_BOOL(random_read_ahead, srv_random_read_ahead,
+ PLUGIN_VAR_NOCMDARG,
+ "Whether to use read ahead for random access within an extent.",
+ NULL, NULL, FALSE);
+
static MYSQL_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
PLUGIN_VAR_RQCMDARG,
"Number of pages that must be accessed sequentially for InnoDB to "
@@ -12423,6 +12634,13 @@ static MYSQL_SYSVAR_UINT(buffer_pool_restore_at_startup, srv_auto_lru_dump,
"0 (the default) disables automatic dumps.",
NULL, NULL, 0, 0, UINT_MAX32, 0);
+static MYSQL_SYSVAR_BOOL(blocking_buffer_pool_restore,
+ innobase_blocking_lru_restore,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "Block XtraDB startup process until buffer pool is full restored from a "
+ "dump file (if present). Disabled by default.",
+ NULL, NULL, FALSE);
+
const char *corrupt_table_action_names[]=
{
"assert", /* 0 */
@@ -12462,6 +12680,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(fast_checksum),
MYSQL_SYSVAR(commit_concurrency),
MYSQL_SYSVAR(concurrency_tickets),
+ MYSQL_SYSVAR(kill_idle_transaction),
MYSQL_SYSVAR(data_file_path),
MYSQL_SYSVAR(doublewrite_file),
MYSQL_SYSVAR(data_home_dir),
@@ -12480,6 +12699,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(flush_method),
MYSQL_SYSVAR(force_recovery),
MYSQL_SYSVAR(large_prefix),
+ MYSQL_SYSVAR(force_load_corrupted),
MYSQL_SYSVAR(locks_unsafe_for_binlog),
MYSQL_SYSVAR(lock_wait_timeout),
#ifdef UNIV_LOG_ARCHIVE
@@ -12536,14 +12756,17 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
MYSQL_SYSVAR(change_buffering_debug),
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+ MYSQL_SYSVAR(random_read_ahead),
MYSQL_SYSVAR(read_ahead_threshold),
MYSQL_SYSVAR(io_capacity),
MYSQL_SYSVAR(buffer_pool_restore_at_startup),
+ MYSQL_SYSVAR(blocking_buffer_pool_restore),
MYSQL_SYSVAR(purge_threads),
MYSQL_SYSVAR(purge_batch_size),
MYSQL_SYSVAR(rollback_segments),
MYSQL_SYSVAR(corrupt_table_action),
MYSQL_SYSVAR(lazy_drop_table),
+ MYSQL_SYSVAR(fake_changes),
NULL
};
diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index f2dd3c11f80..9d6ccaf99a2 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -695,6 +695,10 @@ ha_innobase::add_index(
possible adaptive hash latch to avoid deadlocks of threads. */
trx_search_latch_release_if_reserved(prebuilt->trx);
+ if (prebuilt->trx->fake_changes) {
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+
/* Check if the index name is reserved. */
if (innobase_index_name_is_reserved(user_thd, key_info, num_of_keys)) {
DBUG_RETURN(ER_WRONG_NAME_FOR_INDEX);
@@ -732,6 +736,13 @@ ha_innobase::add_index(
/* Create a background transaction for the operations on
the data dictionary tables. */
trx = innobase_trx_allocate(user_thd);
+ if (trx->fake_changes) {
+ mem_heap_free(heap);
+ trx_general_rollback_for_mysql(trx, NULL);
+ trx_free_for_mysql(trx);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+
trx_start_if_not_started(trx);
/* Create table containing all indexes to be built in this
@@ -1092,6 +1103,10 @@ ha_innobase::prepare_drop_index(
trx_search_latch_release_if_reserved(prebuilt->trx);
trx = prebuilt->trx;
+ if (trx->fake_changes) {
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+
/* Test and mark all the indexes to be dropped */
row_mysql_lock_data_dictionary(trx);
@@ -1296,6 +1311,12 @@ ha_innobase::final_drop_index(
/* Create a background transaction for the operations on
the data dictionary tables. */
trx = innobase_trx_allocate(user_thd);
+ if (trx->fake_changes) {
+ trx_general_rollback_for_mysql(trx, NULL);
+ trx_free_for_mysql(trx);
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ }
+
trx_start_if_not_started(trx);
/* Flag this transaction as a dictionary operation, so that
diff --git a/storage/xtradb/ibuf/ibuf0ibuf.c b/storage/xtradb/ibuf/ibuf0ibuf.c
index f5ed301dcf1..7def360867d 100644
--- a/storage/xtradb/ibuf/ibuf0ibuf.c
+++ b/storage/xtradb/ibuf/ibuf0ibuf.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -402,7 +402,7 @@ ibuf_tree_root_get(
block = buf_page_get(
IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
root = buf_block_get_frame(block);
@@ -590,7 +590,7 @@ ibuf_init_at_db_start(void)
block = buf_page_get(
IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO,
RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
root = buf_block_get_frame(block);
}
@@ -2251,16 +2251,17 @@ ibuf_add_free_page(void)
} else {
buf_block_t* block = buf_page_get(
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
- page = buf_block_get_frame(block);
- }
+ ibuf_enter(&mtr);
- ibuf_enter(&mtr);
+ mutex_enter(&ibuf_mutex);
- mutex_enter(&ibuf_mutex);
+ root = ibuf_tree_root_get(&mtr);
- root = ibuf_tree_root_get(&mtr);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
+
+ page = buf_block_get_frame(block);
+ }
/* Add the page to the free list and update the ibuf size data */
@@ -2374,8 +2375,7 @@ ibuf_remove_free_page(void)
block = buf_page_get(
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
-
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
page = buf_block_get_frame(block);
}
@@ -3066,7 +3066,7 @@ ibuf_get_volume_buffered(
IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH,
mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
prev_page = buf_block_get_frame(block);
@@ -3139,7 +3139,7 @@ count_later:
IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH,
mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
next_page = buf_block_get_frame(block);
@@ -3377,7 +3377,7 @@ ibuf_set_entry_counter(
IBUF_SPACE_ID, 0, prev_page_no,
RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
prev_page = buf_block_get_frame(block);
@@ -3496,6 +3496,8 @@ ibuf_insert_low(
ut_a(trx_sys_multiple_tablespace_format);
+ ut_ad(!(thr_get_trx(thr)->fake_changes));
+
do_merge = FALSE;
/* Perform dirty reads of ibuf->size and ibuf->max_size, to
@@ -4465,6 +4467,7 @@ ibuf_merge_or_delete_for_page(
ut_ad(!block || buf_block_get_space(block) == space);
ut_ad(!block || buf_block_get_page_no(block) == page_no);
ut_ad(!block || buf_block_get_zip_size(block) == zip_size);
+ ut_ad(!block || buf_block_get_io_fix(block) == BUF_IO_READ);
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE
|| trx_sys_hdr_page(space, page_no)) {
@@ -4617,7 +4620,13 @@ loop:
ut_a(success);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ /* This is a user page (secondary index leaf page),
+ but we pretend that it is a change buffer page in
+ order to obey the latching order. This should be OK,
+ because buffered changes are applied immediately while
+ the block is io-fixed. Other threads must not try to
+ latch an io-fixed block. */
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
}
/* Position pcur in the insert buffer at the first entry for this
@@ -4721,7 +4730,12 @@ loop:
__FILE__, __LINE__, &mtr);
ut_a(success);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ /* This is a user page (secondary
+ index leaf page), but it should be OK
+ to use too low latching order for it,
+ as the block is io-fixed. */
+ buf_block_dbg_add_level(
+ block, SYNC_IBUF_TREE_NODE);
if (!ibuf_restore_pos(space, page_no,
search_tuple,
diff --git a/storage/xtradb/include/btr0btr.h b/storage/xtradb/include/btr0btr.h
index c632e034581..058fcfb64de 100644
--- a/storage/xtradb/include/btr0btr.h
+++ b/storage/xtradb/include/btr0btr.h
@@ -199,26 +199,45 @@ btr_block_get_func(
ulint mode, /*!< in: latch mode */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
- mtr_t* mtr) /*!< in/out: mtr */
- __attribute__((nonnull));
+# ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree, may be NULL
+ if it is not an insert buffer tree */
+# endif /* UNIV_SYNC_DEBUG */
+ mtr_t* mtr); /*!< in/out: mini-transaction */
+# ifdef UNIV_SYNC_DEBUG
+/** Gets a buffer page and declares its latching order level.
+@param space tablespace identifier
+@param zip_size compressed page size in bytes or 0 for uncompressed pages
+@param page_no page number
+@param mode latch mode
+@param index index tree, may be NULL if not the insert buffer tree
+@param mtr mini-transaction handle
+@return the block descriptor */
+# define btr_block_get(space,zip_size,page_no,mode,index,mtr) \
+ btr_block_get_func(space,zip_size,page_no,mode, \
+ __FILE__,__LINE__,index,mtr)
+# else /* UNIV_SYNC_DEBUG */
/** Gets a buffer page and declares its latching order level.
@param space tablespace identifier
@param zip_size compressed page size in bytes or 0 for uncompressed pages
@param page_no page number
@param mode latch mode
+@param idx index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@return the block descriptor */
-# define btr_block_get(space,zip_size,page_no,mode,mtr) \
+# define btr_block_get(space,zip_size,page_no,mode,idx,mtr) \
btr_block_get_func(space,zip_size,page_no,mode,__FILE__,__LINE__,mtr)
+# endif /* UNIV_SYNC_DEBUG */
/** Gets a buffer page and declares its latching order level.
@param space tablespace identifier
@param zip_size compressed page size in bytes or 0 for uncompressed pages
@param page_no page number
@param mode latch mode
+@param idx index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@return the uncompressed page frame */
-# define btr_page_get(space,zip_size,page_no,mode,mtr) \
- buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,mtr))
+# define btr_page_get(space,zip_size,page_no,mode,idx,mtr) \
+ buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,idx,mtr))
/**************************************************************//**
Sets the index id field of a page. */
UNIV_INLINE
@@ -389,8 +408,7 @@ btr_free_root(
ulint zip_size, /*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint root_page_no, /*!< in: root page number */
- mtr_t* mtr); /*!< in: a mini-transaction which has already
- been started */
+ mtr_t* mtr); /*!< in/out: mini-transaction */
/*************************************************************//**
Makes tree one level higher by splitting the root, and inserts
the tuple. It is assumed that mtr contains an x-latch on the tree.
diff --git a/storage/xtradb/include/btr0btr.ic b/storage/xtradb/include/btr0btr.ic
index 99c02ab30dc..f446ecb69d3 100644
--- a/storage/xtradb/include/btr0btr.ic
+++ b/storage/xtradb/include/btr0btr.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -48,6 +48,10 @@ btr_block_get_func(
ulint mode, /*!< in: latch mode */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
+#ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree, may be NULL
+ if it is not an insert buffer tree */
+#endif /* UNIV_SYNC_DEBUG */
mtr_t* mtr) /*!< in/out: mtr */
{
buf_block_t* block;
@@ -59,7 +63,9 @@ btr_block_get_func(
if (block && mode != RW_NO_LATCH) {
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(
+ block, index != NULL && dict_index_is_ibuf(index)
+ ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
}
return(block);
diff --git a/storage/xtradb/include/btr0pcur.h b/storage/xtradb/include/btr0pcur.h
index 6c11c973fc9..f605c476844 100644
--- a/storage/xtradb/include/btr0pcur.h
+++ b/storage/xtradb/include/btr0pcur.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -244,18 +244,6 @@ btr_pcur_restore_position_func(
mtr_t* mtr); /*!< in: mtr */
#define btr_pcur_restore_position(l,cur,mtr) \
btr_pcur_restore_position_func(l,cur,__FILE__,__LINE__,mtr)
-/**************************************************************//**
-If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
-releases the page latch and bufferfix reserved by the cursor.
-NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
-made by the current mini-transaction to the data protected by the
-cursor latch, as then the latch must not be released until mtr_commit. */
-UNIV_INTERN
-void
-btr_pcur_release_leaf(
-/*==================*/
- btr_pcur_t* cursor, /*!< in: persistent cursor */
- mtr_t* mtr); /*!< in: mtr */
/*********************************************************//**
Gets the rel_pos field for a cursor whose position has been stored.
@return BTR_PCUR_ON, ... */
@@ -266,10 +254,9 @@ btr_pcur_get_rel_pos(
const btr_pcur_t* cursor);/*!< in: persistent cursor */
/**************************************************************//**
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
-that is, the cursor becomes detached. If there have been modifications
-to the page where pcur is positioned, this can be used instead of
-btr_pcur_release_leaf. Function btr_pcur_store_position should be used
-before calling this, if restoration of cursor is wanted later. */
+that is, the cursor becomes detached.
+Function btr_pcur_store_position should be used before calling this,
+if restoration of cursor is wanted later. */
UNIV_INLINE
void
btr_pcur_commit_specify_mtr(
diff --git a/storage/xtradb/include/btr0pcur.ic b/storage/xtradb/include/btr0pcur.ic
index 59fdb21824b..d86601e5a32 100644
--- a/storage/xtradb/include/btr0pcur.ic
+++ b/storage/xtradb/include/btr0pcur.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -369,10 +369,9 @@ btr_pcur_move_to_next(
/**************************************************************//**
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
-that is, the cursor becomes detached. If there have been modifications
-to the page where pcur is positioned, this can be used instead of
-btr_pcur_release_leaf. Function btr_pcur_store_position should be used
-before calling this, if restoration of cursor is wanted later. */
+that is, the cursor becomes detached.
+Function btr_pcur_store_position should be used before calling this,
+if restoration of cursor is wanted later. */
UNIV_INLINE
void
btr_pcur_commit_specify_mtr(
diff --git a/storage/xtradb/include/buf0buddy.h b/storage/xtradb/include/buf0buddy.h
index f51b8020918..eeea8f76351 100644
--- a/storage/xtradb/include/buf0buddy.h
+++ b/storage/xtradb/include/buf0buddy.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -37,39 +37,39 @@ Created December 2006 by Marko Makela
/**********************************************************************//**
Allocate a block. The thread calling this function must hold
buf_pool->mutex and must not hold buf_pool->zip_mutex or any
-block->mutex. The buf_pool->mutex may only be released and reacquired
-if lru != NULL. This function should only be used for allocating
-compressed page frames or control blocks (buf_page_t). Allocated
-control blocks must be properly initialized immediately after
-buf_buddy_alloc() has returned the memory, before releasing
-buf_pool->mutex.
-@return allocated block, possibly NULL if lru == NULL */
+block->mutex. The buf_pool->mutex may be released and reacquired.
+This function should only be used for allocating compressed page frames.
+@return allocated block, never NULL */
UNIV_INLINE
-void*
+byte*
buf_buddy_alloc(
/*============*/
- buf_pool_t* buf_pool,
- /*!< buffer pool in which the block resides */
- ulint size, /*!< in: block size, up to UNIV_PAGE_SIZE */
- ibool* lru, /*!< in: pointer to a variable that will be assigned
- TRUE if storage was allocated from the LRU list
- and buf_pool->mutex was temporarily released,
- or NULL if the LRU list should not be used */
- ibool have_page_hash_mutex)
- __attribute__((malloc));
+ buf_pool_t* buf_pool, /*!< in/out: buffer pool in which
+ the page resides */
+ ulint size, /*!< in: compressed page size
+ (between PAGE_ZIP_MIN_SIZE and
+ UNIV_PAGE_SIZE) */
+ ibool* lru, /*!< in: pointer to a variable
+ that will be assigned TRUE if
+ storage was allocated from the
+ LRU list and buf_pool->mutex was
+ temporarily released */
+ ibool have_page_hash_mutex)
+ __attribute__((malloc, nonnull));
/**********************************************************************//**
-Release a block. */
+Deallocate a block. */
UNIV_INLINE
void
buf_buddy_free(
/*===========*/
- buf_pool_t* buf_pool,
- /*!< buffer pool in which the block resides */
- void* buf, /*!< in: block to be freed, must not be
- pointed to by the buffer pool */
- ulint size, /*!< in: block size, up to UNIV_PAGE_SIZE */
- ibool have_page_hash_mutex)
+ buf_pool_t* buf_pool, /*!< in/out: buffer pool in which
+ the block resides */
+ void* buf, /*!< in: block to be freed, must not
+ be pointed to by the buffer pool */
+ ulint size, /*!< in: block size,
+ up to UNIV_PAGE_SIZE */
+ ibool have_page_hash_mutex)
__attribute__((nonnull));
#ifndef UNIV_NONINL
diff --git a/storage/xtradb/include/buf0buddy.ic b/storage/xtradb/include/buf0buddy.ic
index 4dbfed52abe..3dd75276656 100644
--- a/storage/xtradb/include/buf0buddy.ic
+++ b/storage/xtradb/include/buf0buddy.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -36,22 +36,22 @@ Created December 2006 by Marko Makela
/**********************************************************************//**
Allocate a block. The thread calling this function must hold
buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex.
-The buf_pool->mutex may only be released and reacquired if lru != NULL.
-@return allocated block, possibly NULL if lru==NULL */
+The buf_pool_mutex may be released and reacquired.
+@return allocated block, never NULL */
UNIV_INTERN
void*
buf_buddy_alloc_low(
/*================*/
- buf_pool_t* buf_pool,
- /*!< in: buffer pool in which the page resides */
- ulint i, /*!< in: index of buf_pool->zip_free[],
- or BUF_BUDDY_SIZES */
- ibool* lru, /*!< in: pointer to a variable that will be assigned
- TRUE if storage was allocated from the LRU list
- and buf_pool->mutex was temporarily released,
- or NULL if the LRU list should not be used */
- ibool have_page_hash_mutex)
- __attribute__((malloc));
+ buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
+ ulint i, /*!< in: index of buf_pool->zip_free[],
+ or BUF_BUDDY_SIZES */
+ ibool* lru, /*!< in: pointer to a variable that
+ will be assigned TRUE if storage was
+ allocated from the LRU list and
+ buf_pool->mutex was temporarily
+ released */
+ ibool have_page_hash_mutex)
+ __attribute__((malloc, nonnull));
/**********************************************************************//**
Deallocate a block. */
@@ -79,6 +79,8 @@ buf_buddy_get_slot(
ulint i;
ulint s;
+ ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+
for (i = 0, s = BUF_BUDDY_LOW; s < size; i++, s <<= 1) {
}
@@ -89,32 +91,32 @@ buf_buddy_get_slot(
/**********************************************************************//**
Allocate a block. The thread calling this function must hold
buf_pool->mutex and must not hold buf_pool->zip_mutex or any
-block->mutex. The buf_pool->mutex may only be released and reacquired
-if lru != NULL. This function should only be used for allocating
-compressed page frames or control blocks (buf_page_t). Allocated
-control blocks must be properly initialized immediately after
-buf_buddy_alloc() has returned the memory, before releasing
-buf_pool->mutex.
-@return allocated block, possibly NULL if lru == NULL */
+block->mutex. The buf_pool->mutex may be released and reacquired.
+This function should only be used for allocating compressed page frames.
+@return allocated block, never NULL */
UNIV_INLINE
-void*
+byte*
buf_buddy_alloc(
/*============*/
- buf_pool_t* buf_pool, /*!< in: buffer pool in which
+ buf_pool_t* buf_pool, /*!< in/out: buffer pool in which
the page resides */
- ulint size, /*!< in: block size, up to
- UNIV_PAGE_SIZE */
+ ulint size, /*!< in: compressed page size
+ (between PAGE_ZIP_MIN_SIZE and
+ UNIV_PAGE_SIZE) */
ibool* lru, /*!< in: pointer to a variable
that will be assigned TRUE if
storage was allocated from the
LRU list and buf_pool->mutex was
- temporarily released, or NULL if
- the LRU list should not be used */
+ temporarily released */
ibool have_page_hash_mutex)
{
//ut_ad(buf_pool_mutex_own(buf_pool));
+ ut_ad(ut_is_2pow(size));
+ ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+ ut_ad(size <= UNIV_PAGE_SIZE);
- return(buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), lru, have_page_hash_mutex));
+ return((byte*) buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size),
+ lru, have_page_hash_mutex));
}
/**********************************************************************//**
@@ -123,14 +125,18 @@ UNIV_INLINE
void
buf_buddy_free(
/*===========*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
- void* buf, /*!< in: block to be freed, must not be
- pointed to by the buffer pool */
- ulint size, /*!< in: block size, up to
- UNIV_PAGE_SIZE */
+ buf_pool_t* buf_pool, /*!< in/out: buffer pool in which
+ the block resides */
+ void* buf, /*!< in: block to be freed, must not
+ be pointed to by the buffer pool */
+ ulint size, /*!< in: block size,
+ up to UNIV_PAGE_SIZE */
ibool have_page_hash_mutex)
{
//ut_ad(buf_pool_mutex_own(buf_pool));
+ ut_ad(ut_is_2pow(size));
+ ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+ ut_ad(size <= UNIV_PAGE_SIZE);
if (!have_page_hash_mutex) {
mutex_enter(&buf_pool->LRU_list_mutex);
diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index ef6a26f9459..d85dac5cc91 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/include/buf0buf.h
@@ -148,6 +148,8 @@ struct buf_pool_info_struct{
ulint n_pages_created; /*!< buf_pool->n_pages_created */
ulint n_pages_written; /*!< buf_pool->n_pages_written */
ulint n_page_gets; /*!< buf_pool->n_page_gets */
+ ulint n_ra_pages_read_rnd; /*!< buf_pool->n_ra_pages_read_rnd,
+ number of pages readahead */
ulint n_ra_pages_read; /*!< buf_pool->n_ra_pages_read, number
of pages readahead */
ulint n_ra_pages_evicted; /*!< buf_pool->n_ra_pages_evicted,
@@ -172,6 +174,8 @@ struct buf_pool_info_struct{
last printout */
/* Statistics about read ahead algorithm. */
+ double pages_readahead_rnd_rate;/*!< random readahead rate in pages per
+ second */
double pages_readahead_rate; /*!< readahead rate in pages per
second */
double pages_evicted_rate; /*!< rate of readahead page evicted
@@ -261,12 +265,6 @@ buf_relocate(
BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_ZIP_PAGE */
buf_page_t* dpage) /*!< in/out: destination control block */
__attribute__((nonnull));
-/********************************************************************//**
-Resizes the buffer pool. */
-UNIV_INTERN
-void
-buf_pool_resize(void);
-/*=================*/
/*********************************************************************//**
Gets the current size of buffer buf_pool in bytes.
@return size in bytes */
@@ -290,6 +288,23 @@ ib_uint64_t
buf_pool_get_oldest_modification(void);
/*==================================*/
/********************************************************************//**
+Allocates a buf_page_t descriptor. This function must succeed. In case
+of failure we assert in this function. */
+UNIV_INLINE
+buf_page_t*
+buf_page_alloc_descriptor(void)
+/*===========================*/
+ __attribute__((malloc));
+/********************************************************************//**
+Free a buf_page_t descriptor. */
+UNIV_INLINE
+void
+buf_page_free_descriptor(
+/*=====================*/
+ buf_page_t* bpage) /*!< in: bpage descriptor to free. */
+ __attribute__((nonnull));
+
+/********************************************************************//**
Allocates a buffer block.
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
UNIV_INTERN
@@ -546,6 +561,18 @@ buf_block_get_freed_page_clock(
__attribute__((pure));
/********************************************************************//**
+Tells if a block is still close enough to the MRU end of the LRU list
+meaning that it is not in danger of getting evicted and also implying
+that it has been accessed recently.
+Note that this is for heuristics only and does not reserve buffer pool
+mutex.
+@return TRUE if block is close to MRU end of LRU */
+UNIV_INLINE
+ibool
+buf_page_peek_if_young(
+/*===================*/
+ const buf_page_t* bpage); /*!< in: block */
+/********************************************************************//**
Recommends a move of a block to the start of the LRU list if there is danger
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
mutex.
@@ -1233,7 +1260,7 @@ ulint
buf_get_free_list_len(void);
/*=======================*/
-/********************************************************************
+/********************************************************************//**
Determine if a block is a sentinel for a buffer pool watch.
@return TRUE if a sentinel for a buffer pool watch, FALSE if not */
UNIV_INTERN
@@ -1622,6 +1649,8 @@ struct buf_pool_stat_struct{
ulint n_pages_written;/*!< number write operations */
ulint n_pages_created;/*!< number of pages created
in the pool with no read */
+ ulint n_ra_pages_read_rnd;/*!< number of pages read in
+ as part of random read ahead */
ulint n_ra_pages_read;/*!< number of pages read in
as part of read ahead */
ulint n_ra_pages_evicted;/*!< number of read ahead
@@ -1766,7 +1795,7 @@ struct buf_pool_struct{
UT_LIST_BASE_NODE_T(buf_page_t) LRU;
/*!< base node of the LRU list */
buf_page_t* LRU_old; /*!< pointer to the about
- buf_LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV
+ LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV
oldest blocks in the LRU list;
NULL if LRU length less than
BUF_LRU_OLD_MIN_LEN;
@@ -1790,8 +1819,10 @@ struct buf_pool_struct{
frames and buf_page_t descriptors of blocks that exist
in the buffer pool only in compressed form. */
/* @{ */
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
UT_LIST_BASE_NODE_T(buf_page_t) zip_clean;
/*!< unmodified compressed pages */
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES_MAX];
/*!< buddy free lists */
diff --git a/storage/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic
index 1a96b575d9b..98d575075ba 100644
--- a/storage/xtradb/include/buf0buf.ic
+++ b/storage/xtradb/include/buf0buf.ic
@@ -125,6 +125,29 @@ buf_block_get_freed_page_clock(
}
/********************************************************************//**
+Tells if a block is still close enough to the MRU end of the LRU list
+meaning that it is not in danger of getting evicted and also implying
+that it has been accessed recently.
+Note that this is for heuristics only and does not reserve buffer pool
+mutex.
+@return TRUE if block is close to MRU end of LRU */
+UNIV_INLINE
+ibool
+buf_page_peek_if_young(
+/*===================*/
+ const buf_page_t* bpage) /*!< in: block */
+{
+ buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
+
+ /* FIXME: bpage->freed_page_clock is 31 bits */
+ return((buf_pool->freed_page_clock & ((1UL << 31) - 1))
+ < ((ulint) bpage->freed_page_clock
+ + (buf_pool->curr_size
+ * (BUF_LRU_OLD_RATIO_DIV - buf_pool->LRU_old_ratio)
+ / (BUF_LRU_OLD_RATIO_DIV * 4))));
+}
+
+/********************************************************************//**
Recommends a move of a block to the start of the LRU list if there is danger
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
mutex.
@@ -154,12 +177,7 @@ buf_page_peek_if_too_old(
buf_pool->stat.n_pages_not_made_young++;
return(FALSE);
} else {
- /* FIXME: bpage->freed_page_clock is 31 bits */
- return((buf_pool->freed_page_clock & ((1UL << 31) - 1))
- > ((ulint) bpage->freed_page_clock
- + (buf_pool->curr_size
- * (BUF_LRU_OLD_RATIO_DIV - buf_pool->LRU_old_ratio)
- / (BUF_LRU_OLD_RATIO_DIV * 4))));
+ return(!buf_page_peek_if_young(bpage));
}
}
@@ -792,6 +810,35 @@ buf_block_get_lock_hash_val(
}
/********************************************************************//**
+Allocates a buf_page_t descriptor. This function must succeed. In case
+of failure we assert in this function.
+@return: the allocated descriptor. */
+UNIV_INLINE
+buf_page_t*
+buf_page_alloc_descriptor(void)
+/*===========================*/
+{
+ buf_page_t* bpage;
+
+ bpage = (buf_page_t*) ut_malloc(sizeof *bpage);
+ ut_d(memset(bpage, 0, sizeof *bpage));
+ UNIV_MEM_ALLOC(bpage, sizeof *bpage);
+
+ return(bpage);
+}
+
+/********************************************************************//**
+Free a buf_page_t descriptor. */
+UNIV_INLINE
+void
+buf_page_free_descriptor(
+/*=====================*/
+ buf_page_t* bpage) /*!< in: bpage descriptor to free. */
+{
+ ut_free(bpage);
+}
+
+/********************************************************************//**
Frees a buffer block which does not contain a file page. */
UNIV_INLINE
void
diff --git a/storage/xtradb/include/buf0lru.h b/storage/xtradb/include/buf0lru.h
index 5d004ec4bb7..700136ec488 100644
--- a/storage/xtradb/include/buf0lru.h
+++ b/storage/xtradb/include/buf0lru.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -30,18 +30,6 @@ Created 11/5/1995 Heikki Tuuri
#include "ut0byte.h"
#include "buf0types.h"
-/** The return type of buf_LRU_free_block() */
-enum buf_lru_free_block_status {
- /** freed */
- BUF_LRU_FREED = 0,
- /** not freed because the caller asked to remove the
- uncompressed frame but the control block cannot be
- relocated */
- BUF_LRU_CANNOT_RELOCATE,
- /** not freed because of some other reason */
- BUF_LRU_NOT_FREED
-};
-
/******************************************************************//**
Tries to remove LRU flushed blocks from the end of the LRU list and put them
to the free list. This is beneficial for the efficiency of the insert buffer
@@ -85,6 +73,7 @@ void
buf_LRU_invalidate_tablespace(
/*==========================*/
ulint id); /*!< in: space id */
+
/******************************************************************//**
*/
UNIV_INTERN
@@ -92,6 +81,7 @@ void
buf_LRU_mark_space_was_deleted(
/*===========================*/
ulint id); /*!< in: space id */
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/********************************************************************//**
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
UNIV_INTERN
@@ -99,22 +89,22 @@ void
buf_LRU_insert_zip_clean(
/*=====================*/
buf_page_t* bpage); /*!< in: pointer to the block in question */
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
/******************************************************************//**
Try to free a block. If bpage is a descriptor of a compressed-only
page, the descriptor object will be freed as well.
-NOTE: If this function returns BUF_LRU_FREED, it will temporarily
+NOTE: If this function returns TRUE, it will temporarily
release buf_pool->mutex. Furthermore, the page frame will no longer be
accessible via bpage.
The caller must hold buf_pool->mutex and buf_page_get_mutex(bpage) and
release these two mutexes after the call. No other
buf_page_get_mutex() may be held when calling this function.
-@return BUF_LRU_FREED if freed, BUF_LRU_CANNOT_RELOCATE or
-BUF_LRU_NOT_FREED otherwise. */
+@return TRUE if freed, FALSE otherwise. */
UNIV_INTERN
-enum buf_lru_free_block_status
+ibool
buf_LRU_free_block(
/*===============*/
buf_page_t* bpage, /*!< in: block to be freed */
@@ -204,7 +194,7 @@ buf_LRU_make_block_old(
/*===================*/
buf_page_t* bpage); /*!< in: control block */
/**********************************************************************//**
-Updates buf_LRU_old_ratio.
+Updates buf_pool->LRU_old_ratio.
@return updated old_pct */
UNIV_INTERN
ulint
@@ -213,7 +203,7 @@ buf_LRU_old_ratio_update(
uint old_pct,/*!< in: Reserve this percentage of
the buffer pool for "old" blocks. */
ibool adjust);/*!< in: TRUE=adjust the LRU list;
- FALSE=just assign buf_LRU_old_ratio
+ FALSE=just assign buf_pool->LRU_old_ratio
during the initialization of InnoDB */
/********************************************************************//**
Update the historical stats that we are collecting for LRU eviction
@@ -235,6 +225,17 @@ ibool
buf_LRU_file_restore(void);
/*======================*/
+/******************************************************************//**
+Remove one page from LRU list and put it to free list */
+UNIV_INTERN
+void
+buf_LRU_free_one_page(
+/*==================*/
+ buf_page_t* bpage) /*!< in/out: block, must contain a file page and
+ be in a state where it can be freed; there
+ may or may not be a hash index to the page */
+ __attribute__((nonnull));
+
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/**********************************************************************//**
Validates the LRU list.
@@ -254,18 +255,15 @@ buf_LRU_print(void);
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
/** @name Heuristics for detecting index scan @{ */
-/** Reserve this much/BUF_LRU_OLD_RATIO_DIV of the buffer pool for
-"old" blocks. Protected by buf_pool->mutex. */
-extern uint buf_LRU_old_ratio;
-/** The denominator of buf_LRU_old_ratio. */
+/** The denominator of buf_pool->LRU_old_ratio. */
#define BUF_LRU_OLD_RATIO_DIV 1024
-/** Maximum value of buf_LRU_old_ratio.
+/** Maximum value of buf_pool->LRU_old_ratio.
@see buf_LRU_old_adjust_len
-@see buf_LRU_old_ratio_update */
+@see buf_pool->LRU_old_ratio_update */
#define BUF_LRU_OLD_RATIO_MAX BUF_LRU_OLD_RATIO_DIV
-/** Minimum value of buf_LRU_old_ratio.
+/** Minimum value of buf_pool->LRU_old_ratio.
@see buf_LRU_old_adjust_len
-@see buf_LRU_old_ratio_update
+@see buf_pool->LRU_old_ratio_update
The minimum must exceed
(BUF_LRU_OLD_TOLERANCE + 5) * BUF_LRU_OLD_RATIO_DIV / BUF_LRU_OLD_MIN_LEN. */
#define BUF_LRU_OLD_RATIO_MIN 51
diff --git a/storage/xtradb/include/buf0rea.h b/storage/xtradb/include/buf0rea.h
index 4910c1e2aca..dedd1904d31 100644
--- a/storage/xtradb/include/buf0rea.h
+++ b/storage/xtradb/include/buf0rea.h
@@ -76,6 +76,32 @@ buf_read_page(
ulint offset, /*!< in: page number */
trx_t* trx);
/********************************************************************//**
+Applies a random read-ahead in buf_pool if there are at least a threshold
+value of accessed pages from the random read-ahead area. Does not read any
+page, not even the one at the position (space, offset), if the read-ahead
+mechanism is not activated. NOTE 1: the calling thread may own latches on
+pages: to avoid deadlocks this function must be written such that it cannot
+end up waiting for these latches! NOTE 2: the calling thread must want
+access to the page given: this rule is set to prevent unintended read-aheads
+performed by ibuf routines, a situation which could result in a deadlock if
+the OS does not support asynchronous i/o.
+@return number of page read requests issued; NOTE that if we read ibuf
+pages, it may happen that the page at the given page number does not
+get read even if we return a positive value!
+@return number of page read requests issued */
+UNIV_INTERN
+ulint
+buf_read_ahead_random(
+/*==================*/
+ ulint space, /*!< in: space id */
+ ulint zip_size, /*!< in: compressed page size in bytes,
+ or 0 */
+ ulint offset, /*!< in: page number of a page which
+ the current thread wants to access */
+ ibool inside_ibuf, /*!< in: TRUE if we are inside ibuf
+ routine */
+ trx_t* trx);
+/********************************************************************//**
Applies linear read-ahead if in the buf_pool the page is a border page of
a linear read-ahead area and all the pages in the area have been accessed.
Does not read any page if the read-ahead mechanism is not activated. Note
diff --git a/storage/xtradb/include/buf0types.h b/storage/xtradb/include/buf0types.h
index 888be86e332..156093aad01 100644
--- a/storage/xtradb/include/buf0types.h
+++ b/storage/xtradb/include/buf0types.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -26,6 +26,8 @@ Created 11/17/1995 Heikki Tuuri
#ifndef buf0types_h
#define buf0types_h
+#include "page0types.h"
+
/** Buffer page (uncompressed or compressed) */
typedef struct buf_page_struct buf_page_t;
/** Buffer block for which an uncompressed page exists */
@@ -60,17 +62,10 @@ enum buf_io_fix {
/** Parameters of binary buddy system for compressed pages (buf0buddy.h) */
/* @{ */
-#if UNIV_WORD_SIZE <= 4 /* 32-bit system */
-/** Base-2 logarithm of the smallest buddy block size */
-# define BUF_BUDDY_LOW_SHIFT 6
-#else /* 64-bit system */
-/** Base-2 logarithm of the smallest buddy block size */
-# define BUF_BUDDY_LOW_SHIFT 7
-#endif
+#define BUF_BUDDY_LOW_SHIFT PAGE_ZIP_MIN_SIZE_SHIFT
+
#define BUF_BUDDY_LOW (1 << BUF_BUDDY_LOW_SHIFT)
- /*!< minimum block size in the binary
- buddy system; must be at least
- sizeof(buf_page_t) */
+
#define BUF_BUDDY_SIZES (UNIV_PAGE_SIZE_SHIFT - BUF_BUDDY_LOW_SHIFT)
#define BUF_BUDDY_SIZES_MAX (UNIV_PAGE_SIZE_SHIFT_MAX - BUF_BUDDY_LOW_SHIFT)
/*!< number of buddy sizes */
diff --git a/storage/xtradb/include/db0err.h b/storage/xtradb/include/db0err.h
index 18ff74a025e..7048341b31e 100644
--- a/storage/xtradb/include/db0err.h
+++ b/storage/xtradb/include/db0err.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -64,8 +64,6 @@ enum db_err {
DB_CANNOT_ADD_CONSTRAINT, /* adding a foreign key constraint
to a table failed */
DB_CORRUPTION, /* data structure corruption noticed */
- DB_COL_APPEARS_TWICE_IN_INDEX, /* InnoDB cannot handle an index
- where same column appears twice */
DB_CANNOT_DROP_CONSTRAINT, /* dropping a foreign key constraint
from a table failed */
DB_NO_SAVEPOINT, /* no savepoint exists with the given
@@ -112,6 +110,8 @@ enum db_err {
foreign keys as its prefix columns */
DB_TOO_BIG_INDEX_COL, /* index column size exceeds maximum
limit */
+ DB_INDEX_CORRUPT, /* we have corrupted index */
+ DB_UNDO_RECORD_TOO_BIG, /* the undo log record is too big */
/* The following are partial failure codes */
DB_FAIL = 1000,
diff --git a/storage/xtradb/include/dict0boot.h b/storage/xtradb/include/dict0boot.h
index c8a09ca7de4..a817775c93c 100644
--- a/storage/xtradb/include/dict0boot.h
+++ b/storage/xtradb/include/dict0boot.h
@@ -141,8 +141,10 @@ dict_create(void);
#define DICT_HDR_XTRADB_MARK 256 /* Flag to distinguish expansion of XtraDB */
/*-------------------------------------------------------------*/
-/* The field number of the page number field in the sys_indexes table
-clustered index */
+/* The field numbers in the SYS_TABLES clustered index */
+#define DICT_SYS_TABLES_TYPE_FIELD 5
+
+/* The field numbers in the SYS_INDEXES clustered index */
#define DICT_SYS_INDEXES_PAGE_NO_FIELD 8
#define DICT_SYS_INDEXES_SPACE_NO_FIELD 7
#define DICT_SYS_INDEXES_TYPE_FIELD 6
diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h
index 28d4413b568..8af806c3572 100644
--- a/storage/xtradb/include/dict0dict.h
+++ b/storage/xtradb/include/dict0dict.h
@@ -585,6 +585,20 @@ dict_table_get_next_index(
# define dict_table_get_next_index(index) UT_LIST_GET_NEXT(indexes, index)
#endif /* UNIV_DEBUG */
#endif /* !UNIV_HOTBACKUP */
+
+/* Skip corrupted index */
+#define dict_table_skip_corrupt_index(index) \
+ while (index && dict_index_is_corrupted(index)) { \
+ index = dict_table_get_next_index(index); \
+ }
+
+/* Get the next non-corrupt index */
+#define dict_table_next_uncorrupted_index(index) \
+do { \
+ index = dict_table_get_next_index(index); \
+ dict_table_skip_corrupt_index(index); \
+} while (0)
+
/********************************************************************//**
Check whether the index is the clustered index.
@return nonzero for clustered index, zero for other indexes */
@@ -593,7 +607,7 @@ ulint
dict_index_is_clust(
/*================*/
const dict_index_t* index) /*!< in: index */
- __attribute__((pure));
+ __attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Check whether the index is unique.
@return nonzero for unique index, zero for other indexes */
@@ -602,7 +616,7 @@ ulint
dict_index_is_unique(
/*=================*/
const dict_index_t* index) /*!< in: index */
- __attribute__((pure));
+ __attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Check whether the index is the insert buffer tree.
@return nonzero for insert buffer, zero for other indexes */
@@ -611,7 +625,7 @@ ulint
dict_index_is_ibuf(
/*===============*/
const dict_index_t* index) /*!< in: index */
- __attribute__((pure));
+ __attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Check whether the index is a secondary index or the insert buffer tree.
@return nonzero for insert buffer, zero for other indexes */
@@ -620,7 +634,7 @@ ulint
dict_index_is_sec_or_ibuf(
/*======================*/
const dict_index_t* index) /*!< in: index */
- __attribute__((pure));
+ __attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Gets the number of user-defined columns in a table in the dictionary
@@ -630,7 +644,8 @@ UNIV_INLINE
ulint
dict_table_get_n_user_cols(
/*=======================*/
- const dict_table_t* table); /*!< in: table */
+ const dict_table_t* table) /*!< in: table */
+ __attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Gets the number of system columns in a table in the dictionary cache.
@return number of system (e.g., ROW_ID) columns of a table */
@@ -638,7 +653,8 @@ UNIV_INLINE
ulint
dict_table_get_n_sys_cols(
/*======================*/
- const dict_table_t* table); /*!< in: table */
+ const dict_table_t* table) /*!< in: table */
+ __attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Gets the number of all columns (also system) in a table in the dictionary
cache.
@@ -647,7 +663,8 @@ UNIV_INLINE
ulint
dict_table_get_n_cols(
/*==================*/
- const dict_table_t* table); /*!< in: table */
+ const dict_table_t* table) /*!< in: table */
+ __attribute__((nonnull, pure, warn_unused_result));
#ifdef UNIV_DEBUG
/********************************************************************//**
Gets the nth column of a table.
@@ -1270,6 +1287,57 @@ void
dict_close(void);
/*============*/
+/**********************************************************************//**
+Check whether the table is corrupted.
+@return nonzero for corrupted table, zero for valid tables */
+UNIV_INLINE
+ulint
+dict_table_is_corrupted(
+/*====================*/
+ const dict_table_t* table) /*!< in: table */
+ __attribute__((nonnull, pure, warn_unused_result));
+
+/**********************************************************************//**
+Check whether the index is corrupted.
+@return nonzero for corrupted index, zero for valid indexes */
+UNIV_INLINE
+ulint
+dict_index_is_corrupted(
+/*====================*/
+ const dict_index_t* index) /*!< in: index */
+ __attribute__((nonnull, pure, warn_unused_result));
+
+/**********************************************************************//**
+Flags an index and table corrupted both in the data dictionary cache
+and in the system table SYS_INDEXES. */
+UNIV_INTERN
+void
+dict_set_corrupted(
+/*===============*/
+ dict_index_t* index) /*!< in/out: index */
+ UNIV_COLD __attribute__((nonnull));
+
+/**********************************************************************//**
+Flags an index corrupted in the data dictionary cache only. This
+is used mostly to mark a corrupted index when index's own dictionary
+is corrupted, and we force to load such index for repair purpose */
+UNIV_INTERN
+void
+dict_set_corrupted_index_cache_only(
+/*================================*/
+ dict_index_t* index, /*!< in/out: index */
+ dict_table_t* table); /*!< in/out: table */
+
+/**********************************************************************//**
+Flags a table with specified space_id corrupted in the table dictionary
+cache.
+@return TRUE if successful */
+UNIV_INTERN
+ibool
+dict_set_corrupted_by_space(
+/*========================*/
+ ulint space_id); /*!< in: space ID */
+
/*************************************************************************
set is_corrupt flag by space_id*/
diff --git a/storage/xtradb/include/dict0dict.ic b/storage/xtradb/include/dict0dict.ic
index 4ec82220ffb..b10deddd28f 100644
--- a/storage/xtradb/include/dict0dict.ic
+++ b/storage/xtradb/include/dict0dict.ic
@@ -27,6 +27,7 @@ Created 1/8/1996 Heikki Tuuri
#ifndef UNIV_HOTBACKUP
#include "dict0load.h"
#include "rem0types.h"
+#include "srv0srv.h"
/*********************************************************************//**
Gets the minimum number of bytes per character.
@@ -849,7 +850,7 @@ dict_table_check_if_in_cache_low(
}
/**********************************************************************//**
-load a table into dictionary cache, ignore any error specified during load;
+load a table into dictionary cache, ignore any error specified during load;
@return table, NULL if not found */
UNIV_INLINE
dict_table_t*
@@ -893,6 +894,18 @@ dict_table_get_low(
table = dict_table_check_if_in_cache_low(table_name);
+ if (table && table->corrupted) {
+ fprintf(stderr, "InnoDB: table");
+ ut_print_name(stderr, NULL, TRUE, table->name);
+ if (srv_load_corrupted) {
+ fputs(" is corrupted, but"
+ " innodb_force_load_corrupted is set\n", stderr);
+ } else {
+ fputs(" is corrupted\n", stderr);
+ return(NULL);
+ }
+ }
+
if (table == NULL) {
table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE);
}
@@ -964,4 +977,35 @@ dict_max_field_len_store_undo(
return(prefix_len);
}
+/********************************************************************//**
+Check whether the table is corrupted.
+@return nonzero for corrupted table, zero for valid tables */
+UNIV_INLINE
+ulint
+dict_table_is_corrupted(
+/*====================*/
+ const dict_table_t* table) /*!< in: table */
+{
+ ut_ad(table);
+ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
+
+ return(UNIV_UNLIKELY(table->corrupted));
+}
+
+/********************************************************************//**
+Check whether the index is corrupted.
+@return nonzero for corrupted index, zero for valid indexes */
+UNIV_INLINE
+ulint
+dict_index_is_corrupted(
+/*====================*/
+ const dict_index_t* index) /*!< in: index */
+{
+ ut_ad(index);
+ ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
+
+ return(UNIV_UNLIKELY((index->type & DICT_CORRUPT)
+ || (index->table && index->table->corrupted)));
+}
+
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h
index 71af9ce2f0c..4701fcd87f9 100644
--- a/storage/xtradb/include/dict0mem.h
+++ b/storage/xtradb/include/dict0mem.h
@@ -51,7 +51,12 @@ combination of types */
#define DICT_UNIQUE 2 /*!< unique index */
#define DICT_UNIVERSAL 4 /*!< index which can contain records from any
other index */
-#define DICT_IBUF 8 /*!< insert buffer tree */
+#define DICT_IBUF 8 /*!< insert buffer tree */
+#define DICT_CORRUPT 16 /*!< bit to store the corrupted flag
+ in SYS_INDEXES.TYPE */
+
+#define DICT_IT_BITS 5 /*!< number of bits used for
+ SYS_INDEXES.TYPE */
/* @} */
/** Types for a table object */
@@ -369,8 +374,9 @@ struct dict_index_struct{
/*!< space where the index tree is placed */
unsigned page:32;/*!< index tree root page number */
#endif /* !UNIV_HOTBACKUP */
- unsigned type:4; /*!< index type (DICT_CLUSTERED, DICT_UNIQUE,
- DICT_UNIVERSAL, DICT_IBUF) */
+ unsigned type:DICT_IT_BITS;
+ /*!< index type (DICT_CLUSTERED, DICT_UNIQUE,
+ DICT_UNIVERSAL, DICT_IBUF, DICT_CORRUPT) */
unsigned trx_id_offset:10;/*!< position of the trx id column
in a clustered index record, if the fields
before it are known to be of a fixed size,
@@ -391,8 +397,6 @@ struct dict_index_struct{
/*!< TRUE if this index is marked to be
dropped in ha_innobase::prepare_drop_index(),
otherwise FALSE */
- unsigned corrupted:1;
- /*!< TRUE if the index object is corrupted */
dict_field_t* fields; /*!< array of field descriptions */
#ifndef UNIV_HOTBACKUP
UT_LIST_NODE_T(dict_index_t)
diff --git a/storage/xtradb/include/dict0types.h b/storage/xtradb/include/dict0types.h
index 8cbd7cd5783..f0a05a38070 100644
--- a/storage/xtradb/include/dict0types.h
+++ b/storage/xtradb/include/dict0types.h
@@ -51,7 +51,8 @@ be or-ed together */
enum dict_err_ignore {
DICT_ERR_IGNORE_NONE = 0, /*!< no error to ignore */
DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root
- page is FIL_NUL or incorrect value */
+ page is FIL_NULL or incorrect value */
+ DICT_ERR_IGNORE_CORRUPT = 2, /*!< skip corrupted indexes */
DICT_ERR_IGNORE_ALL = 0xFFFF /*!< ignore all errors */
};
diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h
index 61ec644796b..2ec0861c837 100644
--- a/storage/xtradb/include/ha_prototypes.h
+++ b/storage/xtradb/include/ha_prototypes.h
@@ -312,4 +312,5 @@ ulint
innobase_get_lower_case_table_names(void);
/*=====================================*/
+
#endif
diff --git a/storage/xtradb/include/mtr0mtr.h b/storage/xtradb/include/mtr0mtr.h
index 5582ad63039..7f608546cc2 100644
--- a/storage/xtradb/include/mtr0mtr.h
+++ b/storage/xtradb/include/mtr0mtr.h
@@ -213,16 +213,6 @@ ulint
mtr_set_savepoint(
/*==============*/
mtr_t* mtr); /*!< in: mtr */
-/**********************************************************//**
-Releases the latches stored in an mtr memo down to a savepoint.
-NOTE! The mtr must not have made changes to buffer pages after the
-savepoint, as these can be handled only by mtr_commit. */
-UNIV_INTERN
-void
-mtr_rollback_to_savepoint(
-/*======================*/
- mtr_t* mtr, /*!< in: mtr */
- ulint savepoint); /*!< in: savepoint */
#ifndef UNIV_HOTBACKUP
/**********************************************************//**
Releases the (index tree) s-latch stored in an mtr memo after a
diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h
index c476d14d51d..b153b0dba7f 100644
--- a/storage/xtradb/include/os0file.h
+++ b/storage/xtradb/include/os0file.h
@@ -290,7 +290,8 @@ The wrapper functions have the prefix of "innodb_". */
__FILE__, __LINE__)
# define os_file_read_trx(file, buf, offset, offset_high, n, trx) \
- os_file_read_func(file, buf, offset, offset_high, n, trx)
+ pfs_os_file_read_func(file, buf, offset, offset_high, n, trx, \
+ __FILE__, __LINE__)
# define os_file_read_no_error_handling(file, buf, offset, \
offset_high, n) \
diff --git a/storage/xtradb/include/page0page.h b/storage/xtradb/include/page0page.h
index c06815cb6ca..c1c659e2b70 100644
--- a/storage/xtradb/include/page0page.h
+++ b/storage/xtradb/include/page0page.h
@@ -68,10 +68,7 @@ typedef byte page_header_t;
#define PAGE_MAX_TRX_ID 18 /* highest id of a trx which may have modified
a record on the page; trx_id_t; defined only
in secondary indexes and in the insert buffer
- tree; NOTE: this may be modified only
- when the thread has an x-latch to the page,
- and ALSO an x-latch to btr_search_latch
- if there is a hash index to the page! */
+ tree */
#define PAGE_HEADER_PRIV_END 26 /* end of private data structure of the page
header which are set in a page create */
/*----*/
diff --git a/storage/xtradb/include/row0row.h b/storage/xtradb/include/row0row.h
index 75e15d67246..c2849be7c3e 100644
--- a/storage/xtradb/include/row0row.h
+++ b/storage/xtradb/include/row0row.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -38,27 +38,16 @@ Created 4/20/1996 Heikki Tuuri
#include "btr0types.h"
/*********************************************************************//**
-Gets the offset of the trx id field, in bytes relative to the origin of
+Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of
a clustered index record.
@return offset of DATA_TRX_ID */
UNIV_INLINE
ulint
-row_get_trx_id_offset_func(
-/*=======================*/
-#ifdef UNIV_DEBUG
- const rec_t* rec, /*!< in: record */
-#endif /* UNIV_DEBUG */
+row_get_trx_id_offset(
+/*==================*/
const dict_index_t* index, /*!< in: clustered index */
- const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
+ const ulint* offsets)/*!< in: record offsets */
__attribute__((nonnull, warn_unused_result));
-#ifdef UNIV_DEBUG
-# define row_get_trx_id_offset(rec, index, offsets) \
- row_get_trx_id_offset_func(rec, index, offsets)
-#else /* UNIV_DEBUG */
-# define row_get_trx_id_offset(rec, index, offsets) \
- row_get_trx_id_offset_func(index, offsets)
-#endif /* UNIV_DEBUG */
-
/*********************************************************************//**
Reads the trx id field from a clustered index record.
@return value of the field */
@@ -77,9 +66,10 @@ UNIV_INLINE
roll_ptr_t
row_get_rec_roll_ptr(
/*=================*/
- const rec_t* rec, /*!< in: record */
- dict_index_t* index, /*!< in: clustered index */
- const ulint* offsets);/*!< in: rec_get_offsets(rec, index) */
+ const rec_t* rec, /*!< in: record */
+ const dict_index_t* index, /*!< in: clustered index */
+ const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
+ __attribute__((nonnull, warn_unused_result));
/*****************************************************************//**
When an insert or purge to a table is performed, this function builds
the entry to be inserted into or purged from an index on the table.
diff --git a/storage/xtradb/include/row0row.ic b/storage/xtradb/include/row0row.ic
index 9d19e430e16..0b9ca982af8 100644
--- a/storage/xtradb/include/row0row.ic
+++ b/storage/xtradb/include/row0row.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -28,25 +28,22 @@ Created 4/20/1996 Heikki Tuuri
#include "trx0undo.h"
/*********************************************************************//**
-Gets the offset of trx id field, in bytes relative to the origin of
+Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of
a clustered index record.
@return offset of DATA_TRX_ID */
UNIV_INLINE
ulint
-row_get_trx_id_offset_func(
-/*=======================*/
-#ifdef UNIV_DEBUG
- const rec_t* rec, /*!< in: record */
-#endif /* UNIV_DEBUG */
+row_get_trx_id_offset(
+/*==================*/
const dict_index_t* index, /*!< in: clustered index */
- const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
+ const ulint* offsets)/*!< in: record offsets */
{
ulint pos;
ulint offset;
ulint len;
ut_ad(dict_index_is_clust(index));
- ut_ad(rec_offs_validate(rec, index, offsets));
+ ut_ad(rec_offs_validate(NULL, index, offsets));
pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
@@ -76,7 +73,7 @@ row_get_rec_trx_id(
offset = index->trx_id_offset;
if (!offset) {
- offset = row_get_trx_id_offset(rec, index, offsets);
+ offset = row_get_trx_id_offset(index, offsets);
}
return(trx_read_trx_id(rec + offset));
@@ -89,9 +86,9 @@ UNIV_INLINE
roll_ptr_t
row_get_rec_roll_ptr(
/*=================*/
- const rec_t* rec, /*!< in: record */
- dict_index_t* index, /*!< in: clustered index */
- const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
+ const rec_t* rec, /*!< in: record */
+ const dict_index_t* index, /*!< in: clustered index */
+ const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
{
ulint offset;
@@ -101,7 +98,7 @@ row_get_rec_roll_ptr(
offset = index->trx_id_offset;
if (!offset) {
- offset = row_get_trx_id_offset(rec, index, offsets);
+ offset = row_get_trx_id_offset(index, offsets);
}
return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN));
diff --git a/storage/xtradb/include/row0upd.ic b/storage/xtradb/include/row0upd.ic
index 2968a548b34..11db82f64da 100644
--- a/storage/xtradb/include/row0upd.ic
+++ b/storage/xtradb/include/row0upd.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -157,11 +157,6 @@ row_upd_rec_sys_fields(
{
ut_ad(dict_index_is_clust(index));
ut_ad(rec_offs_validate(rec, index, offsets));
-#ifdef UNIV_SYNC_DEBUG
- if (!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX)) {
- ut_ad(!buf_block_align(rec)->is_hashed);
- }
-#endif /* UNIV_SYNC_DEBUG */
if (UNIV_LIKELY_NULL(page_zip)) {
ulint pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
@@ -171,7 +166,7 @@ row_upd_rec_sys_fields(
ulint offset = index->trx_id_offset;
if (!offset) {
- offset = row_get_trx_id_offset(rec, index, offsets);
+ offset = row_get_trx_id_offset(index, offsets);
}
#if DATA_TRX_ID + 1 != DATA_ROLL_PTR
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index 2de0ed190ab..daa0fc3b428 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -152,6 +152,10 @@ extern ulint srv_log_buffer_size;
extern char srv_use_global_flush_log_at_trx_commit;
extern char srv_adaptive_flushing;
+/* If this flag is TRUE, then we will load the indexes' (and tables') metadata
+even if they are marked as "corrupted". Mostly it is for DBA to process
+corrupted index and table */
+extern my_bool srv_load_corrupted;
extern ulong srv_show_locks_held;
extern ulong srv_show_verbose_locks;
@@ -174,6 +178,7 @@ extern ulint srv_lock_table_size;
extern ibool srv_thread_concurrency_timer_based;
extern ulint srv_n_file_io_threads;
+extern my_bool srv_random_read_ahead;
extern ulong srv_read_ahead_threshold;
extern ulint srv_n_read_io_threads;
extern ulint srv_n_write_io_threads;
@@ -294,6 +299,7 @@ extern ibool srv_print_latch_waits;
extern ulint srv_activity_count;
extern ulint srv_fatal_semaphore_wait_threshold;
extern ulint srv_dml_needed_delay;
+extern lint srv_kill_idle_transaction;
extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
query threads, and lock table: we allocate
@@ -368,6 +374,9 @@ extern ulint srv_buf_pool_reads;
/** Time in seconds between automatic buffer pool dumps */
extern uint srv_auto_lru_dump;
+/** Whether startup should be blocked until buffer pool is fully restored */
+extern ibool srv_blocking_lru_restore;
+
/** Status variables to be passed to MySQL */
typedef struct export_var_struct export_struc;
@@ -765,6 +774,7 @@ struct export_var_struct{
ulint innodb_buffer_pool_pages_flushed; /*!< srv_buf_pool_flushed */
ulint innodb_buffer_pool_pages_LRU_flushed; /*!< buf_lru_flush_page_count */
ulint innodb_buffer_pool_write_requests;/*!< srv_buf_pool_write_requests */
+ ulint innodb_buffer_pool_read_ahead_rnd;/*!< srv_read_ahead_rnd */
ulint innodb_buffer_pool_read_ahead; /*!< srv_read_ahead */
ulint innodb_buffer_pool_read_ahead_evicted;/*!< srv_read_ahead evicted*/
ulint innodb_checkpoint_age;
diff --git a/storage/xtradb/include/sync0sync.h b/storage/xtradb/include/sync0sync.h
index 2418162aca1..6440a670f14 100644
--- a/storage/xtradb/include/sync0sync.h
+++ b/storage/xtradb/include/sync0sync.h
@@ -640,10 +640,6 @@ or row lock! */
#define SYNC_DICT_HEADER 995
#define SYNC_IBUF_HEADER 914
#define SYNC_IBUF_PESS_INSERT_MUTEX 912
-#define SYNC_IBUF_MUTEX 910 /* ibuf mutex is really below
- SYNC_FSP_PAGE: we assign a value this
- high only to make the program to pass
- the debug checks */
/*-------------------------------*/
#define SYNC_INDEX_TREE 900
#define SYNC_TREE_NODE_NEW 892
@@ -659,8 +655,11 @@ or row lock! */
#define SYNC_FSP 400
#define SYNC_FSP_PAGE 395
/*------------------------------------- Insert buffer headers */
-/*------------------------------------- ibuf_mutex */
+#define SYNC_IBUF_MUTEX 370 /* ibuf_mutex */
/*------------------------------------- Insert buffer tree */
+#define SYNC_IBUF_INDEX_TREE 360
+#define SYNC_IBUF_TREE_NODE_NEW 359
+#define SYNC_IBUF_TREE_NODE 358
#define SYNC_IBUF_BITMAP_MUTEX 351
#define SYNC_IBUF_BITMAP 350
/*------------------------------------- MySQL query cache mutex */
@@ -693,7 +692,6 @@ or row lock! */
#define SYNC_DOUBLEWRITE 140
#define SYNC_OUTER_ANY_LATCH 136
#define SYNC_ANY_LATCH 135
-#define SYNC_THR_LOCAL 133
#define SYNC_MEM_HASH 131
#define SYNC_MEM_POOL 130
diff --git a/storage/xtradb/include/sync0sync.ic b/storage/xtradb/include/sync0sync.ic
index 1d9c8d59b12..aa54226be5d 100644
--- a/storage/xtradb/include/sync0sync.ic
+++ b/storage/xtradb/include/sync0sync.ic
@@ -272,11 +272,10 @@ pfs_mutex_enter_nowait_func(
ulint ret;
struct PSI_mutex_locker* locker = NULL;
PSI_mutex_locker_state state;
- int result = 0;
if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) {
locker = PSI_server->get_thread_mutex_locker(
- &state, mutex->pfs_psi, PSI_MUTEX_LOCK);
+ &state, mutex->pfs_psi, PSI_MUTEX_TRYLOCK);
if (locker) {
PSI_server->start_mutex_wait(locker, file_name, line);
}
@@ -285,7 +284,7 @@ pfs_mutex_enter_nowait_func(
ret = mutex_enter_nowait_func(mutex, file_name, line);
if (locker) {
- PSI_server->end_mutex_wait(locker, result);
+ PSI_server->end_mutex_wait(locker, ret);
}
return(ret);
diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h
index db7bf68deae..495ce0e1184 100644
--- a/storage/xtradb/include/trx0sys.h
+++ b/storage/xtradb/include/trx0sys.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -304,6 +304,17 @@ ibool
trx_in_trx_list(
/*============*/
trx_t* in_trx);/*!< in: trx */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/***********************************************************//**
+Assert that a transaction has been recovered.
+@return TRUE */
+UNIV_INLINE
+ibool
+trx_assert_recovered(
+/*=================*/
+ trx_id_t trx_id) /*!< in: transaction identifier */
+ __attribute__((warn_unused_result));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/*****************************************************************//**
Updates the offset information about the end of the MySQL binlog entry
which corresponds to the transaction just being committed. In a MySQL
diff --git a/storage/xtradb/include/trx0sys.ic b/storage/xtradb/include/trx0sys.ic
index aa2d2ea26b0..af05ab2f5ed 100644
--- a/storage/xtradb/include/trx0sys.ic
+++ b/storage/xtradb/include/trx0sys.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -311,6 +311,28 @@ trx_get_on_id(
return(NULL);
}
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/***********************************************************//**
+Assert that a transaction has been recovered.
+@return TRUE */
+UNIV_INLINE
+ibool
+trx_assert_recovered(
+/*=================*/
+ trx_id_t trx_id) /*!< in: transaction identifier */
+{
+ trx_t* trx;
+
+ mutex_enter(&kernel_mutex);
+ trx = trx_get_on_id(trx_id);
+ ut_a(trx);
+ ut_a(trx->is_recovered);
+ mutex_exit(&kernel_mutex);
+
+ return(TRUE);
+}
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
/****************************************************************//**
Returns the minumum trx id in trx list. This is the smallest id for which
the trx can possibly be active. (But, you must look at the trx->conc_state to
diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h
index 4d3ef8f3e57..a03f7aceafa 100644
--- a/storage/xtradb/include/trx0trx.h
+++ b/storage/xtradb/include/trx0trx.h
@@ -512,6 +512,7 @@ struct trx_struct{
FALSE, one can save CPU time and about
150 bytes in the undo log size as then
we skip XA steps */
+ ulint fake_changes;
ulint flush_log_later;/* In 2PC, we hold the
prepare_commit mutex across
both phases. In that case, we
@@ -594,6 +595,8 @@ struct trx_struct{
replication has processed */
const char* mysql_relay_log_file_name;
ib_int64_t mysql_relay_log_pos;
+ time_t idle_start;
+ ib_int64_t last_stmt_start;
/*------------------------------*/
ulint n_mysql_tables_in_use; /* number of Innobase tables
used in the processing of the current
diff --git a/storage/xtradb/include/trx0undo.h b/storage/xtradb/include/trx0undo.h
index df16c939070..50aa6d0ac09 100644
--- a/storage/xtradb/include/trx0undo.h
+++ b/storage/xtradb/include/trx0undo.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -204,17 +204,51 @@ trx_undo_add_page(
mtr_t* mtr); /*!< in: mtr which does not have a latch to any
undo log page; the caller must have reserved
the rollback segment mutex */
+/********************************************************************//**
+Frees the last undo log page.
+The caller must hold the rollback segment mutex. */
+UNIV_INTERN
+void
+trx_undo_free_last_page_func(
+/*==========================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction */
+#endif /* UNIV_DEBUG */
+ trx_undo_t* undo, /*!< in/out: undo log memory copy */
+ mtr_t* mtr) /*!< in/out: mini-transaction which does not
+ have a latch to any undo log page or which
+ has allocated the undo log page */
+ __attribute__((nonnull));
+#ifdef UNIV_DEBUG
+# define trx_undo_free_last_page(trx,undo,mtr) \
+ trx_undo_free_last_page_func(trx,undo,mtr)
+#else /* UNIV_DEBUG */
+# define trx_undo_free_last_page(trx,undo,mtr) \
+ trx_undo_free_last_page_func(undo,mtr)
+#endif /* UNIV_DEBUG */
+
/***********************************************************************//**
Truncates an undo log from the end. This function is used during a rollback
to free space from an undo log. */
UNIV_INTERN
void
-trx_undo_truncate_end(
-/*==================*/
- trx_t* trx, /*!< in: transaction whose undo log it is */
- trx_undo_t* undo, /*!< in: undo log */
- undo_no_t limit); /*!< in: all undo records with undo number
+trx_undo_truncate_end_func(
+/*=======================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction whose undo log it is */
+#endif /* UNIV_DEBUG */
+ trx_undo_t* undo, /*!< in/out: undo log */
+ undo_no_t limit) /*!< in: all undo records with undo number
>= this value should be truncated */
+ __attribute__((nonnull));
+#ifdef UNIV_DEBUG
+# define trx_undo_truncate_end(trx,undo,limit) \
+ trx_undo_truncate_end_func(trx,undo,limit)
+#else /* UNIV_DEBUG */
+# define trx_undo_truncate_end(trx,undo,limit) \
+ trx_undo_truncate_end_func(undo,limit)
+#endif /* UNIV_DEBUG */
+
/***********************************************************************//**
Truncates an undo log from the start. This function is used during a purge
operation. */
diff --git a/storage/xtradb/include/ut0mem.h b/storage/xtradb/include/ut0mem.h
index 57dfb08f41c..faf6f242883 100644
--- a/storage/xtradb/include/ut0mem.h
+++ b/storage/xtradb/include/ut0mem.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -210,43 +210,6 @@ ut_strlcpy_rev(
ulint size); /*!< in: size of destination buffer */
/**********************************************************************//**
-Compute strlen(ut_strcpyq(str, q)).
-@return length of the string when quoted */
-UNIV_INLINE
-ulint
-ut_strlenq(
-/*=======*/
- const char* str, /*!< in: null-terminated string */
- char q); /*!< in: the quote character */
-
-/**********************************************************************//**
-Make a quoted copy of a NUL-terminated string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_memcpyq().
-@return pointer to end of dest */
-UNIV_INTERN
-char*
-ut_strcpyq(
-/*=======*/
- char* dest, /*!< in: output buffer */
- char q, /*!< in: the quote character */
- const char* src); /*!< in: null-terminated string */
-
-/**********************************************************************//**
-Make a quoted copy of a fixed-length string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_strcpyq().
-@return pointer to end of dest */
-UNIV_INTERN
-char*
-ut_memcpyq(
-/*=======*/
- char* dest, /*!< in: output buffer */
- char q, /*!< in: the quote character */
- const char* src, /*!< in: string to be quoted */
- ulint len); /*!< in: length of src */
-
-/**********************************************************************//**
Return the number of times s2 occurs in s1. Overlapping instances of s2
are only counted once.
@return the number of times s2 occurs in s1 */
diff --git a/storage/xtradb/include/ut0mem.ic b/storage/xtradb/include/ut0mem.ic
index f36c28f1989..c06e2b3ae81 100644
--- a/storage/xtradb/include/ut0mem.ic
+++ b/storage/xtradb/include/ut0mem.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -99,27 +99,6 @@ ut_strcmp(const char* str1, const char* str2)
}
/**********************************************************************//**
-Compute strlen(ut_strcpyq(str, q)).
-@return length of the string when quoted */
-UNIV_INLINE
-ulint
-ut_strlenq(
-/*=======*/
- const char* str, /*!< in: null-terminated string */
- char q) /*!< in: the quote character */
-{
- ulint len;
-
- for (len = 0; *str; len++, str++) {
- if (*str == q) {
- len++;
- }
- }
-
- return(len);
-}
-
-/**********************************************************************//**
Converts a raw binary data to a NUL-terminated hex string. The output is
truncated if there is not enough space in "hex", make sure "hex_size" is at
least (2 * raw_size + 1) if you do not want this to happen. Returns the
diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c
index 0fcbee32454..5fce345d0fe 100644
--- a/storage/xtradb/lock/lock0lock.c
+++ b/storage/xtradb/lock/lock0lock.c
@@ -3912,6 +3912,10 @@ lock_table(
trx = thr_get_trx(thr);
+ if (trx->fake_changes && mode == LOCK_IX) {
+ mode = LOCK_IS;
+ }
+
lock_mutex_enter_kernel();
/* Look for stronger locks the same trx already has on the table */
@@ -5114,6 +5118,11 @@ lock_rec_insert_check_and_lock(
}
trx = thr_get_trx(thr);
+
+ if (trx->fake_changes) {
+ return(DB_SUCCESS);
+ }
+
next_rec = page_rec_get_next_const(rec);
next_rec_heap_no = page_rec_get_heap_no(next_rec);
@@ -5282,6 +5291,10 @@ lock_clust_rec_modify_check_and_lock(
return(DB_SUCCESS);
}
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ return(DB_SUCCESS);
+ }
+
heap_no = rec_offs_comp(offsets)
? rec_get_heap_no_new(rec)
: rec_get_heap_no_old(rec);
@@ -5340,6 +5353,10 @@ lock_sec_rec_modify_check_and_lock(
return(DB_SUCCESS);
}
+ if (thr && thr_get_trx(thr)->fake_changes) {
+ return(DB_SUCCESS);
+ }
+
heap_no = page_rec_get_heap_no(rec);
/* Another transaction cannot have an implicit lock on the record,
@@ -5427,6 +5444,10 @@ lock_sec_rec_read_check_and_lock(
return(DB_SUCCESS);
}
+ if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
+ mode = LOCK_S;
+ }
+
heap_no = page_rec_get_heap_no(rec);
lock_mutex_enter_kernel();
@@ -5503,6 +5524,10 @@ lock_clust_rec_read_check_and_lock(
return(DB_SUCCESS);
}
+ if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
+ mode = LOCK_S;
+ }
+
heap_no = page_rec_get_heap_no(rec);
lock_mutex_enter_kernel();
diff --git a/storage/xtradb/mtr/mtr0mtr.c b/storage/xtradb/mtr/mtr0mtr.c
index 5c946ebd756..529af43d2e0 100644
--- a/storage/xtradb/mtr/mtr0mtr.c
+++ b/storage/xtradb/mtr/mtr0mtr.c
@@ -283,44 +283,6 @@ mtr_commit(
}
#ifndef UNIV_HOTBACKUP
-/**********************************************************//**
-Releases the latches stored in an mtr memo down to a savepoint.
-NOTE! The mtr must not have made changes to buffer pages after the
-savepoint, as these can be handled only by mtr_commit. */
-UNIV_INTERN
-void
-mtr_rollback_to_savepoint(
-/*======================*/
- mtr_t* mtr, /*!< in: mtr */
- ulint savepoint) /*!< in: savepoint */
-{
- mtr_memo_slot_t* slot;
- dyn_array_t* memo;
- ulint offset;
-
- ut_ad(mtr);
- ut_ad(mtr->magic_n == MTR_MAGIC_N);
- ut_ad(mtr->state == MTR_ACTIVE);
-
- memo = &(mtr->memo);
-
- offset = dyn_array_get_data_size(memo);
- ut_ad(offset >= savepoint);
-
- while (offset > savepoint) {
- offset -= sizeof(mtr_memo_slot_t);
-
- slot = dyn_array_get_element(memo, offset);
-
- ut_ad(slot->type != MTR_MEMO_MODIFY);
-
- /* We do not call mtr_memo_slot_note_modification()
- because there MUST be no changes made to the buffer
- pages after the savepoint */
- mtr_memo_slot_release(mtr, slot);
- }
-}
-
/***************************************************//**
Releases an object in the memo stack. */
UNIV_INTERN
diff --git a/storage/xtradb/page/page0zip.c b/storage/xtradb/page/page0zip.c
index b81cba4826a..fc9f30ed94e 100644
--- a/storage/xtradb/page/page0zip.c
+++ b/storage/xtradb/page/page0zip.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 2005, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -151,6 +151,20 @@ page_zip_empty_size(
#endif /* !UNIV_HOTBACKUP */
/*************************************************************//**
+Gets the number of elements in the dense page directory,
+including deleted records (the free list).
+@return number of elements in the dense page directory */
+UNIV_INLINE
+ulint
+page_zip_dir_elems(
+/*===============*/
+ const page_zip_des_t* page_zip) /*!< in: compressed page */
+{
+ /* Exclude the page infimum and supremum from the record count. */
+ return(page_dir_get_n_heap(page_zip->data) - PAGE_HEAP_NO_USER_LOW);
+}
+
+/*************************************************************//**
Gets the size of the compressed page trailer (the dense page directory),
including deleted records (the free list).
@return length of dense page directory, in bytes */
@@ -160,14 +174,42 @@ page_zip_dir_size(
/*==============*/
const page_zip_des_t* page_zip) /*!< in: compressed page */
{
- /* Exclude the page infimum and supremum from the record count. */
- ulint size = PAGE_ZIP_DIR_SLOT_SIZE
- * (page_dir_get_n_heap(page_zip->data)
- - PAGE_HEAP_NO_USER_LOW);
- return(size);
+ return(PAGE_ZIP_DIR_SLOT_SIZE * page_zip_dir_elems(page_zip));
+}
+
+/*************************************************************//**
+Gets an offset to the compressed page trailer (the dense page directory),
+including deleted records (the free list).
+@return offset of the dense page directory */
+UNIV_INLINE
+ulint
+page_zip_dir_start_offs(
+/*====================*/
+ const page_zip_des_t* page_zip, /*!< in: compressed page */
+ ulint n_dense) /*!< in: directory size */
+{
+ ut_ad(n_dense * PAGE_ZIP_DIR_SLOT_SIZE < page_zip_get_size(page_zip));
+
+ return(page_zip_get_size(page_zip) - n_dense * PAGE_ZIP_DIR_SLOT_SIZE);
}
/*************************************************************//**
+Gets a pointer to the compressed page trailer (the dense page directory),
+including deleted records (the free list).
+@param[in] page_zip compressed page
+@param[in] n_dense number of entries in the directory
+@return pointer to the dense page directory */
+#define page_zip_dir_start_low(page_zip, n_dense) \
+ ((page_zip)->data + page_zip_dir_start_offs(page_zip, n_dense))
+/*************************************************************//**
+Gets a pointer to the compressed page trailer (the dense page directory),
+including deleted records (the free list).
+@param[in] page_zip compressed page
+@return pointer to the dense page directory */
+#define page_zip_dir_start(page_zip) \
+ page_zip_dir_start_low(page_zip, page_zip_dir_elems(page_zip))
+
+/*************************************************************//**
Gets the size of the compressed page trailer (the dense page directory),
only including user records (excluding the free list).
@return length of dense page directory comprising existing records, in bytes */
@@ -2246,8 +2288,7 @@ zlib_done:
}
/* Restore the uncompressed columns in heap_no order. */
- storage = page_zip->data + page_zip_get_size(page_zip)
- - n_dense * PAGE_ZIP_DIR_SLOT_SIZE;
+ storage = page_zip_dir_start_low(page_zip, n_dense);
for (slot = 0; slot < n_dense; slot++) {
rec_t* rec = recs[slot];
@@ -2732,8 +2773,7 @@ zlib_done:
return(FALSE);
}
- storage = page_zip->data + page_zip_get_size(page_zip)
- - n_dense * PAGE_ZIP_DIR_SLOT_SIZE;
+ storage = page_zip_dir_start_low(page_zip, n_dense);
externs = storage - n_dense
* (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
@@ -3461,9 +3501,7 @@ page_zip_write_rec(
}
/* Write the data bytes. Store the uncompressed bytes separately. */
- storage = page_zip->data + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE;
+ storage = page_zip_dir_start(page_zip);
if (page_is_leaf(page)) {
ulint len;
@@ -3759,9 +3797,7 @@ corrupt:
field = page + offset;
storage = page_zip->data + z_offset;
- storage_end = page_zip->data + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE;
+ storage_end = page_zip_dir_start(page_zip);
heap_no = 1 + (storage_end - storage) / REC_NODE_PTR_SIZE;
@@ -3797,7 +3833,9 @@ page_zip_write_node_ptr(
{
byte* field;
byte* storage;
+#ifdef UNIV_DEBUG
page_t* page = page_align(rec);
+#endif /* UNIV_DEBUG */
ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
ut_ad(page_simple_validate_new(page));
@@ -3814,9 +3852,7 @@ page_zip_write_node_ptr(
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
UNIV_MEM_ASSERT_RW(rec, size);
- storage = page_zip->data + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE
+ storage = page_zip_dir_start(page_zip)
- (rec_get_heap_no_new(rec) - 1) * REC_NODE_PTR_SIZE;
field = rec + size - REC_NODE_PTR_SIZE;
@@ -3865,7 +3901,9 @@ page_zip_write_trx_id_and_roll_ptr(
{
byte* field;
byte* storage;
+#ifdef UNIV_DEBUG
page_t* page = page_align(rec);
+#endif /* UNIV_DEBUG */
ulint len;
ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
@@ -3883,9 +3921,7 @@ page_zip_write_trx_id_and_roll_ptr(
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
- storage = page_zip->data + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE
+ storage = page_zip_dir_start(page_zip)
- (rec_get_heap_no_new(rec) - 1)
* (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
@@ -3916,17 +3952,9 @@ page_zip_write_trx_id_and_roll_ptr(
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
}
-#ifdef UNIV_ZIP_DEBUG
-/** Set this variable in a debugger to disable page_zip_clear_rec().
-The only observable effect should be the compression ratio due to
-deleted records not being zeroed out. In rare cases, there can be
-page_zip_validate() failures on the node_ptr, trx_id and roll_ptr
-columns if the space is reallocated for a smaller record. */
-UNIV_INTERN ibool page_zip_clear_rec_disable;
-#endif /* UNIV_ZIP_DEBUG */
-
/**********************************************************************//**
-Clear an area on the uncompressed and compressed page, if possible. */
+Clear an area on the uncompressed and compressed page.
+Do not clear the data payload, as that would grow the modification log. */
static
void
page_zip_clear_rec(
@@ -3938,6 +3966,9 @@ page_zip_clear_rec(
{
ulint heap_no;
page_t* page = page_align(rec);
+ byte* storage;
+ byte* field;
+ ulint len;
/* page_zip_validate() would fail here if a record
containing externally stored columns is being deleted. */
ut_ad(rec_offs_validate(rec, index, offsets));
@@ -3953,60 +3984,38 @@ page_zip_clear_rec(
UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
rec_offs_extra_size(offsets));
- if (
-#ifdef UNIV_ZIP_DEBUG
- !page_zip_clear_rec_disable &&
-#endif /* UNIV_ZIP_DEBUG */
- page_zip->m_end
- + 1 + ((heap_no - 1) >= 64)/* size of the log entry */
- + page_zip_get_trailer_len(page_zip,
- dict_index_is_clust(index), NULL)
- < page_zip_get_size(page_zip)) {
- byte* data;
-
- /* Clear only the data bytes, because the allocator and
- the decompressor depend on the extra bytes. */
- memset(rec, 0, rec_offs_data_size(offsets));
-
- if (!page_is_leaf(page)) {
- /* Clear node_ptr on the compressed page. */
- byte* storage = page_zip->data
- + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page)
- - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE;
-
- memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE,
- 0, REC_NODE_PTR_SIZE);
- } else if (dict_index_is_clust(index)) {
- /* Clear trx_id and roll_ptr on the compressed page. */
- byte* storage = page_zip->data
- + page_zip_get_size(page_zip)
- - (page_dir_get_n_heap(page)
- - PAGE_HEAP_NO_USER_LOW)
- * PAGE_ZIP_DIR_SLOT_SIZE;
-
- memset(storage - (heap_no - 1)
- * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
- 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
- }
+ if (!page_is_leaf(page)) {
+ /* Clear node_ptr. On the compressed page,
+ there is an array of node_ptr immediately before the
+ dense page directory, at the very end of the page. */
+ storage = page_zip_dir_start(page_zip);
+ ut_ad(dict_index_get_n_unique_in_tree(index) ==
+ rec_offs_n_fields(offsets) - 1);
+ field = rec_get_nth_field(rec, offsets,
+ rec_offs_n_fields(offsets) - 1,
+ &len);
+ ut_ad(len == REC_NODE_PTR_SIZE);
- /* Log that the data was zeroed out. */
- data = page_zip->data + page_zip->m_end;
- ut_ad(!*data);
- if (UNIV_UNLIKELY(heap_no - 1 >= 64)) {
- *data++ = (byte) (0x80 | (heap_no - 1) >> 7);
- ut_ad(!*data);
- }
- *data++ = (byte) ((heap_no - 1) << 1 | 1);
- ut_ad(!*data);
- ut_ad((ulint) (data - page_zip->data)
- < page_zip_get_size(page_zip));
- page_zip->m_end = data - page_zip->data;
- page_zip->m_nonempty = TRUE;
- } else if (page_is_leaf(page) && dict_index_is_clust(index)) {
- /* Do not clear the record, because there is not enough space
- to log the operation. */
+ ut_ad(!rec_offs_any_extern(offsets));
+ memset(field, 0, REC_NODE_PTR_SIZE);
+ memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE,
+ 0, REC_NODE_PTR_SIZE);
+ } else if (dict_index_is_clust(index)) {
+ /* Clear trx_id and roll_ptr. On the compressed page,
+ there is an array of these fields immediately before the
+ dense page directory, at the very end of the page. */
+ const ulint trx_id_pos
+ = dict_col_get_clust_pos(
+ dict_table_get_sys_col(
+ index->table, DATA_TRX_ID), index);
+ storage = page_zip_dir_start(page_zip);
+ field = rec_get_nth_field(rec, offsets, trx_id_pos, &len);
+ ut_ad(len == DATA_TRX_ID_LEN);
+
+ memset(field, 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
+ memset(storage - (heap_no - 1)
+ * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
+ 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
if (rec_offs_any_extern(offsets)) {
ulint i;
@@ -4015,15 +4024,18 @@ page_zip_clear_rec(
/* Clear all BLOB pointers in order to make
page_zip_validate() pass. */
if (rec_offs_nth_extern(offsets, i)) {
- ulint len;
- byte* field = rec_get_nth_field(
+ field = rec_get_nth_field(
rec, offsets, i, &len);
+ ut_ad(len
+ == BTR_EXTERN_FIELD_REF_SIZE);
memset(field + len
- BTR_EXTERN_FIELD_REF_SIZE,
0, BTR_EXTERN_FIELD_REF_SIZE);
}
}
}
+ } else {
+ ut_ad(!rec_offs_any_extern(offsets));
}
#ifdef UNIV_ZIP_DEBUG
diff --git a/storage/xtradb/pars/pars0opt.c b/storage/xtradb/pars/pars0opt.c
index 2e392ba4836..d992805d9ef 100644
--- a/storage/xtradb/pars/pars0opt.c
+++ b/storage/xtradb/pars/pars0opt.c
@@ -568,7 +568,7 @@ opt_search_plan_for_table(
best_last_op = last_op;
}
- index = dict_table_get_next_index(index);
+ dict_table_next_uncorrupted_index(index);
}
plan->index = best_index;
diff --git a/storage/xtradb/que/que0que.c b/storage/xtradb/que/que0que.c
index d704e0cd1fc..0d13491f25a 100644
--- a/storage/xtradb/que/que0que.c
+++ b/storage/xtradb/que/que0que.c
@@ -1417,6 +1417,12 @@ que_eval_sql(
ut_a(trx->error_state == DB_SUCCESS);
+ if (trx->fake_changes) {
+ /* fake_changes should not access to system tables */
+ fprintf(stderr, "InnoDB: ERROR: innodb_fake_changes tried to access to system tables.\n");
+ return(DB_ERROR);
+ }
+
if (reserve_dict_mutex) {
mutex_enter(&dict_sys->mutex);
}
diff --git a/storage/xtradb/rem/rem0rec.c b/storage/xtradb/rem/rem0rec.c
index 5a96e608ab5..30fc28561fa 100644
--- a/storage/xtradb/rem/rem0rec.c
+++ b/storage/xtradb/rem/rem0rec.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -408,7 +408,7 @@ rec_init_offsets(
do {
ulint len;
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
- len = offs += 4;
+ len = offs += REC_NODE_PTR_SIZE;
goto resolved;
}
@@ -640,7 +640,7 @@ rec_get_offsets_reverse(
do {
ulint len;
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
- len = offs += 4;
+ len = offs += REC_NODE_PTR_SIZE;
goto resolved;
}
@@ -1131,9 +1131,9 @@ rec_convert_dtuple_to_rec_comp(
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
- ut_ad(len == 4);
+ ut_ad(len == REC_NODE_PTR_SIZE);
memcpy(end, dfield_get_data(field), len);
- end += 4;
+ end += REC_NODE_PTR_SIZE;
break;
}
diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c
index b4e66a16b5f..da035421ab9 100644
--- a/storage/xtradb/row/row0ins.c
+++ b/storage/xtradb/row/row0ins.c
@@ -118,6 +118,9 @@ ins_node_create_entry_list(
node->entry_sys_heap);
UT_LIST_ADD_LAST(tuple_list, node->entry_list, entry);
+ /* We will include all indexes (include those corrupted
+ secondary indexes) in the entry list. Filteration of
+ these corrupted index will be done in row_ins() */
index = dict_table_get_next_index(index);
}
}
@@ -1499,6 +1502,11 @@ exit_func:
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
+
+ if (trx->fake_changes) {
+ err = DB_SUCCESS;
+ }
+
return(err);
}
@@ -2004,7 +2012,7 @@ row_ins_index_entry_low(
}
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
- search_mode,
+ thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : search_mode,
&cursor, 0, __FILE__, __LINE__, &mtr);
if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
@@ -2053,7 +2061,6 @@ row_ins_index_entry_low(
mtr_start(&mtr);
if (err != DB_SUCCESS) {
-
goto function_exit;
}
@@ -2065,7 +2072,7 @@ row_ins_index_entry_low(
btr_cur_search_to_nth_level(index, 0, entry,
PAGE_CUR_LE,
- mode | BTR_INSERT,
+ thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT),
&cursor, 0,
__FILE__, __LINE__, &mtr);
}
@@ -2119,6 +2126,22 @@ function_exit:
if (UNIV_LIKELY_NULL(big_rec)) {
rec_t* rec;
ulint* offsets;
+
+ if (thr_get_trx(thr)->fake_changes) {
+ /* skip store extern */
+ if (modify) {
+ dtuple_big_rec_free(big_rec);
+ } else {
+ dtuple_convert_back_big_rec(index, entry, big_rec);
+ }
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+
+ return(err);
+ }
+
mtr_start(&mtr);
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
@@ -2403,6 +2426,13 @@ row_ins(
node->index = dict_table_get_next_index(node->index);
node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry);
+
+ /* Skip corrupted secondar index and its entry */
+ while (node->index && dict_index_is_corrupted(node->index)) {
+
+ node->index = dict_table_get_next_index(node->index);
+ node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry);
+ }
}
ut_ad(node->entry == NULL);
diff --git a/storage/xtradb/row/row0merge.c b/storage/xtradb/row/row0merge.c
index 7d4716cb623..30cfa7c23af 100644
--- a/storage/xtradb/row/row0merge.c
+++ b/storage/xtradb/row/row0merge.c
@@ -56,6 +56,7 @@ Completed by Sunny Bains and Marko Makela
#include "log0log.h"
#include "ut0sort.h"
#include "handler0alter.h"
+#include "ha_prototypes.h"
/* Ignore posix_fadvise() on those platforms where it does not exist */
#if defined __WIN__
@@ -2563,8 +2564,9 @@ row_merge_is_index_usable(
const trx_t* trx, /*!< in: transaction */
const dict_index_t* index) /*!< in: index to check */
{
- return(!trx->read_view
- || read_view_sees_trx_id(trx->read_view, index->trx_id));
+ return(!dict_index_is_corrupted(index)
+ && (!trx->read_view
+ || read_view_sees_trx_id(trx->read_view, index->trx_id)));
}
/*********************************************************************//**
diff --git a/storage/xtradb/row/row0mysql.c b/storage/xtradb/row/row0mysql.c
index 836189e0eb8..ac424ded6cb 100644
--- a/storage/xtradb/row/row0mysql.c
+++ b/storage/xtradb/row/row0mysql.c
@@ -578,6 +578,7 @@ handle_new_error:
case DB_DUPLICATE_KEY:
case DB_FOREIGN_DUPLICATE_KEY:
case DB_TOO_BIG_RECORD:
+ case DB_UNDO_RECORD_TOO_BIG:
case DB_ROW_IS_REFERENCED:
case DB_NO_REFERENCED_ROW:
case DB_CANNOT_ADD_CONSTRAINT:
@@ -1246,6 +1247,7 @@ run_again:
prebuilt->table->stat_n_rows--;
}
+ if (!(trx->fake_changes))
row_update_statistics_if_needed(prebuilt->table);
trx->op_info = "";
@@ -1505,6 +1507,7 @@ run_again:
that changes indexed columns, UPDATEs that change only non-indexed
columns would not affect statistics. */
if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
+ if (!(trx->fake_changes))
row_update_statistics_if_needed(prebuilt->table);
}
@@ -1722,6 +1725,7 @@ run_again:
srv_n_rows_updated++;
}
+ if (!(trx->fake_changes))
row_update_statistics_if_needed(table);
return(err);
@@ -2027,41 +2031,13 @@ row_create_index_for_mysql(
trx_start_if_not_started(trx);
- /* Check that the same column does not appear twice in the index.
- Starting from 4.0.14, InnoDB should be able to cope with that, but
- safer not to allow them. */
-
- for (i = 0; i < dict_index_get_n_fields(index); i++) {
- ulint j;
-
- for (j = 0; j < i; j++) {
- if (0 == ut_strcmp(
- dict_index_get_nth_field(index, j)->name,
- dict_index_get_nth_field(index, i)->name)) {
- ut_print_timestamp(stderr);
-
- fputs(" InnoDB: Error: column ", stderr);
- ut_print_name(stderr, trx, FALSE,
- dict_index_get_nth_field(
- index, i)->name);
- fputs(" appears twice in ", stderr);
- dict_index_name_print(stderr, trx, index);
- fputs("\n"
- "InnoDB: This is not allowed"
- " in InnoDB.\n", stderr);
-
- err = DB_COL_APPEARS_TWICE_IN_INDEX;
-
- goto error_handling;
- }
- }
-
- /* Check also that prefix_len and actual length
- is less than that from DICT_MAX_FIELD_LEN_BY_FORMAT() */
+ for (i = 0; i < index->n_def; i++) {
+ /* Check that prefix_len and actual length
+ < DICT_MAX_INDEX_COL_LEN */
len = dict_index_get_nth_field(index, i)->prefix_len;
- if (field_lengths) {
+ if (field_lengths && field_lengths[i]) {
len = ut_max(len, field_lengths[i]);
}
@@ -2069,6 +2045,7 @@ row_create_index_for_mysql(
if (len > (ulint) DICT_MAX_FIELD_LEN_BY_FORMAT(table)) {
err = DB_TOO_BIG_INDEX_COL;
+ dict_mem_index_free(index);
goto error_handling;
}
}
@@ -2611,10 +2588,29 @@ row_discard_tablespace_for_mysql(
err = DB_ERROR;
} else {
+ dict_index_t* index;
+
/* Set the flag which tells that now it is legal to
IMPORT a tablespace for this table */
table->tablespace_discarded = TRUE;
table->ibd_file_missing = TRUE;
+
+ /* check adaptive hash entries */
+ index = dict_table_get_first_index(table);
+ while (index) {
+ ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
+ if (ref_count) {
+ fprintf(stderr, "InnoDB: Warning:"
+ " hash index ref_count (%lu) is not zero"
+ " after fil_discard_tablespace().\n"
+ "index: \"%s\""
+ " table: \"%s\"\n",
+ ref_count,
+ index->name,
+ table->name);
+ }
+ index = dict_table_get_next_index(index);
+ }
}
}
@@ -2963,6 +2959,19 @@ row_truncate_table_for_mysql(
table->space = space;
index = dict_table_get_first_index(table);
do {
+ ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
+ /* check adaptive hash entries */
+ if (ref_count) {
+ fprintf(stderr, "InnoDB: Warning:"
+ " hash index ref_count (%lu) is not zero"
+ " after fil_discard_tablespace().\n"
+ "index: \"%s\""
+ " table: \"%s\"\n",
+ ref_count,
+ index->name,
+ table->name);
+ }
+
index->space = space;
index = dict_table_get_next_index(index);
} while (index);
@@ -3212,7 +3221,8 @@ row_drop_table_for_mysql(
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- table = dict_table_get_low_ignore_err(name, DICT_ERR_IGNORE_INDEX_ROOT);
+ table = dict_table_get_low_ignore_err(
+ name, DICT_ERR_IGNORE_INDEX_ROOT | DICT_ERR_IGNORE_CORRUPT);
if (!table) {
err = DB_TABLE_NOT_FOUND;
@@ -3359,6 +3369,19 @@ check_next_foreign:
"index_id CHAR;\n"
"foreign_id CHAR;\n"
"found INT;\n"
+
+ "DECLARE CURSOR cur_fk IS\n"
+ "SELECT ID FROM SYS_FOREIGN\n"
+ "WHERE FOR_NAME = :table_name\n"
+ "AND TO_BINARY(FOR_NAME)\n"
+ " = TO_BINARY(:table_name)\n"
+ "LOCK IN SHARE MODE;\n"
+
+ "DECLARE CURSOR cur_idx IS\n"
+ "SELECT ID FROM SYS_INDEXES\n"
+ "WHERE TABLE_ID = table_id\n"
+ "LOCK IN SHARE MODE;\n"
+
"BEGIN\n"
"SELECT ID INTO table_id\n"
"FROM SYS_TABLES\n"
@@ -3381,13 +3404,9 @@ check_next_foreign:
"IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n"
" found := 0;\n"
"END IF;\n"
+ "OPEN cur_fk;\n"
"WHILE found = 1 LOOP\n"
- " SELECT ID INTO foreign_id\n"
- " FROM SYS_FOREIGN\n"
- " WHERE FOR_NAME = :table_name\n"
- " AND TO_BINARY(FOR_NAME)\n"
- " = TO_BINARY(:table_name)\n"
- " LOCK IN SHARE MODE;\n"
+ " FETCH cur_fk INTO foreign_id;\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
@@ -3397,12 +3416,11 @@ check_next_foreign:
" WHERE ID = foreign_id;\n"
" END IF;\n"
"END LOOP;\n"
+ "CLOSE cur_fk;\n"
"found := 1;\n"
+ "OPEN cur_idx;\n"
"WHILE found = 1 LOOP\n"
- " SELECT ID INTO index_id\n"
- " FROM SYS_INDEXES\n"
- " WHERE TABLE_ID = table_id\n"
- " LOCK IN SHARE MODE;\n"
+ " FETCH cur_idx INTO index_id;\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
@@ -3415,6 +3433,7 @@ check_next_foreign:
" AND TABLE_ID = table_id;\n"
" END IF;\n"
"END LOOP;\n"
+ "CLOSE cur_idx;\n"
"DELETE FROM SYS_COLUMNS\n"
"WHERE TABLE_ID = table_id;\n"
"DELETE FROM SYS_TABLES\n"
diff --git a/storage/xtradb/row/row0purge.c b/storage/xtradb/row/row0purge.c
index 83e7c9e4857..efcfdc3bac5 100644
--- a/storage/xtradb/row/row0purge.c
+++ b/storage/xtradb/row/row0purge.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ 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
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -469,6 +469,13 @@ row_purge_del_mark(
heap = mem_heap_create(1024);
while (node->index != NULL) {
+ /* skip corrupted secondary index */
+ dict_table_skip_corrupt_index(node->index);
+
+ if (!node->index) {
+ break;
+ }
+
index = node->index;
/* Build the index entry */
@@ -508,7 +515,8 @@ row_purge_upd_exist_or_extern_func(
ut_ad(node);
- if (node->rec_type == TRX_UNDO_UPD_DEL_REC) {
+ if (node->rec_type == TRX_UNDO_UPD_DEL_REC
+ || (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
goto skip_secondaries;
}
@@ -516,6 +524,12 @@ row_purge_upd_exist_or_extern_func(
heap = mem_heap_create(1024);
while (node->index != NULL) {
+ dict_table_skip_corrupt_index(node->index);
+
+ if (!node->index) {
+ break;
+ }
+
index = node->index;
if (row_upd_changes_ord_field_binary(node->index, node->update,
@@ -632,14 +646,14 @@ row_purge_parse_undo_rec(
roll_ptr_t roll_ptr;
ulint info_bits;
ulint type;
- ulint cmpl_info;
ut_ad(node && thr);
trx = thr_get_trx(thr);
- ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
- updated_extern, &undo_no, &table_id);
+ ptr = trx_undo_rec_get_pars(
+ node->undo_rec, &type, &node->cmpl_info,
+ updated_extern, &undo_no, &table_id);
node->rec_type = type;
if (type == TRX_UNDO_UPD_DEL_REC && !(*updated_extern)) {
@@ -652,7 +666,8 @@ row_purge_parse_undo_rec(
node->table = NULL;
if (type == TRX_UNDO_UPD_EXIST_REC
- && cmpl_info & UPD_NODE_NO_ORD_CHANGE && !(*updated_extern)) {
+ && node->cmpl_info & UPD_NODE_NO_ORD_CHANGE
+ && !(*updated_extern)) {
/* Purge requires no changes to indexes: we may return */
@@ -702,7 +717,7 @@ err_exit:
/* Read to the partial row the fields that occur in indexes */
- if (!(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
+ if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
ptr = trx_undo_rec_get_partial_row(
ptr, clust_index, &node->row,
type == TRX_UNDO_UPD_DEL_REC,
diff --git a/storage/xtradb/row/row0row.c b/storage/xtradb/row/row0row.c
index 2882af00f30..0462f280858 100644
--- a/storage/xtradb/row/row0row.c
+++ b/storage/xtradb/row/row0row.c
@@ -101,12 +101,27 @@ row_build_index_entry(
dfield_copy(dfield, dfield2);
- if (dfield_is_null(dfield) || ind_field->prefix_len == 0) {
+ if (dfield_is_null(dfield)) {
continue;
}
- /* If a column prefix index, take only the prefix.
- Prefix-indexed columns may be externally stored. */
+ if (ind_field->prefix_len == 0
+ && (!dfield_is_ext(dfield)
+ || dict_index_is_clust(index))) {
+ /* The dfield_copy() above suffices for
+ columns that are stored in-page, or for
+ clustered index record columns that are not
+ part of a column prefix in the PRIMARY KEY. */
+ continue;
+ }
+
+ /* If the column is stored externally (off-page) in
+ the clustered index, it must be an ordering field in
+ the secondary index. In the Antelope format, only
+ prefix-indexed columns may be stored off-page in the
+ clustered index record. In the Barracuda format, also
+ fully indexed long CHAR or VARCHAR columns may be
+ stored off-page. */
ut_ad(col->ord_part);
if (UNIV_LIKELY_NULL(ext)) {
@@ -119,15 +134,41 @@ row_build_index_entry(
}
dfield_set_data(dfield, buf, len);
}
+
+ if (ind_field->prefix_len == 0) {
+ /* In the Barracuda format
+ (ROW_FORMAT=DYNAMIC or
+ ROW_FORMAT=COMPRESSED), we can have a
+ secondary index on an entire column
+ that is stored off-page in the
+ clustered index. As this is not a
+ prefix index (prefix_len == 0),
+ include the entire off-page column in
+ the secondary index record. */
+ continue;
+ }
} else if (dfield_is_ext(dfield)) {
+ /* This table is either in Antelope format
+ (ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPACT)
+ or a purge record where the ordered part of
+ the field is not external.
+ In Antelope, the maximum column prefix
+ index length is 767 bytes, and the clustered
+ index record contains a 768-byte prefix of
+ each off-page column. */
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
len -= BTR_EXTERN_FIELD_REF_SIZE;
+ dfield_set_len(dfield, len);
}
- len = dtype_get_at_most_n_mbchars(
- col->prtype, col->mbminmaxlen,
- ind_field->prefix_len, len, dfield_get_data(dfield));
- dfield_set_len(dfield, len);
+ /* If a column prefix index, take only the prefix. */
+ if (ind_field->prefix_len) {
+ len = dtype_get_at_most_n_mbchars(
+ col->prtype, col->mbminmaxlen,
+ ind_field->prefix_len, len,
+ dfield_get_data(dfield));
+ dfield_set_len(dfield, len);
+ }
}
ut_ad(dtuple_check_typed(entry));
diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c
index ef5e30ea16d..c7308ccb765 100644
--- a/storage/xtradb/row/row0sel.c
+++ b/storage/xtradb/row/row0sel.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -101,14 +101,22 @@ row_sel_sec_rec_is_for_blob(
ulint clust_len, /*!< in: length of clust_field */
const byte* sec_field, /*!< in: column in secondary index */
ulint sec_len, /*!< in: length of sec_field */
+ ulint prefix_len, /*!< in: index column prefix length
+ in bytes */
dict_table_t* table) /*!< in: table */
{
ulint len;
byte buf[REC_VERSION_56_MAX_INDEX_COL_LEN];
ulint zip_size = dict_table_flags_to_zip_size(table->flags);
- ulint max_prefix_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table);
+ /* This function should never be invoked on an Antelope format
+ table, because they should always contain enough prefix in the
+ clustered index record. */
+ ut_ad(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE);
+ ut_ad(prefix_len >= sec_len);
+ ut_ad(prefix_len > 0);
+ ut_a(prefix_len <= sizeof buf);
if (UNIV_UNLIKELY
(!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE,
@@ -120,7 +128,7 @@ row_sel_sec_rec_is_for_blob(
return(FALSE);
}
- len = btr_copy_externally_stored_field_prefix(buf, max_prefix_len,
+ len = btr_copy_externally_stored_field_prefix(buf, prefix_len,
zip_size,
clust_field, clust_len);
@@ -134,7 +142,7 @@ row_sel_sec_rec_is_for_blob(
}
len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen,
- sec_len, len, (const char*) buf);
+ prefix_len, len, (const char*) buf);
return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
}
@@ -226,6 +234,7 @@ row_sel_sec_rec_is_for_clust_rec(
col->mbminmaxlen,
clust_field, clust_len,
sec_field, sec_len,
+ ifield->prefix_len,
clust_index->table)) {
goto inequal;
}
@@ -495,7 +504,7 @@ sel_col_prefetch_buf_alloc(
sel_buf = column->prefetch_buf + i;
sel_buf->data = NULL;
-
+ sel_buf->len = 0;
sel_buf->val_buf_size = 0;
}
}
@@ -520,6 +529,8 @@ sel_col_prefetch_buf_free(
mem_free(sel_buf->data);
}
}
+
+ mem_free(prefetch_buf);
}
/*********************************************************************//**
@@ -2543,6 +2554,8 @@ row_sel_field_store_in_mysql_format(
ut_ad(len != UNIV_SQL_NULL);
UNIV_MEM_ASSERT_RW(data, len);
+ UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len);
+ UNIV_MEM_INVALID(dest, templ->mysql_col_len);
switch (templ->type) {
const byte* field_end;
@@ -2581,14 +2594,16 @@ row_sel_field_store_in_mysql_format(
dest = row_mysql_store_true_var_len(
dest, len, templ->mysql_length_bytes);
+ /* Copy the actual data. Leave the rest of the
+ buffer uninitialized. */
+ memcpy(dest, data, len);
+ break;
}
/* Copy the actual data */
ut_memcpy(dest, data, len);
- /* Pad with trailing spaces. We pad with spaces also the
- unused end of a >= 5.0.3 true VARCHAR column, just in case
- MySQL expects its contents to be deterministic. */
+ /* Pad with trailing spaces. */
pad = dest + len;
@@ -3148,6 +3163,39 @@ sel_restore_position_for_mysql(
}
/********************************************************************//**
+Copies a cached field for MySQL from the fetch cache. */
+static
+void
+row_sel_copy_cached_field_for_mysql(
+/*================================*/
+ byte* buf, /*!< in/out: row buffer */
+ const byte* cache, /*!< in: cached row */
+ const mysql_row_templ_t*templ) /*!< in: column template */
+{
+ ulint len;
+
+ buf += templ->mysql_col_offset;
+ cache += templ->mysql_col_offset;
+
+ UNIV_MEM_ASSERT_W(buf, templ->mysql_col_len);
+
+ if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR
+ && templ->type != DATA_INT) {
+ /* Check for != DATA_INT to make sure we do
+ not treat MySQL ENUM or SET as a true VARCHAR!
+ Find the actual length of the true VARCHAR field. */
+ row_mysql_read_true_varchar(
+ &len, cache, templ->mysql_length_bytes);
+ len += templ->mysql_length_bytes;
+ UNIV_MEM_INVALID(buf, templ->mysql_col_len);
+ } else {
+ len = templ->mysql_col_len;
+ }
+
+ ut_memcpy(buf, cache, len);
+}
+
+/********************************************************************//**
Pops a cached row for MySQL from the fetch cache. */
UNIV_INLINE
void
@@ -3159,26 +3207,22 @@ row_sel_pop_cached_row_for_mysql(
{
ulint i;
const mysql_row_templ_t*templ;
- byte* cached_rec;
+ const byte* cached_rec;
ut_ad(prebuilt->n_fetch_cached > 0);
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
+ UNIV_MEM_ASSERT_W(buf, prebuilt->mysql_row_len);
+
+ cached_rec = prebuilt->fetch_cache[prebuilt->fetch_cache_first];
+
if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) {
/* Copy cache record field by field, don't touch fields that
are not covered by current key */
- cached_rec = prebuilt->fetch_cache[
- prebuilt->fetch_cache_first];
for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i;
-#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
- UNIV_MEM_ASSERT_RW(cached_rec
- + templ->mysql_col_offset,
- templ->mysql_col_len);
-#endif
- ut_memcpy(buf + templ->mysql_col_offset,
- cached_rec + templ->mysql_col_offset,
- templ->mysql_col_len);
+ row_sel_copy_cached_field_for_mysql(
+ buf, cached_rec, templ);
/* Copy NULL bit of the current field from cached_rec
to buf */
if (templ->mysql_null_bit_mask) {
@@ -3192,17 +3236,24 @@ row_sel_pop_cached_row_for_mysql(
templ->mysql_null_bit_mask;
}
}
+ } else if (prebuilt->mysql_prefix_len > 63) {
+ /* The record is long. Copy it field by field, in case
+ there are some long VARCHAR column of which only a
+ small length is being used. */
+ UNIV_MEM_INVALID(buf, prebuilt->mysql_prefix_len);
+
+ /* First copy the NULL bits. */
+ ut_memcpy(buf, cached_rec, prebuilt->null_bitmap_len);
+ /* Then copy the requested fields. */
+
+ for (i = 0; i < prebuilt->n_template; i++) {
+ row_sel_copy_cached_field_for_mysql(
+ buf, cached_rec, prebuilt->mysql_template + i);
+ }
+ } else {
+ ut_memcpy(buf, cached_rec, prebuilt->mysql_prefix_len);
}
- else {
-#if 0 /* Some of the cached_rec may legitimately be uninitialized. */
- UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache
- [prebuilt->fetch_cache_first],
- prebuilt->mysql_prefix_len);
-#endif
- ut_memcpy(buf,
- prebuilt->fetch_cache[prebuilt->fetch_cache_first],
- prebuilt->mysql_prefix_len);
- }
+
prebuilt->n_fetch_cached--;
prebuilt->fetch_cache_first++;
@@ -3510,6 +3561,13 @@ row_search_for_mysql(
return(DB_MISSING_HISTORY);
}
+ if (dict_index_is_corrupted(index)) {
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
+#endif /* UNIV_SYNC_DEBUG */
+ return(DB_CORRUPTION);
+ }
+
if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"
diff --git a/storage/xtradb/row/row0uins.c b/storage/xtradb/row/row0uins.c
index d25afed3840..4fa97c9355d 100644
--- a/storage/xtradb/row/row0uins.c
+++ b/storage/xtradb/row/row0uins.c
@@ -328,6 +328,8 @@ row_undo_ins(
node->index = dict_table_get_next_index(
dict_table_get_first_index(node->table));
+ dict_table_skip_corrupt_index(node->index);
+
while (node->index != NULL) {
dtuple_t* entry;
ulint err;
@@ -355,7 +357,7 @@ row_undo_ins(
}
}
- node->index = dict_table_get_next_index(node->index);
+ dict_table_next_uncorrupted_index(node->index);
}
log_free_check();
diff --git a/storage/xtradb/row/row0umod.c b/storage/xtradb/row/row0umod.c
index 2188fdeff49..b86ce9eeabd 100644
--- a/storage/xtradb/row/row0umod.c
+++ b/storage/xtradb/row/row0umod.c
@@ -573,6 +573,14 @@ row_undo_mod_upd_del_sec(
heap = mem_heap_create(1024);
while (node->index != NULL) {
+
+ /* Skip all corrupted secondary index */
+ dict_table_skip_corrupt_index(node->index);
+
+ if (!node->index) {
+ break;
+ }
+
index = node->index;
entry = row_build_index_entry(node->row, node->ext,
@@ -626,6 +634,13 @@ row_undo_mod_del_mark_sec(
heap = mem_heap_create(1024);
while (node->index != NULL) {
+ /* Skip all corrupted secondary index */
+ dict_table_skip_corrupt_index(node->index);
+
+ if (!node->index) {
+ break;
+ }
+
index = node->index;
entry = row_build_index_entry(node->row, node->ext,
@@ -677,6 +692,13 @@ row_undo_mod_upd_exist_sec(
heap = mem_heap_create(1024);
while (node->index != NULL) {
+ /* Skip all corrupted secondary index */
+ dict_table_skip_corrupt_index(node->index);
+
+ if (!node->index) {
+ break;
+ }
+
index = node->index;
if (row_upd_changes_ord_field_binary(node->index, node->update,
@@ -859,6 +881,9 @@ row_undo_mod(
node->index = dict_table_get_next_index(
dict_table_get_first_index(node->table));
+ /* Skip all corrupted secondary index */
+ dict_table_skip_corrupt_index(node->index);
+
if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
err = row_undo_mod_upd_exist_sec(node, thr);
diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c
index 2c7f3056329..5e8099691c5 100644
--- a/storage/xtradb/row/row0upd.c
+++ b/storage/xtradb/row/row0upd.c
@@ -1603,7 +1603,8 @@ row_upd_sec_index_entry(
mode |= BTR_DELETE_MARK;
}
- search_result = row_search_index_entry(index, entry, mode,
+ search_result = row_search_index_entry(index, entry,
+ trx->fake_changes ? BTR_SEARCH_LEAF : mode,
&pcur, &mtr);
btr_cur = btr_pcur_get_btr_cur(&pcur);
@@ -1850,9 +1851,11 @@ row_upd_clust_rec_by_insert(
the previous invocation of this function. Mark the
off-page columns in the entry inherited. */
+ if (!(trx->fake_changes)) {
change_ownership = row_upd_clust_rec_by_insert_inherit(
NULL, NULL, entry, node->update);
ut_a(change_ownership);
+ }
/* fall through */
case UPD_NODE_INSERT_CLUSTERED:
/* A lock wait occurred in row_ins_index_entry() in
@@ -1882,7 +1885,7 @@ err_exit:
delete-marked old record, mark them disowned by the
old record and owned by the new entry. */
- if (rec_offs_any_extern(offsets)) {
+ if (rec_offs_any_extern(offsets) && !(trx->fake_changes)) {
change_ownership = row_upd_clust_rec_by_insert_inherit(
rec, offsets, entry, node->update);
@@ -2012,7 +2015,8 @@ row_upd_clust_rec(
the same transaction do not modify the record in the meantime.
Therefore we can assert that the restoration of the cursor succeeds. */
- ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
+ ut_a(btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_TREE,
+ pcur, mtr));
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
dict_table_is_comp(index->table)));
@@ -2022,7 +2026,8 @@ row_upd_clust_rec(
node->cmpl_info, thr, mtr);
mtr_commit(mtr);
- if (err == DB_SUCCESS && big_rec) {
+ /* skip store extern for fake_changes */
+ if (err == DB_SUCCESS && big_rec && !(thr_get_trx(thr)->fake_changes)) {
ulint offsets_[REC_OFFS_NORMAL_SIZE];
rec_t* rec;
rec_offs_init(offsets_);
@@ -2146,7 +2151,8 @@ row_upd_clust_step(
ut_a(pcur->rel_pos == BTR_PCUR_ON);
- success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
+ success = btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_LEAF,
+ pcur, mtr);
if (!success) {
err = DB_RECORD_NOT_FOUND;
@@ -2323,6 +2329,13 @@ row_upd(
while (node->index != NULL) {
+ /* Skip corrupted index */
+ dict_table_skip_corrupt_index(node->index);
+
+ if (!node->index) {
+ break;
+ }
+
log_free_check();
err = row_upd_sec_step(node, thr);
diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c
index 0606de2e89a..43da8f867a6 100644
--- a/storage/xtradb/srv/srv0srv.c
+++ b/storage/xtradb/srv/srv0srv.c
@@ -87,6 +87,12 @@ Created 10/8/1995 Heikki Tuuri
#include "mysql/plugin.h"
#include "mysql/service_thd_wait.h"
+/* prototypes of new functions added to ha_innodb.cc for kill_idle_transaction */
+ibool innobase_thd_is_idle(const void* thd);
+ib_int64_t innobase_thd_get_start_time(const void* thd);
+void innobase_thd_kill(ulong thd_id);
+ulong innobase_thd_get_thread_id(const void* thd);
+
/* prototypes for new functions added to ha_innodb.cc */
ibool innobase_get_slow_log();
@@ -97,6 +103,9 @@ UNIV_INTERN ulint srv_activity_count = 0;
/* The following is the maximum allowed duration of a lock wait. */
UNIV_INTERN ulint srv_fatal_semaphore_wait_threshold = 600;
+/**/
+UNIV_INTERN lint srv_kill_idle_transaction = 0;
+
/* How much data manipulation language (DML) statements need to be delayed,
in microseconds, in order to reduce the lagging of the purge thread. */
UNIV_INTERN ulint srv_dml_needed_delay = 0;
@@ -234,6 +243,9 @@ UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX;
UNIV_INTERN ulint srv_n_read_io_threads = ULINT_MAX;
UNIV_INTERN ulint srv_n_write_io_threads = ULINT_MAX;
+/* Switch to enable random read ahead. */
+UNIV_INTERN my_bool srv_random_read_ahead = FALSE;
+
/* The universal page size of the database */
UNIV_INTERN ulint srv_page_size_shift = 0;
UNIV_INTERN ulint srv_page_size = 0;
@@ -342,6 +354,9 @@ UNIV_INTERN ulint srv_buf_pool_reads = 0;
/** Time in seconds between automatic buffer pool dumps */
UNIV_INTERN uint srv_auto_lru_dump = 0;
+/** Whether startup should be blocked until buffer pool is fully restored */
+UNIV_INTERN ibool srv_blocking_lru_restore;
+
/* structure to pass status variables to MySQL */
UNIV_INTERN export_struc export_vars;
@@ -2319,6 +2334,8 @@ srv_export_innodb_status(void)
export_vars.innodb_buffer_pool_pages_flushed = srv_buf_pool_flushed;
export_vars.innodb_buffer_pool_pages_LRU_flushed = buf_lru_flush_page_count;
export_vars.innodb_buffer_pool_reads = srv_buf_pool_reads;
+ export_vars.innodb_buffer_pool_read_ahead_rnd
+ = stat.n_ra_pages_read_rnd;
export_vars.innodb_buffer_pool_read_ahead
= stat.n_ra_pages_read;
export_vars.innodb_buffer_pool_read_ahead_evicted
@@ -2829,6 +2846,36 @@ loop:
old_sema = sema;
}
+ if (srv_kill_idle_transaction && trx_sys) {
+ trx_t* trx;
+ time_t now;
+rescan_idle:
+ now = time(NULL);
+ mutex_enter(&kernel_mutex);
+ trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
+ while (trx) {
+ if (trx->conc_state == TRX_ACTIVE
+ && trx->mysql_thd
+ && innobase_thd_is_idle(trx->mysql_thd)) {
+ ib_int64_t start_time = innobase_thd_get_start_time(trx->mysql_thd);
+ ulong thd_id = innobase_thd_get_thread_id(trx->mysql_thd);
+
+ if (trx->last_stmt_start != start_time) {
+ trx->idle_start = now;
+ trx->last_stmt_start = start_time;
+ } else if (difftime(now, trx->idle_start)
+ > srv_kill_idle_transaction) {
+ /* kill the session */
+ mutex_exit(&kernel_mutex);
+ innobase_thd_kill(thd_id);
+ goto rescan_idle;
+ }
+ }
+ trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
+ }
+ mutex_exit(&kernel_mutex);
+ }
+
/* Flush stderr so that a database user gets the output
to possible MySQL error file */
@@ -2874,7 +2921,9 @@ srv_LRU_dump_restore_thread(
os_thread_pf(os_thread_get_curr_id()));
#endif
- if (srv_auto_lru_dump)
+ /* If srv_blocking_lru_restore is TRUE, restore will be done
+ synchronously on startup. */
+ if (srv_auto_lru_dump && !srv_blocking_lru_restore)
buf_LRU_file_restore();
last_dump_time = time(NULL);
@@ -3042,7 +3091,7 @@ srv_master_do_purge(void)
ut_ad(!mutex_own(&kernel_mutex));
- ut_a(srv_n_purge_threads == 0);
+ ut_a(srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0));
do {
/* Check for shutdown and change in purge config. */
@@ -3542,7 +3591,7 @@ retry_flush_batch:
/* Flush logs if needed */
srv_sync_log_buffer_in_background();
- if (srv_n_purge_threads == 0) {
+ if (srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0)) {
srv_main_thread_op_info = "master purging";
srv_master_do_purge();
@@ -3620,7 +3669,7 @@ background_loop:
}
}
- if (srv_n_purge_threads == 0) {
+ if (srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0)) {
srv_main_thread_op_info = "master purging";
srv_master_do_purge();
diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c
index 13a54f5bf03..4083eb75b83 100644
--- a/storage/xtradb/srv/srv0start.c
+++ b/storage/xtradb/srv/srv0start.c
@@ -87,6 +87,7 @@ Created 2/16/1996 Heikki Tuuri
# include "btr0pcur.h"
# include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
# include "zlib.h" /* for ZLIB_VERSION */
+# include "buf0lru.h" /* for buf_LRU_file_restore() */
/** Log sequence number immediately after startup */
UNIV_INTERN ib_uint64_t srv_start_lsn;
@@ -1995,6 +1996,11 @@ innobase_start_or_create_for_mysql(void)
os_thread_create(&srv_LRU_dump_restore_thread, NULL,
thread_ids + 5 + SRV_MAX_N_IO_THREADS);
+ /* If srv_blocking_lru_restore is TRUE, load buffer pool contents
+ synchronously */
+ if (srv_auto_lru_dump && srv_blocking_lru_restore)
+ buf_LRU_file_restore();
+
srv_is_being_started = FALSE;
err = dict_create_or_check_foreign_constraint_tables();
diff --git a/storage/xtradb/sync/sync0sync.c b/storage/xtradb/sync/sync0sync.c
index 4b35d6db177..b38e2183b0f 100644
--- a/storage/xtradb/sync/sync0sync.c
+++ b/storage/xtradb/sync/sync0sync.c
@@ -1218,7 +1218,6 @@ sync_thread_add_level(
case SYNC_WORK_QUEUE:
case SYNC_LOG:
case SYNC_LOG_FLUSH_ORDER:
- case SYNC_THR_LOCAL:
case SYNC_ANY_LATCH:
case SYNC_OUTER_ANY_LATCH:
case SYNC_FILE_FORMAT_TAG:
@@ -1236,6 +1235,7 @@ sync_thread_add_level(
case SYNC_DICT_HEADER:
case SYNC_TRX_I_S_RWLOCK:
case SYNC_TRX_I_S_LAST_READ:
+ case SYNC_IBUF_MUTEX:
if (!sync_thread_levels_g(array, level, TRUE)) {
fprintf(stderr,
"InnoDB: sync_thread_levels_g(array, %lu)"
@@ -1328,22 +1328,33 @@ sync_thread_add_level(
|| sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
break;
case SYNC_TREE_NODE_NEW:
- ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE)
- || sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
+ ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE));
break;
case SYNC_INDEX_TREE:
- if (sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
- && sync_thread_levels_contain(array, SYNC_FSP)) {
- ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1,
- TRUE));
+ ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
+ break;
+ case SYNC_IBUF_TREE_NODE:
+ ut_a(sync_thread_levels_contain(array, SYNC_IBUF_INDEX_TREE)
+ || sync_thread_levels_g(array, SYNC_IBUF_TREE_NODE - 1,
+ TRUE));
+ break;
+ case SYNC_IBUF_TREE_NODE_NEW:
+ /* ibuf_add_free_page() allocates new pages for the
+ change buffer while only holding the tablespace
+ x-latch. These pre-allocated new pages may only be
+ taken in use while holding ibuf_mutex, in
+ btr_page_alloc_for_ibuf(). */
+ ut_a(sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
+ || sync_thread_levels_contain(array, SYNC_FSP));
+ break;
+ case SYNC_IBUF_INDEX_TREE:
+ if (sync_thread_levels_contain(array, SYNC_FSP)) {
+ ut_a(sync_thread_levels_g(array, level - 1, TRUE));
} else {
- ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1,
- TRUE));
+ ut_a(sync_thread_levels_g(
+ array, SYNC_IBUF_TREE_NODE - 1, TRUE));
}
break;
- case SYNC_IBUF_MUTEX:
- ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1, TRUE));
- break;
case SYNC_IBUF_PESS_INSERT_MUTEX:
ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE));
ut_a(!sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
diff --git a/storage/xtradb/trx/trx0rec.c b/storage/xtradb/trx/trx0rec.c
index 84687c7195b..104b80f5d96 100644
--- a/storage/xtradb/trx/trx0rec.c
+++ b/storage/xtradb/trx/trx0rec.c
@@ -1131,13 +1131,14 @@ trx_undo_rec_get_partial_row(
#endif /* !UNIV_HOTBACKUP */
/***********************************************************************//**
-Erases the unused undo log page end. */
-static
-void
+Erases the unused undo log page end.
+@return TRUE if the page contained something, FALSE if it was empty */
+static __attribute__((nonnull))
+ibool
trx_undo_erase_page_end(
/*====================*/
- page_t* undo_page, /*!< in: undo page whose end to erase */
- mtr_t* mtr) /*!< in: mtr */
+ page_t* undo_page, /*!< in/out: undo page whose end to erase */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint first_free;
@@ -1147,6 +1148,7 @@ trx_undo_erase_page_end(
(UNIV_PAGE_SIZE - FIL_PAGE_DATA_END) - first_free);
mlog_write_initial_log_record(undo_page, MLOG_UNDO_ERASE_END, mtr);
+ return(first_free != TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE);
}
/***********************************************************//**
@@ -1214,6 +1216,9 @@ trx_undo_report_row_operation(
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
+#ifdef UNIV_DEBUG
+ int loop_count = 0;
+#endif /* UNIV_DEBUG */
rec_offs_init(offsets_);
ut_a(dict_index_is_clust(index));
@@ -1276,7 +1281,7 @@ trx_undo_report_row_operation(
mtr_start(&mtr);
- for (;;) {
+ do {
buf_block_t* undo_block;
page_t* undo_page;
ulint offset;
@@ -1305,7 +1310,31 @@ trx_undo_report_row_operation(
version the replicate page constructed using the log
records stays identical to the original page */
- trx_undo_erase_page_end(undo_page, &mtr);
+ if (!trx_undo_erase_page_end(undo_page, &mtr)) {
+ /* The record did not fit on an empty
+ undo page. Discard the freshly allocated
+ page and return an error. */
+
+ /* When we remove a page from an undo
+ log, this is analogous to a
+ pessimistic insert in a B-tree, and we
+ must reserve the counterpart of the
+ tree latch, which is the rseg
+ mutex. We must commit the mini-transaction
+ first, because it may be holding lower-level
+ latches, such as SYNC_FSP and SYNC_FSP_PAGE. */
+
+ mtr_commit(&mtr);
+ mtr_start(&mtr);
+
+ mutex_enter(&rseg->mutex);
+ trx_undo_free_last_page(trx, undo, &mtr);
+ mutex_exit(&rseg->mutex);
+
+ err = DB_UNDO_RECORD_TOO_BIG;
+ goto err_exit;
+ }
+
mtr_commit(&mtr);
} else {
/* Success */
@@ -1325,16 +1354,15 @@ trx_undo_report_row_operation(
*roll_ptr = trx_undo_build_roll_ptr(
op_type == TRX_UNDO_INSERT_OP,
rseg->id, page_no, offset);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(DB_SUCCESS);
+ err = DB_SUCCESS;
+ goto func_exit;
}
ut_ad(page_no == undo->last_page_no);
/* We have to extend the undo log by one page */
+ ut_ad(++loop_count < 2);
mtr_start(&mtr);
/* When we add a page to an undo log, this is analogous to
@@ -1346,18 +1374,19 @@ trx_undo_report_row_operation(
page_no = trx_undo_add_page(trx, undo, &mtr);
mutex_exit(&(rseg->mutex));
+ } while (UNIV_LIKELY(page_no != FIL_NULL));
- if (UNIV_UNLIKELY(page_no == FIL_NULL)) {
- /* Did not succeed: out of space */
+ /* Did not succeed: out of space */
+ err = DB_OUT_OF_FILE_SPACE;
- mutex_exit(&(trx->undo_mutex));
- mtr_commit(&mtr);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(DB_OUT_OF_FILE_SPACE);
- }
+err_exit:
+ mutex_exit(&trx->undo_mutex);
+ mtr_commit(&mtr);
+func_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
}
+ return(err);
}
/*============== BUILDING PREVIOUS VERSION OF A RECORD ===============*/
diff --git a/storage/xtradb/trx/trx0trx.c b/storage/xtradb/trx/trx0trx.c
index f816160df58..2bb38571bda 100644
--- a/storage/xtradb/trx/trx0trx.c
+++ b/storage/xtradb/trx/trx0trx.c
@@ -121,6 +121,8 @@ trx_create(
trx->support_xa = TRUE;
+ trx->fake_changes = FALSE;
+
trx->check_foreigns = TRUE;
trx->check_unique_secondary = TRUE;
@@ -143,6 +145,9 @@ trx_create(
trx->mysql_relay_log_file_name = "";
trx->mysql_relay_log_pos = 0;
+ trx->idle_start = 0;
+ trx->last_stmt_start = 0;
+
mutex_create(trx_undo_mutex_key, &trx->undo_mutex, SYNC_TRX_UNDO);
trx->rseg = NULL;
diff --git a/storage/xtradb/trx/trx0undo.c b/storage/xtradb/trx/trx0undo.c
index 4cb4b7b79c5..dae0637f72c 100644
--- a/storage/xtradb/trx/trx0undo.c
+++ b/storage/xtradb/trx/trx0undo.c
@@ -1004,29 +1004,28 @@ trx_undo_free_page(
}
/********************************************************************//**
-Frees an undo log page when there is also the memory object for the undo
-log. */
-static
+Frees the last undo log page.
+The caller must hold the rollback segment mutex. */
+UNIV_INTERN
void
-trx_undo_free_page_in_rollback(
-/*===========================*/
- trx_t* trx __attribute__((unused)), /*!< in: transaction */
- trx_undo_t* undo, /*!< in: undo log memory copy */
- ulint page_no,/*!< in: page number to free: must not be the
- header page */
- mtr_t* mtr) /*!< in: mtr which does not have a latch to any
- undo log page; the caller must have reserved
- the rollback segment mutex */
+trx_undo_free_last_page_func(
+/*==========================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction */
+#endif /* UNIV_DEBUG */
+ trx_undo_t* undo, /*!< in/out: undo log memory copy */
+ mtr_t* mtr) /*!< in/out: mini-transaction which does not
+ have a latch to any undo log page or which
+ has allocated the undo log page */
{
- ulint last_page_no;
-
- ut_ad(undo->hdr_page_no != page_no);
- ut_ad(mutex_own(&(trx->undo_mutex)));
+ ut_ad(mutex_own(&trx->undo_mutex));
+ ut_ad(undo->hdr_page_no != undo->last_page_no);
+ ut_ad(undo->size > 0);
- last_page_no = trx_undo_free_page(undo->rseg, FALSE, undo->space,
- undo->hdr_page_no, page_no, mtr);
+ undo->last_page_no = trx_undo_free_page(
+ undo->rseg, FALSE, undo->space,
+ undo->hdr_page_no, undo->last_page_no, mtr);
- undo->last_page_no = last_page_no;
undo->size--;
}
@@ -1062,9 +1061,11 @@ Truncates an undo log from the end. This function is used during a rollback
to free space from an undo log. */
UNIV_INTERN
void
-trx_undo_truncate_end(
-/*==================*/
- trx_t* trx, /*!< in: transaction whose undo log it is */
+trx_undo_truncate_end_func(
+/*=======================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction whose undo log it is */
+#endif /* UNIV_DEBUG */
trx_undo_t* undo, /*!< in: undo log */
undo_no_t limit) /*!< in: all undo records with undo number
>= this value should be truncated */
@@ -1090,18 +1091,7 @@ trx_undo_truncate_end(
rec = trx_undo_page_get_last_rec(undo_page, undo->hdr_page_no,
undo->hdr_offset);
- for (;;) {
- if (rec == NULL) {
- if (last_page_no == undo->hdr_page_no) {
-
- goto function_exit;
- }
-
- trx_undo_free_page_in_rollback(
- trx, undo, last_page_no, &mtr);
- break;
- }
-
+ while (rec) {
if (trx_undo_rec_get_undo_no(rec) >= limit) {
/* Truncate at least this record off, maybe
more */
@@ -1115,6 +1105,14 @@ trx_undo_truncate_end(
undo->hdr_offset);
}
+ if (last_page_no == undo->hdr_page_no) {
+
+ goto function_exit;
+ }
+
+ ut_ad(last_page_no == undo->last_page_no);
+ trx_undo_free_last_page(trx, undo, &mtr);
+
mtr_commit(&mtr);
}
diff --git a/storage/xtradb/ut/ut0mem.c b/storage/xtradb/ut/ut0mem.c
index 53f15029e1b..303fdd6dd44 100644
--- a/storage/xtradb/ut/ut0mem.c
+++ b/storage/xtradb/ut/ut0mem.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -483,53 +483,6 @@ ut_strlcpy_rev(
return(src_size);
}
-/**********************************************************************//**
-Make a quoted copy of a NUL-terminated string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_memcpyq().
-@return pointer to end of dest */
-UNIV_INTERN
-char*
-ut_strcpyq(
-/*=======*/
- char* dest, /*!< in: output buffer */
- char q, /*!< in: the quote character */
- const char* src) /*!< in: null-terminated string */
-{
- while (*src) {
- if ((*dest++ = *src++) == q) {
- *dest++ = q;
- }
- }
-
- return(dest);
-}
-
-/**********************************************************************//**
-Make a quoted copy of a fixed-length string. Leading and trailing
-quotes will not be included; only embedded quotes will be escaped.
-See also ut_strlenq() and ut_strcpyq().
-@return pointer to end of dest */
-UNIV_INTERN
-char*
-ut_memcpyq(
-/*=======*/
- char* dest, /*!< in: output buffer */
- char q, /*!< in: the quote character */
- const char* src, /*!< in: string to be quoted */
- ulint len) /*!< in: length of src */
-{
- const char* srcend = src + len;
-
- while (src < srcend) {
- if ((*dest++ = *src++) == q) {
- *dest++ = q;
- }
- }
-
- return(dest);
-}
-
#ifndef UNIV_HOTBACKUP
/**********************************************************************//**
Return the number of times s2 occurs in s1. Overlapping instances of s2
diff --git a/storage/xtradb/ut/ut0ut.c b/storage/xtradb/ut/ut0ut.c
index c14be50c41c..4fab362b5f5 100644
--- a/storage/xtradb/ut/ut0ut.c
+++ b/storage/xtradb/ut/ut0ut.c
@@ -674,8 +674,6 @@ ut_strerr(
return("Cannot add constraint");
case DB_CORRUPTION:
return("Data structure corruption");
- case DB_COL_APPEARS_TWICE_IN_INDEX:
- return("Column appears twice in index");
case DB_CANNOT_DROP_CONSTRAINT:
return("Cannot drop constraint");
case DB_NO_SAVEPOINT:
@@ -714,6 +712,10 @@ ut_strerr(
return("No index on referencing keys in referencing table");
case DB_PARENT_NO_INDEX:
return("No index on referenced keys in referenced table");
+ case DB_INDEX_CORRUPT:
+ return("Index corrupted");
+ case DB_UNDO_RECORD_TOO_BIG:
+ return("Undo record too big");
case DB_END_OF_INDEX:
return("End of index");
case DB_SEARCH_ABORTED_BY_USER: