mirror of
https://github.com/MariaDB/server.git
synced 2026-05-15 03:17:20 +02:00
Merging Innodb plugin 1.0.5 revisions from 5.1-main from revisions 3149 to 3163
also merged missing Innodb plugin revisions r5636,r5635 manually
This commit is contained in:
parent
42ea72dbfe
commit
a0e12ec269
109 changed files with 2597 additions and 2444 deletions
35
mysql-test/r/innodb-consistent.result
Normal file
35
mysql-test/r/innodb-consistent.result
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
drop table if exists t1;
|
||||
set session transaction isolation level read committed;
|
||||
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
|
||||
create table t2 like t1;
|
||||
insert into t2 values (1),(2),(3),(4),(5),(6),(7);
|
||||
set autocommit=0;
|
||||
begin;
|
||||
replace into t1 select * from t2;
|
||||
set session transaction isolation level read committed;
|
||||
set autocommit=0;
|
||||
delete from t2 where a=5;
|
||||
commit;
|
||||
delete from t2;
|
||||
commit;
|
||||
commit;
|
||||
begin;
|
||||
insert into t1 select * from t2;
|
||||
set session transaction isolation level read committed;
|
||||
set autocommit=0;
|
||||
delete from t2 where a=5;
|
||||
commit;
|
||||
delete from t2;
|
||||
commit;
|
||||
commit;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
|
|
@ -6,4 +6,5 @@ SELECT f4, f8 FROM bug34300;
|
|||
f4 f8
|
||||
xxx zzz
|
||||
DROP TABLE bug34300;
|
||||
SET @@global.max_allowed_packet=1048576;
|
||||
SET @@global.max_allowed_packet=default;
|
||||
|
|
|
|||
14
mysql-test/r/innodb_bug44369.result
Normal file
14
mysql-test/r/innodb_bug44369.result
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
create table bug44369 (DB_ROW_ID int) engine=innodb;
|
||||
ERROR HY000: Can't create table 'test.bug44369' (errno: -1)
|
||||
create table bug44369 (db_row_id int) engine=innodb;
|
||||
ERROR HY000: Can't create table 'test.bug44369' (errno: -1)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1005 Error creating table 'test/bug44369' with column name 'db_row_id'. 'db_row_id' is a reserved name. Please try to re-create the table with a different column name.
|
||||
Error 1005 Can't create table 'test.bug44369' (errno: -1)
|
||||
create table bug44369 (db_TRX_Id int) engine=innodb;
|
||||
ERROR HY000: Can't create table 'test.bug44369' (errno: -1)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1005 Error creating table 'test/bug44369' with column name 'db_TRX_Id'. 'db_TRX_Id' is a reserved name. Please try to re-create the table with a different column name.
|
||||
Error 1005 Can't create table 'test.bug44369' (errno: -1)
|
||||
9
mysql-test/r/innodb_bug44571.result
Normal file
9
mysql-test/r/innodb_bug44571.result
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
CREATE TABLE bug44571 (foo INT) ENGINE=InnoDB;
|
||||
ALTER TABLE bug44571 CHANGE foo bar INT;
|
||||
ALTER TABLE bug44571 ADD INDEX bug44571b (foo);
|
||||
ERROR 42000: Key column 'foo' doesn't exist in table
|
||||
ALTER TABLE bug44571 ADD INDEX bug44571b (bar);
|
||||
ERROR HY000: Incorrect key file for table 'bug44571'; try to repair it
|
||||
CREATE INDEX bug44571b ON bug44571 (bar);
|
||||
ERROR HY000: Incorrect key file for table 'bug44571'; try to repair it
|
||||
DROP TABLE bug44571;
|
||||
17
mysql-test/r/innodb_bug46000.result
Normal file
17
mysql-test/r/innodb_bug46000.result
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb;
|
||||
ERROR HY000: Can't create table 'test.bug46000' (errno: -1)
|
||||
create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb;
|
||||
ERROR HY000: Can't create table 'test.bug46000' (errno: -1)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index.
|
||||
Error 1005 Can't create table 'test.bug46000' (errno: -1)
|
||||
create table bug46000(id int) engine=innodb;
|
||||
create index GEN_CLUST_INDEX on bug46000(id);
|
||||
ERROR HY000: Can't create table '#sql-temporary' (errno: -1)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index.
|
||||
Error 1005 Can't create table '#sql-temporary' (errno: -1)
|
||||
create index idx on bug46000(id);
|
||||
drop table bug46000;
|
||||
|
|
@ -105,12 +105,6 @@ drop table t1;
|
|||
--error ER_TOO_BIG_ROWSIZE
|
||||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(440)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
||||
# 439 throws error with certain system zlib (ubuntu "intrepid")
|
||||
# but not with zlib bundled with MySQL, because zlib's compressBound()
|
||||
# are different (and used by InnoDB's page_zip_empty_size()); see
|
||||
# http://www.linux-archive.org/archlinux-development/119356-zlib-1-2-3-3-1-a.html
|
||||
# "Fix compressBound(), was low for some pathological cases [Fearnley]".
|
||||
# 438 works with both zlib-s.
|
||||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(438)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
||||
INSERT INTO t1 VALUES(REPEAT('A',512)),(REPEAT('B',512));
|
||||
|
|
|
|||
|
|
@ -14,3 +14,4 @@ innodb_bug39438 : Bug#42383 2009-01-28 lsoares "This fails in embedded
|
|||
query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically
|
||||
partition_innodb_builtin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes
|
||||
partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes
|
||||
innodb_bug46000 : Bug#47860 2009-10-16 satyab Test fails for innodb plugin 1.0.5
|
||||
|
|
|
|||
1
mysql-test/t/innodb-consistent-master.opt
Normal file
1
mysql-test/t/innodb-consistent-master.opt
Normal file
|
|
@ -0,0 +1 @@
|
|||
--innodb_lock_wait_timeout=2
|
||||
58
mysql-test/t/innodb-consistent.test
Normal file
58
mysql-test/t/innodb-consistent.test
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
-- source include/not_embedded.inc
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
# REPLACE INTO ... SELECT and INSERT INTO ... SELECT should do
|
||||
# a consistent read of the source table.
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
connection a;
|
||||
set session transaction isolation level read committed;
|
||||
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
|
||||
create table t2 like t1;
|
||||
insert into t2 values (1),(2),(3),(4),(5),(6),(7);
|
||||
set autocommit=0;
|
||||
|
||||
# REPLACE INTO ... SELECT case
|
||||
begin;
|
||||
# this should not result in any locks on t2.
|
||||
replace into t1 select * from t2;
|
||||
|
||||
connection b;
|
||||
set session transaction isolation level read committed;
|
||||
set autocommit=0;
|
||||
# should not cuase a lock wait.
|
||||
delete from t2 where a=5;
|
||||
commit;
|
||||
delete from t2;
|
||||
commit;
|
||||
connection a;
|
||||
commit;
|
||||
|
||||
# INSERT INTO ... SELECT case
|
||||
begin;
|
||||
# this should not result in any locks on t2.
|
||||
insert into t1 select * from t2;
|
||||
|
||||
connection b;
|
||||
set session transaction isolation level read committed;
|
||||
set autocommit=0;
|
||||
# should not cuase a lock wait.
|
||||
delete from t2 where a=5;
|
||||
commit;
|
||||
delete from t2;
|
||||
commit;
|
||||
connection a;
|
||||
commit;
|
||||
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
-- disable_result_log
|
||||
|
||||
# set packet size and reconnect
|
||||
let $max_packet=`select @@global.max_allowed_packet`;
|
||||
SET @@global.max_allowed_packet=16777216;
|
||||
--connect (newconn, localhost, root,,)
|
||||
|
||||
|
|
@ -32,6 +33,7 @@ SELECT f4, f8 FROM bug34300;
|
|||
|
||||
DROP TABLE bug34300;
|
||||
|
||||
EVAL SET @@global.max_allowed_packet=$max_packet;
|
||||
disconnect newconn;
|
||||
connection default;
|
||||
SET @@global.max_allowed_packet=default;
|
||||
|
|
|
|||
21
mysql-test/t/innodb_bug44369.test
Normal file
21
mysql-test/t/innodb_bug44369.test
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# This is the test for bug 44369. We should
|
||||
# block table creation with columns match
|
||||
# some innodb internal reserved key words,
|
||||
# both case sensitively and insensitely.
|
||||
|
||||
--source include/have_innodb.inc
|
||||
|
||||
# This create table operation should fail.
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table bug44369 (DB_ROW_ID int) engine=innodb;
|
||||
|
||||
# This create should fail as well
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table bug44369 (db_row_id int) engine=innodb;
|
||||
|
||||
show errors;
|
||||
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table bug44369 (db_TRX_Id int) engine=innodb;
|
||||
|
||||
show errors;
|
||||
17
mysql-test/t/innodb_bug44571.test
Normal file
17
mysql-test/t/innodb_bug44571.test
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#
|
||||
# Bug#44571 InnoDB Plugin crashes on ADD INDEX
|
||||
# http://bugs.mysql.com/44571
|
||||
#
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
CREATE TABLE bug44571 (foo INT) ENGINE=InnoDB;
|
||||
ALTER TABLE bug44571 CHANGE foo bar INT;
|
||||
-- error ER_KEY_COLUMN_DOES_NOT_EXITS
|
||||
ALTER TABLE bug44571 ADD INDEX bug44571b (foo);
|
||||
# The following will fail, because the CHANGE foo bar was
|
||||
# not communicated to InnoDB.
|
||||
--error ER_NOT_KEYFILE
|
||||
ALTER TABLE bug44571 ADD INDEX bug44571b (bar);
|
||||
--error ER_NOT_KEYFILE
|
||||
CREATE INDEX bug44571b ON bug44571 (bar);
|
||||
DROP TABLE bug44571;
|
||||
34
mysql-test/t/innodb_bug46000.test
Normal file
34
mysql-test/t/innodb_bug46000.test
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# This is the test for bug 46000. We shall
|
||||
# block any index creation with the name of
|
||||
# "GEN_CLUST_INDEX", which is the reserved
|
||||
# name for innodb default primary index.
|
||||
|
||||
--source include/have_innodb.inc
|
||||
|
||||
# This 'create table' operation should fail because of
|
||||
# using the reserve name as its index name.
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb;
|
||||
|
||||
# Mixed upper/lower case of the reserved key words
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb;
|
||||
|
||||
show errors;
|
||||
|
||||
create table bug46000(id int) engine=innodb;
|
||||
|
||||
# This 'create index' operation should fail.
|
||||
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create index GEN_CLUST_INDEX on bug46000(id);
|
||||
|
||||
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
|
||||
show errors;
|
||||
|
||||
# This 'create index' operation should succeed, no
|
||||
# temp table left from last failed create index
|
||||
# operation.
|
||||
create index idx on bug46000(id);
|
||||
|
||||
drop table bug46000;
|
||||
|
|
@ -21,7 +21,16 @@
|
|||
# those trees.
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
|
||||
|
||||
# Starting at 5.1.38, MySQL CMake files are simplified. But the plugin
|
||||
# CMakeLists.txt still needs to work with previous versions of MySQL.
|
||||
IF (MYSQL_VERSION_ID GREATER "50137")
|
||||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
|
||||
ENDIF (MYSQL_VERSION_ID GREATER "50137")
|
||||
|
||||
IF (CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||
SET(WIN64 TRUE)
|
||||
ENDIF (CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||
|
||||
# Include directories under innobase
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/innobase/include
|
||||
|
|
@ -36,10 +45,10 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
|
|||
|
||||
# Removing compiler optimizations for innodb/mem/* files on 64-bit Windows
|
||||
# due to 64-bit compiler error, See MySQL Bug #19424, #36366, #34297
|
||||
IF(MSVC AND CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||
IF (MSVC AND $(WIN64))
|
||||
SET_SOURCE_FILES_PROPERTIES(mem/mem0mem.c mem/mem0pool.c
|
||||
PROPERTIES COMPILE_FLAGS -Od)
|
||||
ENDIF(MSVC AND CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||
ENDIF (MSVC AND $(WIN64))
|
||||
|
||||
SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
|
||||
buf/buf0buddy.c buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c
|
||||
|
|
@ -74,5 +83,5 @@ SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
|
|||
usr/usr0sess.c
|
||||
ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c
|
||||
ut/ut0list.c ut/ut0wqueue.c)
|
||||
ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DINNODB_RW_LOCKS_USE_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION)
|
||||
MYSQL_STORAGE_ENGINE(INNOBASE)
|
||||
ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION)
|
||||
MYSQL_STORAGE_ENGINE(INNOBASE)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,149 @@
|
|||
2009-10-01 The InnoDB Team
|
||||
|
||||
* fsp/fsp0fsp.c, row/row0merge.c:
|
||||
Clean up after a crash during DROP INDEX. When InnoDB crashes
|
||||
while dropping an index, ensure that the index will be completely
|
||||
dropped during crash recovery. The MySQL .frm file may still
|
||||
contain the dropped index, but there is little that we can do
|
||||
about it.
|
||||
|
||||
2009-09-28 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
When a secondary index exists in the MySQL .frm file but not in
|
||||
the InnoDB data dictionary, return an error instead of letting an
|
||||
assertion fail in index_read.
|
||||
|
||||
2009-09-28 The InnoDB Team
|
||||
|
||||
* btr/btr0btr.c, buf/buf0buf.c, include/page0page.h,
|
||||
include/page0zip.h, page/page0cur.c, page/page0page.c,
|
||||
page/page0zip.c:
|
||||
Do not write to PAGE_INDEX_ID when restoring an uncompressed page
|
||||
after a compression failure. The field should only be written
|
||||
when creating a B-tree page. This fix addresses a race condition
|
||||
in a debug assertion.
|
||||
|
||||
2009-09-28 The InnoDB Team
|
||||
|
||||
* fil/fil0fil.c:
|
||||
Try to prevent the reuse of tablespace identifiers after InnoDB
|
||||
has crashed during table creation. Also, refuse to start if files
|
||||
with duplicate tablespace identifiers are encountered.
|
||||
|
||||
2009-09-25 The InnoDB Team
|
||||
|
||||
* include/os0file.h, os/os0file.c:
|
||||
Fix Bug#47055 unconditional exit(1) on ERROR_WORKING_SET_QUOTA
|
||||
1453 (0x5AD) for InnoDB backend
|
||||
|
||||
2009-09-19 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, mysql-test/innodb-consistent-master.opt,
|
||||
mysql-test/innodb-consistent.result,
|
||||
mysql-test/innodb-consistent.test:
|
||||
Fix Bug#37232 Innodb might get too many read locks for DML with
|
||||
repeatable-read
|
||||
|
||||
2009-09-19 The InnoDB Team
|
||||
|
||||
* fsp/fsp0fsp.c:
|
||||
Fix Bug#31183 Tablespace full problems not reported in error log,
|
||||
error message unclear
|
||||
|
||||
2009-09-17 The InnoDB Team
|
||||
|
||||
* mysql-test/innodb-zip.result, mysql-test/innodb-zip.test:
|
||||
Make the test pass with zlib 1.2.3.3. Apparently, the definition
|
||||
of compressBound() has changed between zlib versions, and the
|
||||
maximum record size of a table with 1K compressed page size has
|
||||
been reduced by one byte. This is an arbitrary test. In practical
|
||||
applications, for good write performance, the compressed page size
|
||||
should be chosen to be bigger than the absolute minimum.
|
||||
|
||||
2009-09-16 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
Fix Bug#46256 drop table with unknown collation crashes innodb
|
||||
|
||||
2009-09-16 The InnoDB Team
|
||||
|
||||
* dict/dict0dict.c, handler/ha_innodb.cc,
|
||||
mysql-test/innodb_bug44369.result, mysql-test/innodb_bug44369.test,
|
||||
row/row0mysql.c:
|
||||
Fix Bug#44369 InnoDB: Does not uniformly disallow disallowed column
|
||||
names
|
||||
|
||||
2009-09-16 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, include/db0err.h,
|
||||
mysql-test/innodb_bug46000.result, mysql-test/innodb_bug46000.test:
|
||||
Fix Bug#46000 using index called GEN_CLUST_INDEX crashes server
|
||||
|
||||
2009-09-02 The InnoDB Team
|
||||
|
||||
* include/lock0lock.h, include/row0mysql.h, lock/lock0lock.c,
|
||||
row/row0mysql.c:
|
||||
Fix a regression introduced by the fix for MySQL bug#26316. We check
|
||||
whether a transaction holds any AUTOINC locks before we acquire
|
||||
the kernel mutex and release those locks.
|
||||
|
||||
2009-08-27 The InnoDB Team
|
||||
|
||||
* dict/dict0dict.c, include/dict0dict.h,
|
||||
mysql-test/innodb_bug44571.result, mysql-test/innodb_bug44571.test:
|
||||
Fix Bug#44571 InnoDB Plugin crashes on ADD INDEX
|
||||
|
||||
2009-08-27 The InnoDB Team
|
||||
|
||||
* row/row0merge.c:
|
||||
Fix a bug in the merge sort that can corrupt indexes in fast index
|
||||
creation. Add some consistency checks. Check that the number of
|
||||
records remains constant in every merge sort pass.
|
||||
|
||||
2009-08-27 The InnoDB Team
|
||||
|
||||
* buf/buf0buf.c, buf/buf0lru.c, buf/buf0rea.c, handler/ha_innodb.cc,
|
||||
include/buf0buf.h, include/buf0buf.ic, include/buf0lru.h,
|
||||
include/ut0ut.h, ut/ut0ut.c:
|
||||
Make it possible to tune the buffer pool LRU eviction policy to be
|
||||
more resistant against index scans. Introduce the settable global
|
||||
variables innodb_old_blocks_pct and innodb_old_blocks_time for
|
||||
controlling the buffer pool eviction policy. The parameter
|
||||
innodb_old_blocks_pct (5..95) controls the desired amount of "old"
|
||||
blocks in the LRU list. The default is 37, corresponding to the
|
||||
old fixed ratio of 3/8. Each time a block is accessed, it will be
|
||||
moved to the "new" blocks if its first access was at least
|
||||
innodb_old_blocks_time milliseconds ago (default 0, meaning every
|
||||
block). The idea is that in index scans, blocks will be accessed
|
||||
a few times within innodb_old_blocks_time, and they will remain in
|
||||
the "old" section of the LRU list. Thus, when innodb_old_blocks_time
|
||||
is nonzero, blocks retrieved for one-time index scans will be more
|
||||
likely candidates for eviction than blocks that are accessed in
|
||||
random patterns.
|
||||
|
||||
2009-08-26 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, os/os0file.c:
|
||||
Fix Bug#42885 buf_read_ahead_random, buf_read_ahead_linear counters,
|
||||
thread wakeups
|
||||
|
||||
2009-08-20 The InnoDB Team
|
||||
|
||||
* lock/lock0lock.c:
|
||||
Fix Bug#46650 Innodb assertion autoinc_lock == lock in
|
||||
lock_table_remove_low on INSERT SELECT
|
||||
|
||||
2009-08-13 The InnoDB Team
|
||||
|
||||
* handler/handler0alter.cc:
|
||||
Fix Bug#46657 InnoDB plugin: invalid read in index_merge_innodb test
|
||||
(Valgrind)
|
||||
|
||||
2009-08-11 The InnoDB Team
|
||||
|
||||
InnoDB Plugin 1.0.4 released
|
||||
|
||||
2009-07-20 The InnoDB Team
|
||||
|
||||
* buf/buf0rea.c, handler/ha_innodb.cc, include/srv0srv.h,
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ DEFS= @DEFS@
|
|||
|
||||
noinst_HEADERS= \
|
||||
handler/ha_innodb.h \
|
||||
handler/handler0vars.h \
|
||||
handler/i_s.h \
|
||||
include/btr0btr.h \
|
||||
include/btr0btr.ic \
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
This is the source of the InnoDB Plugin 1.0.4 for MySQL 5.1
|
||||
===========================================================
|
||||
|
||||
Instructions for compiling the plugin:
|
||||
--------------------------------------
|
||||
|
||||
1. Get the latest MySQL 5.1 sources from
|
||||
http://dev.mysql.com/downloads/mysql/5.1.html#source
|
||||
|
||||
2. Replace the contents of the mysql-5.1.N/storage/innobase/ directory
|
||||
with the contents of this directory.
|
||||
|
||||
3. Optional (only necessary if you are going to run tests from the
|
||||
mysql-test suite): cd into the innobase directory and run ./setup.sh
|
||||
|
||||
4. Compile MySQL as usual.
|
||||
|
||||
5. Enjoy!
|
||||
|
||||
See the online documentation for more detailed instructions:
|
||||
http://www.innodb.com/doc/innodb_plugin-1.0/innodb-plugin-installation.html
|
||||
|
||||
For more information about InnoDB visit
|
||||
http://www.innodb.com
|
||||
|
||||
Please report any problems or issues with the plugin in the InnoDB Forums
|
||||
http://forums.innodb.com/ or in the MySQL Bugs database http://bugs.mysql.com
|
||||
|
||||
Thank you for using the InnoDB plugin!
|
||||
|
|
@ -797,7 +797,7 @@ btr_create(
|
|||
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
|
||||
}
|
||||
|
||||
/* Create a new index page on the the allocated segment page */
|
||||
/* Create a new index page on the allocated segment page */
|
||||
page_zip = buf_block_get_page_zip(block);
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
|
|
@ -1011,7 +1011,26 @@ btr_page_reorganize_low(
|
|||
(!page_zip_compress(page_zip, page, index, NULL))) {
|
||||
|
||||
/* Restore the old page and exit. */
|
||||
buf_frame_copy(page, temp_page);
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
|
||||
/* Check that the bytes that we skip are identical. */
|
||||
ut_a(!memcmp(page, temp_page, PAGE_HEADER));
|
||||
ut_a(!memcmp(PAGE_HEADER + PAGE_N_RECS + page,
|
||||
PAGE_HEADER + PAGE_N_RECS + temp_page,
|
||||
PAGE_DATA - (PAGE_HEADER + PAGE_N_RECS)));
|
||||
ut_a(!memcmp(UNIV_PAGE_SIZE - FIL_PAGE_DATA_END + page,
|
||||
UNIV_PAGE_SIZE - FIL_PAGE_DATA_END + temp_page,
|
||||
FIL_PAGE_DATA_END));
|
||||
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
|
||||
|
||||
memcpy(PAGE_HEADER + page, PAGE_HEADER + temp_page,
|
||||
PAGE_N_RECS - PAGE_N_DIR_SLOTS);
|
||||
memcpy(PAGE_DATA + page, PAGE_DATA + temp_page,
|
||||
UNIV_PAGE_SIZE - PAGE_DATA - FIL_PAGE_DATA_END);
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
|
||||
ut_a(!memcmp(page, temp_page, UNIV_PAGE_SIZE));
|
||||
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
|
@ -1902,7 +1921,7 @@ func_start:
|
|||
n_uniq, &heap);
|
||||
|
||||
/* If the new record is less than the existing record
|
||||
the the split in the middle will copy the existing
|
||||
the split in the middle will copy the existing
|
||||
record to the new node. */
|
||||
if (cmp_dtuple_rec(tuple, first_rec, offsets) < 0) {
|
||||
split_rec = page_get_middle_rec(page);
|
||||
|
|
|
|||
|
|
@ -957,7 +957,7 @@ btr_search_guess_on_hash(
|
|||
/* Increment the page get statistics though we did not really
|
||||
fix the page: for user info only */
|
||||
|
||||
buf_pool->n_page_gets++;
|
||||
buf_pool->stat.n_page_gets++;
|
||||
|
||||
return(TRUE);
|
||||
|
||||
|
|
|
|||
|
|
@ -837,16 +837,35 @@ buf_chunk_not_freed(
|
|||
block = chunk->blocks;
|
||||
|
||||
for (i = chunk->size; i--; block++) {
|
||||
mutex_enter(&block->mutex);
|
||||
|
||||
if (buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE
|
||||
&& !buf_flush_ready_for_replace(&block->page)) {
|
||||
ibool ready;
|
||||
|
||||
switch (buf_block_get_state(block)) {
|
||||
case BUF_BLOCK_ZIP_FREE:
|
||||
case BUF_BLOCK_ZIP_PAGE:
|
||||
case BUF_BLOCK_ZIP_DIRTY:
|
||||
/* The uncompressed buffer pool should never
|
||||
contain compressed block descriptors. */
|
||||
ut_error;
|
||||
break;
|
||||
case BUF_BLOCK_NOT_USED:
|
||||
case BUF_BLOCK_READY_FOR_USE:
|
||||
case BUF_BLOCK_MEMORY:
|
||||
case BUF_BLOCK_REMOVE_HASH:
|
||||
/* Skip blocks that are not being used for
|
||||
file pages. */
|
||||
break;
|
||||
case BUF_BLOCK_FILE_PAGE:
|
||||
mutex_enter(&block->mutex);
|
||||
ready = buf_flush_ready_for_replace(&block->page);
|
||||
mutex_exit(&block->mutex);
|
||||
return(block);
|
||||
}
|
||||
|
||||
mutex_exit(&block->mutex);
|
||||
if (!ready) {
|
||||
|
||||
return(block);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
|
|
@ -966,8 +985,6 @@ buf_pool_init(void)
|
|||
buf_pool->no_flush[i] = os_event_create(NULL);
|
||||
}
|
||||
|
||||
buf_pool->ulint_clock = 1;
|
||||
|
||||
/* 3. Initialize LRU fields
|
||||
--------------------------- */
|
||||
/* All fields are initialized by mem_zalloc(). */
|
||||
|
|
@ -1470,34 +1487,9 @@ buf_pool_resize(void)
|
|||
buf_pool_page_hash_rebuild();
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Moves the block to the start of the LRU list if there is a danger
|
||||
that the block would drift out of the buffer pool. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_block_make_young(
|
||||
/*=================*/
|
||||
buf_page_t* bpage) /*!< in: block to make younger */
|
||||
{
|
||||
ut_ad(!buf_pool_mutex_own());
|
||||
|
||||
/* Note that we read freed_page_clock's without holding any mutex:
|
||||
this is allowed since the result is used only in heuristics */
|
||||
|
||||
if (buf_page_peek_if_too_old(bpage)) {
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
/* There has been freeing activity in the LRU list:
|
||||
best to move to the head of the LRU list */
|
||||
|
||||
buf_LRU_make_block_young(bpage);
|
||||
buf_pool_mutex_exit();
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Moves a page to the start of the buffer pool LRU list. This high-level
|
||||
function can be used to prevent an important page from from slipping out of
|
||||
function can be used to prevent an important page from slipping out of
|
||||
the buffer pool. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
|
|
@ -1514,6 +1506,36 @@ buf_page_make_young(
|
|||
buf_pool_mutex_exit();
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Sets the time of the first access of a page and moves a page to the
|
||||
start of the buffer pool LRU list if it is too old. This high-level
|
||||
function can be used to prevent an important page from slipping
|
||||
out of the buffer pool. */
|
||||
static
|
||||
void
|
||||
buf_page_set_accessed_make_young(
|
||||
/*=============================*/
|
||||
buf_page_t* bpage, /*!< in/out: buffer block of a
|
||||
file page */
|
||||
unsigned access_time) /*!< in: bpage->access_time
|
||||
read under mutex protection,
|
||||
or 0 if unknown */
|
||||
{
|
||||
ut_ad(!buf_pool_mutex_own());
|
||||
ut_a(buf_page_in_file(bpage));
|
||||
|
||||
if (buf_page_peek_if_too_old(bpage)) {
|
||||
buf_pool_mutex_enter();
|
||||
buf_LRU_make_block_young(bpage);
|
||||
buf_pool_mutex_exit();
|
||||
} else if (!access_time) {
|
||||
ulint time_ms = ut_time_ms();
|
||||
buf_pool_mutex_enter();
|
||||
buf_page_set_accessed(bpage, time_ms);
|
||||
buf_pool_mutex_exit();
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Resets the check_index_page_at_flush field of a page if found in the buffer
|
||||
pool. */
|
||||
|
|
@ -1645,11 +1667,12 @@ buf_page_get_zip(
|
|||
buf_page_t* bpage;
|
||||
mutex_t* block_mutex;
|
||||
ibool must_read;
|
||||
unsigned access_time;
|
||||
|
||||
#ifndef UNIV_LOG_DEBUG
|
||||
ut_ad(!ibuf_inside());
|
||||
#endif
|
||||
buf_pool->n_page_gets++;
|
||||
buf_pool->stat.n_page_gets++;
|
||||
|
||||
for (;;) {
|
||||
buf_pool_mutex_enter();
|
||||
|
|
@ -1712,14 +1735,13 @@ err_exit:
|
|||
|
||||
got_block:
|
||||
must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
|
||||
access_time = buf_page_is_accessed(bpage);
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
buf_page_set_accessed(bpage, TRUE);
|
||||
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
buf_block_make_young(bpage);
|
||||
buf_page_set_accessed_make_young(bpage, access_time);
|
||||
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
ut_a(!bpage->file_page_was_freed);
|
||||
|
|
@ -1812,7 +1834,7 @@ buf_zip_decompress(
|
|||
switch (fil_page_get_type(frame)) {
|
||||
case FIL_PAGE_INDEX:
|
||||
if (page_zip_decompress(&block->page.zip,
|
||||
block->frame)) {
|
||||
block->frame, TRUE)) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
|
@ -2000,7 +2022,7 @@ buf_page_get_gen(
|
|||
mtr_t* mtr) /*!< in: mini-transaction */
|
||||
{
|
||||
buf_block_t* block;
|
||||
ibool accessed;
|
||||
unsigned access_time;
|
||||
ulint fix_type;
|
||||
ibool must_read;
|
||||
|
||||
|
|
@ -2016,7 +2038,7 @@ buf_page_get_gen(
|
|||
#ifndef UNIV_LOG_DEBUG
|
||||
ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
|
||||
#endif
|
||||
buf_pool->n_page_gets++;
|
||||
buf_pool->stat.n_page_gets++;
|
||||
loop:
|
||||
block = guess;
|
||||
buf_pool_mutex_enter();
|
||||
|
|
@ -2243,17 +2265,16 @@ wait_until_unfixed:
|
|||
UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page);
|
||||
|
||||
buf_block_buf_fix_inc(block, file, line);
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
/* Check if this is the first access to the page */
|
||||
|
||||
accessed = buf_page_is_accessed(&block->page);
|
||||
|
||||
buf_page_set_accessed(&block->page, TRUE);
|
||||
|
||||
mutex_exit(&block->mutex);
|
||||
|
||||
buf_block_make_young(&block->page);
|
||||
/* Check if this is the first access to the page */
|
||||
|
||||
access_time = buf_page_is_accessed(&block->page);
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
buf_page_set_accessed_make_young(&block->page, access_time);
|
||||
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
ut_a(!block->page.file_page_was_freed);
|
||||
|
|
@ -2306,7 +2327,7 @@ wait_until_unfixed:
|
|||
|
||||
mtr_memo_push(mtr, block, fix_type);
|
||||
|
||||
if (!accessed) {
|
||||
if (!access_time) {
|
||||
/* In the case of a first access, try to apply linear
|
||||
read-ahead */
|
||||
|
||||
|
|
@ -2336,7 +2357,7 @@ buf_page_optimistic_get_func(
|
|||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr) /*!< in: mini-transaction */
|
||||
{
|
||||
ibool accessed;
|
||||
unsigned access_time;
|
||||
ibool success;
|
||||
ulint fix_type;
|
||||
|
||||
|
|
@ -2353,14 +2374,16 @@ buf_page_optimistic_get_func(
|
|||
}
|
||||
|
||||
buf_block_buf_fix_inc(block, file, line);
|
||||
accessed = buf_page_is_accessed(&block->page);
|
||||
buf_page_set_accessed(&block->page, TRUE);
|
||||
|
||||
mutex_exit(&block->mutex);
|
||||
|
||||
buf_block_make_young(&block->page);
|
||||
/* Check if this is the first access to the page.
|
||||
We do a dirty read on purpose, to avoid mutex contention.
|
||||
This field is only used for heuristic purposes; it does not
|
||||
affect correctness. */
|
||||
|
||||
/* Check if this is the first access to the page */
|
||||
access_time = buf_page_is_accessed(&block->page);
|
||||
buf_page_set_accessed_make_young(&block->page, access_time);
|
||||
|
||||
ut_ad(!ibuf_inside()
|
||||
|| ibuf_page(buf_block_get_space(block),
|
||||
|
|
@ -2412,7 +2435,7 @@ buf_page_optimistic_get_func(
|
|||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
ut_a(block->page.file_page_was_freed == FALSE);
|
||||
#endif
|
||||
if (UNIV_UNLIKELY(!accessed)) {
|
||||
if (UNIV_UNLIKELY(!access_time)) {
|
||||
/* In the case of a first access, try to apply linear
|
||||
read-ahead */
|
||||
|
||||
|
|
@ -2425,7 +2448,7 @@ buf_page_optimistic_get_func(
|
|||
ut_a(ibuf_count_get(buf_block_get_space(block),
|
||||
buf_block_get_page_no(block)) == 0);
|
||||
#endif
|
||||
buf_pool->n_page_gets++;
|
||||
buf_pool->stat.n_page_gets++;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
|
@ -2473,8 +2496,20 @@ buf_page_get_known_nowait(
|
|||
|
||||
mutex_exit(&block->mutex);
|
||||
|
||||
if (mode == BUF_MAKE_YOUNG) {
|
||||
buf_block_make_young(&block->page);
|
||||
if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
|
||||
buf_pool_mutex_enter();
|
||||
buf_LRU_make_block_young(&block->page);
|
||||
buf_pool_mutex_exit();
|
||||
} else if (!buf_page_is_accessed(&block->page)) {
|
||||
/* Above, we do a dirty read on purpose, to avoid
|
||||
mutex contention. The field buf_page_t::access_time
|
||||
is only used for heuristic purposes. Writes to the
|
||||
field must be protected by mutex, however. */
|
||||
ulint time_ms = ut_time_ms();
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
buf_page_set_accessed(&block->page, time_ms);
|
||||
buf_pool_mutex_exit();
|
||||
}
|
||||
|
||||
ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
|
||||
|
|
@ -2513,7 +2548,7 @@ buf_page_get_known_nowait(
|
|||
|| (ibuf_count_get(buf_block_get_space(block),
|
||||
buf_block_get_page_no(block)) == 0));
|
||||
#endif
|
||||
buf_pool->n_page_gets++;
|
||||
buf_pool->stat.n_page_gets++;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
|
@ -2589,7 +2624,7 @@ buf_page_try_get_func(
|
|||
#endif /* UNIV_DEBUG_FILE_ACCESSES */
|
||||
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
buf_pool->n_page_gets++;
|
||||
buf_pool->stat.n_page_gets++;
|
||||
|
||||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
ut_a(ibuf_count_get(buf_block_get_space(block),
|
||||
|
|
@ -2608,10 +2643,10 @@ buf_page_init_low(
|
|||
buf_page_t* bpage) /*!< in: block to init */
|
||||
{
|
||||
bpage->flush_type = BUF_FLUSH_LRU;
|
||||
bpage->accessed = FALSE;
|
||||
bpage->io_fix = BUF_IO_NONE;
|
||||
bpage->buf_fix_count = 0;
|
||||
bpage->freed_page_clock = 0;
|
||||
bpage->access_time = 0;
|
||||
bpage->newest_modification = 0;
|
||||
bpage->oldest_modification = 0;
|
||||
HASH_INVALIDATE(bpage, hash);
|
||||
|
|
@ -2907,6 +2942,7 @@ buf_page_create(
|
|||
buf_frame_t* frame;
|
||||
buf_block_t* block;
|
||||
buf_block_t* free_block = NULL;
|
||||
ulint time_ms = ut_time_ms();
|
||||
|
||||
ut_ad(mtr);
|
||||
ut_ad(space || !zip_size);
|
||||
|
|
@ -2953,7 +2989,7 @@ buf_page_create(
|
|||
buf_LRU_add_block(&block->page, FALSE);
|
||||
|
||||
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
|
||||
buf_pool->n_pages_created++;
|
||||
buf_pool->stat.n_pages_created++;
|
||||
|
||||
if (zip_size) {
|
||||
void* data;
|
||||
|
|
@ -2990,12 +3026,12 @@ buf_page_create(
|
|||
rw_lock_x_unlock(&block->lock);
|
||||
}
|
||||
|
||||
buf_page_set_accessed(&block->page, time_ms);
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
|
||||
|
||||
buf_page_set_accessed(&block->page, TRUE);
|
||||
|
||||
mutex_exit(&block->mutex);
|
||||
|
||||
/* Delete possible entries for the page from the insert buffer:
|
||||
|
|
@ -3201,7 +3237,7 @@ corrupt:
|
|||
|
||||
ut_ad(buf_pool->n_pend_reads > 0);
|
||||
buf_pool->n_pend_reads--;
|
||||
buf_pool->n_pages_read++;
|
||||
buf_pool->stat.n_pages_read++;
|
||||
|
||||
if (uncompressed) {
|
||||
rw_lock_x_unlock_gen(&((buf_block_t*) bpage)->lock,
|
||||
|
|
@ -3221,7 +3257,7 @@ corrupt:
|
|||
BUF_IO_WRITE);
|
||||
}
|
||||
|
||||
buf_pool->n_pages_written++;
|
||||
buf_pool->stat.n_pages_written++;
|
||||
|
||||
break;
|
||||
|
||||
|
|
@ -3251,7 +3287,32 @@ void
|
|||
buf_pool_invalidate(void)
|
||||
/*=====================*/
|
||||
{
|
||||
ibool freed;
|
||||
ibool freed;
|
||||
enum buf_flush i;
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
|
||||
for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
|
||||
|
||||
/* As this function is called during startup and
|
||||
during redo application phase during recovery, InnoDB
|
||||
is single threaded (apart from IO helper threads) at
|
||||
this stage. No new write batch can be in intialization
|
||||
stage at this point. */
|
||||
ut_ad(buf_pool->init_flush[i] == FALSE);
|
||||
|
||||
/* However, it is possible that a write batch that has
|
||||
been posted earlier is still not complete. For buffer
|
||||
pool invalidation to proceed we must ensure there is NO
|
||||
write activity happening. */
|
||||
if (buf_pool->n_flush[i] > 0) {
|
||||
buf_pool_mutex_exit();
|
||||
buf_flush_wait_batch_end(i);
|
||||
buf_pool_mutex_enter();
|
||||
}
|
||||
}
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
ut_ad(buf_all_freed());
|
||||
|
||||
|
|
@ -3266,6 +3327,14 @@ buf_pool_invalidate(void)
|
|||
ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
|
||||
ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
|
||||
|
||||
buf_pool->freed_page_clock = 0;
|
||||
buf_pool->LRU_old = NULL;
|
||||
buf_pool->LRU_old_len = 0;
|
||||
buf_pool->LRU_flush_ended = 0;
|
||||
|
||||
memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
|
||||
buf_refresh_io_stats();
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
}
|
||||
|
||||
|
|
@ -3528,6 +3597,7 @@ buf_print(void)
|
|||
"n pending decompressions %lu\n"
|
||||
"n pending reads %lu\n"
|
||||
"n pending flush LRU %lu list %lu single page %lu\n"
|
||||
"pages made young %lu, not young %lu\n"
|
||||
"pages read %lu, created %lu, written %lu\n",
|
||||
(ulong) size,
|
||||
(ulong) UT_LIST_GET_LEN(buf_pool->LRU),
|
||||
|
|
@ -3538,8 +3608,11 @@ buf_print(void)
|
|||
(ulong) buf_pool->n_flush[BUF_FLUSH_LRU],
|
||||
(ulong) buf_pool->n_flush[BUF_FLUSH_LIST],
|
||||
(ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE],
|
||||
(ulong) buf_pool->n_pages_read, buf_pool->n_pages_created,
|
||||
(ulong) buf_pool->n_pages_written);
|
||||
(ulong) buf_pool->stat.n_pages_made_young,
|
||||
(ulong) buf_pool->stat.n_pages_not_made_young,
|
||||
(ulong) buf_pool->stat.n_pages_read,
|
||||
(ulong) buf_pool->stat.n_pages_created,
|
||||
(ulong) buf_pool->stat.n_pages_written);
|
||||
|
||||
/* Count the number of blocks belonging to each index in the buffer */
|
||||
|
||||
|
|
@ -3744,10 +3817,9 @@ buf_print_io(
|
|||
{
|
||||
time_t current_time;
|
||||
double time_elapsed;
|
||||
ulint size;
|
||||
ulint n_gets_diff;
|
||||
|
||||
ut_ad(buf_pool);
|
||||
size = buf_pool->curr_size;
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
|
||||
|
|
@ -3755,12 +3827,14 @@ buf_print_io(
|
|||
"Buffer pool size %lu\n"
|
||||
"Free buffers %lu\n"
|
||||
"Database pages %lu\n"
|
||||
"Old database pages %lu\n"
|
||||
"Modified db pages %lu\n"
|
||||
"Pending reads %lu\n"
|
||||
"Pending writes: LRU %lu, flush list %lu, single page %lu\n",
|
||||
(ulong) size,
|
||||
(ulong) buf_pool->curr_size,
|
||||
(ulong) UT_LIST_GET_LEN(buf_pool->free),
|
||||
(ulong) UT_LIST_GET_LEN(buf_pool->LRU),
|
||||
(ulong) buf_pool->LRU_old_len,
|
||||
(ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
|
||||
(ulong) buf_pool->n_pend_reads,
|
||||
(ulong) buf_pool->n_flush[BUF_FLUSH_LRU]
|
||||
|
|
@ -3772,37 +3846,66 @@ buf_print_io(
|
|||
current_time = time(NULL);
|
||||
time_elapsed = 0.001 + difftime(current_time,
|
||||
buf_pool->last_printout_time);
|
||||
buf_pool->last_printout_time = current_time;
|
||||
|
||||
fprintf(file,
|
||||
"Pages made young %lu, not young %lu\n"
|
||||
"%.2f youngs/s, %.2f non-youngs/s\n"
|
||||
"Pages read %lu, created %lu, written %lu\n"
|
||||
"%.2f reads/s, %.2f creates/s, %.2f writes/s\n",
|
||||
(ulong) buf_pool->n_pages_read,
|
||||
(ulong) buf_pool->n_pages_created,
|
||||
(ulong) buf_pool->n_pages_written,
|
||||
(buf_pool->n_pages_read - buf_pool->n_pages_read_old)
|
||||
(ulong) buf_pool->stat.n_pages_made_young,
|
||||
(ulong) buf_pool->stat.n_pages_not_made_young,
|
||||
(buf_pool->stat.n_pages_made_young
|
||||
- buf_pool->old_stat.n_pages_made_young)
|
||||
/ time_elapsed,
|
||||
(buf_pool->n_pages_created - buf_pool->n_pages_created_old)
|
||||
(buf_pool->stat.n_pages_not_made_young
|
||||
- buf_pool->old_stat.n_pages_not_made_young)
|
||||
/ time_elapsed,
|
||||
(buf_pool->n_pages_written - buf_pool->n_pages_written_old)
|
||||
(ulong) buf_pool->stat.n_pages_read,
|
||||
(ulong) buf_pool->stat.n_pages_created,
|
||||
(ulong) buf_pool->stat.n_pages_written,
|
||||
(buf_pool->stat.n_pages_read
|
||||
- buf_pool->old_stat.n_pages_read)
|
||||
/ time_elapsed,
|
||||
(buf_pool->stat.n_pages_created
|
||||
- buf_pool->old_stat.n_pages_created)
|
||||
/ time_elapsed,
|
||||
(buf_pool->stat.n_pages_written
|
||||
- buf_pool->old_stat.n_pages_written)
|
||||
/ time_elapsed);
|
||||
|
||||
if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) {
|
||||
fprintf(file, "Buffer pool hit rate %lu / 1000\n",
|
||||
n_gets_diff = buf_pool->stat.n_page_gets - buf_pool->old_stat.n_page_gets;
|
||||
|
||||
if (n_gets_diff) {
|
||||
fprintf(file,
|
||||
"Buffer pool hit rate %lu / 1000,"
|
||||
" young-making rate %lu / 1000 not %lu / 1000\n",
|
||||
(ulong)
|
||||
(1000 - ((1000 * (buf_pool->n_pages_read
|
||||
- buf_pool->n_pages_read_old))
|
||||
/ (buf_pool->n_page_gets
|
||||
- buf_pool->n_page_gets_old))));
|
||||
(1000 - ((1000 * (buf_pool->stat.n_pages_read
|
||||
- buf_pool->old_stat.n_pages_read))
|
||||
/ (buf_pool->stat.n_page_gets
|
||||
- buf_pool->old_stat.n_page_gets))),
|
||||
(ulong)
|
||||
(1000 * (buf_pool->stat.n_pages_made_young
|
||||
- buf_pool->old_stat.n_pages_made_young)
|
||||
/ n_gets_diff),
|
||||
(ulong)
|
||||
(1000 * (buf_pool->stat.n_pages_not_made_young
|
||||
- buf_pool->old_stat.n_pages_not_made_young)
|
||||
/ n_gets_diff));
|
||||
} else {
|
||||
fputs("No buffer pool page gets since the last printout\n",
|
||||
file);
|
||||
}
|
||||
|
||||
buf_pool->n_page_gets_old = buf_pool->n_page_gets;
|
||||
buf_pool->n_pages_read_old = buf_pool->n_pages_read;
|
||||
buf_pool->n_pages_created_old = buf_pool->n_pages_created;
|
||||
buf_pool->n_pages_written_old = buf_pool->n_pages_written;
|
||||
/* Statistics about read ahead algorithm */
|
||||
fprintf(file, "Pages read ahead %.2f/s,"
|
||||
" evicted without access %.2f/s\n",
|
||||
(buf_pool->stat.n_ra_pages_read
|
||||
- buf_pool->old_stat.n_ra_pages_read)
|
||||
/ time_elapsed,
|
||||
(buf_pool->stat.n_ra_pages_evicted
|
||||
- buf_pool->old_stat.n_ra_pages_evicted)
|
||||
/ time_elapsed);
|
||||
|
||||
/* Print some values to help us with visualizing what is
|
||||
happening with LRU eviction. */
|
||||
|
|
@ -3814,6 +3917,7 @@ buf_print_io(
|
|||
buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
|
||||
buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
|
||||
|
||||
buf_refresh_io_stats();
|
||||
buf_pool_mutex_exit();
|
||||
}
|
||||
|
||||
|
|
@ -3825,10 +3929,7 @@ buf_refresh_io_stats(void)
|
|||
/*======================*/
|
||||
{
|
||||
buf_pool->last_printout_time = time(NULL);
|
||||
buf_pool->n_page_gets_old = buf_pool->n_page_gets;
|
||||
buf_pool->n_pages_read_old = buf_pool->n_pages_read;
|
||||
buf_pool->n_pages_created_old = buf_pool->n_pages_created;
|
||||
buf_pool->n_pages_written_old = buf_pool->n_pages_written;
|
||||
buf_pool->old_stat = buf_pool->stat;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
|
|
|
|||
|
|
@ -49,18 +49,22 @@ Created 11/5/1995 Heikki Tuuri
|
|||
#include "log0recv.h"
|
||||
#include "srv0srv.h"
|
||||
|
||||
/** The number of blocks from the LRU_old pointer onward, including the block
|
||||
pointed to, must be 3/8 of the whole LRU list length, except that the
|
||||
tolerance defined below is allowed. Note that the tolerance must be small
|
||||
enough such that for even the BUF_LRU_OLD_MIN_LEN long LRU list, the
|
||||
LRU_old pointer is not allowed to point to either end of the LRU list. */
|
||||
/** The number of blocks from the LRU_old pointer onward, including
|
||||
the block pointed to, must be buf_LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV
|
||||
of the whole LRU list length, except that the tolerance defined below
|
||||
is allowed. Note that the tolerance must be small enough such that for
|
||||
even the BUF_LRU_OLD_MIN_LEN long LRU list, the LRU_old pointer is not
|
||||
allowed to point to either end of the LRU list. */
|
||||
|
||||
#define BUF_LRU_OLD_TOLERANCE 20
|
||||
|
||||
/** The whole LRU list length is divided by this number to determine an
|
||||
initial segment in buf_LRU_get_recent_limit */
|
||||
|
||||
#define BUF_LRU_INITIAL_RATIO 8
|
||||
/** The minimum amount of non-old blocks when the LRU_old list exists
|
||||
(that is, when there are more than BUF_LRU_OLD_MIN_LEN blocks).
|
||||
@see buf_LRU_old_adjust_len */
|
||||
#define BUF_LRU_NON_OLD_MIN_LEN 5
|
||||
#if BUF_LRU_NON_OLD_MIN_LEN >= BUF_LRU_OLD_MIN_LEN
|
||||
# error "BUF_LRU_NON_OLD_MIN_LEN >= BUF_LRU_OLD_MIN_LEN"
|
||||
#endif
|
||||
|
||||
/** When dropping the search hash index entries before deleting an ibd
|
||||
file, we build a local array of pages belonging to that tablespace
|
||||
|
|
@ -107,6 +111,15 @@ UNIV_INTERN buf_LRU_stat_t buf_LRU_stat_sum;
|
|||
|
||||
/* @} */
|
||||
|
||||
/** @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. */
|
||||
UNIV_INTERN uint buf_LRU_old_ratio;
|
||||
/** Move blocks to "new" LRU list only if the first access was at
|
||||
least this many milliseconds ago. Not protected by any mutex or latch. */
|
||||
UNIV_INTERN uint buf_LRU_old_threshold_ms;
|
||||
/* @} */
|
||||
|
||||
/******************************************************************//**
|
||||
Takes a block out of the LRU list and page hash table.
|
||||
If the block is compressed-only (BUF_BLOCK_ZIP_PAGE),
|
||||
|
|
@ -428,42 +441,6 @@ next_page:
|
|||
}
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Gets the minimum LRU_position field for the blocks in an initial segment
|
||||
(determined by BUF_LRU_INITIAL_RATIO) of the LRU list. The limit is not
|
||||
guaranteed to be precise, because the ulint_clock may wrap around.
|
||||
@return the limit; zero if could not determine it */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_LRU_get_recent_limit(void)
|
||||
/*==========================*/
|
||||
{
|
||||
const buf_page_t* bpage;
|
||||
ulint len;
|
||||
ulint limit;
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
|
||||
len = UT_LIST_GET_LEN(buf_pool->LRU);
|
||||
|
||||
if (len < BUF_LRU_OLD_MIN_LEN) {
|
||||
/* The LRU list is too short to do read-ahead */
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
|
||||
|
||||
limit = buf_page_get_LRU_position(bpage);
|
||||
len /= BUF_LRU_INITIAL_RATIO;
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
return(limit > len ? (limit - len) : 0);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
|
||||
UNIV_INTERN
|
||||
|
|
@ -594,6 +571,7 @@ buf_LRU_free_from_common_LRU_list(
|
|||
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(bpage);
|
||||
|
||||
|
|
@ -601,11 +579,18 @@ buf_LRU_free_from_common_LRU_list(
|
|||
ut_ad(bpage->in_LRU_list);
|
||||
|
||||
mutex_enter(block_mutex);
|
||||
accessed = buf_page_is_accessed(bpage);
|
||||
freed = buf_LRU_free_block(bpage, TRUE, NULL);
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
switch (freed) {
|
||||
case BUF_LRU_FREED:
|
||||
/* Keep track of pages that are evicted without
|
||||
ever being accessed. This gives us a measure of
|
||||
the effectiveness of readahead */
|
||||
if (!accessed) {
|
||||
++buf_pool->stat.n_ra_pages_evicted;
|
||||
}
|
||||
return(TRUE);
|
||||
|
||||
case BUF_LRU_NOT_FREED:
|
||||
|
|
@ -953,8 +938,10 @@ buf_LRU_old_adjust_len(void)
|
|||
|
||||
ut_a(buf_pool->LRU_old);
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
#if 3 * (BUF_LRU_OLD_MIN_LEN / 8) <= BUF_LRU_OLD_TOLERANCE + 5
|
||||
# error "3 * (BUF_LRU_OLD_MIN_LEN / 8) <= BUF_LRU_OLD_TOLERANCE + 5"
|
||||
ut_ad(buf_LRU_old_ratio >= BUF_LRU_OLD_RATIO_MIN);
|
||||
ut_ad(buf_LRU_old_ratio <= BUF_LRU_OLD_RATIO_MAX);
|
||||
#if BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5)
|
||||
# error "BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5)"
|
||||
#endif
|
||||
#ifdef UNIV_LRU_DEBUG
|
||||
/* buf_pool->LRU_old must be the first item in the LRU list
|
||||
|
|
@ -966,34 +953,39 @@ buf_LRU_old_adjust_len(void)
|
|||
|| UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)->old);
|
||||
#endif /* UNIV_LRU_DEBUG */
|
||||
|
||||
for (;;) {
|
||||
old_len = buf_pool->LRU_old_len;
|
||||
new_len = 3 * (UT_LIST_GET_LEN(buf_pool->LRU) / 8);
|
||||
old_len = buf_pool->LRU_old_len;
|
||||
new_len = ut_min(UT_LIST_GET_LEN(buf_pool->LRU)
|
||||
* buf_LRU_old_ratio / BUF_LRU_OLD_RATIO_DIV,
|
||||
UT_LIST_GET_LEN(buf_pool->LRU)
|
||||
- (BUF_LRU_OLD_TOLERANCE
|
||||
+ BUF_LRU_NON_OLD_MIN_LEN));
|
||||
|
||||
ut_ad(buf_pool->LRU_old->in_LRU_list);
|
||||
ut_a(buf_pool->LRU_old);
|
||||
for (;;) {
|
||||
buf_page_t* LRU_old = buf_pool->LRU_old;
|
||||
|
||||
ut_a(LRU_old);
|
||||
ut_ad(LRU_old->in_LRU_list);
|
||||
#ifdef UNIV_LRU_DEBUG
|
||||
ut_a(buf_pool->LRU_old->old);
|
||||
ut_a(LRU_old->old);
|
||||
#endif /* UNIV_LRU_DEBUG */
|
||||
|
||||
/* Update the LRU_old pointer if necessary */
|
||||
|
||||
if (old_len < new_len - BUF_LRU_OLD_TOLERANCE) {
|
||||
if (old_len + BUF_LRU_OLD_TOLERANCE < new_len) {
|
||||
|
||||
buf_pool->LRU_old = UT_LIST_GET_PREV(
|
||||
LRU, buf_pool->LRU_old);
|
||||
buf_pool->LRU_old = LRU_old = UT_LIST_GET_PREV(
|
||||
LRU, LRU_old);
|
||||
#ifdef UNIV_LRU_DEBUG
|
||||
ut_a(!buf_pool->LRU_old->old);
|
||||
ut_a(!LRU_old->old);
|
||||
#endif /* UNIV_LRU_DEBUG */
|
||||
buf_page_set_old(buf_pool->LRU_old, TRUE);
|
||||
buf_pool->LRU_old_len++;
|
||||
buf_page_set_old(LRU_old, TRUE);
|
||||
old_len = ++buf_pool->LRU_old_len;
|
||||
|
||||
} else if (old_len > new_len + BUF_LRU_OLD_TOLERANCE) {
|
||||
|
||||
buf_page_set_old(buf_pool->LRU_old, FALSE);
|
||||
buf_pool->LRU_old = UT_LIST_GET_NEXT(
|
||||
LRU, buf_pool->LRU_old);
|
||||
buf_pool->LRU_old_len--;
|
||||
buf_page_set_old(LRU_old, FALSE);
|
||||
buf_pool->LRU_old = UT_LIST_GET_NEXT(LRU, LRU_old);
|
||||
old_len = --buf_pool->LRU_old_len;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1021,6 +1013,7 @@ buf_LRU_old_init(void)
|
|||
|
||||
while (bpage != NULL) {
|
||||
ut_ad(bpage->in_LRU_list);
|
||||
ut_ad(buf_page_in_file(bpage));
|
||||
buf_page_set_old(bpage, TRUE);
|
||||
bpage = UT_LIST_GET_NEXT(LRU, bpage);
|
||||
}
|
||||
|
|
@ -1075,16 +1068,19 @@ buf_LRU_remove_block(
|
|||
|
||||
if (UNIV_UNLIKELY(bpage == buf_pool->LRU_old)) {
|
||||
|
||||
/* Below: the previous block is guaranteed to exist, because
|
||||
the LRU_old pointer is only allowed to differ by the
|
||||
tolerance value from strict 3/8 of the LRU list length. */
|
||||
/* Below: the previous block is guaranteed to exist,
|
||||
because the LRU_old pointer is only allowed to differ
|
||||
by BUF_LRU_OLD_TOLERANCE from strict
|
||||
buf_LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV of the LRU
|
||||
list length. */
|
||||
buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
|
||||
|
||||
buf_pool->LRU_old = UT_LIST_GET_PREV(LRU, bpage);
|
||||
ut_a(buf_pool->LRU_old);
|
||||
ut_a(prev_bpage);
|
||||
#ifdef UNIV_LRU_DEBUG
|
||||
ut_a(!buf_pool->LRU_old->old);
|
||||
ut_a(!prev_bpage->old);
|
||||
#endif /* UNIV_LRU_DEBUG */
|
||||
buf_page_set_old(buf_pool->LRU_old, TRUE);
|
||||
buf_pool->LRU_old = prev_bpage;
|
||||
buf_page_set_old(prev_bpage, TRUE);
|
||||
|
||||
buf_pool->LRU_old_len++;
|
||||
}
|
||||
|
|
@ -1149,39 +1145,25 @@ buf_LRU_add_block_to_end_low(
|
|||
/*=========================*/
|
||||
buf_page_t* bpage) /*!< in: control block */
|
||||
{
|
||||
buf_page_t* last_bpage;
|
||||
|
||||
ut_ad(buf_pool);
|
||||
ut_ad(bpage);
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
|
||||
ut_a(buf_page_in_file(bpage));
|
||||
|
||||
last_bpage = UT_LIST_GET_LAST(buf_pool->LRU);
|
||||
|
||||
if (last_bpage) {
|
||||
bpage->LRU_position = last_bpage->LRU_position;
|
||||
} else {
|
||||
bpage->LRU_position = buf_pool_clock_tic();
|
||||
}
|
||||
|
||||
ut_ad(!bpage->in_LRU_list);
|
||||
UT_LIST_ADD_LAST(LRU, buf_pool->LRU, bpage);
|
||||
ut_d(bpage->in_LRU_list = TRUE);
|
||||
|
||||
buf_page_set_old(bpage, TRUE);
|
||||
|
||||
if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
|
||||
|
||||
buf_pool->LRU_old_len++;
|
||||
}
|
||||
|
||||
if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
|
||||
|
||||
ut_ad(buf_pool->LRU_old);
|
||||
|
||||
/* Adjust the length of the old block list if necessary */
|
||||
|
||||
buf_pool->LRU_old_len++;
|
||||
buf_LRU_old_adjust_len();
|
||||
|
||||
} else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) {
|
||||
|
|
@ -1189,6 +1171,7 @@ buf_LRU_add_block_to_end_low(
|
|||
/* The LRU list is now long enough for LRU_old to become
|
||||
defined: init it */
|
||||
|
||||
buf_pool->LRU_old_len++;
|
||||
buf_LRU_old_init();
|
||||
}
|
||||
|
||||
|
|
@ -1222,7 +1205,6 @@ buf_LRU_add_block_low(
|
|||
|
||||
UT_LIST_ADD_FIRST(LRU, buf_pool->LRU, bpage);
|
||||
|
||||
bpage->LRU_position = buf_pool_clock_tic();
|
||||
bpage->freed_page_clock = buf_pool->freed_page_clock;
|
||||
} else {
|
||||
#ifdef UNIV_LRU_DEBUG
|
||||
|
|
@ -1237,11 +1219,6 @@ buf_LRU_add_block_low(
|
|||
UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU, buf_pool->LRU_old,
|
||||
bpage);
|
||||
buf_pool->LRU_old_len++;
|
||||
|
||||
/* We copy the LRU position field of the previous block
|
||||
to the new block */
|
||||
|
||||
bpage->LRU_position = (buf_pool->LRU_old)->LRU_position;
|
||||
}
|
||||
|
||||
ut_d(bpage->in_LRU_list = TRUE);
|
||||
|
|
@ -1295,6 +1272,12 @@ buf_LRU_make_block_young(
|
|||
/*=====================*/
|
||||
buf_page_t* bpage) /*!< in: control block */
|
||||
{
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
|
||||
if (bpage->old) {
|
||||
buf_pool->stat.n_pages_made_young++;
|
||||
}
|
||||
|
||||
buf_LRU_remove_block(bpage);
|
||||
buf_LRU_add_block_low(bpage, FALSE);
|
||||
}
|
||||
|
|
@ -1847,6 +1830,50 @@ buf_LRU_block_free_hashed_page(
|
|||
buf_LRU_block_free_non_file_page(block);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Updates buf_LRU_old_ratio.
|
||||
@return updated old_pct */
|
||||
UNIV_INTERN
|
||||
uint
|
||||
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
|
||||
during the initialization of InnoDB */
|
||||
{
|
||||
uint ratio;
|
||||
|
||||
ratio = old_pct * BUF_LRU_OLD_RATIO_DIV / 100;
|
||||
if (ratio < BUF_LRU_OLD_RATIO_MIN) {
|
||||
ratio = BUF_LRU_OLD_RATIO_MIN;
|
||||
} else if (ratio > BUF_LRU_OLD_RATIO_MAX) {
|
||||
ratio = BUF_LRU_OLD_RATIO_MAX;
|
||||
}
|
||||
|
||||
if (adjust) {
|
||||
buf_pool_mutex_enter();
|
||||
|
||||
if (ratio != buf_LRU_old_ratio) {
|
||||
buf_LRU_old_ratio = ratio;
|
||||
|
||||
if (UT_LIST_GET_LEN(buf_pool->LRU)
|
||||
>= BUF_LRU_OLD_MIN_LEN) {
|
||||
buf_LRU_old_adjust_len();
|
||||
}
|
||||
}
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
} else {
|
||||
buf_LRU_old_ratio = ratio;
|
||||
}
|
||||
|
||||
/* the reverse of
|
||||
ratio = old_pct * BUF_LRU_OLD_RATIO_DIV / 100 */
|
||||
return((uint) (ratio * 100 / (double) BUF_LRU_OLD_RATIO_DIV + 0.5));
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Update the historical stats that we are collecting for LRU eviction
|
||||
policy at the end of each interval. */
|
||||
|
|
@ -1896,7 +1923,6 @@ buf_LRU_validate(void)
|
|||
buf_block_t* block;
|
||||
ulint old_len;
|
||||
ulint new_len;
|
||||
ulint LRU_pos;
|
||||
|
||||
ut_ad(buf_pool);
|
||||
buf_pool_mutex_enter();
|
||||
|
|
@ -1905,7 +1931,11 @@ buf_LRU_validate(void)
|
|||
|
||||
ut_a(buf_pool->LRU_old);
|
||||
old_len = buf_pool->LRU_old_len;
|
||||
new_len = 3 * (UT_LIST_GET_LEN(buf_pool->LRU) / 8);
|
||||
new_len = ut_min(UT_LIST_GET_LEN(buf_pool->LRU)
|
||||
* buf_LRU_old_ratio / BUF_LRU_OLD_RATIO_DIV,
|
||||
UT_LIST_GET_LEN(buf_pool->LRU)
|
||||
- (BUF_LRU_OLD_TOLERANCE
|
||||
+ BUF_LRU_NON_OLD_MIN_LEN));
|
||||
ut_a(old_len >= new_len - BUF_LRU_OLD_TOLERANCE);
|
||||
ut_a(old_len <= new_len + BUF_LRU_OLD_TOLERANCE);
|
||||
}
|
||||
|
|
@ -1943,16 +1973,7 @@ buf_LRU_validate(void)
|
|||
ut_a(buf_pool->LRU_old == bpage);
|
||||
}
|
||||
|
||||
LRU_pos = buf_page_get_LRU_position(bpage);
|
||||
|
||||
bpage = UT_LIST_GET_NEXT(LRU, bpage);
|
||||
|
||||
if (bpage) {
|
||||
/* If the following assert fails, it may
|
||||
not be an error: just the buf_pool clock
|
||||
has wrapped around */
|
||||
ut_a(LRU_pos >= buf_page_get_LRU_position(bpage));
|
||||
}
|
||||
}
|
||||
|
||||
if (buf_pool->LRU_old) {
|
||||
|
|
@ -2000,9 +2021,6 @@ buf_LRU_print(void)
|
|||
ut_ad(buf_pool);
|
||||
buf_pool_mutex_enter();
|
||||
|
||||
fprintf(stderr, "Pool ulint clock %lu\n",
|
||||
(ulong) buf_pool->ulint_clock);
|
||||
|
||||
bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
|
||||
|
||||
while (bpage != NULL) {
|
||||
|
|
@ -2033,18 +2051,16 @@ buf_LRU_print(void)
|
|||
const byte* frame;
|
||||
case BUF_BLOCK_FILE_PAGE:
|
||||
frame = buf_block_get_frame((buf_block_t*) bpage);
|
||||
fprintf(stderr, "\nLRU pos %lu type %lu"
|
||||
fprintf(stderr, "\ntype %lu"
|
||||
" index id %lu\n",
|
||||
(ulong) buf_page_get_LRU_position(bpage),
|
||||
(ulong) fil_page_get_type(frame),
|
||||
(ulong) ut_dulint_get_low(
|
||||
btr_page_get_index_id(frame)));
|
||||
break;
|
||||
case BUF_BLOCK_ZIP_PAGE:
|
||||
frame = bpage->zip.data;
|
||||
fprintf(stderr, "\nLRU pos %lu type %lu size %lu"
|
||||
fprintf(stderr, "\ntype %lu size %lu"
|
||||
" index id %lu\n",
|
||||
(ulong) buf_page_get_LRU_position(bpage),
|
||||
(ulong) fil_page_get_type(frame),
|
||||
(ulong) buf_page_get_zip_size(bpage),
|
||||
(ulong) ut_dulint_get_low(
|
||||
|
|
@ -2052,8 +2068,7 @@ buf_LRU_print(void)
|
|||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "\nLRU pos %lu !state %lu!\n",
|
||||
(ulong) buf_page_get_LRU_position(bpage),
|
||||
fprintf(stderr, "\n!state %lu!\n",
|
||||
(ulong) buf_page_get_state(bpage));
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,14 +38,6 @@ Created 11/5/1995 Heikki Tuuri
|
|||
#include "srv0start.h"
|
||||
#include "srv0srv.h"
|
||||
|
||||
/** The size in blocks of the area where the random read-ahead algorithm counts
|
||||
the accessed pages when deciding whether to read-ahead */
|
||||
#define BUF_READ_AHEAD_RANDOM_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 (1 + BUF_READ_AHEAD_RANDOM_AREA / 2)
|
||||
|
||||
/** The linear read-ahead area size */
|
||||
#define BUF_READ_AHEAD_LINEAR_AREA BUF_READ_AHEAD_AREA
|
||||
|
||||
|
|
@ -62,7 +54,8 @@ flag is cleared and the x-lock released by an i/o-handler thread.
|
|||
@return 1 if a read request was queued, 0 if the page already resided
|
||||
in buf_pool, or if the page is in the doublewrite buffer blocks in
|
||||
which case it is never read into the pool, or if the tablespace does
|
||||
not exist or is being dropped */
|
||||
not exist or is being dropped
|
||||
@return 1 if read request is issued. 0 if it is not */
|
||||
static
|
||||
ulint
|
||||
buf_read_page_low(
|
||||
|
|
@ -164,175 +157,14 @@ buf_read_page_low(
|
|||
return(1);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
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! */
|
||||
static
|
||||
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 */
|
||||
{
|
||||
ib_int64_t tablespace_version;
|
||||
ulint recent_blocks = 0;
|
||||
ulint count;
|
||||
ulint LRU_recent_limit;
|
||||
ulint ibuf_mode;
|
||||
ulint low, high;
|
||||
ulint err;
|
||||
ulint i;
|
||||
ulint buf_read_ahead_random_area;
|
||||
|
||||
/* We have currently disabled random readahead */
|
||||
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);
|
||||
|
||||
buf_read_ahead_random_area = BUF_READ_AHEAD_RANDOM_AREA;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* Get the minimum LRU_position field value for an initial segment
|
||||
of the LRU list, to determine which blocks have recently been added
|
||||
to the start of the list. */
|
||||
|
||||
LRU_recent_limit = buf_LRU_get_recent_limit();
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
|
||||
if (buf_pool->n_pend_reads
|
||||
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
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(space, i);
|
||||
|
||||
if (bpage
|
||||
&& buf_page_is_accessed(bpage)
|
||||
&& (buf_page_get_LRU_position(bpage) > LRU_recent_limit)) {
|
||||
|
||||
recent_blocks++;
|
||||
|
||||
if (recent_blocks >= BUF_READ_AHEAD_RANDOM_THRESHOLD) {
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
goto read_ahead;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
/* Do nothing */
|
||||
return(0);
|
||||
|
||||
read_ahead:
|
||||
/* Read all the suitable blocks within the area */
|
||||
|
||||
if (ibuf_inside()) {
|
||||
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);
|
||||
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 */
|
||||
|
||||
++srv_read_ahead_rnd;
|
||||
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
|
||||
released by the i/o-handler thread. Does a random read-ahead if it seems
|
||||
sensible.
|
||||
@return number of page read requests issued: this can be greater than
|
||||
1 if read-ahead occurred */
|
||||
released by the i/o-handler thread.
|
||||
@return TRUE if page has been read in, FALSE in case of failure */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
ibool
|
||||
buf_read_page(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space id */
|
||||
|
|
@ -341,20 +173,17 @@ buf_read_page(
|
|||
{
|
||||
ib_int64_t tablespace_version;
|
||||
ulint count;
|
||||
ulint count2;
|
||||
ulint err;
|
||||
|
||||
tablespace_version = fil_space_get_version(space);
|
||||
|
||||
count = buf_read_ahead_random(space, zip_size, offset);
|
||||
|
||||
/* We do the i/o in the synchronous aio mode to save thread
|
||||
switches: hence TRUE */
|
||||
|
||||
count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
|
||||
zip_size, FALSE,
|
||||
tablespace_version, offset);
|
||||
srv_buf_pool_reads+= count2;
|
||||
count = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
|
||||
zip_size, FALSE,
|
||||
tablespace_version, offset);
|
||||
srv_buf_pool_reads += count;
|
||||
if (err == DB_TABLESPACE_DELETED) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
|
@ -371,14 +200,14 @@ buf_read_page(
|
|||
/* Increment number of I/O operations used for LRU policy. */
|
||||
buf_LRU_stat_inc_io();
|
||||
|
||||
return(count + count2);
|
||||
return(count > 0);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
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
|
||||
that the the algorithm looks at the 'natural' adjacent successor and
|
||||
that the algorithm looks at the 'natural' adjacent successor and
|
||||
predecessor of the page, which on the leaf level of a B-tree are the next
|
||||
and previous page in the chain of leaves. To know these, the page specified
|
||||
in (space, offset) must already be present in the buf_pool. Thus, the
|
||||
|
|
@ -498,9 +327,17 @@ buf_read_ahead_linear(
|
|||
fail_count++;
|
||||
|
||||
} else if (pred_bpage) {
|
||||
int res = (ut_ulint_cmp(
|
||||
buf_page_get_LRU_position(bpage),
|
||||
buf_page_get_LRU_position(pred_bpage)));
|
||||
/* Note that buf_page_is_accessed() returns
|
||||
the time of the first access. If some blocks
|
||||
of the extent existed in the buffer pool at
|
||||
the time of a linear access pattern, the first
|
||||
access times may be nonmonotonic, even though
|
||||
the latest access times were linear. The
|
||||
threshold (srv_read_ahead_factor) should help
|
||||
a little against this. */
|
||||
int res = ut_ulint_cmp(
|
||||
buf_page_is_accessed(bpage),
|
||||
buf_page_is_accessed(pred_bpage));
|
||||
/* Accesses not in the right order */
|
||||
if (res != 0 && res != asc_or_desc) {
|
||||
fail_count++;
|
||||
|
|
@ -643,7 +480,7 @@ buf_read_ahead_linear(
|
|||
LRU policy decision. */
|
||||
buf_LRU_stat_inc_io();
|
||||
|
||||
++srv_read_ahead_seq;
|
||||
buf_pool->stat.n_ra_pages_read += count;
|
||||
return(count);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1379,7 +1379,7 @@ dict_create_add_foreign_field_to_dictionary(
|
|||
Add a single foreign key definition to the data dictionary tables in the
|
||||
database. We also generate names to constraints that were not named by the
|
||||
user. A generated constraint has a name of the format
|
||||
databasename/tablename_ibfk_<number>, where the numbers start from 1, and
|
||||
databasename/tablename_ibfk_NUMBER, where the numbers start from 1, and
|
||||
are given locally for this table, that is, the number is not global, as in
|
||||
the old format constraints < 4.0.18 it used to be.
|
||||
@return error code or DB_SUCCESS */
|
||||
|
|
|
|||
|
|
@ -82,9 +82,10 @@ static char dict_ibfk[] = "_ibfk_";
|
|||
|
||||
/*******************************************************************//**
|
||||
Tries to find column names for the index and sets the col field of the
|
||||
index. */
|
||||
index.
|
||||
@return TRUE if the column names were found */
|
||||
static
|
||||
void
|
||||
ibool
|
||||
dict_index_find_cols(
|
||||
/*=================*/
|
||||
dict_table_t* table, /*!< in: table */
|
||||
|
|
@ -1169,7 +1170,7 @@ dict_col_name_is_reserved(
|
|||
ulint i;
|
||||
|
||||
for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
|
||||
if (strcmp(name, reserved_names[i]) == 0) {
|
||||
if (innobase_strcasecmp(name, reserved_names[i]) == 0) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
|
@ -1431,7 +1432,7 @@ add_field_size:
|
|||
|
||||
/**********************************************************************//**
|
||||
Adds an index to the dictionary cache.
|
||||
@return DB_SUCCESS or DB_TOO_BIG_RECORD */
|
||||
@return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
dict_index_add_to_cache(
|
||||
|
|
@ -1457,7 +1458,10 @@ dict_index_add_to_cache(
|
|||
ut_a(!dict_index_is_clust(index)
|
||||
|| UT_LIST_GET_LEN(table->indexes) == 0);
|
||||
|
||||
dict_index_find_cols(table, index);
|
||||
if (!dict_index_find_cols(table, index)) {
|
||||
|
||||
return(DB_CORRUPTION);
|
||||
}
|
||||
|
||||
/* Build the cache internal representation of the index,
|
||||
containing also the added system fields */
|
||||
|
|
@ -1665,9 +1669,10 @@ dict_index_remove_from_cache(
|
|||
|
||||
/*******************************************************************//**
|
||||
Tries to find column names for the index and sets the col field of the
|
||||
index. */
|
||||
index.
|
||||
@return TRUE if the column names were found */
|
||||
static
|
||||
void
|
||||
ibool
|
||||
dict_index_find_cols(
|
||||
/*=================*/
|
||||
dict_table_t* table, /*!< in: table */
|
||||
|
|
@ -1692,17 +1697,21 @@ dict_index_find_cols(
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/* It is an error not to find a matching column. */
|
||||
fputs("InnoDB: Error: no matching column for ", stderr);
|
||||
ut_print_name(stderr, NULL, FALSE, field->name);
|
||||
fputs(" in ", stderr);
|
||||
dict_index_name_print(stderr, NULL, index);
|
||||
fputs("!\n", stderr);
|
||||
ut_error;
|
||||
#endif /* UNIV_DEBUG */
|
||||
return(FALSE);
|
||||
|
||||
found:
|
||||
;
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
|
|
|
|||
|
|
@ -594,6 +594,11 @@ fil_node_create(
|
|||
|
||||
UT_LIST_ADD_LAST(chain, space->chain, node);
|
||||
|
||||
if (id < SRV_LOG_SPACE_FIRST_ID && fil_system->max_assigned_id < id) {
|
||||
|
||||
fil_system->max_assigned_id = id;
|
||||
}
|
||||
|
||||
mutex_exit(&fil_system->mutex);
|
||||
}
|
||||
|
||||
|
|
@ -613,12 +618,10 @@ fil_node_open_file(
|
|||
ulint size_high;
|
||||
ibool ret;
|
||||
ibool success;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
byte* buf2;
|
||||
byte* page;
|
||||
ulint space_id;
|
||||
ulint flags;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ut_ad(mutex_own(&(system->mutex)));
|
||||
ut_a(node->n_pending == 0);
|
||||
|
|
@ -654,9 +657,11 @@ fil_node_open_file(
|
|||
size_bytes = (((ib_int64_t)size_high) << 32)
|
||||
+ (ib_int64_t)size_low;
|
||||
#ifdef UNIV_HOTBACKUP
|
||||
node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
|
||||
/* TODO: adjust to zip_size, like below? */
|
||||
#else
|
||||
if (space->id == 0) {
|
||||
node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
|
||||
goto add_size;
|
||||
}
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
ut_a(space->purpose != FIL_LOG);
|
||||
ut_a(space->id != 0);
|
||||
|
||||
|
|
@ -735,7 +740,10 @@ fil_node_open_file(
|
|||
(size_bytes
|
||||
/ dict_table_flags_to_zip_size(flags));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UNIV_HOTBACKUP
|
||||
add_size:
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
space->size += node->size;
|
||||
}
|
||||
|
||||
|
|
@ -955,7 +963,7 @@ close_more:
|
|||
" while the maximum\n"
|
||||
"InnoDB: allowed value would be %lu.\n"
|
||||
"InnoDB: You may need to raise the value of"
|
||||
" innodb_max_files_open in\n"
|
||||
" innodb_open_files in\n"
|
||||
"InnoDB: my.cnf.\n",
|
||||
(ulong) fil_system->n_open,
|
||||
(ulong) fil_system->max_n_open);
|
||||
|
|
@ -1535,7 +1543,7 @@ fil_open_log_and_system_tablespace_files(void)
|
|||
fprintf(stderr,
|
||||
"InnoDB: Warning: you must"
|
||||
" raise the value of"
|
||||
" innodb_max_open_files in\n"
|
||||
" innodb_open_files in\n"
|
||||
"InnoDB: my.cnf! Remember that"
|
||||
" InnoDB keeps all log files"
|
||||
" and all system\n"
|
||||
|
|
@ -2923,7 +2931,6 @@ fil_open_single_table_tablespace(
|
|||
byte* page;
|
||||
ulint space_id;
|
||||
ulint space_flags;
|
||||
ibool ret = TRUE;
|
||||
|
||||
filepath = fil_make_ibd_name(name, FALSE);
|
||||
|
||||
|
|
@ -3001,7 +3008,7 @@ fil_open_single_table_tablespace(
|
|||
(ulong) space_id, (ulong) space_flags,
|
||||
(ulong) id, (ulong) flags);
|
||||
|
||||
ret = FALSE;
|
||||
success = FALSE;
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
|
@ -3021,7 +3028,7 @@ func_exit:
|
|||
os_file_close(file);
|
||||
mem_free(filepath);
|
||||
|
||||
return(ret);
|
||||
return(success);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
|
|
@ -3299,7 +3306,17 @@ fil_load_single_table_tablespace(
|
|||
|
||||
if (!success) {
|
||||
|
||||
goto func_exit;
|
||||
if (srv_force_recovery > 0) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: innodb_force_recovery"
|
||||
" was set to %lu. Continuing crash recovery\n"
|
||||
"InnoDB: even though the tablespace creation"
|
||||
" of this table failed.\n",
|
||||
srv_force_recovery);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* We do not use the size information we have about the file, because
|
||||
|
|
|
|||
|
|
@ -232,6 +232,9 @@ the extent are free and which contain old tuple version to clean. */
|
|||
#define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/* Flag to indicate if we have printed the tablespace full error. */
|
||||
static ibool fsp_tbs_full_error_printed = FALSE;
|
||||
|
||||
/**********************************************************************//**
|
||||
Returns an extent to the free list of a space. */
|
||||
static
|
||||
|
|
@ -1099,7 +1102,7 @@ fsp_header_inc_size(
|
|||
|
||||
/**********************************************************************//**
|
||||
Gets the current free limit of the system tablespace. The free limit
|
||||
means the place of the first page which has never been put to the the
|
||||
means the place of the first page which has never been put to the
|
||||
free list for allocation. The space above that address is initialized
|
||||
to zero. Sets also the global variable log_fsp_current_free_limit.
|
||||
@return free limit in megabytes */
|
||||
|
|
@ -1218,6 +1221,19 @@ fsp_try_extend_data_file(
|
|||
|
||||
if (space == 0 && !srv_auto_extend_last_data_file) {
|
||||
|
||||
/* We print the error message only once to avoid
|
||||
spamming the error log. Note that we don't need
|
||||
to reset the flag to FALSE as dealing with this
|
||||
error requires server restart. */
|
||||
if (fsp_tbs_full_error_printed == FALSE) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: Data file(s) ran"
|
||||
" out of space.\n"
|
||||
"Please add another data file or"
|
||||
" use \'autoextend\' for the last"
|
||||
" data file.\n");
|
||||
fsp_tbs_full_error_printed = TRUE;
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
|
@ -1832,6 +1848,8 @@ fsp_seg_inode_page_find_used(
|
|||
if (!ut_dulint_is_zero(mach_read_from_8(inode + FSEG_ID))) {
|
||||
/* This is used */
|
||||
|
||||
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
|
||||
== FSEG_MAGIC_N_VALUE);
|
||||
return(i);
|
||||
}
|
||||
}
|
||||
|
|
@ -1863,6 +1881,9 @@ fsp_seg_inode_page_find_free(
|
|||
|
||||
return(i);
|
||||
}
|
||||
|
||||
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
|
||||
== FSEG_MAGIC_N_VALUE);
|
||||
}
|
||||
|
||||
return(ULINT_UNDEFINED);
|
||||
|
|
@ -1981,6 +2002,8 @@ fsp_alloc_seg_inode(
|
|||
page + FSEG_INODE_PAGE_NODE, mtr);
|
||||
}
|
||||
|
||||
ut_ad(ut_dulint_is_zero(mach_read_from_8(inode + FSEG_ID))
|
||||
|| mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
|
||||
return(inode);
|
||||
}
|
||||
|
||||
|
|
@ -2018,7 +2041,7 @@ fsp_free_seg_inode(
|
|||
}
|
||||
|
||||
mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr);
|
||||
mlog_write_ulint(inode + FSEG_MAGIC_N, 0, MLOG_4BYTES, mtr);
|
||||
mlog_write_ulint(inode + FSEG_MAGIC_N, 0xfa051ce3, MLOG_4BYTES, mtr);
|
||||
|
||||
if (ULINT_UNDEFINED
|
||||
== fsp_seg_inode_page_find_used(page, zip_size, mtr)) {
|
||||
|
|
@ -2034,11 +2057,11 @@ fsp_free_seg_inode(
|
|||
|
||||
/**********************************************************************//**
|
||||
Returns the file segment inode, page x-latched.
|
||||
@return segment inode, page x-latched */
|
||||
@return segment inode, page x-latched; NULL if the inode is free */
|
||||
static
|
||||
fseg_inode_t*
|
||||
fseg_inode_get(
|
||||
/*===========*/
|
||||
fseg_inode_try_get(
|
||||
/*===============*/
|
||||
fseg_header_t* header, /*!< in: segment header */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes
|
||||
|
|
@ -2054,8 +2077,34 @@ fseg_inode_get(
|
|||
|
||||
inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr);
|
||||
|
||||
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
|
||||
if (UNIV_UNLIKELY
|
||||
(ut_dulint_is_zero(mach_read_from_8(inode + FSEG_ID)))) {
|
||||
|
||||
inode = NULL;
|
||||
} else {
|
||||
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
|
||||
== FSEG_MAGIC_N_VALUE);
|
||||
}
|
||||
|
||||
return(inode);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Returns the file segment inode, page x-latched.
|
||||
@return segment inode, page x-latched */
|
||||
static
|
||||
fseg_inode_t*
|
||||
fseg_inode_get(
|
||||
/*===========*/
|
||||
fseg_header_t* header, /*!< in: segment header */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
mtr_t* mtr) /*!< in: mtr handle */
|
||||
{
|
||||
fseg_inode_t* inode
|
||||
= fseg_inode_try_get(header, space, zip_size, mtr);
|
||||
ut_a(inode);
|
||||
return(inode);
|
||||
}
|
||||
|
||||
|
|
@ -2073,6 +2122,7 @@ fseg_get_nth_frag_page_no(
|
|||
ut_ad(inode && mtr);
|
||||
ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
|
||||
ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
|
||||
return(mach_read_from_4(inode + FSEG_FRAG_ARR
|
||||
+ n * FSEG_FRAG_SLOT_SIZE));
|
||||
}
|
||||
|
|
@ -2091,6 +2141,7 @@ fseg_set_nth_frag_page_no(
|
|||
ut_ad(inode && mtr);
|
||||
ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
|
||||
ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
|
||||
|
||||
mlog_write_ulint(inode + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE,
|
||||
page_no, MLOG_4BYTES, mtr);
|
||||
|
|
@ -2451,6 +2502,8 @@ fseg_fill_free_list(
|
|||
xdes_set_state(descr, XDES_FSEG, mtr);
|
||||
|
||||
seg_id = mtr_read_dulint(inode + FSEG_ID, mtr);
|
||||
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
|
||||
== FSEG_MAGIC_N_VALUE);
|
||||
mlog_write_dulint(descr + XDES_ID, seg_id, mtr);
|
||||
|
||||
flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
|
||||
|
|
@ -2479,6 +2532,7 @@ fseg_alloc_free_extent(
|
|||
fil_addr_t first;
|
||||
|
||||
ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
|
||||
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
|
||||
|
||||
if (flst_get_len(inode + FSEG_FREE, mtr) > 0) {
|
||||
/* Segment free list is not empty, allocate from it */
|
||||
|
|
@ -3136,6 +3190,8 @@ fseg_mark_page_used(
|
|||
|
||||
ut_ad(seg_inode && mtr);
|
||||
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
|
||||
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
|
||||
== FSEG_MAGIC_N_VALUE);
|
||||
|
||||
descr = xdes_get_descriptor(space, zip_size, page, mtr);
|
||||
|
||||
|
|
@ -3373,6 +3429,8 @@ fseg_free_extent(
|
|||
ut_a(xdes_get_state(descr, mtr) == XDES_FSEG);
|
||||
ut_a(0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, mtr),
|
||||
mtr_read_dulint(seg_inode + FSEG_ID, mtr)));
|
||||
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
|
||||
== FSEG_MAGIC_N_VALUE);
|
||||
|
||||
first_page_in_extent = page - (page % FSP_EXTENT_SIZE);
|
||||
|
||||
|
|
@ -3463,7 +3521,13 @@ fseg_free_step(
|
|||
ut_a(descr);
|
||||
ut_a(xdes_get_bit(descr, XDES_FREE_BIT,
|
||||
header_page % FSP_EXTENT_SIZE, mtr) == FALSE);
|
||||
inode = fseg_inode_get(header, space, zip_size, mtr);
|
||||
inode = fseg_inode_try_get(header, space, zip_size, mtr);
|
||||
|
||||
if (UNIV_UNLIKELY(inode == NULL)) {
|
||||
fprintf(stderr, "double free of inode from %u:%u\n",
|
||||
(unsigned) space, (unsigned) header_page);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
descr = fseg_get_first_extent(inode, space, zip_size, mtr);
|
||||
|
||||
|
|
@ -3587,6 +3651,7 @@ fseg_get_first_extent(
|
|||
ut_ad(inode && mtr);
|
||||
|
||||
ut_ad(space == page_get_space_id(page_align(inode)));
|
||||
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
|
||||
|
||||
first = fil_addr_null;
|
||||
|
||||
|
|
@ -3801,6 +3866,7 @@ fseg_print_low(
|
|||
(ulong) reserved, (ulong) used, (ulong) n_full,
|
||||
(ulong) n_frag, (ulong) n_free, (ulong) n_not_full,
|
||||
(ulong) n_used);
|
||||
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
|
||||
}
|
||||
|
||||
#ifdef UNIV_BTR_PRINT
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
/* Include necessary InnoDB headers */
|
||||
extern "C" {
|
||||
#include "univ.i"
|
||||
#include "buf0lru.h"
|
||||
#include "btr0sea.h"
|
||||
#include "os0file.h"
|
||||
#include "os0thread.h"
|
||||
|
|
@ -106,6 +107,9 @@ extern "C" {
|
|||
#include "i_s.h"
|
||||
|
||||
#ifndef MYSQL_SERVER
|
||||
# ifndef MYSQL_PLUGIN_IMPORT
|
||||
# define MYSQL_PLUGIN_IMPORT /* nothing */
|
||||
# endif /* MYSQL_PLUGIN_IMPORT */
|
||||
/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t
|
||||
is defined the same in both builds: the MySQL server and the InnoDB plugin. */
|
||||
extern MYSQL_PLUGIN_IMPORT pthread_mutex_t LOCK_thread_count;
|
||||
|
|
@ -152,6 +156,10 @@ static ulong innobase_write_io_threads;
|
|||
|
||||
static long long innobase_buffer_pool_size, innobase_log_file_size;
|
||||
|
||||
/** Percentage of the buffer pool to reserve for 'old' blocks.
|
||||
Connected to buf_LRU_old_ratio. */
|
||||
static uint innobase_old_blocks_pct;
|
||||
|
||||
/* The default values for the following char* start-up parameters
|
||||
are determined in innobase_init below: */
|
||||
|
||||
|
|
@ -166,9 +174,7 @@ file formats in the configuration file, but can only be set to any
|
|||
of the supported file formats during runtime. */
|
||||
static char* innobase_file_format_check = NULL;
|
||||
|
||||
/* The following has a misleading name: starting from 4.0.5, this also
|
||||
affects Windows: */
|
||||
static char* innobase_unix_file_flush_method = NULL;
|
||||
static char* innobase_file_flush_method = NULL;
|
||||
|
||||
/* Below we have boolean-valued start-up parameters, and their default
|
||||
values */
|
||||
|
|
@ -214,15 +220,34 @@ static void free_share(INNOBASE_SHARE *share);
|
|||
static int innobase_close_connection(handlerton *hton, THD* thd);
|
||||
static int innobase_commit(handlerton *hton, THD* thd, bool all);
|
||||
static int innobase_rollback(handlerton *hton, THD* thd, bool all);
|
||||
static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd,
|
||||
static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd,
|
||||
void *savepoint);
|
||||
static int innobase_savepoint(handlerton *hton, THD* thd, void *savepoint);
|
||||
static int innobase_release_savepoint(handlerton *hton, THD* thd,
|
||||
static int innobase_release_savepoint(handlerton *hton, THD* thd,
|
||||
void *savepoint);
|
||||
static handler *innobase_create_handler(handlerton *hton,
|
||||
TABLE_SHARE *table,
|
||||
MEM_ROOT *mem_root);
|
||||
|
||||
/***********************************************************************
|
||||
This function checks each index name for a table against reserved
|
||||
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
|
||||
this function pushes an error message to the client, and returns true. */
|
||||
static
|
||||
bool
|
||||
innobase_index_name_is_reserved(
|
||||
/*============================*/
|
||||
/* out: true if index name matches a
|
||||
reserved name */
|
||||
const trx_t* trx, /* in: InnoDB transaction handle */
|
||||
const TABLE* form, /* in: information on table
|
||||
columns and indexes */
|
||||
const char* norm_name); /* in: table name */
|
||||
|
||||
/* "GEN_CLUST_INDEX" is the name reserved for Innodb default
|
||||
system primary index. */
|
||||
static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX";
|
||||
|
||||
/** @brief Initialize the default value of innodb_commit_concurrency.
|
||||
|
||||
Once InnoDB is running, the innodb_commit_concurrency must not change
|
||||
|
|
@ -492,10 +517,10 @@ static SHOW_VAR innodb_status_variables[]= {
|
|||
(char*) &export_vars.innodb_buffer_pool_pages_misc, 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_seq",
|
||||
(char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
|
||||
{"buffer_pool_read_ahead",
|
||||
(char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG},
|
||||
{"buffer_pool_read_ahead_evicted",
|
||||
(char*) &export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_LONG},
|
||||
{"buffer_pool_read_requests",
|
||||
(char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG},
|
||||
{"buffer_pool_reads",
|
||||
|
|
@ -865,17 +890,14 @@ convert_error_code_to_mysql(
|
|||
return(ER_PRIMARY_CANT_HAVE_NULL);
|
||||
|
||||
case DB_TOO_MANY_CONCURRENT_TRXS:
|
||||
/* Once MySQL add the appropriate code to errmsg.txt then
|
||||
we can get rid of this #ifdef. NOTE: The code checked by
|
||||
the #ifdef is the suggested name for the error condition
|
||||
and the actual error code name could very well be different.
|
||||
This will require some monitoring, ie. the status
|
||||
of this request on our part.*/
|
||||
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
|
||||
return(ER_TOO_MANY_CONCURRENT_TRXS);
|
||||
#else
|
||||
/* New error code HA_ERR_TOO_MANY_CONCURRENT_TRXS is only
|
||||
available in 5.1.38 and later, but the plugin should still
|
||||
work with previous versions of MySQL. */
|
||||
#ifdef HA_ERR_TOO_MANY_CONCURRENT_TRXS
|
||||
return(HA_ERR_TOO_MANY_CONCURRENT_TRXS);
|
||||
#else /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
|
||||
return(HA_ERR_RECORD_FILE_FULL);
|
||||
#endif
|
||||
#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
|
||||
case DB_UNSUPPORTED:
|
||||
return(HA_ERR_UNSUPPORTED);
|
||||
}
|
||||
|
|
@ -949,7 +971,23 @@ innobase_get_cset_width(
|
|||
*mbminlen = cs->mbminlen;
|
||||
*mbmaxlen = cs->mbmaxlen;
|
||||
} else {
|
||||
ut_a(cset == 0);
|
||||
THD* thd = current_thd;
|
||||
|
||||
if (thd && thd_sql_command(thd) == SQLCOM_DROP_TABLE) {
|
||||
|
||||
/* Fix bug#46256: allow tables to be dropped if the
|
||||
collation is not found, but issue a warning. */
|
||||
if ((global_system_variables.log_warnings)
|
||||
&& (cset != 0)){
|
||||
|
||||
sql_print_warning(
|
||||
"Unknown collation #%lu.", cset);
|
||||
}
|
||||
} else {
|
||||
|
||||
ut_a(cset == 0);
|
||||
}
|
||||
|
||||
*mbminlen = *mbmaxlen = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -2151,7 +2189,7 @@ innobase_change_buffering_inited_ok:
|
|||
|
||||
/* --------------------------------------------------*/
|
||||
|
||||
srv_file_flush_method_str = innobase_unix_file_flush_method;
|
||||
srv_file_flush_method_str = innobase_file_flush_method;
|
||||
|
||||
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
|
||||
srv_n_log_files = (ulint) innobase_log_files_in_group;
|
||||
|
|
@ -2206,6 +2244,9 @@ innobase_change_buffering_inited_ok:
|
|||
ut_a(0 == strcmp(my_charset_latin1.name, "latin1_swedish_ci"));
|
||||
srv_latin1_ordering = my_charset_latin1.sort_order;
|
||||
|
||||
innobase_old_blocks_pct = buf_LRU_old_ratio_update(
|
||||
innobase_old_blocks_pct, FALSE);
|
||||
|
||||
innobase_commit_concurrency_init_default();
|
||||
|
||||
/* Since we in this module access directly the fields of a trx
|
||||
|
|
@ -2459,6 +2500,19 @@ retry:
|
|||
}
|
||||
}
|
||||
|
||||
/* The following calls to read the MySQL binary log
|
||||
file name and the position return consistent results:
|
||||
1) Other InnoDB transactions cannot intervene between
|
||||
these calls as we are holding prepare_commit_mutex.
|
||||
2) Binary logging of other engines is not relevant
|
||||
to InnoDB as all InnoDB requires is that committing
|
||||
InnoDB transactions appear in the same order in the
|
||||
MySQL binary log as they appear in InnoDB logs.
|
||||
3) A MySQL log file rotation cannot happen because
|
||||
MySQL protects against this by having a counter of
|
||||
transactions in prepared state and it only allows
|
||||
a rotation when the counter drops to zero. See
|
||||
LOCK_prep_xids and COND_prep_xids in log.cc. */
|
||||
trx->mysql_log_file_name = mysql_bin_log_file_name();
|
||||
trx->mysql_log_offset = (ib_int64_t) mysql_bin_log_file_pos();
|
||||
|
||||
|
|
@ -3105,7 +3159,7 @@ retry:
|
|||
|
||||
if (is_part) {
|
||||
sql_print_error("Failed to open table %s after "
|
||||
"%lu attemtps.\n", norm_name,
|
||||
"%lu attempts.\n", norm_name,
|
||||
retries);
|
||||
}
|
||||
|
||||
|
|
@ -5006,6 +5060,11 @@ ha_innobase::index_read(
|
|||
|
||||
index = prebuilt->index;
|
||||
|
||||
if (UNIV_UNLIKELY(index == NULL)) {
|
||||
prebuilt->index_usable = FALSE;
|
||||
DBUG_RETURN(HA_ERR_CRASHED);
|
||||
}
|
||||
|
||||
/* Note that if the index for which the search template is built is not
|
||||
necessarily prebuilt->index, but can also be the clustered index */
|
||||
|
||||
|
|
@ -5165,6 +5224,7 @@ ha_innobase::change_active_index(
|
|||
if (UNIV_UNLIKELY(!prebuilt->index)) {
|
||||
sql_print_warning("InnoDB: change_active_index(%u) failed",
|
||||
keynr);
|
||||
prebuilt->index_usable = FALSE;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
|
@ -5657,6 +5717,28 @@ create_table_def(
|
|||
}
|
||||
}
|
||||
|
||||
/* First check whether the column to be added has a
|
||||
system reserved name. */
|
||||
if (dict_col_name_is_reserved(field->field_name)){
|
||||
push_warning_printf(
|
||||
(THD*) trx->mysql_thd,
|
||||
MYSQL_ERROR::WARN_LEVEL_ERROR,
|
||||
ER_CANT_CREATE_TABLE,
|
||||
"Error creating table '%s' with "
|
||||
"column name '%s'. '%s' is a "
|
||||
"reserved name. Please try to "
|
||||
"re-create the table with a "
|
||||
"different column name.",
|
||||
table->name, (char*) field->field_name,
|
||||
(char*) field->field_name);
|
||||
|
||||
dict_mem_table_free(table);
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
error = DB_ERROR;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
dict_mem_table_add_col(table, table->heap,
|
||||
(char*) field->field_name,
|
||||
col_type,
|
||||
|
|
@ -5670,6 +5752,7 @@ create_table_def(
|
|||
|
||||
error = row_create_table_for_mysql(table, trx);
|
||||
|
||||
error_ret:
|
||||
error = convert_error_code_to_mysql(error, flags, NULL);
|
||||
|
||||
DBUG_RETURN(error);
|
||||
|
|
@ -5708,6 +5791,9 @@ create_index(
|
|||
|
||||
n_fields = key->key_parts;
|
||||
|
||||
/* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */
|
||||
ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0);
|
||||
|
||||
ind_type = 0;
|
||||
|
||||
if (key_num == form->s->primary_key) {
|
||||
|
|
@ -5816,8 +5902,8 @@ create_clustered_index_when_no_primary(
|
|||
|
||||
/* We pass 0 as the space id, and determine at a lower level the space
|
||||
id where to store the table */
|
||||
|
||||
index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
|
||||
index = dict_mem_index_create(table_name,
|
||||
innobase_index_reserve_name,
|
||||
0, DICT_CLUSTERED, 0);
|
||||
|
||||
error = row_create_index_for_mysql(index, trx, NULL);
|
||||
|
|
@ -6243,14 +6329,6 @@ ha_innobase::create(
|
|||
flags = DICT_TF_COMPACT;
|
||||
}
|
||||
|
||||
error = create_table_def(trx, form, norm_name,
|
||||
create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
|
||||
flags);
|
||||
|
||||
if (error) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Look for a primary key */
|
||||
|
||||
primary_key_no= (form->s->primary_key != MAX_KEY ?
|
||||
|
|
@ -6262,6 +6340,22 @@ ha_innobase::create(
|
|||
|
||||
ut_a(primary_key_no == -1 || primary_key_no == 0);
|
||||
|
||||
/* Check for name conflicts (with reserved name) for
|
||||
any user indices to be created. */
|
||||
if (innobase_index_name_is_reserved(trx, form, norm_name)) {
|
||||
error = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
error = create_table_def(trx, form, norm_name,
|
||||
create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
|
||||
flags);
|
||||
|
||||
if (error) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
/* Create the keys */
|
||||
|
||||
if (form->s->keys == 0 || primary_key_no == -1) {
|
||||
|
|
@ -8446,6 +8540,7 @@ ha_innobase::store_lock(
|
|||
&& isolation_level != TRX_ISO_SERIALIZABLE
|
||||
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
|
||||
&& (sql_command == SQLCOM_INSERT_SELECT
|
||||
|| sql_command == SQLCOM_REPLACE_SELECT
|
||||
|| sql_command == SQLCOM_UPDATE
|
||||
|| sql_command == SQLCOM_CREATE_TABLE)) {
|
||||
|
||||
|
|
@ -8453,10 +8548,11 @@ ha_innobase::store_lock(
|
|||
option set or this session is using READ COMMITTED
|
||||
isolation level and isolation level of the transaction
|
||||
is not set to serializable and MySQL is doing
|
||||
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
|
||||
CREATE ... SELECT... without FOR UPDATE or
|
||||
IN SHARE MODE in select, then we use consistent
|
||||
read for select. */
|
||||
INSERT INTO...SELECT or REPLACE INTO...SELECT
|
||||
or UPDATE ... = (SELECT ...) or CREATE ...
|
||||
SELECT... without FOR UPDATE or IN SHARE
|
||||
MODE in select, then we use consistent read
|
||||
for select. */
|
||||
|
||||
prebuilt->select_lock_type = LOCK_NONE;
|
||||
prebuilt->stored_select_lock_type = LOCK_NONE;
|
||||
|
|
@ -9612,6 +9708,25 @@ innodb_adaptive_hash_index_update(
|
|||
}
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Update the system variable innodb_old_blocks_pct using the "saved"
|
||||
value. This function is registered as a callback with MySQL. */
|
||||
static
|
||||
void
|
||||
innodb_old_blocks_pct_update(
|
||||
/*=========================*/
|
||||
THD* thd, /*!< in: thread handle */
|
||||
struct st_mysql_sys_var* var, /*!< in: pointer to
|
||||
system variable */
|
||||
void* var_ptr,/*!< out: where the
|
||||
formal string goes */
|
||||
const void* save) /*!< in: immediate result
|
||||
from check function */
|
||||
{
|
||||
innobase_old_blocks_pct = buf_LRU_old_ratio_update(
|
||||
*static_cast<const uint*>(save), TRUE);
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Check if it is a valid value of innodb_change_buffering. This function is
|
||||
registered as a callback with MySQL.
|
||||
|
|
@ -9685,6 +9800,46 @@ static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
This function checks each index name for a table against reserved
|
||||
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
|
||||
this function pushes an error message to the client, and returns true. */
|
||||
static
|
||||
bool
|
||||
innobase_index_name_is_reserved(
|
||||
/*============================*/
|
||||
/* out: true if an index name
|
||||
matches the reserved name */
|
||||
const trx_t* trx, /* in: InnoDB transaction handle */
|
||||
const TABLE* form, /* in: information on table
|
||||
columns and indexes */
|
||||
const char* norm_name) /* in: table name */
|
||||
{
|
||||
KEY* key;
|
||||
uint key_num; /* index number */
|
||||
|
||||
for (key_num = 0; key_num < form->s->keys; key_num++) {
|
||||
key = form->key_info + key_num;
|
||||
|
||||
if (innobase_strcasecmp(key->name,
|
||||
innobase_index_reserve_name) == 0) {
|
||||
/* Push warning to mysql */
|
||||
push_warning_printf((THD*) trx->mysql_thd,
|
||||
MYSQL_ERROR::WARN_LEVEL_ERROR,
|
||||
ER_CANT_CREATE_TABLE,
|
||||
"Cannot Create Index with name "
|
||||
"'%s'. The name is reserved "
|
||||
"for the system default primary "
|
||||
"index.",
|
||||
innobase_index_reserve_name);
|
||||
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
static SHOW_VAR innodb_status_variables_export[]= {
|
||||
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
|
||||
{NullS, NullS, SHOW_LONG}
|
||||
|
|
@ -9753,7 +9908,7 @@ static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
|
|||
" or 2 (write at commit, flush once per second).",
|
||||
NULL, NULL, 1, 0, 2, 0);
|
||||
|
||||
static MYSQL_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
|
||||
static MYSQL_SYSVAR_STR(flush_method, innobase_file_flush_method,
|
||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||
"With which method to flush data.", NULL, NULL, NULL);
|
||||
|
||||
|
|
@ -9849,7 +10004,7 @@ static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
|
|||
NULL, NULL, 500L, 1L, ~0L, 0);
|
||||
|
||||
static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
|
||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR,
|
||||
"Number of file I/O threads in InnoDB.",
|
||||
NULL, NULL, 4, 4, 64, 0);
|
||||
|
||||
|
|
@ -9888,6 +10043,18 @@ static MYSQL_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups,
|
|||
"Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
|
||||
NULL, NULL, 1, 1, 10, 0);
|
||||
|
||||
static MYSQL_SYSVAR_UINT(old_blocks_pct, innobase_old_blocks_pct,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"Percentage of the buffer pool to reserve for 'old' blocks.",
|
||||
NULL, innodb_old_blocks_pct_update, 100 * 3 / 8, 5, 95, 0);
|
||||
|
||||
static MYSQL_SYSVAR_UINT(old_blocks_time, buf_LRU_old_threshold_ms,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"Move blocks to the 'new' end of the buffer pool if the first access"
|
||||
" was at least this many milliseconds ago."
|
||||
" The timeout is disabled if 0 (the default).",
|
||||
NULL, NULL, 0, 0, UINT_MAX32, 0);
|
||||
|
||||
static MYSQL_SYSVAR_LONG(open_files, innobase_open_files,
|
||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||
"How many files at the maximum InnoDB keeps open at the same time.",
|
||||
|
|
@ -9986,6 +10153,8 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
|||
MYSQL_SYSVAR(adaptive_flushing),
|
||||
MYSQL_SYSVAR(max_purge_lag),
|
||||
MYSQL_SYSVAR(mirrored_log_groups),
|
||||
MYSQL_SYSVAR(old_blocks_pct),
|
||||
MYSQL_SYSVAR(old_blocks_time),
|
||||
MYSQL_SYSVAR(open_files),
|
||||
MYSQL_SYSVAR(rollback_on_timeout),
|
||||
MYSQL_SYSVAR(stats_on_metadata),
|
||||
|
|
|
|||
|
|
@ -663,7 +663,7 @@ ha_innobase::add_index(
|
|||
if (UNIV_UNLIKELY(error)) {
|
||||
err_exit:
|
||||
mem_heap_free(heap);
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
trx_free_for_mysql(trx);
|
||||
trx_commit_for_mysql(prebuilt->trx);
|
||||
DBUG_RETURN(error);
|
||||
|
|
@ -801,7 +801,7 @@ error_handling:
|
|||
alter table t drop index b, add index (b);
|
||||
|
||||
The fix will have to parse the SQL and note that the index
|
||||
being added has the same name as the the one being dropped and
|
||||
being added has the same name as the one being dropped and
|
||||
ignore that in the dup index check.*/
|
||||
//dict_table_check_for_dup_indexes(prebuilt->table);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2008, 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/handler0vars.h
|
||||
This file contains accessor functions for dynamic plugin on Windows.
|
||||
***********************************************************************/
|
||||
|
||||
#if defined __WIN__ && defined MYSQL_DYNAMIC_PLUGIN
|
||||
/*******************************************************************//**
|
||||
This is a list of externals that can not be resolved by delay loading.
|
||||
They have to be resolved indirectly via their addresses in the .map file.
|
||||
All of them are external variables. */
|
||||
extern CHARSET_INFO* wdl_my_charset_bin;
|
||||
extern CHARSET_INFO* wdl_my_charset_latin1;
|
||||
extern CHARSET_INFO* wdl_my_charset_filename;
|
||||
extern CHARSET_INFO** wdl_system_charset_info;
|
||||
extern CHARSET_INFO** wdl_default_charset_info;
|
||||
extern CHARSET_INFO** wdl_all_charsets;
|
||||
extern system_variables* wdl_global_system_variables;
|
||||
extern char* wdl_mysql_real_data_home;
|
||||
extern char** wdl_mysql_data_home;
|
||||
extern char** wdl_tx_isolation_names;
|
||||
extern char** wdl_binlog_format_names;
|
||||
extern char* wdl_reg_ext;
|
||||
extern pthread_mutex_t* wdl_LOCK_thread_count;
|
||||
extern key_map* wdl_key_map_full;
|
||||
extern MY_TMPDIR* wdl_mysql_tmpdir_list;
|
||||
extern bool* wdl_mysqld_embedded;
|
||||
extern uint* wdl_lower_case_table_names;
|
||||
extern ulong* wdl_specialflag;
|
||||
extern int* wdl_my_umask;
|
||||
|
||||
#define my_charset_bin (*wdl_my_charset_bin)
|
||||
#define my_charset_latin1 (*wdl_my_charset_latin1)
|
||||
#define my_charset_filename (*wdl_my_charset_filename)
|
||||
#define system_charset_info (*wdl_system_charset_info)
|
||||
#define default_charset_info (*wdl_default_charset_info)
|
||||
#define all_charsets (wdl_all_charsets)
|
||||
#define global_system_variables (*wdl_global_system_variables)
|
||||
#define mysql_real_data_home (wdl_mysql_real_data_home)
|
||||
#define mysql_data_home (*wdl_mysql_data_home)
|
||||
#define tx_isolation_names (wdl_tx_isolation_names)
|
||||
#define binlog_format_names (wdl_binlog_format_names)
|
||||
#define reg_ext (wdl_reg_ext)
|
||||
#define LOCK_thread_count (*wdl_LOCK_thread_count)
|
||||
#define key_map_full (*wdl_key_map_full)
|
||||
#define mysql_tmpdir_list (*wdl_mysql_tmpdir_list)
|
||||
#define mysqld_embedded (*wdl_mysqld_embedded)
|
||||
#define lower_case_table_names (*wdl_lower_case_table_names)
|
||||
#define specialflag (*wdl_specialflag)
|
||||
#define my_umask (*wdl_my_umask)
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -346,7 +346,7 @@ buf_page_release(
|
|||
mtr_t* mtr); /*!< in: mtr */
|
||||
/********************************************************************//**
|
||||
Moves a page to the start of the buffer pool LRU list. This high-level
|
||||
function can be used to prevent an important page from from slipping out of
|
||||
function can be used to prevent an important page from slipping out of
|
||||
the buffer pool. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
|
|
@ -707,15 +707,6 @@ buf_page_belongs_to_unzip_LRU(
|
|||
/*==========================*/
|
||||
const buf_page_t* bpage) /*!< in: pointer to control block */
|
||||
__attribute__((pure));
|
||||
/*********************************************************************//**
|
||||
Determine the approximate LRU list position of a block.
|
||||
@return LRU list position */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
buf_page_get_LRU_position(
|
||||
/*======================*/
|
||||
const buf_page_t* bpage) /*!< in: control block */
|
||||
__attribute__((pure));
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the mutex of a block.
|
||||
|
|
@ -816,14 +807,14 @@ buf_page_set_old(
|
|||
buf_page_t* bpage, /*!< in/out: control block */
|
||||
ibool old); /*!< in: old */
|
||||
/*********************************************************************//**
|
||||
Determine if a block has been accessed in the buffer pool.
|
||||
@return TRUE if accessed */
|
||||
Determine the time of first access of a block in the buffer pool.
|
||||
@return ut_time_ms() at the time of first access, 0 if not accessed */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
unsigned
|
||||
buf_page_is_accessed(
|
||||
/*=================*/
|
||||
const buf_page_t* bpage) /*!< in: control block */
|
||||
__attribute__((pure));
|
||||
__attribute__((nonnull, pure));
|
||||
/*********************************************************************//**
|
||||
Flag a block accessed. */
|
||||
UNIV_INLINE
|
||||
|
|
@ -831,7 +822,8 @@ void
|
|||
buf_page_set_accessed(
|
||||
/*==================*/
|
||||
buf_page_t* bpage, /*!< in/out: control block */
|
||||
ibool accessed); /*!< in: accessed */
|
||||
ulint time_ms) /*!< in: ut_time_ms() */
|
||||
__attribute__((nonnull));
|
||||
/*********************************************************************//**
|
||||
Gets the buf_block_t handle of a buffered file block if an uncompressed
|
||||
page frame exists, or NULL.
|
||||
|
|
@ -1017,14 +1009,6 @@ buf_block_hash_get(
|
|||
/*===============*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset);/*!< in: offset of the page within space */
|
||||
/*******************************************************************//**
|
||||
Increments the pool clock by one and returns its new value. Remember that
|
||||
in the 32 bit version the clock wraps around at 4 billion!
|
||||
@return new clock value */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
buf_pool_clock_tic(void);
|
||||
/*====================*/
|
||||
/*********************************************************************//**
|
||||
Gets the current length of the free list of buffer blocks.
|
||||
@return length of the free list */
|
||||
|
|
@ -1064,16 +1048,10 @@ struct buf_page_struct{
|
|||
flushed to disk, this tells the
|
||||
flush_type.
|
||||
@see enum buf_flush */
|
||||
unsigned accessed:1; /*!< TRUE if the page has been accessed
|
||||
while in the buffer pool: read-ahead
|
||||
may read in pages which have not been
|
||||
accessed yet; a thread is allowed to
|
||||
read this for heuristic purposes
|
||||
without holding any mutex or latch */
|
||||
unsigned io_fix:2; /*!< type of pending I/O operation;
|
||||
also protected by buf_pool_mutex
|
||||
@see enum buf_io_fix */
|
||||
unsigned buf_fix_count:24;/*!< count of how manyfold this block
|
||||
unsigned buf_fix_count:25;/*!< count of how manyfold this block
|
||||
is currently bufferfixed */
|
||||
/* @} */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
|
@ -1103,7 +1081,16 @@ struct buf_page_struct{
|
|||
- BUF_BLOCK_FILE_PAGE: flush_list
|
||||
- BUF_BLOCK_ZIP_DIRTY: flush_list
|
||||
- BUF_BLOCK_ZIP_PAGE: zip_clean
|
||||
- BUF_BLOCK_ZIP_FREE: zip_free[] */
|
||||
- BUF_BLOCK_ZIP_FREE: zip_free[]
|
||||
|
||||
The contents of the list node
|
||||
is undefined if !in_flush_list
|
||||
&& state == BUF_BLOCK_FILE_PAGE,
|
||||
or if state is one of
|
||||
BUF_BLOCK_MEMORY,
|
||||
BUF_BLOCK_REMOVE_HASH or
|
||||
BUF_BLOCK_READY_IN_USE. */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
ibool in_flush_list; /*!< TRUE if in buf_pool->flush_list;
|
||||
when buf_pool_mutex is free, the
|
||||
|
|
@ -1143,17 +1130,7 @@ struct buf_page_struct{
|
|||
#endif /* UNIV_DEBUG */
|
||||
unsigned old:1; /*!< TRUE if the block is in the old
|
||||
blocks in the LRU list */
|
||||
unsigned LRU_position:31;/*!< value which monotonically
|
||||
decreases (or may stay
|
||||
constant if old==TRUE) toward
|
||||
the end of the LRU list, if
|
||||
buf_pool->ulint_clock has not
|
||||
wrapped around: NOTE that this
|
||||
value can only be used in
|
||||
heuristic algorithms, because
|
||||
of the possibility of a
|
||||
wrap-around! */
|
||||
unsigned freed_page_clock:32;/*!< the value of
|
||||
unsigned freed_page_clock:31;/*!< the value of
|
||||
buf_pool->freed_page_clock
|
||||
when this block was the last
|
||||
time put to the head of the
|
||||
|
|
@ -1161,6 +1138,9 @@ struct buf_page_struct{
|
|||
to read this for heuristic
|
||||
purposes without holding any
|
||||
mutex or latch */
|
||||
unsigned access_time:32; /*!< time of first access, or
|
||||
0 if the block was never accessed
|
||||
in the buffer pool */
|
||||
/* @} */
|
||||
# ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
ibool file_page_was_freed;
|
||||
|
|
@ -1305,6 +1285,31 @@ Compute the hash fold value for blocks in buf_pool->zip_hash. */
|
|||
#define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
|
||||
/* @} */
|
||||
|
||||
/** @brief The buffer pool statistics structure. */
|
||||
struct buf_pool_stat_struct{
|
||||
ulint n_page_gets; /*!< number of page gets performed;
|
||||
also successful searches through
|
||||
the adaptive hash index are
|
||||
counted as page gets; this field
|
||||
is NOT protected by the buffer
|
||||
pool mutex */
|
||||
ulint n_pages_read; /*!< number read operations */
|
||||
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;/*!< number of pages read in
|
||||
as part of read ahead */
|
||||
ulint n_ra_pages_evicted;/*!< number of read ahead
|
||||
pages that are evicted without
|
||||
being accessed */
|
||||
ulint n_pages_made_young; /*!< number of pages made young, in
|
||||
calls to buf_LRU_make_block_young() */
|
||||
ulint n_pages_not_made_young; /*!< number of pages not made
|
||||
young because the first access
|
||||
was not long enough ago, in
|
||||
buf_page_peek_if_too_old() */
|
||||
};
|
||||
|
||||
/** @brief The buffer pool structure.
|
||||
|
||||
NOTE! The definition appears here only for other modules of this
|
||||
|
|
@ -1329,28 +1334,16 @@ struct buf_pool_struct{
|
|||
ulint n_pend_reads; /*!< number of pending read operations */
|
||||
ulint n_pend_unzip; /*!< number of pending decompressions */
|
||||
|
||||
time_t last_printout_time; /*!< when buf_print was last time
|
||||
time_t last_printout_time;
|
||||
/*!< when buf_print_io was last time
|
||||
called */
|
||||
ulint n_pages_read; /*!< number read operations */
|
||||
ulint n_pages_written;/*!< number write operations */
|
||||
ulint n_pages_created;/*!< number of pages created
|
||||
in the pool with no read */
|
||||
ulint n_page_gets; /*!< number of page gets performed;
|
||||
also successful searches through
|
||||
the adaptive hash index are
|
||||
counted as page gets; this field
|
||||
is NOT protected by the buffer
|
||||
pool mutex */
|
||||
ulint n_page_gets_old;/*!< n_page_gets when buf_print was
|
||||
last time called: used to calculate
|
||||
hit rate */
|
||||
ulint n_pages_read_old;/*!< n_pages_read when buf_print was
|
||||
last time called */
|
||||
ulint n_pages_written_old;/*!< number write operations */
|
||||
ulint n_pages_created_old;/*!< number of pages created in
|
||||
the pool with no read */
|
||||
buf_pool_stat_t stat; /*!< current statistics */
|
||||
buf_pool_stat_t old_stat; /*!< old statistics */
|
||||
|
||||
/* @} */
|
||||
|
||||
/** @name Page flushing algorithm fields */
|
||||
|
||||
/* @{ */
|
||||
|
||||
UT_LIST_BASE_NODE_T(buf_page_t) flush_list;
|
||||
|
|
@ -1366,10 +1359,6 @@ struct buf_pool_struct{
|
|||
/*!< this is in the set state
|
||||
when there is no flush batch
|
||||
of the given type running */
|
||||
ulint ulint_clock; /*!< a sequence number used to count
|
||||
time. NOTE! This counter wraps
|
||||
around at 4 billion (if ulint ==
|
||||
32 bits)! */
|
||||
ulint freed_page_clock;/*!< a sequence number used
|
||||
to count the number of buffer
|
||||
blocks removed from the end of
|
||||
|
|
@ -1393,9 +1382,11 @@ struct buf_pool_struct{
|
|||
block list */
|
||||
UT_LIST_BASE_NODE_T(buf_page_t) LRU;
|
||||
/*!< base node of the LRU list */
|
||||
buf_page_t* LRU_old; /*!< pointer to the about 3/8 oldest
|
||||
blocks in the LRU list; NULL if LRU
|
||||
length less than BUF_LRU_OLD_MIN_LEN;
|
||||
buf_page_t* LRU_old; /*!< pointer to the about
|
||||
buf_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;
|
||||
NOTE: when LRU_old != NULL, its length
|
||||
should always equal LRU_old_len */
|
||||
ulint LRU_old_len; /*!< length of the LRU list from
|
||||
|
|
|
|||
|
|
@ -72,9 +72,30 @@ buf_page_peek_if_too_old(
|
|||
/*=====================*/
|
||||
const buf_page_t* bpage) /*!< in: block to make younger */
|
||||
{
|
||||
return(buf_pool->freed_page_clock
|
||||
>= buf_page_get_freed_page_clock(bpage)
|
||||
+ 1 + (buf_pool->curr_size / 4));
|
||||
if (UNIV_UNLIKELY(buf_pool->freed_page_clock == 0)) {
|
||||
/* If eviction has not started yet, do not update the
|
||||
statistics or move blocks in the LRU list. This is
|
||||
either the warm-up phase or an in-memory workload. */
|
||||
return(FALSE);
|
||||
} else if (buf_LRU_old_threshold_ms && bpage->old) {
|
||||
unsigned access_time = buf_page_is_accessed(bpage);
|
||||
|
||||
if (access_time > 0
|
||||
&& (ut_time_ms() - access_time)
|
||||
>= buf_LRU_old_threshold_ms) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
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_LRU_old_ratio)
|
||||
/ (BUF_LRU_OLD_RATIO_DIV * 4))));
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
|
|
@ -118,22 +139,6 @@ buf_pool_get_oldest_modification(void)
|
|||
|
||||
return(lsn);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Increments the buf_pool clock by one and returns its new value. Remember
|
||||
that in the 32 bit version the clock wraps around at 4 billion!
|
||||
@return new clock value */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
buf_pool_clock_tic(void)
|
||||
/*====================*/
|
||||
{
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
|
||||
buf_pool->ulint_clock++;
|
||||
|
||||
return(buf_pool->ulint_clock);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/*********************************************************************//**
|
||||
|
|
@ -279,21 +284,6 @@ buf_page_belongs_to_unzip_LRU(
|
|||
&& buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Determine the approximate LRU list position of a block.
|
||||
@return LRU list position */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
buf_page_get_LRU_position(
|
||||
/*======================*/
|
||||
const buf_page_t* bpage) /*!< in: control block */
|
||||
{
|
||||
ut_ad(buf_page_in_file(bpage));
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
|
||||
return(bpage->LRU_position);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the mutex of a block.
|
||||
@return pointer to mutex protecting bpage */
|
||||
|
|
@ -487,17 +477,17 @@ buf_page_set_old(
|
|||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Determine if a block has been accessed in the buffer pool.
|
||||
@return TRUE if accessed */
|
||||
Determine the time of first access of a block in the buffer pool.
|
||||
@return ut_time_ms() at the time of first access, 0 if not accessed */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
unsigned
|
||||
buf_page_is_accessed(
|
||||
/*=================*/
|
||||
const buf_page_t* bpage) /*!< in: control block */
|
||||
{
|
||||
ut_ad(buf_page_in_file(bpage));
|
||||
|
||||
return(bpage->accessed);
|
||||
return(bpage->access_time);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
|
|
@ -507,12 +497,15 @@ void
|
|||
buf_page_set_accessed(
|
||||
/*==================*/
|
||||
buf_page_t* bpage, /*!< in/out: control block */
|
||||
ibool accessed) /*!< in: accessed */
|
||||
ulint time_ms) /*!< in: ut_time_ms() */
|
||||
{
|
||||
ut_a(buf_page_in_file(bpage));
|
||||
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
|
||||
bpage->accessed = accessed;
|
||||
if (!bpage->access_time) {
|
||||
/* Make this the time of the first access. */
|
||||
bpage->access_time = time_ms;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ These are low-level functions
|
|||
#########################################################################*/
|
||||
|
||||
/** Minimum LRU list length for which the LRU_old pointer is defined */
|
||||
#define BUF_LRU_OLD_MIN_LEN 80
|
||||
#define BUF_LRU_OLD_MIN_LEN 512 /* 8 megabytes of 16k pages */
|
||||
|
||||
/** Maximum LRU list search length in buf_flush_LRU_recommendation() */
|
||||
#define BUF_LRU_FREE_SEARCH_LEN (5 + 2 * BUF_READ_AHEAD_AREA)
|
||||
|
|
@ -84,15 +84,6 @@ void
|
|||
buf_LRU_invalidate_tablespace(
|
||||
/*==========================*/
|
||||
ulint id); /*!< in: space id */
|
||||
/******************************************************************//**
|
||||
Gets the minimum LRU_position field for the blocks in an initial segment
|
||||
(determined by BUF_LRU_INITIAL_RATIO) of the LRU list. The limit is not
|
||||
guaranteed to be precise, because the ulint_clock may wrap around.
|
||||
@return the limit; zero if could not determine it */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_LRU_get_recent_limit(void);
|
||||
/*==========================*/
|
||||
/********************************************************************//**
|
||||
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
|
||||
UNIV_INTERN
|
||||
|
|
@ -201,6 +192,18 @@ void
|
|||
buf_LRU_make_block_old(
|
||||
/*===================*/
|
||||
buf_page_t* bpage); /*!< in: control block */
|
||||
/**********************************************************************//**
|
||||
Updates buf_LRU_old_ratio.
|
||||
@return updated old_pct */
|
||||
UNIV_INTERN
|
||||
uint
|
||||
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
|
||||
during the initialization of InnoDB */
|
||||
/********************************************************************//**
|
||||
Update the historical stats that we are collecting for LRU eviction
|
||||
policy at the end of each interval. */
|
||||
|
|
@ -227,6 +230,35 @@ 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. */
|
||||
#define BUF_LRU_OLD_RATIO_DIV 1024
|
||||
/** Maximum value of buf_LRU_old_ratio.
|
||||
@see buf_LRU_old_adjust_len
|
||||
@see buf_LRU_old_ratio_update */
|
||||
#define BUF_LRU_OLD_RATIO_MAX BUF_LRU_OLD_RATIO_DIV
|
||||
/** Minimum value of buf_LRU_old_ratio.
|
||||
@see buf_LRU_old_adjust_len
|
||||
@see buf_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
|
||||
|
||||
#if BUF_LRU_OLD_RATIO_MIN >= BUF_LRU_OLD_RATIO_MAX
|
||||
# error "BUF_LRU_OLD_RATIO_MIN >= BUF_LRU_OLD_RATIO_MAX"
|
||||
#endif
|
||||
#if BUF_LRU_OLD_RATIO_MAX > BUF_LRU_OLD_RATIO_DIV
|
||||
# error "BUF_LRU_OLD_RATIO_MAX > BUF_LRU_OLD_RATIO_DIV"
|
||||
#endif
|
||||
|
||||
/** Move blocks to "new" LRU list only if the first access was at
|
||||
least this many milliseconds ago. Not protected by any mutex or latch. */
|
||||
extern uint buf_LRU_old_threshold_ms;
|
||||
/* @} */
|
||||
|
||||
/** @brief Statistics for selecting the LRU list for eviction.
|
||||
|
||||
These statistics are not 'of' LRU but 'for' LRU. We keep count of I/O
|
||||
|
|
|
|||
|
|
@ -33,12 +33,10 @@ Created 11/5/1995 Heikki Tuuri
|
|||
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
|
||||
released by the i/o-handler thread. Does a random read-ahead if it seems
|
||||
sensible.
|
||||
@return number of page read requests issued: this can be greater than
|
||||
1 if read-ahead occurred */
|
||||
released by the i/o-handler thread.
|
||||
@return TRUE if page has been read in, FALSE in case of failure */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
ibool
|
||||
buf_read_page(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space id */
|
||||
|
|
@ -48,7 +46,7 @@ buf_read_page(
|
|||
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
|
||||
that the the algorithm looks at the 'natural' adjacent successor and
|
||||
that the algorithm looks at the 'natural' adjacent successor and
|
||||
predecessor of the page, which on the leaf level of a B-tree are the next
|
||||
and previous page in the chain of leaves. To know these, the page specified
|
||||
in (space, offset) must already be present in the buf_pool. Thus, the
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ typedef struct buf_block_struct buf_block_t;
|
|||
typedef struct buf_chunk_struct buf_chunk_t;
|
||||
/** Buffer pool comprising buf_chunk_t */
|
||||
typedef struct buf_pool_struct buf_pool_t;
|
||||
/** Buffer pool statistics struct */
|
||||
typedef struct buf_pool_stat_struct buf_pool_stat_t;
|
||||
|
||||
/** A buffer frame. @see page_t */
|
||||
typedef byte buf_frame_t;
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ dict_create_or_check_foreign_constraint_tables(void);
|
|||
Adds foreign key definitions to data dictionary tables in the database. We
|
||||
look at table->foreign_list, and also generate names to constraints that were
|
||||
not named by the user. A generated constraint has a name of the format
|
||||
databasename/tablename_ibfk_<number>, where the numbers start from 1, and are
|
||||
databasename/tablename_ibfk_NUMBER, where the numbers start from 1, and are
|
||||
given locally for this table, that is, the number is not global, as in the
|
||||
old format constraints < 4.0.18 it used to be.
|
||||
@return error code or DB_SUCCESS */
|
||||
|
|
|
|||
|
|
@ -712,7 +712,7 @@ dict_index_find_on_id_low(
|
|||
dulint id); /*!< in: index id */
|
||||
/**********************************************************************//**
|
||||
Adds an index to the dictionary cache.
|
||||
@return DB_SUCCESS or error code */
|
||||
@return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
dict_index_add_to_cache(
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ struct dict_foreign_struct{
|
|||
char* id; /*!< id of the constraint as a
|
||||
null-terminated string */
|
||||
unsigned n_fields:10; /*!< number of indexes' first fields
|
||||
for which the the foreign key
|
||||
for which the foreign key
|
||||
constraint is defined: we allow the
|
||||
indexes to contain more fields than
|
||||
mentioned in the constraint, as long
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ fsp_init(void);
|
|||
/*==========*/
|
||||
/**********************************************************************//**
|
||||
Gets the current free limit of the system tablespace. The free limit
|
||||
means the place of the first page which has never been put to the the
|
||||
means the place of the first page which has never been put to the
|
||||
free list for allocation. The space above that address is initialized
|
||||
to zero. Sets also the global variable log_fsp_current_free_limit.
|
||||
@return free limit in megabytes */
|
||||
|
|
|
|||
|
|
@ -630,6 +630,14 @@ lock_number_of_rows_locked(
|
|||
/*=======================*/
|
||||
trx_t* trx); /*!< in: transaction */
|
||||
/*******************************************************************//**
|
||||
Check if a transaction holds any autoinc locks.
|
||||
@return TRUE if the transaction holds any AUTOINC locks. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
lock_trx_holds_autoinc_locks(
|
||||
/*=========================*/
|
||||
const trx_t* trx); /*!< in: transaction */
|
||||
/*******************************************************************//**
|
||||
Release all the transaction's autoinc locks. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
|
|
|
|||
|
|
@ -118,10 +118,9 @@ UNIV_INLINE
|
|||
ib_uint64_t
|
||||
log_reserve_and_write_fast(
|
||||
/*=======================*/
|
||||
byte* str, /*!< in: string */
|
||||
const void* str, /*!< in: string */
|
||||
ulint len, /*!< in: string length */
|
||||
ib_uint64_t* start_lsn,/*!< out: start lsn of the log record */
|
||||
ibool* success);/*!< out: TRUE if success */
|
||||
ib_uint64_t* start_lsn);/*!< out: start lsn of the log record */
|
||||
/***********************************************************************//**
|
||||
Releases the log mutex. */
|
||||
UNIV_INLINE
|
||||
|
|
@ -283,7 +282,7 @@ log_make_checkpoint_at(
|
|||
later lsn, if IB_ULONGLONG_MAX, makes
|
||||
a checkpoint at the latest lsn */
|
||||
ibool write_always); /*!< in: the function normally checks if
|
||||
the the new checkpoint would have a
|
||||
the new checkpoint would have a
|
||||
greater lsn than the previous one: if
|
||||
not, then no physical write is done;
|
||||
by setting this parameter TRUE, a
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ Created 12/9/1995 Heikki Tuuri
|
|||
#include "mach0data.h"
|
||||
#include "mtr0mtr.h"
|
||||
|
||||
#ifdef UNIV_LOG_DEBUG
|
||||
/******************************************************//**
|
||||
Checks by parsing that the catenated log segment for a single mtr is
|
||||
consistent. */
|
||||
|
|
@ -34,11 +35,12 @@ UNIV_INTERN
|
|||
ibool
|
||||
log_check_log_recs(
|
||||
/*===============*/
|
||||
byte* buf, /*!< in: pointer to the start of
|
||||
const byte* buf, /*!< in: pointer to the start of
|
||||
the log segment in the
|
||||
log_sys->buf log buffer */
|
||||
ulint len, /*!< in: segment length in bytes */
|
||||
ib_uint64_t buf_start_lsn); /*!< in: buffer start lsn */
|
||||
#endif /* UNIV_LOG_DEBUG */
|
||||
|
||||
/************************************************************//**
|
||||
Gets a log block flush bit.
|
||||
|
|
@ -305,55 +307,76 @@ UNIV_INLINE
|
|||
ib_uint64_t
|
||||
log_reserve_and_write_fast(
|
||||
/*=======================*/
|
||||
byte* str, /*!< in: string */
|
||||
const void* str, /*!< in: string */
|
||||
ulint len, /*!< in: string length */
|
||||
ib_uint64_t* start_lsn,/*!< out: start lsn of the log record */
|
||||
ibool* success)/*!< out: TRUE if success */
|
||||
ib_uint64_t* start_lsn)/*!< out: start lsn of the log record */
|
||||
{
|
||||
log_t* log = log_sys;
|
||||
ulint data_len;
|
||||
ib_uint64_t lsn;
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
/* length of the LSN pseudo-record */
|
||||
ulint lsn_len = 1
|
||||
+ mach_get_compressed_size(log_sys->lsn >> 32)
|
||||
+ mach_get_compressed_size(log_sys->lsn & 0xFFFFFFFFUL);
|
||||
#endif /* UNIV_LOG_LSN_DEBUG */
|
||||
|
||||
*success = TRUE;
|
||||
mutex_enter(&log_sys->mutex);
|
||||
|
||||
mutex_enter(&(log->mutex));
|
||||
|
||||
data_len = len + log->buf_free % OS_FILE_LOG_BLOCK_SIZE;
|
||||
data_len = len
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
+ lsn_len
|
||||
#endif /* UNIV_LOG_LSN_DEBUG */
|
||||
+ log_sys->buf_free % OS_FILE_LOG_BLOCK_SIZE;
|
||||
|
||||
if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
|
||||
|
||||
/* The string does not fit within the current log block
|
||||
or the log block would become full */
|
||||
|
||||
*success = FALSE;
|
||||
|
||||
mutex_exit(&(log->mutex));
|
||||
mutex_exit(&log_sys->mutex);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
*start_lsn = log->lsn;
|
||||
*start_lsn = log_sys->lsn;
|
||||
|
||||
ut_memcpy(log->buf + log->buf_free, str, len);
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
{
|
||||
/* Write the LSN pseudo-record. */
|
||||
byte* b = &log_sys->buf[log_sys->buf_free];
|
||||
*b++ = MLOG_LSN | (MLOG_SINGLE_REC_FLAG & *(const byte*) str);
|
||||
/* Write the LSN in two parts,
|
||||
as a pseudo page number and space id. */
|
||||
b += mach_write_compressed(b, log_sys->lsn >> 32);
|
||||
b += mach_write_compressed(b, log_sys->lsn & 0xFFFFFFFFUL);
|
||||
ut_a(b - lsn_len == &log_sys->buf[log_sys->buf_free]);
|
||||
|
||||
log_block_set_data_len((byte*) ut_align_down(log->buf + log->buf_free,
|
||||
memcpy(b, str, len);
|
||||
len += lsn_len;
|
||||
}
|
||||
#else /* UNIV_LOG_LSN_DEBUG */
|
||||
memcpy(log_sys->buf + log_sys->buf_free, str, len);
|
||||
#endif /* UNIV_LOG_LSN_DEBUG */
|
||||
|
||||
log_block_set_data_len((byte*) ut_align_down(log_sys->buf
|
||||
+ log_sys->buf_free,
|
||||
OS_FILE_LOG_BLOCK_SIZE),
|
||||
data_len);
|
||||
#ifdef UNIV_LOG_DEBUG
|
||||
log->old_buf_free = log->buf_free;
|
||||
log->old_lsn = log->lsn;
|
||||
log_sys->old_buf_free = log_sys->buf_free;
|
||||
log_sys->old_lsn = log_sys->lsn;
|
||||
#endif
|
||||
log->buf_free += len;
|
||||
log_sys->buf_free += len;
|
||||
|
||||
ut_ad(log->buf_free <= log->buf_size);
|
||||
ut_ad(log_sys->buf_free <= log_sys->buf_size);
|
||||
|
||||
lsn = log->lsn += len;
|
||||
log_sys->lsn += len;
|
||||
|
||||
#ifdef UNIV_LOG_DEBUG
|
||||
log_check_log_recs(log->buf + log->old_buf_free,
|
||||
log->buf_free - log->old_buf_free, log->old_lsn);
|
||||
log_check_log_recs(log_sys->buf + log_sys->old_buf_free,
|
||||
log_sys->buf_free - log_sys->old_buf_free,
|
||||
log_sys->old_lsn);
|
||||
#endif
|
||||
return(lsn);
|
||||
return(log_sys->lsn);
|
||||
}
|
||||
|
||||
/***********************************************************************//**
|
||||
|
|
|
|||
|
|
@ -433,6 +433,11 @@ are allowed yet: the variable name is misleading. */
|
|||
extern ibool recv_no_ibuf_operations;
|
||||
/** TRUE when recv_init_crash_recovery() has been called. */
|
||||
extern ibool recv_needed_recovery;
|
||||
#ifdef UNIV_DEBUG
|
||||
/** TRUE if writing to the redo log (mtr_commit) is forbidden.
|
||||
Protected by log_sys->mutex. */
|
||||
extern ibool recv_no_log_write;
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/** TRUE if buf_page_is_corrupted() should check if the log sequence
|
||||
number (FIL_PAGE_LSN) is in the future. Initially FALSE, and set by
|
||||
|
|
|
|||
|
|
@ -106,6 +106,9 @@ For 1 - 8 bytes, the flag value must give the length also! @{ */
|
|||
#define MLOG_IBUF_BITMAP_INIT ((byte)27) /*!< initialize an
|
||||
ibuf bitmap page */
|
||||
/*#define MLOG_FULL_PAGE ((byte)28) full contents of a page */
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
# define MLOG_LSN ((byte)28) /* current LSN */
|
||||
#endif
|
||||
#define MLOG_INIT_FILE_PAGE ((byte)29) /*!< this means that a
|
||||
file page is taken
|
||||
into use and the prior
|
||||
|
|
@ -118,7 +121,7 @@ For 1 - 8 bytes, the flag value must give the length also! @{ */
|
|||
#define MLOG_WRITE_STRING ((byte)30) /*!< write a string to
|
||||
a page */
|
||||
#define MLOG_MULTI_REC_END ((byte)31) /*!< if a single mtr writes
|
||||
log records for several pages,
|
||||
several log records,
|
||||
this log record ends the
|
||||
sequence of these records */
|
||||
#define MLOG_DUMMY_RECORD ((byte)32) /*!< dummy log record used to
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ log. */
|
|||
to become available again */
|
||||
#define OS_FILE_SHARING_VIOLATION 76
|
||||
#define OS_FILE_ERROR_NOT_SPECIFIED 77
|
||||
#define OS_FILE_INSUFFICIENT_RESOURCE 78
|
||||
/* @} */
|
||||
|
||||
/** Types for aio operations @{ */
|
||||
|
|
|
|||
|
|
@ -285,44 +285,74 @@ os_fast_mutex_free(
|
|||
/**********************************************************//**
|
||||
Atomic compare-and-swap and increment for InnoDB. */
|
||||
|
||||
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||
#if defined(HAVE_IB_GCC_ATOMIC_BUILTINS)
|
||||
|
||||
#define HAVE_ATOMIC_BUILTINS
|
||||
|
||||
/**********************************************************//**
|
||||
Returns true if swapped, ptr is pointer to target, old_val is value to
|
||||
compare to, new_val is the value to swap in. */
|
||||
|
||||
# define os_compare_and_swap(ptr, old_val, new_val) \
|
||||
__sync_bool_compare_and_swap(ptr, old_val, new_val)
|
||||
|
||||
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
|
||||
os_compare_and_swap(ptr, old_val, new_val)
|
||||
|
||||
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
|
||||
os_compare_and_swap(ptr, old_val, new_val)
|
||||
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
|
||||
|
||||
# ifdef HAVE_IB_ATOMIC_PTHREAD_T_GCC
|
||||
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
|
||||
os_compare_and_swap(ptr, old_val, new_val)
|
||||
# define INNODB_RW_LOCKS_USE_ATOMICS
|
||||
# define IB_ATOMICS_STARTUP_MSG \
|
||||
"Mutexes and rw_locks use GCC atomic builtins"
|
||||
# else /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
|
||||
# define IB_ATOMICS_STARTUP_MSG \
|
||||
"Mutexes use GCC atomic builtins, rw_locks do not"
|
||||
# endif /* HAVE_IB_ATOMIC_PTHREAD_T_GCC */
|
||||
|
||||
/**********************************************************//**
|
||||
Returns the resulting value, ptr is pointer to target, amount is the
|
||||
amount of increment. */
|
||||
|
||||
# define os_atomic_increment(ptr, amount) \
|
||||
__sync_add_and_fetch(ptr, amount)
|
||||
|
||||
# define os_atomic_increment_lint(ptr, amount) \
|
||||
os_atomic_increment(ptr, amount)
|
||||
|
||||
# define os_atomic_increment_ulint(ptr, amount) \
|
||||
os_atomic_increment(ptr, amount)
|
||||
|
||||
/**********************************************************//**
|
||||
Returns the old value of *ptr, atomically sets *ptr to new_val */
|
||||
|
||||
# define os_atomic_test_and_set_byte(ptr, new_val) \
|
||||
__sync_lock_test_and_set(ptr, new_val)
|
||||
|
||||
#elif defined(HAVE_IB_SOLARIS_ATOMICS)
|
||||
|
||||
#define HAVE_ATOMIC_BUILTINS
|
||||
|
||||
/* If not compiling with GCC or GCC doesn't support the atomic
|
||||
intrinsics and running on Solaris >= 10 use Solaris atomics */
|
||||
#elif defined(HAVE_SOLARIS_ATOMICS)
|
||||
|
||||
#include <atomic.h>
|
||||
|
||||
/**********************************************************//**
|
||||
Returns true if swapped, ptr is pointer to target, old_val is value to
|
||||
compare to, new_val is the value to swap in. */
|
||||
|
||||
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
|
||||
(atomic_cas_ulong(ptr, old_val, new_val) == old_val)
|
||||
|
||||
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
|
||||
((lint)atomic_cas_ulong((ulong_t*) ptr, old_val, new_val) == old_val)
|
||||
# ifdef INNODB_RW_LOCKS_USE_ATOMICS
|
||||
# if SIZEOF_PTHREAD_T == 4
|
||||
|
||||
# ifdef HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS
|
||||
# if SIZEOF_PTHREAD_T == 4
|
||||
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
|
||||
((pthread_t)atomic_cas_32(ptr, old_val, new_val) == old_val)
|
||||
# elif SIZEOF_PTHREAD_T == 8
|
||||
|
|
@ -331,21 +361,35 @@ compare to, new_val is the value to swap in. */
|
|||
# else
|
||||
# error "SIZEOF_PTHREAD_T != 4 or 8"
|
||||
# endif /* SIZEOF_PTHREAD_T CHECK */
|
||||
# endif /* INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
# define INNODB_RW_LOCKS_USE_ATOMICS
|
||||
# define IB_ATOMICS_STARTUP_MSG \
|
||||
"Mutexes and rw_locks use Solaris atomic functions"
|
||||
# else /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */
|
||||
# define IB_ATOMICS_STARTUP_MSG \
|
||||
"Mutexes use Solaris atomic functions, rw_locks do not"
|
||||
# endif /* HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS */
|
||||
|
||||
/**********************************************************//**
|
||||
Returns the resulting value, ptr is pointer to target, amount is the
|
||||
amount of increment. */
|
||||
|
||||
# define os_atomic_increment_lint(ptr, amount) \
|
||||
atomic_add_long_nv((ulong_t*) ptr, amount)
|
||||
|
||||
# define os_atomic_increment_ulint(ptr, amount) \
|
||||
atomic_add_long_nv(ptr, amount)
|
||||
|
||||
/**********************************************************//**
|
||||
Returns the old value of *ptr, atomically sets *ptr to new_val */
|
||||
|
||||
# define os_atomic_test_and_set_byte(ptr, new_val) \
|
||||
atomic_swap_uchar(ptr, new_val)
|
||||
/* On Windows, use Windows atomics / interlocked */
|
||||
|
||||
#elif defined(HAVE_WINDOWS_ATOMICS)
|
||||
|
||||
#define HAVE_ATOMIC_BUILTINS
|
||||
|
||||
/* On Windows, use Windows atomics / interlocked */
|
||||
# ifdef _WIN64
|
||||
# define win_cmp_and_xchg InterlockedCompareExchange64
|
||||
# define win_xchg_and_add InterlockedExchangeAdd64
|
||||
|
|
@ -353,31 +397,46 @@ Returns the old value of *ptr, atomically sets *ptr to new_val */
|
|||
# define win_cmp_and_xchg InterlockedCompareExchange
|
||||
# define win_xchg_and_add InterlockedExchangeAdd
|
||||
# endif
|
||||
|
||||
/**********************************************************//**
|
||||
Returns true if swapped, ptr is pointer to target, old_val is value to
|
||||
compare to, new_val is the value to swap in. */
|
||||
|
||||
# define os_compare_and_swap_ulint(ptr, old_val, new_val) \
|
||||
(win_cmp_and_xchg(ptr, new_val, old_val) == old_val)
|
||||
|
||||
# define os_compare_and_swap_lint(ptr, old_val, new_val) \
|
||||
(win_cmp_and_xchg(ptr, new_val, old_val) == old_val)
|
||||
# ifdef INNODB_RW_LOCKS_USE_ATOMICS
|
||||
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
|
||||
|
||||
/* windows thread objects can always be passed to windows atomic functions */
|
||||
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
|
||||
(InterlockedCompareExchange(ptr, new_val, old_val) == old_val)
|
||||
# endif /* INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
# define INNODB_RW_LOCKS_USE_ATOMICS
|
||||
# define IB_ATOMICS_STARTUP_MSG \
|
||||
"Mutexes and rw_locks use Windows interlocked functions"
|
||||
|
||||
/**********************************************************//**
|
||||
Returns the resulting value, ptr is pointer to target, amount is the
|
||||
amount of increment. */
|
||||
|
||||
# define os_atomic_increment_lint(ptr, amount) \
|
||||
(win_xchg_and_add(ptr, amount) + amount)
|
||||
|
||||
# define os_atomic_increment_ulint(ptr, amount) \
|
||||
((ulint) (win_xchg_and_add(ptr, amount) + amount))
|
||||
|
||||
/**********************************************************//**
|
||||
Returns the old value of *ptr, atomically sets *ptr to new_val.
|
||||
InterlockedExchange() operates on LONG, and the LONG will be
|
||||
clobbered */
|
||||
|
||||
# define os_atomic_test_and_set_byte(ptr, new_val) \
|
||||
((byte) InterlockedExchange(ptr, new_val))
|
||||
#endif /* HAVE_GCC_ATOMIC_BUILTINS */
|
||||
|
||||
#else
|
||||
# define IB_ATOMICS_STARTUP_MSG \
|
||||
"Mutexes and rw_locks use InnoDB's own implementation"
|
||||
#endif
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "os0sync.ic"
|
||||
|
|
|
|||
|
|
@ -76,8 +76,11 @@ typedef byte page_header_t;
|
|||
header which are set in a page create */
|
||||
/*----*/
|
||||
#define PAGE_LEVEL 26 /* level of the node in an index tree; the
|
||||
leaf level is the level 0 */
|
||||
#define PAGE_INDEX_ID 28 /* index id where the page belongs */
|
||||
leaf level is the level 0. This field should
|
||||
not be written to after page creation. */
|
||||
#define PAGE_INDEX_ID 28 /* index id where the page belongs.
|
||||
This field should not be written to after
|
||||
page creation. */
|
||||
#define PAGE_BTR_SEG_LEAF 36 /* file segment header for the leaf pages in
|
||||
a B-tree: defined only on the root page of a
|
||||
B-tree, but not in the root of an ibuf tree */
|
||||
|
|
|
|||
|
|
@ -127,8 +127,12 @@ page_zip_decompress(
|
|||
/*================*/
|
||||
page_zip_des_t* page_zip,/*!< in: data, ssize;
|
||||
out: m_start, m_end, m_nonempty, n_blobs */
|
||||
page_t* page) /*!< out: uncompressed page, may be trashed */
|
||||
__attribute__((nonnull));
|
||||
page_t* page, /*!< out: uncompressed page, may be trashed */
|
||||
ibool all) /*!< in: TRUE=decompress the whole page;
|
||||
FALSE=verify but do not copy some
|
||||
page header fields that should not change
|
||||
after page creation */
|
||||
__attribute__((nonnull(1,2)));
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/**********************************************************************//**
|
||||
|
|
@ -385,8 +389,8 @@ IMPORTANT: if page_zip_reorganize() is invoked on a leaf page of a
|
|||
non-clustered index, the caller must update the insert buffer free
|
||||
bits in the same mini-transaction in such a way that the modification
|
||||
will be redo-logged.
|
||||
@return TRUE on success, FALSE on failure; page and page_zip will be
|
||||
left intact on failure. */
|
||||
@return TRUE on success, FALSE on failure; page_zip will be left
|
||||
intact on failure, but page will be overwritten. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
page_zip_reorganize(
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ cmp_dfield_dfield(
|
|||
/*************************************************************//**
|
||||
This function is used to compare a data tuple to a physical record.
|
||||
Only dtuple->n_fields_cmp first fields are taken into account for
|
||||
the the data tuple! If we denote by n = n_fields_cmp, then rec must
|
||||
the data tuple! If we denote by n = n_fields_cmp, then rec must
|
||||
have either m >= n fields, or it must differ from dtuple in some of
|
||||
the m fields rec has. If rec has an externally stored field we do not
|
||||
compare it but return with value 0 if such a comparison should be
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ most significant bytes and bits are written below less significant.
|
|||
- offset_of_this_record) mod 64Ki,
|
||||
where mod is the modulo as a non-negative
|
||||
number;
|
||||
we can calculate the the offset of the next
|
||||
we can calculate the offset of the next
|
||||
record with the formula:
|
||||
relative_offset + offset_of_this_record
|
||||
mod UNIV_PAGE_SIZE
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ row_ins_check_foreign_constraint(
|
|||
/*=============================*/
|
||||
ibool check_ref,/*!< in: TRUE If we want to check that
|
||||
the referenced table is ok, FALSE if we
|
||||
want to to check the foreign key table */
|
||||
want to check the foreign key table */
|
||||
dict_foreign_t* foreign,/*!< in: foreign constraint; NOTE that the
|
||||
tables mentioned in it must be in the
|
||||
dictionary cache if they exist at all */
|
||||
|
|
|
|||
|
|
@ -177,7 +177,9 @@ row_update_prebuilt_trx(
|
|||
in MySQL handle */
|
||||
trx_t* trx); /*!< in: transaction handle */
|
||||
/*********************************************************************//**
|
||||
Unlocks AUTO_INC type locks that were possibly reserved by a trx. */
|
||||
Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
|
||||
function should be called at the the end of an SQL statement, by the
|
||||
connection thread that owns the transaction (trx->mysql_thd). */
|
||||
UNIV_INTERN
|
||||
void
|
||||
row_unlock_table_autoinc_for_mysql(
|
||||
|
|
|
|||
|
|
@ -315,10 +315,6 @@ extern ulint srv_buf_pool_flushed;
|
|||
/** Number of buffer pool reads that led to the
|
||||
reading of a disk page */
|
||||
extern ulint srv_buf_pool_reads;
|
||||
/** Number of sequential read-aheads */
|
||||
extern ulint srv_read_ahead_seq;
|
||||
/** Number of random read-aheads */
|
||||
extern ulint srv_read_ahead_rnd;
|
||||
|
||||
/** Status variables to be passed to MySQL */
|
||||
typedef struct export_var_struct export_struc;
|
||||
|
|
@ -605,13 +601,13 @@ struct export_var_struct{
|
|||
#ifdef UNIV_DEBUG
|
||||
ulint innodb_buffer_pool_pages_latched; /*!< Latched pages */
|
||||
#endif /* UNIV_DEBUG */
|
||||
ulint innodb_buffer_pool_read_requests; /*!< buf_pool->n_page_gets */
|
||||
ulint innodb_buffer_pool_read_requests; /*!< buf_pool->stat.n_page_gets */
|
||||
ulint innodb_buffer_pool_reads; /*!< srv_buf_pool_reads */
|
||||
ulint innodb_buffer_pool_wait_free; /*!< srv_buf_pool_wait_free */
|
||||
ulint innodb_buffer_pool_pages_flushed; /*!< srv_buf_pool_flushed */
|
||||
ulint innodb_buffer_pool_write_requests;/*!< srv_buf_pool_write_requests */
|
||||
ulint innodb_buffer_pool_read_ahead_seq;/*!< srv_read_ahead_seq */
|
||||
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_dblwr_pages_written; /*!< srv_dblwr_pages_written */
|
||||
ulint innodb_dblwr_writes; /*!< srv_dblwr_writes */
|
||||
ibool innodb_have_atomic_builtins; /*!< HAVE_ATOMIC_BUILTINS */
|
||||
|
|
@ -623,9 +619,9 @@ struct export_var_struct{
|
|||
ulint innodb_os_log_pending_writes; /*!< srv_os_log_pending_writes */
|
||||
ulint innodb_os_log_pending_fsyncs; /*!< fil_n_pending_log_flushes */
|
||||
ulint innodb_page_size; /*!< UNIV_PAGE_SIZE */
|
||||
ulint innodb_pages_created; /*!< buf_pool->n_pages_created */
|
||||
ulint innodb_pages_read; /*!< buf_pool->n_pages_read */
|
||||
ulint innodb_pages_written; /*!< buf_pool->n_pages_written */
|
||||
ulint innodb_pages_created; /*!< buf_pool->stat.n_pages_created */
|
||||
ulint innodb_pages_read; /*!< buf_pool->stat.n_pages_read */
|
||||
ulint innodb_pages_written; /*!< buf_pool->stat.n_pages_written */
|
||||
ulint innodb_row_lock_waits; /*!< srv_n_lock_wait_count */
|
||||
ulint innodb_row_lock_current_waits; /*!< srv_n_lock_wait_current_count */
|
||||
ib_int64_t innodb_row_lock_time; /*!< srv_n_lock_wait_time
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ UNIV_INLINE
|
|||
trx_undo_rec_t*
|
||||
trx_undo_rec_copy(
|
||||
/*==============*/
|
||||
trx_undo_rec_t* undo_rec, /*!< in: undo log record */
|
||||
mem_heap_t* heap); /*!< in: heap where copied */
|
||||
const trx_undo_rec_t* undo_rec, /*!< in: undo log record */
|
||||
mem_heap_t* heap); /*!< in: heap where copied */
|
||||
/**********************************************************************//**
|
||||
Reads the undo log record type.
|
||||
@return record type */
|
||||
|
|
|
|||
|
|
@ -100,8 +100,8 @@ UNIV_INLINE
|
|||
trx_undo_rec_t*
|
||||
trx_undo_rec_copy(
|
||||
/*==============*/
|
||||
trx_undo_rec_t* undo_rec, /*!< in: undo log record */
|
||||
mem_heap_t* heap) /*!< in: heap where copied */
|
||||
const trx_undo_rec_t* undo_rec, /*!< in: undo log record */
|
||||
mem_heap_t* heap) /*!< in: heap where copied */
|
||||
{
|
||||
ulint len;
|
||||
|
||||
|
|
|
|||
|
|
@ -133,6 +133,17 @@ trx_rollback(
|
|||
Rollback or clean up any incomplete transactions which were
|
||||
encountered in crash recovery. If the transaction already was
|
||||
committed, then we clean up a possible insert undo log. If the
|
||||
transaction was not yet committed, then we roll it back. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_rollback_or_clean_recovered(
|
||||
/*============================*/
|
||||
ibool all); /*!< in: FALSE=roll back dictionary transactions;
|
||||
TRUE=roll back all non-PREPARED transactions */
|
||||
/*******************************************************************//**
|
||||
Rollback or clean up any incomplete transactions which were
|
||||
encountered in crash recovery. If the transaction already was
|
||||
committed, then we clean up a possible insert undo log. If the
|
||||
transaction was not yet committed, then we roll it back.
|
||||
Note: this is done in a background thread.
|
||||
@return a dummy parameter */
|
||||
|
|
@ -208,9 +219,9 @@ int
|
|||
trx_general_rollback_for_mysql(
|
||||
/*===========================*/
|
||||
trx_t* trx, /*!< in: transaction handle */
|
||||
ibool partial,/*!< in: TRUE if partial rollback requested */
|
||||
trx_savept_t* savept);/*!< in: pointer to savepoint undo number, if
|
||||
partial rollback requested */
|
||||
partial rollback requested, or NULL for
|
||||
complete rollback */
|
||||
/*******************************************************************//**
|
||||
Rolls back a transaction back to a named savepoint. Modifications after the
|
||||
savepoint are undone but InnoDB does NOT release the corresponding locks
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@ typedef byte trx_sysf_rseg_t;
|
|||
|
||||
/* Rollback segment specification slot offsets */
|
||||
/*-------------------------------------------------------------*/
|
||||
#define TRX_SYS_RSEG_SPACE 0 /* space where the the segment
|
||||
#define TRX_SYS_RSEG_SPACE 0 /* space where the segment
|
||||
header is placed; starting with
|
||||
MySQL/InnoDB 5.1.7, this is
|
||||
UNIV_UNDEFINED if the slot is unused */
|
||||
#define TRX_SYS_RSEG_PAGE_NO 4 /* page number where the the segment
|
||||
#define TRX_SYS_RSEG_PAGE_NO 4 /* page number where the segment
|
||||
header is placed; this is FIL_NULL
|
||||
if the slot is unused */
|
||||
/*-------------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ trx_commit_off_kernel(
|
|||
/****************************************************************//**
|
||||
Cleans up a transaction at database startup. The cleanup is needed if
|
||||
the transaction already got to the middle of a commit when the database
|
||||
crashed, andf we cannot roll it back. */
|
||||
crashed, and we cannot roll it back. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_cleanup_at_db_startup(
|
||||
|
|
@ -360,7 +360,7 @@ enum trx_dict_op {
|
|||
operation modes in crash recovery. */
|
||||
TRX_DICT_OP_TABLE = 1,
|
||||
/** The transaction is creating or dropping an index in an
|
||||
existing table. In crash recovery, the the data dictionary
|
||||
existing table. In crash recovery, the data dictionary
|
||||
must be locked, but the table must not be dropped. */
|
||||
TRX_DICT_OP_INDEX = 2
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,11 +46,11 @@ Created 1/20/1994 Heikki Tuuri
|
|||
|
||||
#define INNODB_VERSION_MAJOR 1
|
||||
#define INNODB_VERSION_MINOR 0
|
||||
#define INNODB_VERSION_BUGFIX 4
|
||||
#define INNODB_VERSION_BUGFIX 5
|
||||
|
||||
/* The following is the InnoDB version as shown in
|
||||
SELECT plugin_version FROM information_schema.plugins;
|
||||
calculated in in make_version_string() in sql/sql_show.cc like this:
|
||||
calculated in make_version_string() in sql/sql_show.cc like this:
|
||||
"version >> 8" . "version & 0xff"
|
||||
because the version is shown with only one dot, we skip the last
|
||||
component, i.e. we show M.N.P as M.N */
|
||||
|
|
@ -78,17 +78,25 @@ the virtual method table (vtable) in GCC 3. */
|
|||
# define ha_innobase ha_innodb
|
||||
#endif /* MYSQL_DYNAMIC_PLUGIN */
|
||||
|
||||
/* if any of the following macros is defined at this point this means
|
||||
that the code from the "right" plug.in was executed and we do not
|
||||
need to include ut0auxconf.h which would either define the same macros
|
||||
or will be empty */
|
||||
#if !defined(HAVE_IB_GCC_ATOMIC_BUILTINS) \
|
||||
&& !defined(HAVE_IB_ATOMIC_PTHREAD_T_GCC) \
|
||||
&& !defined(HAVE_IB_SOLARIS_ATOMICS) \
|
||||
&& !defined(HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS) \
|
||||
&& !defined(SIZEOF_PTHREAD_T) \
|
||||
&& !defined(HAVE_IB_PAUSE_INSTRUCTION)
|
||||
# include "ut0auxconf.h"
|
||||
#endif
|
||||
|
||||
#if (defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)) && !defined(MYSQL_SERVER) && !defined(__WIN__)
|
||||
# undef __WIN__
|
||||
# define __WIN__
|
||||
|
||||
# include <windows.h>
|
||||
|
||||
# if defined(HAVE_WINDOWS_ATOMICS)
|
||||
/* If atomics are defined we use them in InnoDB mutex implementation */
|
||||
# define HAVE_ATOMIC_BUILTINS
|
||||
# endif /* HAVE_WINDOWS_ATOMICS */
|
||||
|
||||
# ifdef _NT_
|
||||
# define __NT__
|
||||
# endif
|
||||
|
|
@ -111,45 +119,17 @@ if we are compiling on Windows. */
|
|||
# include <sys/mman.h> /* mmap() for os0proc.c */
|
||||
# endif
|
||||
|
||||
# undef PACKAGE
|
||||
# undef VERSION
|
||||
|
||||
/* Include the header file generated by GNU autoconf */
|
||||
# ifndef __WIN__
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "config.h"
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
# include "config.h"
|
||||
# endif /* UNIV_HOTBACKUP */
|
||||
# endif
|
||||
|
||||
# ifdef HAVE_SCHED_H
|
||||
# include <sched.h>
|
||||
# endif
|
||||
|
||||
# if defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_SOLARIS_ATOMICS) \
|
||||
|| defined(HAVE_WINDOWS_ATOMICS)
|
||||
/* If atomics are defined we use them in InnoDB mutex implementation */
|
||||
# define HAVE_ATOMIC_BUILTINS
|
||||
# endif /* (HAVE_GCC_ATOMIC_BUILTINS) || (HAVE_SOLARIS_ATOMICS)
|
||||
|| (HAVE_WINDOWS_ATOMICS) */
|
||||
|
||||
/* For InnoDB rw_locks to work with atomics we need the thread_id
|
||||
to be no more than machine word wide. The following enables using
|
||||
atomics for InnoDB rw_locks where these conditions are met. */
|
||||
#ifdef HAVE_ATOMIC_BUILTINS
|
||||
/* if HAVE_ATOMIC_PTHREAD_T is defined at this point that means that
|
||||
the code from plug.in has defined it and we do not need to include
|
||||
ut0auxconf.h which would either define HAVE_ATOMIC_PTHREAD_T or will
|
||||
be empty */
|
||||
# ifndef HAVE_ATOMIC_PTHREAD_T
|
||||
# include "ut0auxconf.h"
|
||||
# endif /* HAVE_ATOMIC_PTHREAD_T */
|
||||
/* now HAVE_ATOMIC_PTHREAD_T is eventually defined either by plug.in or
|
||||
from Makefile.in->ut0auxconf.h */
|
||||
# ifdef HAVE_ATOMIC_PTHREAD_T
|
||||
# define INNODB_RW_LOCKS_USE_ATOMICS
|
||||
# endif /* HAVE_ATOMIC_PTHREAD_T */
|
||||
#endif /* HAVE_ATOMIC_BUILTINS */
|
||||
|
||||
/* We only try to do explicit inlining of functions with gcc and
|
||||
Sun Studio */
|
||||
|
||||
|
|
@ -196,12 +176,18 @@ command. Not tested on Windows. */
|
|||
debugging without UNIV_DEBUG */
|
||||
#define UNIV_DEBUG /* Enable ut_ad() assertions
|
||||
and disable UNIV_INLINE */
|
||||
#define UNIV_DEBUG_LOCK_VALIDATE /* Enable
|
||||
ut_ad(lock_rec_validate_page())
|
||||
assertions. */
|
||||
#define UNIV_DEBUG_FILE_ACCESSES /* Debug .ibd file access
|
||||
(field file_page_was_freed
|
||||
in buf_page_t) */
|
||||
#define UNIV_LRU_DEBUG /* debug the buffer pool LRU */
|
||||
#define UNIV_HASH_DEBUG /* debug HASH_ macros */
|
||||
#define UNIV_LIST_DEBUG /* debug UT_LIST_ macros */
|
||||
#define UNIV_LOG_LSN_DEBUG /* write LSN to the redo log;
|
||||
this will break redo log file compatibility, but it may be useful when
|
||||
debugging redo log application problems. */
|
||||
#define UNIV_MEM_DEBUG /* detect memory leaks etc */
|
||||
#define UNIV_IBUF_DEBUG /* debug the insert buffer */
|
||||
#define UNIV_IBUF_COUNT_DEBUG /* debug the insert buffer;
|
||||
|
|
@ -409,7 +395,8 @@ it is read. */
|
|||
it is read or written. */
|
||||
# define UNIV_PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 3)
|
||||
/* Sun Studio includes sun_prefetch.h as of version 5.9 */
|
||||
#elif (defined(__SUNPRO_C) && __SUNPRO_C >= 0x590) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
|
||||
#elif (defined(__SUNPRO_C) && __SUNPRO_C >= 0x590) \
|
||||
|| (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
|
||||
# include <sun_prefetch.h>
|
||||
#if __SUNPRO_C >= 0x550
|
||||
# undef UNIV_INTERN
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
/* Do not remove this file even though it is empty.
|
||||
This file is included in univ.i and will cause compilation failure
|
||||
if not present.
|
||||
A custom check has been added in the generated
|
||||
A custom checks have been added in the generated
|
||||
storage/innobase/Makefile.in that is shipped with the InnoDB Plugin
|
||||
source archive. This check tries to compile a test program and if
|
||||
successful then adds "#define HAVE_ATOMIC_PTHREAD_T" to this file.
|
||||
This is a hack that has been developed in order to check for pthread_t
|
||||
atomicity without the need to regenerate the ./configure script that is
|
||||
source archive. These checks eventually define some macros and put
|
||||
them in this file.
|
||||
This is a hack that has been developed in order to deploy new compile
|
||||
time checks without the need to regenerate the ./configure script that is
|
||||
distributed in the MySQL 5.1 official source archives.
|
||||
If by any chance Makefile.in and ./configure are regenerated and thus
|
||||
the hack from Makefile.in wiped away then the "real" check from plug.in
|
||||
the hack from Makefile.in wiped away then the "real" checks from plug.in
|
||||
will take over.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -219,8 +219,8 @@ UNIV_INLINE
|
|||
void*
|
||||
ut_align(
|
||||
/*=====*/
|
||||
void* ptr, /*!< in: pointer */
|
||||
ulint align_no); /*!< in: align by this number */
|
||||
const void* ptr, /*!< in: pointer */
|
||||
ulint align_no); /*!< in: align by this number */
|
||||
/*********************************************************//**
|
||||
The following function rounds down a pointer to the nearest
|
||||
aligned address.
|
||||
|
|
|
|||
|
|
@ -319,8 +319,8 @@ UNIV_INLINE
|
|||
void*
|
||||
ut_align(
|
||||
/*=====*/
|
||||
void* ptr, /*!< in: pointer */
|
||||
ulint align_no) /*!< in: align by this number */
|
||||
const void* ptr, /*!< in: pointer */
|
||||
ulint align_no) /*!< in: align by this number */
|
||||
{
|
||||
ut_ad(align_no > 0);
|
||||
ut_ad(((align_no - 1) & align_no) == 0);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,11 @@ Created 1/20/1994 Heikki Tuuri
|
|||
#define ut0ut_h
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
|
||||
#include <time.h>
|
||||
#ifndef MYSQL_SERVER
|
||||
#include <ctype.h>
|
||||
|
|
@ -47,7 +52,8 @@ Created 1/20/1994 Heikki Tuuri
|
|||
/** Time stamp */
|
||||
typedef time_t ib_time_t;
|
||||
|
||||
#if defined(IB_HAVE_PAUSE_INSTRUCTION)
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#if defined(HAVE_IB_PAUSE_INSTRUCTION)
|
||||
# ifdef WIN32
|
||||
/* In the Win32 API, the x86 PAUSE instruction is executed by calling
|
||||
the YieldProcessor macro defined in WinNT.h. It is a CPU architecture-
|
||||
|
|
@ -84,6 +90,7 @@ do { \
|
|||
os_thread_sleep(2000 /* 2 ms */); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/********************************************************//**
|
||||
Gets the high 32 bits in a ulint. That is makes a shift >> 32,
|
||||
|
|
@ -216,6 +223,7 @@ UNIV_INTERN
|
|||
ib_time_t
|
||||
ut_time(void);
|
||||
/*=========*/
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/**********************************************************//**
|
||||
Returns system time.
|
||||
Upon successful completion, the value 0 is returned; otherwise the
|
||||
|
|
@ -239,6 +247,16 @@ ullint
|
|||
ut_time_us(
|
||||
/*=======*/
|
||||
ullint* tloc); /*!< out: us since epoch, if non-NULL */
|
||||
/**********************************************************//**
|
||||
Returns the number of milliseconds since some epoch. The
|
||||
value may wrap around. It should only be used for heuristic
|
||||
purposes.
|
||||
@return ms since epoch */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
ut_time_ms(void);
|
||||
/*============*/
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/**********************************************************//**
|
||||
Returns the difference of two times in seconds.
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ a waiting s-lock request on the next record? If this s-lock was placed
|
|||
by a read cursor moving in the ascending order in the index, we cannot
|
||||
do the insert immediately, because when we finally commit our transaction,
|
||||
the read cursor should see also the new inserted record. So we should
|
||||
move the read cursor backward from the the next record for it to pass over
|
||||
move the read cursor backward from the next record for it to pass over
|
||||
the new inserted record. This move backward may be too cumbersome to
|
||||
implement. If we in this situation just enqueue a second x-lock request
|
||||
for our transaction on the next record, then the deadlock mechanism
|
||||
|
|
@ -360,10 +360,9 @@ ibool
|
|||
lock_rec_validate_page(
|
||||
/*===================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
ulint page_no);/*!< in: page number */
|
||||
|
||||
/* Define the following in order to enable lock_rec_validate_page() checks. */
|
||||
# undef UNIV_DEBUG_LOCK_VALIDATE
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/* The lock system */
|
||||
|
|
@ -2622,6 +2621,7 @@ lock_move_reorganize_page(
|
|||
|
||||
#ifdef UNIV_DEBUG_LOCK_VALIDATE
|
||||
ut_ad(lock_rec_validate_page(buf_block_get_space(block),
|
||||
buf_block_get_zip_size(block),
|
||||
buf_block_get_page_no(block)));
|
||||
#endif
|
||||
}
|
||||
|
|
@ -2711,8 +2711,10 @@ lock_move_rec_list_end(
|
|||
|
||||
#ifdef UNIV_DEBUG_LOCK_VALIDATE
|
||||
ut_ad(lock_rec_validate_page(buf_block_get_space(block),
|
||||
buf_block_get_zip_size(block),
|
||||
buf_block_get_page_no(block)));
|
||||
ut_ad(lock_rec_validate_page(buf_block_get_space(new_block),
|
||||
buf_block_get_zip_size(block),
|
||||
buf_block_get_page_no(new_block)));
|
||||
#endif
|
||||
}
|
||||
|
|
@ -2822,6 +2824,7 @@ lock_move_rec_list_start(
|
|||
|
||||
#ifdef UNIV_DEBUG_LOCK_VALIDATE
|
||||
ut_ad(lock_rec_validate_page(buf_block_get_space(block),
|
||||
buf_block_get_zip_size(block),
|
||||
buf_block_get_page_no(block)));
|
||||
#endif
|
||||
}
|
||||
|
|
@ -4630,6 +4633,10 @@ lock_rec_queue_validate(
|
|||
next function call: we have to release lock table mutex
|
||||
to obey the latching order */
|
||||
|
||||
/* If this thread is holding the file space latch
|
||||
(fil_space_t::latch), the following check WILL break
|
||||
latching order and may cause a deadlock of threads. */
|
||||
|
||||
impl_trx = lock_sec_rec_some_has_impl_off_kernel(
|
||||
rec, index, offsets);
|
||||
|
||||
|
|
@ -4687,6 +4694,8 @@ ibool
|
|||
lock_rec_validate_page(
|
||||
/*===================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
ulint page_no)/*!< in: page number */
|
||||
{
|
||||
dict_index_t* index;
|
||||
|
|
@ -4697,7 +4706,6 @@ lock_rec_validate_page(
|
|||
ulint nth_lock = 0;
|
||||
ulint nth_bit = 0;
|
||||
ulint i;
|
||||
ulint zip_size;
|
||||
mtr_t mtr;
|
||||
mem_heap_t* heap = NULL;
|
||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||
|
|
@ -4708,7 +4716,6 @@ lock_rec_validate_page(
|
|||
|
||||
mtr_start(&mtr);
|
||||
|
||||
zip_size = fil_space_get_zip_size(space);
|
||||
ut_ad(zip_size != ULINT_UNDEFINED);
|
||||
block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, &mtr);
|
||||
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
|
||||
|
|
@ -4753,6 +4760,11 @@ loop:
|
|||
|
||||
lock_mutex_exit_kernel();
|
||||
|
||||
/* If this thread is holding the file space
|
||||
latch (fil_space_t::latch), the following
|
||||
check WILL break the latching order and may
|
||||
cause a deadlock of threads. */
|
||||
|
||||
lock_rec_queue_validate(block, rec, index, offsets);
|
||||
|
||||
lock_mutex_enter_kernel();
|
||||
|
|
@ -4843,7 +4855,9 @@ lock_validate(void)
|
|||
|
||||
lock_mutex_exit_kernel();
|
||||
|
||||
lock_rec_validate_page(space, page_no);
|
||||
lock_rec_validate_page(space,
|
||||
fil_space_get_zip_size(space),
|
||||
page_no);
|
||||
|
||||
lock_mutex_enter_kernel();
|
||||
|
||||
|
|
@ -5366,6 +5380,20 @@ lock_release_autoinc_last_lock(
|
|||
lock_table_dequeue(lock);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Check if a transaction holds any autoinc locks.
|
||||
@return TRUE if the transaction holds any AUTOINC locks. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
lock_trx_holds_autoinc_locks(
|
||||
/*=========================*/
|
||||
const trx_t* trx) /*!< in: transaction */
|
||||
{
|
||||
ut_a(trx->autoinc_locks != NULL);
|
||||
|
||||
return(!ib_vector_is_empty(trx->autoinc_locks));
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Release all the transaction's autoinc locks. */
|
||||
UNIV_INTERN
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ log_reserve_and_open(
|
|||
ut_a(len < log->buf_size / 2);
|
||||
loop:
|
||||
mutex_enter(&(log->mutex));
|
||||
ut_ad(!recv_no_log_write);
|
||||
|
||||
/* Calculate an upper limit for the space the string may take in the
|
||||
log buffer */
|
||||
|
|
@ -309,6 +310,7 @@ log_write_low(
|
|||
|
||||
ut_ad(mutex_own(&(log->mutex)));
|
||||
part_loop:
|
||||
ut_ad(!recv_no_log_write);
|
||||
/* Calculate a part length */
|
||||
|
||||
data_len = (log->buf_free % OS_FILE_LOG_BLOCK_SIZE) + str_len;
|
||||
|
|
@ -377,6 +379,7 @@ log_close(void)
|
|||
ib_uint64_t checkpoint_age;
|
||||
|
||||
ut_ad(mutex_own(&(log->mutex)));
|
||||
ut_ad(!recv_no_log_write);
|
||||
|
||||
lsn = log->lsn;
|
||||
|
||||
|
|
@ -668,8 +671,6 @@ log_calc_max_ages(void)
|
|||
ulint archive_margin;
|
||||
ulint smallest_archive_margin;
|
||||
|
||||
ut_ad(!mutex_own(&(log_sys->mutex)));
|
||||
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
|
||||
group = UT_LIST_GET_FIRST(log_sys->log_groups);
|
||||
|
|
@ -1117,6 +1118,7 @@ log_io_complete(
|
|||
}
|
||||
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
ut_ad(!recv_no_log_write);
|
||||
|
||||
ut_a(group->n_pending_writes > 0);
|
||||
ut_a(log_sys->n_pending_writes > 0);
|
||||
|
|
@ -1148,6 +1150,7 @@ log_group_file_header_flush(
|
|||
ulint dest_offset;
|
||||
|
||||
ut_ad(mutex_own(&(log_sys->mutex)));
|
||||
ut_ad(!recv_no_log_write);
|
||||
ut_a(nth_file < group->n_files);
|
||||
|
||||
buf = *(group->file_header_bufs + nth_file);
|
||||
|
|
@ -1219,6 +1222,7 @@ log_group_write_buf(
|
|||
ulint i;
|
||||
|
||||
ut_ad(mutex_own(&(log_sys->mutex)));
|
||||
ut_ad(!recv_no_log_write);
|
||||
ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0);
|
||||
ut_a(((ulint) start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
|
||||
|
||||
|
|
@ -1361,6 +1365,7 @@ loop:
|
|||
#endif
|
||||
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
ut_ad(!recv_no_log_write);
|
||||
|
||||
if (flush_to_disk
|
||||
&& log_sys->flushed_to_disk_lsn >= lsn) {
|
||||
|
|
@ -1974,6 +1979,7 @@ log_checkpoint(
|
|||
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
|
||||
ut_ad(!recv_no_log_write);
|
||||
oldest_lsn = log_buf_pool_get_oldest_modification();
|
||||
|
||||
mutex_exit(&(log_sys->mutex));
|
||||
|
|
@ -2047,7 +2053,7 @@ log_make_checkpoint_at(
|
|||
later lsn, if IB_ULONGLONG_MAX, makes
|
||||
a checkpoint at the latest lsn */
|
||||
ibool write_always) /*!< in: the function normally checks if
|
||||
the the new checkpoint would have a
|
||||
the new checkpoint would have a
|
||||
greater lsn than the previous one: if
|
||||
not, then no physical write is done;
|
||||
by setting this parameter TRUE, a
|
||||
|
|
@ -2086,6 +2092,7 @@ loop:
|
|||
do_checkpoint = FALSE;
|
||||
|
||||
mutex_enter(&(log->mutex));
|
||||
ut_ad(!recv_no_log_write);
|
||||
|
||||
if (log->check_flush_or_checkpoint == FALSE) {
|
||||
mutex_exit(&(log->mutex));
|
||||
|
|
@ -3035,6 +3042,7 @@ loop:
|
|||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
ut_ad(!recv_no_log_write);
|
||||
|
||||
if (log_sys->check_flush_or_checkpoint) {
|
||||
|
||||
|
|
@ -3234,6 +3242,7 @@ loop:
|
|||
ut_a(lsn == log_sys->lsn);
|
||||
}
|
||||
|
||||
#ifdef UNIV_LOG_DEBUG
|
||||
/******************************************************//**
|
||||
Checks by parsing that the catenated log segment for a single mtr is
|
||||
consistent. */
|
||||
|
|
@ -3241,7 +3250,7 @@ UNIV_INTERN
|
|||
ibool
|
||||
log_check_log_recs(
|
||||
/*===============*/
|
||||
byte* buf, /*!< in: pointer to the start of
|
||||
const byte* buf, /*!< in: pointer to the start of
|
||||
the log segment in the
|
||||
log_sys->buf log buffer */
|
||||
ulint len, /*!< in: segment length in bytes */
|
||||
|
|
@ -3249,8 +3258,8 @@ log_check_log_recs(
|
|||
{
|
||||
ib_uint64_t contiguous_lsn;
|
||||
ib_uint64_t scanned_lsn;
|
||||
byte* start;
|
||||
byte* end;
|
||||
const byte* start;
|
||||
const byte* end;
|
||||
byte* buf1;
|
||||
byte* scan_buf;
|
||||
|
||||
|
|
@ -3283,6 +3292,7 @@ log_check_log_recs(
|
|||
|
||||
return(TRUE);
|
||||
}
|
||||
#endif /* UNIV_LOG_DEBUG */
|
||||
|
||||
/******************************************************//**
|
||||
Peeks the current lsn.
|
||||
|
|
|
|||
|
|
@ -78,6 +78,11 @@ UNIV_INTERN ibool recv_recovery_from_backup_on = FALSE;
|
|||
#ifndef UNIV_HOTBACKUP
|
||||
/** TRUE when recv_init_crash_recovery() has been called. */
|
||||
UNIV_INTERN ibool recv_needed_recovery = FALSE;
|
||||
# ifdef UNIV_DEBUG
|
||||
/** TRUE if writing to the redo log (mtr_commit) is forbidden.
|
||||
Protected by log_sys->mutex. */
|
||||
UNIV_INTERN ibool recv_no_log_write = FALSE;
|
||||
# endif /* UNIV_DEBUG */
|
||||
|
||||
/** TRUE if buf_page_is_corrupted() should check if the log sequence
|
||||
number (FIL_PAGE_LSN) is in the future. Initially FALSE, and set by
|
||||
|
|
@ -853,6 +858,11 @@ recv_parse_or_apply_log_rec_body(
|
|||
}
|
||||
|
||||
switch (type) {
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
case MLOG_LSN:
|
||||
/* The LSN is checked in recv_parse_log_rec(). */
|
||||
break;
|
||||
#endif /* UNIV_LOG_LSN_DEBUG */
|
||||
case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES:
|
||||
#ifdef UNIV_DEBUG
|
||||
if (page && page_type == FIL_PAGE_TYPE_ALLOCATED
|
||||
|
|
@ -1269,7 +1279,7 @@ recv_add_to_hash_table(
|
|||
sizeof(recv_data_t) + len);
|
||||
*prev_field = recv_data;
|
||||
|
||||
ut_memcpy(((byte*)recv_data) + sizeof(recv_data_t), body, len);
|
||||
memcpy(recv_data + 1, body, len);
|
||||
|
||||
prev_field = &(recv_data->next);
|
||||
|
||||
|
|
@ -1327,6 +1337,7 @@ recv_recover_page_func(
|
|||
buf_block_t* block) /*!< in/out: buffer block */
|
||||
{
|
||||
page_t* page;
|
||||
page_zip_des_t* page_zip;
|
||||
recv_addr_t* recv_addr;
|
||||
recv_t* recv;
|
||||
byte* buf;
|
||||
|
|
@ -1376,6 +1387,7 @@ recv_recover_page_func(
|
|||
mtr_set_log_mode(&mtr, MTR_LOG_NONE);
|
||||
|
||||
page = block->frame;
|
||||
page_zip = buf_block_get_page_zip(block);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
if (just_read_in) {
|
||||
|
|
@ -1436,13 +1448,19 @@ recv_recover_page_func(
|
|||
if (recv->type == MLOG_INIT_FILE_PAGE) {
|
||||
page_lsn = page_newest_lsn;
|
||||
|
||||
mach_write_ull(page + UNIV_PAGE_SIZE
|
||||
- FIL_PAGE_END_LSN_OLD_CHKSUM, 0);
|
||||
mach_write_ull(page + FIL_PAGE_LSN, 0);
|
||||
memset(FIL_PAGE_LSN + page, 0, 8);
|
||||
memset(UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM
|
||||
+ page, 0, 8);
|
||||
|
||||
if (page_zip) {
|
||||
memset(FIL_PAGE_LSN + page_zip->data, 0, 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (recv->start_lsn >= page_lsn) {
|
||||
|
||||
ib_uint64_t end_lsn;
|
||||
|
||||
if (!modification_to_page) {
|
||||
|
||||
modification_to_page = TRUE;
|
||||
|
|
@ -1464,11 +1482,17 @@ recv_recover_page_func(
|
|||
recv_parse_or_apply_log_rec_body(recv->type, buf,
|
||||
buf + recv->len,
|
||||
block, &mtr);
|
||||
mach_write_ull(page + UNIV_PAGE_SIZE
|
||||
- FIL_PAGE_END_LSN_OLD_CHKSUM,
|
||||
recv->start_lsn + recv->len);
|
||||
mach_write_ull(page + FIL_PAGE_LSN,
|
||||
recv->start_lsn + recv->len);
|
||||
|
||||
end_lsn = recv->start_lsn + recv->len;
|
||||
mach_write_ull(FIL_PAGE_LSN + page, end_lsn);
|
||||
mach_write_ull(UNIV_PAGE_SIZE
|
||||
- FIL_PAGE_END_LSN_OLD_CHKSUM
|
||||
+ page, end_lsn);
|
||||
|
||||
if (page_zip) {
|
||||
mach_write_ull(FIL_PAGE_LSN
|
||||
+ page_zip->data, end_lsn);
|
||||
}
|
||||
}
|
||||
|
||||
if (recv->len > RECV_DATA_BLOCK_SIZE) {
|
||||
|
|
@ -1686,6 +1710,7 @@ loop:
|
|||
/* Flush all the file pages to disk and invalidate them in
|
||||
the buffer pool */
|
||||
|
||||
ut_d(recv_no_log_write = TRUE);
|
||||
mutex_exit(&(recv_sys->mutex));
|
||||
mutex_exit(&(log_sys->mutex));
|
||||
|
||||
|
|
@ -1699,6 +1724,7 @@ loop:
|
|||
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
mutex_enter(&(recv_sys->mutex));
|
||||
ut_d(recv_no_log_write = FALSE);
|
||||
|
||||
recv_no_ibuf_operations = FALSE;
|
||||
}
|
||||
|
|
@ -1910,6 +1936,17 @@ recv_parse_log_rec(
|
|||
return(0);
|
||||
}
|
||||
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
if (*type == MLOG_LSN) {
|
||||
ib_uint64_t lsn = (ib_uint64_t) *space << 32 | *page_no;
|
||||
# ifdef UNIV_LOG_DEBUG
|
||||
ut_a(lsn == log_sys->old_lsn);
|
||||
# else /* UNIV_LOG_DEBUG */
|
||||
ut_a(lsn == recv_sys->recovered_lsn);
|
||||
# endif /* UNIV_LOG_DEBUG */
|
||||
}
|
||||
#endif /* UNIV_LOG_LSN_DEBUG */
|
||||
|
||||
/* Check that page_no is sensible */
|
||||
|
||||
if (UNIV_UNLIKELY(*page_no > 0x8FFFFFFFUL)) {
|
||||
|
|
@ -2167,6 +2204,12 @@ loop:
|
|||
#endif
|
||||
/* In normal mysqld crash recovery we do not try to
|
||||
replay file operations */
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
} else if (type == MLOG_LSN) {
|
||||
/* Do not add these records to the hash table.
|
||||
The page number and space id fields are misused
|
||||
for something else. */
|
||||
#endif /* UNIV_LOG_LSN_DEBUG */
|
||||
} else {
|
||||
recv_add_to_hash_table(type, space, page_no, body,
|
||||
ptr + len, old_lsn,
|
||||
|
|
@ -2198,11 +2241,11 @@ loop:
|
|||
= recv_sys->recovered_offset + total_len;
|
||||
recv_previous_parsed_rec_is_multi = 1;
|
||||
|
||||
if ((!store_to_hash) && (type != MLOG_MULTI_REC_END)) {
|
||||
#ifdef UNIV_LOG_DEBUG
|
||||
if ((!store_to_hash) && (type != MLOG_MULTI_REC_END)) {
|
||||
recv_check_incomplete_log_recs(ptr, len);
|
||||
#endif /* UNIV_LOG_DEBUG */
|
||||
}
|
||||
#endif /* UNIV_LOG_DEBUG */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
|
|
@ -2266,7 +2309,11 @@ loop:
|
|||
break;
|
||||
}
|
||||
|
||||
if (store_to_hash) {
|
||||
if (store_to_hash
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
&& type != MLOG_LSN
|
||||
#endif /* UNIV_LOG_LSN_DEBUG */
|
||||
) {
|
||||
recv_add_to_hash_table(type, space, page_no,
|
||||
body, ptr + len,
|
||||
old_lsn,
|
||||
|
|
@ -2415,8 +2462,7 @@ recv_scan_log_recs(
|
|||
scanned_lsn = start_lsn;
|
||||
more_data = FALSE;
|
||||
|
||||
while (log_block < buf + len && !finished) {
|
||||
|
||||
do {
|
||||
no = log_block_get_hdr_no(log_block);
|
||||
/*
|
||||
fprintf(stderr, "Log block header no %lu\n", no);
|
||||
|
|
@ -2546,10 +2592,11 @@ recv_scan_log_recs(
|
|||
/* Log data for this group ends here */
|
||||
|
||||
finished = TRUE;
|
||||
break;
|
||||
} else {
|
||||
log_block += OS_FILE_LOG_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
} while (log_block < buf + len && !finished);
|
||||
|
||||
*group_scanned_lsn = scanned_lsn;
|
||||
|
||||
|
|
@ -3104,6 +3151,11 @@ recv_recovery_from_checkpoint_finish(void)
|
|||
#ifndef UNIV_LOG_DEBUG
|
||||
recv_sys_free();
|
||||
#endif
|
||||
/* Roll back any recovered data dictionary transactions, so
|
||||
that the data dictionary tables will be free of any locks.
|
||||
The data dictionary latch should guarantee that there is at
|
||||
most one data dictionary transaction active at a time. */
|
||||
trx_rollback_or_clean_recovered(FALSE);
|
||||
|
||||
/* Drop partially created indexes. */
|
||||
row_merge_drop_temp_indexes();
|
||||
|
|
|
|||
|
|
@ -475,16 +475,18 @@ mem_heap_block_free(
|
|||
len = block->len;
|
||||
block->magic_n = MEM_FREED_BLOCK_MAGIC_N;
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
if (!srv_use_sys_malloc) {
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
/* In the debug version we set the memory to a random combination
|
||||
of hex 0xDE and 0xAD. */
|
||||
/* In the debug version we set the memory to a random
|
||||
combination of hex 0xDE and 0xAD. */
|
||||
|
||||
mem_erase_buf((byte*)block, len);
|
||||
mem_erase_buf((byte*)block, len);
|
||||
#else /* UNIV_MEM_DEBUG */
|
||||
UNIV_MEM_ASSERT_AND_FREE(block, len);
|
||||
UNIV_MEM_ASSERT_AND_FREE(block, len);
|
||||
#endif /* UNIV_MEM_DEBUG */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
}
|
||||
if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) {
|
||||
|
||||
ut_ad(!buf_block);
|
||||
|
|
@ -495,6 +497,14 @@ mem_heap_block_free(
|
|||
buf_block_free(buf_block);
|
||||
}
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
/* In the debug version we set the memory to a random
|
||||
combination of hex 0xDE and 0xAD. */
|
||||
|
||||
mem_erase_buf((byte*)block, len);
|
||||
#else /* UNIV_MEM_DEBUG */
|
||||
UNIV_MEM_ASSERT_AND_FREE(block, len);
|
||||
#endif /* UNIV_MEM_DEBUG */
|
||||
ut_free(block);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ Created 11/26/1995 Heikki Tuuri
|
|||
#include "log0log.h"
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "log0recv.h"
|
||||
/*****************************************************************//**
|
||||
Releases the item in the slot given. */
|
||||
UNIV_INLINE
|
||||
|
|
@ -115,7 +116,6 @@ mtr_log_reserve_and_write(
|
|||
dyn_array_t* mlog;
|
||||
dyn_block_t* block;
|
||||
ulint data_size;
|
||||
ibool success;
|
||||
byte* first_data;
|
||||
|
||||
ut_ad(mtr);
|
||||
|
|
@ -134,8 +134,8 @@ mtr_log_reserve_and_write(
|
|||
if (mlog->heap == NULL) {
|
||||
mtr->end_lsn = log_reserve_and_write_fast(
|
||||
first_data, dyn_block_get_used(mlog),
|
||||
&(mtr->start_lsn), &success);
|
||||
if (success) {
|
||||
&mtr->start_lsn);
|
||||
if (mtr->end_lsn) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -182,6 +182,8 @@ mtr_commit(
|
|||
ut_d(mtr->state = MTR_COMMITTING);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/* This is a dirty read, for debugging. */
|
||||
ut_ad(!recv_no_log_write);
|
||||
write_log = mtr->modifications && mtr->n_log_recs;
|
||||
|
||||
if (write_log) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
-- disable_result_log
|
||||
-- enable_warnings
|
||||
|
||||
let $sample_pages=`select @@innodb_stats_sample_pages`;
|
||||
SET GLOBAL innodb_stats_sample_pages=0;
|
||||
|
||||
# check that the value has been adjusted to 1
|
||||
|
|
@ -61,3 +62,4 @@ SET GLOBAL innodb_stats_sample_pages=16;
|
|||
ANALYZE TABLE innodb_analyze;
|
||||
|
||||
DROP TABLE innodb_analyze;
|
||||
EVAL SET GLOBAL innodb_stats_sample_pages=$sample_pages;
|
||||
|
|
|
|||
1
storage/innobase/mysql-test/innodb-consistent-master.opt
Normal file
1
storage/innobase/mysql-test/innodb-consistent-master.opt
Normal file
|
|
@ -0,0 +1 @@
|
|||
--innodb_lock_wait_timeout=2
|
||||
35
storage/innobase/mysql-test/innodb-consistent.result
Normal file
35
storage/innobase/mysql-test/innodb-consistent.result
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
drop table if exists t1;
|
||||
set session transaction isolation level read committed;
|
||||
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
|
||||
create table t2 like t1;
|
||||
insert into t2 values (1),(2),(3),(4),(5),(6),(7);
|
||||
set autocommit=0;
|
||||
begin;
|
||||
replace into t1 select * from t2;
|
||||
set session transaction isolation level read committed;
|
||||
set autocommit=0;
|
||||
delete from t2 where a=5;
|
||||
commit;
|
||||
delete from t2;
|
||||
commit;
|
||||
commit;
|
||||
begin;
|
||||
insert into t1 select * from t2;
|
||||
set session transaction isolation level read committed;
|
||||
set autocommit=0;
|
||||
delete from t2 where a=5;
|
||||
commit;
|
||||
delete from t2;
|
||||
commit;
|
||||
commit;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
58
storage/innobase/mysql-test/innodb-consistent.test
Normal file
58
storage/innobase/mysql-test/innodb-consistent.test
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
-- source include/not_embedded.inc
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
# REPLACE INTO ... SELECT and INSERT INTO ... SELECT should do
|
||||
# a consistent read of the source table.
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
connection a;
|
||||
set session transaction isolation level read committed;
|
||||
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
|
||||
create table t2 like t1;
|
||||
insert into t2 values (1),(2),(3),(4),(5),(6),(7);
|
||||
set autocommit=0;
|
||||
|
||||
# REPLACE INTO ... SELECT case
|
||||
begin;
|
||||
# this should not result in any locks on t2.
|
||||
replace into t1 select * from t2;
|
||||
|
||||
connection b;
|
||||
set session transaction isolation level read committed;
|
||||
set autocommit=0;
|
||||
# should not cuase a lock wait.
|
||||
delete from t2 where a=5;
|
||||
commit;
|
||||
delete from t2;
|
||||
commit;
|
||||
connection a;
|
||||
commit;
|
||||
|
||||
# INSERT INTO ... SELECT case
|
||||
begin;
|
||||
# this should not result in any locks on t2.
|
||||
insert into t1 select * from t2;
|
||||
|
||||
connection b;
|
||||
set session transaction isolation level read committed;
|
||||
set autocommit=0;
|
||||
# should not cuase a lock wait.
|
||||
delete from t2 where a=5;
|
||||
commit;
|
||||
delete from t2;
|
||||
commit;
|
||||
connection a;
|
||||
commit;
|
||||
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
|
@ -141,7 +141,7 @@ drop table t1;
|
|||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(440)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
||||
ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs
|
||||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(439)))
|
||||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(438)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
||||
INSERT INTO t1 VALUES(REPEAT('A',512)),(REPEAT('B',512));
|
||||
DROP TABLE t1;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ drop table t1;
|
|||
--error ER_TOO_BIG_ROWSIZE
|
||||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(440)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
||||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(439)))
|
||||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(438)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
||||
INSERT INTO t1 VALUES(REPEAT('A',512)),(REPEAT('B',512));
|
||||
DROP TABLE t1;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
-- disable_result_log
|
||||
|
||||
# set packet size and reconnect
|
||||
let $max_packet=`select @@global.max_allowed_packet`;
|
||||
SET @@global.max_allowed_packet=16777216;
|
||||
--connect (newconn, localhost, root,,)
|
||||
|
||||
|
|
@ -30,3 +31,4 @@ ALTER TABLE bug34300 ADD COLUMN (f10 INT);
|
|||
SELECT f4, f8 FROM bug34300;
|
||||
|
||||
DROP TABLE bug34300;
|
||||
EVAL SET @@global.max_allowed_packet=$max_packet;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
let $file_format=`select @@innodb_file_format`;
|
||||
let $file_per_table=`select @@innodb_file_per_table`;
|
||||
SET GLOBAL innodb_file_format='Barracuda';
|
||||
SET GLOBAL innodb_file_per_table=ON;
|
||||
|
||||
|
|
@ -1153,3 +1155,5 @@ DROP TABLE IF EXISTS table4;
|
|||
DROP TABLE IF EXISTS table5;
|
||||
DROP TABLE IF EXISTS table6;
|
||||
|
||||
EVAL SET GLOBAL innodb_file_format=$file_format;
|
||||
EVAL SET GLOBAL innodb_file_per_table=$file_per_table;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ SET storage_engine=InnoDB;
|
|||
-- disable_query_log
|
||||
-- disable_result_log
|
||||
|
||||
let $file_format=`select @@innodb_file_format`;
|
||||
let $file_format_check=`select @@innodb_file_format_check`;
|
||||
let $file_per_table=`select @@innodb_file_per_table`;
|
||||
SET GLOBAL innodb_file_format='Barracuda';
|
||||
SET GLOBAL innodb_file_per_table=on;
|
||||
|
||||
|
|
@ -24,3 +27,6 @@ CHECK TABLE table0 EXTENDED;
|
|||
INSERT IGNORE INTO `table0` SET `col19` = '19940127002709', `col20` = 2383927.9055146948, `col21` = 4293243420.5621204000, `col22` = '20511211123705', `col23` = 4289899778.6573381000, `col24` = 4293449279.0540481000, `col25` = 'emphysemic', `col26` = 'dentally', `col27` = '2347406', `col28` = 'eruct', `col30` = 1222, `col31` = 4294372994.9941406000, `col32` = 4291385574.1173744000, `col33` = 'borrowing\'s', `col34` = 'septics', `col35` = 'ratter\'s', `col36` = 'Kaye', `col37` = 'Florentia', `col38` = 'allium', `col39` = 'barkeep', `col40` = '19510407003441', `col41` = 4293559200.4215522000, `col42` = 22482, `col43` = 'decussate', `col44` = 'Brom\'s', `col45` = 'violated', `col46` = 4925506.4635456400, `col47` = 930549, `col48` = '51296066', `col49` = 'voluminously', `col50` = '29306676', `col51` = -88, `col52` = -2153690, `col53` = 4290250202.1464887000, `col54` = 'expropriation', `col55` = 'Aberdeen\'s', `col56` = 20343, `col58` = '19640415171532', `col59` = 'extern', `col60` = 'Ubana', `col61` = 4290487961.8539081000, `col62` = '2147', `col63` = -24271, `col64` = '20750801194548', `col65` = 'Cunaxa\'s', `col66` = 'pasticcio', `col67` = 2795817, `col68` = 'Indore\'s', `col70` = 6864127, `col71` = '1817832', `col72` = '20540506114211', `col73` = '20040101012300', `col74` = 'rationalized', `col75` = '45522', `col76` = 'indene', `col77` = -6964559, `col78` = 4247535.5266884370, `col79` = '20720416124357', `col80` = '2143', `col81` = 4292060102.4466386000, `col82` = 'striving', `col83` = 'boneblack\'s', `col84` = 'redolent', `col85` = 6489697.9009369183, `col86` = 4287473465.9731131000, `col87` = 7726015, `col88` = 'perplexed', `col89` = '17153791', `col90` = 5478587.1108127078, `col91` = 4287091404.7004304000, `col92` = 'Boulez\'s', `col93` = '2931278';
|
||||
CHECK TABLE table0 EXTENDED;
|
||||
DROP TABLE table0;
|
||||
EVAL SET GLOBAL innodb_file_format=$file_format;
|
||||
EVAL SET GLOBAL innodb_file_format_check=$file_format_check;
|
||||
EVAL SET GLOBAL innodb_file_per_table=$file_per_table;
|
||||
|
|
|
|||
14
storage/innobase/mysql-test/innodb_bug44369.result
Normal file
14
storage/innobase/mysql-test/innodb_bug44369.result
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
create table bug44369 (DB_ROW_ID int) engine=innodb;
|
||||
ERROR HY000: Can't create table 'test.bug44369' (errno: -1)
|
||||
create table bug44369 (db_row_id int) engine=innodb;
|
||||
ERROR HY000: Can't create table 'test.bug44369' (errno: -1)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1005 Error creating table 'test/bug44369' with column name 'db_row_id'. 'db_row_id' is a reserved name. Please try to re-create the table with a different column name.
|
||||
Error 1005 Can't create table 'test.bug44369' (errno: -1)
|
||||
create table bug44369 (db_TRX_Id int) engine=innodb;
|
||||
ERROR HY000: Can't create table 'test.bug44369' (errno: -1)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1005 Error creating table 'test/bug44369' with column name 'db_TRX_Id'. 'db_TRX_Id' is a reserved name. Please try to re-create the table with a different column name.
|
||||
Error 1005 Can't create table 'test.bug44369' (errno: -1)
|
||||
21
storage/innobase/mysql-test/innodb_bug44369.test
Normal file
21
storage/innobase/mysql-test/innodb_bug44369.test
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# This is the test for bug 44369. We should
|
||||
# block table creation with columns match
|
||||
# some innodb internal reserved key words,
|
||||
# both case sensitively and insensitely.
|
||||
|
||||
--source include/have_innodb.inc
|
||||
|
||||
# This create table operation should fail.
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table bug44369 (DB_ROW_ID int) engine=innodb;
|
||||
|
||||
# This create should fail as well
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table bug44369 (db_row_id int) engine=innodb;
|
||||
|
||||
show errors;
|
||||
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table bug44369 (db_TRX_Id int) engine=innodb;
|
||||
|
||||
show errors;
|
||||
9
storage/innobase/mysql-test/innodb_bug44571.result
Normal file
9
storage/innobase/mysql-test/innodb_bug44571.result
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
CREATE TABLE bug44571 (foo INT) ENGINE=InnoDB;
|
||||
ALTER TABLE bug44571 CHANGE foo bar INT;
|
||||
ALTER TABLE bug44571 ADD INDEX bug44571b (foo);
|
||||
ERROR 42000: Key column 'foo' doesn't exist in table
|
||||
ALTER TABLE bug44571 ADD INDEX bug44571b (bar);
|
||||
ERROR HY000: Incorrect key file for table 'bug44571'; try to repair it
|
||||
CREATE INDEX bug44571b ON bug44571 (bar);
|
||||
ERROR HY000: Incorrect key file for table 'bug44571'; try to repair it
|
||||
DROP TABLE bug44571;
|
||||
17
storage/innobase/mysql-test/innodb_bug44571.test
Normal file
17
storage/innobase/mysql-test/innodb_bug44571.test
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#
|
||||
# Bug#44571 InnoDB Plugin crashes on ADD INDEX
|
||||
# http://bugs.mysql.com/44571
|
||||
#
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
CREATE TABLE bug44571 (foo INT) ENGINE=InnoDB;
|
||||
ALTER TABLE bug44571 CHANGE foo bar INT;
|
||||
-- error ER_KEY_COLUMN_DOES_NOT_EXITS
|
||||
ALTER TABLE bug44571 ADD INDEX bug44571b (foo);
|
||||
# The following will fail, because the CHANGE foo bar was
|
||||
# not communicated to InnoDB.
|
||||
--error ER_NOT_KEYFILE
|
||||
ALTER TABLE bug44571 ADD INDEX bug44571b (bar);
|
||||
--error ER_NOT_KEYFILE
|
||||
CREATE INDEX bug44571b ON bug44571 (bar);
|
||||
DROP TABLE bug44571;
|
||||
17
storage/innobase/mysql-test/innodb_bug46000.result
Normal file
17
storage/innobase/mysql-test/innodb_bug46000.result
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb;
|
||||
ERROR HY000: Can't create table 'test.bug46000' (errno: -1)
|
||||
create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb;
|
||||
ERROR HY000: Can't create table 'test.bug46000' (errno: -1)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index.
|
||||
Error 1005 Can't create table 'test.bug46000' (errno: -1)
|
||||
create table bug46000(id int) engine=innodb;
|
||||
create index GEN_CLUST_INDEX on bug46000(id);
|
||||
ERROR HY000: Can't create table '#sql-temporary' (errno: -1)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index.
|
||||
Error 1005 Can't create table '#sql-temporary' (errno: -1)
|
||||
create index idx on bug46000(id);
|
||||
drop table bug46000;
|
||||
34
storage/innobase/mysql-test/innodb_bug46000.test
Normal file
34
storage/innobase/mysql-test/innodb_bug46000.test
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# This is the test for bug 46000. We shall
|
||||
# block any index creation with the name of
|
||||
# "GEN_CLUST_INDEX", which is the reserved
|
||||
# name for innodb default primary index.
|
||||
|
||||
--source include/have_innodb.inc
|
||||
|
||||
# This 'create table' operation should fail because of
|
||||
# using the reserve name as its index name.
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb;
|
||||
|
||||
# Mixed upper/lower case of the reserved key words
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb;
|
||||
|
||||
show errors;
|
||||
|
||||
create table bug46000(id int) engine=innodb;
|
||||
|
||||
# This 'create index' operation should fail.
|
||||
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create index GEN_CLUST_INDEX on bug46000(id);
|
||||
|
||||
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
|
||||
show errors;
|
||||
|
||||
# This 'create index' operation should succeed, no
|
||||
# temp table left from last failed create index
|
||||
# operation.
|
||||
create index idx on bug46000(id);
|
||||
|
||||
drop table bug46000;
|
||||
|
|
@ -42,3 +42,4 @@ ERROR HY000: Incorrect arguments to SET
|
|||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Barracuda
|
||||
set global innodb_file_format_check=antelope;
|
||||
|
|
|
|||
|
|
@ -26,3 +26,4 @@ set global innodb_file_format=on;
|
|||
--error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format=off;
|
||||
select @@innodb_file_format_check;
|
||||
set global innodb_file_format_check=antelope;
|
||||
|
|
|
|||
|
|
@ -88,7 +88,9 @@ UNIV_INTERN ibool os_do_not_call_flush_at_each_write = FALSE;
|
|||
/* We do not call os_file_flush in every os_file_write. */
|
||||
#endif /* UNIV_DO_FLUSH */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#ifdef UNIV_HOTBACKUP
|
||||
# define os_aio_use_native_aio FALSE
|
||||
#else /* UNIV_HOTBACKUP */
|
||||
/* We use these mutexes to protect lseek + file i/o operation, if the
|
||||
OS does not provide an atomic pread or pwrite, or similar */
|
||||
#define OS_FILE_N_SEEK_MUTEXES 16
|
||||
|
|
@ -198,7 +200,7 @@ static ulint os_aio_n_segments = ULINT_UNDEFINED;
|
|||
/** If the following is TRUE, read i/o handler threads try to
|
||||
wait until a batch of new read requests have been posted */
|
||||
static ibool os_aio_recommend_sleep_for_read_threads = FALSE;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
|
||||
UNIV_INTERN ulint os_n_file_reads = 0;
|
||||
UNIV_INTERN ulint os_bytes_read_since_printout = 0;
|
||||
|
|
@ -315,6 +317,12 @@ os_file_get_last_error(
|
|||
" software or another instance\n"
|
||||
"InnoDB: of MySQL."
|
||||
" Please close it to get rid of this error.\n");
|
||||
} else if (err == ERROR_WORKING_SET_QUOTA
|
||||
|| err == ERROR_NO_SYSTEM_RESOURCES) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: The error means that there are no"
|
||||
" sufficient system resources or quota to"
|
||||
" complete the operation.\n");
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Some operating system error numbers"
|
||||
|
|
@ -336,6 +344,9 @@ os_file_get_last_error(
|
|||
} else if (err == ERROR_SHARING_VIOLATION
|
||||
|| err == ERROR_LOCK_VIOLATION) {
|
||||
return(OS_FILE_SHARING_VIOLATION);
|
||||
} else if (err == ERROR_WORKING_SET_QUOTA
|
||||
|| err == ERROR_NO_SYSTEM_RESOURCES) {
|
||||
return(OS_FILE_INSUFFICIENT_RESOURCE);
|
||||
} else {
|
||||
return(100 + err);
|
||||
}
|
||||
|
|
@ -454,6 +465,10 @@ os_file_handle_error_cond_exit(
|
|||
|
||||
os_thread_sleep(10000000); /* 10 sec */
|
||||
return(TRUE);
|
||||
} else if (err == OS_FILE_INSUFFICIENT_RESOURCE) {
|
||||
|
||||
os_thread_sleep(100000); /* 100 ms */
|
||||
return(TRUE);
|
||||
} else {
|
||||
if (name) {
|
||||
fprintf(stderr, "InnoDB: File name %s\n", name);
|
||||
|
|
@ -1245,6 +1260,7 @@ try_again:
|
|||
}
|
||||
#endif
|
||||
#ifdef UNIV_NON_BUFFERED_IO
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
|
||||
/* Do not use unbuffered i/o to log files because
|
||||
value 2 denotes that we do not flush the log at every
|
||||
|
|
@ -1253,10 +1269,14 @@ try_again:
|
|||
== SRV_WIN_IO_UNBUFFERED) {
|
||||
attributes = attributes | FILE_FLAG_NO_BUFFERING;
|
||||
}
|
||||
#endif
|
||||
# else /* !UNIV_HOTBACKUP */
|
||||
attributes = attributes | FILE_FLAG_NO_BUFFERING;
|
||||
# endif /* !UNIV_HOTBACKUP */
|
||||
#endif /* UNIV_NON_BUFFERED_IO */
|
||||
} else if (purpose == OS_FILE_NORMAL) {
|
||||
attributes = 0;
|
||||
#ifdef UNIV_NON_BUFFERED_IO
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
|
||||
/* Do not use unbuffered i/o to log files because
|
||||
value 2 denotes that we do not flush the log at every
|
||||
|
|
@ -1265,7 +1285,10 @@ try_again:
|
|||
== SRV_WIN_IO_UNBUFFERED) {
|
||||
attributes = attributes | FILE_FLAG_NO_BUFFERING;
|
||||
}
|
||||
#endif
|
||||
# else /* !UNIV_HOTBACKUP */
|
||||
attributes = attributes | FILE_FLAG_NO_BUFFERING;
|
||||
# endif /* !UNIV_HOTBACKUP */
|
||||
#endif /* UNIV_NON_BUFFERED_IO */
|
||||
} else {
|
||||
attributes = 0;
|
||||
ut_error;
|
||||
|
|
@ -2022,7 +2045,9 @@ os_file_pread(
|
|||
offset */
|
||||
{
|
||||
off_t offs;
|
||||
#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
|
||||
ssize_t n_bytes;
|
||||
#endif /* HAVE_PREAD && !HAVE_BROKEN_PREAD */
|
||||
|
||||
ut_a((offset & 0xFFFFFFFFUL) == offset);
|
||||
|
||||
|
|
@ -2061,16 +2086,20 @@ os_file_pread(
|
|||
{
|
||||
off_t ret_offset;
|
||||
ssize_t ret;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ulint i;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
os_mutex_enter(os_file_count_mutex);
|
||||
os_n_pending_reads++;
|
||||
os_mutex_exit(os_file_count_mutex);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/* Protect the seek / read operation with a mutex */
|
||||
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
|
||||
|
||||
os_mutex_enter(os_file_seek_mutexes[i]);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ret_offset = lseek(file, offs, SEEK_SET);
|
||||
|
||||
|
|
@ -2080,7 +2109,9 @@ os_file_pread(
|
|||
ret = read(file, buf, (ssize_t)n);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
os_mutex_enter(os_file_count_mutex);
|
||||
os_n_pending_reads--;
|
||||
|
|
@ -2158,16 +2189,20 @@ os_file_pwrite(
|
|||
#else
|
||||
{
|
||||
off_t ret_offset;
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
ulint i;
|
||||
# endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
os_mutex_enter(os_file_count_mutex);
|
||||
os_n_pending_writes++;
|
||||
os_mutex_exit(os_file_count_mutex);
|
||||
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
/* Protect the seek / write operation with a mutex */
|
||||
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
|
||||
|
||||
os_mutex_enter(os_file_seek_mutexes[i]);
|
||||
# endif /* UNIV_HOTBACKUP */
|
||||
|
||||
ret_offset = lseek(file, offs, SEEK_SET);
|
||||
|
||||
|
|
@ -2193,7 +2228,9 @@ os_file_pwrite(
|
|||
# endif /* UNIV_DO_FLUSH */
|
||||
|
||||
func_exit:
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
||||
# endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
os_mutex_enter(os_file_count_mutex);
|
||||
os_n_pending_writes--;
|
||||
|
|
@ -2227,7 +2264,9 @@ os_file_read(
|
|||
DWORD low;
|
||||
DWORD high;
|
||||
ibool retry;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ulint i;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ut_a((offset & 0xFFFFFFFFUL) == offset);
|
||||
|
||||
|
|
@ -2246,16 +2285,20 @@ try_again:
|
|||
os_n_pending_reads++;
|
||||
os_mutex_exit(os_file_count_mutex);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/* Protect the seek / read operation with a mutex */
|
||||
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
|
||||
|
||||
os_mutex_enter(os_file_seek_mutexes[i]);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
|
||||
|
||||
if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
os_mutex_enter(os_file_count_mutex);
|
||||
os_n_pending_reads--;
|
||||
|
|
@ -2266,7 +2309,9 @@ try_again:
|
|||
|
||||
ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
os_mutex_enter(os_file_count_mutex);
|
||||
os_n_pending_reads--;
|
||||
|
|
@ -2275,7 +2320,7 @@ try_again:
|
|||
if (ret && len == n) {
|
||||
return(TRUE);
|
||||
}
|
||||
#else
|
||||
#else /* __WIN__ */
|
||||
ibool retry;
|
||||
ssize_t ret;
|
||||
|
||||
|
|
@ -2294,7 +2339,7 @@ try_again:
|
|||
"InnoDB: Was only able to read %ld.\n",
|
||||
(ulong)n, (ulong)offset_high,
|
||||
(ulong)offset, (long)ret);
|
||||
#endif
|
||||
#endif /* __WIN__ */
|
||||
#ifdef __WIN__
|
||||
error_handling:
|
||||
#endif
|
||||
|
|
@ -2343,7 +2388,9 @@ os_file_read_no_error_handling(
|
|||
DWORD low;
|
||||
DWORD high;
|
||||
ibool retry;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ulint i;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ut_a((offset & 0xFFFFFFFFUL) == offset);
|
||||
|
||||
|
|
@ -2362,16 +2409,20 @@ try_again:
|
|||
os_n_pending_reads++;
|
||||
os_mutex_exit(os_file_count_mutex);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/* Protect the seek / read operation with a mutex */
|
||||
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
|
||||
|
||||
os_mutex_enter(os_file_seek_mutexes[i]);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
|
||||
|
||||
if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
os_mutex_enter(os_file_count_mutex);
|
||||
os_n_pending_reads--;
|
||||
|
|
@ -2382,7 +2433,9 @@ try_again:
|
|||
|
||||
ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
os_mutex_enter(os_file_count_mutex);
|
||||
os_n_pending_reads--;
|
||||
|
|
@ -2391,7 +2444,7 @@ try_again:
|
|||
if (ret && len == n) {
|
||||
return(TRUE);
|
||||
}
|
||||
#else
|
||||
#else /* __WIN__ */
|
||||
ibool retry;
|
||||
ssize_t ret;
|
||||
|
||||
|
|
@ -2404,7 +2457,7 @@ try_again:
|
|||
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
#endif /* __WIN__ */
|
||||
#ifdef __WIN__
|
||||
error_handling:
|
||||
#endif
|
||||
|
|
@ -2463,9 +2516,11 @@ os_file_write(
|
|||
DWORD ret2;
|
||||
DWORD low;
|
||||
DWORD high;
|
||||
ulint i;
|
||||
ulint n_retries = 0;
|
||||
ulint err;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ulint i;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ut_a((offset & 0xFFFFFFFF) == offset);
|
||||
|
||||
|
|
@ -2482,16 +2537,20 @@ retry:
|
|||
os_n_pending_writes++;
|
||||
os_mutex_exit(os_file_count_mutex);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/* Protect the seek / write operation with a mutex */
|
||||
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
|
||||
|
||||
os_mutex_enter(os_file_seek_mutexes[i]);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
|
||||
|
||||
if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
os_mutex_enter(os_file_count_mutex);
|
||||
os_n_pending_writes--;
|
||||
|
|
@ -2525,7 +2584,9 @@ retry:
|
|||
}
|
||||
# endif /* UNIV_DO_FLUSH */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
os_mutex_enter(os_file_count_mutex);
|
||||
os_n_pending_writes--;
|
||||
|
|
@ -3371,9 +3432,21 @@ void
|
|||
os_aio_simulated_put_read_threads_to_sleep(void)
|
||||
/*============================================*/
|
||||
{
|
||||
|
||||
/* The idea of putting background IO threads to sleep is only for
|
||||
Windows when using simulated AIO. Windows XP seems to schedule
|
||||
background threads too eagerly to allow for coalescing during
|
||||
readahead requests. */
|
||||
#ifdef __WIN__
|
||||
os_aio_array_t* array;
|
||||
ulint g;
|
||||
|
||||
if (os_aio_use_native_aio) {
|
||||
/* We do not use simulated aio: do nothing */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
os_aio_recommend_sleep_for_read_threads = TRUE;
|
||||
|
||||
for (g = 0; g < os_aio_n_segments; g++) {
|
||||
|
|
@ -3384,6 +3457,7 @@ os_aio_simulated_put_read_threads_to_sleep(void)
|
|||
os_event_reset(os_aio_segment_wait_events[g]);
|
||||
}
|
||||
}
|
||||
#endif /* __WIN__ */
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
|
|
|
|||
|
|
@ -1195,7 +1195,7 @@ page_cur_insert_rec_zip_reorg(
|
|||
}
|
||||
|
||||
/* Out of space: restore the page */
|
||||
if (!page_zip_decompress(page_zip, page)) {
|
||||
if (!page_zip_decompress(page_zip, page, FALSE)) {
|
||||
ut_error; /* Memory corrupted? */
|
||||
}
|
||||
ut_ad(page_validate(page, index));
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ Created 2/2/1994 Heikki Tuuri
|
|||
==============
|
||||
|
||||
The index page consists of a page header which contains the page's
|
||||
id and other information. On top of it are the the index records
|
||||
id and other information. On top of it are the index records
|
||||
in a heap linked into a one way linear list according to alphabetic order.
|
||||
|
||||
Just below page end is an array of pointers which we call page directory,
|
||||
|
|
@ -679,7 +679,7 @@ page_copy_rec_list_end(
|
|||
|
||||
if (UNIV_UNLIKELY
|
||||
(!page_zip_decompress(new_page_zip,
|
||||
new_page))) {
|
||||
new_page, FALSE))) {
|
||||
ut_error;
|
||||
}
|
||||
ut_ad(page_validate(new_page, index));
|
||||
|
|
@ -792,7 +792,7 @@ page_copy_rec_list_start(
|
|||
|
||||
if (UNIV_UNLIKELY
|
||||
(!page_zip_decompress(new_page_zip,
|
||||
new_page))) {
|
||||
new_page, FALSE))) {
|
||||
ut_error;
|
||||
}
|
||||
ut_ad(page_validate(new_page, index));
|
||||
|
|
|
|||
|
|
@ -47,8 +47,10 @@ Created June 2005 by Marko Makela
|
|||
# define buf_LRU_stat_inc_unzip() ((void) 0)
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */
|
||||
UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1];
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/* Please refer to ../include/page0zip.ic for a description of the
|
||||
compressed page format. */
|
||||
|
|
@ -1144,7 +1146,9 @@ page_zip_compress(
|
|||
ulint* offsets = NULL;
|
||||
ulint n_blobs = 0;
|
||||
byte* storage;/* storage of uncompressed columns */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ullint usec = ut_time_us(NULL);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
#ifdef PAGE_ZIP_COMPRESS_DBG
|
||||
FILE* logfile = NULL;
|
||||
#endif
|
||||
|
|
@ -1208,7 +1212,9 @@ page_zip_compress(
|
|||
}
|
||||
}
|
||||
#endif /* PAGE_ZIP_COMPRESS_DBG */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
page_zip_stat[page_zip->ssize - 1].compressed++;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
if (UNIV_UNLIKELY(n_dense * PAGE_ZIP_DIR_SLOT_SIZE
|
||||
>= page_zip_get_size(page_zip))) {
|
||||
|
|
@ -1345,8 +1351,10 @@ err_exit:
|
|||
fclose(logfile);
|
||||
}
|
||||
#endif /* PAGE_ZIP_COMPRESS_DBG */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
page_zip_stat[page_zip->ssize - 1].compressed_usec
|
||||
+= ut_time_us(NULL) - usec;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
|
@ -1404,12 +1412,14 @@ err_exit:
|
|||
fclose(logfile);
|
||||
}
|
||||
#endif /* PAGE_ZIP_COMPRESS_DBG */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
{
|
||||
page_zip_stat_t* zip_stat
|
||||
= &page_zip_stat[page_zip->ssize - 1];
|
||||
zip_stat->compressed_ok++;
|
||||
zip_stat->compressed_usec += ut_time_us(NULL) - usec;
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
|
@ -2811,7 +2821,11 @@ page_zip_decompress(
|
|||
/*================*/
|
||||
page_zip_des_t* page_zip,/*!< in: data, ssize;
|
||||
out: m_start, m_end, m_nonempty, n_blobs */
|
||||
page_t* page) /*!< out: uncompressed page, may be trashed */
|
||||
page_t* page, /*!< out: uncompressed page, may be trashed */
|
||||
ibool all) /*!< in: TRUE=decompress the whole page;
|
||||
FALSE=verify but do not copy some
|
||||
page header fields that should not change
|
||||
after page creation */
|
||||
{
|
||||
z_stream d_stream;
|
||||
dict_index_t* index = NULL;
|
||||
|
|
@ -2820,7 +2834,9 @@ page_zip_decompress(
|
|||
ulint trx_id_col = ULINT_UNDEFINED;
|
||||
mem_heap_t* heap;
|
||||
ulint* offsets;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ullint usec = ut_time_us(NULL);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ut_ad(page_zip_simple_validate(page_zip));
|
||||
UNIV_MEM_ASSERT_W(page, UNIV_PAGE_SIZE);
|
||||
|
|
@ -2839,13 +2855,36 @@ page_zip_decompress(
|
|||
heap = mem_heap_create(n_dense * (3 * sizeof *recs) + UNIV_PAGE_SIZE);
|
||||
recs = mem_heap_alloc(heap, n_dense * (2 * sizeof *recs));
|
||||
|
||||
if (all) {
|
||||
/* Copy the page header. */
|
||||
memcpy(page, page_zip->data, PAGE_DATA);
|
||||
} else {
|
||||
/* Check that the bytes that we skip are identical. */
|
||||
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
|
||||
ut_a(!memcmp(FIL_PAGE_TYPE + page,
|
||||
FIL_PAGE_TYPE + page_zip->data,
|
||||
PAGE_HEADER - FIL_PAGE_TYPE));
|
||||
ut_a(!memcmp(PAGE_HEADER + PAGE_LEVEL + page,
|
||||
PAGE_HEADER + PAGE_LEVEL + page_zip->data,
|
||||
PAGE_DATA - (PAGE_HEADER + PAGE_LEVEL)));
|
||||
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
|
||||
|
||||
/* Copy the mutable parts of the page header. */
|
||||
memcpy(page, page_zip->data, FIL_PAGE_TYPE);
|
||||
memcpy(PAGE_HEADER + page, PAGE_HEADER + page_zip->data,
|
||||
PAGE_LEVEL - PAGE_N_DIR_SLOTS);
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
|
||||
/* Check that the page headers match after copying. */
|
||||
ut_a(!memcmp(page, page_zip->data, PAGE_DATA));
|
||||
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
|
||||
}
|
||||
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
/* Clear the page. */
|
||||
memset(page, 0x55, UNIV_PAGE_SIZE);
|
||||
/* Clear the uncompressed page, except the header. */
|
||||
memset(PAGE_DATA + page, 0x55, UNIV_PAGE_SIZE - PAGE_DATA);
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
UNIV_MEM_INVALID(page, UNIV_PAGE_SIZE);
|
||||
/* Copy the page header. */
|
||||
memcpy(page, page_zip->data, PAGE_DATA);
|
||||
UNIV_MEM_INVALID(PAGE_DATA + page, UNIV_PAGE_SIZE - PAGE_DATA);
|
||||
|
||||
/* Copy the page directory. */
|
||||
if (UNIV_UNLIKELY(!page_zip_dir_decode(page_zip, page, recs,
|
||||
|
|
@ -2976,12 +3015,14 @@ err_exit:
|
|||
|
||||
page_zip_fields_free(index);
|
||||
mem_heap_free(heap);
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
{
|
||||
page_zip_stat_t* zip_stat
|
||||
= &page_zip_stat[page_zip->ssize - 1];
|
||||
zip_stat->decompressed++;
|
||||
zip_stat->decompressed_usec += ut_time_us(NULL) - usec;
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/* Update the stat counter for LRU policy. */
|
||||
buf_LRU_stat_inc_unzip();
|
||||
|
|
@ -3084,7 +3125,7 @@ page_zip_validate_low(
|
|||
#endif /* UNIV_DEBUG_VALGRIND */
|
||||
|
||||
temp_page_zip = *page_zip;
|
||||
valid = page_zip_decompress(&temp_page_zip, temp_page);
|
||||
valid = page_zip_decompress(&temp_page_zip, temp_page, TRUE);
|
||||
if (!valid) {
|
||||
fputs("page_zip_validate(): failed to decompress\n", stderr);
|
||||
goto func_exit;
|
||||
|
|
@ -4362,8 +4403,8 @@ IMPORTANT: if page_zip_reorganize() is invoked on a leaf page of a
|
|||
non-clustered index, the caller must update the insert buffer free
|
||||
bits in the same mini-transaction in such a way that the modification
|
||||
will be redo-logged.
|
||||
@return TRUE on success, FALSE on failure; page and page_zip will be
|
||||
left intact on failure. */
|
||||
@return TRUE on success, FALSE on failure; page_zip will be left
|
||||
intact on failure, but page will be overwritten. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
page_zip_reorganize(
|
||||
|
|
@ -4428,9 +4469,6 @@ page_zip_reorganize(
|
|||
|
||||
if (UNIV_UNLIKELY(!page_zip_compress(page_zip, page, index, mtr))) {
|
||||
|
||||
/* Restore the old page and exit. */
|
||||
buf_frame_copy(page, temp_page);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
buf_block_free(temp_block);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
|
@ -4591,7 +4629,8 @@ corrupt:
|
|||
memcpy(page_zip->data + page_zip_get_size(page_zip)
|
||||
- trailer_size, ptr + 8 + size, trailer_size);
|
||||
|
||||
if (UNIV_UNLIKELY(!page_zip_decompress(page_zip, page))) {
|
||||
if (UNIV_UNLIKELY(!page_zip_decompress(page_zip, page,
|
||||
TRUE))) {
|
||||
|
||||
goto corrupt;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
# Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine],
|
||||
MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine],
|
||||
[Transactional Tables using InnoDB], [max,max-no-ndb])
|
||||
MYSQL_PLUGIN_DIRECTORY(innobase, [storage/innobase])
|
||||
MYSQL_PLUGIN_STATIC(innobase, [libinnobase.a])
|
||||
|
|
@ -38,33 +38,75 @@ MYSQL_PLUGIN_ACTIONS(innobase, [
|
|||
irix*|osf*|sysv5uw7*|openbsd*)
|
||||
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
|
||||
*solaris*|*SunOS*)
|
||||
# Begin Solaris atomic function checks
|
||||
AC_CHECK_FUNCS(atomic_cas_ulong atomic_cas_32 \
|
||||
atomic_cas_64 atomic_add_long,
|
||||
AC_DEFINE(
|
||||
[HAVE_SOLARIS_ATOMICS],
|
||||
[1],
|
||||
[Define to 1 if Solaris supports \
|
||||
atomic functions.]))
|
||||
### End Solaris atomic function checks
|
||||
|
||||
CFLAGS="$CFLAGS -DUNIV_SOLARIS";;
|
||||
esac
|
||||
|
||||
INNODB_DYNAMIC_CFLAGS="-DMYSQL_DYNAMIC_PLUGIN"
|
||||
case "$target_cpu---$target_os" in
|
||||
x86_64---*)
|
||||
|
||||
case "$target_cpu" in
|
||||
x86_64)
|
||||
# The AMD64 ABI forbids absolute addresses in shared libraries
|
||||
;;
|
||||
*---solaris*|*---SunOS*)
|
||||
# Shared objects must be linked from PIC code on Solaris.
|
||||
;;
|
||||
*86---)
|
||||
*86)
|
||||
# Use absolute addresses on IA-32
|
||||
INNODB_DYNAMIC_CFLAGS="$INNODB_DYNAMIC_CFLAGS -prefer-non-pic"
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(INNODB_DYNAMIC_CFLAGS)
|
||||
|
||||
AC_MSG_CHECKING(whether GCC atomic builtins are available)
|
||||
# either define HAVE_IB_GCC_ATOMIC_BUILTINS or not
|
||||
AC_TRY_RUN(
|
||||
[
|
||||
int main()
|
||||
{
|
||||
long x;
|
||||
long y;
|
||||
long res;
|
||||
char c;
|
||||
|
||||
x = 10;
|
||||
y = 123;
|
||||
res = __sync_bool_compare_and_swap(&x, x, y);
|
||||
if (!res || x != y) {
|
||||
return(1);
|
||||
}
|
||||
|
||||
x = 10;
|
||||
y = 123;
|
||||
res = __sync_bool_compare_and_swap(&x, x + 1, y);
|
||||
if (res || x != 10) {
|
||||
return(1);
|
||||
}
|
||||
|
||||
x = 10;
|
||||
y = 123;
|
||||
res = __sync_add_and_fetch(&x, y);
|
||||
if (res != 123 + 10 || x != 123 + 10) {
|
||||
return(1);
|
||||
}
|
||||
|
||||
c = 10;
|
||||
res = __sync_lock_test_and_set(&c, 123);
|
||||
if (res != 10 || c != 123) {
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
],
|
||||
[
|
||||
AC_DEFINE([HAVE_IB_GCC_ATOMIC_BUILTINS], [1],
|
||||
[GCC atomic builtins are available])
|
||||
AC_MSG_RESULT(yes)
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT(no)
|
||||
]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING(whether pthread_t can be used by GCC atomic builtins)
|
||||
# either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not
|
||||
AC_TRY_RUN(
|
||||
[
|
||||
#include <pthread.h>
|
||||
|
|
@ -85,47 +127,73 @@ MYSQL_PLUGIN_ACTIONS(innobase, [
|
|||
}
|
||||
],
|
||||
[
|
||||
AC_DEFINE([HAVE_ATOMIC_PTHREAD_T], [1],
|
||||
AC_DEFINE([HAVE_IB_ATOMIC_PTHREAD_T_GCC], [1],
|
||||
[pthread_t can be used by GCC atomic builtins])
|
||||
AC_MSG_RESULT(yes)
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT(no)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
# Try using solaris atomics on SunOS if GCC atomics are not available
|
||||
AC_CHECK_DECLS(
|
||||
[HAVE_ATOMIC_PTHREAD_T],
|
||||
AC_MSG_CHECKING(whether Solaris libc atomic functions are available)
|
||||
# either define HAVE_IB_SOLARIS_ATOMICS or not
|
||||
AC_CHECK_FUNCS(atomic_add_long \
|
||||
atomic_cas_32 \
|
||||
atomic_cas_64 \
|
||||
atomic_cas_ulong,
|
||||
|
||||
AC_DEFINE([HAVE_IB_SOLARIS_ATOMICS], [1],
|
||||
[Define to 1 if Solaris libc atomic functions \
|
||||
are available])
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING(whether pthread_t can be used by Solaris libc atomic functions)
|
||||
# either define HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS or not
|
||||
AC_TRY_RUN(
|
||||
[
|
||||
AC_MSG_NOTICE(no need to check pthread_t size)
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
pthread_t x1;
|
||||
pthread_t x2;
|
||||
pthread_t x3;
|
||||
|
||||
memset(&x1, 0x0, sizeof(x1));
|
||||
memset(&x2, 0x0, sizeof(x2));
|
||||
memset(&x3, 0x0, sizeof(x3));
|
||||
|
||||
if (sizeof(pthread_t) == 4) {
|
||||
|
||||
atomic_cas_32(&x1, x2, x3);
|
||||
|
||||
} else if (sizeof(pthread_t) == 8) {
|
||||
|
||||
atomic_cas_64(&x1, x2, x3);
|
||||
|
||||
} else {
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
],
|
||||
[
|
||||
AC_CHECK_DECLS(
|
||||
[HAVE_SOLARIS_ATOMICS],
|
||||
[
|
||||
AC_MSG_CHECKING(checking if pthread_t size is integral)
|
||||
AC_TRY_RUN(
|
||||
[
|
||||
#include <pthread.h>
|
||||
int main()
|
||||
{
|
||||
pthread_t x = 0;
|
||||
return(0);
|
||||
}
|
||||
],
|
||||
[
|
||||
AC_DEFINE([HAVE_ATOMIC_PTHREAD_T], [1],
|
||||
AC_DEFINE([HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS], [1],
|
||||
[pthread_t can be used by solaris atomics])
|
||||
AC_MSG_RESULT(yes)
|
||||
# size of pthread_t is needed for typed solaris atomics
|
||||
AC_CHECK_SIZEOF([pthread_t], [], [#include <pthread.h>])
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
])
|
||||
AC_MSG_RESULT(yes)
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT(no)
|
||||
]
|
||||
)
|
||||
|
||||
# this is needed to know which one of atomic_cas_32() or atomic_cas_64()
|
||||
# to use in the source
|
||||
AC_CHECK_SIZEOF([pthread_t], [], [#include <pthread.h>])
|
||||
|
||||
# Check for x86 PAUSE instruction
|
||||
AC_MSG_CHECKING(for x86 PAUSE instruction)
|
||||
# We have to actually try running the test program, because of a bug
|
||||
|
|
@ -142,7 +210,7 @@ MYSQL_PLUGIN_ACTIONS(innobase, [
|
|||
}
|
||||
],
|
||||
[
|
||||
AC_DEFINE([IB_HAVE_PAUSE_INSTRUCTION], [1], [Does x86 PAUSE instruction exist])
|
||||
AC_DEFINE([HAVE_IB_PAUSE_INSTRUCTION], [1], [Does x86 PAUSE instruction exist])
|
||||
AC_MSG_RESULT(yes)
|
||||
],
|
||||
[
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ Created 7/1/1994 Heikki Tuuri
|
|||
|
||||
The records are put into alphabetical order in the following
|
||||
way: let F be the first field where two records disagree.
|
||||
If there is a character in some position n where the the
|
||||
If there is a character in some position n where the
|
||||
records disagree, the order is determined by comparison of
|
||||
the characters at position n, possibly after
|
||||
collating transformation. If there is no such character,
|
||||
|
|
@ -76,7 +76,7 @@ cmp_debug_dtuple_rec_with_match(
|
|||
/*************************************************************//**
|
||||
This function is used to compare two data fields for which the data type
|
||||
is such that we must use MySQL code to compare them. The prototype here
|
||||
must be a copy of the the one in ha_innobase.cc!
|
||||
must be a copy of the one in ha_innobase.cc!
|
||||
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
|
||||
extern
|
||||
int
|
||||
|
|
@ -399,7 +399,7 @@ next_byte:
|
|||
/*************************************************************//**
|
||||
This function is used to compare a data tuple to a physical record.
|
||||
Only dtuple->n_fields_cmp first fields are taken into account for
|
||||
the the data tuple! If we denote by n = n_fields_cmp, then rec must
|
||||
the data tuple! If we denote by n = n_fields_cmp, then rec must
|
||||
have either m >= n fields, or it must differ from dtuple in some of
|
||||
the m fields rec has. If rec has an externally stored field we do not
|
||||
compare it but return with value 0 if such a comparison should be
|
||||
|
|
|
|||
8
storage/innobase/revert_gen.sh
Executable file
8
storage/innobase/revert_gen.sh
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# revert changes to all generated files. this is useful in some situations
|
||||
# when merging changes between branches.
|
||||
|
||||
set -eu
|
||||
|
||||
svn revert include/pars0grm.h pars/pars0grm.h pars/lexyy.c pars/pars0grm.c
|
||||
|
|
@ -1191,7 +1191,7 @@ row_ins_check_foreign_constraint(
|
|||
/*=============================*/
|
||||
ibool check_ref,/*!< in: TRUE if we want to check that
|
||||
the referenced table is ok, FALSE if we
|
||||
want to to check the foreign key table */
|
||||
want to check the foreign key table */
|
||||
dict_foreign_t* foreign,/*!< in: foreign constraint; NOTE that the
|
||||
tables mentioned in it must be in the
|
||||
dictionary cache if they exist at all */
|
||||
|
|
|
|||
|
|
@ -60,9 +60,19 @@ Completed by Sunny Bains and Marko Makela
|
|||
#ifdef UNIV_DEBUG
|
||||
/** Set these in order ot enable debug printout. */
|
||||
/* @{ */
|
||||
/** Log the outcome of each row_merge_cmp() call, comparing records. */
|
||||
static ibool row_merge_print_cmp;
|
||||
/** Log each record read from temporary file. */
|
||||
static ibool row_merge_print_read;
|
||||
/** Log each record write to temporary file. */
|
||||
static ibool row_merge_print_write;
|
||||
/** Log each row_merge_blocks() call, merging two blocks of records to
|
||||
a bigger one. */
|
||||
static ibool row_merge_print_block;
|
||||
/** Log each block read from temporary file. */
|
||||
static ibool row_merge_print_block_read;
|
||||
/** Log each block read from temporary file. */
|
||||
static ibool row_merge_print_block_write;
|
||||
/* @} */
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
|
|
@ -109,8 +119,9 @@ typedef struct row_merge_buf_struct row_merge_buf_t;
|
|||
|
||||
/** Information about temporary files used in merge sort */
|
||||
struct merge_file_struct {
|
||||
int fd; /*!< file descriptor */
|
||||
ulint offset; /*!< file offset */
|
||||
int fd; /*!< file descriptor */
|
||||
ulint offset; /*!< file offset (end of file) */
|
||||
ib_uint64_t n_rec; /*!< number of records in the file */
|
||||
};
|
||||
|
||||
/** Information about temporary files used in merge sort */
|
||||
|
|
@ -682,6 +693,13 @@ row_merge_read(
|
|||
ib_uint64_t ofs = ((ib_uint64_t) offset) * sizeof *buf;
|
||||
ibool success;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (row_merge_print_block_read) {
|
||||
fprintf(stderr, "row_merge_read fd=%d ofs=%lu\n",
|
||||
fd, (ulong) offset);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf,
|
||||
(ulint) (ofs & 0xFFFFFFFF),
|
||||
(ulint) (ofs >> 32),
|
||||
|
|
@ -709,6 +727,13 @@ row_merge_write(
|
|||
ib_uint64_t ofs = ((ib_uint64_t) offset)
|
||||
* sizeof(row_merge_block_t);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (row_merge_print_block_write) {
|
||||
fprintf(stderr, "row_merge_write fd=%d ofs=%lu\n",
|
||||
fd, (ulong) offset);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
return(UNIV_LIKELY(os_file_write("(merge)", OS_FILE_FROM_FD(fd), buf,
|
||||
(ulint) (ofs & 0xFFFFFFFF),
|
||||
(ulint) (ofs >> 32),
|
||||
|
|
@ -718,7 +743,7 @@ row_merge_write(
|
|||
/********************************************************************//**
|
||||
Read a merge record.
|
||||
@return pointer to next record, or NULL on I/O error or end of list */
|
||||
static
|
||||
static __attribute__((nonnull))
|
||||
const byte*
|
||||
row_merge_read_rec(
|
||||
/*===============*/
|
||||
|
|
@ -1070,7 +1095,7 @@ row_merge_cmp(
|
|||
Reads clustered index of the table and create temporary files
|
||||
containing the index entries for the indexes to be built.
|
||||
@return DB_SUCCESS or error */
|
||||
static
|
||||
static __attribute__((nonnull))
|
||||
ulint
|
||||
row_merge_read_clustered_index(
|
||||
/*===========================*/
|
||||
|
|
@ -1233,6 +1258,7 @@ row_merge_read_clustered_index(
|
|||
|
||||
if (UNIV_LIKELY
|
||||
(row && row_merge_buf_add(buf, row, ext))) {
|
||||
file->n_rec++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1274,14 +1300,19 @@ err_exit:
|
|||
UNIV_MEM_INVALID(block[0], sizeof block[0]);
|
||||
merge_buf[i] = row_merge_buf_empty(buf);
|
||||
|
||||
/* Try writing the record again, now that
|
||||
the buffer has been written out and emptied. */
|
||||
if (UNIV_LIKELY(row != NULL)) {
|
||||
/* Try writing the record again, now
|
||||
that the buffer has been written out
|
||||
and emptied. */
|
||||
|
||||
if (UNIV_UNLIKELY
|
||||
(row && !row_merge_buf_add(buf, row, ext))) {
|
||||
/* An empty buffer should have enough
|
||||
room for at least one record. */
|
||||
ut_error;
|
||||
if (UNIV_UNLIKELY
|
||||
(!row_merge_buf_add(buf, row, ext))) {
|
||||
/* An empty buffer should have enough
|
||||
room for at least one record. */
|
||||
ut_error;
|
||||
}
|
||||
|
||||
file->n_rec++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1320,7 +1351,7 @@ func_exit:
|
|||
b2 = row_merge_write_rec(&block[2], &buf[2], b2, \
|
||||
of->fd, &of->offset, \
|
||||
mrec##N, offsets##N); \
|
||||
if (UNIV_UNLIKELY(!b2)) { \
|
||||
if (UNIV_UNLIKELY(!b2 || ++of->n_rec > file->n_rec)) { \
|
||||
goto corrupt; \
|
||||
} \
|
||||
b##N = row_merge_read_rec(&block[N], &buf[N], \
|
||||
|
|
@ -1336,14 +1367,14 @@ func_exit:
|
|||
} while (0)
|
||||
|
||||
/*************************************************************//**
|
||||
Merge two blocks of linked lists on disk and write a bigger block.
|
||||
Merge two blocks of records on disk and write a bigger block.
|
||||
@return DB_SUCCESS or error code */
|
||||
static
|
||||
ulint
|
||||
row_merge_blocks(
|
||||
/*=============*/
|
||||
const dict_index_t* index, /*!< in: index being created */
|
||||
merge_file_t* file, /*!< in/out: file containing
|
||||
const merge_file_t* file, /*!< in: file containing
|
||||
index entries */
|
||||
row_merge_block_t* block, /*!< in/out: 3 buffers */
|
||||
ulint* foffs0, /*!< in/out: offset of first
|
||||
|
|
@ -1366,6 +1397,17 @@ row_merge_blocks(
|
|||
ulint* offsets0;/* offsets of mrec0 */
|
||||
ulint* offsets1;/* offsets of mrec1 */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (row_merge_print_block) {
|
||||
fprintf(stderr,
|
||||
"row_merge_blocks fd=%d ofs=%lu + fd=%d ofs=%lu"
|
||||
" = fd=%d ofs=%lu\n",
|
||||
file->fd, (ulong) *foffs0,
|
||||
file->fd, (ulong) *foffs1,
|
||||
of->fd, (ulong) of->offset);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
heap = row_merge_heap_create(index, &offsets0, &offsets1);
|
||||
|
||||
/* Write a record and read the next record. Split the output
|
||||
|
|
@ -1437,17 +1479,88 @@ done1:
|
|||
return(b2 ? DB_SUCCESS : DB_CORRUPTION);
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Copy a block of index entries.
|
||||
@return TRUE on success, FALSE on failure */
|
||||
static __attribute__((nonnull))
|
||||
ibool
|
||||
row_merge_blocks_copy(
|
||||
/*==================*/
|
||||
const dict_index_t* index, /*!< in: index being created */
|
||||
const merge_file_t* file, /*!< in: input file */
|
||||
row_merge_block_t* block, /*!< in/out: 3 buffers */
|
||||
ulint* foffs0, /*!< in/out: input file offset */
|
||||
merge_file_t* of) /*!< in/out: output file */
|
||||
{
|
||||
mem_heap_t* heap; /*!< memory heap for offsets0, offsets1 */
|
||||
|
||||
mrec_buf_t buf[3]; /*!< buffer for handling
|
||||
split mrec in block[] */
|
||||
const byte* b0; /*!< pointer to block[0] */
|
||||
byte* b2; /*!< pointer to block[2] */
|
||||
const mrec_t* mrec0; /*!< merge rec, points to block[0] */
|
||||
ulint* offsets0;/* offsets of mrec0 */
|
||||
ulint* offsets1;/* dummy offsets */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (row_merge_print_block) {
|
||||
fprintf(stderr,
|
||||
"row_merge_blocks_copy fd=%d ofs=%lu"
|
||||
" = fd=%d ofs=%lu\n",
|
||||
file->fd, (ulong) foffs0,
|
||||
of->fd, (ulong) of->offset);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
heap = row_merge_heap_create(index, &offsets0, &offsets1);
|
||||
|
||||
/* Write a record and read the next record. Split the output
|
||||
file in two halves, which can be merged on the following pass. */
|
||||
|
||||
if (!row_merge_read(file->fd, *foffs0, &block[0])) {
|
||||
corrupt:
|
||||
mem_heap_free(heap);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
b0 = block[0];
|
||||
b2 = block[2];
|
||||
|
||||
b0 = row_merge_read_rec(&block[0], &buf[0], b0, index, file->fd,
|
||||
foffs0, &mrec0, offsets0);
|
||||
if (UNIV_UNLIKELY(!b0 && mrec0)) {
|
||||
|
||||
goto corrupt;
|
||||
}
|
||||
|
||||
if (mrec0) {
|
||||
/* append all mrec0 to output */
|
||||
for (;;) {
|
||||
ROW_MERGE_WRITE_GET_NEXT(0, goto done0);
|
||||
}
|
||||
}
|
||||
done0:
|
||||
|
||||
/* The file offset points to the beginning of the last page
|
||||
that has been read. Update it to point to the next block. */
|
||||
(*foffs0)++;
|
||||
|
||||
mem_heap_free(heap);
|
||||
return(row_merge_write_eof(&block[2], b2, of->fd, &of->offset)
|
||||
!= NULL);
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Merge disk files.
|
||||
@return DB_SUCCESS or error code */
|
||||
static
|
||||
static __attribute__((nonnull))
|
||||
ulint
|
||||
row_merge(
|
||||
/*======*/
|
||||
const dict_index_t* index, /*!< in: index being created */
|
||||
merge_file_t* file, /*!< in/out: file containing
|
||||
index entries */
|
||||
ulint half, /*!< in: half the file */
|
||||
ulint* half, /*!< in/out: half the file */
|
||||
row_merge_block_t* block, /*!< in/out: 3 buffers */
|
||||
int* tmpfd, /*!< in/out: temporary file handle */
|
||||
TABLE* table) /*!< in/out: MySQL table, for
|
||||
|
|
@ -1458,43 +1571,75 @@ row_merge(
|
|||
ulint foffs1; /*!< second input offset */
|
||||
ulint error; /*!< error code */
|
||||
merge_file_t of; /*!< output file */
|
||||
const ulint ihalf = *half;
|
||||
/*!< half the input file */
|
||||
ulint ohalf; /*!< half the output file */
|
||||
|
||||
UNIV_MEM_ASSERT_W(block[0], 3 * sizeof block[0]);
|
||||
ut_ad(half > 0);
|
||||
ut_ad(ihalf < file->offset);
|
||||
|
||||
of.fd = *tmpfd;
|
||||
of.offset = 0;
|
||||
of.n_rec = 0;
|
||||
|
||||
/* Merge blocks to the output file. */
|
||||
ohalf = 0;
|
||||
foffs0 = 0;
|
||||
foffs1 = half;
|
||||
foffs1 = ihalf;
|
||||
|
||||
for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) {
|
||||
ulint ahalf; /*!< arithmetic half the input file */
|
||||
|
||||
for (; foffs0 < half && foffs1 < file->offset; foffs0++, foffs1++) {
|
||||
error = row_merge_blocks(index, file, block,
|
||||
&foffs0, &foffs1, &of, table);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
return(error);
|
||||
}
|
||||
|
||||
/* Record the offset of the output file when
|
||||
approximately half the output has been generated. In
|
||||
this way, the next invocation of row_merge() will
|
||||
spend most of the time in this loop. The initial
|
||||
estimate is ohalf==0. */
|
||||
ahalf = file->offset / 2;
|
||||
ut_ad(ohalf <= of.offset);
|
||||
|
||||
/* Improve the estimate until reaching half the input
|
||||
file size, or we can not get any closer to it. All
|
||||
comparands should be non-negative when !(ohalf < ahalf)
|
||||
because ohalf <= of.offset. */
|
||||
if (ohalf < ahalf || of.offset - ahalf < ohalf - ahalf) {
|
||||
ohalf = of.offset;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the last block, if there is one. */
|
||||
while (foffs0 < half) {
|
||||
if (!row_merge_read(file->fd, foffs0++, block)
|
||||
|| !row_merge_write(of.fd, of.offset++, block)) {
|
||||
/* Copy the last blocks, if there are any. */
|
||||
|
||||
while (foffs0 < ihalf) {
|
||||
if (!row_merge_blocks_copy(index, file, block, &foffs0, &of)) {
|
||||
return(DB_CORRUPTION);
|
||||
}
|
||||
}
|
||||
|
||||
ut_ad(foffs0 == ihalf);
|
||||
|
||||
while (foffs1 < file->offset) {
|
||||
if (!row_merge_read(file->fd, foffs1++, block)
|
||||
|| !row_merge_write(of.fd, of.offset++, block)) {
|
||||
if (!row_merge_blocks_copy(index, file, block, &foffs1, &of)) {
|
||||
return(DB_CORRUPTION);
|
||||
}
|
||||
}
|
||||
|
||||
ut_ad(foffs1 == file->offset);
|
||||
|
||||
if (UNIV_UNLIKELY(of.n_rec != file->n_rec)) {
|
||||
return(DB_CORRUPTION);
|
||||
}
|
||||
|
||||
/* Swap file descriptors for the next pass. */
|
||||
*tmpfd = file->fd;
|
||||
*file = of;
|
||||
*half = ohalf;
|
||||
|
||||
UNIV_MEM_INVALID(block[0], 3 * sizeof block[0]);
|
||||
|
||||
|
|
@ -1517,20 +1662,25 @@ row_merge_sort(
|
|||
reporting erroneous key value
|
||||
if applicable */
|
||||
{
|
||||
ulint blksz; /*!< block size */
|
||||
ulint half = file->offset / 2;
|
||||
|
||||
for (blksz = 1; blksz < file->offset; blksz *= 2) {
|
||||
ulint half;
|
||||
/* The file should always contain at least one byte (the end
|
||||
of file marker). Thus, it must be at least one block. */
|
||||
ut_ad(file->offset > 0);
|
||||
|
||||
do {
|
||||
ulint error;
|
||||
|
||||
ut_ad(ut_is_2pow(blksz));
|
||||
half = ut_2pow_round((file->offset + (blksz - 1)) / 2, blksz);
|
||||
error = row_merge(index, file, half, block, tmpfd, table);
|
||||
error = row_merge(index, file, &half, block, tmpfd, table);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
return(error);
|
||||
}
|
||||
}
|
||||
|
||||
/* half > 0 should hold except when the file consists
|
||||
of one block. No need to merge further then. */
|
||||
ut_ad(half > 0 || file->offset == 1);
|
||||
} while (half < file->offset && half > 0);
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
|
@ -1797,7 +1947,15 @@ row_merge_drop_index(
|
|||
static const char str1[] =
|
||||
"PROCEDURE DROP_INDEX_PROC () IS\n"
|
||||
"BEGIN\n"
|
||||
/* Rename the index, so that it will be dropped by
|
||||
row_merge_drop_temp_indexes() at crash recovery
|
||||
if the server crashes before this trx is committed. */
|
||||
"UPDATE SYS_INDEXES SET NAME=CONCAT('"
|
||||
TEMP_INDEX_PREFIX_STR "', NAME) WHERE ID = :indexid;\n"
|
||||
"COMMIT WORK;\n"
|
||||
/* Drop the field definitions of the index. */
|
||||
"DELETE FROM SYS_FIELDS WHERE INDEX_ID = :indexid;\n"
|
||||
/* Drop the index definition and the B-tree. */
|
||||
"DELETE FROM SYS_INDEXES WHERE ID = :indexid\n"
|
||||
" AND TABLE_ID = :tableid;\n"
|
||||
"END;\n";
|
||||
|
|
@ -1909,6 +2067,7 @@ row_merge_file_create(
|
|||
{
|
||||
merge_file->fd = innobase_mysql_tmpfile();
|
||||
merge_file->offset = 0;
|
||||
merge_file->n_rec = 0;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
|
|
@ -2129,7 +2288,7 @@ row_merge_rename_tables(
|
|||
if (err != DB_SUCCESS) {
|
||||
err_exit:
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -510,7 +510,7 @@ handle_new_error:
|
|||
switch (err) {
|
||||
case DB_LOCK_WAIT_TIMEOUT:
|
||||
if (row_rollback_on_timeout) {
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
|
|
@ -526,7 +526,7 @@ handle_new_error:
|
|||
/* Roll back the latest, possibly incomplete
|
||||
insertion or update */
|
||||
|
||||
trx_general_rollback_for_mysql(trx, TRUE, savept);
|
||||
trx_general_rollback_for_mysql(trx, savept);
|
||||
}
|
||||
/* MySQL will roll back the latest SQL statement */
|
||||
break;
|
||||
|
|
@ -548,7 +548,7 @@ handle_new_error:
|
|||
/* Roll back the whole transaction; this resolution was added
|
||||
to version 3.23.43 */
|
||||
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
break;
|
||||
|
||||
case DB_MUST_GET_MORE_FILE_SPACE:
|
||||
|
|
@ -866,18 +866,22 @@ row_update_statistics_if_needed(
|
|||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Unlocks AUTO_INC type locks that were possibly reserved by a trx. */
|
||||
Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
|
||||
function should be called at the the end of an SQL statement, by the
|
||||
connection thread that owns the transaction (trx->mysql_thd). */
|
||||
UNIV_INTERN
|
||||
void
|
||||
row_unlock_table_autoinc_for_mysql(
|
||||
/*===============================*/
|
||||
trx_t* trx) /*!< in/out: transaction */
|
||||
{
|
||||
mutex_enter(&kernel_mutex);
|
||||
if (lock_trx_holds_autoinc_locks(trx)) {
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
lock_release_autoinc_locks(trx);
|
||||
lock_release_autoinc_locks(trx);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
|
|
@ -1767,7 +1771,6 @@ row_create_table_for_mysql(
|
|||
const char* table_name;
|
||||
ulint table_name_len;
|
||||
ulint err;
|
||||
ulint i;
|
||||
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
|
|
@ -1802,15 +1805,6 @@ err_exit:
|
|||
goto err_exit;
|
||||
}
|
||||
|
||||
/* Check that no reserved column names are used. */
|
||||
for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
|
||||
if (dict_col_name_is_reserved(
|
||||
dict_table_get_col_name(table, i))) {
|
||||
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
|
||||
trx_start_if_not_started(trx);
|
||||
|
||||
/* The table name is prefixed with the database name and a '/'.
|
||||
|
|
@ -1885,7 +1879,7 @@ err_exit:
|
|||
|
||||
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
}
|
||||
|
||||
switch (err) {
|
||||
|
|
@ -2053,7 +2047,7 @@ error_handling:
|
|||
|
||||
trx->error_state = DB_SUCCESS;
|
||||
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
|
||||
row_drop_table_for_mysql(table_name, trx, FALSE);
|
||||
|
||||
|
|
@ -2121,7 +2115,7 @@ row_table_add_foreign_constraints(
|
|||
|
||||
trx->error_state = DB_SUCCESS;
|
||||
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
|
||||
row_drop_table_for_mysql(name, trx, FALSE);
|
||||
|
||||
|
|
@ -2488,7 +2482,7 @@ row_discard_tablespace_for_mysql(
|
|||
|
||||
if (err != DB_SUCCESS) {
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
} else {
|
||||
dict_table_change_id_in_cache(table, new_id);
|
||||
|
|
@ -2497,7 +2491,7 @@ row_discard_tablespace_for_mysql(
|
|||
|
||||
if (!success) {
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
|
||||
err = DB_ERROR;
|
||||
|
|
@ -2949,7 +2943,7 @@ next_rec:
|
|||
|
||||
if (err != DB_SUCCESS) {
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Unable to assign a new identifier to table ",
|
||||
|
|
@ -3590,7 +3584,7 @@ row_delete_constraint(
|
|||
|
||||
if ((err == DB_SUCCESS) && !strchr(id, '/')) {
|
||||
/* Old format < 4.0.18 constraints have constraint ids
|
||||
<number>_<number>. We only try deleting them if the
|
||||
NUMBER_NUMBER. We only try deleting them if the
|
||||
constraint name does not contain a '/' character, otherwise
|
||||
deleting a new format constraint named 'foo/bar' from
|
||||
database 'baz' would remove constraint 'bar' from database
|
||||
|
|
@ -3854,7 +3848,7 @@ end:
|
|||
"InnoDB: succeed.\n", stderr);
|
||||
}
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
} else {
|
||||
/* The following call will also rename the .ibd data file if
|
||||
|
|
@ -3863,7 +3857,7 @@ end:
|
|||
if (!dict_table_rename_in_cache(table, new_name,
|
||||
!new_is_tmp)) {
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
goto funct_exit;
|
||||
}
|
||||
|
|
@ -3903,7 +3897,7 @@ end:
|
|||
ut_a(dict_table_rename_in_cache(table,
|
||||
old_name, FALSE));
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
74
storage/innobase/scripts/export.sh
Executable file
74
storage/innobase/scripts/export.sh
Executable file
|
|
@ -0,0 +1,74 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# export current working directory in a format suitable for sending to MySQL
|
||||
# as a snapshot. also generates the actual snapshot and sends it to MySQL.
|
||||
|
||||
set -eu
|
||||
|
||||
die () {
|
||||
echo $*
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ $# -ne 2 ] ; then
|
||||
die "Usage: export.sh revision-number-of-last-snapshot current-revision-number"
|
||||
fi
|
||||
|
||||
# If we are run from within the scripts/ directory then change directory to
|
||||
# one level up so that the relative paths work.
|
||||
DIR=`basename $PWD`
|
||||
|
||||
if [ "${DIR}" = "scripts" ]; then
|
||||
cd ..
|
||||
fi
|
||||
|
||||
START_REV=$(($1 + 1))
|
||||
END_REV=$2
|
||||
|
||||
set +u
|
||||
if test -z $EDITOR; then
|
||||
die "\$EDITOR is not set"
|
||||
fi
|
||||
set -u
|
||||
|
||||
rm -rf to-mysql
|
||||
mkdir to-mysql{,/storage,/patches,/mysql-test{,/t,/r,/include}}
|
||||
svn log -v -r "$START_REV:BASE" > to-mysql/log
|
||||
svn export -q . to-mysql/storage/innobase
|
||||
|
||||
REV=$START_REV
|
||||
while [ $REV -le $END_REV ]
|
||||
do
|
||||
PATCH=to-mysql/patches/r$REV.patch
|
||||
svn log -v -r$REV > $PATCH
|
||||
if [ $(wc -c < $PATCH) -gt 73 ]
|
||||
then
|
||||
svn diff -r$(($REV-1)):$REV >> $PATCH
|
||||
else
|
||||
rm $PATCH
|
||||
fi
|
||||
REV=$(($REV + 1))
|
||||
done
|
||||
|
||||
cd to-mysql/storage/innobase
|
||||
|
||||
mv mysql-test/*.test mysql-test/*.opt ../../mysql-test/t
|
||||
mv mysql-test/*.result ../../mysql-test/r
|
||||
mv mysql-test/*.inc ../../mysql-test/include
|
||||
rmdir mysql-test
|
||||
|
||||
rm setup.sh export.sh revert_gen.sh compile-innodb-debug compile-innodb
|
||||
|
||||
cd ../..
|
||||
$EDITOR log
|
||||
cd ..
|
||||
|
||||
fname="innodb-5.1-ss$2.tar.gz"
|
||||
|
||||
rm -f $fname
|
||||
tar czf $fname to-mysql
|
||||
scp $fname mysql:snapshots
|
||||
rm $fname
|
||||
rm -rf to-mysql
|
||||
|
||||
echo "Sent $fname to MySQL"
|
||||
|
|
@ -102,6 +102,7 @@ Created 10/8/1995 Heikki Tuuri
|
|||
#include "row0mysql.h"
|
||||
#include "ha_prototypes.h"
|
||||
#include "trx0i_s.h"
|
||||
#include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
|
||||
|
||||
/* This is set to TRUE if the MySQL user has set it in MySQL; currently
|
||||
affects only FOREIGN KEY definition parsing */
|
||||
|
|
@ -292,12 +293,6 @@ UNIV_INTERN ulint srv_buf_pool_flushed = 0;
|
|||
reading of a disk page */
|
||||
UNIV_INTERN ulint srv_buf_pool_reads = 0;
|
||||
|
||||
/** Number of sequential read-aheads */
|
||||
UNIV_INTERN ulint srv_read_ahead_seq = 0;
|
||||
|
||||
/** Number of random read-aheads */
|
||||
UNIV_INTERN ulint srv_read_ahead_rnd = 0;
|
||||
|
||||
/* structure to pass status variables to MySQL */
|
||||
UNIV_INTERN export_struc export_vars;
|
||||
|
||||
|
|
@ -464,8 +459,6 @@ static ulint srv_main_background_loops = 0;
|
|||
static ulint srv_main_flush_loops = 0;
|
||||
/* Log writes involving flush. */
|
||||
static ulint srv_log_writes_and_flush = 0;
|
||||
/* Log writes not including flush. */
|
||||
static ulint srv_log_buffer_writes = 0;
|
||||
|
||||
/* This is only ever touched by the master thread. It records the
|
||||
time when the last flush of log file has happened. The master
|
||||
|
|
@ -614,7 +607,7 @@ future, but at the moment we plan to implement a more coarse solution,
|
|||
which could be called a global priority inheritance. If a thread
|
||||
has to wait for a long time, say 300 milliseconds, for a resource,
|
||||
we just guess that it may be waiting for a resource owned by a background
|
||||
thread, and boost the the priority of all runnable background threads
|
||||
thread, and boost the priority of all runnable background threads
|
||||
to the normal level. The background threads then themselves adjust
|
||||
their fixed priority back to background after releasing all resources
|
||||
they had (or, at some fixed points in their program code).
|
||||
|
|
@ -714,9 +707,8 @@ srv_print_master_thread_info(
|
|||
srv_main_1_second_loops, srv_main_sleeps,
|
||||
srv_main_10_second_loops, srv_main_background_loops,
|
||||
srv_main_flush_loops);
|
||||
fprintf(file, "srv_master_thread log flush and writes: %lu "
|
||||
" log writes only: %lu\n",
|
||||
srv_log_writes_and_flush, srv_log_buffer_writes);
|
||||
fprintf(file, "srv_master_thread log flush and writes: %lu\n",
|
||||
srv_log_writes_and_flush);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
|
|
@ -1877,14 +1869,16 @@ srv_export_innodb_status(void)
|
|||
export_vars.innodb_data_reads = os_n_file_reads;
|
||||
export_vars.innodb_data_writes = os_n_file_writes;
|
||||
export_vars.innodb_data_written = srv_data_written;
|
||||
export_vars.innodb_buffer_pool_read_requests = buf_pool->n_page_gets;
|
||||
export_vars.innodb_buffer_pool_read_requests = buf_pool->stat.n_page_gets;
|
||||
export_vars.innodb_buffer_pool_write_requests
|
||||
= srv_buf_pool_write_requests;
|
||||
export_vars.innodb_buffer_pool_wait_free = srv_buf_pool_wait_free;
|
||||
export_vars.innodb_buffer_pool_pages_flushed = srv_buf_pool_flushed;
|
||||
export_vars.innodb_buffer_pool_reads = srv_buf_pool_reads;
|
||||
export_vars.innodb_buffer_pool_read_ahead_rnd = srv_read_ahead_rnd;
|
||||
export_vars.innodb_buffer_pool_read_ahead_seq = srv_read_ahead_seq;
|
||||
export_vars.innodb_buffer_pool_read_ahead
|
||||
= buf_pool->stat.n_ra_pages_read;
|
||||
export_vars.innodb_buffer_pool_read_ahead_evicted
|
||||
= buf_pool->stat.n_ra_pages_evicted;
|
||||
export_vars.innodb_buffer_pool_pages_data
|
||||
= UT_LIST_GET_LEN(buf_pool->LRU);
|
||||
export_vars.innodb_buffer_pool_pages_dirty
|
||||
|
|
@ -1915,9 +1909,9 @@ srv_export_innodb_status(void)
|
|||
export_vars.innodb_log_writes = srv_log_writes;
|
||||
export_vars.innodb_dblwr_pages_written = srv_dblwr_pages_written;
|
||||
export_vars.innodb_dblwr_writes = srv_dblwr_writes;
|
||||
export_vars.innodb_pages_created = buf_pool->n_pages_created;
|
||||
export_vars.innodb_pages_read = buf_pool->n_pages_read;
|
||||
export_vars.innodb_pages_written = buf_pool->n_pages_written;
|
||||
export_vars.innodb_pages_created = buf_pool->stat.n_pages_created;
|
||||
export_vars.innodb_pages_read = buf_pool->stat.n_pages_read;
|
||||
export_vars.innodb_pages_written = buf_pool->stat.n_pages_written;
|
||||
export_vars.innodb_row_lock_waits = srv_n_lock_wait_count;
|
||||
export_vars.innodb_row_lock_current_waits
|
||||
= srv_n_lock_wait_current_count;
|
||||
|
|
@ -2284,12 +2278,6 @@ srv_sync_log_buffer_in_background(void)
|
|||
log_buffer_sync_in_background(TRUE);
|
||||
srv_last_log_flush_time = current_time;
|
||||
srv_log_writes_and_flush++;
|
||||
} else {
|
||||
/* Actually we don't need to write logs here.
|
||||
We are just being extra safe here by forcing
|
||||
the log buffer to log file. */
|
||||
log_buffer_sync_in_background(FALSE);
|
||||
srv_log_buffer_writes++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2340,8 +2328,8 @@ loop:
|
|||
|
||||
srv_main_thread_op_info = "reserving kernel mutex";
|
||||
|
||||
n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read
|
||||
+ buf_pool->n_pages_written;
|
||||
n_ios_very_old = log_sys->n_log_ios + buf_pool->stat.n_pages_read
|
||||
+ buf_pool->stat.n_pages_written;
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
/* Store the user activity counter at the start of this loop */
|
||||
|
|
@ -2361,8 +2349,8 @@ loop:
|
|||
skip_sleep = FALSE;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read
|
||||
+ buf_pool->n_pages_written;
|
||||
n_ios_old = log_sys->n_log_ios + buf_pool->stat.n_pages_read
|
||||
+ buf_pool->stat.n_pages_written;
|
||||
srv_main_thread_op_info = "sleeping";
|
||||
srv_main_1_second_loops++;
|
||||
|
||||
|
|
@ -2401,8 +2389,8 @@ loop:
|
|||
|
||||
n_pend_ios = buf_get_n_pending_ios()
|
||||
+ log_sys->n_pending_writes;
|
||||
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
|
||||
+ buf_pool->n_pages_written;
|
||||
n_ios = log_sys->n_log_ios + buf_pool->stat.n_pages_read
|
||||
+ buf_pool->stat.n_pages_written;
|
||||
if (n_pend_ios < SRV_PEND_IO_THRESHOLD
|
||||
&& (n_ios - n_ios_old < SRV_RECENT_IO_ACTIVITY)) {
|
||||
srv_main_thread_op_info = "doing insert buffer merge";
|
||||
|
|
@ -2418,6 +2406,8 @@ loop:
|
|||
/* Try to keep the number of modified pages in the
|
||||
buffer pool under the limit wished by the user */
|
||||
|
||||
srv_main_thread_op_info =
|
||||
"flushing buffer pool pages";
|
||||
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST,
|
||||
PCT_IO(100),
|
||||
IB_ULONGLONG_MAX);
|
||||
|
|
@ -2436,6 +2426,8 @@ loop:
|
|||
ulint n_flush = buf_flush_get_desired_flush_rate();
|
||||
|
||||
if (n_flush) {
|
||||
srv_main_thread_op_info =
|
||||
"flushing buffer pool pages";
|
||||
n_flush = ut_min(PCT_IO(100), n_flush);
|
||||
n_pages_flushed =
|
||||
buf_flush_batch(
|
||||
|
|
@ -2473,8 +2465,8 @@ loop:
|
|||
are not required, and may be disabled. */
|
||||
|
||||
n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
|
||||
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
|
||||
+ buf_pool->n_pages_written;
|
||||
n_ios = log_sys->n_log_ios + buf_pool->stat.n_pages_read
|
||||
+ buf_pool->stat.n_pages_written;
|
||||
|
||||
srv_main_10_second_loops++;
|
||||
if (n_pend_ios < SRV_PEND_IO_THRESHOLD
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ Created 2/16/1996 Heikki Tuuri
|
|||
# include "row0row.h"
|
||||
# include "row0mysql.h"
|
||||
# include "btr0pcur.h"
|
||||
# include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
|
||||
/** Log sequence number immediately after startup */
|
||||
UNIV_INTERN ib_uint64_t srv_start_lsn;
|
||||
|
|
@ -1096,6 +1097,10 @@ innobase_start_or_create_for_mysql(void)
|
|||
"InnoDB: !!!!!!!! UNIV_SEARCH_DEBUG switched on !!!!!!!!!\n");
|
||||
#endif
|
||||
|
||||
#ifdef UNIV_LOG_LSN_DEBUG
|
||||
fprintf(stderr,
|
||||
"InnoDB: !!!!!!!! UNIV_LOG_LSN_DEBUG switched on !!!!!!!!!\n");
|
||||
#endif /* UNIV_LOG_LSN_DEBUG */
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
fprintf(stderr,
|
||||
"InnoDB: !!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!\n");
|
||||
|
|
@ -1106,34 +1111,7 @@ innobase_start_or_create_for_mysql(void)
|
|||
"InnoDB: The InnoDB memory heap is disabled\n");
|
||||
}
|
||||
|
||||
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||
# ifdef INNODB_RW_LOCKS_USE_ATOMICS
|
||||
fprintf(stderr,
|
||||
"InnoDB: Mutexes and rw_locks use GCC atomic builtins.\n");
|
||||
# else /* INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
fprintf(stderr,
|
||||
"InnoDB: Mutexes use GCC atomic builtins, rw_locks do not.\n");
|
||||
# endif /* INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
#elif defined(HAVE_SOLARIS_ATOMICS)
|
||||
# ifdef INNODB_RW_LOCKS_USE_ATOMICS
|
||||
fprintf(stderr,
|
||||
"InnoDB: Mutexes and rw_locks use Solaris atomic functions.\n");
|
||||
# else
|
||||
fprintf(stderr,
|
||||
"InnoDB: Mutexes use Solaris atomic functions.\n");
|
||||
# endif /* INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
#elif HAVE_WINDOWS_ATOMICS
|
||||
# ifdef INNODB_RW_LOCKS_USE_ATOMICS
|
||||
fprintf(stderr,
|
||||
"InnoDB: Mutexes and rw_locks use Windows interlocked functions.\n");
|
||||
# else
|
||||
fprintf(stderr,
|
||||
"InnoDB: Mutexes use Windows interlocked functions.\n");
|
||||
# endif /* INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
#else /* HAVE_GCC_ATOMIC_BUILTINS */
|
||||
fprintf(stderr,
|
||||
"InnoDB: Neither mutexes nor rw_locks use GCC atomic builtins.\n");
|
||||
#endif /* HAVE_GCC_ATOMIC_BUILTINS */
|
||||
fprintf(stderr, "InnoDB: %s\n", IB_ATOMICS_STARTUP_MSG);
|
||||
|
||||
/* Since InnoDB does not currently clean up all its internal data
|
||||
structures in MySQL Embedded Server Library server_end(), we
|
||||
|
|
@ -1829,7 +1807,7 @@ innobase_start_or_create_for_mysql(void)
|
|||
/* Actually, we did not change the undo log format between
|
||||
4.0 and 4.1.1, and we would not need to run purge to
|
||||
completion. Note also that the purge algorithm in 4.1.1
|
||||
can process the the history list again even after a full
|
||||
can process the history list again even after a full
|
||||
purge, because our algorithm does not cut the end of the
|
||||
history list in all cases so that it would become empty
|
||||
after a full purge. That mean that we may purge 4.0 type
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ Created 9/11/1995 Heikki Tuuri
|
|||
#include "os0thread.h"
|
||||
#include "mem0mem.h"
|
||||
#include "srv0srv.h"
|
||||
#include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
|
||||
/*
|
||||
IMPLEMENTATION OF THE RW_LOCK
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ Created 9/5/1995 Heikki Tuuri
|
|||
#include "buf0buf.h"
|
||||
#include "srv0srv.h"
|
||||
#include "buf0types.h"
|
||||
#include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
|
||||
|
||||
/*
|
||||
REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX
|
||||
|
|
@ -849,7 +850,8 @@ sync_thread_levels_g(
|
|||
/*=================*/
|
||||
sync_level_t* arr, /*!< in: pointer to level array for an OS
|
||||
thread */
|
||||
ulint limit) /*!< in: level limit */
|
||||
ulint limit, /*!< in: level limit */
|
||||
ulint warn) /*!< in: TRUE=display a diagnostic message */
|
||||
{
|
||||
sync_level_t* slot;
|
||||
rw_lock_t* lock;
|
||||
|
|
@ -863,6 +865,11 @@ sync_thread_levels_g(
|
|||
if (slot->latch != NULL) {
|
||||
if (slot->level <= limit) {
|
||||
|
||||
if (!warn) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
lock = slot->latch;
|
||||
mutex = slot->latch;
|
||||
|
||||
|
|
@ -1100,7 +1107,7 @@ sync_thread_add_level(
|
|||
case SYNC_DICT_HEADER:
|
||||
case SYNC_TRX_I_S_RWLOCK:
|
||||
case SYNC_TRX_I_S_LAST_READ:
|
||||
if (!sync_thread_levels_g(array, level)) {
|
||||
if (!sync_thread_levels_g(array, level, TRUE)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: sync_thread_levels_g(array, %lu)"
|
||||
" does not hold!\n", level);
|
||||
|
|
@ -1111,36 +1118,44 @@ sync_thread_add_level(
|
|||
/* 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). */
|
||||
if (!sync_thread_levels_g(array, level)) {
|
||||
ut_a(sync_thread_levels_g(array, level - 1));
|
||||
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));
|
||||
}
|
||||
break;
|
||||
case SYNC_REC_LOCK:
|
||||
ut_a((sync_thread_levels_contain(array, SYNC_KERNEL)
|
||||
&& sync_thread_levels_g(array, SYNC_REC_LOCK - 1))
|
||||
|| sync_thread_levels_g(array, SYNC_REC_LOCK));
|
||||
if (sync_thread_levels_contain(array, SYNC_KERNEL)) {
|
||||
ut_a(sync_thread_levels_g(array, SYNC_REC_LOCK - 1,
|
||||
TRUE));
|
||||
} else {
|
||||
ut_a(sync_thread_levels_g(array, SYNC_REC_LOCK, TRUE));
|
||||
}
|
||||
break;
|
||||
case SYNC_IBUF_BITMAP:
|
||||
/* Either the thread must own the master mutex to all
|
||||
the bitmap pages, or it is allowed to latch only ONE
|
||||
bitmap page. */
|
||||
ut_a((sync_thread_levels_contain(array, SYNC_IBUF_BITMAP_MUTEX)
|
||||
&& sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1))
|
||||
|| sync_thread_levels_g(array, SYNC_IBUF_BITMAP));
|
||||
if (sync_thread_levels_contain(array,
|
||||
SYNC_IBUF_BITMAP_MUTEX)) {
|
||||
ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1,
|
||||
TRUE));
|
||||
} else {
|
||||
ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP,
|
||||
TRUE));
|
||||
}
|
||||
break;
|
||||
case SYNC_FSP_PAGE:
|
||||
ut_a(sync_thread_levels_contain(array, SYNC_FSP));
|
||||
break;
|
||||
case SYNC_FSP:
|
||||
ut_a(sync_thread_levels_contain(array, SYNC_FSP)
|
||||
|| sync_thread_levels_g(array, SYNC_FSP));
|
||||
|| sync_thread_levels_g(array, SYNC_FSP, TRUE));
|
||||
break;
|
||||
case SYNC_TRX_UNDO_PAGE:
|
||||
ut_a(sync_thread_levels_contain(array, SYNC_TRX_UNDO)
|
||||
|| sync_thread_levels_contain(array, SYNC_RSEG)
|
||||
|| sync_thread_levels_contain(array, SYNC_PURGE_SYS)
|
||||
|| sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE));
|
||||
|| sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE, TRUE));
|
||||
break;
|
||||
case SYNC_RSEG_HEADER:
|
||||
ut_a(sync_thread_levels_contain(array, SYNC_RSEG));
|
||||
|
|
@ -1152,37 +1167,41 @@ sync_thread_add_level(
|
|||
case SYNC_TREE_NODE:
|
||||
ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE)
|
||||
|| sync_thread_levels_contain(array, SYNC_DICT_OPERATION)
|
||||
|| sync_thread_levels_g(array, SYNC_TREE_NODE - 1));
|
||||
|| 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));
|
||||
break;
|
||||
case SYNC_INDEX_TREE:
|
||||
ut_a((sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
|
||||
&& sync_thread_levels_contain(array, SYNC_FSP)
|
||||
&& sync_thread_levels_g(array, SYNC_FSP_PAGE - 1))
|
||||
|| sync_thread_levels_g(array, SYNC_TREE_NODE - 1));
|
||||
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));
|
||||
} else {
|
||||
ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1,
|
||||
TRUE));
|
||||
}
|
||||
break;
|
||||
case SYNC_IBUF_MUTEX:
|
||||
ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1));
|
||||
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)
|
||||
&& !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
|
||||
ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE));
|
||||
ut_a(!sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
|
||||
break;
|
||||
case SYNC_IBUF_HEADER:
|
||||
ut_a(sync_thread_levels_g(array, SYNC_FSP - 1)
|
||||
&& !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
|
||||
&& !sync_thread_levels_contain(
|
||||
array, 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));
|
||||
ut_a(!sync_thread_levels_contain(array,
|
||||
SYNC_IBUF_PESS_INSERT_MUTEX));
|
||||
break;
|
||||
case SYNC_DICT:
|
||||
#ifdef UNIV_DEBUG
|
||||
ut_a(buf_debug_prints
|
||||
|| sync_thread_levels_g(array, SYNC_DICT));
|
||||
|| sync_thread_levels_g(array, SYNC_DICT, TRUE));
|
||||
#else /* UNIV_DEBUG */
|
||||
ut_a(sync_thread_levels_g(array, SYNC_DICT));
|
||||
ut_a(sync_thread_levels_g(array, SYNC_DICT, TRUE));
|
||||
#endif /* UNIV_DEBUG */
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue