Browse Source

Merge XtraDB from Percona-Server-5.5.20-24.1 into MariaDB 5.5.

pull/374/head
unknown 14 years ago
parent
commit
4917073305
  1. 2
      VERSION
  2. 1
      mysql-test/suite/percona/percona_flush_contiguous_neighbors-master.opt
  3. 21
      mysql-test/suite/percona/percona_flush_contiguous_neighbors.result
  4. 37
      mysql-test/suite/percona/percona_flush_contiguous_neighbors.test
  5. 52
      mysql-test/suite/percona/percona_query_response_time-replication.result
  6. 52
      mysql-test/suite/percona/percona_query_response_time-stored.result
  7. 104
      mysql-test/suite/percona/percona_query_response_time.result
  8. 2
      mysql-test/suite/percona/percona_server_variables_debug.result
  9. 1
      mysql-test/suite/percona/percona_server_variables_release.result
  10. 35
      mysql-test/suite/percona/percona_sync_flush.result
  11. 33
      mysql-test/suite/percona/percona_sync_flush.test
  12. 22
      mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments.inc
  13. 200
      mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments.result
  14. 200
      mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments_disable.result
  15. 31
      mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.result
  16. 40
      mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.test
  17. 15
      mysql-test/suite/sys_vars/r/innodb_flush_checkpoint_debug_basic.result
  18. 12
      mysql-test/suite/sys_vars/t/innodb_flush_checkpoint_debug_basic.test
  19. 16
      storage/xtradb/btr/btr0btr.c
  20. 31
      storage/xtradb/btr/btr0cur.c
  21. 2
      storage/xtradb/btr/btr0pcur.c
  22. 304
      storage/xtradb/btr/btr0sea.c
  23. 208
      storage/xtradb/buf/buf0buf.c
  24. 66
      storage/xtradb/buf/buf0flu.c
  25. 186
      storage/xtradb/buf/buf0lru.c
  26. 5
      storage/xtradb/dict/dict0dict.c
  27. 4
      storage/xtradb/dict/dict0load.c
  28. 49
      storage/xtradb/fil/fil0fil.c
  29. 67
      storage/xtradb/fsp/fsp0fsp.c
  30. 70
      storage/xtradb/ha/ha0ha.c
  31. 95
      storage/xtradb/handler/ha_innodb.cc
  32. 2
      storage/xtradb/handler/i_s.cc
  33. 317
      storage/xtradb/ibuf/ibuf0ibuf.c
  34. 18
      storage/xtradb/include/btr0cur.h
  35. 8
      storage/xtradb/include/btr0pcur.h
  36. 32
      storage/xtradb/include/btr0pcur.ic
  37. 42
      storage/xtradb/include/btr0sea.h
  38. 29
      storage/xtradb/include/btr0types.h
  39. 68
      storage/xtradb/include/buf0buf.h
  40. 44
      storage/xtradb/include/buf0buf.ic
  41. 5
      storage/xtradb/include/buf0types.h
  42. 23
      storage/xtradb/include/fil0fil.h
  43. 102
      storage/xtradb/include/fsp0fsp.h
  44. 34
      storage/xtradb/include/fsp0fsp.ic
  45. 23
      storage/xtradb/include/ha0ha.h
  46. 54
      storage/xtradb/include/ha0ha.ic
  47. 4
      storage/xtradb/include/page0page.h
  48. 1
      storage/xtradb/include/row0upd.ic
  49. 3
      storage/xtradb/include/srv0srv.h
  50. 5
      storage/xtradb/include/sync0rw.h
  51. 1
      storage/xtradb/include/sync0rw.ic
  52. 1
      storage/xtradb/include/sync0sync.h
  53. 1
      storage/xtradb/include/trx0trx.h
  54. 2
      storage/xtradb/include/univ.i
  55. 45
      storage/xtradb/log/log0log.c
  56. 16
      storage/xtradb/page/page0page.c
  57. 2
      storage/xtradb/page/page0zip.c
  58. 23
      storage/xtradb/row/row0ins.c
  59. 13
      storage/xtradb/row/row0mysql.c
  60. 29
      storage/xtradb/srv/srv0srv.c
  61. 28
      storage/xtradb/srv/srv0start.c
  62. 9
      storage/xtradb/sync/sync0rw.c
  63. 1
      storage/xtradb/sync/sync0sync.c

2
VERSION

@ -1,4 +1,4 @@
MYSQL_VERSION_MAJOR=5
MYSQL_VERSION_MINOR=5
MYSQL_VERSION_PATCH=21
MYSQL_VERSION_PATCH=20
MYSQL_VERSION_EXTRA=

1
mysql-test/suite/percona/percona_flush_contiguous_neighbors-master.opt

@ -0,0 +1 @@
--innodb_flush_neighbor_pages=cont

21
mysql-test/suite/percona/percona_flush_contiguous_neighbors.result

@ -0,0 +1,21 @@
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (id INT AUTO_INCREMENT, foo CHAR(255), PRIMARY KEY (id)) ENGINE=InnoDB;
INSERT INTO t1(foo) VALUES ('a'), ('b');
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
DROP TABLE t1;

37
mysql-test/suite/percona/percona_flush_contiguous_neighbors.test

@ -0,0 +1,37 @@
# Test for innodb_flush_neighbor_pages=contiguous.
# The test is very crude: we simply overflow the buffer pool with such a number of
# new/modified pages that some flushing is bound to happen.
--source include/have_innodb.inc
--source include/big_test.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1 (id INT AUTO_INCREMENT, foo CHAR(255), PRIMARY KEY (id)) ENGINE=InnoDB;
INSERT INTO t1(foo) VALUES ('a'), ('b');
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
INSERT INTO t1(foo) SELECT foo FROM t1;
# TODO: cannot record a stable value here. A check of > 0 should be enough,
# but the variable is not accessible through INFORMATION_SCHEMA currently.
# SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_flushed';
DROP TABLE t1;

52
mysql-test/suite/percona/percona_query_response_time-replication.result

@ -100,10 +100,10 @@ SHOW QUERY_RESPONSE_TIME;
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -146,10 +146,10 @@ time count total
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
@ -251,10 +251,10 @@ SHOW QUERY_RESPONSE_TIME;
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -297,10 +297,10 @@ time count total
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
@ -375,7 +375,7 @@ SHOW QUERY_RESPONSE_TIME;
1000.000000 0 0.000000
10000.000000 0 0.000000
100000.000000 0 0.000000
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -391,7 +391,7 @@ time count total
1000.000000 0 0.000000
10000.000000 0 0.000000
100000.000000 0 0.000000
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
@ -469,7 +469,7 @@ SHOW QUERY_RESPONSE_TIME;
16807.000000 0 0.000000
117649.000000 0 0.000000
823543.000000 0 0.000000
5764801.00000 0 0.000000
5764801.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -488,7 +488,7 @@ time count total
16807.000000 0 0.000000
117649.000000 0 0.000000
823543.000000 0 0.000000
5764801.00000 0 0.000000
5764801.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
@ -556,7 +556,7 @@ SHOW QUERY_RESPONSE_TIME;
1.000000 34 12.250000
156.000000 33 77.099997
24336.000000 0 0.000000
3796416.00000 0 0.000000
3796416.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -565,7 +565,7 @@ time count total
1.000000 34 12.250000
156.000000 33 77.099997
24336.000000 0 0.000000
3796416.00000 0 0.000000
3796416.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
@ -632,7 +632,7 @@ SHOW QUERY_RESPONSE_TIME;
0.001000 0 0.000000
1.000000 34 12.250000
1000.000000 33 77.099997
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -640,7 +640,7 @@ time count total
0.001000 0 0.000000
1.000000 34 12.250000
1000.000000 33 77.099997
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
@ -709,7 +709,7 @@ SHOW QUERY_RESPONSE_TIME;
0.001000 0 0.000000
1.000000 34 12.250000
1000.000000 33 77.099997
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -717,7 +717,7 @@ time count total
0.001000 0 0.000000
1.000000 34 12.250000
1000.000000 33 77.099997
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;

52
mysql-test/suite/percona/percona_query_response_time-stored.result

@ -80,10 +80,10 @@ SHOW QUERY_RESPONSE_TIME;
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -126,10 +126,10 @@ time count total
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET SESSION query_exec_time=0.1;
@ -204,10 +204,10 @@ SHOW QUERY_RESPONSE_TIME;
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -250,10 +250,10 @@ time count total
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET SESSION query_exec_time=0.1;
@ -301,7 +301,7 @@ SHOW QUERY_RESPONSE_TIME;
1000.000000 0 0.000000
10000.000000 0 0.000000
100000.000000 0 0.000000
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -317,7 +317,7 @@ time count total
1000.000000 0 0.000000
10000.000000 0 0.000000
100000.000000 0 0.000000
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET SESSION query_exec_time=0.1;
@ -368,7 +368,7 @@ SHOW QUERY_RESPONSE_TIME;
16807.000000 0 0.000000
117649.000000 0 0.000000
823543.000000 0 0.000000
5764801.00000 0 0.000000
5764801.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -387,7 +387,7 @@ time count total
16807.000000 0 0.000000
117649.000000 0 0.000000
823543.000000 0 0.000000
5764801.00000 0 0.000000
5764801.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET SESSION query_exec_time=0.1;
@ -428,7 +428,7 @@ SHOW QUERY_RESPONSE_TIME;
1.000000 55 8.450000
156.000000 11 25.699999
24336.000000 0 0.000000
3796416.00000 0 0.000000
3796416.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -437,7 +437,7 @@ time count total
1.000000 55 8.450000
156.000000 11 25.699999
24336.000000 0 0.000000
3796416.00000 0 0.000000
3796416.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET SESSION query_exec_time=0.1;
@ -477,7 +477,7 @@ SHOW QUERY_RESPONSE_TIME;
0.001000 0 0.000000
1.000000 55 8.450000
1000.000000 11 25.699999
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -485,7 +485,7 @@ time count total
0.001000 0 0.000000
1.000000 55 8.450000
1000.000000 11 25.699999
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET SESSION query_exec_time=0.1;
@ -527,7 +527,7 @@ SHOW QUERY_RESPONSE_TIME;
0.001000 0 0.000000
1.000000 55 8.450000
1000.000000 11 25.699999
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -535,7 +535,7 @@ time count total
0.001000 0 0.000000
1.000000 55 8.450000
1000.000000 11 25.699999
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;

104
mysql-test/suite/percona/percona_query_response_time.result

@ -45,10 +45,10 @@ SHOW QUERY_RESPONSE_TIME;
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -91,10 +91,10 @@ time count total
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
SET SESSION query_exec_time=0.31;
@ -231,10 +231,10 @@ SHOW QUERY_RESPONSE_TIME;
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -277,10 +277,10 @@ time count total
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET SESSION query_exec_time=0.1;
@ -328,10 +328,10 @@ SHOW QUERY_RESPONSE_TIME;
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -374,10 +374,10 @@ time count total
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
SET SESSION query_exec_time=0.31;
@ -514,10 +514,10 @@ SHOW QUERY_RESPONSE_TIME;
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -560,10 +560,10 @@ time count total
131072.000000 0 0.000000
262144.000000 0 0.000000
524288.000000 0 0.000000
1048576.00000 0 0.000000
2097152.00000 0 0.000000
4194304.00000 0 0.000000
8388608.00000 0 0.000000
1048576.000000 0 0.000000
2097152.000000 0 0.000000
4194304.000000 0 0.000000
8388608.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET SESSION query_exec_time=0.1;
@ -584,7 +584,7 @@ SHOW QUERY_RESPONSE_TIME;
1000.000000 0 0.000000
10000.000000 0 0.000000
100000.000000 0 0.000000
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -600,7 +600,7 @@ time count total
1000.000000 0 0.000000
10000.000000 0 0.000000
100000.000000 0 0.000000
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
SET SESSION query_exec_time=0.31;
@ -710,7 +710,7 @@ SHOW QUERY_RESPONSE_TIME;
1000.000000 0 0.000000
10000.000000 0 0.000000
100000.000000 0 0.000000
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -726,7 +726,7 @@ time count total
1000.000000 0 0.000000
10000.000000 0 0.000000
100000.000000 0 0.000000
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET SESSION query_exec_time=0.1;
@ -750,7 +750,7 @@ SHOW QUERY_RESPONSE_TIME;
16807.000000 0 0.000000
117649.000000 0 0.000000
823543.000000 0 0.000000
5764801.00000 0 0.000000
5764801.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -769,7 +769,7 @@ time count total
16807.000000 0 0.000000
117649.000000 0 0.000000
823543.000000 0 0.000000
5764801.00000 0 0.000000
5764801.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
SET SESSION query_exec_time=0.31;
@ -882,7 +882,7 @@ SHOW QUERY_RESPONSE_TIME;
16807.000000 0 0.000000
117649.000000 0 0.000000
823543.000000 0 0.000000
5764801.00000 0 0.000000
5764801.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -901,7 +901,7 @@ time count total
16807.000000 0 0.000000
117649.000000 0 0.000000
823543.000000 0 0.000000
5764801.00000 0 0.000000
5764801.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET SESSION query_exec_time=0.1;
@ -915,7 +915,7 @@ SHOW QUERY_RESPONSE_TIME;
1.000000 0 0.000000
156.000000 0 0.000000
24336.000000 0 0.000000
3796416.00000 0 0.000000
3796416.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -924,7 +924,7 @@ time count total
1.000000 0 0.000000
156.000000 0 0.000000
24336.000000 0 0.000000
3796416.00000 0 0.000000
3796416.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
SET SESSION query_exec_time=0.31;
@ -1027,7 +1027,7 @@ SHOW QUERY_RESPONSE_TIME;
1.000000 11 4.050000
156.000000 11 25.699999
24336.000000 0 0.000000
3796416.00000 0 0.000000
3796416.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -1036,7 +1036,7 @@ time count total
1.000000 11 4.050000
156.000000 11 25.699999
24336.000000 0 0.000000
3796416.00000 0 0.000000
3796416.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET SESSION query_exec_time=0.1;
@ -1049,7 +1049,7 @@ SHOW QUERY_RESPONSE_TIME;
0.001000 0 0.000000
1.000000 0 0.000000
1000.000000 0 0.000000
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -1057,7 +1057,7 @@ time count total
0.001000 0 0.000000
1.000000 0 0.000000
1000.000000 0 0.000000
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
SET SESSION query_exec_time=0.31;
@ -1159,7 +1159,7 @@ SHOW QUERY_RESPONSE_TIME;
0.001000 0 0.000000
1.000000 11 4.050000
1000.000000 11 25.699999
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -1167,7 +1167,7 @@ time count total
0.001000 0 0.000000
1.000000 11 4.050000
1000.000000 11 25.699999
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET SESSION query_exec_time=0.1;
@ -1182,7 +1182,7 @@ SHOW QUERY_RESPONSE_TIME;
0.001000 0 0.000000
1.000000 0 0.000000
1000.000000 0 0.000000
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -1190,7 +1190,7 @@ time count total
0.001000 0 0.000000
1.000000 0 0.000000
1000.000000 0 0.000000
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
SET SESSION query_exec_time=0.31;
@ -1292,7 +1292,7 @@ SHOW QUERY_RESPONSE_TIME;
0.001000 0 0.000000
1.000000 11 4.050000
1000.000000 11 25.699999
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
time count total
@ -1300,7 +1300,7 @@ time count total
0.001000 0 0.000000
1.000000 11 4.050000
1000.000000 11 25.699999
1000000.00000 0 0.000000
1000000.000000 0 0.000000
TOO LONG 0 TOO LONG
SET SESSION query_exec_time=default;
SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;

2
mysql-test/suite/percona/percona_server_variables_debug.result

@ -109,6 +109,7 @@ INNODB_FILE_FORMAT
INNODB_FILE_FORMAT_CHECK
INNODB_FILE_FORMAT_MAX
INNODB_FILE_PER_TABLE
INNODB_FLUSH_CHECKPOINT_DEBUG
INNODB_FLUSH_LOG_AT_TRX_COMMIT
INNODB_FLUSH_METHOD
INNODB_FLUSH_NEIGHBOR_PAGES
@ -228,6 +229,7 @@ MAX_SP_RECURSION_DEPTH
MAX_TMP_TABLES
MAX_USER_CONNECTIONS
MAX_WRITE_LOCK_COUNT
METADATA_LOCKS_CACHE_SIZE
MIN_EXAMINED_ROW_LIMIT
MULTI_RANGE_COUNT
MYISAM_DATA_POINTER_SIZE

1
mysql-test/suite/percona/percona_server_variables_release.result

@ -225,6 +225,7 @@ MAX_SP_RECURSION_DEPTH
MAX_TMP_TABLES
MAX_USER_CONNECTIONS
MAX_WRITE_LOCK_COUNT
METADATA_LOCKS_CACHE_SIZE
MIN_EXAMINED_ROW_LIMIT
MULTI_RANGE_COUNT
MYISAM_DATA_POINTER_SIZE

35
mysql-test/suite/percona/percona_sync_flush.result

@ -0,0 +1,35 @@
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (id INT AUTO_INCREMENT, foo CHAR(255), PRIMARY KEY (id)) ENGINE=InnoDB;
SET @@global.innodb_flush_checkpoint_debug=1;
INSERT INTO t1(foo) VALUES ('a'), ('b');
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
SET @@global.innodb_flush_checkpoint_debug=0;
UPDATE t1 SET foo='d' WHERE foo='c';
DROP TABLE t1;

33
mysql-test/suite/percona/percona_sync_flush.test

@ -0,0 +1,33 @@
# Test for InnoDB sync state flushing.
--source include/have_innodb.inc
--source include/have_debug.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1 (id INT AUTO_INCREMENT, foo CHAR(255), PRIMARY KEY (id)) ENGINE=InnoDB;
# It is hard to get to InnoDB sync state flushing in MTR with regular workload. Perhaps
# it is possible with many parallel connections, but that would be brittle anyway.
# So, just disable preflushing and checkpointing and issue simple workload.
SET @@global.innodb_flush_checkpoint_debug=1;
INSERT INTO t1(foo) VALUES ('a'), ('b');
let $rep=0;
while ($rep < 14)
{
INSERT INTO t1(foo) SELECT foo FROM t1;
UPDATE t1 SET foo='c';
inc $rep;
}
# By now checkpoint age should be well past sync flush point. Allow
# preflushing/checkpointing again and do some work in order to do the sync flush.
SET @@global.innodb_flush_checkpoint_debug=0;
UPDATE t1 SET foo='d' WHERE foo='c';
DROP TABLE t1;

22
mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments.inc

@ -91,5 +91,27 @@ let $query=select * from t1 -- comment in the end
;
--source percona_query_cache_with_comments_eval.inc
let $query=select */* a comment \*/from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select *# a comment \\
from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select *-- a comment \\
from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select "\\\\"" /* not a comment */" from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select "\\\\"" /*! not a comment */" from t1;
--source include/percona_query_cache_with_comments_eval.inc
# following two queries related to bug #856404.
# There are different queries, but opt_query_cache_strip_comments thinks that they are equal.
let $query=select ' \' ' from t1;
--source percona_query_cache_with_comments_eval.inc
let $query=select ' \' /* comment inside quotes with internal backslash quote */' from t1;
--source percona_query_cache_with_comments_eval.inc

200
mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments.result

