Commit 346b7301 authored by Jon Olav Hauglid's avatar Jon Olav Hauglid

Merge from mysql-5.5-innodb to mysql-5.5-bugteam

No conflicts
parents 00490194 38f54271
This diff is collapsed.
This diff is collapsed.
SET GLOBAL tx_isolation='REPEATABLE-READ';
SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=on;
CREATE TABLE bug56680(
a INT AUTO_INCREMENT PRIMARY KEY,
b CHAR(1),
c INT,
INDEX(b))
ENGINE=InnoDB;
INSERT INTO bug56680 VALUES(0,'x',1);
BEGIN;
SELECT b FROM bug56680;
b
x
BEGIN;
UPDATE bug56680 SET b='X';
SELECT b FROM bug56680;
b
x
SELECT * FROM bug56680;
a b c
1 x 1
ROLLBACK;
SELECT b FROM bug56680;
b
x
SET GLOBAL tx_isolation='READ-UNCOMMITTED';
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
BEGIN;
SELECT b FROM bug56680 LIMIT 2;
b
x
x
BEGIN;
DELETE FROM bug56680 WHERE a=1;
INSERT INTO bug56680 VALUES(1,'X',1);
SELECT b FROM bug56680 LIMIT 3;
b
X
x
x
SELECT b FROM bug56680 LIMIT 2;
b
x
x
CHECK TABLE bug56680;
Table Op Msg_type Msg_text
test.bug56680 check status OK
ROLLBACK;
SELECT b FROM bug56680 LIMIT 2;
b
x
x
CHECK TABLE bug56680;
Table Op Msg_type Msg_text
test.bug56680 check status OK
SELECT b FROM bug56680 LIMIT 2;
b
x
x
CREATE TABLE bug56680_2(
a INT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(2) CHARSET latin1 COLLATE latin1_german2_ci,
c INT,
INDEX(b))
ENGINE=InnoDB;
INSERT INTO bug56680_2 SELECT 0,_latin1 0xdf,c FROM bug56680;
BEGIN;
SELECT HEX(b) FROM bug56680_2 LIMIT 2;
HEX(b)
DF
DF
DELETE FROM bug56680_2 WHERE a=1;
INSERT INTO bug56680_2 VALUES(1,'SS',1);
SELECT HEX(b) FROM bug56680_2 LIMIT 3;
HEX(b)
5353
DF
DF
CHECK TABLE bug56680_2;
Table Op Msg_type Msg_text
test.bug56680_2 check status OK
ALTER TABLE bug56680_2 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1;
SELECT HEX(b) FROM bug56680_2 LIMIT 2;
HEX(b)
5353
DF
DELETE FROM bug56680_2 WHERE a=1;
INSERT INTO bug56680_2 VALUES(1,_latin1 0xdf,1);
SELECT HEX(b) FROM bug56680_2 LIMIT 3;
HEX(b)
DF
DF
DF
CHECK TABLE bug56680_2;
Table Op Msg_type Msg_text
test.bug56680_2 check status OK
DROP TABLE bug56680_2;
DROP TABLE bug56680;
cardinality
10
Table Op Msg_type Msg_text
test.bug57252 analyze status OK
cardinality
10
This diff is collapsed.
#
# Bug#56632: ALTER TABLE implicitly changes ROW_FORMAT to COMPRESSED
# http://bugs.mysql.com/56632
#
# Innodb automatically uses compressed mode when the KEY_BLOCK_SIZE
# parameter is used, except if the ROW_FORMAT is also specified, in
# which case the KEY_BLOCK_SIZE is ignored and a warning is shown.
# But Innodb was getting confused when neither of those parameters
# was used on the ALTER statement after they were both used on the
# CREATE.
#
# This will test the results of all 4 combinations of these two
# parameters of the CREATE and ALTER.
#
# Tests 1-5 use INNODB_STRICT_MODE=1 which returns an error
# if there is anything wrong with the statement.
#
# 1) CREATE with ROW_FORMAT=COMPACT & KEY_BLOCK_SIZE=1, ALTER with neither.
# Result; CREATE; fails with error ER_CANT_CREATE_TABLE
# 2) CREATE with ROW_FORMAT=COMPACT, ALTER with KEY_BLOCK_SIZE=1
# Result; CREATE succeeds,
# ALTER quietly converts ROW_FORMAT to compressed.
# 3) CREATE with KEY_BLOCK_SIZE=1, ALTER with ROW_FORMAT=COMPACT
# Result; CREATE quietly converts ROW_FORMAT to compressed,
# ALTER fails with error ER_CANT_CREATE_TABLE.
# 4) CREATE with neither, ALTER with ROW_FORMAT=COMPACT & KEY_BLOCK_SIZE=1
# Result; CREATE succeeds,
# ALTER; fails with error ER_CANT_CREATE_TABLE
# 5) CREATE with KEY_BLOCK_SIZE=3 (invalid), ALTER with neither.
# Result; CREATE; fails with error ER_CANT_CREATE_TABLE
#
# Tests 6-11 use INNODB_STRICT_MODE=0 which automatically makes
# adjustments if the prameters are incompatible.
#
# 6) CREATE with ROW_FORMAT=COMPACT & KEY_BLOCK_SIZE=1, ALTER with neither.
# Result; CREATE succeeds, warns that KEY_BLOCK_SIZE is ignored.
# ALTER succeeds, no warnings.
# 7) CREATE with ROW_FORMAT=COMPACT, ALTER with KEY_BLOCK_SIZE=1
# Result; CREATE succeeds,
# ALTER quietly converts ROW_FORMAT to compressed.
# 8) CREATE with KEY_BLOCK_SIZE=1, ALTER with ROW_FORMAT=COMPACT
# Result; CREATE quietly converts ROW_FORMAT to compressed,
# ALTER succeeds, warns that KEY_BLOCK_SIZE is ignored.
# 9) CREATE with neither, ALTER with ROW_FORMAT=COMPACT & KEY_BLOCK_SIZE=1
# Result; CREATE succeeds,
# ALTER succeeds, warns that KEY_BLOCK_SIZE is ignored.
# 10) CREATE with KEY_BLOCK_SIZE=3 (invalid), ALTER with neither.
# Result; CREATE succeeds, warns that KEY_BLOCK_SIZE=3 is ignored.
# ALTER succeeds, warns that KEY_BLOCK_SIZE=3 is ignored.
# 11) CREATE with KEY_BLOCK_SIZE=3 (invalid), ALTER with ROW_FORMAT=COMPACT.
# Result; CREATE succeeds, warns that KEY_BLOCK_SIZE=3 is ignored.
# ALTER succeeds, warns that KEY_BLOCK_SIZE=3 is ignored.
# 12) CREATE with KEY_BLOCK_SIZE=3 (invalid), ALTER with KEY_BLOCK_SIZE=1.
# Result; CREATE succeeds, warns that KEY_BLOCK_SIZE=3 is ignored.
# ALTER succeeds, quietly converts ROW_FORMAT to compressed.
-- source include/have_innodb.inc
SET storage_engine=InnoDB;
--disable_query_log
# These values can change during the test
LET $innodb_file_format_orig=`select @@innodb_file_format`;
LET $innodb_file_format_max_orig=`select @@innodb_file_format_max`;
LET $innodb_file_per_table_orig=`select @@innodb_file_per_table`;
LET $innodb_strict_mode_orig=`select @@session.innodb_strict_mode`;
--enable_query_log
SET GLOBAL innodb_file_format=`Barracuda`;
SET GLOBAL innodb_file_per_table=ON;
# Innodb strict mode will cause an error on the CREATE or ALTER when;
# 1. both ROW_FORMAT=COMPACT and KEY_BLOCK_SIZE=1,
# 2. KEY_BLOCK_SIZE is not a valid number (0,1,2,4,8,16).
# With innodb_strict_mode = OFF, These errors are corrected
# and just a warning is returned.
SET SESSION innodb_strict_mode = ON;
--echo # Test 1) CREATE with ROW_FORMAT & KEY_BLOCK_SIZE, ALTER with neither
DROP TABLE IF EXISTS bug56632;
--error ER_CANT_CREATE_TABLE
CREATE TABLE bug56632 ( i INT ) ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=1;
SHOW WARNINGS;
--echo # Test 2) CREATE with ROW_FORMAT, ALTER with KEY_BLOCK_SIZE
DROP TABLE IF EXISTS bug56632;
CREATE TABLE bug56632 ( i INT ) ROW_FORMAT=COMPACT;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
ALTER TABLE bug56632 KEY_BLOCK_SIZE=1;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
--echo # Test 3) CREATE with KEY_BLOCK_SIZE, ALTER with ROW_FORMAT
DROP TABLE IF EXISTS bug56632;
CREATE TABLE bug56632 ( i INT ) KEY_BLOCK_SIZE=1;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
--disable_result_log
--error ER_CANT_CREATE_TABLE
ALTER TABLE bug56632 ROW_FORMAT=COMPACT;
--enable_result_log
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
--echo # Test 4) CREATE with neither, ALTER with ROW_FORMAT & KEY_BLOCK_SIZE
DROP TABLE IF EXISTS bug56632;
CREATE TABLE bug56632 ( i INT );
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
--disable_result_log
--error ER_CANT_CREATE_TABLE
ALTER TABLE bug56632 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=1;
--enable_result_log
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
--echo # Test 5) CREATE with KEY_BLOCK_SIZE=3 (invalid).
DROP TABLE IF EXISTS bug56632;
--error ER_CANT_CREATE_TABLE
CREATE TABLE bug56632 ( i INT ) KEY_BLOCK_SIZE=3;
SHOW WARNINGS;
SET SESSION innodb_strict_mode = OFF;
--echo # Test 6) CREATE with ROW_FORMAT & KEY_BLOCK_SIZE, ALTER with neither
DROP TABLE IF EXISTS bug56632;
CREATE TABLE bug56632 ( i INT ) ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=1;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
ALTER TABLE bug56632 ADD COLUMN f1 INT;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
--echo # Test 7) CREATE with ROW_FORMAT, ALTER with KEY_BLOCK_SIZE
DROP TABLE IF EXISTS bug56632;
CREATE TABLE bug56632 ( i INT ) ROW_FORMAT=COMPACT;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
ALTER TABLE bug56632 KEY_BLOCK_SIZE=1;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
--echo # Test 8) CREATE with KEY_BLOCK_SIZE, ALTER with ROW_FORMAT
DROP TABLE IF EXISTS bug56632;
CREATE TABLE bug56632 ( i INT ) KEY_BLOCK_SIZE=1;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
ALTER TABLE bug56632 ROW_FORMAT=COMPACT;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
--echo # Test 9) CREATE with neither, ALTER with ROW_FORMAT & KEY_BLOCK_SIZE
DROP TABLE IF EXISTS bug56632;
CREATE TABLE bug56632 ( i INT );
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
ALTER TABLE bug56632 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=1;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
--echo # Test 10) CREATE with KEY_BLOCK_SIZE=3 (invalid), ALTER with neither.
DROP TABLE IF EXISTS bug56632;
CREATE TABLE bug56632 ( i INT ) KEY_BLOCK_SIZE=3;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
ALTER TABLE bug56632 ADD COLUMN f1 INT;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
--echo # Test 11) CREATE with KEY_BLOCK_SIZE=3 (invalid), ALTER with ROW_FORMAT=COMPACT.
DROP TABLE IF EXISTS bug56632;
CREATE TABLE bug56632 ( i INT ) KEY_BLOCK_SIZE=3;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
ALTER TABLE bug56632 ROW_FORMAT=COMPACT;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
--echo # Test 12) CREATE with KEY_BLOCK_SIZE=3 (invalid), ALTER with KEY_BLOCK_SIZE=1.
DROP TABLE IF EXISTS bug56632;
CREATE TABLE bug56632 ( i INT ) KEY_BLOCK_SIZE=3;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
ALTER TABLE bug56632 KEY_BLOCK_SIZE=1;
SHOW WARNINGS;
SHOW CREATE TABLE bug56632;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 'bug56632';
--echo # Cleanup
DROP TABLE IF EXISTS bug56632;
--disable_query_log
EVAL SET GLOBAL innodb_file_per_table=$innodb_file_per_table_orig;
EVAL SET GLOBAL innodb_file_format_max=$innodb_file_format_max_orig;
EVAL SET GLOBAL innodb_file_format=$innodb_file_format_orig;
EVAL SET SESSION innodb_strict_mode=$innodb_strict_mode_orig;
--enable_query_log
#
# Bug #56680 InnoDB may return wrong results from a case-insensitive index
#
-- source include/have_innodb.inc
-- disable_query_log
SET @tx_isolation_orig = @@tx_isolation;
SET @innodb_file_per_table_orig = @@innodb_file_per_table;
SET @innodb_file_format_orig = @@innodb_file_format;
SET @innodb_file_format_max_orig = @@innodb_file_format_max;
# The flag innodb_change_buffering_debug is only available in debug builds.
# It instructs InnoDB to try to evict pages from the buffer pool when
# change buffering is possible, so that the change buffer will be used
# whenever possible.
-- error 0,ER_UNKNOWN_SYSTEM_VARIABLE
SET @innodb_change_buffering_debug_orig = @@innodb_change_buffering_debug;
-- error 0,ER_UNKNOWN_SYSTEM_VARIABLE
SET GLOBAL innodb_change_buffering_debug = 1;
-- enable_query_log
SET GLOBAL tx_isolation='REPEATABLE-READ';
SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=on;
CREATE TABLE bug56680(
a INT AUTO_INCREMENT PRIMARY KEY,
b CHAR(1),
c INT,
INDEX(b))
ENGINE=InnoDB;
INSERT INTO bug56680 VALUES(0,'x',1);
BEGIN;
SELECT b FROM bug56680;
connect (con1,localhost,root,,);
connection con1;
BEGIN;
UPDATE bug56680 SET b='X';
connection default;
# This should return the last committed value 'x', but would return 'X'
# due to a bug in row_search_for_mysql().
SELECT b FROM bug56680;
# This would always return the last committed value 'x'.
SELECT * FROM bug56680;
connection con1;
ROLLBACK;
disconnect con1;
connection default;
SELECT b FROM bug56680;
# For the rest of this test, use the READ UNCOMMITTED isolation level
# to see what exists in the secondary index.
SET GLOBAL tx_isolation='READ-UNCOMMITTED';
# Create enough rows for the table, so that the insert buffer will be
# used for modifying the secondary index page. There must be multiple
# index pages, because changes to the root page are never buffered.
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
INSERT INTO bug56680 SELECT 0,b,c FROM bug56680;
BEGIN;
SELECT b FROM bug56680 LIMIT 2;
connect (con1,localhost,root,,);
connection con1;
BEGIN;
DELETE FROM bug56680 WHERE a=1;
# This should be buffered, if innodb_change_buffering_debug = 1 is in effect.
INSERT INTO bug56680 VALUES(1,'X',1);
# This should force an insert buffer merge, and return 'X' in the first row.
SELECT b FROM bug56680 LIMIT 3;
connection default;
SELECT b FROM bug56680 LIMIT 2;
CHECK TABLE bug56680;
connection con1;
ROLLBACK;
SELECT b FROM bug56680 LIMIT 2;
CHECK TABLE bug56680;
connection default;
disconnect con1;
SELECT b FROM bug56680 LIMIT 2;
CREATE TABLE bug56680_2(
a INT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(2) CHARSET latin1 COLLATE latin1_german2_ci,
c INT,
INDEX(b))
ENGINE=InnoDB;
INSERT INTO bug56680_2 SELECT 0,_latin1 0xdf,c FROM bug56680;
BEGIN;
SELECT HEX(b) FROM bug56680_2 LIMIT 2;
DELETE FROM bug56680_2 WHERE a=1;
# This should be buffered, if innodb_change_buffering_debug = 1 is in effect.
INSERT INTO bug56680_2 VALUES(1,'SS',1);
# This should force an insert buffer merge, and return 'SS' in the first row.
SELECT HEX(b) FROM bug56680_2 LIMIT 3;
CHECK TABLE bug56680_2;
# Test this with compressed tables.
ALTER TABLE bug56680_2 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1;
SELECT HEX(b) FROM bug56680_2 LIMIT 2;
DELETE FROM bug56680_2 WHERE a=1;
# This should be buffered, if innodb_change_buffering_debug = 1 is in effect.
INSERT INTO bug56680_2 VALUES(1,_latin1 0xdf,1);
# This should force an insert buffer merge, and return 0xdf in the first row.
SELECT HEX(b) FROM bug56680_2 LIMIT 3;
CHECK TABLE bug56680_2;
DROP TABLE bug56680_2;
DROP TABLE bug56680;
-- disable_query_log
SET GLOBAL tx_isolation = @tx_isolation_orig;
SET GLOBAL innodb_file_per_table = @innodb_file_per_table_orig;
SET GLOBAL innodb_file_format = @innodb_file_format_orig;
SET GLOBAL innodb_file_format_max = @innodb_file_format_max_orig;
-- error 0, ER_UNKNOWN_SYSTEM_VARIABLE
SET GLOBAL innodb_change_buffering_debug = @innodb_change_buffering_debug_orig;
#
# Bug#57252 disabling innobase_stats_on_metadata disables ANALYZE
# http://bugs.mysql.com/57252
#
-- source include/have_innodb.inc
-- disable_query_log
-- disable_result_log
SET @innodb_stats_on_metadata_orig = @@innodb_stats_on_metadata;
CREATE TABLE bug57252 (a INT, KEY akey (a)) ENGINE=INNODB;
BEGIN;
let $i = 10;
while ($i) {
eval INSERT INTO bug57252 VALUES ($i);
dec $i;
}
COMMIT;
-- enable_result_log
SET GLOBAL innodb_stats_on_metadata=0;
# this calls ::info() without HA_STATUS_CONST and so
# index->stat_n_diff_key_vals[] is not copied to the mysql-visible
# rec_per_key
SELECT cardinality FROM information_schema.statistics
WHERE table_name='bug57252' AND index_name='akey';
# this calls ::info() with HA_STATUS_CONST and so
# index->stat_n_diff_key_vals[] is copied to the mysql-visible
# rec_per_key at the end; when the bug is present dict_update_statistics()
# is not called beforehand and so index->stat_n_diff_key_vals[] contains
# an outdated data and thus we get an outdated data in the result when the
# bug is present
ANALYZE TABLE bug57252;
SELECT cardinality FROM information_schema.statistics
WHERE table_name='bug57252' AND index_name='akey';
DROP TABLE bug57252;
SET GLOBAL innodb_stats_on_metadata = @innodb_stats_on_metadata_orig;
......@@ -3,6 +3,7 @@ create table t2 (variable_name text);
load data infile "MYSQLTEST_VARDIR/tmp/sys_vars.all_vars.txt" into table t1;
insert into t2 select variable_name from information_schema.global_variables;
insert into t2 select variable_name from information_schema.session_variables;
delete from t2 where variable_name='innodb_change_buffering_debug';
update t2 set variable_name= replace(variable_name, "PERFORMANCE_SCHEMA_", "PFS_");
select variable_name as `There should be *no* long test name listed below:` from t2
where length(variable_name) > 50;
......
......@@ -61,6 +61,9 @@ eval load data infile "$MYSQLTEST_VARDIR/tmp/sys_vars.all_vars.txt" into table t
insert into t2 select variable_name from information_schema.global_variables;
insert into t2 select variable_name from information_schema.session_variables;
# This is only present in debug builds.
delete from t2 where variable_name='innodb_change_buffering_debug';
# Performance schema variables are too long for files named
# 'mysql-test/suite/sys_vars/t/' ...
# ... 'performance_schema_events_waits_history_long_size_basic-master.opt'
......
......@@ -125,9 +125,13 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
CHECK_FUNCTION_EXISTS(atomic_cas_ulong HAVE_ATOMIC_CAS_ULONG)
CHECK_FUNCTION_EXISTS(atomic_cas_32 HAVE_ATOMIC_CAS_32)
CHECK_FUNCTION_EXISTS(atomic_cas_64 HAVE_ATOMIC_CAS_64)
CHECK_FUNCTION_EXISTS(atomic_add_long HAVE_ATOMIC_ADD_LONG)
IF(HAVE_ATOMIC_CAS_ULONG AND HAVE_ATOMIC_CAS_32 AND
HAVE_ATOMIC_CAS_64 AND HAVE_ATOMIC_ADD_LONG)
CHECK_FUNCTION_EXISTS(atomic_add_long_nv HAVE_ATOMIC_ADD_LONG_NV)
CHECK_FUNCTION_EXISTS(atomic_swap_uchar HAVE_ATOMIC_SWAP_UCHAR)
IF(HAVE_ATOMIC_CAS_ULONG AND
HAVE_ATOMIC_CAS_32 AND
HAVE_ATOMIC_CAS_64 AND
HAVE_ATOMIC_ADD_LONG_NV AND
HAVE_ATOMIC_SWAP_UCHAR)
SET(HAVE_IB_SOLARIS_ATOMICS 1)
ENDIF()
......@@ -231,7 +235,7 @@ SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
os/os0file.c os/os0proc.c os/os0sync.c os/os0thread.c
page/page0cur.c page/page0page.c page/page0zip.c
que/que0que.c
handler/ha_innodb.cc handler/handler0alter.cc handler/i_s.cc handler/mysql_addons.cc
handler/ha_innodb.cc handler/handler0alter.cc handler/i_s.cc
read/read0read.c
rem/rem0cmp.c rem/rem0rec.c
row/row0ext.c row/row0ins.c row/row0merge.c row/row0mysql.c row/row0purge.c row/row0row.c
......
......@@ -115,7 +115,6 @@ noinst_HEADERS= \
include/mtr0mtr.h \
include/mtr0mtr.ic \
include/mtr0types.h \
include/mysql_addons.h \
include/os0file.h \
include/os0file.ic \
include/os0proc.h \
......@@ -258,7 +257,6 @@ libinnobase_a_SOURCES= \
handler/ha_innodb.cc \
handler/handler0alter.cc \
handler/i_s.cc \
handler/mysql_addons.cc \
ibuf/ibuf0ibuf.c \
lock/lock0iter.c \
lock/lock0lock.c \
......
......@@ -1744,7 +1744,7 @@ func_exit:
See if there is enough place in the page modification log to log
an update-in-place.
@return TRUE if enough place */
static
UNIV_INTERN
ibool
btr_cur_update_alloc_zip(
/*=====================*/
......
......@@ -281,7 +281,7 @@ 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.
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 */
UNIV_INTERN
......
......@@ -172,7 +172,7 @@ The chain of modified blocks (buf_pool->flush_list) contains the blocks
holding file pages that have been modified in the memory
but not written to disk yet. The block with the oldest modification
which has not yet been written to disk is at the end of the chain.
The access to this list is protected by flush_list_mutex.
The access to this list is protected by buf_pool->flush_list_mutex.
The chain of unmodified compressed blocks (buf_pool->zip_clean)
contains the control blocks (buf_page_t) of those compressed pages
......@@ -1882,8 +1882,8 @@ buf_pool_watch_set(
ut_ad(!bpage->in_page_hash);
ut_ad(bpage->buf_fix_count == 0);
/* bpage is pointing to buf_pool_watch[],
which is protected by buf_pool_mutex.
/* bpage is pointing to buf_pool->watch[],
which is protected by buf_pool->mutex.
Normally, buf_page_t objects are protected by
buf_block_t::mutex or buf_pool->zip_mutex or both. */
......@@ -3008,6 +3008,46 @@ wait_until_unfixed:
bytes. */
UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page);
#endif
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
if ((mode == BUF_GET_IF_IN_POOL || mode == BUF_GET_IF_IN_POOL_OR_WATCH)
&& ibuf_debug) {
/* 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, NULL)
== BUF_LRU_FREED) {
mutex_exit(&block->mutex);
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
/* Set the watch, as it would have
been set if the page were not in the
buffer pool in the first place. */
block = (buf_block_t*) buf_pool_watch_set(
space, offset, fold);
if (UNIV_LIKELY_NULL(block)) {
/* The page entered the buffer
pool for some reason. Try to
evict it again. */
goto got_block;
}
}
buf_pool_mutex_exit(buf_pool);
fprintf(stderr,
"innodb_change_buffering_debug evict %u %u\n",
(unsigned) space, (unsigned) offset);
return(NULL);
} else if (buf_flush_page_try(buf_pool, block)) {
fprintf(stderr,
"innodb_change_buffering_debug flush %u %u\n",
(unsigned) space, (unsigned) offset);
guess = block;
goto loop;
}
/* Failed to evict the page; change it directly */
}
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
buf_block_buf_fix_inc(block, file, line);
......
......@@ -321,7 +321,7 @@ buf_flush_insert_sorted_into_flush_list(
buf_flush_list_mutex_enter(buf_pool);
/* The field in_LRU_list is protected by buf_pool_mutex, which
/* The field in_LRU_list is protected by buf_pool->mutex, which
we are not holding. However, while a block is in the flush
list, it is dirty and cannot be discarded, not from the
page_hash or from the LRU list. At most, the uncompressed
......@@ -1061,7 +1061,7 @@ buf_flush_write_block_low(
ut_ad(buf_page_in_file(bpage));
/* We are not holding buf_pool_mutex or block_mutex here.
/* We are not holding buf_pool->mutex or block_mutex here.
Nevertheless, it is safe to access bpage, because it is
io_fixed and oldest_modification != 0. Thus, it cannot be
relocated in the buffer pool or removed from flush_list or
......@@ -1132,6 +1132,83 @@ buf_flush_write_block_low(
}
}
# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
/********************************************************************//**
Writes a flushable page asynchronously from the buffer pool to a file.
NOTE: buf_pool->mutex and block->mutex must be held upon entering this
function, and they will be released by this function after flushing.
This is loosely based on buf_flush_batch() and buf_flush_page().
@return TRUE if the page was flushed and the mutexes released */
UNIV_INTERN
ibool
buf_flush_page_try(
/*===============*/
buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
buf_block_t* block) /*!< in/out: buffer control block */
{
ut_ad(buf_pool_mutex_own(buf_pool));
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
ut_ad(mutex_own(&block->mutex));
if (!buf_flush_ready_for_flush(&block->page, BUF_FLUSH_LRU)) {
return(FALSE);
}
if (buf_pool->n_flush[BUF_FLUSH_LRU] > 0
|| buf_pool->init_flush[BUF_FLUSH_LRU]) {
/* There is already a flush batch of the same type running */
return(FALSE);
}
buf_pool->init_flush[BUF_FLUSH_LRU] = TRUE;
buf_page_set_io_fix(&block->page, BUF_IO_WRITE);
buf_page_set_flush_type(&block->page, BUF_FLUSH_LRU);
if (buf_pool->n_flush[BUF_FLUSH_LRU]++ == 0) {
os_event_reset(buf_pool->no_flush[BUF_FLUSH_LRU]);
}
/* VERY IMPORTANT:
Because any thread may call the LRU flush, even when owning
locks on pages, to avoid deadlocks, we must make sure that the
s-lock is acquired on the page without waiting: this is
accomplished because buf_flush_ready_for_flush() must hold,
and that requires the page not to be bufferfixed. */
rw_lock_s_lock_gen(&block->lock, BUF_IO_WRITE);
/* Note that the s-latch is acquired before releasing the
buf_pool mutex: this ensures that the latch is acquired
immediately. */
mutex_exit(&block->mutex);
buf_pool_mutex_exit(buf_pool);
/* Even though block is not protected by any mutex at this
point, it is safe to access block, because it is io_fixed and
oldest_modification != 0. Thus, it cannot be relocated in the
buffer pool or removed from flush_list or LRU_list. */
buf_flush_write_block_low(&block->page);
buf_pool_mutex_enter(buf_pool);
buf_pool->init_flush[BUF_FLUSH_LRU] = FALSE;
if (buf_pool->n_flush[BUF_FLUSH_LRU] == 0) {
/* The running flush batch has ended */
os_event_set(buf_pool->no_flush[BUF_FLUSH_LRU]);
}
buf_pool_mutex_exit(buf_pool);
buf_flush_buffered_writes();
return(TRUE);
}
# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
/********************************************************************//**
Writes a flushable page asynchronously from the buffer pool to a file.
NOTE: in simulated aio we must call
......@@ -2116,12 +2193,12 @@ buf_flush_validate_low(
ut_ad(bpage->in_flush_list);
/* A page in flush_list can be in BUF_BLOCK_REMOVE_HASH
state. This happens when a page is in the middle of
being relocated. In that case the original descriptor
can have this state and still be in the flush list
waiting to acquire the flush_list_mutex to complete
the relocation. */
/* A page in buf_pool->flush_list can be in
BUF_BLOCK_REMOVE_HASH state. This happens when a page
is in the middle of being relocated. In that case the
original descriptor can have this state and still be
in the flush list waiting to acquire the
buf_pool->flush_list_mutex to complete the relocation. */
ut_a(buf_page_in_file(bpage)
|| buf_page_get_state(bpage) == BUF_BLOCK_REMOVE_HASH);
ut_a(om > 0);
......
......@@ -356,8 +356,8 @@ scan_again:
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
......@@ -403,7 +403,7 @@ scan_again:
/* Descriptors of uncompressed
blocks will not be relocated,
because we are holding the
buf_pool_mutex. */
buf_pool->mutex. */
break;
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
......@@ -1443,10 +1443,10 @@ 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
release buf_pool_mutex. Furthermore, the page frame will no longer be
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
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
......
This diff is collapsed.
......@@ -109,6 +109,7 @@ class ha_innobase: public handler
ulint innobase_update_autoinc(ulonglong auto_inc);
void innobase_initialize_autoinc();
dict_index_t* innobase_get_index(uint keynr);
int info_low(uint flag, bool called_from_analyze);
/* Init values for the class: */
public:
......
/*****************************************************************************
Copyright (c) 2007, 2009, Innobase Oy. 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
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/**************************************************//**
@file handler/mysql_addons.cc
This file contains functions that need to be added to
MySQL code but have not been added yet.
Whenever you add a function here submit a MySQL bug
report (feature request) with the implementation. Then
write the bug number in the comment before the
function in this file.
When MySQL commits the function it can be deleted from
here. In a perfect world this file exists but is empty.
Created November 07, 2007 Vasil Dimov
*******************************************************/
#ifndef MYSQL_SERVER
#define MYSQL_SERVER
#endif /* MYSQL_SERVER */
#include <sql_priv.h>
#include "mysql_addons.h"
#include "univ.i"
This diff is collapsed.
......@@ -243,6 +243,22 @@ btr_cur_pessimistic_insert(
que_thr_t* thr, /*!< in: query thread or NULL */
mtr_t* mtr); /*!< in: mtr */
/*************************************************************//**
See if there is enough place in the page modification log to log
an update-in-place.
@return TRUE if enough place */
UNIV_INTERN
ibool
btr_cur_update_alloc_zip(
/*=====================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page */
buf_block_t* block, /*!< in/out: buffer page */
dict_index_t* index, /*!< in: the index corresponding to the block */
ulint length, /*!< in: size needed */
ibool create, /*!< in: TRUE=delete-and-insert,
FALSE=update-in-place */
mtr_t* mtr) /*!< in: mini-transaction */
__attribute__((nonnull, warn_unused_result));
/*************************************************************//**
Updates a record when the update causes no size changes in its fields.
@return DB_SUCCESS or error number */
UNIV_INTERN
......
......@@ -36,7 +36,7 @@ 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
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
......
......@@ -35,7 +35,7 @@ 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.
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 */
UNIV_INTERN
......@@ -86,7 +86,7 @@ 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
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
......
......@@ -96,7 +96,7 @@ enum buf_page_state {
BUF_BLOCK_ZIP_FREE = 0, /*!< contains a free
compressed page */
BUF_BLOCK_POOL_WATCH = 0, /*!< a sentinel for the buffer pool
watch, element of buf_pool_watch[] */
watch, element of buf_pool->watch[] */
BUF_BLOCK_ZIP_PAGE, /*!< contains a clean
compressed page */
BUF_BLOCK_ZIP_DIRTY, /*!< contains a compressed
......@@ -1210,10 +1210,10 @@ struct buf_page_struct{
#endif /* !UNIV_HOTBACKUP */
page_zip_des_t zip; /*!< compressed page; zip.data
(but not the data it points to) is
also protected by buf_pool_mutex;
also protected by buf_pool->mutex;
state == BUF_BLOCK_ZIP_PAGE and
zip.data == NULL means an active
buf_pool_watch */
buf_pool->watch */
#ifndef UNIV_HOTBACKUP
buf_page_t* hash; /*!< node used in chaining to
buf_pool->page_hash or
......@@ -1224,15 +1224,16 @@ struct buf_page_struct{
#endif /* UNIV_DEBUG */
/** @name Page flushing fields
All these are protected by buf_pool_mutex. */
All these are protected by buf_pool->mutex. */
/* @{ */
UT_LIST_NODE_T(buf_page_t) list;
/*!< based on state, this is a
list node, protected either by
buf_pool_mutex or by
flush_list_mutex, in one of the
following lists in buf_pool:
buf_pool->mutex or by
buf_pool->flush_list_mutex,
in one of the following lists in
buf_pool:
- BUF_BLOCK_NOT_USED: free
- BUF_BLOCK_FILE_PAGE: flush_list
......@@ -1242,9 +1243,9 @@ struct buf_page_struct{
If bpage is part of flush_list
then the node pointers are
covered by flush_list_mutex.
covered by buf_pool->flush_list_mutex.
Otherwise these pointers are
protected by buf_pool_mutex.
protected by buf_pool->mutex.
The contents of the list node
is undefined if !in_flush_list
......@@ -1256,17 +1257,18 @@ struct buf_page_struct{
#ifdef UNIV_DEBUG
ibool in_flush_list; /*!< TRUE if in buf_pool->flush_list;
when flush_list_mutex is free, the
following should hold: in_flush_list
when buf_pool->flush_list_mutex is
free, the following should hold:
in_flush_list
== (state == BUF_BLOCK_FILE_PAGE
|| state == BUF_BLOCK_ZIP_DIRTY)
Writes to this field must be
covered by both block->mutex
and flush_list_mutex. Hence
and buf_pool->flush_list_mutex. Hence
reads can happen while holding
any one of the two mutexes */
ibool in_free_list; /*!< TRUE if in buf_pool->free; when
buf_pool_mutex is free, the following
buf_pool->mutex is free, the following
should hold: in_free_list
== (state == BUF_BLOCK_NOT_USED) */
#endif /* UNIV_DEBUG */
......@@ -1286,7 +1288,7 @@ struct buf_page_struct{
modifications are on disk.
Writes to this field must be
covered by both block->mutex
and flush_list_mutex. Hence
and buf_pool->flush_list_mutex. Hence
reads can happen while holding
any one of the two mutexes */
/* @} */
......@@ -1661,20 +1663,13 @@ struct buf_pool_struct{
/* @} */
};
/** mutex protecting the buffer pool struct and control blocks, except the
read-write lock in them */
extern mutex_t buf_pool_mutex;
/** mutex protecting the control blocks of compressed-only pages
(of type buf_page_t, not buf_block_t) */
extern mutex_t buf_pool_zip_mutex;
/** @name Accessors for buf_pool_mutex.
Use these instead of accessing buf_pool_mutex directly. */
/** @name Accessors for buf_pool->mutex.
Use these instead of accessing buf_pool->mutex directly. */
/* @{ */
/** Test if buf_pool_mutex is owned. */
/** Test if a buffer pool mutex is owned. */
#define buf_pool_mutex_own(b) mutex_own(&b->mutex)
/** Acquire the buffer pool mutex. */
/** Acquire a buffer pool mutex. */
#define buf_pool_mutex_enter(b) do { \
ut_ad(!mutex_own(&b->zip_mutex)); \
mutex_enter(&b->mutex); \
......
......@@ -84,6 +84,21 @@ buf_flush_init_for_writing(
ib_uint64_t newest_lsn); /*!< in: newest modification lsn
to the page */
#ifndef UNIV_HOTBACKUP
# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
/********************************************************************//**
Writes a flushable page asynchronously from the buffer pool to a file.
NOTE: buf_pool->mutex and block->mutex must be held upon entering this
function, and they will be released by this function after flushing.
This is loosely based on buf_flush_batch() and buf_flush_page().
@return TRUE if the page was flushed and the mutexes released */
UNIV_INTERN
ibool
buf_flush_page_try(
/*===============*/
buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
buf_block_t* block) /*!< in/out: buffer control block */
__attribute__((nonnull, warn_unused_result));
# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
/*******************************************************************//**
This utility flushes dirty blocks from the end of the LRU list.
NOTE: The calling thread may own latches to pages: to avoid deadlocks,
......
......@@ -174,10 +174,13 @@ store the charset-collation number; one byte is left unused, though */
/* Pack mbminlen, mbmaxlen to mbminmaxlen. */
#define DATA_MBMINMAXLEN(mbminlen, mbmaxlen) \
((mbmaxlen) * DATA_MBMAX + (mbminlen))
/* Get mbminlen from mbminmaxlen. */
#define DATA_MBMINLEN(mbminmaxlen) UNIV_EXPECT(((mbminmaxlen) % DATA_MBMAX), 1)
/* Get mbminlen from mbminmaxlen. Cast the result of UNIV_EXPECT to ulint
because in GCC it returns a long. */
#define DATA_MBMINLEN(mbminmaxlen) ((ulint) \
UNIV_EXPECT(((mbminmaxlen) % DATA_MBMAX), \
1))
/* Get mbmaxlen from mbminmaxlen. */
#define DATA_MBMAXLEN(mbminmaxlen) ((mbminmaxlen) / DATA_MBMAX)
#define DATA_MBMAXLEN(mbminmaxlen) ((ulint) ((mbminmaxlen) / DATA_MBMAX))
#ifndef UNIV_HOTBACKUP
/*********************************************************************//**
......
......@@ -63,6 +63,11 @@ typedef enum {
/** Operations that can currently be buffered. */
extern ibuf_use_t ibuf_use;
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
/** Flag to control insert buffer debugging. */
extern uint ibuf_debug;
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
/** The insert buffer control structure */
extern ibuf_t* ibuf;
......
/*****************************************************************************
Copyright (c) 2007, 2009, Innobase Oy. 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
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/**************************************************//**
@file include/mysql_addons.h
This file contains functions that need to be added to
MySQL code but have not been added yet.
Whenever you add a function here submit a MySQL bug
report (feature request) with the implementation. Then
write the bug number in the comment before the
function in this file.
When MySQL commits the function it can be deleted from
here. In a perfect world this file exists but is empty.
Created November 07, 2007 Vasil Dimov
*******************************************************/
......@@ -76,6 +76,12 @@ struct os_event_struct {
/*!< list of all created events */
};
/** Denotes an infinite delay for os_event_wait_time() */
#define OS_SYNC_INFINITE_TIME ULINT_UNDEFINED
/** Return value of os_event_wait_time() when the time is exceeded */
#define OS_SYNC_TIME_EXCEEDED 1
/** Operating system mutex */
typedef struct os_mutex_struct os_mutex_str_t;
/** Operating system mutex handle */
......@@ -173,7 +179,23 @@ os_event_wait_low(
os_event_reset(). */
#define os_event_wait(event) os_event_wait_low(event, 0)
#define os_event_wait_time(e, t) os_event_wait_time_low(event, t, 0)
/**********************************************************//**
Waits for an event object until it is in the signaled state or
a timeout is exceeded. In Unix the timeout is always infinite.
@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
UNIV_INTERN
ulint
os_event_wait_time_low(
/*===================*/
os_event_t event, /*!< in: event to wait */
ulint time_in_usec, /*!< in: timeout in
microseconds, or
OS_SYNC_INFINITE_TIME */
ib_int64_t reset_sig_count); /*!< in: zero or the value
returned by previous call of
os_event_reset(). */
/*********************************************************//**
Creates an operating system mutex semaphore. Because these are slow, the
mutex semaphore of InnoDB itself (mutex_t) should be used where possible.
......
......@@ -801,9 +801,9 @@ UNIV_INTERN
void
rec_print(
/*======*/
FILE* file, /*!< in: file where to print */
const rec_t* rec, /*!< in: physical record */
dict_index_t* index); /*!< in: record descriptor */
FILE* file, /*!< in: file where to print */
const rec_t* rec, /*!< in: physical record */
const dict_index_t* index); /*!< in: record descriptor */
#endif /* UNIV_HOTBACKUP */
/* Maximum lengths for the data in a physical record if the offsets
......
......@@ -538,6 +538,10 @@ struct mysql_row_templ_struct {
Innobase record in the current index;
not defined if template_type is
ROW_MYSQL_WHOLE_ROW */
ulint clust_rec_field_no; /*!< field number of the column in an
Innobase record in the clustered index;
not defined if template_type is
ROW_MYSQL_WHOLE_ROW */
ulint mysql_col_offset; /*!< offset of the column in the MySQL
row format */
ulint mysql_col_len; /*!< length of the column in the MySQL
......
......@@ -167,8 +167,11 @@ row_upd_changes_field_size_or_external(
const upd_t* update);/*!< in: update vector */
#endif /* !UNIV_HOTBACKUP */
/***********************************************************//**
Replaces the new column values stored in the update vector to the record
given. No field size changes are allowed. */
Replaces the new column values stored in the update vector to the
record given. No field size changes are allowed. This function is
usually invoked on a clustered index. The only use case for a
secondary index is row_ins_sec_index_entry_by_modify() or its
counterpart in ibuf_insert_to_index_page(). */
UNIV_INTERN
void
row_upd_rec_in_place(
......
......@@ -57,6 +57,15 @@ extern const char srv_mysql50_table_name_prefix[9];
thread starts running */
extern os_event_t srv_lock_timeout_thread_event;
/* The monitor thread waits on this event. */
extern os_event_t srv_monitor_event;
/* The lock timeout thread waits on this event. */
extern os_event_t srv_timeout_event;
/* The error monitor thread waits on this event. */
extern os_event_t srv_error_event;
/* If the last data file is auto-extended, we add this many pages to it
at a time */
#define SRV_AUTO_EXTEND_INCREMENT \
......
......@@ -470,6 +470,20 @@ struct trx_struct{
of view of concurrency control:
TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY,
... */
/*------------------------------*/
/* MySQL has a transaction coordinator to coordinate two phase
commit between multiple storage engines and the binary log. When
an engine participates in a transaction, it's responsible for
registering itself using the trans_register_ha() API. */
unsigned is_registered:1;/* This flag is set to 1 after the
transaction has been registered with
the coordinator using the XA API, and
is set to 0 after commit or rollback. */
unsigned owns_prepare_mutex:1;/* 1 if owns prepare mutex, if
this is set to 1 then registered should
also be set to 1. This is used in the
XA code */
/*------------------------------*/
ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */
ulint check_foreigns; /* normally TRUE, but if the user
wants to suppress foreign key checks,
......@@ -500,9 +514,6 @@ struct trx_struct{
in that case we must flush the log
in trx_commit_complete_for_mysql() */
ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */
ulint active_trans; /*!< 1 - if a transaction in MySQL
is active. 2 - if prepare_commit_mutex
was taken */
ulint has_search_latch;
/* TRUE if this trx has latched the
search system latch in S-mode */
......
......@@ -4859,11 +4859,11 @@ loop:
ut_a(rec);
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
#if 0
fprintf(stderr,
"Validating %lu %lu\n",
(ulong) space, (ulong) page_no);
#endif
lock_mutex_exit_kernel();
/* If this thread is holding the file space
......
......@@ -3098,10 +3098,15 @@ loop:
if (srv_fast_shutdown < 2
&& (srv_error_monitor_active
|| srv_lock_timeout_active || srv_monitor_active)) {
|| srv_lock_timeout_active
|| srv_monitor_active)) {
mutex_exit(&kernel_mutex);
os_event_set(srv_error_event);
os_event_set(srv_monitor_event);
os_event_set(srv_timeout_event);
goto loop;
}
......@@ -3128,6 +3133,8 @@ loop:
log_buffer_flush_to_disk();
mutex_exit(&kernel_mutex);
return; /* We SKIP ALL THE REST !! */
}
......
This directory contains patches that need to be applied to the MySQL
source tree in order to get the mysql-test suite to succeed (when
storage/innobase is replaced with this InnoDB branch). Things to keep
in mind when adding new patches here:
* The patch must be appliable from the mysql top-level source directory.
* The patch filename must end in ".diff".
* All patches here are expected to apply cleanly to the latest MySQL 5.1
tree when storage/innobase is replaced with this InnoDB branch. If
changes to either of those cause the patch to fail, then please check
whether the patch is still needed and, if yes, adjust it so it applies
cleanly.
* If applicable, always submit the patch at http://bugs.mysql.com and
name the file here like bug%d.diff. Once the patch is committed to
MySQL remove the file from here.
* If the patch cannot be proposed for inclusion in the MySQL source tree
(via http://bugs.mysql.com) then add a comment at the beginning of the
patch, explaining the problem it is solving, how it does solve it and
why it is not applicable for inclusion in the MySQL source tree.
Obviously this is a very bad situation and should be avoided at all
costs, especially for files that are in the MySQL source repository
(not in storage/innobase).
* If you ever need to add a patch here that is not related to mysql-test
suite, then please move this directory from ./mysql-test/patches to
./patches and remove this text.
InnoDB's estimate for the index cardinality depends on a pseudo random
number generator (it picks up random pages to sample). After an
optimization that was made in r2625 the following EXPLAINs started
returning a different number of rows (3 instead of 4).
This patch adjusts the result file.
This patch cannot be proposed to MySQL because the failures occur only
in this tree and do not occur in the standard InnoDB 5.1. Furthermore,
the file index_merge2.inc is used by other engines too.
--- mysql-test/r/index_merge_innodb.result.orig 2008-09-30 18:32:13.000000000 +0300
+++ mysql-test/r/index_merge_innodb.result 2008-09-30 18:33:01.000000000 +0300
@@ -111,7 +111,7 @@
explain select count(*) from t1 where
key1a = 2 and key1b is null and key2a = 2 and key2b is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 4 Using intersect(i1,i2); Using where; Using index
+1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 3 Using intersect(i1,i2); Using where; Using index
select count(*) from t1 where
key1a = 2 and key1b is null and key2a = 2 and key2b is null;
count(*)
@@ -119,7 +119,7 @@
explain select count(*) from t1 where
key1a = 2 and key1b is null and key3a = 2 and key3b is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 4 Using intersect(i1,i3); Using where; Using index
+1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 3 Using intersect(i1,i3); Using where; Using index
select count(*) from t1 where
key1a = 2 and key1b is null and key3a = 2 and key3b is null;
count(*)
--- mysql-test/r/information_schema.result.orig 2009-01-31 03:38:50.000000000 +0200
+++ mysql-test/r/information_schema.result 2009-01-31 07:51:58.000000000 +0200
@@ -71,6 +71,13 @@
TRIGGERS
USER_PRIVILEGES
VIEWS
+INNODB_CMP_RESET
+INNODB_TRX
+INNODB_CMPMEM_RESET
+INNODB_LOCK_WAITS
+INNODB_CMPMEM
+INNODB_CMP
+INNODB_LOCKS
columns_priv
db
event
@@ -799,6 +806,8 @@
TABLES UPDATE_TIME datetime
TABLES CHECK_TIME datetime
TRIGGERS CREATED datetime
+INNODB_TRX trx_started datetime
+INNODB_TRX trx_wait_started datetime
event execute_at datetime
event last_executed datetime
event starts datetime
@@ -852,7 +861,7 @@
flush privileges;
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
table_schema count(*)
-information_schema 28
+information_schema 35
mysql 22
create table t1 (i int, j int);
create trigger trg1 before insert on t1 for each row
@@ -1267,6 +1276,13 @@
TRIGGERS TRIGGER_SCHEMA
USER_PRIVILEGES GRANTEE
VIEWS TABLE_SCHEMA
+INNODB_CMP_RESET page_size
+INNODB_TRX trx_id
+INNODB_CMPMEM_RESET page_size
+INNODB_LOCK_WAITS requesting_trx_id
+INNODB_CMPMEM page_size
+INNODB_CMP page_size
+INNODB_LOCKS lock_id
SELECT t.table_name, c1.column_name
FROM information_schema.tables t
INNER JOIN
@@ -1310,6 +1326,13 @@
TRIGGERS TRIGGER_SCHEMA
USER_PRIVILEGES GRANTEE
VIEWS TABLE_SCHEMA
+INNODB_CMP_RESET page_size
+INNODB_TRX trx_id
+INNODB_CMPMEM_RESET page_size
+INNODB_LOCK_WAITS requesting_trx_id
+INNODB_CMPMEM page_size
+INNODB_CMP page_size
+INNODB_LOCKS lock_id
SELECT MAX(table_name) FROM information_schema.tables WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test');
MAX(table_name)
VIEWS
@@ -1386,6 +1409,13 @@
FILES information_schema.FILES 1
GLOBAL_STATUS information_schema.GLOBAL_STATUS 1
GLOBAL_VARIABLES information_schema.GLOBAL_VARIABLES 1
+INNODB_CMP information_schema.INNODB_CMP 1
+INNODB_CMPMEM information_schema.INNODB_CMPMEM 1
+INNODB_CMPMEM_RESET information_schema.INNODB_CMPMEM_RESET 1
+INNODB_CMP_RESET information_schema.INNODB_CMP_RESET 1
+INNODB_LOCKS information_schema.INNODB_LOCKS 1
+INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1
+INNODB_TRX information_schema.INNODB_TRX 1
KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
PARTITIONS information_schema.PARTITIONS 1
PLUGINS information_schema.PLUGINS 1
diff mysql-test/r/information_schema_db.result.orig mysql-test/r/information_schema_db.result
--- mysql-test/r/information_schema_db.result.orig 2008-08-04 09:27:49.000000000 +0300
+++ mysql-test/r/information_schema_db.result 2008-10-07 12:26:31.000000000 +0300
@@ -33,6 +33,13 @@
TRIGGERS
USER_PRIVILEGES
VIEWS
+INNODB_CMP_RESET
+INNODB_TRX
+INNODB_CMPMEM_RESET
+INNODB_LOCK_WAITS
+INNODB_CMPMEM
+INNODB_CMP
+INNODB_LOCKS
show tables from INFORMATION_SCHEMA like 'T%';
Tables_in_information_schema (T%)
TABLES
diff mysql-test/r/mysqlshow.result.orig mysql-test/r/mysqlshow.result
--- mysql-test/r/mysqlshow.result.orig 2008-08-04 09:27:51.000000000 +0300
+++ mysql-test/r/mysqlshow.result 2008-10-07 12:35:39.000000000 +0300
@@ -107,6 +107,13 @@
| TRIGGERS |
| USER_PRIVILEGES |
| VIEWS |
+| INNODB_CMP_RESET |
+| INNODB_TRX |
+| INNODB_CMPMEM_RESET |
+| INNODB_LOCK_WAITS |
+| INNODB_CMPMEM |
+| INNODB_CMP |
+| INNODB_LOCKS |
+---------------------------------------+
Database: INFORMATION_SCHEMA
+---------------------------------------+
@@ -140,6 +147,13 @@
| TRIGGERS |
| USER_PRIVILEGES |
| VIEWS |
+| INNODB_CMP_RESET |
+| INNODB_TRX |
+| INNODB_CMPMEM_RESET |
+| INNODB_LOCK_WAITS |
+| INNODB_CMPMEM |
+| INNODB_CMP |
+| INNODB_LOCKS |
+---------------------------------------+
Wildcard: inf_rmation_schema
+--------------------+
--- mysql-test/suite/sys_vars/t/innodb_change_buffering_basic.test.orig Mon Mar 15 16:15:22 2010
+++ mysql-test/suite/sys_vars/t/innodb_change_buffering_basic.test Fri Mar 19 01:19:09 2010
@@ -11,8 +11,8 @@
#
# exists as global only
#
---echo Valid values are 'inserts' and 'none'
-select @@global.innodb_change_buffering in ('inserts', 'none');
+--echo Valid values are 'inserts', 'deletes', 'changes', 'purges', 'all', and 'none'
+select @@global.innodb_change_buffering in ('inserts', 'deletes', 'changes', 'purges', 'all', 'none');
select @@global.innodb_change_buffering;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.innodb_change_buffering;
--- mysql-test/suite/sys_vars/r/innodb_change_buffering_basic.result.orig Mon Mar 15 16:15:22 2010
+++ mysql-test/suite/sys_vars/r/innodb_change_buffering_basic.result Fri Mar 19 01:23:58 2010
@@ -1,28 +1,28 @@
SET @start_global_value = @@global.innodb_change_buffering;
SELECT @start_global_value;
@start_global_value
-inserts
-Valid values are 'inserts' and 'none'
-select @@global.innodb_change_buffering in ('inserts', 'none');
-@@global.innodb_change_buffering in ('inserts', 'none')
+all
+Valid values are 'inserts', 'deletes', 'changes', 'purges', 'all', and 'none'
+select @@global.innodb_change_buffering in ('inserts', 'deletes', 'changes', 'purges', 'all', 'none');
+@@global.innodb_change_buffering in ('inserts', 'deletes', 'changes', 'purges', 'all', 'none')
1
select @@global.innodb_change_buffering;
@@global.innodb_change_buffering
-inserts
+all
select @@session.innodb_change_buffering;
ERROR HY000: Variable 'innodb_change_buffering' is a GLOBAL variable
show global variables like 'innodb_change_buffering';
Variable_name Value
-innodb_change_buffering inserts
+innodb_change_buffering all
show session variables like 'innodb_change_buffering';
Variable_name Value
-innodb_change_buffering inserts
+innodb_change_buffering all
select * from information_schema.global_variables where variable_name='innodb_change_buffering';
VARIABLE_NAME VARIABLE_VALUE
-INNODB_CHANGE_BUFFERING inserts
+INNODB_CHANGE_BUFFERING all
select * from information_schema.session_variables where variable_name='innodb_change_buffering';
VARIABLE_NAME VARIABLE_VALUE
-INNODB_CHANGE_BUFFERING inserts
+INNODB_CHANGE_BUFFERING all
set global innodb_change_buffering='none';
select @@global.innodb_change_buffering;
@@global.innodb_change_buffering
@@ -60,4 +60,4 @@
SET @@global.innodb_change_buffering = @start_global_value;
SELECT @@global.innodb_change_buffering;
@@global.innodb_change_buffering
-inserts
+all
diff mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test.orig mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test
--- mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test.orig 2008-10-07 11:32:30.000000000 +0300
+++ mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test 2008-10-07 11:52:14.000000000 +0300
@@ -37,10 +37,6 @@
# Check if Value can set #
####################################################################
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
-SET @@GLOBAL.innodb_file_per_table=1;
---echo Expected error 'Read only variable'
-
SELECT COUNT(@@GLOBAL.innodb_file_per_table);
--echo 1 Expected
@@ -52,7 +48,7 @@
# Check if the value in GLOBAL Table matches value in variable #
#################################################################
-SELECT @@GLOBAL.innodb_file_per_table = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_file_per_table';
--echo 1 Expected
diff mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result.orig mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result
--- mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result.orig 2008-10-07 11:32:02.000000000 +0300
+++ mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result 2008-10-07 11:52:47.000000000 +0300
@@ -4,18 +4,15 @@
1
1 Expected
'#---------------------BS_STVARS_028_02----------------------#'
-SET @@GLOBAL.innodb_file_per_table=1;
-ERROR HY000: Variable 'innodb_file_per_table' is a read only variable
-Expected error 'Read only variable'
SELECT COUNT(@@GLOBAL.innodb_file_per_table);
COUNT(@@GLOBAL.innodb_file_per_table)
1
1 Expected
'#---------------------BS_STVARS_028_03----------------------#'
-SELECT @@GLOBAL.innodb_file_per_table = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_file_per_table';
-@@GLOBAL.innodb_file_per_table = VARIABLE_VALUE
+IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
1
1 Expected
SELECT COUNT(@@GLOBAL.innodb_file_per_table);
--- mysql-test/suite/sys_vars/t/innodb_lock_wait_timeout_basic.test.orig 2008-08-04 09:28:16.000000000 +0300
+++ mysql-test/suite/sys_vars/t/innodb_lock_wait_timeout_basic.test 2008-10-07 11:14:15.000000000 +0300
@@ -37,10 +37,6 @@
# Check if Value can set #
####################################################################
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
-SET @@GLOBAL.innodb_lock_wait_timeout=1;
---echo Expected error 'Read only variable'
-
SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
--echo 1 Expected
@@ -84,13 +80,9 @@
SELECT COUNT(@@innodb_lock_wait_timeout);
--echo 1 Expected
---Error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT COUNT(@@local.innodb_lock_wait_timeout);
---echo Expected error 'Variable is a GLOBAL variable'
---Error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT COUNT(@@SESSION.innodb_lock_wait_timeout);
---echo Expected error 'Variable is a GLOBAL variable'
SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
--echo 1 Expected
--- mysql-test/suite/sys_vars/r/innodb_lock_wait_timeout_basic.result.orig 2008-08-04 09:27:50.000000000 +0300
+++ mysql-test/suite/sys_vars/r/innodb_lock_wait_timeout_basic.result 2008-10-07 11:15:14.000000000 +0300
@@ -4,9 +4,6 @@
1
1 Expected
'#---------------------BS_STVARS_032_02----------------------#'
-SET @@GLOBAL.innodb_lock_wait_timeout=1;
-ERROR HY000: Variable 'innodb_lock_wait_timeout' is a read only variable
-Expected error 'Read only variable'
SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
COUNT(@@GLOBAL.innodb_lock_wait_timeout)
1
@@ -39,11 +36,11 @@
1
1 Expected
SELECT COUNT(@@local.innodb_lock_wait_timeout);
-ERROR HY000: Variable 'innodb_lock_wait_timeout' is a GLOBAL variable
-Expected error 'Variable is a GLOBAL variable'
+COUNT(@@local.innodb_lock_wait_timeout)
+1
SELECT COUNT(@@SESSION.innodb_lock_wait_timeout);
-ERROR HY000: Variable 'innodb_lock_wait_timeout' is a GLOBAL variable
-Expected error 'Variable is a GLOBAL variable'
+COUNT(@@SESSION.innodb_lock_wait_timeout)
+1
SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
COUNT(@@GLOBAL.innodb_lock_wait_timeout)
1
--- mysql-test/suite/sys_vars/r/innodb_thread_concurrency_basic.result.orig 2008-12-04 18:45:52 -06:00
+++ mysql-test/suite/sys_vars/r/innodb_thread_concurrency_basic.result 2009-02-12 02:05:48 -06:00
@@ -1,19 +1,19 @@
SET @global_start_value = @@global.innodb_thread_concurrency;
SELECT @global_start_value;
@global_start_value
-8
+0
'#--------------------FN_DYNVARS_046_01------------------------#'
SET @@global.innodb_thread_concurrency = 0;
SET @@global.innodb_thread_concurrency = DEFAULT;
SELECT @@global.innodb_thread_concurrency;
@@global.innodb_thread_concurrency
-8
+0
'#---------------------FN_DYNVARS_046_02-------------------------#'
SET innodb_thread_concurrency = 1;
ERROR HY000: Variable 'innodb_thread_concurrency' is a GLOBAL variable and should be set with SET GLOBAL
SELECT @@innodb_thread_concurrency;
@@innodb_thread_concurrency
-8
+0
SELECT local.innodb_thread_concurrency;
ERROR 42S02: Unknown table 'local' in field list
SET global innodb_thread_concurrency = 0;
@@ -93,4 +93,4 @@
SET @@global.innodb_thread_concurrency = @global_start_value;
SELECT @@global.innodb_thread_concurrency;
@@global.innodb_thread_concurrency
-8
+0
The partition_innodb test only fails if run immediately after innodb_trx_weight.
The reason for this failure is that innodb_trx_weight creates deadlocks and
leaves something like this in the SHOW ENGINE INNODB STATUS output:
------------------------
LATEST DETECTED DEADLOCK
------------------------
090213 10:26:25
*** (1) TRANSACTION:
TRANSACTION 313, ACTIVE 0 sec, OS thread id 13644672 inserting
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 488, 3 row lock(s)
MySQL thread id 3, query id 36 localhost root update
The regular expressions that partition_innodb is using are intended to extract
the lock structs and row locks numbers from another part of the output:
------------
TRANSACTIONS
------------
Trx id counter 31D
Purge done for trx's n:o < 0 undo n:o < 0
History list length 4
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0, not started, OS thread id 13645056
0 lock struct(s), heap size 488, 0 row lock(s)
MySQL thread id 8, query id 81 localhost root
In the InnoDB Plugin a transaction id is not printed as 2 consecutive
decimal integers (as it is in InnoDB 5.1) but rather as a single
hexadecimal integer. Thus the regular expressions somehow pick the wrong
part of the SHOW ENGINE INNODB STATUS output.
So after the regular expressions are adjusted to the InnoDB Plugin's variant
of trx_id prinout, then they pick the expected part of the output.
This patch cannot be proposed to MySQL because the failures occur only
in this tree and do not occur in the standard InnoDB 5.1.
--- mysql-test/t/partition_innodb.test 2008-11-14 22:51:17 +0000
+++ mysql-test/t/partition_innodb.test 2009-02-13 07:36:07 +0000
@@ -27,14 +27,14 @@
# grouping/referencing in replace_regex is very slow on long strings,
# removing all before/after the interesting row before grouping/referencing
---replace_regex /.*---TRANSACTION [0-9]+ [0-9]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
+--replace_regex /.*---TRANSACTION [0-9A-F]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
SHOW ENGINE InnoDB STATUS;
UPDATE t1 SET data = data*2 WHERE data = 2;
# grouping/referencing in replace_regex is very slow on long strings,
# removing all before/after the interesting row before grouping/referencing
---replace_regex /.*---TRANSACTION [0-9]+ [0-9]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
+--replace_regex /.*---TRANSACTION [0-9A-F]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
SHOW ENGINE InnoDB STATUS;
SET @@session.tx_isolation = @old_tx_isolation;
......@@ -72,6 +72,9 @@ UNIV_INTERN ulint os_event_count = 0;
UNIV_INTERN ulint os_mutex_count = 0;
UNIV_INTERN ulint os_fast_mutex_count = 0;
/* The number of microsecnds in a second. */
static const ulint MICROSECS_IN_A_SECOND = 1000000;
/* Because a mutex is embedded inside an event and there is an
event embedded inside a mutex, on free, this generates a recursive call.
This version of the free event function doesn't acquire the global lock */
......@@ -121,6 +124,57 @@ os_cond_init(
#endif
}
/*********************************************************//**
Do a timed wait on condition variable.
@return TRUE if timed out, FALSE otherwise */
UNIV_INLINE
ibool
os_cond_wait_timed(
/*===============*/
os_cond_t* cond, /*!< in: condition variable. */
os_fast_mutex_t* mutex, /*!< in: fast mutex */
#ifndef __WIN__
const struct timespec* abstime /*!< in: timeout */
#else
ulint time_in_ms /*!< in: timeout in
milliseconds*/
#endif /* !__WIN__ */
)
{
#ifdef __WIN__
BOOL ret;
ut_a(sleep_condition_variable != NULL);
ret = sleep_condition_variable(cond, mutex, time_in_ms);
if (!ret && GetLastError() == WAIT_TIMEOUT) {
return(TRUE);
}
ut_a(ret);
return(FALSE);
#else
int ret;
ret = pthread_cond_timedwait(cond, mutex, abstime);
switch (ret) {
case 0:
case ETIMEDOUT:
break;
default:
fprintf(stderr, " InnoDB: pthread_cond_timedwait() returned: "
"%d: abstime={%lu,%lu}\n",
ret, abstime->tv_sec, abstime->tv_nsec);
ut_error;
}
return(ret == ETIMEDOUT);
#endif
}
/*********************************************************//**
Wait on condition variable */
UNIV_INLINE
......@@ -572,6 +626,128 @@ os_event_wait_low(
}
}
/**********************************************************//**
Waits for an event object until it is in the signaled state or
a timeout is exceeded.
@return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
UNIV_INTERN
ulint
os_event_wait_time_low(
/*===================*/
os_event_t event, /*!< in: event to wait */
ulint time_in_usec, /*!< in: timeout in
microseconds, or
OS_SYNC_INFINITE_TIME */
ib_int64_t reset_sig_count) /*!< in: zero or the value
returned by previous call of
os_event_reset(). */
{
ibool timed_out;
ib_int64_t old_signal_count;
#ifdef __WIN__
DWORD time_in_ms;
if (!srv_use_native_conditions) {
DWORD err;
ut_a(event);
if (time_in_usec != OS_SYNC_INFINITE_TIME) {
time_in_ms = time_in_ms / 1000;
err = WaitForSingleObject(event->handle, time_in_ms);
} else {
err = WaitForSingleObject(event->handle, INFINITE);
}
if (err == WAIT_OBJECT_0) {
return(0);
} else if (err == WAIT_TIMEOUT) {
return(OS_SYNC_TIME_EXCEEDED);
}
ut_error;
/* Dummy value to eliminate compiler warning. */
return(42);
} else {
ut_a(sleep_condition_variable != NULL);
if (time_in_usec != OS_SYNC_INFINITE_TIME) {
time_in_ms = time_in_usec / 1000;
} else {
time_in_ms = INFINITE;
}
}
#else
struct timespec abstime;
if (time_in_usec != OS_SYNC_INFINITE_TIME) {
struct timeval tv;
int ret;
ulint sec;
ulint usec;
ret = ut_usectime(&sec, &usec);
ut_a(ret == 0);
tv.tv_sec = sec;
tv.tv_usec = usec;
tv.tv_usec += time_in_usec;
if ((ulint) tv.tv_usec >= MICROSECS_IN_A_SECOND) {
tv.tv_sec += time_in_usec / MICROSECS_IN_A_SECOND;
tv.tv_usec %= MICROSECS_IN_A_SECOND;
}
abstime.tv_sec = tv.tv_sec;
abstime.tv_nsec = tv.tv_usec * 1000;
} else {
abstime.tv_nsec = 999999999;
abstime.tv_sec = (time_t) ULINT_MAX;
}
ut_a(abstime.tv_nsec <= 999999999);
#endif /* __WIN__ */
os_fast_mutex_lock(&event->os_mutex);
if (reset_sig_count) {
old_signal_count = reset_sig_count;
} else {
old_signal_count = event->signal_count;
}
do {
if (event->is_set == TRUE
|| event->signal_count != old_signal_count) {
break;
}
timed_out = os_cond_wait_timed(
&event->cond_var, &event->os_mutex,
#ifndef __WIN__
&abstime
#else
time_in_ms
#endif /* !__WIN__ */
);
} while (!timed_out);
os_fast_mutex_unlock(&event->os_mutex);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
}
return(timed_out ? OS_SYNC_TIME_EXCEEDED : 0);
}
/*********************************************************//**
Creates an operating system mutex semaphore. Because these are slow, the
mutex semaphore of InnoDB itself (mutex_t) should be used where possible.
......
......@@ -146,10 +146,11 @@ MYSQL_PLUGIN_ACTIONS(innobase, [
AC_MSG_CHECKING(whether Solaris libc atomic functions are available)
# either define HAVE_IB_SOLARIS_ATOMICS or not
AC_CHECK_FUNCS(atomic_add_long \
AC_CHECK_FUNCS(atomic_cas_ulong \
atomic_cas_32 \
atomic_cas_64 \
atomic_cas_ulong,
atomic_add_long_nv \
atomic_swap_uchar,
AC_DEFINE([HAVE_IB_SOLARIS_ATOMICS], [1],
[Define to 1 if Solaris libc atomic functions \
......
......@@ -1749,9 +1749,9 @@ UNIV_INTERN
void
rec_print(
/*======*/
FILE* file, /*!< in: file where to print */
const rec_t* rec, /*!< in: physical record */
dict_index_t* index) /*!< in: record descriptor */
FILE* file, /*!< in: file where to print */
const rec_t* rec, /*!< in: physical record */
const dict_index_t* index) /*!< in: record descriptor */
{
ut_ad(index);
......
......@@ -503,7 +503,7 @@ row_mysql_convert_row_to_innobase(
row is used, as row may contain
pointers to this record! */
{
mysql_row_templ_t* templ;
const mysql_row_templ_t*templ;
dfield_t* dfield;
ulint i;
......
......@@ -2667,21 +2667,22 @@ row_sel_store_mysql_rec(
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
const rec_t* rec, /*!< in: Innobase record in the index
which was described in prebuilt's
template; must be protected by
a page latch */
template, or in the clustered index;
must be protected by a page latch */
ibool rec_clust, /*!< in: TRUE if rec is in the
clustered index instead of
prebuilt->index */
const ulint* offsets) /*!< in: array returned by
rec_get_offsets() */
rec_get_offsets(rec) */
{
mysql_row_templ_t* templ;
mem_heap_t* extern_field_heap = NULL;
mem_heap_t* heap;
const byte* data;
ulint len;
ulint i;
mem_heap_t* extern_field_heap = NULL;
mem_heap_t* heap;
ulint i;
ut_ad(prebuilt->mysql_template);
ut_ad(prebuilt->default_rec);
ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
mem_heap_free(prebuilt->blob_heap);
......@@ -2690,10 +2691,15 @@ row_sel_store_mysql_rec(
for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i;
const mysql_row_templ_t*templ = prebuilt->mysql_template + i;
const byte* data;
ulint len;
ulint field_no;
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
templ->rec_field_no))) {
field_no = rec_clust
? templ->clust_rec_field_no : templ->rec_field_no;
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) {
/* Copy an externally stored field to the temporary
heap */
......@@ -2721,7 +2727,7 @@ row_sel_store_mysql_rec(
data = btr_rec_copy_externally_stored_field(
rec, offsets,
dict_table_zip_size(prebuilt->table),
templ->rec_field_no, &len, heap);
field_no, &len, heap);
if (UNIV_UNLIKELY(!data)) {
/* The externally stored field
......@@ -2742,8 +2748,7 @@ row_sel_store_mysql_rec(
} else {
/* Field is stored in the row. */
data = rec_get_nth_field(rec, offsets,
templ->rec_field_no, &len);
data = rec_get_nth_field(rec, offsets, field_no, &len);
if (UNIV_UNLIKELY(templ->type == DATA_BLOB)
&& len != UNIV_SQL_NULL) {
......@@ -3105,7 +3110,7 @@ row_sel_pop_cached_row_for_mysql(
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct */
{
ulint i;
mysql_row_templ_t* templ;
const mysql_row_templ_t*templ;
byte* cached_rec;
ut_ad(prebuilt->n_fetch_cached > 0);
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
......@@ -3162,15 +3167,21 @@ ibool
row_sel_push_cache_row_for_mysql(
/*=============================*/
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
const rec_t* rec, /*!< in: record to push; must
be protected by a page latch */
const ulint* offsets) /*!< in: rec_get_offsets() */
const rec_t* rec, /*!< in: record to push, in the index
which was described in prebuilt's
template, or in the clustered index;
must be protected by a page latch */
ibool rec_clust, /*!< in: TRUE if rec is in the
clustered index instead of
prebuilt->index */
const ulint* offsets) /*!< in: rec_get_offsets(rec) */
{
byte* buf;
ulint i;
ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
ut_a(!prebuilt->templ_contains_blob);
if (prebuilt->fetch_cache[0] == NULL) {
......@@ -3199,7 +3210,7 @@ row_sel_push_cache_row_for_mysql(
if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
prebuilt->fetch_cache[
prebuilt->n_fetch_cached],
prebuilt, rec, offsets))) {
prebuilt, rec, rec_clust, offsets))) {
return(FALSE);
}
......@@ -3600,7 +3611,8 @@ row_search_for_mysql(
ut_ad(!rec_get_deleted_flag(rec, comp));
if (!row_sel_store_mysql_rec(buf, prebuilt,
rec, offsets)) {
rec, FALSE,
offsets)) {
/* Only fresh inserts may contain
incomplete externally stored
columns. Pretend that such
......@@ -4234,7 +4246,6 @@ no_gap_lock:
is necessary, because we can only get the undo
information via the clustered index record. */
ut_ad(index != clust_index);
ut_ad(!dict_index_is_clust(index));
if (!lock_sec_rec_cons_read_sees(
......@@ -4350,26 +4361,10 @@ requires_clust_rec:
goto next_rec;
}
if (prebuilt->need_to_access_clustered) {
result_rec = clust_rec;
ut_ad(rec_offs_validate(result_rec, clust_index,
offsets));
} else {
/* We used 'offsets' for the clust rec, recalculate
them for 'rec' */
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
result_rec = rec;
}
/* result_rec can legitimately be delete-marked
now that it has been established that it points to a
clustered index record that exists in the read view. */
result_rec = clust_rec;
ut_ad(rec_offs_validate(result_rec, clust_index, offsets));
} else {
result_rec = rec;
ut_ad(!rec_get_deleted_flag(rec, comp));
}
/* We found a qualifying record 'result_rec'. At this point,
......@@ -4378,6 +4373,7 @@ requires_clust_rec:
ut_ad(rec_offs_validate(result_rec,
result_rec != rec ? clust_index : index,
offsets));
ut_ad(!rec_get_deleted_flag(result_rec, comp));
/* At this point, the clustered index record is protected
by a page latch that was acquired when pcur was positioned.
......@@ -4402,6 +4398,7 @@ requires_clust_rec:
cursor. */
if (!row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
result_rec != rec,
offsets)) {
/* Only fresh inserts may contain incomplete
externally stored columns. Pretend that such
......@@ -4419,15 +4416,31 @@ requires_clust_rec:
goto next_rec;
} else {
if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
if (UNIV_UNLIKELY
(prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE)) {
/* CHECK TABLE: fetch the row */
if (result_rec != rec
&& !prebuilt->need_to_access_clustered) {
/* We used 'offsets' for the clust
rec, recalculate them for 'rec' */
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED,
&heap);
result_rec = rec;
}
memcpy(buf + 4, result_rec
- rec_offs_extra_size(offsets),
rec_offs_size(offsets));
mach_write_to_4(buf,
rec_offs_extra_size(offsets) + 4);
} else {
if (!row_sel_store_mysql_rec(buf, prebuilt,
result_rec, offsets)) {
/* Returning a row to MySQL */
if (!row_sel_store_mysql_rec(buf, prebuilt, result_rec,
result_rec != rec,
offsets)) {
/* Only fresh inserts may contain
incomplete externally stored
columns. Pretend that such records do
......
......@@ -466,8 +466,11 @@ row_upd_changes_field_size_or_external(
#endif /* !UNIV_HOTBACKUP */
/***********************************************************//**
Replaces the new column values stored in the update vector to the record
given. No field size changes are allowed. */
Replaces the new column values stored in the update vector to the
record given. No field size changes are allowed. This function is
usually invoked on a clustered index. The only use case for a
secondary index is row_ins_sec_index_entry_by_modify() or its
counterpart in ibuf_insert_to_index_page(). */
UNIV_INTERN
void
row_upd_rec_in_place(
......
......@@ -695,6 +695,12 @@ struct srv_slot_struct{
/* Table for MySQL threads where they will be suspended to wait for locks */
UNIV_INTERN srv_slot_t* srv_mysql_table = NULL;
UNIV_INTERN os_event_t srv_timeout_event;
UNIV_INTERN os_event_t srv_monitor_event;
UNIV_INTERN os_event_t srv_error_event;
UNIV_INTERN os_event_t srv_lock_timeout_thread_event;
UNIV_INTERN srv_sys_t* srv_sys = NULL;
......@@ -1012,6 +1018,12 @@ srv_init(void)
ut_a(slot->event);
}
srv_error_event = os_event_create(NULL);
srv_timeout_event = os_event_create(NULL);
srv_monitor_event = os_event_create(NULL);
srv_lock_timeout_thread_event = os_event_create(NULL);
for (i = 0; i < SRV_MASTER + 1; i++) {
......@@ -2049,6 +2061,7 @@ srv_monitor_thread(
/*!< in: a dummy parameter required by
os_thread_create */
{
ib_int64_t sig_count;
double time_elapsed;
time_t current_time;
time_t last_table_monitor_time;
......@@ -2067,26 +2080,28 @@ srv_monitor_thread(
#endif
UT_NOT_USED(arg);
srv_last_monitor_time = time(NULL);
last_table_monitor_time = time(NULL);
last_tablespace_monitor_time = time(NULL);
last_monitor_time = time(NULL);
srv_last_monitor_time = ut_time();
last_table_monitor_time = ut_time();
last_tablespace_monitor_time = ut_time();
last_monitor_time = ut_time();
mutex_skipped = 0;
last_srv_print_monitor = srv_print_innodb_monitor;
loop:
srv_monitor_active = TRUE;
/* Wake up every 5 seconds to see if we need to print
monitor information. */
monitor information or if signalled at shutdown. */
os_thread_sleep(5000000);
sig_count = os_event_reset(srv_monitor_event);
current_time = time(NULL);
os_event_wait_time_low(srv_monitor_event, 5000000, sig_count);
current_time = ut_time();
time_elapsed = difftime(current_time, last_monitor_time);
if (time_elapsed > 15) {
last_monitor_time = time(NULL);
last_monitor_time = ut_time();
if (srv_print_innodb_monitor) {
/* Reset mutex_skipped counter everytime
......@@ -2130,7 +2145,7 @@ loop:
if (srv_print_innodb_tablespace_monitor
&& difftime(current_time,
last_tablespace_monitor_time) > 60) {
last_tablespace_monitor_time = time(NULL);
last_tablespace_monitor_time = ut_time();
fputs("========================"
"========================\n",
......@@ -2156,7 +2171,7 @@ loop:
if (srv_print_innodb_table_monitor
&& difftime(current_time, last_table_monitor_time) > 60) {
last_table_monitor_time = time(NULL);
last_table_monitor_time = ut_time();
fputs("===========================================\n",
stderr);
......@@ -2216,16 +2231,20 @@ srv_lock_timeout_thread(
ibool some_waits;
double wait_time;
ulint i;
ib_int64_t sig_count;
#ifdef UNIV_PFS_THREAD
pfs_register_thread(srv_lock_timeout_thread_key);
#endif
loop:
/* When someone is waiting for a lock, we wake up every second
and check if a timeout has passed for a lock wait */
os_thread_sleep(1000000);
sig_count = os_event_reset(srv_timeout_event);
os_event_wait_time_low(srv_timeout_event, 1000000, sig_count);
srv_lock_timeout_active = TRUE;
......@@ -2320,6 +2339,7 @@ srv_error_monitor_thread(
ulint fatal_cnt = 0;
ib_uint64_t old_lsn;
ib_uint64_t new_lsn;
ib_int64_t sig_count;
old_lsn = srv_start_lsn;
......@@ -2395,7 +2415,9 @@ loop:
fflush(stderr);
os_thread_sleep(1000000);
sig_count = os_event_reset(srv_error_event);
os_event_wait_time_low(srv_error_event, 1000000, sig_count);
if (srv_shutdown_state < SRV_SHUTDOWN_CLEANUP) {
......@@ -2646,6 +2668,21 @@ loop:
for (i = 0; i < 10; i++) {
ulint cur_time = ut_time_ms();
/* ALTER TABLE in MySQL requires on Unix that the table handler
can drop tables lazily after there no longer are SELECT
queries to them. */
srv_main_thread_op_info = "doing background drop tables";
row_drop_tables_for_mysql_in_background();
srv_main_thread_op_info = "";
if (srv_fast_shutdown && srv_shutdown_state > 0) {
goto background_loop;
}
buf_get_total_stat(&buf_stat);
n_ios_old = log_sys->n_log_ios + buf_stat.n_pages_read
......@@ -2654,7 +2691,8 @@ loop:
srv_main_thread_op_info = "sleeping";
srv_main_1_second_loops++;
if (next_itr_time > cur_time) {
if (next_itr_time > cur_time
&& srv_shutdown_state == SRV_SHUTDOWN_NONE) {
/* Get sleep interval in micro seconds. We use
ut_min() to avoid long sleep in case of
......@@ -2668,21 +2706,6 @@ loop:
/* Each iteration should happen at 1 second interval. */
next_itr_time = ut_time_ms() + 1000;
/* ALTER TABLE in MySQL requires on Unix that the table handler
can drop tables lazily after there no longer are SELECT
queries to them. */
srv_main_thread_op_info = "doing background drop tables";
row_drop_tables_for_mysql_in_background();
srv_main_thread_op_info = "";
if (srv_fast_shutdown && srv_shutdown_state > 0) {
goto background_loop;
}
/* Flush logs if needed */
srv_sync_log_buffer_in_background();
......@@ -2860,7 +2883,9 @@ background_loop:
MySQL tries to drop a table while there are still open handles
to it and we had to put it to the background drop queue.) */
os_thread_sleep(100000);
if (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
os_thread_sleep(100000);
}
}
if (srv_n_purge_threads == 0) {
......
......@@ -477,7 +477,6 @@ io_handler_thread(
the aio array */
{
ulint segment;
ulint i;
segment = *((ulint*)arg);
......@@ -490,7 +489,7 @@ io_handler_thread(
pfs_register_thread(io_handler_thread_key);
#endif /* UNIV_PFS_THREAD */
for (i = 0;; i++) {
while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
fil_aio_wait(segment);
mutex_enter(&ios_mutex);
......@@ -498,8 +497,6 @@ io_handler_thread(
mutex_exit(&ios_mutex);
}
thr_local_free(os_thread_get_curr_id());
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit.
The thread actually never comes here because it is exited in an
......
......@@ -1207,8 +1207,8 @@ sync_thread_add_level(
case SYNC_BUF_BLOCK:
/* Either the thread must own the buffer pool mutex
(buf_pool_mutex), or it is allowed to latch only ONE
buffer block (block->mutex or buf_pool_zip_mutex). */
(buf_pool->mutex), or it is allowed to latch only ONE
buffer block (block->mutex or buf_pool->zip_mutex). */
if (!sync_thread_levels_g(array, level, FALSE)) {
ut_a(sync_thread_levels_g(array, level - 1, TRUE));
ut_a(sync_thread_levels_contain(array, SYNC_BUF_POOL));
......
......@@ -38,8 +38,6 @@ Created July 17, 2007 Vasil Dimov
#include <mysql/plugin.h>
#include "mysql_addons.h"
#include "buf0buf.h"
#include "dict0dict.h"
#include "ha0storage.h"
......
......@@ -105,7 +105,11 @@ trx_create(
trx->is_purge = 0;
trx->is_recovered = 0;
trx->conc_state = TRX_NOT_STARTED;
trx->start_time = time(NULL);
trx->is_registered = 0;
trx->owns_prepare_mutex = 0;
trx->start_time = ut_time();
trx->isolation_level = TRX_ISO_REPEATABLE_READ;
......@@ -124,7 +128,6 @@ trx_create(
trx->table_id = 0;
trx->mysql_thd = NULL;
trx->active_trans = 0;
trx->duplicates = 0;
trx->n_mysql_tables_in_use = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment