1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Merge XtraDB 9 into MariaDB.

This commit is contained in:
unknown
2010-01-15 16:58:25 +01:00
155 changed files with 5372 additions and 3094 deletions

View File

@ -85,6 +85,7 @@ TABLE_PRIVILEGES
TRIGGERS
USER_PRIVILEGES
VIEWS
XTRADB_ADMIN_COMMAND
XTRADB_ENHANCEMENTS
columns_priv
db
@ -865,8 +866,8 @@ TABLE_CONSTRAINTS TABLE_NAME select
TABLE_PRIVILEGES TABLE_NAME select
VIEWS TABLE_NAME select
INNODB_BUFFER_POOL_PAGES_INDEX table_name select
INNODB_INDEX_STATS table_name select
INNODB_TABLE_STATS table_name select
INNODB_INDEX_STATS table_name select
delete from mysql.user where user='mysqltest_4';
delete from mysql.db where user='mysqltest_4';
flush privileges;

View File

@ -35,7 +35,7 @@ INNODB_CMP
INNODB_RSEG
XTRADB_ENHANCEMENTS
INNODB_BUFFER_POOL_PAGES_INDEX
INNODB_INDEX_STATS
XTRADB_ADMIN_COMMAND
INNODB_TRX
INNODB_CMP_RESET
INNODB_LOCK_WAITS
@ -44,6 +44,7 @@ INNODB_LOCKS
INNODB_CMPMEM
INNODB_TABLE_STATS
INNODB_BUFFER_POOL_PAGES_BLOB
INNODB_INDEX_STATS
SELECT t.table_name, c1.column_name
FROM information_schema.tables t
INNER JOIN
@ -93,7 +94,7 @@ INNODB_CMP page_size
INNODB_RSEG rseg_id
XTRADB_ENHANCEMENTS name
INNODB_BUFFER_POOL_PAGES_INDEX schema_name
INNODB_INDEX_STATS table_name
XTRADB_ADMIN_COMMAND result_message
INNODB_TRX trx_id
INNODB_CMP_RESET page_size
INNODB_LOCK_WAITS requesting_trx_id
@ -102,6 +103,7 @@ INNODB_LOCKS lock_id
INNODB_CMPMEM page_size
INNODB_TABLE_STATS table_name
INNODB_BUFFER_POOL_PAGES_BLOB space_id
INNODB_INDEX_STATS table_name
SELECT t.table_name, c1.column_name
FROM information_schema.tables t
INNER JOIN
@ -151,7 +153,7 @@ INNODB_CMP page_size
INNODB_RSEG rseg_id
XTRADB_ENHANCEMENTS name
INNODB_BUFFER_POOL_PAGES_INDEX schema_name
INNODB_INDEX_STATS table_name
XTRADB_ADMIN_COMMAND result_message
INNODB_TRX trx_id
INNODB_CMP_RESET page_size
INNODB_LOCK_WAITS requesting_trx_id
@ -160,6 +162,7 @@ INNODB_LOCKS lock_id
INNODB_CMPMEM page_size
INNODB_TABLE_STATS table_name
INNODB_BUFFER_POOL_PAGES_BLOB space_id
INNODB_INDEX_STATS table_name
select 1 as f1 from information_schema.tables where "CHARACTER_SETS"=
(select cast(table_name as char) from information_schema.tables
order by table_name limit 1) limit 1;
@ -262,7 +265,7 @@ Database: information_schema
| INNODB_RSEG |
| XTRADB_ENHANCEMENTS |
| INNODB_BUFFER_POOL_PAGES_INDEX |
| INNODB_INDEX_STATS |
| XTRADB_ADMIN_COMMAND |
| INNODB_TRX |
| INNODB_CMP_RESET |
| INNODB_LOCK_WAITS |
@ -271,6 +274,7 @@ Database: information_schema
| INNODB_CMPMEM |
| INNODB_TABLE_STATS |
| INNODB_BUFFER_POOL_PAGES_BLOB |
| INNODB_INDEX_STATS |
+---------------------------------------+
Database: INFORMATION_SCHEMA
+---------------------------------------+
@ -310,7 +314,7 @@ Database: INFORMATION_SCHEMA
| INNODB_RSEG |
| XTRADB_ENHANCEMENTS |
| INNODB_BUFFER_POOL_PAGES_INDEX |
| INNODB_INDEX_STATS |
| XTRADB_ADMIN_COMMAND |
| INNODB_TRX |
| INNODB_CMP_RESET |
| INNODB_LOCK_WAITS |
@ -319,6 +323,7 @@ Database: INFORMATION_SCHEMA
| INNODB_CMPMEM |
| INNODB_TABLE_STATS |
| INNODB_BUFFER_POOL_PAGES_BLOB |
| INNODB_INDEX_STATS |
+---------------------------------------+
Wildcard: inf_rmation_schema
+--------------------+
@ -328,5 +333,5 @@ Wildcard: inf_rmation_schema
+--------------------+
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
table_schema count(*)
information_schema 43
information_schema 44
mysql 22

View File

@ -875,11 +875,11 @@ ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT;
SELECT * FROM t1;
d1
1
3
2
SELECT * FROM t1;
d1
1
3
2
INSERT INTO t1 VALUES(null);
Got one of the listed errors
ALTER TABLE t1 AUTO_INCREMENT = 3;
@ -888,13 +888,13 @@ Table Create Table
t1 CREATE TABLE `t1` (
`d1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`d1`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES(null);
SELECT * FROM t1;
d1
1
2
3
4
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SHOW VARIABLES LIKE "%auto_inc%";

View 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;

View File

@ -1,4 +1,3 @@
SET @save_innodb_file_format_check=@@global.innodb_file_format_check;
create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
commit;
@ -629,7 +628,7 @@ drop table t1;
create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb;
insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,3,'ac','ac'),(4,4,'afe','afe'),(5,4,'affe','affe');
alter table t1 add unique index (b), add unique index (c), add unique index (d);
ERROR 23000: Duplicate entry '4' for key 'b'
ERROR 23000: Duplicate entry 'ac' for key 'c'
alter table t1 add unique index (c), add unique index (b), add index (d);
ERROR 23000: Duplicate entry 'ac' for key 'c'
show create table t1;
@ -970,6 +969,7 @@ create index t1u on t1 (u(1));
drop table t1;
set global innodb_file_per_table=0;
set global innodb_file_format=Antelope;
set global innodb_file_format_check=Antelope;
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
CREATE TABLE t1(
@ -1171,4 +1171,3 @@ a b
3 a
3 b
DROP TABLE t1;
SET GLOBAL innodb_file_format_check=@save_innodb_file_format_check;

View File

@ -196,15 +196,15 @@ drop table t1;
set innodb_strict_mode = on;
create table t1 (id int primary key) engine = innodb key_block_size = 0;
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 0. Valid values are [1, 2, 4, 8, 16]
Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 0. Valid values are [1, 2, 4, 8, 16]
Error 1005 Can't create table 'test.t1' (errno: 1478)
create table t2 (id int primary key) engine = innodb key_block_size = 9;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t3 (id int primary key) engine = innodb key_block_size = 1;
create table t4 (id int primary key) engine = innodb key_block_size = 2;
@ -233,30 +233,30 @@ key_block_size = 8 row_format = compressed;
create table t2 (id int primary key) engine = innodb
key_block_size = 8 row_format = redundant;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t3 (id int primary key) engine = innodb
key_block_size = 8 row_format = compact;
ERROR HY000: Can't create table 'test.t3' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t3' (errno: 1478)
create table t4 (id int primary key) engine = innodb
key_block_size = 8 row_format = dynamic;
ERROR HY000: Can't create table 'test.t4' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t4' (errno: 1478)
create table t5 (id int primary key) engine = innodb
key_block_size = 8 row_format = default;
ERROR HY000: Can't create table 'test.t5' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t5' (errno: 1478)
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
@ -266,26 +266,26 @@ drop table t1;
create table t1 (id int primary key) engine = innodb
key_block_size = 9 row_format = redundant;
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
Error 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t1' (errno: 1478)
create table t2 (id int primary key) engine = innodb
key_block_size = 9 row_format = compact;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t2 (id int primary key) engine = innodb
key_block_size = 9 row_format = dynamic;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
Error 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t2' (errno: 1478)
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
@ -293,45 +293,45 @@ table_schema table_name row_format
set global innodb_file_per_table = off;
create table t1 (id int primary key) engine = innodb key_block_size = 1;
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t1' (errno: 1478)
create table t2 (id int primary key) engine = innodb key_block_size = 2;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t3 (id int primary key) engine = innodb key_block_size = 4;
ERROR HY000: Can't create table 'test.t3' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t3' (errno: 1478)
create table t4 (id int primary key) engine = innodb key_block_size = 8;
ERROR HY000: Can't create table 'test.t4' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t4' (errno: 1478)
create table t5 (id int primary key) engine = innodb key_block_size = 16;
ERROR HY000: Can't create table 'test.t5' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t5' (errno: 1478)
create table t6 (id int primary key) engine = innodb row_format = compressed;
ERROR HY000: Can't create table 'test.t6' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.
Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.
Error 1005 Can't create table 'test.t6' (errno: 1478)
create table t7 (id int primary key) engine = innodb row_format = dynamic;
ERROR HY000: Can't create table 'test.t7' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table.
Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table.
Error 1005 Can't create table 'test.t7' (errno: 1478)
create table t8 (id int primary key) engine = innodb row_format = compact;
create table t9 (id int primary key) engine = innodb row_format = redundant;
@ -345,45 +345,45 @@ set global innodb_file_per_table = on;
set global innodb_file_format = `0`;
create table t1 (id int primary key) engine = innodb key_block_size = 1;
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t1' (errno: 1478)
create table t2 (id int primary key) engine = innodb key_block_size = 2;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t3 (id int primary key) engine = innodb key_block_size = 4;
ERROR HY000: Can't create table 'test.t3' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t3' (errno: 1478)
create table t4 (id int primary key) engine = innodb key_block_size = 8;
ERROR HY000: Can't create table 'test.t4' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t4' (errno: 1478)
create table t5 (id int primary key) engine = innodb key_block_size = 16;
ERROR HY000: Can't create table 'test.t5' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t5' (errno: 1478)
create table t6 (id int primary key) engine = innodb row_format = compressed;
ERROR HY000: Can't create table 'test.t6' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope.
Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t6' (errno: 1478)
create table t7 (id int primary key) engine = innodb row_format = dynamic;
ERROR HY000: Can't create table 'test.t7' (errno: 1478)
show errors;
show warnings;
Level Code Message
Error 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope.
Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t7' (errno: 1478)
create table t8 (id int primary key) engine = innodb row_format = compact;
create table t9 (id int primary key) engine = innodb row_format = redundant;

View File

@ -3090,7 +3090,7 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction
commit;
drop table t1, t2, t3, t5, t6, t8, t9;
CREATE TABLE t1 (DB_ROW_ID int) engine=innodb;
ERROR HY000: Can't create table 'test.t1' (errno: -1)
ERROR 42000: Incorrect column name 'DB_ROW_ID'
CREATE TABLE t1 (
a BIGINT(20) NOT NULL,
PRIMARY KEY (a)

View File

@ -1,4 +1,2 @@
set @old_innodb_file_format=@@innodb_file_format;
set @old_innodb_file_per_table=@@innodb_file_per_table;
SET GLOBAL innodb_file_format='Barracuda';
SET GLOBAL innodb_file_per_table=ON;

View File

@ -1,14 +1,6 @@
create table bug44369 (DB_ROW_ID int) engine=innodb;
ERROR HY000: Can't create table 'test.bug44369' (errno: -1)
ERROR 42000: Incorrect column name 'DB_ROW_ID'
create table bug44369 (db_row_id int) engine=innodb;
ERROR HY000: Can't create table 'test.bug44369' (errno: -1)
show warnings;
Level Code Message
Warning 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)
ERROR 42000: Incorrect column name 'db_row_id'
create table bug44369 (db_TRX_Id int) engine=innodb;
ERROR HY000: Can't create table 'test.bug44369' (errno: -1)
show warnings;
Level Code Message
Warning 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)
ERROR 42000: Incorrect column name 'db_TRX_Id'

View File

@ -0,0 +1,7 @@
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);
CREATE INDEX bug44571c ON bug44571 (bar);
DROP TABLE bug44571;

View File

@ -0,0 +1,9 @@
SET foreign_key_checks=0;
CREATE TABLE t1 (id int, foreign key (id) references t2(id)) ENGINE=INNODB;
CREATE TABLE t2 (id int, foreign key (id) references t1(id)) ENGINE=INNODB;
SET foreign_key_checks=1;
SELECT COUNT(*) FROM information_schema.key_column_usage WHERE REFERENCED_TABLE_NAME in ('t1', 't2');
COUNT(*)
2
SET foreign_key_checks=0;
DROP TABLE t1, t2;

View File

@ -0,0 +1,24 @@
set @old_innodb_file_format_check=@@innodb_file_format_check;
select @old_innodb_file_format_check;
@old_innodb_file_format_check
Antelope
set global innodb_file_format_check = Barracuda;
select @@innodb_file_format_check;
@@innodb_file_format_check
Barracuda
set global innodb_file_format_check = DEFAULT;
select @@innodb_file_format_check;
@@innodb_file_format_check
Barracuda
set global innodb_file_format_check = @old_innodb_file_format_check;
select @@innodb_file_format_check;
@@innodb_file_format_check
Antelope
set global innodb_file_format_check = cheetah;
ERROR HY000: Incorrect arguments to SET
set global innodb_file_format_check = Bear;
ERROR HY000: Incorrect arguments to SET
set global innodb_file_format_check = on;
ERROR HY000: Incorrect arguments to SET
set global innodb_file_format_check = off;
ERROR HY000: Incorrect arguments to SET

View File

@ -1,4 +1,3 @@
set @old_innodb_file_format=@@innodb_file_format;
call mtr.add_suppression("InnoDB: invalid innodb_file_format_check value");
select @@innodb_file_format;
@@innodb_file_format
@ -32,8 +31,6 @@ select @@innodb_file_format_check;
@@innodb_file_format_check
Barracuda
set global innodb_file_format_check=default;
Warnings:
Warning 1210 Ignoring SET innodb_file_format=on
select @@innodb_file_format_check;
@@innodb_file_format_check
Barracuda
@ -44,5 +41,4 @@ ERROR HY000: Incorrect arguments to SET
select @@innodb_file_format_check;
@@innodb_file_format_check
Barracuda
set global innodb_file_format=@old_innodb_file_format;
set global innodb_file_format_check=Antelope;
set global innodb_file_format_check=antelope;

View File

@ -1,6 +1,5 @@
SET @old_innodb_file_format=@@innodb_file_format;
SET @old_innodb_file_per_table=@@innodb_file_per_table;
SET @old_innodb_file_format_check=@@innodb_file_format_check;
SET GLOBAL innodb_file_format='Barracuda';
SET GLOBAL innodb_file_per_table=ON;
DROP TABLE IF EXISTS `test1`;
@ -29,4 +28,4 @@ ALTER TABLE test1 ENGINE=MyISAM;
DROP TABLE test1;
SET GLOBAL innodb_file_format=@old_innodb_file_format;
SET GLOBAL innodb_file_per_table=@old_innodb_file_per_table;
SET GLOBAL innodb_file_format_check=@old_innodb_file_format_check;
set global innodb_file_format_check=Antelope;

View File

@ -11,7 +11,7 @@
-- disable_result_log
-- enable_warnings
SET @old_innodb_stats_sample_pages=@@innodb_stats_sample_pages;
let $sample_pages=`select @@innodb_stats_sample_pages`;
SET GLOBAL innodb_stats_sample_pages=0;
# check that the value has been adjusted to 1
@ -62,4 +62,4 @@ SET GLOBAL innodb_stats_sample_pages=16;
ANALYZE TABLE innodb_analyze;
DROP TABLE innodb_analyze;
SET GLOBAL innodb_stats_sample_pages=@old_innodb_stats_sample_pages;
EVAL SET GLOBAL innodb_stats_sample_pages=$sample_pages;

View File

@ -0,0 +1 @@
--loose-innodb_lock_wait_timeout=2

View 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;

View File

@ -1,6 +1,6 @@
-- source include/have_innodb.inc
SET @save_innodb_file_format_check=@@global.innodb_file_format_check;
let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
@ -404,6 +404,7 @@ create index t1u on t1 (u(1));
drop table t1;
eval set global innodb_file_per_table=$per_table;
eval set global innodb_file_format=$format;
eval set global innodb_file_format_check=$format;
#
# Test to check whether CREATE INDEX handles implicit foreign key
@ -541,4 +542,9 @@ disconnect b;
DROP TABLE t1;
SET GLOBAL innodb_file_format_check=@save_innodb_file_format_check;
#
# restore environment to the state it was before this test execution
#
-- disable_query_log
eval SET GLOBAL innodb_file_format_check=$innodb_file_format_check_orig;

View File

@ -1 +1 @@
--binlog_cache_size=32768 --innodb_lock_wait_timeout=1
--binlog_cache_size=32768 --loose_innodb_lock_wait_timeout=1

View File

@ -1 +1 @@
--innodb_lock_wait_timeout=2
--loose-innodb_lock_wait_timeout=2

View File

@ -1,2 +1 @@
--innodb-use-sys-malloc=true
--innodb-use-sys-malloc=true
--loose-innodb-use-sys-malloc=true

View File

@ -178,11 +178,11 @@ set innodb_strict_mode = on;
--error ER_CANT_CREATE_TABLE
create table t1 (id int primary key) engine = innodb key_block_size = 0;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb key_block_size = 9;
show errors;
show warnings;
create table t3 (id int primary key) engine = innodb key_block_size = 1;
@ -208,22 +208,22 @@ key_block_size = 8 row_format = compressed;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb
key_block_size = 8 row_format = redundant;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t3 (id int primary key) engine = innodb
key_block_size = 8 row_format = compact;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t4 (id int primary key) engine = innodb
key_block_size = 8 row_format = dynamic;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t5 (id int primary key) engine = innodb
key_block_size = 8 row_format = default;
show errors;
show warnings;
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
@ -233,17 +233,17 @@ drop table t1;
--error ER_CANT_CREATE_TABLE
create table t1 (id int primary key) engine = innodb
key_block_size = 9 row_format = redundant;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb
key_block_size = 9 row_format = compact;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb
key_block_size = 9 row_format = dynamic;
show errors;
show warnings;
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
@ -253,25 +253,25 @@ set global innodb_file_per_table = off;
--error ER_CANT_CREATE_TABLE
create table t1 (id int primary key) engine = innodb key_block_size = 1;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb key_block_size = 2;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t3 (id int primary key) engine = innodb key_block_size = 4;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t4 (id int primary key) engine = innodb key_block_size = 8;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t5 (id int primary key) engine = innodb key_block_size = 16;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t6 (id int primary key) engine = innodb row_format = compressed;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t7 (id int primary key) engine = innodb row_format = dynamic;
show errors;
show warnings;
create table t8 (id int primary key) engine = innodb row_format = compact;
create table t9 (id int primary key) engine = innodb row_format = redundant;
@ -285,25 +285,25 @@ set global innodb_file_format = `0`;
--error ER_CANT_CREATE_TABLE
create table t1 (id int primary key) engine = innodb key_block_size = 1;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb key_block_size = 2;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t3 (id int primary key) engine = innodb key_block_size = 4;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t4 (id int primary key) engine = innodb key_block_size = 8;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t5 (id int primary key) engine = innodb key_block_size = 16;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t6 (id int primary key) engine = innodb row_format = compressed;
show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table t7 (id int primary key) engine = innodb row_format = dynamic;
show errors;
show warnings;
create table t8 (id int primary key) engine = innodb row_format = compact;
create table t9 (id int primary key) engine = innodb row_format = redundant;

View File

@ -2270,7 +2270,7 @@ disconnect j;
drop table t1, t2, t3, t5, t6, t8, t9;
# bug 18934, "InnoDB crashes when table uses column names like DB_ROW_ID"
--error 1005
--error ER_WRONG_COLUMN_NAME
CREATE TABLE t1 (DB_ROW_ID int) engine=innodb;
#

View File

@ -9,7 +9,7 @@
-- disable_result_log
# set packet size and reconnect
SET @save_max_allowed_packet=@@global.max_allowed_packet;
let $max_packet=`select @@global.max_allowed_packet`;
SET @@global.max_allowed_packet=16777216;
--connect (newconn, localhost, root,,)
@ -33,4 +33,4 @@ SELECT f4, f8 FROM bug34300;
DROP TABLE bug34300;
disconnect newconn;
connection default;
SET @@global.max_allowed_packet=@save_max_allowed_packet;
EVAL SET @@global.max_allowed_packet=$max_packet;

View File

@ -4,9 +4,9 @@
#
-- source include/have_innodb.inc
set @old_innodb_file_format=@@innodb_file_format;
set @old_innodb_file_per_table=@@innodb_file_per_table;
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;
@ -1155,5 +1155,5 @@ DROP TABLE IF EXISTS table4;
DROP TABLE IF EXISTS table5;
DROP TABLE IF EXISTS table6;
set global innodb_file_format=@old_innodb_file_format;
set global innodb_file_per_table=@old_innodb_file_per_table;
EVAL SET GLOBAL innodb_file_format=$file_format;
EVAL SET GLOBAL innodb_file_per_table=$file_per_table;

View File

@ -13,9 +13,10 @@ SET storage_engine=InnoDB;
-- disable_query_log
-- disable_result_log
set @old_innodb_file_per_table=@@innodb_file_per_table;
set @old_innodb_file_format=@@innodb_file_format;
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;
@ -27,6 +28,6 @@ INSERT IGNORE INTO `table0` SET `col19` = '19940127002709', `col20` = 2383927.90
CHECK TABLE table0 EXTENDED;
DROP TABLE table0;
set global innodb_file_per_table=@old_innodb_file_per_table;
set global innodb_file_format=@old_innodb_file_format;
set global innodb_file_format_check=Antelope;
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;

View File

@ -1 +1 @@
--innodb_commit_concurrency=1
--loose_innodb_commit_concurrency=1

View File

@ -6,16 +6,12 @@
--source include/have_innodb.inc
# This create table operation should fail.
--error ER_CANT_CREATE_TABLE
--error ER_WRONG_COLUMN_NAME
create table bug44369 (DB_ROW_ID int) engine=innodb;
# This create should fail as well
--error ER_CANT_CREATE_TABLE
--error ER_WRONG_COLUMN_NAME
create table bug44369 (db_row_id int) engine=innodb;
show warnings;
--error ER_CANT_CREATE_TABLE
--error ER_WRONG_COLUMN_NAME
create table bug44369 (db_TRX_Id int) engine=innodb;
show warnings;

View File

@ -0,0 +1,13 @@
#
# 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);
ALTER TABLE bug44571 ADD INDEX bug44571b (bar);
CREATE INDEX bug44571c ON bug44571 (bar);
DROP TABLE bug44571;

View File

@ -0,0 +1,16 @@
# This is the test for bug 46676: mysqld got exception 0xc0000005
# It is reproducible with InnoDB plugin 1.0.4 + MySQL 5.1.37.
# But no longer reproducible after MySQL 5.1.38 (with plugin 1.0.5).
--source include/have_innodb.inc
SET foreign_key_checks=0;
CREATE TABLE t1 (id int, foreign key (id) references t2(id)) ENGINE=INNODB;
CREATE TABLE t2 (id int, foreign key (id) references t1(id)) ENGINE=INNODB;
SET foreign_key_checks=1;
# Server crashes
SELECT COUNT(*) FROM information_schema.key_column_usage WHERE REFERENCED_TABLE_NAME in ('t1', 't2');
SET foreign_key_checks=0;
DROP TABLE t1, t2;

View File

@ -0,0 +1,45 @@
# This is the unit test for bug *47167.
# It tests setting the global variable
# "innodb_file_format_check" with a
# user-Defined Variable.
--source include/have_innodb.inc
# Save the value (Antelope) in 'innodb_file_format_check' to
# 'old_innodb_file_format_check'
set @old_innodb_file_format_check=@@innodb_file_format_check;
# @old_innodb_file_format_check shall have the value of 'Antelope'
select @old_innodb_file_format_check;
# Reset the value in 'innodb_file_format_check' to 'Barracuda'
set global innodb_file_format_check = Barracuda;
select @@innodb_file_format_check;
# Set 'innodb_file_format_check' to its default value, which
# is the latest file format supported in the current release.
set global innodb_file_format_check = DEFAULT;
select @@innodb_file_format_check;
# Put the saved value back to 'innodb_file_format_check'
set global innodb_file_format_check = @old_innodb_file_format_check;
# Check whether 'innodb_file_format_check' get its original value.
select @@innodb_file_format_check;
# Following are negative tests, all should fail.
--disable_warnings
--error ER_WRONG_ARGUMENTS
set global innodb_file_format_check = cheetah;
--error ER_WRONG_ARGUMENTS
set global innodb_file_format_check = Bear;
--error ER_WRONG_ARGUMENTS
set global innodb_file_format_check = on;
--error ER_WRONG_ARGUMENTS
set global innodb_file_format_check = off;
--enable_warnings

View File

@ -1,5 +1,4 @@
-- source include/have_innodb.inc
set @old_innodb_file_format=@@innodb_file_format;
call mtr.add_suppression("InnoDB: invalid innodb_file_format_check value");
@ -29,6 +28,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=@old_innodb_file_format;
set global innodb_file_format_check=Antelope;
set global innodb_file_format_check=antelope;

View File

@ -109,19 +109,18 @@ SELECT * FROM ```t'\"_str` WHERE c1 = '3' FOR UPDATE;
-- send
SELECT * FROM ```t'\"_str` WHERE c1 = '4' FOR UPDATE;
-- connection con_verify_innodb_locks
# Loop, giving time for the above 2 queries to execute before continuing.
# Without this, it sometimes happens that the SELECT FROM innodb_locks
# executes before some of them, resulting in less than expected number
# of rows being selected from innodb_locks.
SET @counter := 0;
while (`SELECT (@counter := @counter + 1) <= 50 AND COUNT(*) != 14 FROM INFORMATION_SCHEMA.INNODB_LOCKS`)
{
sleep 0.1;
}
-- enable_result_log
-- connection con_verify_innodb_locks
# Wait for the above queries to execute before continuing.
# Without this, it sometimes happens that the SELECT from innodb_locks
# executes before some of them, resulting in less than expected number
# of rows being selected from innodb_locks. If there is a bug and there
# are no 14 rows in innodb_locks then this test will fail with timeout.
let $count = 14;
let $table = INFORMATION_SCHEMA.INNODB_LOCKS;
-- source include/wait_until_rows_count.inc
# the above enables the query log, re-disable it
-- disable_query_log
SELECT lock_mode, lock_type, lock_table, lock_index, lock_rec, lock_data
FROM INFORMATION_SCHEMA.INNODB_LOCKS ORDER BY lock_data;

View File

@ -2,7 +2,7 @@
SET @old_innodb_file_format=@@innodb_file_format;
SET @old_innodb_file_per_table=@@innodb_file_per_table;
SET @old_innodb_file_format_check=@@innodb_file_format_check;
let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
SET GLOBAL innodb_file_format='Barracuda';
SET GLOBAL innodb_file_per_table=ON;
@ -45,4 +45,4 @@ ALTER TABLE test1 ENGINE=MyISAM;
DROP TABLE test1;
SET GLOBAL innodb_file_format=@old_innodb_file_format;
SET GLOBAL innodb_file_per_table=@old_innodb_file_per_table;
SET GLOBAL innodb_file_format_check=@old_innodb_file_format_check;
eval set global innodb_file_format_check=$innodb_file_format_check_orig;

View File

@ -13,28 +13,33 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# This is the CMakeLists for InnoDB Plugin
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
# 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)
# Check type sizes
include(CheckTypeSize)
# Currently, the checked results are not used.
CHECK_TYPE_SIZE(int SIZEOF_INT)
CHECK_TYPE_SIZE(long SIZEOF_LONG)
CHECK_TYPE_SIZE(void* SIZEOF_VOID_P)
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")
ADD_DEFINITIONS(-D_WIN32 -D_LIB -DMYSQL_SERVER)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib
${CMAKE_SOURCE_DIR}/storage/xtradb/include
${CMAKE_SOURCE_DIR}/storage/xtradb/handler
# Include directories under innobase
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/xtradb/include
${CMAKE_SOURCE_DIR}/storage/xtradb/handler)
# Include directories under mysql
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/sql
${CMAKE_SOURCE_DIR}/regex
${CMAKE_SOURCE_DIR}/zlib
${CMAKE_SOURCE_DIR}/extra/yassl/include)
# Removing compiler optimizations for innodb/mem/* files on 64-bit Windows
@ -77,5 +82,20 @@ 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 -DIB_HAVE_PAUSE_INSTRUCTION)
IF (MYSQL_VERSION_ID GREATER "50137")
MYSQL_STORAGE_ENGINE(INNOBASE)
# Use ha_innodb for plugin name, if plugin is built
GET_TARGET_PROPERTY(LIB_LOCATION ha_innobase LOCATION)
IF(LIB_LOCATION)
SET_TARGET_PROPERTIES(ha_innobase PROPERTIES OUTPUT_NAME ha_innodb)
ENDIF(LIB_LOCATION)
ELSE (MYSQL_VERSION_ID GREATER "50137")
IF (NOT SOURCE_SUBLIBS)
ADD_DEFINITIONS(-D_WIN32 -DMYSQL_SERVER)
ADD_LIBRARY(innobase STATIC ${INNOBASE_SOURCES})
# Require mysqld_error.h, which is built as part of the GenError
ADD_DEPENDENCIES(innobase GenError)
ENDIF (NOT SOURCE_SUBLIBS)
ENDIF (MYSQL_VERSION_ID GREATER "50137")

View File

@ -1,3 +1,319 @@
2009-11-20 The InnoDB Team
* handler/ha_innodb.cc:
Add a workaround to prevent a crash due to Bug#45961 DDL on
partitioned innodb tables leaves data dictionary in an inconsistent
state
2009-11-19 The InnoDB Team
* btr/btr0btr.c:
Fix Bug#48469 when innodb tablespace is configured too small, crash
and corruption!
2009-11-19 The InnoDB Team
* data/data0type.c:
Fix Bug#48526 Data type for float and double is incorrectly reported
in InnoDB table monitor
2009-11-19 The InnoDB Team
* CMakeLists.txt:
Fix Bug#48317 cannot build innodb as static library
2009-11-18 The InnoDB Team
* handler/handler0alter.cc:
Fix Bug#48782 On lock wait timeout, CREATE INDEX (creating primary key)
attempts DROP TABLE
2009-11-17 The InnoDB Team
* handler/ha_innodb.cc, mysql-test/innodb.result,
mysql-test/innodb.test, mysql-test/innodb_bug44369.result,
mysql-test/innodb_bug44369.test, mysql-test/patches/innodb-index.diff,
row/row0mysql.c:
Report duplicate table names to the client connection, not to the
error log.
2009-11-12 The InnoDB Team
* handler/ha_innodb.cc, include/db0err.h, row/row0merge.c,
row/row0mysql.c:
Allow CREATE INDEX to be interrupted.
Also, when CHECK TABLE is interrupted, report ER_QUERY_INTERRUPTED.
2009-11-11 The InnoDB Team
* handler/ha_innodb.cc, mysql-test/innodb_bug47167.result,
mysql-test/innodb_bug47167.test, mysql-test/innodb_file_format.result:
Fix Bug#47167 "set global innodb_file_format_check" cannot set value
by User-Defined Variable
2009-11-11 The InnoDB Team
* include/os0file.h, os/os0file.c:
Fix Bug#3139 Mysql crashes: 'windows error 995' after several selects
on a large DB
2009-11-04 The InnoDB Team
* handler/ha_innodb.cc:
Fix Bug#32430 'show innodb status' causes errors
Invalid (old?) table or database name in logs
2009-11-02 The InnoDB Team
* btr/btr0sea.c, buf/buf0buf.c, dict/dict0dict.c, fil/fil0fil.c,
ibuf/ibuf0ibuf.c, include/btr0sea.h, include/dict0dict.h,
include/fil0fil.h, include/ibuf0ibuf.h, include/lock0lock.h,
include/log0log.h, include/log0recv.h, include/mem0mem.h,
include/mem0pool.h, include/os0file.h, include/pars0pars.h,
include/srv0srv.h, include/thr0loc.h, include/trx0i_s.h,
include/trx0purge.h, include/trx0rseg.h, include/trx0sys.h,
include/trx0undo.h, include/usr0sess.h, lock/lock0lock.c,
log/log0log.c, log/log0recv.c, mem/mem0dbg.c, mem/mem0pool.c,
os/os0file.c, os/os0sync.c, os/os0thread.c, pars/lexyy.c,
pars/pars0lex.l, que/que0que.c, srv/srv0srv.c, srv/srv0start.c,
sync/sync0arr.c, sync/sync0sync.c, thr/thr0loc.c, trx/trx0i_s.c,
trx/trx0purge.c, trx/trx0rseg.c, trx/trx0sys.c, trx/trx0undo.c,
usr/usr0sess.c, ut/ut0mem.c:
Fix Bug #45992 innodb memory not freed after shutdown
Fix Bug #46656 InnoDB plugin: memory leaks (Valgrind)
2009-10-29 The InnoDB Team
* handler/ha_innodb.cc, mysql-test/innodb-autoinc.result,
mysql-test/innodb-autoinc.test:
Fix Bug#47125 auto_increment start value is ignored if an index is
created and engine=innodb
2009-10-29 The InnoDB Team
* handler/ha_innodb.cc, mysql-test/innodb_bug47777.result,
mysql-test/innodb_bug47777.test:
Fix Bug#47777 innodb dies with spatial pk: Failing assertion: buf <=
original_buf + buf_len
2009-10-29 The InnoDB Team
* handler/ha_innodb.cc:
Fix Bug#38996 Race condition in ANALYZE TABLE
2009-10-29 The InnoDB Team
* handler/ha_innodb.cc:
Fix bug#42383: Can't create table 'test.bug39438'
2009-10-29 The InnoDB Team
* os/os0proc.c:
Fix Bug#48237 Error handling in os_mem_alloc_large appears to
be incorrect
2009-10-29 The InnoDB Team
* buf/buf0buf.c, buf/buf0lru.c, include/buf0buf.h, include/buf0buf.ic:
Fix corruption of the buf_pool->LRU_old list and improve debug
assertions.
2009-10-28 The InnoDB Team
* srv/srv0start.c:
Fix Bug#41490 After enlargement of InnoDB page size, the error message
become inaccurate
2009-10-26 The InnoDB Team
* row/row0ins.c:
When allocating a data tuple, zero out the system fields in order
to avoid Valgrind warnings about uninitialized fields in
dtuple_validate().
2009-10-22 The InnoDB Team
* handler/ha_innodb.cc, mysql-test/innodb-zip.result,
mysql-test/innodb-zip.test, mysql-test/innodb_bug44369.result,
mysql-test/innodb_bug44369.test:
Fix Bug#47233 Innodb calls push_warning(MYSQL_ERROR::WARN_LEVEL_ERROR)
2009-10-19 The InnoDB Team
* mysql-test/innodb_information_schema.test:
Fix Bug#47808 innodb_information_schema.test fails when run under
valgrind
2009-10-15 The InnoDB Team
* include/page0page.ic:
Fix Bug#47058 Failure to compile innodb_plugin on solaris 10u7 + spro
cc/CC 5.10
2009-10-13 The InnoDB Team
* buf/buf0flu.c:
Call fsync() on datafiles after a batch of pages is written to disk
even when skip_innodb_doublewrite is set.
2009-10-05 The InnoDB Team
* buf/buf0buf.c:
Do not invalidate buffer pool while an LRU batch is active. Added code
to buf_pool_invalidate() to wait for the running batches to finish.
2009-10-01 The InnoDB Team
* handler/ha_innodb.cc:
Fix Bug#47763 typo in error message: Failed to open table %s after %lu
attemtps.
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,

View File

@ -22,7 +22,7 @@ MYSQLLIBdir= $(pkglibdir)
pkgplugindir= $(pkglibdir)/plugin
INCLUDES= -I$(top_srcdir)/include -I$(top_builddir)/include \
-I$(top_srcdir)/regex \
-I$(top_srcdir)/storage/xtradb/include \
-I$(srcdir)/include \
-I$(top_srcdir)/sql \
-I$(srcdir) @ZLIB_INCLUDES@
@ -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 \

View File

@ -790,14 +790,21 @@ btr_create(
} else {
/* It is a non-ibuf tree: create a file segment for leaf
pages */
fseg_create(space, page_no,
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr);
if (!fseg_create(space, page_no,
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) {
/* Not enough space for new segment, free root
segment before return. */
btr_free_root(space, zip_size, page_no, mtr);
return(FIL_NULL);
}
/* The fseg create acquires a second latch on the page,
therefore we must declare it: */
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 +1018,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 +1928,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);

View File

@ -175,6 +175,21 @@ btr_search_sys_create(
btr_search_sys->hash_index = ha_create(hash_size, 0, 0);
}
/*****************************************************************//**
Frees the adaptive search system at a database shutdown. */
UNIV_INTERN
void
btr_search_sys_free(void)
/*=====================*/
{
mem_free(btr_search_latch_temp);
btr_search_latch_temp = NULL;
mem_heap_free(btr_search_sys->hash_index->heap);
hash_table_free(btr_search_sys->hash_index);
mem_free(btr_search_sys);
btr_search_sys = NULL;
}
/********************************************************************//**
Disable the adaptive hash search system and empty the index. */
UNIV_INTERN
@ -957,7 +972,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);

View File

@ -531,11 +531,10 @@ buf_buddy_relocate(
UNIV_MEM_ASSERT_W(src, size);
mutex = buf_page_get_mutex_enter(bpage);
ut_a(mutex);
mutex_enter(&zip_free_mutex);
if (buf_page_can_relocate(bpage)) {
if (mutex && buf_page_can_relocate(bpage)) {
/* Relocate the compressed page. */
ut_a(bpage->zip.data == src);
memcpy(dst, src, size);
@ -563,7 +562,9 @@ success:
rw_lock_x_unlock(&page_hash_latch);
}
if (mutex) {
mutex_exit(mutex);
}
} else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) {
/* This must be a buf_page_t object. */
UNIV_MEM_ASSERT_RW(src, size);

View File

@ -51,6 +51,40 @@ Created 11/5/1995 Heikki Tuuri
#include "dict0dict.h"
#include "log0recv.h"
#include "page0zip.h"
#include "trx0trx.h"
/* prototypes for new functions added to ha_innodb.cc */
trx_t* innobase_get_trx();
inline void _increment_page_get_statistics(buf_block_t* block, trx_t* trx)
{
ulint block_hash;
ulint block_hash_byte;
byte block_hash_offset;
ut_ad(block);
if (!innobase_get_slow_log() || !trx || !trx->take_stats)
return;
if (!trx->distinct_page_access_hash) {
trx->distinct_page_access_hash = mem_alloc(DPAH_SIZE);
memset(trx->distinct_page_access_hash, 0, DPAH_SIZE);
}
block_hash = ut_hash_ulint((block->page.space << 20) + block->page.space +
block->page.offset, DPAH_SIZE << 3);
block_hash_byte = block_hash >> 3;
block_hash_offset = (byte) block_hash & 0x07;
if (block_hash_byte < 0 || block_hash_byte >= DPAH_SIZE)
fprintf(stderr, "!!! block_hash_byte = %lu block_hash_offset = %lu !!!\n", block_hash_byte, block_hash_offset);
if (block_hash_offset < 0 || block_hash_offset > 7)
fprintf(stderr, "!!! block_hash_byte = %lu block_hash_offset = %lu !!!\n", block_hash_byte, block_hash_offset);
if ((trx->distinct_page_access_hash[block_hash_byte] & ((byte) 0x01 << block_hash_offset)) == 0)
trx->distinct_page_access++;
trx->distinct_page_access_hash[block_hash_byte] |= (byte) 0x01 << block_hash_offset;
return;
}
/*
IMPLEMENTATION OF THE BUFFER POOL
@ -845,16 +879,35 @@ buf_chunk_not_freed(
block = chunk->blocks;
for (i = chunk->size; i--; block++) {
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);
if (buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE
&& !buf_flush_ready_for_replace(&block->page)) {
ready = buf_flush_ready_for_replace(&block->page);
mutex_exit(&block->mutex);
if (!ready) {
return(block);
}
mutex_exit(&block->mutex);
break;
}
}
return(NULL);
@ -985,8 +1038,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(). */
@ -1024,7 +1075,11 @@ buf_pool_free(void)
os_mem_free_large(chunk->mem, chunk->mem_size);
}
buf_pool->n_chunks = 0;
mem_free(buf_pool->chunks);
hash_table_free(buf_pool->page_hash);
hash_table_free(buf_pool->zip_hash);
mem_free(buf_pool);
buf_pool = NULL;
}
/********************************************************************//**
@ -1171,10 +1226,15 @@ buf_relocate(
#ifdef UNIV_LRU_DEBUG
/* buf_pool->LRU_old must be the first item in the LRU list
whose "old" flag is set. */
ut_a(buf_pool->LRU_old->old);
ut_a(!UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)
|| !UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)->old);
ut_a(!UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)
|| UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)->old);
} else {
/* Check that the "old" flag is consistent in
the block and its neighbours. */
buf_page_set_old(dpage, buf_page_is_old(dpage));
#endif /* UNIV_LRU_DEBUG */
}
@ -1509,36 +1569,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();
mutex_enter(&LRU_list_mutex);
/* 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();
mutex_exit(&LRU_list_mutex);
}
}
/********************************************************************//**
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
@ -1557,6 +1590,42 @@ buf_page_make_young(
mutex_exit(&LRU_list_mutex);
}
/********************************************************************//**
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();
mutex_enter(&LRU_list_mutex);
buf_LRU_make_block_young(bpage);
//buf_pool_mutex_exit();
mutex_exit(&LRU_list_mutex);
} else if (!access_time) {
ulint time_ms = ut_time_ms();
mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
//buf_pool_mutex_enter();
if (block_mutex) {
buf_page_set_accessed(bpage, time_ms);
mutex_exit(block_mutex);
}
//buf_pool_mutex_exit();
}
}
/********************************************************************//**
Resets the check_index_page_at_flush field of a page if found in the buffer
pool. */
@ -1696,11 +1765,20 @@ buf_page_get_zip(
buf_page_t* bpage;
mutex_t* block_mutex;
ibool must_read;
unsigned access_time;
trx_t* trx = NULL;
ulint sec;
ulint ms;
ib_uint64_t start_time;
ib_uint64_t finish_time;
#ifndef UNIV_LOG_DEBUG
ut_ad(!ibuf_inside());
#endif
buf_pool->n_page_gets++;
if (innobase_get_slow_log()) {
trx = innobase_get_trx();
}
buf_pool->stat.n_page_gets++;
for (;;) {
//buf_pool_mutex_enter();
@ -1716,7 +1794,7 @@ lookup:
//buf_pool_mutex_exit();
rw_lock_s_unlock(&page_hash_latch);
buf_read_page(space, zip_size, offset);
buf_read_page(space, zip_size, offset, trx);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 37 || buf_validate());
@ -1770,14 +1848,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);
@ -1793,6 +1870,13 @@ got_block:
/* Let us wait until the read operation
completes */
if (innobase_get_slow_log() && trx && trx->take_stats)
{
ut_usectime(&sec, &ms);
start_time = (ib_uint64_t)sec * 1000000 + ms;
} else {
start_time = 0;
}
for (;;) {
enum buf_io_fix io_fix;
@ -1807,6 +1891,12 @@ got_block:
break;
}
}
if (innobase_get_slow_log() && trx && trx->take_stats && start_time)
{
ut_usectime(&sec, &ms);
finish_time = (ib_uint64_t)sec * 1000000 + ms;
trx->io_reads_wait_timer += (ulint)(finish_time - start_time);
}
}
#ifdef UNIV_IBUF_COUNT_DEBUG
@ -1870,7 +1960,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);
}
@ -2058,10 +2148,15 @@ 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;
mutex_t* block_mutex;
trx_t* trx = NULL;
ulint sec;
ulint ms;
ib_uint64_t start_time;
ib_uint64_t finish_time;
ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH)
@ -2075,14 +2170,16 @@ 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++;
if (innobase_get_slow_log()) {
trx = innobase_get_trx();
}
buf_pool->stat.n_page_gets++;
loop:
block = guess;
//buf_pool_mutex_enter();
if (block) {
block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
ut_a(block_mutex);
/* If the guess is a compressed page descriptor that
has been allocated by buf_buddy_alloc(), it may have
@ -2092,7 +2189,9 @@ loop:
the guess may be pointing to a buffer pool chunk that
has been released when resizing the buffer pool. */
if (!buf_block_is_uncompressed(block)
if (!block_mutex) {
block = guess = NULL;
} else if (!buf_block_is_uncompressed(block)
|| offset != block->page.offset
|| space != block->page.space
|| buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
@ -2127,7 +2226,7 @@ loop2:
return(NULL);
}
buf_read_page(space, zip_size, offset);
buf_read_page(space, zip_size, offset, trx);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 37 || buf_validate());
@ -2351,17 +2450,17 @@ wait_until_unfixed:
UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page);
buf_block_buf_fix_inc(block, file, line);
//buf_pool_mutex_exit();
//mutex_exit(&block->mutex);
/* Check if this is the first access to the page */
accessed = buf_page_is_accessed(&block->page);
buf_page_set_accessed(&block->page, TRUE);
access_time = buf_page_is_accessed(&block->page);
//buf_pool_mutex_exit();
mutex_exit(block_mutex);
buf_block_make_young(&block->page);
buf_page_set_accessed_make_young(&block->page, access_time);
#ifdef UNIV_DEBUG_FILE_ACCESSES
ut_a(!block->page.file_page_was_freed);
@ -2379,6 +2478,13 @@ wait_until_unfixed:
/* Let us wait until the read operation
completes */
if (innobase_get_slow_log() && trx && trx->take_stats)
{
ut_usectime(&sec, &ms);
start_time = (ib_uint64_t)sec * 1000000 + ms;
} else {
start_time = 0;
}
for (;;) {
enum buf_io_fix io_fix;
@ -2393,6 +2499,12 @@ wait_until_unfixed:
break;
}
}
if (innobase_get_slow_log() && trx && trx->take_stats && start_time)
{
ut_usectime(&sec, &ms);
finish_time = (ib_uint64_t)sec * 1000000 + ms;
trx->io_reads_wait_timer += (ulint)(finish_time - start_time);
}
}
fix_type = MTR_MEMO_BUF_FIX;
@ -2414,17 +2526,21 @@ 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 */
buf_read_ahead_linear(space, zip_size, offset);
buf_read_ahead_linear(space, zip_size, offset, trx);
}
#ifdef UNIV_IBUF_COUNT_DEBUG
ut_a(ibuf_count_get(buf_block_get_space(block),
buf_block_get_page_no(block)) == 0);
#endif
if (innobase_get_slow_log()) {
_increment_page_get_statistics(block, trx);
}
return(block);
}
@ -2444,9 +2560,10 @@ 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;
trx_t* trx = NULL;
ut_ad(mtr && block);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
@ -2461,14 +2578,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),
@ -2520,21 +2639,28 @@ 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 (innobase_get_slow_log()) {
trx = innobase_get_trx();
}
if (UNIV_UNLIKELY(!access_time)) {
/* In the case of a first access, try to apply linear
read-ahead */
buf_read_ahead_linear(buf_block_get_space(block),
buf_block_get_zip_size(block),
buf_block_get_page_no(block));
buf_block_get_page_no(block), trx);
}
#ifdef UNIV_IBUF_COUNT_DEBUG
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++;
if (innobase_get_slow_log()) {
_increment_page_get_statistics(block, trx);
}
return(TRUE);
}
@ -2556,6 +2682,7 @@ buf_page_get_known_nowait(
{
ibool success;
ulint fix_type;
trx_t* trx = NULL;
ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
@ -2581,8 +2708,24 @@ 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();
mutex_enter(&LRU_list_mutex);
buf_LRU_make_block_young(&block->page);
//buf_pool_mutex_exit();
mutex_exit(&LRU_list_mutex);
} 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();
mutex_enter(&block->mutex);
buf_page_set_accessed(&block->page, time_ms);
//buf_pool_mutex_exit();
mutex_exit(&block->mutex);
}
ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
@ -2621,7 +2764,12 @@ 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++;
if (innobase_get_slow_log()) {
trx = innobase_get_trx();
_increment_page_get_statistics(block, trx);
}
return(TRUE);
}
@ -2700,7 +2848,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),
@ -2719,10 +2867,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);
@ -3044,6 +3192,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);
@ -3095,7 +3244,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;
@ -3132,13 +3281,13 @@ buf_page_create(
rw_lock_x_unlock(&block->lock);
}
buf_page_set_accessed(&block->page, time_ms);
//buf_pool_mutex_exit();
mutex_exit(&LRU_list_mutex);
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:
@ -3355,7 +3504,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,
@ -3380,7 +3529,7 @@ corrupt:
BUF_IO_WRITE);
}
buf_pool->n_pages_written++;
buf_pool->stat.n_pages_written++;
break;
@ -3412,6 +3561,31 @@ buf_pool_invalidate(void)
/*=====================*/
{
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());
@ -3427,6 +3601,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();
mutex_exit(&LRU_list_mutex);
}
@ -3706,6 +3888,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),
@ -3716,8 +3899,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 */
@ -3927,10 +4113,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();
mutex_enter(&LRU_list_mutex);
@ -3943,13 +4128,15 @@ buf_print_io(
"Buffer pool size, bytes %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) size * UNIV_PAGE_SIZE,
(ulong) buf_pool->curr_size,
(ulong) buf_pool->curr_size * UNIV_PAGE_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]
@ -3961,37 +4148,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. */
@ -4003,6 +4219,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();
mutex_exit(&LRU_list_mutex);
mutex_exit(&free_list_mutex);
@ -4018,10 +4235,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;
}
/*********************************************************************//**

View File

@ -330,6 +330,28 @@ buf_flush_write_complete(
}
}
/********************************************************************//**
Flush a batch of writes to the datafiles that have already been
written by the OS. */
static
void
buf_flush_sync_datafiles(void)
/*==========================*/
{
/* Wake possible simulated aio thread to actually post the
writes to the operating system */
os_aio_simulated_wake_handler_threads();
/* Wait that all async writes to tablespaces have been posted to
the OS */
os_aio_wait_until_no_pending_writes();
/* Now we flush the data to disk (for example, with fsync) */
fil_flush_file_spaces(FIL_TABLESPACE);
return;
}
/********************************************************************//**
Flushes possible buffered writes from the doublewrite memory buffer to disk,
and also wakes up the aio thread if simulated aio is used. It is very
@ -347,8 +369,8 @@ buf_flush_buffered_writes(void)
ulint i;
if (!srv_use_doublewrite_buf || trx_doublewrite == NULL) {
os_aio_simulated_wake_handler_threads();
/* Sync the writes to the disk. */
buf_flush_sync_datafiles();
return;
}
@ -556,22 +578,10 @@ flush:
buf_LRU_stat_inc_io();
}
/* Wake possible simulated aio thread to actually post the
writes to the operating system */
os_aio_simulated_wake_handler_threads();
/* Wait that all async writes to tablespaces have been posted to
the OS */
os_aio_wait_until_no_pending_writes();
/* Now we flush the data to disk (for example, with fsync) */
fil_flush_file_spaces(FIL_TABLESPACE);
/* Sync the writes to the disk. */
buf_flush_sync_datafiles();
/* We can now reuse the doublewrite memory buffer: */
trx_doublewrite->first_free = 0;
mutex_exit(&(trx_doublewrite->mutex));
@ -994,9 +1004,7 @@ buf_flush_try_neighbors(
|| buf_page_is_old(bpage)) {
mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
ut_a(block_mutex);
if (buf_flush_ready_for_flush(bpage, flush_type)
if (block_mutex && buf_flush_ready_for_flush(bpage, flush_type)
&& (i == offset || !bpage->buf_fix_count)) {
/* We only try to flush those
neighbors != offset where the buf fix count is
@ -1012,7 +1020,7 @@ buf_flush_try_neighbors(
//buf_pool_mutex_enter();
rw_lock_s_lock(&page_hash_latch);
} else {
} else if (block_mutex) {
mutex_exit(block_mutex);
}
}
@ -1050,6 +1058,7 @@ buf_flush_batch(
min_n), otherwise ignored */
{
buf_page_t* bpage;
buf_page_t* prev_bpage = NULL;
ulint page_count = 0;
ulint old_page_count;
ulint space;
@ -1103,6 +1112,9 @@ flush_next:
mutex_enter(&flush_list_mutex);
remaining = UT_LIST_GET_LEN(buf_pool->flush_list);
bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
if (bpage) {
prev_bpage = UT_LIST_GET_PREV(flush_list, bpage);
}
mutex_exit(&flush_list_mutex);
if (!bpage
|| bpage->oldest_modification >= lsn_limit) {
@ -1123,11 +1135,14 @@ flush_next:
mutex_t*block_mutex = buf_page_get_mutex_enter(bpage);
ibool ready;
ut_a(buf_page_in_file(bpage));
//ut_a(buf_page_in_file(bpage));
ut_a(block_mutex);
if (block_mutex) {
ready = buf_flush_ready_for_flush(bpage, flush_type);
mutex_exit(block_mutex);
} else {
ready = FALSE;
}
if (ready) {
space = buf_page_get_space(bpage);
@ -1162,6 +1177,13 @@ flush_next:
mutex_enter(&flush_list_mutex);
bpage = UT_LIST_GET_PREV(flush_list, bpage);
//ut_ad(!bpage || bpage->in_flush_list); /* optimistic */
if (bpage != prev_bpage) {
/* the search may warp.. retrying */
bpage = NULL;
}
if (bpage) {
prev_bpage = UT_LIST_GET_PREV(flush_list, bpage);
}
mutex_exit(&flush_list_mutex);
remaining--;
}
@ -1271,13 +1293,13 @@ buf_flush_LRU_recommendation(void)
}
block_mutex = buf_page_get_mutex_enter(bpage);
ut_a(block_mutex);
if (buf_flush_ready_for_replace(bpage)) {
if (block_mutex && buf_flush_ready_for_replace(bpage)) {
n_replaceable++;
}
if (block_mutex) {
mutex_exit(block_mutex);
}
distance++;

View File

@ -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),
@ -255,9 +268,12 @@ scan_again:
mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
buf_page_t* prev_bpage;
ut_a(block_mutex);
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
if (!block_mutex) {
goto next_page;
}
ut_a(buf_page_in_file(bpage));
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE
@ -360,9 +376,13 @@ scan_again:
ut_a(buf_page_in_file(bpage));
ut_a(block_mutex);
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
if (!block_mutex) {
bpage = prev_bpage;
continue;
}
if (buf_page_get_space(bpage) == id) {
if (bpage->buf_fix_count > 0
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
@ -450,45 +470,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();
mutex_enter(&LRU_list_mutex);
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();
mutex_exit(&LRU_list_mutex);
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();
mutex_exit(&LRU_list_mutex);
return(limit > len ? (limit - len) : 0);
}
/********************************************************************//**
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
UNIV_INTERN
@ -631,10 +612,13 @@ restart:
bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) {
enum buf_lru_free_block_status freed;
unsigned accessed;
mutex_t* block_mutex
= buf_page_get_mutex_enter(bpage);
ut_a(block_mutex);
if (!block_mutex) {
goto restart;
}
if (!bpage->in_LRU_list
|| !buf_page_in_file(bpage)) {
@ -645,11 +629,18 @@ restart:
ut_ad(buf_page_in_file(bpage));
ut_ad(bpage->in_LRU_list);
accessed = buf_page_is_accessed(bpage);
freed = buf_LRU_free_block(bpage, TRUE, NULL, have_LRU_mutex);
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:
@ -1027,8 +1018,10 @@ buf_LRU_old_adjust_len(void)
ut_a(buf_pool->LRU_old);
//ut_ad(buf_pool_mutex_own());
ut_ad(mutex_own(&LRU_list_mutex));
#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
@ -1040,34 +1033,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);
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++;
old_len = ++buf_pool->LRU_old_len;
buf_page_set_old(LRU_old, TRUE);
} 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_pool->LRU_old = UT_LIST_GET_NEXT(LRU, LRU_old);
old_len = --buf_pool->LRU_old_len;
buf_page_set_old(LRU_old, FALSE);
} else {
return;
}
@ -1092,12 +1090,13 @@ buf_LRU_old_init(void)
the adjust function to move the LRU_old pointer to the right
position */
bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
while (bpage != NULL) {
for (bpage = UT_LIST_GET_LAST(buf_pool->LRU); bpage != NULL;
bpage = UT_LIST_GET_PREV(LRU, bpage)) {
ut_ad(bpage->in_LRU_list);
buf_page_set_old(bpage, TRUE);
bpage = UT_LIST_GET_NEXT(LRU, bpage);
ut_ad(buf_page_in_file(bpage));
/* This loop temporarily violates the
assertions of buf_page_set_old(). */
bpage->old = TRUE;
}
buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU);
@ -1152,16 +1151,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++;
}
@ -1172,10 +1174,19 @@ buf_LRU_remove_block(
buf_unzip_LRU_remove_block_if_needed(bpage);
/* If the LRU list is so short that LRU_old not defined, return */
/* If the LRU list is so short that LRU_old is not defined,
clear the "old" flags and return */
if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) {
for (bpage = UT_LIST_GET_FIRST(buf_pool->LRU); bpage != NULL;
bpage = UT_LIST_GET_NEXT(LRU, bpage)) {
/* This loop temporarily violates the
assertions of buf_page_set_old(). */
bpage->old = FALSE;
}
buf_pool->LRU_old = NULL;
buf_pool->LRU_old_len = 0;
return;
}
@ -1227,8 +1238,6 @@ 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());
@ -1236,31 +1245,18 @@ buf_LRU_add_block_to_end_low(
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);
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_page_set_old(bpage, TRUE);
buf_pool->LRU_old_len++;
buf_LRU_old_adjust_len();
} else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) {
@ -1269,6 +1265,8 @@ buf_LRU_add_block_to_end_low(
defined: init it */
buf_LRU_old_init();
} else {
buf_page_set_old(bpage, buf_pool->LRU_old != NULL);
}
/* If this is a zipped block with decompressed frame as well
@ -1302,7 +1300,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
@ -1317,23 +1314,17 @@ 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;
}
bpage->in_LRU_list = TRUE;
buf_page_set_old(bpage, old);
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_page_set_old(bpage, old);
buf_LRU_old_adjust_len();
} else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) {
@ -1342,6 +1333,8 @@ buf_LRU_add_block_low(
defined: init it */
buf_LRU_old_init();
} else {
buf_page_set_old(bpage, buf_pool->LRU_old != NULL);
}
/* If this is a zipped block with decompressed frame as well
@ -1375,6 +1368,13 @@ buf_LRU_make_block_young(
/*=====================*/
buf_page_t* bpage) /*!< in: control block */
{
//ut_ad(buf_pool_mutex_own());
ut_ad(mutex_own(&LRU_list_mutex));
if (bpage->old) {
buf_pool->stat.n_pages_made_young++;
}
buf_LRU_remove_block(bpage);
buf_LRU_add_block_low(bpage, FALSE);
}
@ -1571,15 +1571,6 @@ not_freed:
buf_pool->LRU_old = b;
}
#ifdef UNIV_LRU_DEBUG
ut_a(prev_b->old
|| !UT_LIST_GET_NEXT(LRU, b)
|| UT_LIST_GET_NEXT(LRU, b)->old);
} else {
ut_a(!prev_b->old
|| !UT_LIST_GET_NEXT(LRU, b)
|| !UT_LIST_GET_NEXT(LRU, b)->old);
#endif /* UNIV_LRU_DEBUG */
}
lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
@ -1595,6 +1586,11 @@ not_freed:
defined: init it */
buf_LRU_old_init();
}
#ifdef UNIV_LRU_DEBUG
/* Check that the "old" flag is consistent
in the block and its neighbours. */
buf_page_set_old(b, buf_page_is_old(b));
#endif /* UNIV_LRU_DEBUG */
} else {
b->in_LRU_list = FALSE;
buf_LRU_add_block_low(b, buf_page_is_old(b));
@ -1985,6 +1981,52 @@ buf_LRU_block_free_hashed_page(
buf_LRU_block_free_non_file_page(block, have_page_hash_mutex);
}
/**********************************************************************//**
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();
mutex_enter(&LRU_list_mutex);
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();
mutex_exit(&LRU_list_mutex);
} 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. */
@ -2023,6 +2065,218 @@ func_exit:
memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur);
}
/********************************************************************//**
Dump the LRU page list to the specific file. */
#define LRU_DUMP_FILE "ib_lru_dump"
UNIV_INTERN
ibool
buf_LRU_file_dump(void)
/*===================*/
{
os_file_t dump_file = -1;
ibool success;
byte* buffer_base = NULL;
byte* buffer = NULL;
buf_page_t* bpage;
ulint buffers;
ulint offset;
ibool ret = FALSE;
ulint i;
for (i = 0; i < srv_n_data_files; i++) {
if (strstr(srv_data_file_names[i], LRU_DUMP_FILE) != NULL) {
fprintf(stderr,
" InnoDB: The name '%s' seems to be used for"
" innodb_data_file_path. Dumping LRU list is not"
" done for safeness.\n", LRU_DUMP_FILE);
goto end;
}
}
buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE);
buffer = ut_align(buffer_base, UNIV_PAGE_SIZE);
if (!buffer) {
fprintf(stderr,
" InnoDB: cannot allocate buffer.\n");
goto end;
}
dump_file = os_file_create(LRU_DUMP_FILE, OS_FILE_OVERWRITE,
OS_FILE_NORMAL, OS_DATA_FILE, &success);
if (!success) {
os_file_get_last_error(TRUE);
fprintf(stderr,
" InnoDB: cannot open %s\n", LRU_DUMP_FILE);
goto end;
}
mutex_enter(&LRU_list_mutex);
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
buffers = offset = 0;
while (bpage != NULL) {
if (offset == 0) {
memset(buffer, 0, UNIV_PAGE_SIZE);
}
mach_write_to_4(buffer + offset * 4, bpage->space);
offset++;
mach_write_to_4(buffer + offset * 4, bpage->offset);
offset++;
if (offset == UNIV_PAGE_SIZE/4) {
success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
(buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
(buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
UNIV_PAGE_SIZE);
if (!success) {
mutex_exit(&LRU_list_mutex);
fprintf(stderr,
" InnoDB: cannot write page %lu of %s\n",
buffers, LRU_DUMP_FILE);
goto end;
}
buffers++;
offset = 0;
}
bpage = UT_LIST_GET_PREV(LRU, bpage);
}
mutex_exit(&LRU_list_mutex);
if (offset == 0) {
memset(buffer, 0, UNIV_PAGE_SIZE);
}
mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
offset++;
mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
offset++;
success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
(buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
(buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
UNIV_PAGE_SIZE);
if (!success) {
goto end;
}
ret = TRUE;
end:
if (dump_file != -1)
os_file_close(dump_file);
if (buffer_base)
ut_free(buffer_base);
return(ret);
}
/********************************************************************//**
Read the pages based on the specific file.*/
UNIV_INTERN
ibool
buf_LRU_file_restore(void)
/*======================*/
{
os_file_t dump_file = -1;
ibool success;
byte* buffer_base = NULL;
byte* buffer = NULL;
ulint buffers;
ulint offset;
ulint reads = 0;
ulint req = 0;
ibool terminated = FALSE;
ibool ret = FALSE;
buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE);
buffer = ut_align(buffer_base, UNIV_PAGE_SIZE);
if (!buffer) {
fprintf(stderr,
" InnoDB: cannot allocate buffer.\n");
goto end;
}
dump_file = os_file_create_simple_no_error_handling(
LRU_DUMP_FILE, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
if (!success) {
os_file_get_last_error(TRUE);
fprintf(stderr,
" InnoDB: cannot open %s\n", LRU_DUMP_FILE);
goto end;
}
buffers = 0;
while (!terminated) {
success = os_file_read(dump_file, buffer,
(buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
(buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
UNIV_PAGE_SIZE);
if (!success) {
fprintf(stderr,
" InnoDB: cannot read page %lu of %s,"
" or meet unexpected terminal.",
buffers, LRU_DUMP_FILE);
goto end;
}
for (offset = 0; offset < UNIV_PAGE_SIZE/4; offset += 2) {
ulint space_id, zip_size, page_no;
ulint err;
ib_int64_t tablespace_version;
space_id = mach_read_from_4(buffer + offset * 4);
page_no = mach_read_from_4(buffer + (offset + 1) * 4);
if (space_id == 0xFFFFFFFFUL
|| page_no == 0xFFFFFFFFUL) {
terminated = TRUE;
break;
}
if (offset % 16 == 15) {
os_aio_simulated_wake_handler_threads();
buf_flush_free_margin(FALSE);
}
zip_size = fil_space_get_zip_size(space_id);
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
continue;
}
if (fil_area_is_exist(space_id, zip_size, page_no, 0,
zip_size ? zip_size : UNIV_PAGE_SIZE)) {
tablespace_version = fil_space_get_version(space_id);
req++;
reads += buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
| OS_AIO_SIMULATED_WAKE_LATER,
space_id, zip_size, TRUE,
tablespace_version, page_no, NULL);
buf_LRU_stat_inc_io();
}
}
buffers++;
}
os_aio_simulated_wake_handler_threads();
buf_flush_free_margin(FALSE);
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: reading pages based on the dumped LRU list was done."
" (requested: %lu, read: %lu)\n", req, reads);
ret = TRUE;
end:
if (dump_file != -1)
os_file_close(dump_file);
if (buffer_base)
ut_free(buffer_base);
return(ret);
}
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/**********************************************************************//**
Validates the LRU list.
@ -2036,7 +2290,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();
@ -2046,7 +2299,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);
}
@ -2077,28 +2334,24 @@ buf_LRU_validate(void)
}
if (buf_page_is_old(bpage)) {
old_len++;
}
const buf_page_t* prev
= UT_LIST_GET_PREV(LRU, bpage);
const buf_page_t* next
= UT_LIST_GET_NEXT(LRU, bpage);
if (buf_pool->LRU_old && (old_len == 1)) {
if (!old_len++) {
ut_a(buf_pool->LRU_old == bpage);
} else {
ut_a(!prev || buf_page_is_old(prev));
}
LRU_pos = buf_page_get_LRU_position(bpage);
ut_a(!next || buf_page_is_old(next));
}
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) {
ut_a(buf_pool->LRU_old_len == old_len);
}
mutex_exit(&LRU_list_mutex);
mutex_enter(&free_list_mutex);
@ -2149,9 +2402,6 @@ buf_LRU_print(void)
//buf_pool_mutex_enter();
mutex_enter(&LRU_list_mutex);
fprintf(stderr, "Pool ulint clock %lu\n",
(ulong) buf_pool->ulint_clock);
bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
while (bpage != NULL) {
@ -2182,18 +2432,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(
@ -2201,8 +2449,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;
}

View File

@ -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,8 +54,9 @@ 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 */
static
not exist or is being dropped
@return 1 if read request is issued. 0 if it is not */
UNIV_INTERN
ulint
buf_read_page_low(
/*==============*/
@ -82,7 +75,8 @@ buf_read_page_low(
treat the tablespace as dropped; this is a timestamp we
use to stop dangling page reads from a tablespace
which we have DISCARDed + IMPORTed back */
ulint offset) /*!< in: page number */
ulint offset, /*!< in: page number */
trx_t* trx)
{
buf_page_t* bpage;
ulint wake_later;
@ -183,15 +177,15 @@ not_to_recover:
ut_ad(buf_page_in_file(bpage));
if (zip_size) {
*err = fil_io(OS_FILE_READ | wake_later,
*err = _fil_io(OS_FILE_READ | wake_later,
sync, space, zip_size, offset, 0, zip_size,
bpage->zip.data, bpage);
bpage->zip.data, bpage, trx);
} else {
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
*err = fil_io(OS_FILE_READ | wake_later,
*err = _fil_io(OS_FILE_READ | wake_later,
sync, space, 0, offset, 0, UNIV_PAGE_SIZE,
((buf_block_t*) bpage)->frame, bpage);
((buf_block_t*) bpage)->frame, bpage, trx);
}
ut_a(*err == DB_SUCCESS);
@ -204,207 +198,34 @@ not_to_recover:
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_read_ahead & 1)) {
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();
mutex_enter(&buf_pool_mutex);
if (buf_pool->n_pend_reads
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
//buf_pool_mutex_exit();
mutex_exit(&buf_pool_mutex);
return(0);
}
mutex_exit(&buf_pool_mutex);
/* Count how many blocks in the area have been recently accessed,
that is, reside near the start of the LRU list. */
rw_lock_s_lock(&page_hash_latch);
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();
rw_lock_s_unlock(&page_hash_latch);
goto read_ahead;
}
}
}
//buf_pool_mutex_exit();
rw_lock_s_unlock(&page_hash_latch);
/* 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 */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
ulint offset) /*!< in: page number */
ulint offset, /*!< in: page number */
trx_t* trx)
{
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,
count = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
zip_size, FALSE,
tablespace_version, offset);
srv_buf_pool_reads+= count2;
tablespace_version, offset, trx);
srv_buf_pool_reads += count;
if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr);
fprintf(stderr,
@ -421,14 +242,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
@ -454,8 +275,9 @@ buf_read_ahead_linear(
/*==================*/
ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
ulint offset) /*!< in: page number of a page; NOTE: the current thread
ulint offset, /*!< in: page number of a page; NOTE: the current thread
must want access to this page (see NOTE 3 above) */
trx_t* trx)
{
ib_int64_t tablespace_version;
buf_page_t* bpage;
@ -557,9 +379,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++;
@ -670,7 +500,7 @@ buf_read_ahead_linear(
count += buf_read_page_low(
&err, FALSE,
ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
space, zip_size, FALSE, tablespace_version, i);
space, zip_size, FALSE, tablespace_version, i, trx);
if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr);
fprintf(stderr,
@ -705,7 +535,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);
}
@ -760,7 +590,7 @@ buf_read_ibuf_merge_pages(
buf_read_page_low(&err, sync && (i + 1 == n_stored),
BUF_READ_ANY_PAGE, space_ids[i],
zip_size, TRUE, space_versions[i],
page_nos[i]);
page_nos[i], NULL);
if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) {
tablespace_deleted:
@ -857,12 +687,12 @@ buf_read_recv_pages(
if ((i + 1 == n_stored) && sync) {
buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
zip_size, TRUE, tablespace_version,
page_nos[i]);
page_nos[i], NULL);
} else {
buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
| OS_AIO_SIMULATED_WAKE_LATER,
space, zip_size, TRUE,
tablespace_version, page_nos[i]);
tablespace_version, page_nos[i], NULL);
}
}

View File

@ -237,6 +237,22 @@ dtype_print(
fputs("DATA_SYS", stderr);
break;
case DATA_FLOAT:
fputs("DATA_FLOAT", stderr);
break;
case DATA_DOUBLE:
fputs("DATA_DOUBLE", stderr);
break;
case DATA_DECIMAL:
fputs("DATA_DECIMAL", stderr);
break;
case DATA_VARMYSQL:
fputs("DATA_VARMYSQL", stderr);
break;
default:
fprintf(stderr, "type %lu", (ulong) mtype);
break;

View File

@ -1387,7 +1387,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 */

View File

@ -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 */
@ -1261,7 +1262,7 @@ dict_index_too_big_for_undo(
= TRX_UNDO_PAGE_HDR - TRX_UNDO_PAGE_HDR_SIZE
+ 2 /* next record pointer */
+ 1 /* type_cmpl */
+ 11 /* trx->undo_no */ - 11 /* table->id */
+ 11 /* trx->undo_no */ + 11 /* table->id */
+ 1 /* rec_get_info_bits() */
+ 11 /* DB_TRX_ID */
+ 11 /* DB_ROLL_PTR */
@ -1440,7 +1441,11 @@ dict_index_too_big_for_tree(
goto add_field_size;
}
if (srv_relax_table_creation) {
field_max_size = dict_col_get_min_size(col);
} else {
field_max_size = dict_col_get_max_size(col);
}
field_ext_max_size = field_max_size < 256 ? 1 : 2;
if (field->prefix_len) {
@ -1493,7 +1498,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(
@ -1519,7 +1524,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 */
@ -1732,9 +1740,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 */
@ -1759,17 +1768,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 */
@ -4711,6 +4724,26 @@ dict_ind_init(void)
dict_ind_redundant->cached = dict_ind_compact->cached = TRUE;
}
/**********************************************************************//**
Frees dict_ind_redundant and dict_ind_compact. */
static
void
dict_ind_free(void)
/*===============*/
{
dict_table_t* table;
table = dict_ind_compact->table;
dict_mem_index_free(dict_ind_compact);
dict_ind_compact = NULL;
dict_mem_table_free(table);
table = dict_ind_redundant->table;
dict_mem_index_free(dict_ind_redundant);
dict_ind_redundant = NULL;
dict_mem_table_free(table);
}
#ifndef UNIV_HOTBACKUP
/**********************************************************************//**
Get index by name
@ -4836,4 +4869,55 @@ dict_table_check_for_dup_indexes(
}
}
#endif /* UNIV_DEBUG */
/**************************************************************************
Closes the data dictionary module. */
UNIV_INTERN
void
dict_close(void)
/*============*/
{
ulint i;
/* Free the hash elements. We don't remove them from the table
because we are going to destroy the table anyway. */
for (i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) {
dict_table_t* table;
table = HASH_GET_FIRST(dict_sys->table_hash, i);
while (table) {
dict_table_t* prev_table = table;
table = HASH_GET_NEXT(name_hash, prev_table);
#ifdef UNIV_DEBUG
ut_a(prev_table->magic_n == DICT_TABLE_MAGIC_N);
#endif
/* Acquire only because it's a pre-condition. */
mutex_enter(&dict_sys->mutex);
dict_table_remove_from_cache(prev_table);
mutex_exit(&dict_sys->mutex);
}
}
hash_table_free(dict_sys->table_hash);
/* The elements are the same instance as in dict_sys->table_hash,
therefore we don't delete the individual elements. */
hash_table_free(dict_sys->table_id_hash);
dict_ind_free();
mutex_free(&dict_sys->mutex);
rw_lock_free(&dict_operation_lock);
memset(&dict_operation_lock, 0x0, sizeof(dict_operation_lock));
mutex_free(&dict_foreign_err_mutex);
mem_free(dict_sys);
dict_sys = NULL;
}
#endif /* !UNIV_HOTBACKUP */

View File

@ -327,6 +327,17 @@ fil_get_space_id_for_table(
/*=======================*/
const char* name); /*!< in: table name in the standard
'databasename/tablename' format */
/*******************************************************************//**
Frees a space object from the tablespace memory cache. Closes the files in
the chain but does not delete them. There must not be any pending i/o's or
flushes on the files. */
static
ibool
fil_space_free(
/*===========*/
/* out: TRUE if success */
ulint id, /* in: space id */
ibool own_mutex);/* in: TRUE if own system->mutex */
/********************************************************************//**
Reads data from a space to a buffer. Remember that the possible incomplete
blocks at the end of file are ignored: they are not taken into account when
@ -600,6 +611,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);
}
@ -619,12 +635,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);
@ -660,9 +674,12 @@ fil_node_open_file(
size_bytes = (((ib_int64_t)size_high) << 32)
+ (ib_int64_t)size_low;
#ifdef UNIV_HOTBACKUP
if (space->id == 0) {
node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
/* TODO: adjust to zip_size, like below? */
#else
os_file_close(node->handle);
goto add_size;
}
#endif /* UNIV_HOTBACKUP */
ut_a(space->purpose != FIL_LOG);
ut_a(space->id != 0);
@ -741,7 +758,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;
}
@ -961,7 +981,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);
@ -1141,7 +1161,7 @@ try_again:
mutex_exit(&fil_system->mutex);
fil_space_free(namesake_id);
fil_space_free(namesake_id, FALSE);
goto try_again;
}
@ -1266,17 +1286,21 @@ Frees a space object from the tablespace memory cache. Closes the files in
the chain but does not delete them. There must not be any pending i/o's or
flushes on the files.
@return TRUE if success */
UNIV_INTERN
static
ibool
fil_space_free(
/*===========*/
ulint id) /*!< in: space id */
/* out: TRUE if success */
ulint id, /* in: space id */
ibool own_mutex) /* in: TRUE if own system->mutex */
{
fil_space_t* space;
fil_space_t* namespace;
fil_node_t* fil_node;
if (!own_mutex) {
mutex_enter(&fil_system->mutex);
}
space = fil_space_get_by_id(id);
@ -1323,7 +1347,9 @@ fil_space_free(
ut_a(0 == UT_LIST_GET_LEN(space->chain));
if (!own_mutex) {
mutex_exit(&fil_system->mutex);
}
rw_lock_free(&(space->latch));
@ -1541,7 +1567,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"
@ -1583,6 +1609,8 @@ fil_close_all_files(void)
space = UT_LIST_GET_FIRST(fil_system->space_list);
while (space != NULL) {
fil_space_t* prev_space = space;
node = UT_LIST_GET_FIRST(space->chain);
while (node != NULL) {
@ -1592,6 +1620,7 @@ fil_close_all_files(void)
node = UT_LIST_GET_NEXT(chain, node);
}
space = UT_LIST_GET_NEXT(space_list, space);
fil_space_free(prev_space->id, TRUE);
}
mutex_exit(&fil_system->mutex);
@ -2223,7 +2252,7 @@ try_again:
#endif
/* printf("Deleting tablespace %s id %lu\n", space->name, id); */
success = fil_space_free(id);
success = fil_space_free(id, FALSE);
if (success) {
success = os_file_delete(path);
@ -2929,7 +2958,6 @@ fil_open_single_table_tablespace(
byte* page;
ulint space_id;
ulint space_flags;
ibool ret = TRUE;
filepath = fil_make_ibd_name(name, FALSE);
@ -3330,7 +3358,7 @@ skip_write:
(ulong) space_id, (ulong) space_flags,
(ulong) id, (ulong) flags);
ret = FALSE;
success = FALSE;
goto func_exit;
}
@ -3350,7 +3378,7 @@ func_exit:
os_file_close(file);
mem_free(filepath);
return(ret);
return(success);
}
#endif /* !UNIV_HOTBACKUP */
@ -3566,7 +3594,7 @@ fil_load_single_table_tablespace(
fprintf(stderr,
"InnoDB: Renaming tablespace %s of id %lu,\n"
"InnoDB: to %s_ibbackup_old_vers_<timestamp>\n"
"InnoDB: because its size %lld is too small"
"InnoDB: because its size %" PRId64 " is too small"
" (< 4 pages 16 kB each),\n"
"InnoDB: or the space id in the file header"
" is not sensible.\n"
@ -3628,9 +3656,19 @@ fil_load_single_table_tablespace(
if (!success) {
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
the rounding formula for extents and pages is somewhat complex; we
let fil_node_open() do that task. */
@ -4163,7 +4201,7 @@ fil_extend_space_to_desired_size(
node->name, node->handle, buf,
offset_low, offset_high,
page_size * n_pages,
NULL, NULL);
NULL, NULL, NULL);
#endif
if (success) {
node->size += n_pages;
@ -4490,7 +4528,7 @@ Reads or writes data. This operation is asynchronous (aio).
i/o on a tablespace which does not exist */
UNIV_INTERN
ulint
fil_io(
_fil_io(
/*===*/
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE,
ORed to OS_FILE_LOG, if a log i/o
@ -4515,8 +4553,9 @@ fil_io(
void* buf, /*!< in/out: buffer where to store read data
or from where to write; in aio this must be
appropriately aligned */
void* message) /*!< in: message for aio handler if non-sync
void* message, /*!< in: message for aio handler if non-sync
aio used, else ignored */
trx_t* trx)
{
ulint mode;
fil_space_t* space;
@ -4686,7 +4725,7 @@ fil_io(
#else
/* Queue the aio request */
ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
offset_low, offset_high, len, node, message);
offset_low, offset_high, len, node, message, trx);
#endif
ut_a(ret);
@ -4706,6 +4745,78 @@ fil_io(
return(DB_SUCCESS);
}
/********************************************************************//**
Confirm whether the parameters are valid or not */
UNIV_INTERN
ibool
fil_area_is_exist(
/*==============*/
ulint space_id, /*!< in: space id */
ulint zip_size, /*!< in: compressed page size in bytes;
0 for uncompressed pages */
ulint block_offset, /*!< in: offset in number of blocks */
ulint byte_offset, /*!< in: remainder of offset in bytes; in
aio this must be divisible by the OS block
size */
ulint len) /*!< in: how many bytes to read or write; this
must not cross a file boundary; in aio this
must be a block size multiple */
{
fil_space_t* space;
fil_node_t* node;
/* Reserve the fil_system mutex and make sure that we can open at
least one file while holding it, if the file is not already open */
fil_mutex_enter_and_prepare_for_io(space_id);
space = fil_space_get_by_id(space_id);
if (!space) {
mutex_exit(&fil_system->mutex);
return(FALSE);
}
node = UT_LIST_GET_FIRST(space->chain);
for (;;) {
if (UNIV_UNLIKELY(node == NULL)) {
mutex_exit(&fil_system->mutex);
return(FALSE);
}
if (space->id != 0 && node->size == 0) {
/* We do not know the size of a single-table tablespace
before we open the file */
break;
}
if (node->size > block_offset) {
/* Found! */
break;
} else {
block_offset -= node->size;
node = UT_LIST_GET_NEXT(chain, node);
}
}
/* Open file if closed */
fil_node_prepare_for_io(node, fil_system, space);
fil_node_complete_io(node, fil_system, OS_FILE_READ);
/* Check that at least the start offset is within the bounds of a
single-table tablespace */
if (UNIV_UNLIKELY(node->size <= block_offset)
&& space->id != 0 && space->purpose == FIL_TABLESPACE) {
mutex_exit(&fil_system->mutex);
return(FALSE);
}
mutex_exit(&fil_system->mutex);
return(TRUE);
}
#ifndef UNIV_HOTBACKUP
/**********************************************************************//**
Waits for an aio operation to complete. This function is used to write the
@ -5065,6 +5176,29 @@ fil_page_get_type(
return(mach_read_from_2(page + FIL_PAGE_TYPE));
}
/********************************************************************
Initializes the tablespace memory cache. */
UNIV_INTERN
void
fil_close(void)
/*===========*/
{
/* The mutex should already have been freed. */
ut_ad(fil_system->mutex.magic_n == 0);
hash_table_free(fil_system->spaces);
hash_table_free(fil_system->name_hash);
ut_a(UT_LIST_GET_LEN(fil_system->LRU) == 0);
ut_a(UT_LIST_GET_LEN(fil_system->unflushed_spaces) == 0);
ut_a(UT_LIST_GET_LEN(fil_system->space_list) == 0);
mem_free(fil_system);
fil_system = NULL;
}
/*************************************************************************
Return local hash table informations. */

View File

@ -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

View File

@ -79,6 +79,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"
@ -111,7 +112,6 @@ extern "C" {
#include "ha_innodb.h"
#include "i_s.h"
#include "handler0vars.h"
#ifdef MYSQL_SERVER
// Defined in trx0sys.c
@ -122,9 +122,12 @@ extern ib_int64_t trx_sys_mysql_relay_log_pos;
#endif /* MYSQL_SERVER */
#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 pthread_mutex_t LOCK_thread_count;
extern MYSQL_PLUGIN_IMPORT pthread_mutex_t LOCK_thread_count;
#if MYSQL_VERSION_ID < 50124
/* this is defined in mysql_priv.h inside #ifdef MYSQL_SERVER
@ -148,13 +151,9 @@ static bool innodb_inited = 0;
/* In the Windows plugin, the return value of current_thd is
undefined. Map it to NULL. */
#if defined MYSQL_DYNAMIC_PLUGIN && defined __WIN__
# undef current_thd
# define current_thd NULL
# define EQ_CURRENT_THD(thd) TRUE
#else /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */
#define EQ_CURRENT_THD(thd) ((thd) == current_thd)
#endif /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */
static struct handlerton* innodb_hton_ptr;
@ -174,6 +173,10 @@ static ulong innobase_write_io_threads;
static my_bool innobase_thread_concurrency_timer_based;
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: */
@ -188,9 +191,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 */
@ -204,7 +205,7 @@ static my_bool innobase_use_doublewrite = TRUE;
static my_bool innobase_use_checksums = TRUE;
static my_bool innobase_extra_undoslots = FALSE;
static my_bool innobase_fast_recovery = FALSE;
static my_bool innobase_use_purge_thread = FALSE;
static my_bool innobase_recovery_stats = TRUE;
static my_bool innobase_locks_unsafe_for_binlog = FALSE;
static my_bool innobase_overwrite_relay_log_info = FALSE;
static my_bool innobase_rollback_on_timeout = FALSE;
@ -287,10 +288,10 @@ innobase_file_format_check_on_off(
/************************************************************//**
Validate the file format check config parameters, as a side effect it
sets the srv_check_file_format_at_startup variable.
@return true if valid config value */
@return the format_id if valid config value, otherwise, return -1 */
static
bool
innobase_file_format_check_validate(
int
innobase_file_format_validate_and_set(
/*================================*/
const char* format_check); /*!< in: parameter value */
/****************************************************************//**
@ -521,10 +522,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",
@ -805,11 +806,20 @@ convert_error_code_to_mysql(
case DB_SUCCESS:
return(0);
case DB_INTERRUPTED:
my_error(ER_QUERY_INTERRUPTED, MYF(0));
/* fall through */
case DB_ERROR:
default:
return(-1); /* unspecified error */
case DB_DUPLICATE_KEY:
/* Be cautious with returning this error, since
mysql could re-enter the storage layer to get
duplicated key info, the operation requires a
valid table handle and/or transaction information,
which might not always be available in the error
handling stage. */
return(HA_ERR_FOUND_DUPP_KEY);
case DB_FOREIGN_DUPLICATE_KEY:
@ -896,17 +906,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);
}
@ -980,7 +987,23 @@ innobase_get_cset_width(
*mbminlen = cs->mbminlen;
*mbmaxlen = cs->mbmaxlen;
} else {
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;
}
}
@ -1054,6 +1077,7 @@ innobase_get_charset(
}
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list;
/*******************************************************************//**
Map an OS error to an errno value. The OS error number is stored in
_doserrno and the mapped value is stored in errno) */
@ -1341,6 +1365,16 @@ innobase_trx_init(
trx->check_unique_secondary = !thd_test_options(
thd, OPTION_RELAXED_UNIQUE_CHECKS);
#ifdef EXTENDED_SLOWLOG
if (thd_log_slow_verbosity(thd) & SLOG_V_INNODB) {
trx->take_stats = TRUE;
} else {
trx->take_stats = FALSE;
}
#else
trx->take_stats = FALSE;
#endif
DBUG_VOID_RETURN;
}
@ -1397,6 +1431,32 @@ check_trx_exists(
}
/*************************************************************************
Gets current trx. */
extern "C"
trx_t*
innobase_get_trx()
{
THD *thd=current_thd;
if (likely(thd != 0)) {
trx_t*& trx = thd_to_trx(thd);
return(trx);
} else {
return(NULL);
}
}
extern "C"
ibool
innobase_get_slow_log()
{
#ifdef EXTENDED_SLOWLOG
return((ibool) thd_opt_slow_log());
#else
return(FALSE);
#endif
}
/*********************************************************************//**
Construct ha_innobase handler. */
UNIV_INTERN
@ -1713,15 +1773,19 @@ innobase_convert_identifier(
FALSE=id is an UTF-8 string */
{
char nz[NAME_LEN + 1];
#if MYSQL_VERSION_ID >= 50141
char nz2[NAME_LEN + 1 + EXPLAIN_FILENAME_MAX_EXTRA_LENGTH];
#else /* MYSQL_VERSION_ID >= 50141 */
char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
#endif /* MYSQL_VERSION_ID >= 50141 */
const char* s = id;
int q;
if (file_id) {
/* Decode the table name. The filename_to_tablename()
function expects a NUL-terminated string. The input and
output strings buffers must not be shared. */
/* Decode the table name. The MySQL function expects
a NUL-terminated string. The input and output strings
buffers must not be shared. */
if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
idlen = (sizeof nz) - 1;
@ -1731,7 +1795,13 @@ innobase_convert_identifier(
nz[idlen] = 0;
s = nz2;
#if MYSQL_VERSION_ID >= 50141
idlen = explain_filename((THD*) thd, nz, nz2, sizeof nz2,
EXPLAIN_PARTITIONS_AS_COMMENT);
goto no_quote;
#else /* MYSQL_VERSION_ID >= 50141 */
idlen = filename_to_tablename(nz, nz2, sizeof nz2);
#endif /* MYSQL_VERSION_ID >= 50141 */
}
/* See if the identifier needs to be quoted. */
@ -1742,6 +1812,9 @@ innobase_convert_identifier(
}
if (q == EOF) {
#if MYSQL_VERSION_ID >= 50141
no_quote:
#endif /* MYSQL_VERSION_ID >= 50141 */
if (UNIV_UNLIKELY(idlen > buflen)) {
idlen = buflen;
}
@ -2224,8 +2297,8 @@ mem_free_and_error:
/* Did the user specify a format name that we support ?
As a side effect it will update the variable
srv_check_file_format_at_startup */
if (!innobase_file_format_check_validate(
innobase_file_format_check)) {
if (innobase_file_format_validate_and_set(
innobase_file_format_check) < 0) {
sql_print_error("InnoDB: invalid "
"innodb_file_format_check value: "
@ -2266,7 +2339,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;
@ -2294,8 +2367,7 @@ innobase_change_buffering_inited_ok:
srv_force_recovery = (ulint) innobase_force_recovery;
srv_fast_recovery = (ibool) innobase_fast_recovery;
srv_use_purge_thread = (ibool) innobase_use_purge_thread;
srv_recovery_stats = (ibool) innobase_recovery_stats;
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
srv_use_checksums = (ibool) innobase_use_checksums;
@ -2331,6 +2403,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
@ -2512,7 +2587,10 @@ innobase_alter_table_flags(
{
return(HA_ONLINE_ADD_INDEX_NO_WRITES
| HA_ONLINE_DROP_INDEX_NO_WRITES
| HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES
/* Current InnoDB doesn't sort unique indexes along mysqld's order
It is dangerous to use index. So it is disabled until
the bug http://bugs.mysql.com/47622 */
/* | HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES */
| HA_ONLINE_DROP_UNIQUE_INDEX_NO_WRITES
| HA_ONLINE_ADD_PK_INDEX_NO_WRITES);
}
@ -2678,6 +2756,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();
@ -2763,6 +2854,8 @@ innobase_rollback(
innobase_release_stat_resources(trx);
trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
/* If we had reserved the auto-inc lock for some table (if
we come here to roll back the latest SQL statement) we
release it now before a possibly lengthy rollback */
@ -3324,7 +3417,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);
}
@ -3928,7 +4021,6 @@ ha_innobase::store_key_val_for_row(
as BLOB data in innodb. */
|| mysql_type == MYSQL_TYPE_GEOMETRY) {
CHARSET_INFO* cs;
ulint key_len;
ulint true_len;
@ -5229,6 +5321,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 */
@ -5388,6 +5485,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);
}
@ -5395,7 +5493,9 @@ ha_innobase::change_active_index(
prebuilt->index);
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
sql_print_warning("InnoDB: insufficient history for index %u",
push_warning_printf(user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
HA_ERR_TABLE_DEF_CHANGED,
"InnoDB: insufficient history for index %u",
keynr);
/* The caller seems to ignore this. Thus, we must check
this again in row_search_for_mysql(). */
@ -5852,7 +5952,7 @@ create_table_def(
number fits in one byte in prtype */
push_warning_printf(
(THD*) trx->mysql_thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CANT_CREATE_TABLE,
"In InnoDB, charset-collation codes"
" must be below 256."
@ -5884,17 +5984,8 @@ 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_WARN,
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);
my_error(ER_WRONG_COLUMN_NAME, MYF(0),
field->field_name);
dict_mem_table_free(table);
trx_commit_for_mysql(trx);
@ -5916,6 +6007,14 @@ create_table_def(
error = row_create_table_for_mysql(table, trx);
if (error == DB_DUPLICATE_KEY) {
char buf[100];
innobase_convert_identifier(buf, sizeof buf,
table_name, strlen(table_name),
trx->mysql_thd, TRUE);
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), buf);
}
error_ret:
error = convert_error_code_to_mysql(error, flags, NULL);
@ -6066,7 +6165,6 @@ 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,
innobase_index_reserve_name,
0, DICT_CLUSTERED, 0);
@ -6121,7 +6219,7 @@ create_options_are_valid(
/* Valid value. */
break;
default:
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: invalid"
" KEY_BLOCK_SIZE = %lu."
@ -6135,7 +6233,7 @@ create_options_are_valid(
/* If KEY_BLOCK_SIZE was specified, check for its
dependencies. */
if (kbs_specified && !srv_file_per_table) {
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE"
" requires innodb_file_per_table.");
@ -6143,7 +6241,7 @@ create_options_are_valid(
}
if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE"
" requires innodb_file_format >"
@ -6167,7 +6265,7 @@ create_options_are_valid(
if (!srv_file_per_table) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ROW_FORMAT=%s"
" requires innodb_file_per_table.",
@ -6179,7 +6277,7 @@ create_options_are_valid(
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ROW_FORMAT=%s"
" requires innodb_file_format >"
@ -6196,7 +6294,7 @@ create_options_are_valid(
&& form->s->row_type == ROW_TYPE_DYNAMIC) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: cannot specify"
" ROW_FORMAT = DYNAMIC with"
@ -6220,7 +6318,7 @@ create_options_are_valid(
if (kbs_specified) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: cannot specify"
" ROW_FORMAT = %s with"
@ -6233,7 +6331,7 @@ create_options_are_valid(
default:
push_warning(thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: invalid ROW_FORMAT specifier.");
ret = FALSE;
@ -6297,13 +6395,15 @@ ha_innobase::create(
1. <database_name>/<table_name>: for normal table creation
2. full path: for temp table creation, or sym link
When srv_file_per_table is on, check for full path pattern, i.e.
When srv_file_per_table is on and mysqld_embedded is off,
check for full path pattern, i.e.
X:\dir\..., X is a driver letter, or
\\dir1\dir2\..., UNC path
returns error if it is in full path format, but not creating a temp.
table. Currently InnoDB does not support symbolic link on Windows. */
if (srv_file_per_table
&& !mysqld_embedded
&& (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
if ((name[1] == ':')
@ -6521,6 +6621,7 @@ ha_innobase::create(
goto cleanup;
}
/* Create the keys */
if (form->s->keys == 0 || primary_key_no == -1) {
@ -6969,6 +7070,24 @@ ha_innobase::rename_table(
innobase_commit_low(trx);
trx_free_for_mysql(trx);
/* Add a special case to handle the Duplicated Key error
and return DB_ERROR instead.
This is to avoid a possible SIGSEGV error from mysql error
handling code. Currently, mysql handles the Duplicated Key
error by re-entering the storage layer and getting dup key
info by calling get_dup_key(). This operation requires a valid
table handle ('row_prebuilt_t' structure) which could no
longer be available in the error handling stage. The suggested
solution is to report a 'table exists' error message (since
the dup key error here is due to an existing table whose name
is the one we are trying to rename to) and return the generic
error code. */
if (error == (int) DB_DUPLICATE_KEY) {
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to);
error = DB_ERROR;
}
error = convert_error_code_to_mysql(error, 0, NULL);
DBUG_RETURN(error);
@ -7521,12 +7640,16 @@ ha_innobase::check(
ret = row_check_table_for_mysql(prebuilt);
if (ret == DB_SUCCESS) {
switch (ret) {
case DB_SUCCESS:
return(HA_ADMIN_OK);
}
case DB_INTERRUPTED:
my_error(ER_QUERY_INTERRUPTED, MYF(0));
return(-1);
default:
return(HA_ADMIN_CORRUPT);
}
}
/*************************************************************//**
Adds information about free space in the InnoDB tablespace to a table comment
@ -8072,7 +8195,10 @@ ha_innobase::external_lock(
ulong const tx_isolation = thd_tx_isolation(ha_thd());
if (tx_isolation <= ISO_READ_COMMITTED
&& binlog_format == BINLOG_FORMAT_STMT
&& thd_binlog_filter_ok(thd))
#if MYSQL_VERSION_ID > 50140
&& thd_binlog_filter_ok(thd)
#endif /* MYSQL_VERSION_ID > 50140 */
)
{
char buf[256];
my_snprintf(buf, sizeof(buf),
@ -8185,6 +8311,23 @@ ha_innobase::external_lock(
statement has ended */
if (trx->n_mysql_tables_in_use == 0) {
#ifdef EXTENDED_SLOWLOG
increment_thd_innodb_stats(thd, trx->io_reads,
trx->io_read,
trx->io_reads_wait_timer,
trx->lock_que_wait_timer,
trx->innodb_que_wait_timer,
trx->distinct_page_access);
trx->io_reads = 0;
trx->io_read = 0;
trx->io_reads_wait_timer = 0;
trx->lock_que_wait_timer = 0;
trx->innodb_que_wait_timer = 0;
trx->distinct_page_access = 0;
if (trx->distinct_page_access_hash)
memset(trx->distinct_page_access_hash, 0, DPAH_SIZE);
#endif
trx->mysql_n_tables_locked = 0;
prebuilt->used_in_HANDLER = FALSE;
@ -8472,8 +8615,8 @@ innodb_mutex_show_status(
rw_lock_wait_time += mutex->lspent_time;
}
#else /* UNIV_DEBUG */
buf1len= (uint) my_snprintf(buf1, sizeof(buf1), "%s:%lu",
mutex->cfile_name, (ulong) mutex->cline);
buf1len= (uint) my_snprintf(buf1, sizeof(buf1), "%s",
mutex->cmutex_name);
buf2len= (uint) my_snprintf(buf2, sizeof(buf2), "os_waits=%lu",
mutex->count_os_wait);
@ -8498,8 +8641,8 @@ next_mutex:
while (lock != NULL) {
if (lock->count_os_wait
&& !buf_pool_is_block_lock(lock)) {
buf1len= my_snprintf(buf1, sizeof(buf1), "%s:%lu",
lock->cfile_name, (ulong) lock->cline);
buf1len= my_snprintf(buf1, sizeof(buf1), "%s",
lock->lock_name);
buf2len= my_snprintf(buf2, sizeof(buf2),
"os_waits=%lu", lock->count_os_wait);
@ -8720,6 +8863,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)) {
@ -8727,10 +8871,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;
@ -8960,7 +9105,6 @@ ha_innobase::get_auto_increment(
table->next_number_field);
current = *first_value > col_max_value ? autoinc : *first_value;
need = *nb_reserved_values * increment;
/* Compute the last value in the interval */
@ -9324,8 +9468,7 @@ innobase_xa_prepare(
executing XA PREPARE and XA COMMIT commands.
In this case we cannot know how many minutes or hours
will be between XA PREPARE and XA COMMIT, and we don't want
to block for undefined period of time.
*/
to block for undefined period of time. */
pthread_mutex_lock(&prepare_commit_mutex);
trx->active_trans = 2;
}
@ -9577,6 +9720,20 @@ ha_innobase::check_if_incompatible_data(
DBUG_RETURN(COMPATIBLE_DATA_NO);
}
/* Renaming column asynchronizes dictionary between mysqld and InnoDB...
If not synchronized, treat as COMPATIBLE_DATA_NO
until the bug http://bugs.mysql.com/47621 is fixed officialily */
{
uint i;
for (i = 0; i < table->s->fields; i++) {
if (table->field[i]->flags & FIELD_IN_ADD_INDEX
&& innobase_strcasecmp(table->field[i]->field_name,
dict_table_get_col_name(prebuilt->table, i))) {
return(COMPATIBLE_DATA_NO);
}
}
}
/* Check if a column participating in a foreign key is being renamed.
There is no mechanism for updating InnoDB foreign key definitions. */
if (foreign_key_column_is_being_renamed(prebuilt, table)) {
@ -9685,25 +9842,24 @@ innobase_file_format_check_on_off(
/************************************************************//**
Validate the file format check config parameters, as a side effect it
sets the srv_check_file_format_at_startup variable.
@return true if valid config value */
@return the format_id if valid config value, otherwise, return -1 */
static
bool
innobase_file_format_check_validate(
int
innobase_file_format_validate_and_set(
/*================================*/
const char* format_check) /*!< in: parameter value */
{
uint format_id;
bool ret = true;
format_id = innobase_file_format_name_lookup(format_check);
if (format_id < DICT_TF_FORMAT_MAX + 1) {
srv_check_file_format_at_startup = format_id;
} else {
ret = false;
}
return(ret);
return((int) format_id);
} else {
return(-1);
}
}
/*************************************************************//**
@ -9722,7 +9878,6 @@ innodb_file_format_name_validate(
struct st_mysql_value* value) /*!< in: incoming string */
{
const char* file_format_input;
char* file_format_input_strdup;
char buff[STRING_BUFFER_USUAL_SIZE];
int len = sizeof(buff);
@ -9739,20 +9894,14 @@ innodb_file_format_name_validate(
if (format_id <= DICT_TF_FORMAT_MAX) {
/* Copy out from stack-allocated memory (which will not
survive return from this function). The memory will be
freed in innodb_file_format_check_update(). */
file_format_input_strdup = thd_strmake(thd, file_format_input, len);
/* Save a pointer to the name in the
'file_format_name_map' constant array. */
*static_cast<const char**>(save) =
trx_sys_file_format_id_to_name(format_id);
*static_cast<char**>(save) = file_format_input_strdup;
if (file_format_input_strdup == NULL) {
return(1);
} else {
return(0);
}
}
}
*static_cast<const char**>(save) = NULL;
return(1);
@ -9810,9 +9959,9 @@ innodb_file_format_check_validate(
struct st_mysql_value* value) /*!< in: incoming string */
{
const char* file_format_input;
char* file_format_input_strdup;
char buff[STRING_BUFFER_USUAL_SIZE];
int len = sizeof(buff);
int format_id;
ut_a(save != NULL);
ut_a(value != NULL);
@ -9825,28 +9974,29 @@ innodb_file_format_check_validate(
message if they did so. */
if (innobase_file_format_check_on_off(file_format_input)) {
sql_print_warning(
push_warning_printf(thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WRONG_ARGUMENTS,
"InnoDB: invalid innodb_file_format_check "
"value; on/off can only be set at startup or "
"in the configuration file");
} else if (innobase_file_format_check_validate(
file_format_input)) {
/* Copy out from stack-allocated memory (which will not
survive return from this function). The memory will be
freed in innodb_file_format_check_update(). */
file_format_input_strdup = thd_strmake(thd, file_format_input, len);
*static_cast<char**>(save) = file_format_input_strdup;
if (file_format_input_strdup == NULL) {
return(1);
} else {
format_id = innobase_file_format_validate_and_set(
file_format_input);
if (format_id >= 0) {
/* Save a pointer to the name in the
'file_format_name_map' constant array. */
*static_cast<const char**>(save) =
trx_sys_file_format_id_to_name(
(uint)format_id);
return(0);
}
} else {
sql_print_warning(
push_warning_printf(thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WRONG_ARGUMENTS,
"InnoDB: invalid innodb_file_format_check "
"value; can be any format up to %s "
"or its equivalent numeric id",
@ -9854,6 +10004,7 @@ innodb_file_format_check_validate(
DICT_TF_FORMAT_MAX));
}
}
}
*static_cast<const char**>(save) = NULL;
return(1);
@ -9882,6 +10033,7 @@ innodb_file_format_check_update(
ut_a(var_ptr != NULL);
format_name_in = *static_cast<const char*const*>(save);
if (!format_name_in) {
return;
@ -9931,6 +10083,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.
@ -10077,12 +10248,17 @@ static MYSQL_SYSVAR_BOOL(extra_undoslots, innobase_extra_undoslots,
static MYSQL_SYSVAR_BOOL(fast_recovery, innobase_fast_recovery,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Enable to use speed hack of recovery avoiding flush list sorting.",
NULL, NULL, TRUE);
static MYSQL_SYSVAR_BOOL(recovery_stats, innobase_recovery_stats,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Output statistics of recovery process after it.",
NULL, NULL, FALSE);
static MYSQL_SYSVAR_BOOL(use_purge_thread, innobase_use_purge_thread,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Enable to use purge devoted thread.",
NULL, NULL, FALSE);
static MYSQL_SYSVAR_ULONG(use_purge_thread, srv_use_purge_thread,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Number of purge devoted threads. #### over 1 is EXPERIMENTAL ####",
NULL, NULL, 1, 0, 64, 0);
static MYSQL_SYSVAR_BOOL(overwrite_relay_log_info, innobase_overwrite_relay_log_info,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
@ -10124,12 +10300,15 @@ static MYSQL_SYSVAR_STR(file_format, innobase_file_format_name,
innodb_file_format_name_validate,
innodb_file_format_name_update, "Antelope");
/* If a new file format is introduced, the file format
name needs to be updated accordingly. Please refer to
file_format_name_map[] defined in trx0sys.c for the next
file format name. */
static MYSQL_SYSVAR_STR(file_format_check, innobase_file_format_check,
PLUGIN_VAR_OPCMDARG,
"The highest file format in the tablespace.",
innodb_file_format_check_validate,
innodb_file_format_check_update,
"on");
innodb_file_format_check_update, "Barracuda");
static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
PLUGIN_VAR_OPCMDARG,
@ -10138,7 +10317,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);
@ -10179,7 +10358,7 @@ static MYSQL_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
static MYSQL_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing,
PLUGIN_VAR_NOCMDARG,
"Attempt flushing dirty pages to avoid IO bursts at checkpoints.",
NULL, NULL, TRUE);
NULL, NULL, FALSE);
static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
PLUGIN_VAR_RQCMDARG,
@ -10275,7 +10454,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);
@ -10314,6 +10493,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.",
@ -10392,13 +10583,18 @@ static MYSQL_SYSVAR_LONGLONG(ibuf_max_size, srv_ibuf_max_size,
static MYSQL_SYSVAR_ULONG(ibuf_active_contract, srv_ibuf_active_contract,
PLUGIN_VAR_RQCMDARG,
"Enable/Disable active_contract of insert buffer. 0:disable 1:enable",
NULL, NULL, 0, 0, 1, 0);
NULL, NULL, 1, 0, 1, 0);
static MYSQL_SYSVAR_ULONG(ibuf_accel_rate, srv_ibuf_accel_rate,
PLUGIN_VAR_RQCMDARG,
"Tunes amount of insert buffer processing of background, in addition to innodb_io_capacity. (in percentage)",
NULL, NULL, 100, 100, 999999999, 0);
static MYSQL_SYSVAR_ULONG(checkpoint_age_target, srv_checkpoint_age_target,
PLUGIN_VAR_RQCMDARG,
"Control soft limit of checkpoint age. (0 : not control)",
NULL, NULL, 0, 0, ~0UL, 0);
static MYSQL_SYSVAR_ULONG(flush_neighbor_pages, srv_flush_neighbor_pages,
PLUGIN_VAR_RQCMDARG,
"Enable/Disable flushing also neighbor pages. 0:disable 1:enable",
@ -10434,7 +10630,7 @@ TYPELIB read_ahead_typelib=
};
static MYSQL_SYSVAR_ENUM(read_ahead, srv_read_ahead,
PLUGIN_VAR_RQCMDARG,
"Control read ahead activity. (none, random, [linear], both)",
"Control read ahead activity (none, random, [linear], both). [from 1.0.5: random read ahead is ignored]",
NULL, innodb_read_ahead_update, 2, &read_ahead_typelib);
static
@ -10465,8 +10661,8 @@ TYPELIB adaptive_checkpoint_typelib=
};
static MYSQL_SYSVAR_ENUM(adaptive_checkpoint, srv_adaptive_checkpoint,
PLUGIN_VAR_RQCMDARG,
"Enable/Disable flushing along modified age. ([none], reflex, estimate)",
NULL, innodb_adaptive_checkpoint_update, 0, &adaptive_checkpoint_typelib);
"Enable/Disable flushing along modified age. (none, reflex, [estimate])",
NULL, innodb_adaptive_checkpoint_update, 2, &adaptive_checkpoint_typelib);
static MYSQL_SYSVAR_ULONG(enable_unsafe_group_commit, srv_enable_unsafe_group_commit,
PLUGIN_VAR_RQCMDARG,
@ -10488,6 +10684,11 @@ static MYSQL_SYSVAR_ULONG(dict_size_limit, srv_dict_size_limit,
"Limit the allocated memory for dictionary cache. (0: unlimited)",
NULL, NULL, 0, 0, LONG_MAX, 0);
static MYSQL_SYSVAR_ULONG(relax_table_creation, srv_relax_table_creation,
PLUGIN_VAR_RQCMDARG,
"Relax limitation of column size at table creation as builtin InnoDB.",
NULL, NULL, 0, 0, 1, 0);
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(additional_mem_pool_size),
MYSQL_SYSVAR(autoextend_increment),
@ -10500,6 +10701,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(doublewrite),
MYSQL_SYSVAR(extra_undoslots),
MYSQL_SYSVAR(fast_recovery),
MYSQL_SYSVAR(recovery_stats),
MYSQL_SYSVAR(fast_shutdown),
MYSQL_SYSVAR(file_io_threads),
MYSQL_SYSVAR(read_io_threads),
@ -10524,6 +10726,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(overwrite_relay_log_info),
MYSQL_SYSVAR(rollback_on_timeout),
@ -10550,6 +10754,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(ibuf_max_size),
MYSQL_SYSVAR(ibuf_active_contract),
MYSQL_SYSVAR(ibuf_accel_rate),
MYSQL_SYSVAR(checkpoint_age_target),
MYSQL_SYSVAR(flush_neighbor_pages),
MYSQL_SYSVAR(read_ahead),
MYSQL_SYSVAR(adaptive_checkpoint),
@ -10562,6 +10767,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(read_ahead_threshold),
MYSQL_SYSVAR(io_capacity),
MYSQL_SYSVAR(use_purge_thread),
MYSQL_SYSVAR(relax_table_creation),
NULL
};
@ -10593,6 +10799,7 @@ i_s_innodb_cmpmem,
i_s_innodb_cmpmem_reset,
i_s_innodb_table_stats,
i_s_innodb_index_stats,
i_s_innodb_admin_command,
i_s_innodb_patches
mysql_declare_plugin_end;

View File

@ -258,12 +258,14 @@ int thd_binlog_format(const MYSQL_THD thd);
*/
void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all);
#if MYSQL_VERSION_ID > 50140
/**
Check if binary logging is filtered for thread's current db.
@param thd Thread handle
@retval 1 the query is not filtered, 0 otherwise.
*/
bool thd_binlog_filter_ok(const MYSQL_THD thd);
#endif /* MYSQL_VERSION_ID > 50140 */
}
typedef struct trx_struct trx_t;
@ -289,6 +291,8 @@ trx_t*
innobase_trx_allocate(
/*==================*/
MYSQL_THD thd); /*!< in: user thread handle */
/*********************************************************************//**
This function checks each index name for a table against reserved
system default primary index name 'GEN_CLUST_INDEX'. If a name

View File

@ -35,7 +35,6 @@ extern "C" {
}
#include "ha_innodb.h"
#include "handler0vars.h"
/*************************************************************//**
Copies an InnoDB column to a MySQL field. This function is
@ -629,7 +628,7 @@ ha_innobase::add_index(
ulint num_created = 0;
ibool dict_locked = FALSE;
ulint new_primary;
ulint error;
int error;
DBUG_ENTER("ha_innobase::add_index");
ut_a(table);
@ -668,7 +667,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);
@ -766,10 +765,11 @@ err_exit:
ut_ad(error == DB_SUCCESS);
/* Commit the data dictionary transaction in order to release
the table locks on the system tables. Unfortunately, this
means that if MySQL crashes while creating a new primary key
inside row_merge_build_indexes(), indexed_table will not be
dropped on crash recovery. Thus, it will become orphaned. */
the table locks on the system tables. This means that if
MySQL crashes while creating a new primary key inside
row_merge_build_indexes(), indexed_table will not be dropped
by trx_rollback_active(). It will have to be recovered or
dropped by the database administrator. */
trx_commit_for_mysql(trx);
row_mysql_unlock_data_dictionary(trx);
@ -806,7 +806,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
@ -868,6 +868,7 @@ error_handling:
indexed_table->n_mysql_handles_opened++;
error = row_merge_drop_table(trx, innodb_table);
innodb_table = indexed_table;
goto convert_error;
case DB_TOO_BIG_RECORD:
@ -882,7 +883,9 @@ error:
/* fall through */
default:
if (new_primary) {
if (indexed_table != innodb_table) {
row_merge_drop_table(trx, indexed_table);
}
} else {
if (!dict_locked) {
row_mysql_lock_data_dictionary(trx);

View File

@ -1,73 +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 MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_bin;
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_latin1;
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_filename;
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO* system_charset_info;
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO* default_charset_info;
//extern MYSQL_PLUGIN_IMPORT CHARSET_INFO** all_charsets;
extern MYSQL_PLUGIN_IMPORT system_variables global_system_variables;
//extern MYSQL_PLUGIN_IMPORT char* mysql_real_data_home;
extern MYSQL_PLUGIN_IMPORT char* mysql_data_home;
//extern MYSQL_PLUGIN_IMPORT char** tx_isolation_names;
//extern MYSQL_PLUGIN_IMPORT char** binlog_format_names;
//extern MYSQL_PLUGIN_IMPORT char reg_ext;
extern MYSQL_PLUGIN_IMPORT pthread_mutex_t LOCK_thread_count;
extern MYSQL_PLUGIN_IMPORT key_map key_map_full;
extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list;
extern MYSQL_PLUGIN_IMPORT bool mysqld_embedded;
extern MYSQL_PLUGIN_IMPORT uint lower_case_table_names;
extern MYSQL_PLUGIN_IMPORT ulong specialflag;
extern MYSQL_PLUGIN_IMPORT int my_umask;
extern MYSQL_PLUGIN_IMPORT char *relay_log_info_file;
/*
#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

View File

@ -47,6 +47,7 @@ extern "C" {
#include "trx0rseg.h" /* for trx_rseg_struct */
#include "trx0sys.h" /* for trx_sys */
#include "dict0dict.h" /* for dict_sys */
#include "buf0lru.h" /* for XTRA_LRU_[DUMP/RESTORE] */
/* from buf0buf.c */
struct buf_chunk_struct{
ulint mem_size; /* allocated size of the chunk */
@ -56,7 +57,6 @@ struct buf_chunk_struct{
buf_block_t* blocks; /* array of buffer control blocks */
};
}
#include "handler0vars.h"
static const char plugin_author[] = "Innobase Oy";
@ -84,14 +84,16 @@ do { \
#define STRUCT_FLD(name, value) value
#endif
static const ST_FIELD_INFO END_OF_ST_FIELD_INFO =
{STRUCT_FLD(field_name, NULL),
STRUCT_FLD(field_length, 0),
STRUCT_FLD(field_type, MYSQL_TYPE_NULL),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)};
/* Don't use a static const variable here, as some C++ compilers (notably
HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */
#define END_OF_ST_FIELD_INFO \
{STRUCT_FLD(field_name, NULL), \
STRUCT_FLD(field_length, 0), \
STRUCT_FLD(field_type, MYSQL_TYPE_NULL), \
STRUCT_FLD(value, 0), \
STRUCT_FLD(field_flags, 0), \
STRUCT_FLD(old_name, ""), \
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}
/*
Use the following types mapping:
@ -511,7 +513,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_index_fields_info[] =
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
{STRUCT_FLD(field_name, "accessed"),
{STRUCT_FLD(field_name, "access_time"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
@ -728,7 +730,7 @@ i_s_innodb_buffer_pool_pages_fill(
field_store_string(table->field[0], page_type);
table->field[1]->store(block->page.space);
table->field[2]->store(block->page.offset);
table->field[3]->store(block->page.LRU_position);
table->field[3]->store(0);
table->field[4]->store(block->page.buf_fix_count);
table->field[5]->store(block->page.flush_type);
@ -817,11 +819,11 @@ i_s_innodb_buffer_pool_pages_index_fill(
table->field[5]->store(page_get_n_recs(frame));
table->field[6]->store(page_get_data_size(frame));
table->field[7]->store(block->is_hashed);
table->field[8]->store(block->page.accessed);
table->field[8]->store(block->page.access_time);
table->field[9]->store(block->page.newest_modification != 0);
table->field[10]->store(block->page.oldest_modification != 0);
table->field[11]->store(block->page.old);
table->field[12]->store(block->page.LRU_position);
table->field[12]->store(0);
table->field[13]->store(block->page.buf_fix_count);
table->field[14]->store(block->page.flush_type);
@ -915,7 +917,7 @@ i_s_innodb_buffer_pool_pages_blob_fill(
table->field[4]->store(block->page.offset);
}
table->field[5]->store(block->page.LRU_position);
table->field[5]->store(0);
table->field[6]->store(block->page.buf_fix_count);
table->field[7]->store(block->page.flush_type);
@ -2953,3 +2955,170 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_index_stats =
STRUCT_FLD(system_vars, NULL),
STRUCT_FLD(__reserved1, NULL)
};
/***********************************************************************
*/
static ST_FIELD_INFO i_s_innodb_admin_command_info[] =
{
{STRUCT_FLD(field_name, "result_message"),
STRUCT_FLD(field_length, 1024),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
END_OF_ST_FIELD_INFO
};
#ifndef INNODB_COMPATIBILITY_HOOKS
#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS
#endif
extern "C" {
char **thd_query(MYSQL_THD thd);
}
static
int
i_s_innodb_admin_command_fill(
/*==========================*/
THD* thd,
TABLE_LIST* tables,
COND* cond)
{
TABLE* i_s_table = (TABLE *) tables->table;
CHARSET_INFO *cs= system_charset_info;
char** query_str;
char* ptr;
char quote = '\0';
char* command_head = "XTRA_";
DBUG_ENTER("i_s_innodb_admin_command_fill");
/* deny access to non-superusers */
if (check_global_access(thd, PROCESS_ACL)) {
DBUG_RETURN(0);
}
if(thd_sql_command(thd) != SQLCOM_SELECT) {
field_store_string(i_s_table->field[0],
"SELECT command is only accepted.");
goto end_func;
}
query_str = thd_query(thd);
ptr = *query_str;
for (; *ptr; ptr++) {
if (*ptr == quote) {
quote = '\0';
} else if (quote) {
} else if (*ptr == '`' || *ptr == '"') {
quote = *ptr;
} else {
long i;
for (i = 0; command_head[i]; i++) {
if (toupper((int)(unsigned char)(ptr[i]))
!= toupper((int)(unsigned char)
(command_head[i]))) {
goto nomatch;
}
}
break;
nomatch:
;
}
}
if (!*ptr) {
field_store_string(i_s_table->field[0],
"No XTRA_* command in the SQL statement."
" Please add /*!XTRA_xxxx*/ to the SQL.");
goto end_func;
}
if (!strncasecmp("XTRA_HELLO", ptr, 10)) {
/* This is example command XTRA_HELLO */
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: administration command test for XtraDB"
" 'XTRA_HELLO' was detected.\n");
field_store_string(i_s_table->field[0],
"Hello!");
goto end_func;
}
else if (!strncasecmp("XTRA_LRU_DUMP", ptr, 13)) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: administration command 'XTRA_LRU_DUMP'"
" was detected.\n");
if (buf_LRU_file_dump()) {
field_store_string(i_s_table->field[0],
"XTRA_LRU_DUMP was succeeded.");
} else {
field_store_string(i_s_table->field[0],
"XTRA_LRU_DUMP was failed.");
}
goto end_func;
}
else if (!strncasecmp("XTRA_LRU_RESTORE", ptr, 16)) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: administration command 'XTRA_LRU_RESTORE'"
" was detected.\n");
if (buf_LRU_file_restore()) {
field_store_string(i_s_table->field[0],
"XTRA_LRU_RESTORE was succeeded.");
} else {
field_store_string(i_s_table->field[0],
"XTRA_LRU_RESTORE was failed.");
}
goto end_func;
}
field_store_string(i_s_table->field[0],
"Undefined XTRA_* command.");
goto end_func;
end_func:
if (schema_table_store_record(thd, i_s_table)) {
DBUG_RETURN(1);
} else {
DBUG_RETURN(0);
}
}
static
int
i_s_innodb_admin_command_init(
/*==========================*/
void* p)
{
DBUG_ENTER("i_s_innodb_admin_command_init");
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = i_s_innodb_admin_command_info;
schema->fill_table = i_s_innodb_admin_command_fill;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_innodb_admin_command =
{
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
STRUCT_FLD(author, plugin_author),
STRUCT_FLD(descr, "XtraDB specific command acceptor"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_innodb_admin_command_init),
STRUCT_FLD(deinit, i_s_common_deinit),
STRUCT_FLD(version, 0x0100 /* 1.0 */),
STRUCT_FLD(status_vars, NULL),
STRUCT_FLD(system_vars, NULL),
STRUCT_FLD(__reserved1, NULL)
};

View File

@ -40,5 +40,6 @@ extern struct st_mysql_plugin i_s_innodb_patches;
extern struct st_mysql_plugin i_s_innodb_rseg;
extern struct st_mysql_plugin i_s_innodb_table_stats;
extern struct st_mysql_plugin i_s_innodb_index_stats;
extern struct st_mysql_plugin i_s_innodb_admin_command;
#endif /* i_s_h */

View File

@ -38,5 +38,10 @@ struct innodb_enhancement {
{"innodb_stats","Additional features about InnoDB statistics/optimizer","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_recovery_patches","Bugfixes and adjustments about recovery process","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_purge_thread","Enable to use purge devoted thread","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_admin_command_base","XtraDB specific command interface through i_s","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_show_lock_name","Show mutex/lock name instead of crated file/line","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_extend_slow","Extended statistics in slow.log","It is InnoDB-part only. It needs to patch also to mysqld.","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_relax_table_creation","Relax limitation of column size at table creation as builtin InnoDB.","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_lru_dump_restore","Dump and restore command for content of buffer pool","","http://www.percona.com/docs/wiki/percona-xtradb"},
{NULL, NULL, NULL, NULL}
};

File diff suppressed because it is too large Load Diff

View File

@ -389,6 +389,27 @@ ibuf_count_set(
}
#endif
/******************************************************************//**
Closes insert buffer and frees the data structures. */
UNIV_INTERN
void
ibuf_close(void)
/*============*/
{
mutex_free(&ibuf_pessimistic_insert_mutex);
memset(&ibuf_pessimistic_insert_mutex,
0x0, sizeof(ibuf_pessimistic_insert_mutex));
mutex_free(&ibuf_mutex);
memset(&ibuf_mutex, 0x0, sizeof(ibuf_mutex));
mutex_free(&ibuf_bitmap_mutex);
memset(&ibuf_bitmap_mutex, 0x0, sizeof(ibuf_mutex));
mem_free(ibuf);
ibuf = NULL;
}
/******************************************************************//**
Updates the size information of the ibuf, assuming the segment size has not
changed. */

View File

@ -618,7 +618,7 @@ enum btr_cur_method {
hash_node, and might be necessary to
update */
BTR_CUR_BINARY, /*!< success using the binary search */
BTR_CUR_INSERT_TO_IBUF, /*!< performed the intended insert to
BTR_CUR_INSERT_TO_IBUF /*!< performed the intended insert to
the insert buffer */
};

View File

@ -41,6 +41,12 @@ void
btr_search_sys_create(
/*==================*/
ulint hash_size); /*!< in: hash index hash table size */
/*****************************************************************//**
Frees the adaptive search system at a database shutdown. */
UNIV_INTERN
void
btr_search_sys_free(void);
/*=====================*/
/********************************************************************//**
Disable the adaptive hash search system and empty the index. */

View File

@ -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.
@ -825,14 +816,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
@ -840,7 +831,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.
@ -1026,14 +1018,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 */
@ -1073,16 +1057,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 */
@ -1112,7 +1090,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. */
/* resplit for optimistic use */
UT_LIST_NODE_T(buf_page_t) free;
UT_LIST_NODE_T(buf_page_t) flush_list;
@ -1155,18 +1142,8 @@ struct buf_page_struct{
debugging */
//#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
blocks in buf_pool->LRU_old */
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
@ -1174,6 +1151,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;
@ -1318,6 +1298,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
@ -1342,28 +1347,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;
@ -1379,10 +1372,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
@ -1406,17 +1395,18 @@ 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
the block to which LRU_old points
onward, including that block;
see buf0lru.c for the restrictions
on this value; not defined if
LRU_old == NULL;
on this value; 0 if LRU_old == NULL;
NOTE: LRU_old_len must be adjusted
whenever LRU_old shrinks or grows! */

View File

@ -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))));
}
}
/*********************************************************************//**
@ -125,23 +146,6 @@ try_again:
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());
ut_ad(mutex_own(&LRU_list_mutex));
buf_pool->ulint_clock++;
return(buf_pool->ulint_clock);
}
#endif /* !UNIV_HOTBACKUP */
/*********************************************************************//**
@ -287,21 +291,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()); /* This is used in optimistic */
return(bpage->LRU_position);
}
/*********************************************************************//**
Gets the mutex of a block.
@return pointer to mutex protecting bpage */
@ -508,10 +497,19 @@ buf_page_set_old(
ut_ad(bpage->in_LRU_list);
#ifdef UNIV_LRU_DEBUG
if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)
&& UT_LIST_GET_PREV(LRU, bpage)->old
== UT_LIST_GET_NEXT(LRU, bpage)->old) {
ut_a(UT_LIST_GET_PREV(LRU, bpage)->old == old);
ut_a((buf_pool->LRU_old_len == 0) == (buf_pool->LRU_old == NULL));
/* If a block is flagged "old", the LRU_old list must exist. */
ut_a(!old || buf_pool->LRU_old);
if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)) {
const buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage);
const buf_page_t* next = UT_LIST_GET_NEXT(LRU, bpage);
if (prev->old == next->old) {
ut_a(prev->old == old);
} else {
ut_a(!prev->old);
ut_a(buf_pool->LRU_old == (old ? bpage : next));
}
}
#endif /* UNIV_LRU_DEBUG */
@ -519,17 +517,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);
}
/*********************************************************************//**
@ -539,12 +537,16 @@ 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(buf_pool_mutex_own());
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
bpage->accessed = accessed;
if (!bpage->access_time) {
/* Make this the time of the first access. */
bpage->access_time = time_ms;
}
}
/*********************************************************************//**
@ -825,15 +827,15 @@ buf_page_get_newest_modification(
ib_uint64_t lsn;
mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
ut_a(block_mutex);
if (buf_page_in_file(bpage)) {
if (block_mutex && buf_page_in_file(bpage)) {
lsn = bpage->newest_modification;
} else {
lsn = 0;
}
if (block_mutex) {
mutex_exit(block_mutex);
}
return(lsn);
}

View File

@ -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
@ -203,6 +194,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. */
@ -210,6 +213,18 @@ UNIV_INTERN
void
buf_LRU_stat_update(void);
/*=====================*/
/********************************************************************//**
Dump the LRU page list to the specific file. */
UNIV_INTERN
ibool
buf_LRU_file_dump(void);
/*===================*/
/********************************************************************//**
Read the pages based on the specific file.*/
UNIV_INTERN
ibool
buf_LRU_file_restore(void);
/*======================*/
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/**********************************************************************//**
@ -229,6 +244,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

View File

@ -27,28 +27,59 @@ Created 11/5/1995 Heikki Tuuri
#define buf0rea_h
#include "univ.i"
#include "trx0types.h"
#include "buf0types.h"
/********************************************************************//**
Low-level function which reads a page asynchronously from a file to the
buffer buf_pool if it is not already there, in which case does nothing.
Sets the io_fix flag and sets an exclusive lock on the buffer frame. The
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
@return 1 if read request is issued. 0 if it is not */
UNIV_INTERN
ulint
buf_read_page_low(
/*==============*/
ulint* err, /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are
trying to read from a non-existent tablespace, or a
tablespace which is just now being dropped */
ibool sync, /*!< in: TRUE if synchronous aio is desired */
ulint mode, /*!< in: BUF_READ_IBUF_PAGES_ONLY, ...,
ORed to OS_AIO_SIMULATED_WAKE_LATER (see below
at read-ahead functions) */
ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size, or 0 */
ibool unzip, /*!< in: TRUE=request uncompressed page */
ib_int64_t tablespace_version, /*!< in: if the space memory object has
this timestamp different from what we are giving here,
treat the tablespace as dropped; this is a timestamp we
use to stop dangling page reads from a tablespace
which we have DISCARDed + IMPORTed back */
ulint offset, /*!< in: page number */
trx_t* trx);
/********************************************************************//**
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 */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
ulint offset);/*!< in: page number */
ulint offset, /*!< in: page number */
trx_t* trx);
/********************************************************************//**
Applies linear read-ahead if in the buf_pool the page is a border page of
a linear read-ahead area and all the pages in the area have been accessed.
Does not read any page if the read-ahead mechanism is not activated. Note
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
@ -74,8 +105,9 @@ buf_read_ahead_linear(
/*==================*/
ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
ulint offset);/*!< in: page number of a page; NOTE: the current thread
ulint offset, /*!< in: page number of a page; NOTE: the current thread
must want access to this page (see NOTE 3 above) */
trx_t* trx);
/********************************************************************//**
Issues read requests for pages which the ibuf module wants to read in, in
order to contract the insert buffer tree. Technically, this function is like

View File

@ -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;

View File

@ -32,6 +32,7 @@ enum db_err {
/* The following are error codes */
DB_ERROR,
DB_INTERRUPTED,
DB_OUT_OF_MEMORY,
DB_OUT_OF_FILE_SPACE,
DB_LOCK_WAIT,

View File

@ -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 */

View File

@ -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(
@ -1157,6 +1157,13 @@ void
dict_ind_init(void);
/*===============*/
/**********************************************************************//**
Closes the data dictionary module. */
UNIV_INTERN
void
dict_close(void);
/*============*/
#ifndef UNIV_NONINL
#include "dict0dict.ic"
#endif

View File

@ -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

View File

@ -224,15 +224,6 @@ fil_space_create(
0 for uncompressed tablespaces */
ulint purpose);/*!< in: FIL_TABLESPACE, or FIL_LOG if log */
/*******************************************************************//**
Frees a space object from a the tablespace memory cache. Closes the files in
the chain but does not delete them.
@return TRUE if success */
UNIV_INTERN
ibool
fil_space_free(
/*===========*/
ulint id); /*!< in: space id */
/*******************************************************************//**
Returns the size of the space in pages. The tablespace must be cached in the
memory cache.
@return space size, 0 if space not found */
@ -278,6 +269,12 @@ fil_init(
ulint hash_size, /*!< in: hash table size */
ulint max_n_open); /*!< in: max number of open files */
/*******************************************************************//**
Initializes the tablespace memory cache. */
UNIV_INTERN
void
fil_close(void);
/*===========*/
/*******************************************************************//**
Opens all log files and system tablespace data files. They stay open until the
database server shutdown. This should be called at a server startup after the
space objects for the log and the system tablespace have been created. The
@ -614,9 +611,12 @@ fil_space_get_n_reserved_extents(
Reads or writes data. This operation is asynchronous (aio).
@return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do
i/o on a tablespace which does not exist */
#define fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message) \
_fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message, NULL)
UNIV_INTERN
ulint
fil_io(
_fil_io(
/*===*/
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE,
ORed to OS_FILE_LOG, if a log i/o
@ -641,8 +641,25 @@ fil_io(
void* buf, /*!< in/out: buffer where to store read data
or from where to write; in aio this must be
appropriately aligned */
void* message); /*!< in: message for aio handler if non-sync
void* message, /*!< in: message for aio handler if non-sync
aio used, else ignored */
trx_t* trx);
/********************************************************************//**
Confirm whether the parameters are valid or not */
UNIV_INTERN
ibool
fil_area_is_exist(
/*==============*/
ulint space_id, /*!< in: space id */
ulint zip_size, /*!< in: compressed page size in bytes;
0 for uncompressed pages */
ulint block_offset, /*!< in: offset in number of blocks */
ulint byte_offset, /*!< in: remainder of offset in bytes; in
aio this must be divisible by the OS block
size */
ulint len); /*!< in: how many bytes to read or write; this
must not cross a file boundary; in aio this
must be a block size multiple */
/**********************************************************************//**
Waits for an aio operation to complete. This function is used to write the
handler for completed requests. The aio array of pending requests is divided

View File

@ -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 */

View File

@ -356,6 +356,12 @@ void
ibuf_print(
/*=======*/
FILE* file); /*!< in: file where to print */
/******************************************************************//**
Closes insert buffer and frees the data structures. */
UNIV_INTERN
void
ibuf_close(void);
/*============*/
#define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO
#define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO

View File

@ -59,6 +59,12 @@ lock_sys_create(
/*============*/
ulint n_cells); /*!< in: number of slots in lock hash table */
/*********************************************************************//**
Closes the lock system at database shutdown. */
UNIV_INTERN
void
lock_sys_close(void);
/*================*/
/*********************************************************************//**
Checks if some transaction has an implicit x-lock on a record in a clustered
index.
@return transaction which has the x-lock, or NULL */
@ -630,6 +636,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

View File

@ -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
@ -573,6 +572,18 @@ UNIV_INTERN
void
log_refresh_stats(void);
/*===================*/
/**********************************************************
Shutdown the log system but do not release all the memory. */
UNIV_INTERN
void
log_shutdown(void);
/*==============*/
/**********************************************************
Free the log system data structures. */
UNIV_INTERN
void
log_mem_free(void);
/*==============*/
extern log_t* log_sys;
@ -722,9 +733,12 @@ struct log_group_struct{
ulint lsn_offset; /*!< the offset of the above lsn */
ulint n_pending_writes;/*!< number of currently pending flush
writes for this log group */
byte** file_header_bufs_ptr;/*!< unaligned buffers */
byte** file_header_bufs;/*!< buffers for each file
header in the group */
#ifdef UNIV_LOG_ARCHIVE
/*-----------------------------*/
byte** archive_file_header_bufs_ptr;/*!< unaligned buffers */
byte** archive_file_header_bufs;/*!< buffers for each file
header in the group */
ulint archive_space_id;/*!< file space which
@ -743,10 +757,12 @@ struct log_group_struct{
completion function then sets the new
value to ..._file_no */
ulint next_archived_offset; /*!< like the preceding field */
#endif /* UNIV_LOG_ARCHIVE */
/*-----------------------------*/
ib_uint64_t scanned_lsn; /*!< used only in recovery: recovery scan
succeeded up to this lsn in this log
group */
byte* checkpoint_buf_ptr;/*!< unaligned checkpoint header */
byte* checkpoint_buf; /*!< checkpoint header is written from
this buffer to the group */
UT_LIST_NODE_T(log_group_t)
@ -764,6 +780,7 @@ struct log_struct{
#ifndef UNIV_HOTBACKUP
mutex_t mutex; /*!< mutex protecting the log */
#endif /* !UNIV_HOTBACKUP */
byte* buf_ptr; /* unaligned log buffer */
byte* buf; /*!< log buffer */
ulint buf_size; /*!< log buffer size in bytes */
ulint max_buf_free; /*!< recommended maximum value of
@ -900,6 +917,7 @@ struct log_struct{
should wait for this without owning
the log mutex */
#endif /* !UNIV_HOTBACKUP */
byte* checkpoint_buf_ptr;/* unaligned checkpoint header */
byte* checkpoint_buf; /*!< checkpoint header is read to this
buffer */
/* @} */

View File

@ -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);
}
/***********************************************************************//**

View File

@ -239,6 +239,18 @@ UNIV_INTERN
void
recv_sys_create(void);
/*=================*/
/**********************************************************//**
Release recovery system mutexes. */
UNIV_INTERN
void
recv_sys_close(void);
/*================*/
/********************************************************//**
Frees the recovery system memory. */
UNIV_INTERN
void
recv_sys_mem_free(void);
/*===================*/
/********************************************************//**
Inits the recovery system for a recovery operation. */
UNIV_INTERN
@ -246,6 +258,12 @@ void
recv_sys_init(
/*==========*/
ulint available_memory); /*!< in: available memory in bytes */
/********************************************************//**
Reset the state of the recovery system variables. */
UNIV_INTERN
void
recv_sys_var_init(void);
/*===================*/
/*******************************************************************//**
Empties the hash table of stored log records, applying them to appropriate
pages. */
@ -412,6 +430,39 @@ struct recv_sys_struct{
hash_table_t* addr_hash;/*!< hash table of file addresses of pages */
ulint n_addrs;/*!< number of not processed hashed file
addresses in the hash table */
/* If you modified the following defines at original file,
You should also modify them. */
/* defined in os0file.c */
#define OS_AIO_MERGE_N_CONSECUTIVE 64
/* defined in log0recv.c */
#define RECV_READ_AHEAD_AREA 32
time_t stats_recv_start_time;
ulint stats_recv_turns;
ulint stats_read_requested_pages;
ulint stats_read_in_area[RECV_READ_AHEAD_AREA];
ulint stats_read_io_pages;
ulint stats_read_io_consecutive[OS_AIO_MERGE_N_CONSECUTIVE];
ulint stats_write_io_pages;
ulint stats_write_io_consecutive[OS_AIO_MERGE_N_CONSECUTIVE];
ulint stats_doublewrite_check_pages;
ulint stats_doublewrite_overwrite_pages;
ulint stats_recover_pages_with_read;
ulint stats_recover_pages_without_read;
ulint stats_log_recs;
ulint stats_log_len_sum;
ulint stats_applied_log_recs;
ulint stats_applied_log_len_sum;
ulint stats_pages_already_new;
ib_uint64_t stats_oldest_modified_lsn;
ib_uint64_t stats_newest_modified_lsn;
};
/** The recovery system */
@ -433,6 +484,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

View File

@ -82,6 +82,13 @@ void
mem_init(
/*=====*/
ulint size); /*!< in: common pool size in bytes */
/******************************************************************//**
Closes the memory system. */
UNIV_INTERN
void
mem_close(void);
/*===========*/
/**************************************************************//**
Use this macro instead of the corresponding function! Macro for memory
heap creation. */

View File

@ -62,6 +62,13 @@ mem_pool_create(
/*============*/
ulint size); /*!< in: pool size in bytes */
/********************************************************************//**
Frees a memory pool. */
UNIV_INTERN
void
mem_pool_free(
/*==========*/
mem_pool_t* pool); /*!< in, own: memory pool */
/********************************************************************//**
Allocates memory from a pool. NOTE: This low-level function should only be
used in mem0mem.*!
@return own: allocated memory buffer */

View File

@ -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

View File

@ -53,6 +53,7 @@ Created 10/21/1995 Heikki Tuuri
#define os0file_h
#include "univ.i"
#include "trx0types.h"
#ifndef __WIN__
#include <dirent.h>
@ -157,6 +158,8 @@ log. */
to become available again */
#define OS_FILE_SHARING_VIOLATION 76
#define OS_FILE_ERROR_NOT_SPECIFIED 77
#define OS_FILE_INSUFFICIENT_RESOURCE 78
#define OS_FILE_OPERATION_ABORTED 79
/* @} */
/** Types for aio operations @{ */
@ -497,9 +500,12 @@ os_file_get_last_error(
/*******************************************************************//**
Requests a synchronous read operation.
@return TRUE if request was successful, FALSE if fail */
#define os_file_read(file, buf, offset, offset_high, n) \
_os_file_read(file, buf, offset, offset_high, n, NULL)
UNIV_INTERN
ibool
os_file_read(
_os_file_read(
/*=========*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
@ -507,7 +513,8 @@ os_file_read(
offset where to read */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n); /*!< in: number of bytes to read */
ulint n, /*!< in: number of bytes to read */
trx_t* trx);
/*******************************************************************//**
Rewind file to its start, read at most size - 1 bytes from it to str, and
NUL-terminate str. All errors are silently ignored. This function is
@ -619,6 +626,13 @@ os_aio_init(
ulint n_write_segs, /*<! in: number of writer threads */
ulint n_slots_sync); /*<! in: number of slots in the sync aio
array */
/***********************************************************************
Frees the asynchronous io system. */
UNIV_INTERN
void
os_aio_free(void);
/*=============*/
/*******************************************************************//**
Requests an asynchronous i/o operation.
@return TRUE if request was queued successfully, FALSE if fail */
@ -654,10 +668,11 @@ os_aio(
(can be used to identify a completed
aio operation); ignored if mode is
OS_AIO_SYNC */
void* message2);/*!< in: message for the aio handler
void* message2,/*!< in: message for the aio handler
(can be used to identify a completed
aio operation); ignored if mode is
OS_AIO_SYNC */
trx_t* trx);
/************************************************************************//**
Wakes up all async i/o threads so that they know to exit themselves in
shutdown. */

View File

@ -285,43 +285,73 @@ 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)
# 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
# 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)
@ -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
/* 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"

View File

@ -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 */

View File

@ -907,7 +907,7 @@ page_get_data_size(
/************************************************************//**
Allocates a block of memory from the free list of an index page. */
UNIV_INTERN
UNIV_INLINE
void
page_mem_alloc_free(
/*================*/

View File

@ -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(

View File

@ -583,6 +583,12 @@ pars_info_get_bound_id(
pars_info_t* info, /*!< in: info struct */
const char* name); /*!< in: bound id name to find */
/******************************************************************//**
Release any resources used by the lexer. */
UNIV_INTERN
void
pars_lexer_close(void);
/*==================*/
/** Extra information supplied for pars_sql(). */
struct pars_info_struct {

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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(
@ -754,8 +756,6 @@ struct row_prebuilt_struct {
store it here so that we can return
it to MySQL */
/*----------------------*/
UT_LIST_NODE_T(row_prebuilt_t) prebuilts;
/*!< list node of table->prebuilts */
ulint magic_n2; /*!< this should be the same as
magic_n */
};

View File

@ -80,6 +80,9 @@ at a time */
#define SRV_AUTO_EXTEND_INCREMENT \
(srv_auto_extend_increment * ((1024 * 1024) / UNIV_PAGE_SIZE))
/* prototypes for new functions added to ha_innodb.cc */
ibool innobase_get_slow_log();
/* This is set to TRUE if the MySQL user has set it in MySQL */
extern ibool srv_lower_case_table_names;
@ -133,8 +136,9 @@ extern ulint* srv_data_file_is_raw_partition;
extern ibool srv_extra_undoslots;
extern ibool srv_fast_recovery;
extern ibool srv_recovery_stats;
extern ibool srv_use_purge_thread;
extern ulint srv_use_purge_thread;
extern ibool srv_auto_extend_last_data_file;
extern ulint srv_last_file_size_max;
@ -235,12 +239,14 @@ extern ulong srv_replication_delay;
extern long long srv_ibuf_max_size;
extern ulong srv_ibuf_active_contract;
extern ulong srv_ibuf_accel_rate;
extern ulint srv_checkpoint_age_target;
extern ulong srv_flush_neighbor_pages;
extern ulong srv_enable_unsafe_group_commit;
extern ulong srv_read_ahead;
extern ulong srv_adaptive_checkpoint;
extern ulong srv_expand_import;
extern ulint srv_relax_table_creation;
extern ulong srv_extra_rsegments;
extern ulong srv_dict_size_limit;
@ -345,10 +351,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;
@ -428,6 +430,7 @@ enum srv_thread_type {
SRV_INSERT, /**< thread flushing the insert buffer to disk */
#endif
SRV_PURGE, /* thread purging undo records */
SRV_PURGE_WORKER, /* thread purging undo records */
SRV_MASTER /**< the master thread, (whose type number must
be biggest) */
};
@ -446,7 +449,7 @@ void
srv_init(void);
/*==========*/
/*********************************************************************//**
Frees the OS fast mutex created in srv_boot(). */
Frees the data structures created in srv_init(). */
UNIV_INTERN
void
srv_free(void);
@ -509,6 +512,13 @@ srv_purge_thread(
/*=============*/
void* arg); /* in: a dummy parameter required by
os_thread_create */
/*************************************************************************
The undo purge thread. */
UNIV_INTERN
os_thread_ret_t
srv_purge_worker_thread(
/*====================*/
void* arg);
/*******************************************************************//**
Tells the Innobase server that there has been activity in the database
and wakes up the master thread if it is suspended (not sleeping). Used
@ -645,13 +655,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 */
@ -663,9 +673,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

View File

@ -120,7 +120,7 @@ is necessary only if the memory block containing it is freed. */
# endif /* UNIV_SYNC_DEBUG */
#else /* UNIV_DEBUG */
# define rw_lock_create(L, level) \
rw_lock_create_func((L), __FILE__, __LINE__)
rw_lock_create_func((L), #L, NULL, 0)
#endif /* UNIV_DEBUG */
/******************************************************************//**
@ -137,8 +137,8 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
#endif /* UNIV_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */
/******************************************************************//**
@ -540,7 +540,8 @@ struct rw_lock_struct {
ulint level; /*!< Level in the global latching order. */
#endif /* UNIV_SYNC_DEBUG */
ulint count_os_wait; /*!< Count of os_waits. May not be accurate */
const char* cfile_name;/*!< File name where lock created */
//const char* cfile_name;/*!< File name where lock created */
const char* lock_name;/*!< lock name */
/* last s-lock file/line is not guaranteed to be correct */
const char* last_s_file_name;/*!< File name where last s-locked */
const char* last_x_file_name;/*!< File name where last x-locked */
@ -551,7 +552,7 @@ struct rw_lock_struct {
are at the start of this struct, thus we can
peek this field without causing much memory
bus traffic */
unsigned cline:14; /*!< Line where created */
//unsigned cline:14; /*!< Line where created */
unsigned last_s_line:14; /*!< Line number where last time s-locked */
unsigned last_x_line:14; /*!< Line number where last time x-locked */
ulint magic_n; /*!< RW_LOCK_MAGIC_N */

View File

@ -80,7 +80,7 @@ necessary only if the memory block containing it is freed. */
# endif
#else
# define mutex_create(M, level) \
mutex_create_func((M), __FILE__, __LINE__)
mutex_create_func((M), #M, NULL, 0)
#endif
/******************************************************************//**
@ -93,8 +93,8 @@ void
mutex_create_func(
/*==============*/
mutex_t* mutex, /*!< in: pointer to memory */
#ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
@ -513,7 +513,7 @@ struct mutex_struct {
os_fast_mutex; /*!< We use this OS mutex in place of lock_word
when atomic operations are not enabled */
#endif
ulint waiters; /*!< This ulint is set to 1 if there are (or
volatile ulint waiters; /*!< This ulint is set to 1 if there are (or
may be) threads waiting in the global wait
array for this mutex to be released.
Otherwise, this is 0. */
@ -524,9 +524,9 @@ struct mutex_struct {
ulint line; /*!< Line where the mutex was locked */
ulint level; /*!< Level in the global latching order */
#endif /* UNIV_SYNC_DEBUG */
#ifdef UNIV_DEBUG
const char* cfile_name;/*!< File name where mutex created */
ulint cline; /*!< Line where created */
#ifdef UNIV_DEBUG
os_thread_id_t thread_id; /*!< The thread id of the thread
which locked the mutex. */
ulint magic_n; /*!< MUTEX_MAGIC_N */
@ -541,9 +541,9 @@ struct mutex_struct {
ulong count_os_yield; /*!< count of os_wait */
ulonglong lspent_time; /*!< mutex os_wait timer msec */
ulonglong lmax_spent_time;/*!< mutex os_wait timer msec */
const char* cmutex_name; /*!< mutex name */
ulint mutex_type; /*!< 0=usual mutex, 1=rw_lock mutex */
#endif /* UNIV_DEBUG */
const char* cmutex_name; /*!< mutex name */
};
/** The global array of wait cells for implementation of the databases own

View File

@ -39,6 +39,12 @@ UNIV_INTERN
void
thr_local_init(void);
/*================*/
/****************************************************************//**
Close the thread local storage module. */
UNIV_INTERN
void
thr_local_close(void);
/*=================*/
/*******************************************************************//**
Creates a local storage struct for the calling new thread. */
UNIV_INTERN

View File

@ -141,6 +141,13 @@ void
trx_i_s_cache_init(
/*===============*/
trx_i_s_cache_t* cache); /*!< out: cache to init */
/*******************************************************************//**
Free the INFORMATION SCHEMA trx related cache. */
UNIV_INTERN
void
trx_i_s_cache_free(
/*===============*/
trx_i_s_cache_t* cache); /*!< in/out: cache to free */
/*******************************************************************//**
Issue a shared/read lock on the tables cache. */

View File

@ -71,6 +71,12 @@ void
trx_purge_sys_create(void);
/*======================*/
/********************************************************************//**
Frees the global purge system control structure. */
UNIV_INTERN
void
trx_purge_sys_close(void);
/*======================*/
/************************************************************************
Adds the update undo log as the first log in the history list. Removes the
update undo log segment from the rseg slot if it is too big for reuse. */
UNIV_INTERN
@ -108,6 +114,25 @@ UNIV_INTERN
ulint
trx_purge(void);
/*===========*/
/**********************************************************************
This function runs a purge worker batch */
UNIV_INTERN
void
trx_purge_worker(
/*=============*/
ulint worker_id);
/**********************************************************************
This function waits the event for worker batch */
UNIV_INTERN
void
trx_purge_worker_wait(void);
/*========================*/
/**********************************************************************
This function wakes the waiting worker batch */
UNIV_INTERN
void
trx_purge_worker_wake(void);
/*========================*/
/******************************************************************//**
Prints information of the purge system to stderr. */
UNIV_INTERN
@ -125,6 +150,11 @@ struct trx_purge_struct{
of the trx system and it never ends */
que_t* query; /*!< The query graph which will do the
parallelized purge operation */
ulint n_worker;
os_event_t worker_event;
sess_t** sess_arr;
trx_t** trx_arr;
que_t** query_arr;
rw_lock_t latch; /*!< The latch protecting the purge view.
A purge operation must acquire an
x-latch here for the instant at which

View File

@ -44,7 +44,7 @@ UNIV_INLINE
trx_undo_rec_t*
trx_undo_rec_copy(
/*==============*/
trx_undo_rec_t* undo_rec, /*!< in: undo log record */
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.

View File

@ -100,7 +100,7 @@ UNIV_INLINE
trx_undo_rec_t*
trx_undo_rec_copy(
/*==============*/
trx_undo_rec_t* undo_rec, /*!< in: undo log record */
const trx_undo_rec_t* undo_rec, /*!< in: undo log record */
mem_heap_t* heap) /*!< in: heap where copied */
{
ulint len;

View File

@ -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

View File

@ -125,6 +125,13 @@ trx_rseg_create(
ulint max_size, /*!< in: max size in pages */
ulint* id, /*!< out: rseg id */
mtr_t* mtr); /*!< in: mtr */
/***************************************************************************
Free's an instance of the rollback segment in memory. */
UNIV_INTERN
void
trx_rseg_mem_free(
/*==============*/
trx_rseg_t* rseg); /* in, own: instance to free */
/* Real max value may be 4076 in usual. But reserve 4 slot for safety or etc... */

View File

@ -344,6 +344,12 @@ void
trx_sys_file_format_tag_init(void);
/*==============================*/
/*****************************************************************//**
Shutdown/Close the transaction system. */
UNIV_INTERN
void
trx_sys_close(void);
/*===============*/
/*****************************************************************//**
Get the name representation of the file format from its id.
@return pointer to the name */
UNIV_INTERN

Some files were not shown because too many files have changed in this diff Show More