@ -831,7 +831,7 @@ show status like "Qcache_hits";
Variable_name Value
Qcache_hits 50
-----------------------------------------------------
select ' \' ' from t1
select */* a comment \*/from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
@ -842,6 +842,167 @@ Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 50
select */* a comment \*/from t1;
a
1
2
3
select */* a comment \*/from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 52
-----------------------------------------------------
select *# a comment \
from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 52
select *# a comment \
from t1;
a
1
2
3
select *# a comment \
from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 54
-----------------------------------------------------
select *-- a comment \
from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 54
select *-- a comment \
from t1;
a
1
2
3
select *-- a comment \
from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 56
-----------------------------------------------------
select "\\"" /* not a comment */" from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 56
select "\\"" /* not a comment */" from t1;
\" /* not a comment */
\" /* not a comment */
\" /* not a comment */
\" /* not a comment */
select "\\"" /* not a comment */" from t1;
\" /* not a comment */
\" /* not a comment */
\" /* not a comment */
\" /* not a comment */
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 2
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 2
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 57
-----------------------------------------------------
select "\\"" /*! not a comment */" from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 2
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 2
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 57
select "\\"" /*! not a comment */" from t1;
\" /*! not a comment */
\" /*! not a comment */
\" /*! not a comment */
\" /*! not a comment */
select "\\"" /*! not a comment */" from t1;
\" /*! not a comment */
\" /*! not a comment */
\" /*! not a comment */
\" /*! not a comment */
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 58
-----------------------------------------------------
select ' \' ' from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 58
select ' \' ' from t1;
'
'
@ -854,13 +1015,44 @@ select ' \' ' from t1;
'
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 2
Qcache_queries_in_cache 4
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 2
Qcache_inserts 4
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 59
-----------------------------------------------------
select ' \' /* comment inside quotes with internal backslash quote */' from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 4
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 4
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 59
select ' \' /* comment inside quotes with internal backslash quote */' from t1;
' /* comment inside quotes with internal backslash quote */
' /* comment inside quotes with internal backslash quote */
' /* comment inside quotes with internal backslash quote */
' /* comment inside quotes with internal backslash quote */
select ' \' /* comment inside quotes with internal backslash quote */' from t1;
' /* comment inside quotes with internal backslash quote */
' /* comment inside quotes with internal backslash quote */
' /* comment inside quotes with internal backslash quote */
' /* comment inside quotes with internal backslash quote */
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 5
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 5
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 51
Qcache_hits 60
DROP TABLE t1;
SET GLOBAL query_cache_size=default;
set global query_cache_strip_comments=OFF;

200
mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments_disable.result

@ -830,7 +830,7 @@ show status like "Qcache_hits";
Variable_name Value
Qcache_hits 25
-----------------------------------------------------
select ' \' ' from t1
select */* a comment \*/from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
@ -841,6 +841,167 @@ Qcache_inserts 20
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 25
select */* a comment \*/from t1;
a
1
2
3
select */* a comment \*/from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 21
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 21
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 26
-----------------------------------------------------
select *# a comment \
from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 21
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 21
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 26
select *# a comment \
from t1;
a
1
2
3
select *# a comment \
from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 22
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 22
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 27
-----------------------------------------------------
select *-- a comment \
from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 22
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 22
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 27
select *-- a comment \
from t1;
a
1
2
3
select *-- a comment \
from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 23
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 23
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 28
-----------------------------------------------------
select "\\"" /* not a comment */" from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 23
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 23
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 28
select "\\"" /* not a comment */" from t1;
\" /* not a comment */
\" /* not a comment */
\" /* not a comment */
\" /* not a comment */
select "\\"" /* not a comment */" from t1;
\" /* not a comment */
\" /* not a comment */
\" /* not a comment */
\" /* not a comment */
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 24
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 24
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 29
-----------------------------------------------------
select "\\"" /*! not a comment */" from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 24
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 24
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 29
select "\\"" /*! not a comment */" from t1;
\" /*! not a comment */
\" /*! not a comment */
\" /*! not a comment */
\" /*! not a comment */
select "\\"" /*! not a comment */" from t1;
\" /*! not a comment */
\" /*! not a comment */
\" /*! not a comment */
\" /*! not a comment */
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 25
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 25
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 30
-----------------------------------------------------
select ' \' ' from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 25
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 25
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 30
select ' \' ' from t1;
'
'
@ -853,13 +1014,44 @@ select ' \' ' from t1;
'
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 21
Qcache_queries_in_cache 26
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 21
Qcache_inserts 26
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 26
Qcache_hits 31
-----------------------------------------------------
select ' \' /* comment inside quotes with internal backslash quote */' from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 26
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 26
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 31
select ' \' /* comment inside quotes with internal backslash quote */' from t1;
' /* comment inside quotes with internal backslash quote */
' /* comment inside quotes with internal backslash quote */
' /* comment inside quotes with internal backslash quote */
' /* comment inside quotes with internal backslash quote */
select ' \' /* comment inside quotes with internal backslash quote */' from t1;
' /* comment inside quotes with internal backslash quote */
' /* comment inside quotes with internal backslash quote */
' /* comment inside quotes with internal backslash quote */
' /* comment inside quotes with internal backslash quote */
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 27
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 27
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 32
DROP TABLE t1;
SET GLOBAL query_cache_size=default;
set global query_cache_strip_comments=OFF;

31
mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.result

@ -3,21 +3,18 @@ flush query cache;
flush query cache;
reset query cache;
flush status;
DROP TABLE IF EXISTS t;
CREATE TABLE t(id INT, number INT);
INSERT INTO t VALUES (0,1);
INSERT INTO t VALUES (1,2);
INSERT INTO t VALUES (2,3);
SET SESSION debug="+d,status_waiting_on_query_cache_mutex_sleep";
SET DEBUG_SYNC='status_waiting_on_query_cache_mutex SIGNAL thread_ready';
SELECT number from t where id > 0;
SHOW PROCESSLIST;
Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read
### root ### test Query ### NULL SHOW PROCESSLIST ### ### ###
### root ### test Query ### Waiting on query cache mutex SELECT number from t where id > 0 ### ### ###
SELECT id, info, state FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id;
id info state
### SELECT id, info, state FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id executing
### SELECT number from t where id > 0 Waiting on query cache mutex
DROP TABLE t;
SET DEBUG_SYNC='after_query_cache_mutex SIGNAL mutex_locked WAIT_FOR unlock_mutex';
SELECT "mutex_locked_query" as action;
SET DEBUG_SYNC='now WAIT_FOR mutex_locked';
SET DEBUG_SYNC='before_query_cache_mutex SIGNAL try_lock_mutex';
SELECT "try_lock_mutex_query" as action;
SET DEBUG_SYNC='now WAIT_FOR try_lock_mutex';
SELECT SQL_NO_CACHE state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE info='SELECT "try_lock_mutex_query" as action';
state
Waiting on query cache mutex
SET DEBUG_SYNC='now SIGNAL unlock_mutex';
action
mutex_locked_query
action
try_lock_mutex_query
SET GLOBAL query_cache_size=0;

40
mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.test

@ -3,29 +3,33 @@
--source include/have_debug_sync.inc
SET GLOBAL query_cache_size=1355776;
--source include/percona_query_cache_with_comments_clear.inc
--let try_lock_mutex_query=SELECT "try_lock_mutex_query" as action
-- disable_warnings
DROP TABLE IF EXISTS t;
-- enable_warnings
CREATE TABLE t(id INT, number INT);
INSERT INTO t VALUES (0,1);
INSERT INTO t VALUES (1,2);
INSERT INTO t VALUES (2,3);
--connect (mutex_locked_conn, localhost, root,,)
--connect (try_mutex_lock_conn, localhost, root,,)
--connect (conn,localhost,root,,)
--connection mutex_locked_conn
SET DEBUG_SYNC='after_query_cache_mutex SIGNAL mutex_locked WAIT_FOR unlock_mutex';
send SELECT "mutex_locked_query" as action;
--connection conn
SET SESSION debug="+d,status_waiting_on_query_cache_mutex_sleep";
SET DEBUG_SYNC='status_waiting_on_query_cache_mutex SIGNAL thread_ready';
SEND SELECT number from t where id > 0;
--connection default
SET DEBUG_SYNC='now WAIT_FOR mutex_locked';
--connection try_mutex_lock_conn
SET DEBUG_SYNC='before_query_cache_mutex SIGNAL try_lock_mutex';
send_eval $try_lock_mutex_query;
--connection default
--replace_column 1 ### 3 ### 6 ### 9 ### 10 ### 11 ###
SHOW PROCESSLIST;
SET DEBUG_SYNC='now WAIT_FOR try_lock_mutex';
eval SELECT SQL_NO_CACHE state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE info='$try_lock_mutex_query';
SET DEBUG_SYNC='now SIGNAL unlock_mutex';
--replace_column 1 ###
SELECT id, info, state FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id;
--connection mutex_locked_conn
reap;
--connection try_mutex_lock_conn
reap;
--disconnect conn
DROP TABLE t;
--connection default
--disconnect mutex_locked_conn
--disconnect try_mutex_lock_conn
SET GLOBAL query_cache_size=0;

15
mysql-test/suite/sys_vars/r/innodb_flush_checkpoint_debug_basic.result

@ -0,0 +1,15 @@
SELECT @@global.innodb_flush_checkpoint_debug;
@@global.innodb_flush_checkpoint_debug
0
SET @@global.innodb_flush_checkpoint_debug=1;
SELECT @@global.innodb_flush_checkpoint_debug;
@@global.innodb_flush_checkpoint_debug
1
SET @@global.innodb_flush_checkpoint_debug=0;
SELECT @@global.innodb_flush_checkpoint_debug;
@@global.innodb_flush_checkpoint_debug
0
SET @@session.innodb_flush_checkpoint_debug=1;
ERROR HY000: Variable 'innodb_flush_checkpoint_debug' is a GLOBAL variable and should be set with SET GLOBAL
SELECT @@session.innodb_flush_checkpoint_debug;
ERROR HY000: Variable 'innodb_flush_checkpoint_debug' is a GLOBAL variable

12
mysql-test/suite/sys_vars/t/innodb_flush_checkpoint_debug_basic.test

@ -0,0 +1,12 @@
--source include/have_debug.inc
--source include/have_xtradb.inc
SELECT @@global.innodb_flush_checkpoint_debug;
SET @@global.innodb_flush_checkpoint_debug=1;
SELECT @@global.innodb_flush_checkpoint_debug;
SET @@global.innodb_flush_checkpoint_debug=0;
SELECT @@global.innodb_flush_checkpoint_debug;
--error ER_GLOBAL_VARIABLE
SET @@session.innodb_flush_checkpoint_debug=1;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT @@session.innodb_flush_checkpoint_debug;

16
storage/xtradb/btr/btr0btr.c

@ -1523,7 +1523,7 @@ btr_free_root(
}
ut_a(block);
btr_search_drop_page_hash_index(block, NULL);
btr_search_drop_page_hash_index(block);
header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP;
#ifdef UNIV_BTR_DEBUG
@ -1592,7 +1592,7 @@ btr_page_reorganize_low(
#ifndef UNIV_HOTBACKUP
if (UNIV_LIKELY(!recovery)) {
btr_search_drop_page_hash_index(block, index);
btr_search_drop_page_hash_index(block);
}
block->check_index_page_at_flush = TRUE;
@ -1760,7 +1760,7 @@ btr_page_empty(
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
btr_search_drop_page_hash_index(block, index);
btr_search_drop_page_hash_index(block);
btr_blob_dbg_remove(page, index, "btr_page_empty");
/* Recreate the page: note that global data on page (possible
@ -3093,7 +3093,7 @@ btr_lift_page_up(
mem_heap_free(heap);
}
btr_search_drop_page_hash_index(block, index);
btr_search_drop_page_hash_index(block);
/* Make the father empty */
btr_page_empty(father_block, father_page_zip, index, page_level, mtr);
@ -3317,7 +3317,7 @@ err_exit:
goto err_exit;
}
btr_search_drop_page_hash_index(block, index);
btr_search_drop_page_hash_index(block);
/* Remove the page from the level list */
btr_level_list_remove(space, zip_size, page, index, mtr);
@ -3358,7 +3358,7 @@ err_exit:
goto err_exit;
}
btr_search_drop_page_hash_index(block, index);
btr_search_drop_page_hash_index(block);
#ifdef UNIV_BTR_DEBUG
if (UNIV_LIKELY_NULL(merge_page_zip)) {
@ -3473,7 +3473,7 @@ btr_discard_only_page_on_level(
ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
btr_search_drop_page_hash_index(block, index);
btr_search_drop_page_hash_index(block);
btr_page_get_father(index, block, mtr, &cursor);
father = btr_cur_get_block(&cursor);
@ -3578,7 +3578,7 @@ btr_discard_page(
page = buf_block_get_frame(block);
ut_a(page_is_comp(merge_page) == page_is_comp(page));
btr_search_drop_page_hash_index(block, index);
btr_search_drop_page_hash_index(block);
if (left_page_no == FIL_NULL && !page_is_leaf(page)) {

31
storage/xtradb/btr/btr0cur.c

@ -488,8 +488,6 @@ btr_cur_search_to_nth_level(
cursor->flag = BTR_CUR_BINARY;
cursor->index = index;
cursor->ibuf_cnt = ULINT_UNDEFINED;
#ifndef BTR_CUR_ADAPT
guess = NULL;
#else
@ -800,21 +798,8 @@ retry_page_get:
/* We're doing a search on an ibuf tree and we're one
level above the leaf page. */
ulint is_min_rec;
ut_ad(level == 0);
is_min_rec = rec_get_info_bits(node_ptr, 0)
& REC_INFO_MIN_REC_FLAG;
if (!is_min_rec) {
cursor->ibuf_cnt
= ibuf_rec_get_counter(node_ptr);
ut_a(cursor->ibuf_cnt <= 0xFFFF
|| cursor->ibuf_cnt == ULINT_UNDEFINED);
}
buf_mode = BUF_GET;
rw_latch = RW_NO_LATCH;
goto retry_page_get;
@ -2007,7 +1992,7 @@ btr_cur_update_in_place(
was_delete_marked = rec_get_deleted_flag(
rec, page_is_comp(buf_block_get_frame(block)));
is_hashed = block->is_hashed;
is_hashed = (block->index != NULL);
if (is_hashed) {
/* TO DO: Can we skip this if none of the fields
@ -3683,16 +3668,11 @@ btr_record_not_null_field_in_rec(
}
for (i = 0; i < n_unique; i++) {
ulint rec_len;
rec_get_nth_field_offs(offsets, i, &rec_len);
if (rec_len != UNIV_SQL_NULL) {
n_not_null[i]++;
} else {
/* Break if we hit the first NULL value */
if (rec_offs_nth_sql_null(offsets, i)) {
break;
}
n_not_null[i]++;
}
}
@ -3840,8 +3820,7 @@ btr_estimate_number_of_different_key_vals(
if (n_not_null) {
btr_record_not_null_field_in_rec(
n_cols, offsets_next_rec,
n_not_null);
n_cols, offsets_next_rec, n_not_null);
}
total_external_size

2
storage/xtradb/btr/btr0pcur.c

@ -253,6 +253,8 @@ btr_pcur_restore_position_func(
cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr);
cursor->latch_mode = latch_mode;
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
cursor->block_when_stored = btr_pcur_get_block(cursor);
return(FALSE);

304
storage/xtradb/btr/btr0sea.c

@ -44,15 +44,11 @@ Created 2/17/1996 Heikki Tuuri
#include "ha0ha.h"
#include "srv0srv.h"
/** Flag: has the search system been enabled?
Protected by btr_search_latch and btr_search_enabled_mutex. */
Protected by btr_search_latch. */
UNIV_INTERN char btr_search_enabled = TRUE;
UNIV_INTERN ibool btr_search_fully_disabled = FALSE;
UNIV_INTERN ulint btr_search_index_num = 1;
/** Mutex protecting btr_search_enabled */
static mutex_t btr_search_enabled_mutex;
#ifdef UNIV_PFS_MUTEX
/* Key to register btr_search_enabled_mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t btr_search_enabled_mutex_key;
@ -186,8 +182,6 @@ btr_search_sys_create(
//rw_lock_create(btr_search_latch_key, &btr_search_latch,
// SYNC_SEARCH_SYS);
mutex_create(btr_search_enabled_mutex_key,
&btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
@ -238,27 +232,40 @@ void
btr_search_disable(void)
/*====================*/
{
mutex_enter(&btr_search_enabled_mutex);
dict_table_t* table;
ulint i;
mutex_enter(&dict_sys->mutex);
btr_search_x_lock_all();
/* Disable access to hash index, also tell ha_insert_for_fold()
stop adding new nodes to hash index, but still allow updating
existing nodes */
btr_search_enabled = FALSE;
/* Clear all block->is_hashed flags and remove all entries
from btr_search_sys->hash_index. */
buf_pool_drop_hash_index();
/* Clear the index->search_info->ref_count of every index in
the data dictionary cache. */
for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU); table;
table = UT_LIST_GET_NEXT(table_LRU, table)) {
dict_index_t* index;
for (index = dict_table_get_first_index(table); index;
index = dict_table_get_next_index(index)) {
/* hash index has been cleaned up, disallow any operation to
the hash index */
btr_search_fully_disabled = TRUE;
index->search_info->ref_count = 0;
}
}
mutex_exit(&dict_sys->mutex);
/* btr_search_enabled_mutex should guarantee this. */
ut_ad(!btr_search_enabled);
/* Set all block->index = NULL. */
buf_pool_clear_hash_index();
/* Clear the adaptive hash index. */
for (i = 0; i < btr_search_index_num; i++) {
hash_table_clear(btr_search_sys->hash_index[i]);
mem_heap_empty(btr_search_sys->hash_index[i]->heap);
}
btr_search_x_unlock_all();
mutex_exit(&btr_search_enabled_mutex);
}
/********************************************************************//**
@ -268,14 +275,11 @@ void
btr_search_enable(void)
/*====================*/
{
mutex_enter(&btr_search_enabled_mutex);
btr_search_x_lock_all();
btr_search_enabled = TRUE;
btr_search_fully_disabled = FALSE;
btr_search_x_unlock_all();
mutex_exit(&btr_search_enabled_mutex);
}
/*****************************************************************//**
@ -499,7 +503,7 @@ btr_search_update_block_hash_info(
&& (block->n_bytes == info->n_bytes)
&& (block->left_side == info->left_side)) {
if ((block->is_hashed)
if ((block->index)
&& (block->curr_n_fields == info->n_fields)
&& (block->curr_n_bytes == info->n_bytes)
&& (block->curr_left_side == info->left_side)) {
@ -528,7 +532,7 @@ btr_search_update_block_hash_info(
/ BTR_SEARCH_PAGE_BUILD_LIMIT)
&& (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) {
if ((!block->is_hashed)
if ((!block->index)
|| (block->n_hash_helps
> 2 * page_get_n_recs(block->frame))
|| (block->n_fields != block->curr_n_fields)
@ -560,9 +564,9 @@ btr_search_update_hash_ref(
buf_block_t* block, /*!< in: buffer block where cursor positioned */
btr_cur_t* cursor) /*!< in: cursor */
{
dict_index_t* index;
ulint fold;
rec_t* rec;
index_id_t index_id;
const rec_t* rec;
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
#ifdef UNIV_SYNC_DEBUG
@ -573,13 +577,15 @@ btr_search_update_hash_ref(
ut_ad(page_align(btr_cur_get_rec(cursor))
== buf_block_get_frame(block));
if (!block->is_hashed) {
index = block->index;
if (!index) {
return;
}
ut_a(block->index == cursor->index);
ut_a(!dict_index_is_ibuf(cursor->index));
ut_a(index == cursor->index);
ut_a(!dict_index_is_ibuf(index));
if ((info->n_hash_potential > 0)
&& (block->curr_n_fields == info->n_fields)
@ -596,12 +602,11 @@ btr_search_update_hash_ref(
return;
}
index_id = cursor->index->id;
fold = rec_fold(rec,
rec_get_offsets(rec, cursor->index, offsets_,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
block->curr_n_fields,
block->curr_n_bytes, index_id);
block->curr_n_bytes, index->id);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@ -870,7 +875,7 @@ btr_search_guess_on_hash(
{
buf_pool_t* buf_pool;
buf_block_t* block;
rec_t* rec;
const rec_t* rec;
ulint fold;
index_id_t index_id;
#ifdef notdefined
@ -956,7 +961,7 @@ btr_search_guess_on_hash(
ut_ad(page_rec_is_user_rec(rec));
btr_cur_position(index, rec, block, cursor);
btr_cur_position(index, (rec_t*) rec, block, cursor);
/* Check the validity of the guess within the page */
@ -1058,11 +1063,10 @@ UNIV_INTERN
void
btr_search_drop_page_hash_index(
/*============================*/
buf_block_t* block, /*!< in: block containing index page,
buf_block_t* block) /*!< in: block containing index page,
s- or x-latched, or an index page
for which we know that
block->buf_fix_count == 0 */
dict_index_t* index_in)
{
hash_table_t* table;
ulint n_fields;
@ -1080,24 +1084,14 @@ btr_search_drop_page_hash_index(
const dict_index_t* index;
ulint* offsets;
#ifdef UNIV_SYNC_DEBUG
if (index_in) {
ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_SHARED));
ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_EX));
}
#endif /* UNIV_SYNC_DEBUG */
retry:
if (index_in) {
index = index_in;
rw_lock_s_lock(btr_search_get_latch(index->id));
} else if (btr_search_index_num > 1) {
if (btr_search_index_num > 1) {
rw_lock_t* btr_search_latch;
/* FIXME: This may be optimistic implementation still. */
btr_search_latch = (rw_lock_t*)(block->btr_search_latch);
if (UNIV_LIKELY(!btr_search_latch)) {
if (block->is_hashed) {
if (block->index) {
goto retry;
}
return;
@ -1107,7 +1101,7 @@ retry:
rw_lock_s_unlock(btr_search_latch);
goto retry;
}
if (UNIV_LIKELY(!block->is_hashed)) {
if (UNIV_LIKELY(!block->index)) {
rw_lock_s_unlock(btr_search_latch);
goto retry;
}
@ -1116,18 +1110,16 @@ retry:
} else {
/* btr_search_index_num == 1 */
/* btr_search_latch is only one and able to obtain
before evaluating block->is_hashed. */
before evaluating block->index. */
rw_lock_s_lock(btr_search_latch_part[0]);
if (UNIV_LIKELY(!block->is_hashed)) {
if (UNIV_LIKELY(!block->index)) {
rw_lock_s_unlock(btr_search_latch_part[0]);
return;
}
index = block->index;
}
page = block->frame;
if (UNIV_LIKELY(!block->is_hashed)) {
if (UNIV_LIKELY(!index)) {
rw_lock_s_unlock(btr_search_get_latch(index->id));
@ -1155,6 +1147,7 @@ retry:
ut_a(n_fields + n_bytes > 0);
page = block->frame;
n_recs = page_get_n_recs(page);
/* Calculate and cache fold values into an array for fast deletion
@ -1203,7 +1196,7 @@ next_rec:
rw_lock_x_lock(btr_search_get_latch(index->id));
if (UNIV_UNLIKELY(!block->is_hashed)) {
if (UNIV_UNLIKELY(!block->index)) {
/* Someone else has meanwhile dropped the hash index */
goto cleanup;
@ -1231,10 +1224,9 @@ next_rec:
ut_a(index->search_info->ref_count > 0);
index->search_info->ref_count--;
block->is_hashed = FALSE;
block->index = NULL;
block->btr_search_latch = NULL;
cleanup:
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
if (UNIV_UNLIKELY(block->n_pointers)) {
@ -1309,7 +1301,7 @@ retry:
if (buf_block_get_state(block)
!= BUF_BLOCK_FILE_PAGE
|| block->index != index
|| !block->is_hashed) {
|| !block->index) {
continue;
}
@ -1375,7 +1367,7 @@ next_rec:
rw_lock_x_lock(btr_search_get_latch(index->id));
if (UNIV_UNLIKELY(!block->is_hashed)) {
if (UNIV_UNLIKELY(!block->index)) {
goto cleanup;
}
@ -1400,7 +1392,6 @@ next_rec:
ut_a(index->search_info->ref_count > 0);
index->search_info->ref_count--;
block->is_hashed = FALSE;
block->index = NULL;
block->btr_search_latch = NULL;
@ -1434,8 +1425,8 @@ cleanup:
}
/********************************************************************//**
Drops a page hash index when a page is freed from a fseg to the file system.
Drops possible hash index if the page happens to be in the buffer pool. */
Drops a possible page hash index when a page is evicted from the buffer pool
or freed in a file segment. */
UNIV_INTERN
void
btr_search_drop_page_hash_when_freed(
@ -1448,32 +1439,23 @@ btr_search_drop_page_hash_when_freed(
buf_block_t* block;
mtr_t mtr;
if (!buf_page_peek_if_search_hashed(space, page_no)) {
return;
}
mtr_start(&mtr);
/* We assume that if the caller has a latch on the page, then the
caller has already dropped the hash index for the page, and we never
get here. Therefore we can acquire the s-latch to the page without
having to fear a deadlock. */
/* If the caller has a latch on the page, then the caller must
have a x-latch on the page and it must have already dropped
the hash index for the page. Because of the x-latch that we
are possibly holding, we cannot s-latch the page, but must
(recursively) x-latch it, even though we are only reading. */
block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL,
block = buf_page_get_gen(space, zip_size, page_no, RW_X_LATCH, NULL,
BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__,
&mtr);
/* Because the buffer pool mutex was released by
buf_page_peek_if_search_hashed(), it is possible that the
block was removed from the buffer pool by another thread
before buf_page_get_gen() got a chance to acquire the buffer
pool mutex again. Thus, we must check for a NULL return. */
if (UNIV_LIKELY(block != NULL)) {
if (block && block->index) {
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
btr_search_drop_page_hash_index(block, NULL);
btr_search_drop_page_hash_index(block);
}
mtr_commit(&mtr);
@ -1501,7 +1483,6 @@ btr_search_build_page_hash_index(
rec_t* next_rec;
ulint fold;
ulint next_fold;
index_id_t index_id;
ulint n_cached;
ulint n_recs;
ulint* folds;
@ -1526,13 +1507,13 @@ btr_search_build_page_hash_index(
rw_lock_s_lock(btr_search_get_latch(index->id));
if (block->is_hashed && ((block->curr_n_fields != n_fields)
if (block->index && ((block->curr_n_fields != n_fields)
|| (block->curr_n_bytes != n_bytes)
|| (block->curr_left_side != left_side))) {
rw_lock_s_unlock(btr_search_get_latch(index->id));
btr_search_drop_page_hash_index(block, index);
btr_search_drop_page_hash_index(block);
} else {
rw_lock_s_unlock(btr_search_get_latch(index->id));
}
@ -1565,7 +1546,7 @@ btr_search_build_page_hash_index(
n_cached = 0;
index_id = btr_page_get_index_id(page);
ut_a(index->id == btr_page_get_index_id(page));
rec = page_rec_get_next(page_get_infimum_rec(page));
@ -1580,7 +1561,7 @@ btr_search_build_page_hash_index(
}
}
fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
if (left_side) {
@ -1607,7 +1588,7 @@ btr_search_build_page_hash_index(
offsets = rec_get_offsets(next_rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
next_fold = rec_fold(next_rec, offsets, n_fields,
n_bytes, index_id);
n_bytes, index->id);
if (fold != next_fold) {
/* Insert an entry into the hash index */
@ -1632,13 +1613,13 @@ btr_search_build_page_hash_index(
rw_lock_x_lock(btr_search_get_latch(index->id));
if (UNIV_UNLIKELY(btr_search_fully_disabled)) {
if (UNIV_UNLIKELY(!btr_search_enabled)) {
goto exit_func;
}
if (block->is_hashed && ((block->curr_n_fields != n_fields)
|| (block->curr_n_bytes != n_bytes)
|| (block->curr_left_side != left_side))) {
if (block->index && ((block->curr_n_fields != n_fields)
|| (block->curr_n_bytes != n_bytes)
|| (block->curr_left_side != left_side))) {
goto exit_func;
}
@ -1647,11 +1628,10 @@ btr_search_build_page_hash_index(
rebuild hash index for a page that is already hashed, we
have to take care not to increment the counter in that
case. */
if (!block->is_hashed) {
if (!block->index) {
index->search_info->ref_count++;
}
block->is_hashed = TRUE;
block->n_hash_helps = 0;
block->curr_n_fields = n_fields;
@ -1700,23 +1680,24 @@ btr_search_move_or_delete_hash_entries(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
ut_a(!new_block->is_hashed || new_block->index == index);
ut_a(!block->is_hashed || block->index == index);
ut_a(!(new_block->is_hashed || block->is_hashed)
|| !dict_index_is_ibuf(index));
rw_lock_s_lock(btr_search_get_latch(index->id));
if (new_block->is_hashed) {
ut_a(!new_block->index || new_block->index == index);
ut_a(!block->index || block->index == index);
ut_a(!(new_block->index || block->index)
|| !dict_index_is_ibuf(index));
if (new_block->index) {
rw_lock_s_unlock(btr_search_get_latch(index->id));
btr_search_drop_page_hash_index(block, index);
btr_search_drop_page_hash_index(block);
return;
}
if (block->is_hashed) {
if (block->index) {
n_fields = block->curr_n_fields;
n_bytes = block->curr_n_bytes;
@ -1753,42 +1734,48 @@ btr_search_update_hash_on_delete(
{
hash_table_t* table;
buf_block_t* block;
rec_t* rec;
const rec_t* rec;
ulint fold;
index_id_t index_id;
dict_index_t* index;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
mem_heap_t* heap = NULL;
rec_offs_init(offsets_);
rec = btr_cur_get_rec(cursor);
block = btr_cur_get_block(cursor);
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
if (!block->is_hashed) {
index = block->index;
if (!index) {
return;
}
ut_a(block->index == cursor->index);
ut_a(index == cursor->index);
ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
ut_a(!dict_index_is_ibuf(cursor->index));
ut_a(!dict_index_is_ibuf(index));
table = btr_search_get_hash_index(cursor->index->id);
index_id = cursor->index->id;
fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
rec = btr_cur_get_rec(cursor);
fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
block->curr_n_fields, block->curr_n_bytes, index_id);
block->curr_n_fields, block->curr_n_bytes, index->id);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
ha_search_and_delete_if_found(table, fold, rec);
if (block->index) {
ut_a(block->index == index);
ha_search_and_delete_if_found(table, fold, rec);
}
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
}
@ -1806,6 +1793,7 @@ btr_search_update_hash_node_on_insert(
{
hash_table_t* table;
buf_block_t* block;
dict_index_t* index;
rec_t* rec;
rec = btr_cur_get_rec(cursor);
@ -1816,16 +1804,25 @@ btr_search_update_hash_node_on_insert(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
if (!block->is_hashed) {
index = block->index;
if (!index) {
return;
}
ut_a(block->index == cursor->index);
ut_a(!dict_index_is_ibuf(cursor->index));
ut_a(cursor->index == index);
ut_a(!dict_index_is_ibuf(index));
rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
if (!block->index) {
goto func_exit;
}
ut_a(block->index == index);
if ((cursor->flag == BTR_CUR_HASH)
&& (cursor->n_fields == block->curr_n_fields)
&& (cursor->n_bytes == block->curr_n_bytes)
@ -1836,6 +1833,7 @@ btr_search_update_hash_node_on_insert(
ha_search_and_update_if_found(table, cursor->fold, rec,
block, page_rec_get_next(rec));
func_exit:
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
} else {
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
@ -1857,10 +1855,10 @@ btr_search_update_hash_on_insert(
{
hash_table_t* table;
buf_block_t* block;
dict_index_t* index;
rec_t* rec;
rec_t* ins_rec;
rec_t* next_rec;
index_id_t index_id;
ulint fold;
ulint ins_fold;
ulint next_fold = 0; /* remove warning (??? bug ???) */
@ -1885,15 +1883,15 @@ btr_search_update_hash_on_insert(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
if (!block->is_hashed) {
index = block->index;
if (!index) {
return;
}
ut_a(block->index == cursor->index);
ut_a(!dict_index_is_ibuf(cursor->index));
index_id = cursor->index->id;
ut_a(index == cursor->index);
ut_a(!dict_index_is_ibuf(index));
n_fields = block->curr_n_fields;
n_bytes = block->curr_n_bytes;
@ -1902,28 +1900,32 @@ btr_search_update_hash_on_insert(
ins_rec = page_rec_get_next(rec);
next_rec = page_rec_get_next(ins_rec);
offsets = rec_get_offsets(ins_rec, cursor->index, offsets,
offsets = rec_get_offsets(ins_rec, index, offsets,
ULINT_UNDEFINED, &heap);
ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index_id);
ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index->id);
if (!page_rec_is_supremum(next_rec)) {
offsets = rec_get_offsets(next_rec, cursor->index, offsets,
offsets = rec_get_offsets(next_rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
next_fold = rec_fold(next_rec, offsets, n_fields,
n_bytes, index_id);
n_bytes, index->id);
}
if (!page_rec_is_infimum(rec)) {
offsets = rec_get_offsets(rec, cursor->index, offsets,
offsets = rec_get_offsets(rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
} else {
if (left_side) {
rw_lock_x_lock(btr_search_get_latch(index_id));
rw_lock_x_lock(btr_search_get_latch(index->id));
locked = TRUE;
if (!btr_search_enabled) {
goto function_exit;
}
ha_insert_for_fold(table, ins_fold, block, ins_rec);
}
@ -1934,9 +1936,13 @@ btr_search_update_hash_on_insert(
if (!locked) {
rw_lock_x_lock(btr_search_get_latch(index_id));
rw_lock_x_lock(btr_search_get_latch(index->id));
locked = TRUE;
if (!btr_search_enabled) {
goto function_exit;
}
}
if (!left_side) {
@ -1952,9 +1958,13 @@ check_next_rec:
if (!left_side) {
if (!locked) {
rw_lock_x_lock(btr_search_get_latch(index_id));
rw_lock_x_lock(btr_search_get_latch(index->id));
locked = TRUE;
if (!btr_search_enabled) {
goto function_exit;
}
}
ha_insert_for_fold(table, ins_fold, block, ins_rec);
@ -1967,9 +1977,13 @@ check_next_rec:
if (!locked) {
rw_lock_x_lock(btr_search_get_latch(index_id));
rw_lock_x_lock(btr_search_get_latch(index->id));
locked = TRUE;
if (!btr_search_enabled) {
goto function_exit;
}
}
if (!left_side) {
@ -1977,7 +1991,7 @@ check_next_rec:
ha_insert_for_fold(table, ins_fold, block, ins_rec);
/*
fputs("Hash insert for ", stderr);
dict_index_name_print(stderr, cursor->index);
dict_index_name_print(stderr, index);
fprintf(stderr, " fold %lu\n", ins_fold);
*/
} else {
@ -1990,7 +2004,7 @@ function_exit:
mem_heap_free(heap);
}
if (locked) {
rw_lock_x_unlock(btr_search_get_latch(index_id));
rw_lock_x_unlock(btr_search_get_latch(index->id));
}
}
@ -2082,21 +2096,20 @@ btr_search_validate(void)
ut_a(!dict_index_is_ibuf(block->index));
offsets = rec_get_offsets((const rec_t*) node->data,
page_index_id = btr_page_get_index_id(block->frame);
offsets = rec_get_offsets(node->data,
block->index, offsets,
block->curr_n_fields
+ (block->curr_n_bytes > 0),
&heap);
page_index_id = btr_page_get_index_id(block->frame);
if (UNIV_UNLIKELY
(!block->is_hashed || node->fold
!= rec_fold((rec_t*)(node->data),
offsets,
block->curr_n_fields,
block->curr_n_bytes,
page_index_id))) {
if (!block->index || node->fold
!= rec_fold(node->data,
offsets,
block->curr_n_fields,
block->curr_n_bytes,
page_index_id)) {
const page_t* page = block->frame;
ok = FALSE;
@ -2112,20 +2125,19 @@ btr_search_validate(void)
node->data,
(ullint) page_index_id,
(ulong) node->fold,
(ulong) rec_fold((rec_t*)(node->data),
(ulong) rec_fold(node->data,
offsets,
block->curr_n_fields,
block->curr_n_bytes,
page_index_id));
fputs("InnoDB: Record ", stderr);
rec_print_new(stderr, (rec_t*)node->data,
offsets);
rec_print_new(stderr, node->data, offsets);
fprintf(stderr, "\nInnoDB: on that page."
" Page mem address %p, is hashed %lu,"
" Page mem address %p, is hashed %p,"
" n fields %lu, n bytes %lu\n"
"InnoDB: side %lu\n",
(void*) page, (ulong) block->is_hashed,
(void*) page, (void*) block->index,
(ulong) block->curr_n_fields,
(ulong) block->curr_n_bytes,
(ulong) block->curr_left_side);

208
storage/xtradb/buf/buf0buf.c

@ -917,6 +917,16 @@ pfs_register_buffer_block(
rwlock->pfs_psi = (PSI_server)
? PSI_server->init_rwlock(buf_block_lock_key, rwlock)
: NULL;
# ifdef UNIV_SYNC_DEBUG
rwlock = &block->debug_latch;
ut_a(!rwlock->pfs_psi);
rwlock->pfs_psi = (PSI_server)
? PSI_server->init_rwlock(buf_block_debug_latch_key,
rwlock)
: NULL;
# endif /* UNIV_SYNC_DEBUG */
# endif /* UNIV_PFS_RWLOCK */
block++;
}
@ -952,8 +962,6 @@ buf_block_init(
block->index = NULL;
block->btr_search_latch = NULL;
block->is_hashed = FALSE;
#ifdef UNIV_DEBUG
block->page.in_page_hash = FALSE;
block->page.in_zip_hash = FALSE;
@ -980,17 +988,24 @@ buf_block_init(
mutex_create(PFS_NOT_INSTRUMENTED, &block->mutex, SYNC_BUF_BLOCK);
rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING);
# ifdef UNIV_SYNC_DEBUG
rw_lock_create(PFS_NOT_INSTRUMENTED,
&block->debug_latch, SYNC_NO_ORDER_CHECK);
# endif /* UNIV_SYNC_DEBUG */
#else /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
mutex_create(buffer_block_mutex_key, &block->mutex, SYNC_BUF_BLOCK);
rw_lock_create(buf_block_lock_key, &block->lock, SYNC_LEVEL_VARYING);
# ifdef UNIV_SYNC_DEBUG
rw_lock_create(buf_block_debug_latch_key,
&block->debug_latch, SYNC_NO_ORDER_CHECK);
# endif /* UNIV_SYNC_DEBUG */
#endif /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
ut_ad(rw_lock_validate(&(block->lock)));
#ifdef UNIV_SYNC_DEBUG
rw_lock_create(buf_block_debug_latch_key,
&block->debug_latch, SYNC_NO_ORDER_CHECK);
#endif /* UNIV_SYNC_DEBUG */
}
/********************************************************************//**
@ -1317,6 +1332,26 @@ buf_pool_free_instance(
{
buf_chunk_t* chunk;
buf_chunk_t* chunks;
buf_page_t* bpage;
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
while (bpage != NULL) {
buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
enum buf_page_state state = buf_page_get_state(bpage);
ut_ad(buf_page_in_file(bpage));
ut_ad(bpage->in_LRU_list);
if (state != BUF_BLOCK_FILE_PAGE) {
/* We must not have any dirty block except
when doing a fast shutdown. */
ut_ad(state == BUF_BLOCK_ZIP_PAGE
|| srv_fast_shutdown == 2);
buf_page_free_descriptor(bpage);
}
bpage = prev_bpage;
}
chunks = buf_pool->chunks;
chunk = chunks + buf_pool->n_chunks;
@ -1392,87 +1427,13 @@ buf_pool_free(
}
/********************************************************************//**
Drops adaptive hash index for a buffer pool instance. */
static
void
buf_pool_drop_hash_index_instance(
/*==============================*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ibool* released_search_latch) /*!< out: flag for signalling
whether the search latch was
released */
{
buf_chunk_t* chunks = buf_pool->chunks;
buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
while (--chunk >= chunks) {
ulint i;
buf_block_t* block = chunk->blocks;
for (i = chunk->size; i--; block++) {
/* block->is_hashed cannot be modified
when we have an x-latch on btr_search_latch;
see the comment in buf0buf.h */
if (!block->is_hashed) {
continue;
}
/* To follow the latching order, we
have to release btr_search_latch
before acquiring block->latch. */
btr_search_x_unlock_all();
/* When we release the search latch,
we must rescan all blocks, because
some may become hashed again. */
*released_search_latch = TRUE;
rw_lock_x_lock(&block->lock);
/* This should be guaranteed by the
callers, which will be holding
btr_search_enabled_mutex. */
ut_ad(!btr_search_enabled);
/* Because we did not buffer-fix the
block by calling buf_block_get_gen(),
it is possible that the block has been
allocated for some other use after
btr_search_latch was released above.
We do not care which file page the
block is mapped to. All we want to do
is to drop any hash entries referring
to the page. */
/* It is possible that
block->page.state != BUF_FILE_PAGE.
Even that does not matter, because
btr_search_drop_page_hash_index() will
check block->is_hashed before doing
anything. block->is_hashed can only
be set on uncompressed file pages. */
btr_search_drop_page_hash_index(block, NULL);
rw_lock_x_unlock(&block->lock);
btr_search_x_lock_all();
ut_ad(!btr_search_enabled);
}
}
}
/********************************************************************//**
Drops the adaptive hash index. To prevent a livelock, this function
is only to be called while holding btr_search_latch and while
btr_search_enabled == FALSE. */
Clears the adaptive hash index on all pages in the buffer pool. */
UNIV_INTERN
void
buf_pool_drop_hash_index(void)
/*==========================*/
buf_pool_clear_hash_index(void)
/*===========================*/
{
ibool released_search_latch;
ulint p;
#ifdef UNIV_SYNC_DEBUG
ulint j;
@ -1483,21 +1444,34 @@ buf_pool_drop_hash_index(void)
#endif /* UNIV_SYNC_DEBUG */
ut_ad(!btr_search_enabled);
do {
ulint i;
for (p = 0; p < srv_buf_pool_instances; p++) {
buf_pool_t* buf_pool = buf_pool_from_array(p);
buf_chunk_t* chunks = buf_pool->chunks;
buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
released_search_latch = FALSE;
while (--chunk >= chunks) {
buf_block_t* block = chunk->blocks;
ulint i = chunk->size;
for (i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
for (; i--; block++) {
dict_index_t* index = block->index;
buf_pool = buf_pool_from_array(i);
/* We can set block->index = NULL
when we have an x-latch on btr_search_latch;
see the comment in buf0buf.h */
buf_pool_drop_hash_index_instance(
buf_pool, &released_search_latch);
}
if (!index) {
/* Not hashed */
continue;
}
} while (released_search_latch);
block->index = NULL;
# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
block->n_pointers = 0;
# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
}
}
}
}
/********************************************************************//**
@ -1638,12 +1612,12 @@ buf_pool_watch_set(
rw_lock_x_lock(&buf_pool->page_hash_latch);
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
if (bpage) {
if (UNIV_LIKELY_NULL(bpage)) {
block_mutex = buf_page_get_mutex_enter(bpage);
ut_a(block_mutex);
}
if (UNIV_LIKELY_NULL(bpage)) {
if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) {
/* The page was loaded meanwhile. */
rw_lock_x_unlock(&buf_pool->page_hash_latch);
@ -1895,40 +1869,6 @@ buf_reset_check_index_page_at_flush(
rw_lock_s_unlock(&buf_pool->page_hash_latch);
}
/********************************************************************//**
Returns the current state of is_hashed of a page. FALSE if the page is
not in the pool. NOTE that this operation does not fix the page in the
pool if it is found there.
@return TRUE if page hash index is built in search system */
UNIV_INTERN
ibool
buf_page_peek_if_search_hashed(
/*===========================*/
ulint space, /*!< in: space id */
ulint offset) /*!< in: page number */
{
buf_block_t* block;
ibool is_hashed;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
//buf_pool_mutex_enter(buf_pool);
rw_lock_s_lock(&buf_pool->page_hash_latch);
block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
is_hashed = FALSE;
} else {
ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
is_hashed = block->is_hashed;
}
//buf_pool_mutex_exit(buf_pool);
rw_lock_s_unlock(&buf_pool->page_hash_latch);
return(is_hashed);
}
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//**
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
@ -2218,7 +2158,6 @@ buf_block_init_low(
block->btr_search_latch = NULL;
block->n_hash_helps = 0;
block->is_hashed = FALSE;
block->n_fields = 1;
block->n_bytes = 0;
block->left_side = TRUE;
@ -4473,6 +4412,9 @@ buf_pool_validate_instance(
ut_a(rw_lock_is_locked(&block->lock,
RW_LOCK_EX));
break;
case BUF_IO_PIN:
break;
}
n_lru++;
@ -4502,6 +4444,7 @@ buf_pool_validate_instance(
ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
switch (buf_page_get_io_fix(b)) {
case BUF_IO_NONE:
case BUF_IO_PIN:
/* All clean blocks should be I/O-unfixed. */
break;
case BUF_IO_READ:
@ -4541,6 +4484,7 @@ buf_pool_validate_instance(
switch (buf_page_get_io_fix(b)) {
case BUF_IO_NONE:
case BUF_IO_READ:
case BUF_IO_PIN:
break;
case BUF_IO_WRITE:
switch (buf_page_get_flush_type(b)) {

66
storage/xtradb/buf/buf0flu.c

@ -1399,6 +1399,7 @@ buf_flush_try_neighbors(
ulint high;
ulint count = 0;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
ibool is_forward_scan;
ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST);
@ -1429,7 +1430,32 @@ buf_flush_try_neighbors(
high = fil_space_get_size(space);
}
for (i = low; i < high; i++) {
if (srv_flush_neighbor_pages == 2) {
/* In the case of contiguous flush where the requested page
does not fall at the start of flush area, first scan backward
from the page and later forward from it. */
is_forward_scan = (offset == low);
}
else {
is_forward_scan = TRUE;
}
scan:
if (srv_flush_neighbor_pages == 2) {
if (is_forward_scan) {
i = offset;
}
else {
i = offset - 1;
}
}
else {
i = low;
}
for (; is_forward_scan ? (i < high) : (i >= low);
is_forward_scan ? i++ : i--) {
buf_page_t* bpage;
@ -1460,6 +1486,12 @@ buf_flush_try_neighbors(
//buf_pool_mutex_exit(buf_pool);
rw_lock_s_unlock(&buf_pool->page_hash_latch);
if (srv_flush_neighbor_pages == 2) {
/* This is contiguous neighbor page flush and
the pages here are not contiguous. */
break;
}
continue;
}
@ -1495,6 +1527,22 @@ buf_flush_try_neighbors(
}
//buf_pool_mutex_exit(buf_pool);
rw_lock_s_unlock(&buf_pool->page_hash_latch);
if (srv_flush_neighbor_pages == 2) {
/* We are trying to do the contiguous neighbor page
flush, but the last page we checked was unflushable,
making a "hole" in the flush, so stop this attempt. */
break;
}
}
if (!is_forward_scan) {
/* Backward scan done, now do the forward scan */
ut_a (srv_flush_neighbor_pages == 2);
is_forward_scan = TRUE;
goto scan;
}
return(count);
@ -1988,6 +2036,22 @@ buf_flush_list(
buf_pool = buf_pool_from_array(i);
if (lsn_limit != IB_ULONGLONG_MAX) {
buf_page_t* bpage;
buf_flush_list_mutex_enter(buf_pool);
bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
if (!bpage
|| bpage->oldest_modification >= lsn_limit) {
buf_flush_list_mutex_exit(buf_pool);
continue;
} else {
buf_flush_list_mutex_exit(buf_pool);
}
}
if (!buf_flush_start(buf_pool, BUF_FLUSH_LIST)) {
/* We have two choices here. If lsn_limit was
specified then skipping an instance of buffer

186
storage/xtradb/buf/buf0lru.c

@ -68,8 +68,12 @@ allowed to point to either end of the LRU list. */
/** When dropping the search hash index entries before deleting an ibd
file, we build a local array of pages belonging to that tablespace
in the buffer pool. Following is the size of that array. */
#define BUF_LRU_DROP_SEARCH_HASH_SIZE 1024
in the buffer pool. Following is the size of that array.
We also release buf_pool->mutex after scanning this many pages of the
flush_list when dropping a table. This is to ensure that other threads
are not blocked for extended period of time when using very large
buffer pools. */
#define BUF_LRU_DROP_SEARCH_SIZE 1024
/** If we switch on the InnoDB monitor because there are too few available
frames in the buffer pool, we set this to TRUE */
@ -222,7 +226,7 @@ buf_LRU_drop_page_hash_batch(
ulint i;
ut_ad(arr != NULL);
ut_ad(count <= BUF_LRU_DROP_SEARCH_HASH_SIZE);
ut_ad(count <= BUF_LRU_DROP_SEARCH_SIZE);
for (i = 0; i < count; ++i) {
btr_search_drop_page_hash_when_freed(space_id, zip_size,
@ -256,7 +260,7 @@ buf_LRU_drop_page_hash_for_tablespace(
}
page_arr = ut_malloc(
sizeof(ulint) * BUF_LRU_DROP_SEARCH_HASH_SIZE);
sizeof(ulint) * BUF_LRU_DROP_SEARCH_SIZE);
//buf_pool_mutex_enter(buf_pool);
mutex_enter(&buf_pool->LRU_list_mutex);
@ -293,7 +297,7 @@ next_page:
//mutex_enter(&((buf_block_t*) bpage)->mutex);
is_fixed = bpage->buf_fix_count > 0
|| !((buf_block_t*) bpage)->is_hashed;
|| !((buf_block_t*) bpage)->index;
//mutex_exit(&((buf_block_t*) bpage)->mutex);
if (is_fixed) {
@ -304,12 +308,14 @@ next_page:
/* Store the page number so that we can drop the hash
index in a batch later. */
page_arr[num_entries] = bpage->offset;
mutex_exit(block_mutex);
ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
ut_a(num_entries < BUF_LRU_DROP_SEARCH_SIZE);
++num_entries;
if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
if (num_entries < BUF_LRU_DROP_SEARCH_SIZE) {
goto next_page;
}
@ -366,39 +372,42 @@ next_page:
}
/******************************************************************//**
Invalidates all pages belonging to a given tablespace inside a specific
Remove all dirty pages belonging to a given tablespace inside a specific
buffer pool instance when we are deleting the data file(s) of that
tablespace. */
tablespace. The pages still remain a part of LRU and are evicted from
the list as they age towards the tail of the LRU. */
static
void
buf_LRU_invalidate_tablespace_buf_pool_instance(
/*============================================*/
buf_LRU_remove_dirty_pages_for_tablespace(
/*======================================*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint id) /*!< in: space id */
{
buf_page_t* bpage;
ibool all_freed;
ulint i;
scan_again:
//buf_pool_mutex_enter(buf_pool);
mutex_enter(&buf_pool->LRU_list_mutex);
rw_lock_x_lock(&buf_pool->page_hash_latch);
buf_flush_list_mutex_enter(buf_pool);
all_freed = TRUE;
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list), i = 0;
bpage != NULL; ++i) {
while (bpage != NULL) {
buf_page_t* prev_bpage;
mutex_t* block_mutex = NULL;
ut_a(buf_page_in_file(bpage));
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
prev_bpage = UT_LIST_GET_PREV(flush_list, bpage);
/* bpage->space and bpage->io_fix are protected by
buf_pool_mutex and block_mutex. It is safe to check
them while holding buf_pool_mutex only. */
buf_pool->mutex and block_mutex. It is safe to check
them while holding buf_pool->mutex only. */
if (buf_page_get_space(bpage) != id) {
/* Skip this block, as it does not belong to
@ -411,90 +420,97 @@ scan_again:
all_freed = FALSE;
goto next_page;
} else {
block_mutex = buf_page_get_mutex_enter(bpage);
if (!block_mutex) {
/* It may be impossible case...
Something wrong, so will be scan_again */
}
all_freed = FALSE;
goto next_page;
}
/* We have to release the flush_list_mutex to obey the
latching order. We are however guaranteed that the page
will stay in the flush_list because buf_flush_remove()
needs buf_pool->mutex as well. */
buf_flush_list_mutex_exit(buf_pool);
block_mutex = buf_page_get_mutex_enter(bpage);
if (bpage->buf_fix_count > 0) {
if (!block_mutex) {
/* It may be impossible case...
Something wrong, so will be scan_again */
all_freed = FALSE;
goto next_page;
}
mutex_exit(block_mutex);
/* We cannot remove this page during
this scan yet; maybe the system is
currently reading it in, or flushing
the modifications to the file */
if (bpage->buf_fix_count > 0) {
mutex_exit(block_mutex);
buf_flush_list_mutex_enter(buf_pool);
all_freed = FALSE;
/* We cannot remove this page during
this scan yet; maybe the system is
currently reading it in, or flushing
the modifications to the file */
goto next_page;
}
all_freed = FALSE;
goto next_page;
}
ut_ad(mutex_own(block_mutex));
ut_ad(bpage->oldest_modification != 0);
#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
"Dropping space %lu page %lu\n",
(ulong) buf_page_get_space(bpage),
(ulong) buf_page_get_page_no(bpage));
buf_flush_remove(bpage);
mutex_exit(block_mutex);
buf_flush_list_mutex_enter(buf_pool);
next_page:
bpage = prev_bpage;
if (!bpage) {
break;
}
#endif
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
/* This is a compressed-only block
descriptor. Do nothing. */
} else if (((buf_block_t*) bpage)->is_hashed) {
ulint page_no;
ulint zip_size;
//buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->LRU_list_mutex);
rw_lock_x_unlock(&buf_pool->page_hash_latch);
/* Every BUF_LRU_DROP_SEARCH_SIZE iterations in the
loop we release buf_pool->mutex to let other threads
do their job. */
if (i < BUF_LRU_DROP_SEARCH_SIZE) {
continue;
}
zip_size = buf_page_get_zip_size(bpage);
page_no = buf_page_get_page_no(bpage);
/* We IO-fix the block to make sure that the block
stays in its position in the flush_list. */
if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
/* Block is already IO-fixed. We don't
want to change the value. Lets leave
this block alone. */
continue;
}
mutex_exit(block_mutex);
buf_flush_list_mutex_exit(buf_pool);
block_mutex = buf_page_get_mutex(bpage);
mutex_enter(block_mutex);
buf_page_set_sticky(bpage);
mutex_exit(block_mutex);
/* Note that the following call will acquire
an S-latch on the page */
/* Now it is safe to release the buf_pool->mutex. */
//buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->LRU_list_mutex);
rw_lock_x_unlock(&buf_pool->page_hash_latch);
btr_search_drop_page_hash_when_freed(
id, zip_size, page_no);
goto scan_again;
}
os_thread_yield();
//buf_pool_mutex_enter(buf_pool);
mutex_enter(&buf_pool->LRU_list_mutex);
rw_lock_x_lock(&buf_pool->page_hash_latch);
if (bpage->oldest_modification != 0) {
buf_flush_remove(bpage);
}
mutex_enter(block_mutex);
buf_page_unset_sticky(bpage);
mutex_exit(block_mutex);
/* Remove from the LRU list. */
buf_flush_list_mutex_enter(buf_pool);
ut_ad(bpage->in_flush_list);
if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
!= BUF_BLOCK_ZIP_FREE) {
buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE);
mutex_exit(block_mutex);
} else {
/* The block_mutex should have been released
by buf_LRU_block_remove_hashed_page() when it
returns BUF_BLOCK_ZIP_FREE. */
ut_ad(block_mutex == &buf_pool->zip_mutex);
ut_ad(!mutex_own(block_mutex));
}
next_page:
bpage = prev_bpage;
i = 0;
}
//buf_pool_mutex_exit(buf_pool);
// buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->LRU_list_mutex);
rw_lock_x_unlock(&buf_pool->page_hash_latch);
buf_flush_list_mutex_exit(buf_pool);
ut_ad(buf_flush_validate(buf_pool));
if (!all_freed) {
os_thread_sleep(20000);
@ -525,7 +541,7 @@ buf_LRU_invalidate_tablespace(
buf_pool = buf_pool_from_array(i);
buf_LRU_drop_page_hash_for_tablespace(buf_pool, id);
buf_LRU_invalidate_tablespace_buf_pool_instance(buf_pool, id);
buf_LRU_remove_dirty_pages_for_tablespace(buf_pool, id);
}
}
@ -567,7 +583,7 @@ buf_LRU_mark_space_was_deleted(
for (k = chunk->size; k--; block++) {
if (buf_block_get_state(block)
!= BUF_BLOCK_FILE_PAGE
|| !block->is_hashed
|| !block->index
|| buf_page_get_space(&block->page) != id) {
continue;
}
@ -575,7 +591,7 @@ buf_LRU_mark_space_was_deleted(
btr_search_s_unlock_all();
rw_lock_x_lock(&block->lock);
btr_search_drop_page_hash_index(block, NULL);
btr_search_drop_page_hash_index(block);
rw_lock_x_unlock(&block->lock);
btr_search_s_lock_all();
@ -1726,8 +1742,7 @@ not_freed:
/* Prevent buf_page_get_gen() from
decompressing the block while we release
buf_pool->mutex and block_mutex. */
b->buf_fix_count++;
b->io_fix = BUF_IO_READ;
buf_page_set_sticky(b);
mutex_exit(&buf_pool->zip_mutex);
}
@ -1744,7 +1759,7 @@ not_freed:
UNIV_MEM_VALID(((buf_block_t*) bpage)->frame,
UNIV_PAGE_SIZE);
btr_search_drop_page_hash_index((buf_block_t*) bpage, NULL);
btr_search_drop_page_hash_index((buf_block_t*) bpage);
UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
UNIV_PAGE_SIZE);
@ -1772,8 +1787,7 @@ not_freed:
if (b) {
mutex_enter(&buf_pool->zip_mutex);
b->buf_fix_count--;
buf_page_set_io_fix(b, BUF_IO_NONE);
buf_page_unset_sticky(b);
mutex_exit(&buf_pool->zip_mutex);
}

5
storage/xtradb/dict/dict0dict.c

@ -919,6 +919,11 @@ dict_index_find_on_id_low(
dict_table_t* table;
dict_index_t* index;
/* This can happen if the system tablespace is the wrong page size */
if (dict_sys == NULL) {
return(NULL);
}
table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
while (table) {

4
storage/xtradb/dict/dict0load.c

@ -849,7 +849,7 @@ loop:
object and check that the .ibd file exists. */
fil_open_single_table_tablespace(FALSE, space_id,
flags, name);
flags, name, NULL);
}
mem_free(name);
@ -1904,7 +1904,7 @@ err_exit:
if (!fil_open_single_table_tablespace(
TRUE, table->space,
table->flags == DICT_TF_COMPACT ? 0 :
table->flags & ~(~0 << DICT_TF_BITS), name)) {
table->flags & ~(~0 << DICT_TF_BITS), name, NULL)) {
/* We failed to find a sensible
tablespace file */

49
storage/xtradb/fil/fil0fil.c

@ -1827,36 +1827,44 @@ fil_write_flushed_lsn_to_data_files(
}
/*******************************************************************//**
Reads the flushed lsn and arch no fields from a data file at database
startup. */
Reads the flushed lsn, arch no, and tablespace flag fields from a data
file at database startup. */
UNIV_INTERN
void
fil_read_flushed_lsn_and_arch_log_no(
/*=================================*/
fil_read_first_page(
/*================*/
os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
ulint* flags, /*!< out: tablespace flags */
#ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no, /*!< in/out: */
ulint* max_arch_log_no, /*!< in/out: */
ulint* min_arch_log_no, /*!< out: min of archived
log numbers in data files */
ulint* max_arch_log_no, /*!< out: max of archived
log numbers in data files */
#endif /* UNIV_LOG_ARCHIVE */
ib_uint64_t* min_flushed_lsn, /*!< in/out: */
ib_uint64_t* max_flushed_lsn) /*!< in/out: */
ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed
lsn values in data files */
ib_uint64_t* max_flushed_lsn) /*!< out: max of flushed
lsn values in data files */
{
byte* buf;
byte* buf2;
page_t* page;
ib_uint64_t flushed_lsn;
buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
buf = ut_malloc(2 * UNIV_PAGE_SIZE);
/* Align the memory for a possible read from a raw device */
buf = ut_align(buf2, UNIV_PAGE_SIZE);
page = ut_align(buf, UNIV_PAGE_SIZE);
os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE);
os_file_read(data_file, page, 0, 0, UNIV_PAGE_SIZE);
flushed_lsn = mach_read_from_8(buf + FIL_PAGE_FILE_FLUSH_LSN);
*flags = mach_read_from_4(page +
FSP_HEADER_OFFSET + FSP_SPACE_FLAGS);
ut_free(buf2);
flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
ut_free(buf);
if (!one_read_already) {
*min_flushed_lsn = flushed_lsn;
@ -3174,8 +3182,11 @@ fil_open_single_table_tablespace(
accessing the first page of the file */
ulint id, /*!< in: space id */
ulint flags, /*!< in: tablespace flags */
const char* name) /*!< in: table name in the
const char* name, /*!< in: table name in the
databasename/tablename format */
trx_t* trx) /*!< in: transaction. This is only used
for IMPORT TABLESPACE, must be NULL
otherwise */
{
os_file_t file;
char* filepath;
@ -3393,6 +3404,11 @@ skip_info:
/* over write space id of all pages */
rec_offs_init(offsets_);
/* Unlock the data dictionary to not block queries
accessing other tables */
ut_a(trx);
row_mysql_unlock_data_dictionary(trx);
fprintf(stderr, "InnoDB: Progress in %%:");
for (offset = 0; offset < free_limit_bytes;
@ -3594,6 +3610,9 @@ skip_write:
fprintf(stderr, " done.\n");
/* Reacquire the data dictionary lock */
row_mysql_lock_data_dictionary(trx);
/* update SYS_INDEXES set root page */
index = dict_table_get_first_index(table);
while (index) {

67
storage/xtradb/fsp/fsp0fsp.c

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@ -50,67 +50,6 @@ Created 11/29/1995 Heikki Tuuri
#include "dict0mem.h"
#include "trx0sys.h"
#define FSP_HEADER_OFFSET FIL_PAGE_DATA /* Offset of the space header
within a file page */
/* The data structures in files are defined just as byte strings in C */
typedef byte fsp_header_t;
typedef byte xdes_t;
/* SPACE HEADER
============
File space header data structure: this data structure is contained in the
first page of a space. The space for this header is reserved in every extent
descriptor page, but used only in the first. */
/*-------------------------------------*/
#define FSP_SPACE_ID 0 /* space id */
#define FSP_NOT_USED 4 /* this field contained a value up to
which we know that the modifications
in the database have been flushed to
the file space; not used now */
#define FSP_SIZE 8 /* Current size of the space in
pages */
#define FSP_FREE_LIMIT 12 /* Minimum page number for which the
free list has not been initialized:
the pages >= this limit are, by
definition, free; note that in a
single-table tablespace where size
< 64 pages, this number is 64, i.e.,
we have initialized the space
about the first extent, but have not
physically allocted those pages to the
file */
#define FSP_SPACE_FLAGS 16 /* table->flags & ~DICT_TF_COMPACT */
#define FSP_FRAG_N_USED 20 /* number of used pages in the
FSP_FREE_FRAG list */
#define FSP_FREE 24 /* list of free extents */
#define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE)
/* list of partially free extents not
belonging to any segment */
#define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE)
/* list of full extents not belonging
to any segment */
#define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE)
/* 8 bytes which give the first unused
segment id */
#define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE)
/* list of pages containing segment
headers, where all the segment inode
slots are reserved */
#define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE)
/* list of pages containing segment
headers, where not all the segment
header slots are reserved */
/*-------------------------------------*/
/* File space header size */
#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
#define FSP_FREE_ADD 4 /* this many free extents are added
to the free list from above
FSP_FREE_LIMIT at a time */
/* FILE SEGMENT INODE
==================

70
storage/xtradb/ha/ha0ha.c

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -88,41 +88,6 @@ ha_create_func(
return(table);
}
/*************************************************************//**
Empties a hash table and frees the memory heaps. */
UNIV_INTERN
void
ha_clear(
/*=====*/
hash_table_t* table) /*!< in, own: hash table */
{
ulint i;
ulint n;
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
#ifdef UNIV_SYNC_DEBUG
/* cannot identificate which btr_search_latch[i] for now */
//ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
#endif /* UNIV_SYNC_DEBUG */
#ifndef UNIV_HOTBACKUP
/* Free the memory heaps. */
n = table->n_mutexes;
for (i = 0; i < n; i++) {
mem_heap_free(table->heaps[i]);
}
#endif /* !UNIV_HOTBACKUP */
/* Clear the hash table. */
n = hash_get_n_cells(table);
for (i = 0; i < n; i++) {
hash_get_nth_cell(table, i)->node = NULL;
}
}
/*************************************************************//**
Inserts an entry into a hash table. If an entry with the same fold number
is found, its node is updated to point to the new data, and no new node
@ -141,7 +106,7 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
void* data) /*!< in: data, must not be NULL */
const rec_t* data) /*!< in: data, must not be NULL */
{
hash_cell_t* cell;
ha_node_t* node;
@ -154,7 +119,11 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(block->frame == page_align(data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(block->btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
ASSERT_HASH_MUTEX_OWN(table, fold);
ut_ad(btr_search_enabled);
hash = hash_calc_hash(fold, table);
@ -174,7 +143,6 @@ ha_insert_for_fold_func(
prev_block->n_pointers--;
block->n_pointers++;
}
ut_ad(!btr_search_fully_disabled);
# endif /* !UNIV_HOTBACKUP */
prev_node->block = block;
@ -187,13 +155,6 @@ ha_insert_for_fold_func(
prev_node = prev_node->next;
}
/* We are in the process of disabling hash index, do not add
new chain node */
if (!btr_search_enabled) {
ut_ad(!btr_search_fully_disabled);
return(TRUE);
}
/* We have to allocate a new chain node */
node = mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t));
@ -251,6 +212,10 @@ ha_delete_hash_node(
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
#ifdef UNIV_SYNC_DEBUG
// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(btr_search_enabled);
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
# ifndef UNIV_HOTBACKUP
if (table->adaptive) {
@ -273,11 +238,11 @@ ha_search_and_update_if_found_func(
/*===============================*/
hash_table_t* table, /*!< in/out: hash table */
ulint fold, /*!< in: folded value of the searched data */
void* data, /*!< in: pointer to the data */
const rec_t* data, /*!< in: pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* new_block,/*!< in: block containing new_data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
void* new_data)/*!< in: new pointer to the data */
const rec_t* new_data)/*!< in: new pointer to the data */
{
ha_node_t* node;
@ -287,6 +252,13 @@ ha_search_and_update_if_found_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(new_block->frame == page_align(new_data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
#ifdef UNIV_SYNC_DEBUG
// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
if (!btr_search_enabled) {
return;
}
node = ha_search_with_data(table, fold, data);
@ -323,6 +295,10 @@ ha_remove_all_nodes_to_page(
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ASSERT_HASH_MUTEX_OWN(table, fold);
#ifdef UNIV_SYNC_DEBUG
// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(btr_search_enabled);
node = ha_chain_get_first(table, fold);

95
storage/xtradb/handler/ha_innodb.cc

@ -3035,7 +3035,6 @@ skip_overwrite:
/* Get the current high water mark format. */
innobase_file_format_max = (char*) trx_sys_file_format_max_get();
btr_search_fully_disabled = (!btr_search_enabled);
DBUG_RETURN(FALSE);
error:
DBUG_RETURN(TRUE);
@ -5839,8 +5838,7 @@ no_commit:
switch (sql_command) {
case SQLCOM_LOAD:
if ((trx->duplicates
& (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
if (trx->duplicates) {
goto set_max_autoinc;
}
@ -6128,8 +6126,7 @@ ha_innobase::update_row(
&& table->next_number_field
&& new_row == table->record[0]
&& thd_sql_command(user_thd) == SQLCOM_INSERT
&& (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
== TRX_DUP_IGNORE) {
&& trx->duplicates) {
ulonglong auto_inc;
ulonglong col_max_value;
@ -6515,6 +6512,7 @@ ha_innobase::index_read(
(byte*) key_ptr,
(ulint) key_len,
prebuilt->trx);
DBUG_ASSERT(prebuilt->search_tuple->n_fields > 0);
} else {
/* We position the cursor to the last or the first entry
in the index */
@ -6616,7 +6614,6 @@ ha_innobase::innobase_get_index(
dict_index_t* index = 0;
DBUG_ENTER("innobase_get_index");
ha_statistic_increment(&SSV::ha_read_key_count);
if (keynr != MAX_KEY && table->s->keys > 0) {
key = table->key_info + keynr;
@ -6630,13 +6627,13 @@ ha_innobase::innobase_get_index(
table. Only print message if the index translation
table exists */
if (share->idx_trans_tbl.index_mapping) {
sql_print_error("InnoDB could not find "
"index %s key no %u for "
"table %s through its "
"index translation table",
key ? key->name : "NULL",
keynr,
prebuilt->table->name);
sql_print_warning("InnoDB could not find "
"index %s key no %u for "
"table %s through its "
"index translation table",
key ? key->name : "NULL",
keynr,
prebuilt->table->name);
}
index = dict_table_get_index_on_name(prebuilt->table,
@ -8465,6 +8462,9 @@ ha_innobase::records_in_range(
(const uchar*) 0),
(ulint) (min_key ? min_key->length : 0),
prebuilt->trx);
DBUG_ASSERT(min_key
? range_start->n_fields > 0
: range_start->n_fields == 0);
row_sel_convert_mysql_key_to_innobase(
range_end, (byte*) key_val_buff2,
@ -8473,6 +8473,9 @@ ha_innobase::records_in_range(
(const uchar*) 0),
(ulint) (max_key ? max_key->length : 0),
prebuilt->trx);
DBUG_ASSERT(max_key
? range_end->n_fields > 0
: range_end->n_fields == 0);
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
HA_READ_KEY_EXACT);
@ -9217,7 +9220,10 @@ ha_innobase::check(
putc('\n', stderr);
#endif
if (!btr_validate_index(index, prebuilt->trx)) {
/* If this is an index being created, break */
if (*index->name == TEMP_INDEX_PREFIX) {
break;
} else if (!btr_validate_index(index, prebuilt->trx)) {
is_ok = FALSE;
innobase_format_name(
@ -9770,6 +9776,7 @@ ha_innobase::extra(
break;
case HA_EXTRA_RESET_STATE:
reset_template();
thd_to_trx(ha_thd())->duplicates = 0;
break;
case HA_EXTRA_NO_KEYREAD:
prebuilt->read_just_key = 0;
@ -9787,19 +9794,18 @@ ha_innobase::extra(
parameters below. We must not invoke update_thd()
either, because the calling threads may change.
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
case HA_EXTRA_IGNORE_DUP_KEY:
case HA_EXTRA_INSERT_WITH_UPDATE:
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
break;
case HA_EXTRA_NO_IGNORE_DUP_KEY:
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_IGNORE;
break;
case HA_EXTRA_WRITE_CAN_REPLACE:
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
break;
case HA_EXTRA_WRITE_CANNOT_REPLACE:
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
break;
case HA_EXTRA_NO_IGNORE_DUP_KEY:
thd_to_trx(ha_thd())->duplicates &=
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
break;
default:/* Do nothing */
;
}
@ -12549,10 +12555,42 @@ static MYSQL_SYSVAR_ULINT(checkpoint_age_target, srv_checkpoint_age_target,
"Control soft limit of checkpoint age. (0 : not control)",
NULL, NULL, 0, 0, ~0UL, 0);
static MYSQL_SYSVAR_ULINT(flush_neighbor_pages, srv_flush_neighbor_pages,
PLUGIN_VAR_RQCMDARG,
"Enable/Disable flushing also neighbor pages. 0:disable 1:enable",
NULL, NULL, 1, 0, 1, 0);
static
void
innodb_flush_neighbor_pages_update(
THD* thd,
struct st_mysql_sys_var* var,
void* var_ptr,
const void* save)
{
*(long *)var_ptr = (*(long *)save) % 3;
}
const char *flush_neighbor_pages_names[]=
{
"none", /* 0 */
"area",
"cont", /* 2 */
/* For compatibility with the older patch */
"0", /* "none" + 3 */
"1", /* "area" + 3 */
"2", /* "cont" + 3 */
NullS
};
TYPELIB flush_neighbor_pages_typelib=
{
array_elements(flush_neighbor_pages_names) - 1,
"flush_neighbor_pages_typelib",
flush_neighbor_pages_names,
NULL
};
static MYSQL_SYSVAR_ENUM(flush_neighbor_pages, srv_flush_neighbor_pages,
PLUGIN_VAR_RQCMDARG, "Neighbor page flushing behaviour: none: do not flush, "
"[area]: flush selected pages one-by-one, "
"cont: flush a contiguous block of pages", NULL,
innodb_flush_neighbor_pages_update, 1, &flush_neighbor_pages_typelib);
static
void
@ -12618,6 +12656,14 @@ static MYSQL_SYSVAR_ENUM(adaptive_flushing_method, srv_adaptive_flushing_method,
"Choose method of innodb_adaptive_flushing. (native, [estimate], keep_average)",
NULL, innodb_adaptive_flushing_method_update, 1, &adaptive_flushing_method_typelib);
#ifdef UNIV_DEBUG
static MYSQL_SYSVAR_ULONG(flush_checkpoint_debug, srv_flush_checkpoint_debug,
PLUGIN_VAR_RQCMDARG,
"Debug flags for InnoDB flushing and checkpointing (0=none,"
"1=stop preflush and checkpointing)",
NULL, NULL, 0, 0, 1, 0);
#endif
static MYSQL_SYSVAR_ULONG(import_table_from_xtrabackup, srv_expand_import,
PLUGIN_VAR_RQCMDARG,
"Enable/Disable converting automatically *.ibd files when import tablespace.",
@ -12764,6 +12810,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(purge_threads),
MYSQL_SYSVAR(purge_batch_size),
MYSQL_SYSVAR(rollback_segments),
#ifdef UNIV_DEBUG
MYSQL_SYSVAR(flush_checkpoint_debug),
#endif
MYSQL_SYSVAR(corrupt_table_action),
MYSQL_SYSVAR(lazy_drop_table),
MYSQL_SYSVAR(fake_changes),

2
storage/xtradb/handler/i_s.cc

@ -3916,7 +3916,7 @@ i_s_innodb_buffer_pool_pages_index_fill(
table->field[2]->store(block->page.offset, TRUE);
table->field[3]->store(page_get_n_recs(frame), TRUE);
table->field[4]->store(page_get_data_size(frame), TRUE);
table->field[5]->store(block->is_hashed, TRUE);
table->field[5]->store(block->index != NULL, TRUE);
table->field[6]->store(block->page.access_time, TRUE);
table->field[7]->store(block->page.newest_modification != 0, TRUE);
table->field[8]->store(block->page.oldest_modification != 0, TRUE);

317
storage/xtradb/ibuf/ibuf0ibuf.c

@ -254,11 +254,20 @@ ibuf_count_check(
list of the ibuf */
/* @} */
#define IBUF_REC_FIELD_SPACE 0 /*!< in the pre-4.1 format,
the page number. later, the space_id */
#define IBUF_REC_FIELD_MARKER 1 /*!< starting with 4.1, a marker
consisting of 1 byte that is 0 */
#define IBUF_REC_FIELD_PAGE 2 /*!< starting with 4.1, the
page number */
#define IBUF_REC_FIELD_METADATA 3 /* the metadata field */
#define IBUF_REC_FIELD_USER 4 /* first user field */
/* Various constants for checking the type of an ibuf record and extracting
data from it. For details, see the description of the record format at the
top of this file. */
/** @name Format of the fourth column of an insert buffer record
/** @name Format of the IBUF_REC_FIELD_METADATA of an insert buffer record
The fourth column in the MySQL 5.5 format contains an operation
type, counter, and some flags. */
/* @{ */
@ -1275,13 +1284,13 @@ ibuf_rec_get_page_no_func(
ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(rec) > 2);
field = rec_get_nth_field_old(rec, 1, &len);
field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len);
if (len == 1) {
/* This is of the >= 4.1.x record format */
ut_a(trx_sys_multiple_tablespace_format);
field = rec_get_nth_field_old(rec, 2, &len);
field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_PAGE, &len);
} else {
ut_a(trx_doublewrite_must_reset_space_ids);
ut_a(!trx_sys_multiple_tablespace_format);
@ -1321,13 +1330,13 @@ ibuf_rec_get_space_func(
ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(rec) > 2);
field = rec_get_nth_field_old(rec, 1, &len);
field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len);
if (len == 1) {
/* This is of the >= 4.1.x record format */
ut_a(trx_sys_multiple_tablespace_format);
field = rec_get_nth_field_old(rec, 0, &len);
field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_SPACE, &len);
ut_a(len == 4);
return(mach_read_from_4(field));
@ -1377,9 +1386,9 @@ ibuf_rec_get_info_func(
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(ibuf_inside(mtr));
fields = rec_get_n_fields_old(rec);
ut_a(fields > 4);
ut_a(fields > IBUF_REC_FIELD_USER);
types = rec_get_nth_field_old(rec, 3, &len);
types = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len);
info_len_local = len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE;
@ -1405,7 +1414,8 @@ ibuf_rec_get_info_func(
ut_a(op_local < IBUF_OP_COUNT);
ut_a((len - info_len_local) ==
(fields - 4) * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
(fields - IBUF_REC_FIELD_USER)
* DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
if (op) {
*op = op_local;
@ -1449,7 +1459,7 @@ ibuf_rec_get_op_type_func(
ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(rec) > 2);
(void) rec_get_nth_field_old(rec, 1, &len);
(void) rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len);
if (len > 1) {
/* This is a < 4.1.x format record */
@ -1478,12 +1488,12 @@ ibuf_rec_get_counter(
const byte* ptr;
ulint len;
if (rec_get_n_fields_old(rec) < 4) {
if (rec_get_n_fields_old(rec) <= IBUF_REC_FIELD_METADATA) {
return(ULINT_UNDEFINED);
}
ptr = rec_get_nth_field_old(rec, 3, &len);
ptr = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len);
if (len >= 2) {
@ -1708,7 +1718,7 @@ ibuf_build_entry_from_ibuf_rec_func(
|| mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(ibuf_inside(mtr));
data = rec_get_nth_field_old(ibuf_rec, 1, &len);
data = rec_get_nth_field_old(ibuf_rec, IBUF_REC_FIELD_MARKER, &len);
if (len > 1) {
/* This a < 4.1.x format record */
@ -1720,13 +1730,13 @@ ibuf_build_entry_from_ibuf_rec_func(
ut_a(trx_sys_multiple_tablespace_format);
ut_a(*data == 0);
ut_a(rec_get_n_fields_old(ibuf_rec) > 4);
ut_a(rec_get_n_fields_old(ibuf_rec) > IBUF_REC_FIELD_USER);
n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
n_fields = rec_get_n_fields_old(ibuf_rec) - IBUF_REC_FIELD_USER;
tuple = dtuple_create(heap, n_fields);
types = rec_get_nth_field_old(ibuf_rec, 3, &len);
types = rec_get_nth_field_old(ibuf_rec, IBUF_REC_FIELD_METADATA, &len);
ibuf_rec_get_info(mtr, ibuf_rec, NULL, &comp, &info_len, NULL);
@ -1740,7 +1750,8 @@ ibuf_build_entry_from_ibuf_rec_func(
for (i = 0; i < n_fields; i++) {
field = dtuple_get_nth_field(tuple, i);
data = rec_get_nth_field_old(ibuf_rec, i + 4, &len);
data = rec_get_nth_field_old(
ibuf_rec, i + IBUF_REC_FIELD_USER, &len);
dfield_set_data(field, data, len);
@ -1787,7 +1798,7 @@ ibuf_rec_get_size(
field_offset = 2;
types_offset = DATA_ORDER_NULL_TYPE_BUF_SIZE;
} else {
field_offset = 4;
field_offset = IBUF_REC_FIELD_USER;
types_offset = DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE;
}
@ -1848,7 +1859,7 @@ ibuf_rec_get_volume_func(
ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(ibuf_rec) > 2);
data = rec_get_nth_field_old(ibuf_rec, 1, &len);
data = rec_get_nth_field_old(ibuf_rec, IBUF_REC_FIELD_MARKER, &len);
pre_4_1 = (len > 1);
if (pre_4_1) {
@ -1871,7 +1882,8 @@ ibuf_rec_get_volume_func(
ut_a(trx_sys_multiple_tablespace_format);
ut_a(*data == 0);
types = rec_get_nth_field_old(ibuf_rec, 3, &len);
types = rec_get_nth_field_old(
ibuf_rec, IBUF_REC_FIELD_METADATA, &len);
ibuf_rec_get_info(mtr, ibuf_rec, &op, &comp, &info_len, NULL);
@ -1901,7 +1913,8 @@ ibuf_rec_get_volume_func(
}
types += info_len;
n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
n_fields = rec_get_n_fields_old(ibuf_rec)
- IBUF_REC_FIELD_USER;
}
data_size = ibuf_rec_get_size(ibuf_rec, types, n_fields, pre_4_1, comp);
@ -1956,11 +1969,11 @@ ibuf_entry_build(
n_fields = dtuple_get_n_fields(entry);
tuple = dtuple_create(heap, n_fields + 4);
tuple = dtuple_create(heap, n_fields + IBUF_REC_FIELD_USER);
/* 1) Space Id */
field = dtuple_get_nth_field(tuple, 0);
field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_SPACE);
buf = mem_heap_alloc(heap, 4);
@ -1970,7 +1983,7 @@ ibuf_entry_build(
/* 2) Marker byte */
field = dtuple_get_nth_field(tuple, 1);
field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_MARKER);
buf = mem_heap_alloc(heap, 1);
@ -1982,7 +1995,7 @@ ibuf_entry_build(
/* 3) Page number */
field = dtuple_get_nth_field(tuple, 2);
field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_PAGE);
buf = mem_heap_alloc(heap, 4);
@ -2030,10 +2043,7 @@ ibuf_entry_build(
ulint fixed_len;
const dict_field_t* ifield;
/* We add 4 below because we have the 4 extra fields at the
start of an ibuf record */
field = dtuple_get_nth_field(tuple, i + 4);
field = dtuple_get_nth_field(tuple, i + IBUF_REC_FIELD_USER);
entry_field = dtuple_get_nth_field(entry, i);
dfield_copy(field, entry_field);
@ -2066,13 +2076,13 @@ ibuf_entry_build(
/* 4) Type info, part #2 */
field = dtuple_get_nth_field(tuple, 3);
field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_METADATA);
dfield_set_data(field, type_info, ti - type_info);
/* Set all the types in the new tuple binary */
dtuple_set_types_binary(tuple, n_fields + 4);
dtuple_set_types_binary(tuple, n_fields + IBUF_REC_FIELD_USER);
return(tuple);
}
@ -2132,11 +2142,11 @@ ibuf_new_search_tuple_build(
ut_a(trx_sys_multiple_tablespace_format);
tuple = dtuple_create(heap, 3);
tuple = dtuple_create(heap, IBUF_REC_FIELD_METADATA);
/* Store the space id in tuple */
field = dtuple_get_nth_field(tuple, 0);
field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_SPACE);
buf = mem_heap_alloc(heap, 4);
@ -2146,7 +2156,7 @@ ibuf_new_search_tuple_build(
/* Store the new format record marker byte */
field = dtuple_get_nth_field(tuple, 1);
field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_MARKER);
buf = mem_heap_alloc(heap, 1);
@ -2156,7 +2166,7 @@ ibuf_new_search_tuple_build(
/* Store the page number in tuple */
field = dtuple_get_nth_field(tuple, 2);
field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_PAGE);
buf = mem_heap_alloc(heap, 4);
@ -2164,7 +2174,7 @@ ibuf_new_search_tuple_build(
dfield_set_data(field, buf, 4);
dtuple_set_types_binary(tuple, 3);
dtuple_set_types_binary(tuple, IBUF_REC_FIELD_METADATA);
return(tuple);
}
@ -2833,8 +2843,10 @@ ibuf_get_volume_buffered_hash(
ulint fold;
ulint bitmask;
len = ibuf_rec_get_size(rec, types, rec_get_n_fields_old(rec) - 4,
FALSE, comp);
len = ibuf_rec_get_size(
rec, types,
rec_get_n_fields_old(rec) - IBUF_REC_FIELD_USER,
FALSE, comp);
fold = ut_fold_binary(data, len);
hash += (fold / (CHAR_BIT * sizeof *hash)) % size;
@ -2886,8 +2898,8 @@ ibuf_get_volume_buffered_count_func(
ut_ad(ibuf_inside(mtr));
n_fields = rec_get_n_fields_old(rec);
ut_ad(n_fields > 4);
n_fields -= 4;
ut_ad(n_fields > IBUF_REC_FIELD_USER);
n_fields -= IBUF_REC_FIELD_USER;
rec_get_nth_field_offs_old(rec, 1, &len);
/* This function is only invoked when buffering new
@ -2896,7 +2908,7 @@ ibuf_get_volume_buffered_count_func(
ut_a(len == 1);
ut_ad(trx_sys_multiple_tablespace_format);
types = rec_get_nth_field_old(rec, 3, &len);
types = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len);
switch (UNIV_EXPECT(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE,
IBUF_REC_INFO_SIZE)) {
@ -3208,7 +3220,7 @@ ibuf_update_max_tablespace_id(void)
} else {
rec = btr_pcur_get_rec(&pcur);
field = rec_get_nth_field_old(rec, 0, &len);
field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_SPACE, &len);
ut_a(len == 4);
@ -3230,10 +3242,12 @@ ibuf_update_max_tablespace_id(void)
ibuf_get_entry_counter_low_func(rec,space,page_no)
#endif
/****************************************************************//**
Helper function for ibuf_set_entry_counter. Checks if rec is for (space,
page_no), and if so, reads counter value from it and returns that + 1.
Otherwise, returns 0.
@return new counter value, or 0 */
Helper function for ibuf_get_entry_counter_func. Checks if rec is for
(space, page_no), and if so, reads counter value from it and returns
that + 1.
@retval ULINT_UNDEFINED if the record does not contain any counter
@retval 0 if the record is not for (space, page_no)
@retval 1 + previous counter value, otherwise */
static
ulint
ibuf_get_entry_counter_low_func(
@ -3254,7 +3268,7 @@ ibuf_get_entry_counter_low_func(
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(rec_get_n_fields_old(rec) > 2);
field = rec_get_nth_field_old(rec, 1, &len);
field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len);
if (UNIV_UNLIKELY(len != 1)) {
/* pre-4.1 format */
@ -3267,7 +3281,7 @@ ibuf_get_entry_counter_low_func(
ut_a(trx_sys_multiple_tablespace_format);
/* Check the tablespace identifier. */
field = rec_get_nth_field_old(rec, 0, &len);
field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_SPACE, &len);
ut_a(len == 4);
if (mach_read_from_4(field) != space) {
@ -3276,7 +3290,7 @@ ibuf_get_entry_counter_low_func(
}
/* Check the page offset. */
field = rec_get_nth_field_old(rec, 2, &len);
field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_PAGE, &len);
ut_a(len == 4);
if (mach_read_from_4(field) != page_no) {
@ -3285,7 +3299,7 @@ ibuf_get_entry_counter_low_func(
}
/* Check if the record contains a counter field. */
field = rec_get_nth_field_old(rec, 3, &len);
field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len);
switch (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) {
default:
@ -3301,147 +3315,61 @@ ibuf_get_entry_counter_low_func(
}
}
#ifdef UNIV_DEBUG
# define ibuf_get_entry_counter(space,page_no,rec,mtr,exact_leaf) \
ibuf_get_entry_counter_func(space,page_no,rec,mtr,exact_leaf)
#else /* UNIV_DEBUG */
# define ibuf_get_entry_counter(space,page_no,rec,mtr,exact_leaf) \
ibuf_get_entry_counter_func(space,page_no,rec,exact_leaf)
#endif
/****************************************************************//**
Set the counter field in entry to the correct value based on the current
Calculate the counter field for an entry based on the current
last record in ibuf for (space, page_no).
@return FALSE if we should abort this insertion to ibuf */
@return the counter field, or ULINT_UNDEFINED
if we should abort this insertion to ibuf */
static
ibool
ibuf_set_entry_counter(
/*===================*/
dtuple_t* entry, /*!< in/out: entry to patch */
ulint
ibuf_get_entry_counter_func(
/*========================*/
ulint space, /*!< in: space id of entry */
ulint page_no, /*!< in: page number of entry */
btr_pcur_t* pcur, /*!< in: pcur positioned on the record
found by btr_pcur_open(.., entry,
PAGE_CUR_LE, ..., pcur, ...) */
ibool is_optimistic, /*!< in: is this an optimistic insert */
mtr_t* mtr) /*!< in: mtr */
const rec_t* rec, /*!< in: the record preceding the
insertion point */
#ifdef UNIV_DEBUG
mtr_t* mtr, /*!< in: mini-transaction */
#endif /* UNIV_DEBUG */
ibool only_leaf) /*!< in: TRUE if this is the only
leaf page that can contain entries
for (space,page_no), that is, there
was no exact match for (space,page_no)
in the node pointer */
{
dfield_t* field;
byte* data;
ulint counter = 0;
/* pcur points to either a user rec or to a page's infimum record. */
ut_ad(ibuf_inside(mtr));
ut_ad(mtr_memo_contains(mtr, btr_pcur_get_block(pcur),
MTR_MEMO_PAGE_X_FIX));
ut_ad(page_validate(btr_pcur_get_page(pcur), ibuf->index));
if (btr_pcur_is_on_user_rec(pcur)) {
counter = ibuf_get_entry_counter_low(
mtr, btr_pcur_get_rec(pcur), space, page_no);
if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
/* The record lacks a counter field.
Such old records must be merged before
new records can be buffered. */
return(FALSE);
}
} else if (btr_pcur_is_before_first_in_tree(pcur, mtr)) {
/* Ibuf tree is either completely empty, or the insert
position is at the very first record of a non-empty tree. In
either case we have no previous records for (space,
page_no). */
counter = 0;
} else if (btr_pcur_is_before_first_on_page(pcur)) {
btr_cur_t* cursor = btr_pcur_get_btr_cur(pcur);
if (cursor->low_match < 3) {
/* If low_match < 3, we know that the father node
pointer did not contain the searched for (space,
page_no), which means that the search ended on the
right page regardless of the counter value, and
since we're at the infimum record, there are no
existing records. */
counter = 0;
} else {
rec_t* rec;
const page_t* page;
buf_block_t* block;
page_t* prev_page;
ulint prev_page_no;
ut_a(cursor->ibuf_cnt != ULINT_UNDEFINED);
page = btr_pcur_get_page(pcur);
prev_page_no = btr_page_get_prev(page, mtr);
ut_a(prev_page_no != FIL_NULL);
block = buf_page_get(
IBUF_SPACE_ID, 0, prev_page_no,
RW_X_LATCH, mtr);
ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX));
ut_ad(page_validate(page_align(rec), ibuf->index));
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
prev_page = buf_block_get_frame(block);
rec = page_rec_get_prev(
page_get_supremum_rec(prev_page));
ut_ad(page_rec_is_user_rec(rec));
counter = ibuf_get_entry_counter_low(
mtr, rec, space, page_no);
if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
/* The record lacks a counter field.
Such old records must be merged before
new records can be buffered. */
return(FALSE);
}
if (counter < cursor->ibuf_cnt) {
/* Search ended on the wrong page. */
if (is_optimistic) {
/* In an optimistic insert, we can
shift the insert position to the left
page, since it only needs an X-latch
on the page itself, which the
original search acquired for us. */
btr_cur_position(
ibuf->index, rec, block,
btr_pcur_get_btr_cur(pcur));
} else {
/* We can't shift the insert
position to the left page in a
pessimistic insert since it would
require an X-latch on the left
page's left page, so we have to
abort. */
return(FALSE);
}
} else {
/* The counter field in the father node is
the same as we would insert; we don't know
whether the insert should go to this page or
the left page (the later fields can differ),
so refuse the insert. */
return(FALSE);
}
}
if (page_rec_is_supremum(rec)) {
/* This is just for safety. The record should be a
page infimum or a user record. */
ut_ad(0);
return(ULINT_UNDEFINED);
} else if (!page_rec_is_infimum(rec)) {
return(ibuf_get_entry_counter_low(mtr, rec, space, page_no));
} else if (only_leaf
|| fil_page_get_prev(page_align(rec)) == FIL_NULL) {
/* The parent node pointer did not contain the
searched for (space, page_no), which means that the
search ended on the correct page regardless of the
counter value, and since we're at the infimum record,
there are no existing records. */
return(0);
} else {
/* The cursor is not positioned at or before a user record. */
return(FALSE);
/* We used to read the previous page here. It would
break the latching order, because the caller has
buffer-fixed an insert buffer bitmap page. */
return(ULINT_UNDEFINED);
}
/* Patch counter value in already built entry. */
field = dtuple_get_nth_field(entry, 3);
data = dfield_get_data(field);
mach_write_to_2(data + IBUF_REC_OFFSET_COUNTER, counter);
return(TRUE);
}
/*********************************************************************//**
@ -3650,16 +3578,27 @@ fail_exit:
}
}
/* Patch correct counter value to the entry to insert. This can
change the insert position, which can result in the need to abort in
some cases. */
if (!no_counter
&& !ibuf_set_entry_counter(ibuf_entry, space, page_no, &pcur,
mode == BTR_MODIFY_PREV, &mtr)) {
if (!no_counter) {
/* Patch correct counter value to the entry to
insert. This can change the insert position, which can
result in the need to abort in some cases. */
ulint counter = ibuf_get_entry_counter(
space, page_no, btr_pcur_get_rec(&pcur), &mtr,
btr_pcur_get_btr_cur(&pcur)->low_match
< IBUF_REC_FIELD_METADATA);
dfield_t* field;
if (counter == ULINT_UNDEFINED) {
bitmap_fail:
ibuf_mtr_commit(&bitmap_mtr);
ibuf_mtr_commit(&bitmap_mtr);
goto fail_exit;
}
goto fail_exit;
field = dtuple_get_nth_field(
ibuf_entry, IBUF_REC_FIELD_METADATA);
mach_write_to_2(
(byte*) dfield_get_data(field)
+ IBUF_REC_OFFSET_COUNTER, counter);
}
/* Set the bitmap bit denoting that the insert buffer contains
@ -4003,7 +3942,7 @@ ibuf_insert_to_index_page(
ut_ad(ibuf_inside(mtr));
ut_ad(dtuple_check_typed(entry));
ut_ad(!buf_block_align(page)->is_hashed);
ut_ad(!buf_block_align(page)->index);
if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
!= (ibool)!!page_is_comp(page))) {

18
storage/xtradb/include/btr0cur.h

@ -743,24 +743,6 @@ struct btr_cur_struct {
NULL */
ulint fold; /*!< fold value used in the search if
flag is BTR_CUR_HASH */
/*----- Delete buffering -------*/
ulint ibuf_cnt; /* in searches done on insert buffer
trees, this contains the "counter"
value (the first two bytes of the
fourth field) extracted from the
page above the leaf page, from the
father node pointer that pointed to
the leaf page. in other words, it
contains the minimum counter value
for records to be inserted on the
chosen leaf page. If for some reason
this can't be read, or if the search
ended on the leftmost leaf page in
the tree (in which case the father
node pointer had the 'minimum
record' flag set), this is
ULINT_UNDEFINED. */
/*------------------------------*/
/* @} */
btr_path_t* path_arr; /*!< in estimating the number of
rows in range, we store in this array

8
storage/xtradb/include/btr0pcur.h

@ -263,14 +263,6 @@ btr_pcur_commit_specify_mtr(
/*========================*/
btr_pcur_t* pcur, /*!< in: persistent cursor */
mtr_t* mtr); /*!< in: mtr to commit */
/**************************************************************//**
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
@return TRUE if detached */
UNIV_INLINE
ibool
btr_pcur_is_detached(
/*=================*/
btr_pcur_t* pcur); /*!< in: persistent cursor */
/*********************************************************//**
Moves the persistent cursor to the next record in the tree. If no records are
left, the cursor stays 'after last in tree'.

32
storage/xtradb/include/btr0pcur.ic

@ -388,38 +388,6 @@ btr_pcur_commit_specify_mtr(
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
}
/**************************************************************//**
Sets the pcur latch mode to BTR_NO_LATCHES. */
UNIV_INLINE
void
btr_pcur_detach(
/*============*/
btr_pcur_t* pcur) /*!< in: persistent cursor */
{
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
pcur->latch_mode = BTR_NO_LATCHES;
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
}
/**************************************************************//**
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
@return TRUE if detached */
UNIV_INLINE
ibool
btr_pcur_is_detached(
/*=================*/
btr_pcur_t* pcur) /*!< in: persistent cursor */
{
if (pcur->latch_mode == BTR_NO_LATCHES) {
return(TRUE);
}
return(FALSE);
}
/**************************************************************//**
Sets the old_rec_buf field to NULL. */
UNIV_INLINE

42
storage/xtradb/include/btr0sea.h

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -137,11 +137,10 @@ UNIV_INTERN
void
btr_search_drop_page_hash_index(
/*============================*/
buf_block_t* block, /*!< in: block containing index page,
buf_block_t* block); /*!< in: block containing index page,
s- or x-latched, or an index page
for which we know that
block->buf_fix_count == 0 */
dict_index_t* index_in);
/************************************************************************
Drops a page hash index based on index */
UNIV_INTERN
@ -150,8 +149,8 @@ btr_search_drop_page_hash_index_on_index(
/*=====================================*/
dict_index_t* index); /* in: record descriptor */
/********************************************************************//**
Drops a page hash index when a page is freed from a fseg to the file system.
Drops possible hash index if the page happens to be in the buffer pool. */
Drops a possible page hash index when a page is evicted from the buffer pool
or freed in a file segment. */
UNIV_INTERN
void
btr_search_drop_page_hash_when_freed(
@ -235,19 +234,6 @@ void
btr_search_s_unlock_all(void);
/*==========================*/
/** Flag: has the search system been enabled?
Protected by btr_search_latch and btr_search_enabled_mutex. */
extern char btr_search_enabled;
extern ulint btr_search_index_num;
/** Flag: whether the search system has completed its disabling process,
It is set to TRUE right after buf_pool_drop_hash_index() in
btr_search_disable(), indicating hash index entries are cleaned up.
Protected by btr_search_latch and btr_search_enabled_mutex. */
extern ibool btr_search_fully_disabled;
/** The search info struct in an index */
struct btr_search_struct{
ulint ref_count; /*!< Number of blocks in this index tree
@ -316,26 +302,6 @@ struct btr_search_sys_struct{
/** The adaptive hash index */
extern btr_search_sys_t* btr_search_sys;
/** @brief The latch protecting the adaptive search system
This latch protects the
(1) hash index;
(2) columns of a record to which we have a pointer in the hash index;
but does NOT protect:
(3) next record offset field in a record;
(4) next or previous records on the same page.
Bear in mind (3) and (4) when using the hash index.
*/
//extern rw_lock_t* btr_search_latch_temp;
extern rw_lock_t** btr_search_latch_part;
/** The latch protecting the adaptive search system */
//#define btr_search_latch (*btr_search_latch_temp)
#ifdef UNIV_SEARCH_PERF_STAT
/** Number of successful adaptive hash index lookups */
extern ulint btr_search_n_succ;

29
storage/xtradb/include/btr0types.h

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -30,6 +30,7 @@ Created 2/17/1996 Heikki Tuuri
#include "rem0types.h"
#include "page0types.h"
#include "sync0rw.h"
/** Persistent cursor */
typedef struct btr_pcur_struct btr_pcur_t;
@ -38,6 +39,32 @@ typedef struct btr_cur_struct btr_cur_t;
/** B-tree search information for the adaptive hash index */
typedef struct btr_search_struct btr_search_t;
/** @brief The latch protecting the adaptive search system
This latch protects the
(1) hash index;
(2) columns of a record to which we have a pointer in the hash index;
but does NOT protect:
(3) next record offset field in a record;
(4) next or previous records on the same page.
Bear in mind (3) and (4) when using the hash index.
*/
//extern rw_lock_t* btr_search_latch_temp;
extern rw_lock_t** btr_search_latch_part;
/** The latch protecting the adaptive search system */
//#define btr_search_latch (*btr_search_latch_temp)
/** Flag: has the search system been enabled?
Protected by btr_search_latch. */
extern char btr_search_enabled;
extern ulint btr_search_index_num;
#ifdef UNIV_BLOB_DEBUG
# include "buf0types.h"
/** An index->blobs entry for keeping track of off-page column references */

68
storage/xtradb/include/buf0buf.h

@ -244,13 +244,11 @@ buf_pool_free(
ulint n_instances); /*!< in: numbere of instances to free */
/********************************************************************//**
Drops the adaptive hash index. To prevent a livelock, this function
is only to be called while holding btr_search_latch and while
btr_search_enabled == FALSE. */
Clears the adaptive hash index on all pages in the buffer pool. */
UNIV_INTERN
void
buf_pool_drop_hash_index(void);
/*==========================*/
buf_pool_clear_hash_index(void);
/*===========================*/
/********************************************************************//**
Relocate a buffer control block. Relocates the block on the LRU list
@ -583,17 +581,6 @@ buf_page_peek_if_too_old(
/*=====================*/
const buf_page_t* bpage); /*!< in: block to make younger */
/********************************************************************//**
Returns the current state of is_hashed of a page. FALSE if the page is
not in the pool. NOTE that this operation does not fix the page in the
pool if it is found there.
@return TRUE if page hash index is built in search system */
UNIV_INTERN
ibool
buf_page_peek_if_search_hashed(
/*===========================*/
ulint space, /*!< in: space id */
ulint offset);/*!< in: page number */
/********************************************************************//**
Gets the youngest modification log sequence number for a frame.
Returns zero if not file page or no modification occurred yet.
@return newest modification to page */
@ -952,7 +939,27 @@ buf_block_set_io_fix(
/*=================*/
buf_block_t* block, /*!< in/out: control block */
enum buf_io_fix io_fix);/*!< in: io_fix state */
/*********************************************************************//**
Makes a block sticky. A sticky block implies that even after we release
the buf_pool->mutex and the block->mutex:
* it cannot be removed from the flush_list
* the block descriptor cannot be relocated
* it cannot be removed from the LRU list
Note that:
* the block can still change its position in the LRU list
* the next and previous pointers can change. */
UNIV_INLINE
void
buf_page_set_sticky(
/*================*/
buf_page_t* bpage); /*!< in/out: control block */
/*********************************************************************//**
Removes stickiness of a block. */
UNIV_INLINE
void
buf_page_unset_sticky(
/*==================*/
buf_page_t* bpage); /*!< in/out: control block */
/********************************************************************//**
Determine if a buffer block can be relocated in memory. The block
can be dirty, but it must not be I/O-fixed or bufferfixed. */
@ -1569,13 +1576,16 @@ struct buf_block_struct{
/* @} */
/** @name Hash search fields
These 6 fields may only be modified when we have
These 5 fields may only be modified when we have
an x-latch on btr_search_latch AND
- we are holding an s-latch or x-latch on buf_block_struct::lock or
- we know that buf_block_struct::buf_fix_count == 0.
An exception to this is when we init or create a page
in the buffer pool in buf0buf.c. */
in the buffer pool in buf0buf.c.
Another exception is that assigning block->index = NULL
is allowed whenever holding an x-latch on btr_search_latch. */
/* @{ */
@ -1584,21 +1594,21 @@ struct buf_block_struct{
pointers in the adaptive hash index
pointing to this frame */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
volatile unsigned is_hashed:1; /*!< TRUE if hash index has
already been built on this
page; note that it does not
guarantee that the index is
complete, though: there may
have been hash collisions,
record deletions, etc. */
unsigned curr_n_fields:10;/*!< prefix length for hash indexing:
number of full fields */
unsigned curr_n_bytes:15;/*!< number of bytes in hash
indexing */
unsigned curr_left_side:1;/*!< TRUE or FALSE in hash indexing */
dict_index_t* index; /*!< Index for which the adaptive
hash index has been created. */
volatile rw_lock_t* btr_search_latch;
dict_index_t* index; /*!< Index for which the
adaptive hash index has been
created, or NULL if the page
does not exist in the
index. Note that it does not
guarantee that the index is
complete, though: there may
have been hash collisions,
record deletions, etc. */
volatile rw_lock_t* btr_search_latch;
/* @} */
# ifdef UNIV_SYNC_DEBUG
/** @name Debug fields */

44
storage/xtradb/include/buf0buf.ic

@ -444,6 +444,7 @@ buf_page_get_io_fix(
case BUF_IO_NONE:
case BUF_IO_READ:
case BUF_IO_WRITE:
case BUF_IO_PIN:
return(io_fix);
}
ut_error;
@ -494,6 +495,49 @@ buf_block_set_io_fix(
buf_page_set_io_fix(&block->page, io_fix);
}
/*********************************************************************//**
Makes a block sticky. A sticky block implies that even after we release
the buf_pool->mutex and the block->mutex:
* it cannot be removed from the flush_list
* the block descriptor cannot be relocated
* it cannot be removed from the LRU list
Note that:
* the block can still change its position in the LRU list
* the next and previous pointers can change. */
UNIV_INLINE
void
buf_page_set_sticky(
/*================*/
buf_page_t* bpage) /*!< in/out: control block */
{
#ifdef UNIV_DEBUG
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
#endif
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
bpage->io_fix = BUF_IO_PIN;
}
/*********************************************************************//**
Removes stickiness of a block. */
UNIV_INLINE
void
buf_page_unset_sticky(
/*==================*/
buf_page_t* bpage) /*!< in/out: control block */
{
#ifdef UNIV_DEBUG
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
#endif
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_PIN);
bpage->io_fix = BUF_IO_NONE;
}
/********************************************************************//**
Determine if a buffer block can be relocated in memory. The block
can be dirty, but it must not be I/O-fixed or bufferfixed. */

5
storage/xtradb/include/buf0types.h

@ -57,7 +57,10 @@ enum buf_flush {
enum buf_io_fix {
BUF_IO_NONE = 0, /**< no pending I/O */
BUF_IO_READ, /**< read pending */
BUF_IO_WRITE /**< write pending */
BUF_IO_WRITE, /**< write pending */
BUF_IO_PIN /**< disallow relocation of
block and its removal of from
the flush_list */
};
/** Parameters of binary buddy system for compressed pages (buf0buddy.h) */

23
storage/xtradb/include/fil0fil.h

@ -34,6 +34,7 @@ Created 10/25/1995 Heikki Tuuri
#include "sync0rw.h"
#include "ibuf0types.h"
#endif /* !UNIV_HOTBACKUP */
#include "trx0types.h"
/** When mysqld is run, the default directory "." is the mysqld datadir,
but in the MySQL Embedded Server Library and ibbackup it is not the default
@ -329,18 +330,23 @@ Reads the flushed lsn and arch no fields from a data file at database
startup. */
UNIV_INTERN
void
fil_read_flushed_lsn_and_arch_log_no(
/*=================================*/
fil_read_first_page(
/*================*/
os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
ulint* flags, /*!< out: tablespace flags */
#ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no, /*!< in/out: */
ulint* max_arch_log_no, /*!< in/out: */
ulint* min_arch_log_no, /*!< out: min of archived
log numbers in data files */
ulint* max_arch_log_no, /*!< out: max of archived
log numbers in data files */
#endif /* UNIV_LOG_ARCHIVE */
ib_uint64_t* min_flushed_lsn, /*!< in/out: */
ib_uint64_t* max_flushed_lsn); /*!< in/out: */
ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed
lsn values in data files */
ib_uint64_t* max_flushed_lsn); /*!< out: max of flushed
lsn values in data files */
/*******************************************************************//**
Increments the count of pending insert buffer page merges, if space is not
being deleted.
@ -474,8 +480,11 @@ fil_open_single_table_tablespace(
accessing the first page of the file */
ulint id, /*!< in: space id */
ulint flags, /*!< in: tablespace flags */
const char* name); /*!< in: table name in the
const char* name, /*!< in: table name in the
databasename/tablename format */
trx_t* trx); /*!< in: transaction. This is only used
for IMPORT TABLESPACE, must be NULL
otherwise */
/********************************************************************//**
It is possible, though very improbable, that the lsn's in the tablespace to be
imported have risen above the current system lsn, if a lengthy purge, ibuf

102
storage/xtradb/include/fsp0fsp.h

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@ -34,6 +34,90 @@ Created 12/18/1995 Heikki Tuuri
#include "page0types.h"
#include "fsp0types.h"
/* @defgroup fsp_flags InnoDB Tablespace Flag Constants @{ */
/** Number of flag bits used to indicate the tablespace page size */
#define FSP_FLAGS_WIDTH_PAGE_SSIZE 4
/** Zero relative shift position of the PAGE_SSIZE field */
#define FSP_FLAGS_POS_PAGE_SSIZE 6
/** Bit mask of the PAGE_SSIZE field */
#define FSP_FLAGS_MASK_PAGE_SSIZE \
((~(~0 << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \
<< FSP_FLAGS_POS_PAGE_SSIZE)
/** Return the value of the PAGE_SSIZE field */
#define FSP_FLAGS_GET_PAGE_SSIZE(flags) \
((flags & FSP_FLAGS_MASK_PAGE_SSIZE) \
>> FSP_FLAGS_POS_PAGE_SSIZE)
/* @} */
/* @defgroup Tablespace Header Constants (moved from fsp0fsp.c) @{ */
/** Offset of the space header within a file page */
#define FSP_HEADER_OFFSET FIL_PAGE_DATA
/* The data structures in files are defined just as byte strings in C */
typedef byte fsp_header_t;
typedef byte xdes_t;
/* SPACE HEADER
============
File space header data structure: this data structure is contained in the
first page of a space. The space for this header is reserved in every extent
descriptor page, but used only in the first. */
/*-------------------------------------*/
#define FSP_SPACE_ID 0 /* space id */
#define FSP_NOT_USED 4 /* this field contained a value up to
which we know that the modifications
in the database have been flushed to
the file space; not used now */
#define FSP_SIZE 8 /* Current size of the space in
pages */
#define FSP_FREE_LIMIT 12 /* Minimum page number for which the
free list has not been initialized:
the pages >= this limit are, by
definition, free; note that in a
single-table tablespace where size
< 64 pages, this number is 64, i.e.,
we have initialized the space
about the first extent, but have not
physically allocted those pages to the
file */
#define FSP_SPACE_FLAGS 16 /* fsp_space_t.flags, similar to
dict_table_t::flags */
#define FSP_FRAG_N_USED 20 /* number of used pages in the
FSP_FREE_FRAG list */
#define FSP_FREE 24 /* list of free extents */
#define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE)
/* list of partially free extents not
belonging to any segment */
#define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE)
/* list of full extents not belonging
to any segment */
#define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE)
/* 8 bytes which give the first unused
segment id */
#define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE)
/* list of pages containing segment
headers, where all the segment inode
slots are reserved */
#define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE)
/* list of pages containing segment
headers, where not all the segment
header slots are reserved */
/*-------------------------------------*/
/* File space header size */
#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
#define FSP_FREE_ADD 4 /* this many free extents are added
to the free list from above
FSP_FREE_LIMIT at a time */
/* @} */
/* @} */
/**********************************************************************//**
Initializes the file space system. */
UNIV_INTERN
@ -352,6 +436,18 @@ fseg_print(
mtr_t* mtr); /*!< in: mtr */
#endif /* UNIV_BTR_PRINT */
/********************************************************************//**
Extract the page size from tablespace flags.
This feature, storing the page_ssize into the tablespace flags, is added
to InnoDB 5.6.4. This is here only to protect against a crash if a newer
database is opened with this code branch.
@return page size of the tablespace in bytes */
UNIV_INLINE
ulint
fsp_flags_get_page_size(
/*====================*/
ulint flags); /*!< in: tablespace flags */
#ifndef UNIV_NONINL
#include "fsp0fsp.ic"
#endif

34
storage/xtradb/include/fsp0fsp.ic

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@ -43,3 +43,31 @@ fsp_descr_page(
return(UNIV_UNLIKELY((page_no & (zip_size - 1)) == FSP_XDES_OFFSET));
}
/********************************************************************//**
Extract the page size from tablespace flags.
This feature, storing the page_ssize into the tablespace flags, is added
to InnoDB 5.6.4. This is here only to protect against a crash if a newer
database is opened with this code branch.
@return page size of the tablespace in bytes */
UNIV_INLINE
ulint
fsp_flags_get_page_size(
/*====================*/
ulint flags) /*!< in: tablespace flags */
{
ulint page_size = 0;
ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
/* Convert from a 'log2 minus 9' to a page size in bytes. */
if (UNIV_UNLIKELY(ssize)) {
page_size = (512 << ssize);
ut_ad(page_size <= UNIV_PAGE_SIZE);
} else {
/* If the page size was not stored, then it is the
original 16k. */
page_size = UNIV_PAGE_SIZE;
}
return(page_size);
}

23
storage/xtradb/include/ha0ha.h

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -31,13 +31,14 @@ Created 8/18/1994 Heikki Tuuri
#include "hash0hash.h"
#include "page0types.h"
#include "buf0types.h"
#include "rem0types.h"
/*************************************************************//**
Looks for an element in a hash table.
@return pointer to the data of the first hash table node in chain
having the fold number, NULL if not found */
UNIV_INLINE
void*
const rec_t*
ha_search_and_get_data(
/*===================*/
hash_table_t* table, /*!< in: hash table */
@ -51,11 +52,11 @@ ha_search_and_update_if_found_func(
/*===============================*/
hash_table_t* table, /*!< in/out: hash table */
ulint fold, /*!< in: folded value of the searched data */
void* data, /*!< in: pointer to the data */
const rec_t* data, /*!< in: pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* new_block,/*!< in: block containing new_data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
void* new_data);/*!< in: new pointer to the data */
const rec_t* new_data);/*!< in: new pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
/** Looks for an element when we know the pointer to the data and
@ -113,14 +114,6 @@ chosen to be a slightly bigger prime number.
# define ha_create(n_c,n_m,level) ha_create_func(n_c,n_m)
#endif /* UNIV_SYNC_DEBUG */
/*************************************************************//**
Empties a hash table and frees the memory heaps. */
UNIV_INTERN
void
ha_clear(
/*=====*/
hash_table_t* table); /*!< in, own: hash table */
/*************************************************************//**
Inserts an entry into a hash table. If an entry with the same fold number
is found, its node is updated to point to the new data, and no new node
@ -138,7 +131,7 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
void* data); /*!< in: data, must not be NULL */
const rec_t* data); /*!< in: data, must not be NULL */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
/**
@ -174,7 +167,7 @@ ha_search_and_delete_if_found(
/*==========================*/
hash_table_t* table, /*!< in: hash table */
ulint fold, /*!< in: folded value of the searched data */
void* data); /*!< in: pointer to the data */
const rec_t* data); /*!< in: pointer to the data */
#ifndef UNIV_HOTBACKUP
/*****************************************************************//**
Removes from the chain determined by fold all nodes whose data pointer
@ -217,7 +210,7 @@ struct ha_node_struct {
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block; /*!< buffer block containing the data, or NULL */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
void* data; /*!< pointer to the data */
const rec_t* data; /*!< pointer to the data */
ulint fold; /*!< fold value for the data */
};

54
storage/xtradb/include/ha0ha.ic

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -25,6 +25,7 @@ Created 8/18/1994 Heikki Tuuri
#include "ut0rnd.h"
#include "mem0mem.h"
#include "btr0types.h"
/***********************************************************//**
Deletes a hash node. */
@ -39,10 +40,10 @@ ha_delete_hash_node(
Gets a hash node data.
@return pointer to the data */
UNIV_INLINE
void*
const rec_t*
ha_node_get_data(
/*=============*/
ha_node_t* node) /*!< in: hash chain node */
const ha_node_t* node) /*!< in: hash chain node */
{
return(node->data);
}
@ -57,7 +58,7 @@ ha_node_set_data_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
void* data) /*!< in: pointer to the data */
const rec_t* data) /*!< in: pointer to the data */
{
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
node->block = block;
@ -105,41 +106,12 @@ ha_chain_get_first(
hash_get_nth_cell(table, hash_calc_hash(fold, table))->node);
}
/*************************************************************//**
Looks for an element in a hash table.
@return pointer to the first hash table node in chain having the fold
number, NULL if not found */
UNIV_INLINE
ha_node_t*
ha_search(
/*======*/
hash_table_t* table, /*!< in: hash table */
ulint fold) /*!< in: folded value of the searched data */
{
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
node = ha_chain_get_first(table, fold);
while (node) {
if (node->fold == fold) {
return(node);
}
node = ha_chain_get_next(node);
}
return(NULL);
}
/*************************************************************//**
Looks for an element in a hash table.
@return pointer to the data of the first hash table node in chain
having the fold number, NULL if not found */
UNIV_INLINE
void*
const rec_t*
ha_search_and_get_data(
/*===================*/
hash_table_t* table, /*!< in: hash table */
@ -148,6 +120,10 @@ ha_search_and_get_data(
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
#ifdef UNIV_SYNC_DEBUG
// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(btr_search_enabled);
node = ha_chain_get_first(table, fold);
@ -172,12 +148,14 @@ ha_search_with_data(
/*================*/
hash_table_t* table, /*!< in: hash table */
ulint fold, /*!< in: folded value of the searched data */
void* data) /*!< in: pointer to the data */
const rec_t* data) /*!< in: pointer to the data */
{
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
ut_ad(btr_search_enabled);
node = ha_chain_get_first(table, fold);
while (node) {
@ -202,11 +180,15 @@ ha_search_and_delete_if_found(
/*==========================*/
hash_table_t* table, /*!< in: hash table */
ulint fold, /*!< in: folded value of the searched data */
void* data) /*!< in: pointer to the data */
const rec_t* data) /*!< in: pointer to the data */
{
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
#ifdef UNIV_SYNC_DEBUG
// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(btr_search_enabled);
node = ha_search_with_data(table, fold, data);

4
storage/xtradb/include/page0page.h

@ -893,6 +893,7 @@ page_parse_create(
ulint comp, /*!< in: nonzero=compact page format */
buf_block_t* block, /*!< in: block or NULL */
mtr_t* mtr); /*!< in: mtr or NULL */
#ifndef UNIV_HOTBACKUP
/************************************************************//**
Prints record contents including the data relevant only in
the index page context. */
@ -902,6 +903,7 @@ page_rec_print(
/*===========*/
const rec_t* rec, /*!< in: physical record */
const ulint* offsets);/*!< in: record descriptor */
# ifdef UNIV_BTR_PRINT
/***************************************************************//**
This is used to print the contents of the directory for
debugging purposes. */
@ -941,6 +943,8 @@ page_print(
in directory */
ulint rn); /*!< in: print rn first and last records
in directory */
# endif /* UNIV_BTR_PRINT */
#endif /* !UNIV_HOTBACKUP */
/***************************************************************//**
The following is used to validate a record on a page. This function
differs from rec_validate as it can also check the n_owned field and

1
storage/xtradb/include/row0upd.ic

@ -28,7 +28,6 @@ Created 12/27/1996 Heikki Tuuri
# include "trx0trx.h"
# include "trx0undo.h"
# include "row0row.h"
# include "btr0sea.h"
#endif /* !UNIV_HOTBACKUP */
#include "page0zip.h"

3
storage/xtradb/include/srv0srv.h

@ -288,6 +288,9 @@ extern ibool srv_print_lock_waits;
extern ibool srv_print_buf_io;
extern ibool srv_print_log_io;
extern ibool srv_print_latch_waits;
extern ulint srv_flush_checkpoint_debug;
#else /* UNIV_DEBUG */
# define srv_print_thread_releases FALSE
# define srv_print_lock_waits FALSE

5
storage/xtradb/include/sync0rw.h

@ -543,7 +543,7 @@ mutex. */
UNIV_INTERN
void
rw_lock_debug_mutex_enter(void);
/*==========================*/
/*===========================*/
/******************************************************************//**
Releases the debug mutex. */
UNIV_INTERN
@ -634,7 +634,8 @@ struct rw_lock_struct {
};
#ifdef UNIV_SYNC_DEBUG
/** The structure for storing debug info of an rw-lock */
/** The structure for storing debug info of an rw-lock. All access to this
structure must be protected by rw_lock_debug_mutex_enter(). */
struct rw_lock_debug_struct {
os_thread_id_t thread_id; /*!< The thread id of the thread which

1
storage/xtradb/include/sync0rw.ic

@ -406,6 +406,7 @@ rw_lock_s_lock_func(
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
/* TODO: study performance of UNIV_LIKELY branch prediction hints. */

1
storage/xtradb/include/sync0sync.h

@ -674,7 +674,6 @@ or row lock! */
#define SYNC_LOG_FLUSH_ORDER 156
#define SYNC_RECV 168
#define SYNC_WORK_QUEUE 162
#define SYNC_SEARCH_SYS_CONF 161 /* for assigning btr_search_enabled */
#define SYNC_SEARCH_SYS 160 /* NOTE that if we have a memory
heap that can be extended to the
buffer pool, its logical level is

1
storage/xtradb/include/trx0trx.h

@ -494,6 +494,7 @@ struct trx_struct{
this is set to 1 then registered should
also be set to 1. This is used in the
XA code */
unsigned called_commit_ordered:1;/* 1 if innobase_commit_ordered has run. */
/*------------------------------*/
ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */
ulint check_foreigns; /* normally TRUE, but if the user

2
storage/xtradb/include/univ.i

@ -54,7 +54,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_BUGFIX 8
#ifndef PERCONA_INNODB_VERSION
#define PERCONA_INNODB_VERSION 20.1
#define PERCONA_INNODB_VERSION 24.1
#endif
/* The following is the InnoDB version as shown in

45
storage/xtradb/log/log0log.c

@ -1693,10 +1693,13 @@ log_preflush_pool_modified_pages(
recv_apply_hashed_log_recs(TRUE);
}
retry:
n_pages = buf_flush_list(ULINT_MAX, new_oldest);
if (sync) {
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
if (sync && n_pages != 0) {
//buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
os_thread_sleep(100000);
goto retry;
}
if (n_pages == ULINT_UNDEFINED) {
@ -2020,6 +2023,13 @@ log_checkpoint(
{
ib_uint64_t oldest_lsn;
#ifdef UNIV_DEBUG
if (srv_flush_checkpoint_debug == 1) {
return TRUE;
}
#endif
if (recv_recovery_is_on()) {
recv_apply_hashed_log_recs(TRUE);
}
@ -2124,7 +2134,11 @@ log_make_checkpoint_at(
physical write will always be made to
log files */
{
/* Preflush pages synchronously */
#ifdef UNIV_DEBUG
if (srv_flush_checkpoint_debug == 1)
return;
#endif
/* Preflush pages synchronously */
while (!log_preflush_pool_modified_pages(lsn, TRUE));
@ -2216,7 +2230,13 @@ log_checkpoint_margin(void)
ibool checkpoint_sync;
ibool do_checkpoint;
ibool success;
loop:
#ifdef UNIV_DEBUG
if (srv_flush_checkpoint_debug == 1)
return;
#endif
loop:
sync = FALSE;
checkpoint_sync = FALSE;
do_checkpoint = FALSE;
@ -2239,13 +2259,15 @@ loop:
/* A flush is urgent: we have to do a synchronous preflush */
sync = TRUE;
advance = 2 * (age - log->max_modified_age_sync);
advance = age - log->max_modified_age_sync;
} else if (age > log_max_modified_age_async()) {
/* A flush is not urgent: we do an asynchronous preflush */
advance = age - log_max_modified_age_async();
log->check_flush_or_checkpoint = FALSE;
} else {
advance = 0;
log->check_flush_or_checkpoint = FALSE;
}
checkpoint_age = log->lsn - log->last_checkpoint_lsn;
@ -2262,9 +2284,9 @@ loop:
do_checkpoint = TRUE;
log->check_flush_or_checkpoint = FALSE;
//log->check_flush_or_checkpoint = FALSE;
} else {
log->check_flush_or_checkpoint = FALSE;
//log->check_flush_or_checkpoint = FALSE;
}
mutex_exit(&(log->mutex));
@ -2272,6 +2294,7 @@ loop:
if (advance) {
ib_uint64_t new_oldest = oldest_lsn + advance;
retry:
success = log_preflush_pool_modified_pages(new_oldest, sync);
/* If the flush succeeded, this thread has done its part
@ -2286,7 +2309,7 @@ loop:
log->check_flush_or_checkpoint = TRUE;
mutex_exit(&(log->mutex));
goto loop;
goto retry;
}
}
@ -3164,7 +3187,11 @@ void
log_check_margins(void)
/*===================*/
{
loop:
#ifdef UNIV_DEBUG
if (srv_flush_checkpoint_debug == 1)
return;
#endif
loop:
log_flush_margin();
log_checkpoint_margin();

16
storage/xtradb/page/page0page.c

@ -215,12 +215,6 @@ page_set_max_trx_id(
{
page_t* page = buf_block_get_frame(block);
#ifndef UNIV_HOTBACKUP
const ibool is_hashed = block->is_hashed;
if (is_hashed) {
rw_lock_x_lock(btr_search_get_latch(block->index->id));
}
ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
#endif /* !UNIV_HOTBACKUP */
@ -241,12 +235,6 @@ page_set_max_trx_id(
} else {
mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id);
}
#ifndef UNIV_HOTBACKUP
if (is_hashed) {
rw_lock_x_unlock(btr_search_get_latch(block->index->id));
}
#endif /* !UNIV_HOTBACKUP */
}
/************************************************************//**
@ -1603,13 +1591,14 @@ page_rec_print(
" n_owned: %lu; heap_no: %lu; next rec: %lu\n",
(ulong) rec_get_n_owned_old(rec),
(ulong) rec_get_heap_no_old(rec),
(ulong) rec_get_next_offs(rec, TRUE));
(ulong) rec_get_next_offs(rec, FALSE));
}
page_rec_check(rec);
rec_validate(rec, offsets);
}
# ifdef UNIV_BTR_PRINT
/***************************************************************//**
This is used to print the contents of the directory for
debugging purposes. */
@ -1770,6 +1759,7 @@ page_print(
page_dir_print(page, dn);
page_print_list(block, index, rn);
}
# endif /* UNIV_BTR_PRINT */
#endif /* !UNIV_HOTBACKUP */
/***************************************************************//**

2
storage/xtradb/page/page0zip.c

@ -4456,7 +4456,7 @@ page_zip_reorganize(
#ifndef UNIV_HOTBACKUP
temp_block = buf_block_alloc(buf_pool);
btr_search_drop_page_hash_index(block, index);
btr_search_drop_page_hash_index(block);
block->check_index_page_at_flush = TRUE;
#else /* !UNIV_HOTBACKUP */
ut_ad(block == back_block1);

23
storage/xtradb/row/row0ins.c

@ -437,11 +437,9 @@ row_ins_cascade_calc_update_vec(
dict_table_t* table = foreign->foreign_table;
dict_index_t* index = foreign->foreign_index;
upd_t* update;
upd_field_t* ufield;
dict_table_t* parent_table;
dict_index_t* parent_index;
upd_t* parent_update;
upd_field_t* parent_ufield;
ulint n_fields_updated;
ulint parent_field_no;
ulint i;
@ -477,13 +475,15 @@ row_ins_cascade_calc_update_vec(
dict_index_get_nth_col_no(parent_index, i));
for (j = 0; j < parent_update->n_fields; j++) {
parent_ufield = parent_update->fields + j;
const upd_field_t* parent_ufield
= &parent_update->fields[j];
if (parent_ufield->field_no == parent_field_no) {
ulint min_size;
const dict_col_t* col;
ulint ufield_len;
upd_field_t* ufield;
col = dict_index_get_nth_col(index, i);
@ -985,10 +985,9 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
if ((node->is_delete
&& (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL))
|| (!node->is_delete
&& (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL))) {
if (node->is_delete
? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
: (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)) {
/* Build the appropriate update vector which sets
foreign->n_fields first fields in rec to SQL NULL */
@ -997,6 +996,8 @@ row_ins_foreign_check_on_constraint(
update->info_bits = 0;
update->n_fields = foreign->n_fields;
UNIV_MEM_INVALID(update->fields,
update->n_fields * sizeof *update->fields);
for (i = 0; i < foreign->n_fields; i++) {
upd_field_t* ufield = &update->fields[i];
@ -1665,7 +1666,7 @@ row_ins_scan_sec_index_for_duplicate(
ulint n_fields_cmp;
btr_pcur_t pcur;
ulint err = DB_SUCCESS;
unsigned allow_duplicates;
ulint allow_duplicates;
mtr_t mtr;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
@ -1696,7 +1697,7 @@ row_ins_scan_sec_index_for_duplicate(
btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr);
allow_duplicates = thr_get_trx(thr)->duplicates & TRX_DUP_IGNORE;
allow_duplicates = thr_get_trx(thr)->duplicates;
/* Scan index records and check if there is a duplicate */
@ -1830,7 +1831,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
if (trx->duplicates & TRX_DUP_IGNORE) {
if (trx->duplicates) {
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@ -1874,7 +1875,7 @@ row_ins_duplicate_error_in_clust(
offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
if (trx->duplicates & TRX_DUP_IGNORE) {
if (trx->duplicates) {
/* If the SQL-query will update or replace
duplicate key we will take X-lock for

13
storage/xtradb/row/row0mysql.c

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2000, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -291,21 +291,21 @@ row_mysql_pad_col(
/* space=0x0020 */
pad_end = pad + len;
ut_a(!(len % 2));
do {
while (pad < pad_end) {
*pad++ = 0x00;
*pad++ = 0x20;
} while (pad < pad_end);
};
break;
case 4:
/* space=0x00000020 */
pad_end = pad + len;
ut_a(!(len % 4));
do {
while (pad < pad_end) {
*pad++ = 0x00;
*pad++ = 0x00;
*pad++ = 0x00;
*pad++ = 0x20;
} while (pad < pad_end);
}
break;
}
}
@ -2736,7 +2736,7 @@ row_import_tablespace_for_mysql(
success = fil_open_single_table_tablespace(
TRUE, table->space,
table->flags == DICT_TF_COMPACT ? 0 : table->flags,
table->name);
table->name, trx);
if (success) {
table->ibd_file_missing = FALSE;
table->tablespace_discarded = FALSE;
@ -4119,6 +4119,7 @@ end:
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, NULL);
trx->error_state = DB_SUCCESS;
err = DB_ERROR;
goto funct_exit;
}

29
storage/xtradb/srv/srv0srv.c

@ -446,7 +446,7 @@ UNIV_INTERN ulong srv_ibuf_accel_rate = 100;
#define PCT_IBUF_IO(pct) ((ulint) (srv_io_capacity * srv_ibuf_accel_rate * ((double) pct / 10000.0)))
UNIV_INTERN ulint srv_checkpoint_age_target = 0;
UNIV_INTERN ulint srv_flush_neighbor_pages = 1; /* 0:disable 1:enable */
UNIV_INTERN ulint srv_flush_neighbor_pages = 1; /* 0:disable 1:area 2:contiguous */
UNIV_INTERN ulint srv_deprecated_enable_unsafe_group_commit = 0;
UNIV_INTERN ulong srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
@ -471,6 +471,9 @@ UNIV_INTERN ibool srv_print_lock_waits = FALSE;
UNIV_INTERN ibool srv_print_buf_io = FALSE;
UNIV_INTERN ibool srv_print_log_io = FALSE;
UNIV_INTERN ibool srv_print_latch_waits = FALSE;
UNIV_INTERN ulong srv_flush_checkpoint_debug = 0;
#endif /* UNIV_DEBUG */
UNIV_INTERN ulint srv_n_rows_inserted = 0;
@ -1253,7 +1256,7 @@ retry:
static void
srv_conc_exit_innodb_timer_based(trx_t* trx)
{
(void) os_atomic_increment_lint(&srv_conc_n_threads, -1);
(void) os_atomic_increment_lint(&srv_conc_n_threads, -1);
trx->declared_to_be_inside_innodb = FALSE;
trx->n_tickets_to_enter_innodb = 0;
return;
@ -1475,7 +1478,7 @@ srv_conc_force_enter_innodb(
ut_ad(srv_conc_n_threads >= 0);
#ifdef HAVE_ATOMIC_BUILTINS
if (srv_thread_concurrency_timer_based) {
(void) os_atomic_increment_lint(&srv_conc_n_threads, 1);
(void) os_atomic_increment_lint(&srv_conc_n_threads, 1);
trx->declared_to_be_inside_innodb = TRUE;
trx->n_tickets_to_enter_innodb = 1;
return;
@ -3625,11 +3628,18 @@ retry_flush_batch:
PCT_IO(10), IB_ULONGLONG_MAX);
}
srv_main_thread_op_info = "making checkpoint";
#ifdef UNIV_DEBUG
if (srv_flush_checkpoint_debug != 1) {
#endif
/* Make a new checkpoint about once in 10 seconds */
srv_main_thread_op_info = "making checkpoint";
log_checkpoint(TRUE, FALSE, TRUE);
/* Make a new checkpoint about once in 10 seconds */
log_checkpoint(TRUE, FALSE, TRUE);
#ifdef UNIV_DEBUG
}
#endif
srv_main_thread_op_info = "reserving kernel mutex";
@ -3708,6 +3718,10 @@ background_loop:
}
mutex_exit(&kernel_mutex);
#ifdef UNIV_DEBUG
if (srv_flush_checkpoint_debug == 1)
goto skip_flush;
#endif
flush_loop:
srv_main_thread_op_info = "flushing buffer pool pages";
srv_main_flush_loops++;
@ -3748,6 +3762,9 @@ flush_loop:
goto flush_loop;
}
#ifdef UNIV_DEBUG
skip_flush:
#endif
srv_main_thread_op_info = "reserving kernel mutex";
mutex_enter(&kernel_mutex);

28
storage/xtradb/srv/srv0start.c

@ -735,6 +735,7 @@ open_or_create_data_files(
ibool one_created = FALSE;
ulint size;
ulint size_high;
ulint flags;
ulint rounded_size_pages;
char name[10000];
@ -917,12 +918,31 @@ open_or_create_data_files(
return(DB_ERROR);
}
skip_size_check:
fil_read_flushed_lsn_and_arch_log_no(
files[i], one_opened,
fil_read_first_page(
files[i], one_opened, &flags,
#ifdef UNIV_LOG_ARCHIVE
min_arch_log_no, max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */
min_flushed_lsn, max_flushed_lsn);
if (UNIV_PAGE_SIZE
!= fsp_flags_get_page_size(flags)) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Error: data file %s"
" uses page size %lu,\n",
name,
fsp_flags_get_page_size(flags));
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: but the only supported"
" page size in this release is=%lu\n",
(ulong) UNIV_PAGE_SIZE);
return(DB_ERROR);
}
one_opened = TRUE;
} else {
/* We created the data file and now write it full of
@ -1060,8 +1080,8 @@ skip_size_check:
(ulong) TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9);
}
fil_read_flushed_lsn_and_arch_log_no(
files[i], one_opened,
fil_read_first_page(
files[i], one_opened, &flags,
#ifdef UNIV_LOG_ARCHIVE
min_arch_log_no, max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */

9
storage/xtradb/sync/sync0rw.c

@ -623,6 +623,9 @@ rw_lock_x_lock_func(
ibool spinning = FALSE;
ut_ad(rw_lock_validate(lock));
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */
i = 0;
@ -710,7 +713,7 @@ mutex. */
UNIV_INTERN
void
rw_lock_debug_mutex_enter(void)
/*==========================*/
/*===========================*/
{
loop:
if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
@ -937,11 +940,13 @@ rw_lock_list_print_info(
putc('\n', file);
}
rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(file, info);
info = UT_LIST_GET_NEXT(list, info);
}
rw_lock_debug_mutex_exit();
}
#ifndef INNODB_RW_LOCKS_USE_ATOMICS
mutex_exit(&(lock->mutex));
@ -985,11 +990,13 @@ rw_lock_print(
putc('\n', stderr);
}
rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(stderr, info);
info = UT_LIST_GET_NEXT(list, info);
}
rw_lock_debug_mutex_exit();
}
}

1
storage/xtradb/sync/sync0sync.c

@ -1222,7 +1222,6 @@ sync_thread_add_level(
case SYNC_OUTER_ANY_LATCH:
case SYNC_FILE_FORMAT_TAG:
case SYNC_DOUBLEWRITE:
case SYNC_SEARCH_SYS_CONF:
case SYNC_TRX_LOCK_HEAP:
case SYNC_KERNEL:
case SYNC_IBUF_BITMAP_MUTEX:

Loading…
Cancel
Save