Merge mysql-5.1-innodb -> mysql-5.1
This commit is contained in:
commit
0bbaf6e8a7
8
mysql-test/suite/innodb/r/innodb_bug60049.result
Normal file
8
mysql-test/suite/innodb/r/innodb_bug60049.result
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
CREATE TABLE t(a INT)ENGINE=InnoDB;
|
||||||
|
RENAME TABLE t TO u;
|
||||||
|
DROP TABLE u;
|
||||||
|
SELECT @@innodb_fast_shutdown;
|
||||||
|
@@innodb_fast_shutdown
|
||||||
|
0
|
||||||
|
Last record of ID_IND root page (9):
|
||||||
|
1808000018050074000000000000000c5359535f464f524549474e5f434f4c53
|
1
mysql-test/suite/innodb/t/innodb_bug60049-master.opt
Normal file
1
mysql-test/suite/innodb/t/innodb_bug60049-master.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--innodb_fast_shutdown=0
|
39
mysql-test/suite/innodb/t/innodb_bug60049.test
Normal file
39
mysql-test/suite/innodb/t/innodb_bug60049.test
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# Bug #60049 Verify that purge leaves no garbage in unique secondary indexes
|
||||||
|
# This test requires a fresh server start-up and a slow shutdown.
|
||||||
|
# This was a suspected bug (not a bug).
|
||||||
|
|
||||||
|
-- source include/not_embedded.inc
|
||||||
|
-- source include/have_innodb.inc
|
||||||
|
|
||||||
|
CREATE TABLE t(a INT)ENGINE=InnoDB;
|
||||||
|
RENAME TABLE t TO u;
|
||||||
|
DROP TABLE u;
|
||||||
|
SELECT @@innodb_fast_shutdown;
|
||||||
|
let $MYSQLD_DATADIR=`select @@datadir`;
|
||||||
|
|
||||||
|
# Shut down the server
|
||||||
|
-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
|
-- shutdown_server 10
|
||||||
|
-- source include/wait_until_disconnected.inc
|
||||||
|
|
||||||
|
# Check the tail of ID_IND (SYS_TABLES.ID)
|
||||||
|
let IBDATA1=$MYSQLD_DATADIR/ibdata1;
|
||||||
|
perl;
|
||||||
|
my $file = $ENV{'IBDATA1'};
|
||||||
|
open(FILE, "<$file") || die "Unable to open $file";
|
||||||
|
# Read DICT_HDR_TABLE_IDS, the root page number of ID_IND (SYS_TABLES.ID).
|
||||||
|
seek(FILE, 7*16384+38+36, 0) || die "Unable to seek $file";
|
||||||
|
die unless read(FILE, $_, 4) == 4;
|
||||||
|
my $sys_tables_id_root = unpack("N", $_);
|
||||||
|
print "Last record of ID_IND root page ($sys_tables_id_root):\n";
|
||||||
|
# This should be the last record in ID_IND. Dump it in hexadecimal.
|
||||||
|
seek(FILE, $sys_tables_id_root*16384 + 152, 0) || die "Unable to seek $file";
|
||||||
|
read(FILE, $_, 32) || die "Unable to read $file";
|
||||||
|
close(FILE);
|
||||||
|
print unpack("H*", $_), "\n";
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Restart the server.
|
||||||
|
-- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
|
-- enable_reconnect
|
||||||
|
-- source include/wait_until_connected_again.inc
|
28
mysql-test/suite/innodb_plugin/r/innodb_bug59307.result
Normal file
28
mysql-test/suite/innodb_plugin/r/innodb_bug59307.result
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
CREATE TABLE t1 (
|
||||||
|
t1_int INT,
|
||||||
|
t1_time TIME
|
||||||
|
) ENGINE=innodb;
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
t2_int int PRIMARY KEY,
|
||||||
|
t2_int2 INT
|
||||||
|
) ENGINE=INNODB;
|
||||||
|
INSERT INTO t2 VALUES ();
|
||||||
|
Warnings:
|
||||||
|
Warning 1364 Field 't2_int' doesn't have a default value
|
||||||
|
INSERT INTO t1 VALUES ();
|
||||||
|
SELECT *
|
||||||
|
FROM t1 AS t1a
|
||||||
|
WHERE NOT EXISTS
|
||||||
|
(SELECT *
|
||||||
|
FROM t1 AS t1b
|
||||||
|
WHERE t1b.t1_int NOT IN
|
||||||
|
(SELECT t2.t2_int
|
||||||
|
FROM t2
|
||||||
|
WHERE t1b.t1_time LIKE t1b.t1_int
|
||||||
|
OR t1b.t1_time <> t2.t2_int2
|
||||||
|
AND 6=7
|
||||||
|
)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
t1_int t1_time
|
||||||
|
DROP TABLE t1,t2;
|
8
mysql-test/suite/innodb_plugin/r/innodb_bug60049.result
Normal file
8
mysql-test/suite/innodb_plugin/r/innodb_bug60049.result
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
CREATE TABLE t(a INT)ENGINE=InnoDB;
|
||||||
|
RENAME TABLE t TO u;
|
||||||
|
DROP TABLE u;
|
||||||
|
SELECT @@innodb_fast_shutdown;
|
||||||
|
@@innodb_fast_shutdown
|
||||||
|
0
|
||||||
|
Last record of ID_IND root page (9):
|
||||||
|
1808000018050074000000000000000c5359535f464f524549474e5f434f4c53
|
32
mysql-test/suite/innodb_plugin/t/innodb_bug59307.test
Normal file
32
mysql-test/suite/innodb_plugin/t/innodb_bug59307.test
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
-- source include/have_innodb_plugin.inc
|
||||||
|
# Bug #59307 uninitialized value in rw_lock_set_writer_id_and_recursion_flag()
|
||||||
|
# when Valgrind instrumentation (UNIV_DEBUG_VALGRIND) is not enabled
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
t1_int INT,
|
||||||
|
t1_time TIME
|
||||||
|
) ENGINE=innodb;
|
||||||
|
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
t2_int int PRIMARY KEY,
|
||||||
|
t2_int2 INT
|
||||||
|
) ENGINE=INNODB;
|
||||||
|
|
||||||
|
INSERT INTO t2 VALUES ();
|
||||||
|
INSERT INTO t1 VALUES ();
|
||||||
|
|
||||||
|
SELECT *
|
||||||
|
FROM t1 AS t1a
|
||||||
|
WHERE NOT EXISTS
|
||||||
|
(SELECT *
|
||||||
|
FROM t1 AS t1b
|
||||||
|
WHERE t1b.t1_int NOT IN
|
||||||
|
(SELECT t2.t2_int
|
||||||
|
FROM t2
|
||||||
|
WHERE t1b.t1_time LIKE t1b.t1_int
|
||||||
|
OR t1b.t1_time <> t2.t2_int2
|
||||||
|
AND 6=7
|
||||||
|
)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
DROP TABLE t1,t2;
|
@ -0,0 +1 @@
|
|||||||
|
--innodb_fast_shutdown=0
|
39
mysql-test/suite/innodb_plugin/t/innodb_bug60049.test
Normal file
39
mysql-test/suite/innodb_plugin/t/innodb_bug60049.test
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# Bug #60049 Verify that purge leaves no garbage in unique secondary indexes
|
||||||
|
# This test requires a fresh server start-up and a slow shutdown.
|
||||||
|
# This was a suspected bug (not a bug).
|
||||||
|
|
||||||
|
-- source include/not_embedded.inc
|
||||||
|
-- source include/have_innodb_plugin.inc
|
||||||
|
|
||||||
|
CREATE TABLE t(a INT)ENGINE=InnoDB;
|
||||||
|
RENAME TABLE t TO u;
|
||||||
|
DROP TABLE u;
|
||||||
|
SELECT @@innodb_fast_shutdown;
|
||||||
|
let $MYSQLD_DATADIR=`select @@datadir`;
|
||||||
|
|
||||||
|
# Shut down the server
|
||||||
|
-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
|
-- shutdown_server 10
|
||||||
|
-- source include/wait_until_disconnected.inc
|
||||||
|
|
||||||
|
# Check the tail of ID_IND (SYS_TABLES.ID)
|
||||||
|
let IBDATA1=$MYSQLD_DATADIR/ibdata1;
|
||||||
|
perl;
|
||||||
|
my $file = $ENV{'IBDATA1'};
|
||||||
|
open(FILE, "<$file") || die "Unable to open $file";
|
||||||
|
# Read DICT_HDR_TABLE_IDS, the root page number of ID_IND (SYS_TABLES.ID).
|
||||||
|
seek(FILE, 7*16384+38+36, 0) || die "Unable to seek $file";
|
||||||
|
die unless read(FILE, $_, 4) == 4;
|
||||||
|
my $sys_tables_id_root = unpack("N", $_);
|
||||||
|
print "Last record of ID_IND root page ($sys_tables_id_root):\n";
|
||||||
|
# This should be the last record in ID_IND. Dump it in hexadecimal.
|
||||||
|
seek(FILE, $sys_tables_id_root*16384 + 152, 0) || die "Unable to seek $file";
|
||||||
|
read(FILE, $_, 32) || die "Unable to read $file";
|
||||||
|
close(FILE);
|
||||||
|
print unpack("H*", $_), "\n";
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Restart the server.
|
||||||
|
-- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
|
-- enable_reconnect
|
||||||
|
-- source include/wait_until_connected_again.inc
|
@ -1,3 +1,15 @@
|
|||||||
|
2011-02-15 The InnoDB Team
|
||||||
|
|
||||||
|
* sync/sync0rw.c, innodb_bug59307.test:
|
||||||
|
Bug#59307 Valgrind: uninitialized value in
|
||||||
|
rw_lock_set_writer_id_and_recursion_flag()
|
||||||
|
|
||||||
|
2011-02-14 The InnoDB Team
|
||||||
|
|
||||||
|
* handler/handler0alter.cc:
|
||||||
|
Bug#59749 Enabling concurrent reads while creating non-primary
|
||||||
|
unique index gives failures
|
||||||
|
|
||||||
2011-01-31 The InnoDB Team
|
2011-01-31 The InnoDB Team
|
||||||
|
|
||||||
* btr/btr0cur.c, include/row0upd.h,
|
* btr/btr0cur.c, include/row0upd.h,
|
||||||
|
@ -42,6 +42,560 @@ Created 6/2/1994 Heikki Tuuri
|
|||||||
#include "ibuf0ibuf.h"
|
#include "ibuf0ibuf.h"
|
||||||
#include "trx0trx.h"
|
#include "trx0trx.h"
|
||||||
|
|
||||||
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
|
# include "srv0srv.h"
|
||||||
|
# include "ut0rbt.h"
|
||||||
|
|
||||||
|
/** TRUE when messages about index->blobs modification are enabled. */
|
||||||
|
static ibool btr_blob_dbg_msg;
|
||||||
|
|
||||||
|
/** Issue a message about an operation on index->blobs.
|
||||||
|
@param op operation
|
||||||
|
@param b the entry being subjected to the operation
|
||||||
|
@param ctx the context of the operation */
|
||||||
|
#define btr_blob_dbg_msg_issue(op, b, ctx) \
|
||||||
|
fprintf(stderr, op " %u:%u:%u->%u %s(%u,%u,%u)\n", \
|
||||||
|
(b)->ref_page_no, (b)->ref_heap_no, \
|
||||||
|
(b)->ref_field_no, (b)->blob_page_no, ctx, \
|
||||||
|
(b)->owner, (b)->always_owner, (b)->del)
|
||||||
|
|
||||||
|
/** Insert to index->blobs a reference to an off-page column.
|
||||||
|
@param index the index tree
|
||||||
|
@param b the reference
|
||||||
|
@param ctx context (for logging) */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_rbt_insert(
|
||||||
|
/*====================*/
|
||||||
|
dict_index_t* index, /*!< in/out: index tree */
|
||||||
|
const btr_blob_dbg_t* b, /*!< in: the reference */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
{
|
||||||
|
if (btr_blob_dbg_msg) {
|
||||||
|
btr_blob_dbg_msg_issue("insert", b, ctx);
|
||||||
|
}
|
||||||
|
mutex_enter(&index->blobs_mutex);
|
||||||
|
rbt_insert(index->blobs, b, b);
|
||||||
|
mutex_exit(&index->blobs_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove from index->blobs a reference to an off-page column.
|
||||||
|
@param index the index tree
|
||||||
|
@param b the reference
|
||||||
|
@param ctx context (for logging) */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_rbt_delete(
|
||||||
|
/*====================*/
|
||||||
|
dict_index_t* index, /*!< in/out: index tree */
|
||||||
|
const btr_blob_dbg_t* b, /*!< in: the reference */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
{
|
||||||
|
if (btr_blob_dbg_msg) {
|
||||||
|
btr_blob_dbg_msg_issue("delete", b, ctx);
|
||||||
|
}
|
||||||
|
mutex_enter(&index->blobs_mutex);
|
||||||
|
ut_a(rbt_delete(index->blobs, b));
|
||||||
|
mutex_exit(&index->blobs_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Comparator for items (btr_blob_dbg_t) in index->blobs.
|
||||||
|
The key in index->blobs is (ref_page_no, ref_heap_no, ref_field_no).
|
||||||
|
@return negative, 0 or positive if *a<*b, *a=*b, *a>*b */
|
||||||
|
static
|
||||||
|
int
|
||||||
|
btr_blob_dbg_cmp(
|
||||||
|
/*=============*/
|
||||||
|
const void* a, /*!< in: first btr_blob_dbg_t to compare */
|
||||||
|
const void* b) /*!< in: second btr_blob_dbg_t to compare */
|
||||||
|
{
|
||||||
|
const btr_blob_dbg_t* aa = a;
|
||||||
|
const btr_blob_dbg_t* bb = b;
|
||||||
|
|
||||||
|
ut_ad(aa != NULL);
|
||||||
|
ut_ad(bb != NULL);
|
||||||
|
|
||||||
|
if (aa->ref_page_no != bb->ref_page_no) {
|
||||||
|
return(aa->ref_page_no < bb->ref_page_no ? -1 : 1);
|
||||||
|
}
|
||||||
|
if (aa->ref_heap_no != bb->ref_heap_no) {
|
||||||
|
return(aa->ref_heap_no < bb->ref_heap_no ? -1 : 1);
|
||||||
|
}
|
||||||
|
if (aa->ref_field_no != bb->ref_field_no) {
|
||||||
|
return(aa->ref_field_no < bb->ref_field_no ? -1 : 1);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Add a reference to an off-page column to the index->blobs map. */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_add_blob(
|
||||||
|
/*==================*/
|
||||||
|
const rec_t* rec, /*!< in: clustered index record */
|
||||||
|
ulint field_no, /*!< in: off-page column number */
|
||||||
|
ulint page_no, /*!< in: start page of the column */
|
||||||
|
dict_index_t* index, /*!< in/out: index tree */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
{
|
||||||
|
btr_blob_dbg_t b;
|
||||||
|
const page_t* page = page_align(rec);
|
||||||
|
|
||||||
|
ut_a(index->blobs);
|
||||||
|
|
||||||
|
b.blob_page_no = page_no;
|
||||||
|
b.ref_page_no = page_get_page_no(page);
|
||||||
|
b.ref_heap_no = page_rec_get_heap_no(rec);
|
||||||
|
b.ref_field_no = field_no;
|
||||||
|
ut_a(b.ref_field_no >= index->n_uniq);
|
||||||
|
b.always_owner = b.owner = TRUE;
|
||||||
|
b.del = FALSE;
|
||||||
|
ut_a(!rec_get_deleted_flag(rec, page_is_comp(page)));
|
||||||
|
btr_blob_dbg_rbt_insert(index, &b, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Add to index->blobs any references to off-page columns from a record.
|
||||||
|
@return number of references added */
|
||||||
|
UNIV_INTERN
|
||||||
|
ulint
|
||||||
|
btr_blob_dbg_add_rec(
|
||||||
|
/*=================*/
|
||||||
|
const rec_t* rec, /*!< in: record */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const ulint* offsets,/*!< in: offsets */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
{
|
||||||
|
ulint count = 0;
|
||||||
|
ulint i;
|
||||||
|
btr_blob_dbg_t b;
|
||||||
|
ibool del;
|
||||||
|
|
||||||
|
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||||
|
|
||||||
|
if (!rec_offs_any_extern(offsets)) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ref_page_no = page_get_page_no(page_align(rec));
|
||||||
|
b.ref_heap_no = page_rec_get_heap_no(rec);
|
||||||
|
del = (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) != 0);
|
||||||
|
|
||||||
|
for (i = 0; i < rec_offs_n_fields(offsets); i++) {
|
||||||
|
if (rec_offs_nth_extern(offsets, i)) {
|
||||||
|
ulint len;
|
||||||
|
const byte* field_ref = rec_get_nth_field(
|
||||||
|
rec, offsets, i, &len);
|
||||||
|
|
||||||
|
ut_a(len != UNIV_SQL_NULL);
|
||||||
|
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||||
|
field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
|
||||||
|
|
||||||
|
if (!memcmp(field_ref, field_ref_zero,
|
||||||
|
BTR_EXTERN_FIELD_REF_SIZE)) {
|
||||||
|
/* the column has not been stored yet */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ref_field_no = i;
|
||||||
|
b.blob_page_no = mach_read_from_4(
|
||||||
|
field_ref + BTR_EXTERN_PAGE_NO);
|
||||||
|
ut_a(b.ref_field_no >= index->n_uniq);
|
||||||
|
b.always_owner = b.owner
|
||||||
|
= !(field_ref[BTR_EXTERN_LEN]
|
||||||
|
& BTR_EXTERN_OWNER_FLAG);
|
||||||
|
b.del = del;
|
||||||
|
|
||||||
|
btr_blob_dbg_rbt_insert(index, &b, ctx);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Display the references to off-page columns.
|
||||||
|
This function is to be called from a debugger,
|
||||||
|
for example when a breakpoint on ut_dbg_assertion_failed is hit. */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_print(
|
||||||
|
/*===============*/
|
||||||
|
const dict_index_t* index) /*!< in: index tree */
|
||||||
|
{
|
||||||
|
const ib_rbt_node_t* node;
|
||||||
|
|
||||||
|
if (!index->blobs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We intentionally do not acquire index->blobs_mutex here.
|
||||||
|
This function is to be called from a debugger, and the caller
|
||||||
|
should make sure that the index->blobs_mutex is held. */
|
||||||
|
|
||||||
|
for (node = rbt_first(index->blobs);
|
||||||
|
node != NULL; node = rbt_next(index->blobs, node)) {
|
||||||
|
const btr_blob_dbg_t* b
|
||||||
|
= rbt_value(btr_blob_dbg_t, node);
|
||||||
|
fprintf(stderr, "%u:%u:%u->%u%s%s%s\n",
|
||||||
|
b->ref_page_no, b->ref_heap_no, b->ref_field_no,
|
||||||
|
b->blob_page_no,
|
||||||
|
b->owner ? "" : "(disowned)",
|
||||||
|
b->always_owner ? "" : "(has disowned)",
|
||||||
|
b->del ? "(deleted)" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Remove from index->blobs any references to off-page columns from a record.
|
||||||
|
@return number of references removed */
|
||||||
|
UNIV_INTERN
|
||||||
|
ulint
|
||||||
|
btr_blob_dbg_remove_rec(
|
||||||
|
/*====================*/
|
||||||
|
const rec_t* rec, /*!< in: record */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const ulint* offsets,/*!< in: offsets */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
{
|
||||||
|
ulint i;
|
||||||
|
ulint count = 0;
|
||||||
|
btr_blob_dbg_t b;
|
||||||
|
|
||||||
|
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||||
|
|
||||||
|
if (!rec_offs_any_extern(offsets)) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ref_page_no = page_get_page_no(page_align(rec));
|
||||||
|
b.ref_heap_no = page_rec_get_heap_no(rec);
|
||||||
|
|
||||||
|
for (i = 0; i < rec_offs_n_fields(offsets); i++) {
|
||||||
|
if (rec_offs_nth_extern(offsets, i)) {
|
||||||
|
ulint len;
|
||||||
|
const byte* field_ref = rec_get_nth_field(
|
||||||
|
rec, offsets, i, &len);
|
||||||
|
|
||||||
|
ut_a(len != UNIV_SQL_NULL);
|
||||||
|
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||||
|
field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
|
||||||
|
|
||||||
|
b.ref_field_no = i;
|
||||||
|
b.blob_page_no = mach_read_from_4(
|
||||||
|
field_ref + BTR_EXTERN_PAGE_NO);
|
||||||
|
|
||||||
|
switch (b.blob_page_no) {
|
||||||
|
case 0:
|
||||||
|
/* The column has not been stored yet.
|
||||||
|
The BLOB pointer must be all zero.
|
||||||
|
There cannot be a BLOB starting at
|
||||||
|
page 0, because page 0 is reserved for
|
||||||
|
the tablespace header. */
|
||||||
|
ut_a(!memcmp(field_ref, field_ref_zero,
|
||||||
|
BTR_EXTERN_FIELD_REF_SIZE));
|
||||||
|
/* fall through */
|
||||||
|
case FIL_NULL:
|
||||||
|
/* the column has been freed already */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
btr_blob_dbg_rbt_delete(index, &b, ctx);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Check that there are no references to off-page columns from or to
|
||||||
|
the given page. Invoked when freeing or clearing a page.
|
||||||
|
@return TRUE when no orphan references exist */
|
||||||
|
UNIV_INTERN
|
||||||
|
ibool
|
||||||
|
btr_blob_dbg_is_empty(
|
||||||
|
/*==================*/
|
||||||
|
dict_index_t* index, /*!< in: index */
|
||||||
|
ulint page_no) /*!< in: page number */
|
||||||
|
{
|
||||||
|
const ib_rbt_node_t* node;
|
||||||
|
ibool success = TRUE;
|
||||||
|
|
||||||
|
if (!index->blobs) {
|
||||||
|
return(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_enter(&index->blobs_mutex);
|
||||||
|
|
||||||
|
for (node = rbt_first(index->blobs);
|
||||||
|
node != NULL; node = rbt_next(index->blobs, node)) {
|
||||||
|
const btr_blob_dbg_t* b
|
||||||
|
= rbt_value(btr_blob_dbg_t, node);
|
||||||
|
|
||||||
|
if (b->ref_page_no != page_no && b->blob_page_no != page_no) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: orphan BLOB ref%s%s%s %u:%u:%u->%u\n",
|
||||||
|
b->owner ? "" : "(disowned)",
|
||||||
|
b->always_owner ? "" : "(has disowned)",
|
||||||
|
b->del ? "(deleted)" : "",
|
||||||
|
b->ref_page_no, b->ref_heap_no, b->ref_field_no,
|
||||||
|
b->blob_page_no);
|
||||||
|
|
||||||
|
if (b->blob_page_no != page_no || b->owner || !b->del) {
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_exit(&index->blobs_mutex);
|
||||||
|
return(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Count and process all references to off-page columns on a page.
|
||||||
|
@return number of references processed */
|
||||||
|
UNIV_INTERN
|
||||||
|
ulint
|
||||||
|
btr_blob_dbg_op(
|
||||||
|
/*============*/
|
||||||
|
const page_t* page, /*!< in: B-tree leaf page */
|
||||||
|
const rec_t* rec, /*!< in: record to start from
|
||||||
|
(NULL to process the whole page) */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const char* ctx, /*!< in: context (for logging) */
|
||||||
|
const btr_blob_dbg_op_f op) /*!< in: operation on records */
|
||||||
|
{
|
||||||
|
ulint count = 0;
|
||||||
|
mem_heap_t* heap = NULL;
|
||||||
|
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||||
|
ulint* offsets = offsets_;
|
||||||
|
rec_offs_init(offsets_);
|
||||||
|
|
||||||
|
ut_a(fil_page_get_type(page) == FIL_PAGE_INDEX);
|
||||||
|
ut_a(!rec || page_align(rec) == page);
|
||||||
|
|
||||||
|
if (!index->blobs || !page_is_leaf(page)
|
||||||
|
|| !dict_index_is_clust(index)) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec == NULL) {
|
||||||
|
rec = page_get_infimum_rec(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
offsets = rec_get_offsets(rec, index, offsets,
|
||||||
|
ULINT_UNDEFINED, &heap);
|
||||||
|
count += op(rec, index, offsets, ctx);
|
||||||
|
rec = page_rec_get_next_const(rec);
|
||||||
|
} while (!page_rec_is_supremum(rec));
|
||||||
|
|
||||||
|
if (UNIV_LIKELY_NULL(heap)) {
|
||||||
|
mem_heap_free(heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Count and add to index->blobs any references to off-page columns
|
||||||
|
from records on a page.
|
||||||
|
@return number of references added */
|
||||||
|
UNIV_INTERN
|
||||||
|
ulint
|
||||||
|
btr_blob_dbg_add(
|
||||||
|
/*=============*/
|
||||||
|
const page_t* page, /*!< in: rewritten page */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
{
|
||||||
|
btr_blob_dbg_assert_empty(index, page_get_page_no(page));
|
||||||
|
|
||||||
|
return(btr_blob_dbg_op(page, NULL, index, ctx, btr_blob_dbg_add_rec));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Count and remove from index->blobs any references to off-page columns
|
||||||
|
from records on a page.
|
||||||
|
Used when reorganizing a page, before copying the records.
|
||||||
|
@return number of references removed */
|
||||||
|
UNIV_INTERN
|
||||||
|
ulint
|
||||||
|
btr_blob_dbg_remove(
|
||||||
|
/*================*/
|
||||||
|
const page_t* page, /*!< in: b-tree page */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
{
|
||||||
|
ulint count;
|
||||||
|
|
||||||
|
count = btr_blob_dbg_op(page, NULL, index, ctx,
|
||||||
|
btr_blob_dbg_remove_rec);
|
||||||
|
|
||||||
|
/* Check that no references exist. */
|
||||||
|
btr_blob_dbg_assert_empty(index, page_get_page_no(page));
|
||||||
|
|
||||||
|
return(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Restore in index->blobs any references to off-page columns
|
||||||
|
Used when page reorganize fails due to compressed page overflow. */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_restore(
|
||||||
|
/*=================*/
|
||||||
|
const page_t* npage, /*!< in: page that failed to compress */
|
||||||
|
const page_t* page, /*!< in: copy of original page */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
{
|
||||||
|
ulint removed;
|
||||||
|
ulint added;
|
||||||
|
|
||||||
|
ut_a(page_get_page_no(npage) == page_get_page_no(page));
|
||||||
|
ut_a(page_get_space_id(npage) == page_get_space_id(page));
|
||||||
|
|
||||||
|
removed = btr_blob_dbg_remove(npage, index, ctx);
|
||||||
|
added = btr_blob_dbg_add(page, index, ctx);
|
||||||
|
ut_a(added == removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Modify the 'deleted' flag of a record. */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_set_deleted_flag(
|
||||||
|
/*==========================*/
|
||||||
|
const rec_t* rec, /*!< in: record */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const ulint* offsets,/*!< in: rec_get_offs(rec, index) */
|
||||||
|
ibool del) /*!< in: TRUE=deleted, FALSE=exists */
|
||||||
|
{
|
||||||
|
const ib_rbt_node_t* node;
|
||||||
|
btr_blob_dbg_t b;
|
||||||
|
btr_blob_dbg_t* c;
|
||||||
|
ulint i;
|
||||||
|
|
||||||
|
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||||
|
ut_a(dict_index_is_clust(index));
|
||||||
|
ut_a(del == !!del);/* must be FALSE==0 or TRUE==1 */
|
||||||
|
|
||||||
|
if (!rec_offs_any_extern(offsets) || !index->blobs) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ref_page_no = page_get_page_no(page_align(rec));
|
||||||
|
b.ref_heap_no = page_rec_get_heap_no(rec);
|
||||||
|
|
||||||
|
for (i = 0; i < rec_offs_n_fields(offsets); i++) {
|
||||||
|
if (rec_offs_nth_extern(offsets, i)) {
|
||||||
|
ulint len;
|
||||||
|
const byte* field_ref = rec_get_nth_field(
|
||||||
|
rec, offsets, i, &len);
|
||||||
|
|
||||||
|
ut_a(len != UNIV_SQL_NULL);
|
||||||
|
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||||
|
field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
|
||||||
|
|
||||||
|
b.ref_field_no = i;
|
||||||
|
b.blob_page_no = mach_read_from_4(
|
||||||
|
field_ref + BTR_EXTERN_PAGE_NO);
|
||||||
|
|
||||||
|
switch (b.blob_page_no) {
|
||||||
|
case 0:
|
||||||
|
ut_a(memcmp(field_ref, field_ref_zero,
|
||||||
|
BTR_EXTERN_FIELD_REF_SIZE));
|
||||||
|
/* page number 0 is for the
|
||||||
|
page allocation bitmap */
|
||||||
|
case FIL_NULL:
|
||||||
|
/* the column has been freed already */
|
||||||
|
ut_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_enter(&index->blobs_mutex);
|
||||||
|
node = rbt_lookup(index->blobs, &b);
|
||||||
|
ut_a(node);
|
||||||
|
|
||||||
|
c = rbt_value(btr_blob_dbg_t, node);
|
||||||
|
/* The flag should be modified. */
|
||||||
|
c->del = del;
|
||||||
|
if (btr_blob_dbg_msg) {
|
||||||
|
b = *c;
|
||||||
|
mutex_exit(&index->blobs_mutex);
|
||||||
|
btr_blob_dbg_msg_issue("del_mk", &b, "");
|
||||||
|
} else {
|
||||||
|
mutex_exit(&index->blobs_mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Change the ownership of an off-page column. */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_owner(
|
||||||
|
/*===============*/
|
||||||
|
const rec_t* rec, /*!< in: record */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const ulint* offsets,/*!< in: rec_get_offs(rec, index) */
|
||||||
|
ulint i, /*!< in: ith field in rec */
|
||||||
|
ibool own) /*!< in: TRUE=owned, FALSE=disowned */
|
||||||
|
{
|
||||||
|
const ib_rbt_node_t* node;
|
||||||
|
btr_blob_dbg_t b;
|
||||||
|
const byte* field_ref;
|
||||||
|
ulint len;
|
||||||
|
|
||||||
|
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||||
|
ut_a(rec_offs_nth_extern(offsets, i));
|
||||||
|
|
||||||
|
field_ref = rec_get_nth_field(rec, offsets, i, &len);
|
||||||
|
ut_a(len != UNIV_SQL_NULL);
|
||||||
|
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||||
|
field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
|
||||||
|
|
||||||
|
b.ref_page_no = page_get_page_no(page_align(rec));
|
||||||
|
b.ref_heap_no = page_rec_get_heap_no(rec);
|
||||||
|
b.ref_field_no = i;
|
||||||
|
b.owner = !(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG);
|
||||||
|
b.blob_page_no = mach_read_from_4(field_ref + BTR_EXTERN_PAGE_NO);
|
||||||
|
|
||||||
|
ut_a(b.owner == own);
|
||||||
|
|
||||||
|
mutex_enter(&index->blobs_mutex);
|
||||||
|
node = rbt_lookup(index->blobs, &b);
|
||||||
|
/* row_ins_clust_index_entry_by_modify() invokes
|
||||||
|
btr_cur_unmark_extern_fields() also for the newly inserted
|
||||||
|
references, which are all zero bytes until the columns are stored.
|
||||||
|
The node lookup must fail if and only if that is the case. */
|
||||||
|
ut_a(!memcmp(field_ref, field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE)
|
||||||
|
== !node);
|
||||||
|
|
||||||
|
if (node) {
|
||||||
|
btr_blob_dbg_t* c = rbt_value(btr_blob_dbg_t, node);
|
||||||
|
/* Some code sets ownership from TRUE to TRUE.
|
||||||
|
We do not allow changing ownership from FALSE to FALSE. */
|
||||||
|
ut_a(own || c->owner);
|
||||||
|
|
||||||
|
c->owner = own;
|
||||||
|
if (!own) {
|
||||||
|
c->always_owner = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_exit(&index->blobs_mutex);
|
||||||
|
}
|
||||||
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Latching strategy of the InnoDB B-tree
|
Latching strategy of the InnoDB B-tree
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
@ -296,6 +850,7 @@ btr_page_create(
|
|||||||
page_t* page = buf_block_get_frame(block);
|
page_t* page = buf_block_get_frame(block);
|
||||||
|
|
||||||
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
|
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
|
||||||
|
btr_blob_dbg_assert_empty(index, buf_block_get_page_no(block));
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||||
page_create_zip(block, index, level, mtr);
|
page_create_zip(block, index, level, mtr);
|
||||||
@ -489,6 +1044,7 @@ btr_page_free_low(
|
|||||||
modify clock */
|
modify clock */
|
||||||
|
|
||||||
buf_block_modify_clock_inc(block);
|
buf_block_modify_clock_inc(block);
|
||||||
|
btr_blob_dbg_assert_empty(index, buf_block_get_page_no(block));
|
||||||
|
|
||||||
if (dict_index_is_ibuf(index)) {
|
if (dict_index_is_ibuf(index)) {
|
||||||
|
|
||||||
@ -773,6 +1329,13 @@ btr_create(
|
|||||||
block = buf_page_get(space, zip_size, page_no,
|
block = buf_page_get(space, zip_size, page_no,
|
||||||
RW_X_LATCH, mtr);
|
RW_X_LATCH, mtr);
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
|
if ((type & DICT_CLUSTERED) && !index->blobs) {
|
||||||
|
mutex_create(&index->blobs_mutex, SYNC_ANY_LATCH);
|
||||||
|
index->blobs = rbt_create(sizeof(btr_blob_dbg_t),
|
||||||
|
btr_blob_dbg_cmp);
|
||||||
|
}
|
||||||
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
block = fseg_create(space, 0,
|
block = fseg_create(space, 0,
|
||||||
PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
|
PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
|
||||||
}
|
}
|
||||||
@ -996,6 +1559,7 @@ btr_page_reorganize_low(
|
|||||||
|
|
||||||
block->check_index_page_at_flush = TRUE;
|
block->check_index_page_at_flush = TRUE;
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
#endif /* !UNIV_HOTBACKUP */
|
||||||
|
btr_blob_dbg_remove(page, index, "btr_page_reorganize");
|
||||||
|
|
||||||
/* Recreate the page: note that global data on page (possible
|
/* Recreate the page: note that global data on page (possible
|
||||||
segment headers, next page-field, etc.) is preserved intact */
|
segment headers, next page-field, etc.) is preserved intact */
|
||||||
@ -1024,6 +1588,8 @@ btr_page_reorganize_low(
|
|||||||
(!page_zip_compress(page_zip, page, index, NULL))) {
|
(!page_zip_compress(page_zip, page, index, NULL))) {
|
||||||
|
|
||||||
/* Restore the old page and exit. */
|
/* Restore the old page and exit. */
|
||||||
|
btr_blob_dbg_restore(page, temp_page, index,
|
||||||
|
"btr_page_reorganize_compress_fail");
|
||||||
|
|
||||||
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
|
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
|
||||||
/* Check that the bytes that we skip are identical. */
|
/* Check that the bytes that we skip are identical. */
|
||||||
@ -1157,6 +1723,7 @@ btr_page_empty(
|
|||||||
#endif /* UNIV_ZIP_DEBUG */
|
#endif /* UNIV_ZIP_DEBUG */
|
||||||
|
|
||||||
btr_search_drop_page_hash_index(block);
|
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
|
/* Recreate the page: note that global data on page (possible
|
||||||
segment headers, next page-field, etc.) is preserved intact */
|
segment headers, next page-field, etc.) is preserved intact */
|
||||||
@ -2497,6 +3064,7 @@ btr_lift_page_up(
|
|||||||
index);
|
index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btr_blob_dbg_remove(page, index, "btr_lift_page_up");
|
||||||
lock_update_copy_and_discard(father_block, block);
|
lock_update_copy_and_discard(father_block, block);
|
||||||
|
|
||||||
/* Go upward to root page, decrementing levels by one. */
|
/* Go upward to root page, decrementing levels by one. */
|
||||||
@ -2758,6 +3326,7 @@ err_exit:
|
|||||||
lock_update_merge_right(merge_block, orig_succ, block);
|
lock_update_merge_right(merge_block, orig_succ, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btr_blob_dbg_remove(page, index, "btr_compress");
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
||||||
if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) {
|
if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) {
|
||||||
@ -2988,6 +3557,8 @@ btr_discard_page(
|
|||||||
block);
|
block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btr_blob_dbg_remove(page, index, "btr_discard_page");
|
||||||
|
|
||||||
/* Free the file page */
|
/* Free the file page */
|
||||||
btr_page_free(index, block, mtr);
|
btr_page_free(index, block, mtr);
|
||||||
|
|
||||||
|
@ -2572,6 +2572,7 @@ btr_cur_del_mark_set_clust_rec(
|
|||||||
|
|
||||||
page_zip = buf_block_get_page_zip(block);
|
page_zip = buf_block_get_page_zip(block);
|
||||||
|
|
||||||
|
btr_blob_dbg_set_deleted_flag(rec, index, offsets, val);
|
||||||
btr_rec_set_deleted_flag(rec, page_zip, val);
|
btr_rec_set_deleted_flag(rec, page_zip, val);
|
||||||
|
|
||||||
trx = thr_get_trx(thr);
|
trx = thr_get_trx(thr);
|
||||||
@ -3595,6 +3596,8 @@ btr_cur_set_ownership_of_extern_field(
|
|||||||
} else {
|
} else {
|
||||||
mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val);
|
mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btr_blob_dbg_owner(rec, index, offsets, i, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
@ -4094,6 +4097,11 @@ btr_store_big_rec_extern_fields_func(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (prev_page_no == FIL_NULL) {
|
if (prev_page_no == FIL_NULL) {
|
||||||
|
btr_blob_dbg_add_blob(
|
||||||
|
rec, big_rec_vec->fields[i]
|
||||||
|
.field_no, page_no, index,
|
||||||
|
"store");
|
||||||
|
|
||||||
mach_write_to_4(field_ref
|
mach_write_to_4(field_ref
|
||||||
+ BTR_EXTERN_SPACE_ID,
|
+ BTR_EXTERN_SPACE_ID,
|
||||||
space_id);
|
space_id);
|
||||||
@ -4169,6 +4177,11 @@ next_zip_page:
|
|||||||
MLOG_4BYTES, &mtr);
|
MLOG_4BYTES, &mtr);
|
||||||
|
|
||||||
if (prev_page_no == FIL_NULL) {
|
if (prev_page_no == FIL_NULL) {
|
||||||
|
btr_blob_dbg_add_blob(
|
||||||
|
rec, big_rec_vec->fields[i]
|
||||||
|
.field_no, page_no, index,
|
||||||
|
"store");
|
||||||
|
|
||||||
mlog_write_ulint(field_ref
|
mlog_write_ulint(field_ref
|
||||||
+ BTR_EXTERN_SPACE_ID,
|
+ BTR_EXTERN_SPACE_ID,
|
||||||
space_id,
|
space_id,
|
||||||
@ -4337,6 +4350,37 @@ btr_free_externally_stored_field(
|
|||||||
rec_zip_size = 0;
|
rec_zip_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
|
if (!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG)
|
||||||
|
&& !((field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG)
|
||||||
|
&& (rb_ctx == RB_NORMAL || rb_ctx == RB_RECOVERY))) {
|
||||||
|
/* This off-page column will be freed.
|
||||||
|
Check that no references remain. */
|
||||||
|
|
||||||
|
btr_blob_dbg_t b;
|
||||||
|
|
||||||
|
b.blob_page_no = mach_read_from_4(
|
||||||
|
field_ref + BTR_EXTERN_PAGE_NO);
|
||||||
|
|
||||||
|
if (rec) {
|
||||||
|
/* Remove the reference from the record to the
|
||||||
|
BLOB. If the BLOB were not freed, the
|
||||||
|
reference would be removed when the record is
|
||||||
|
removed. Freeing the BLOB will overwrite the
|
||||||
|
BTR_EXTERN_PAGE_NO in the field_ref of the
|
||||||
|
record with FIL_NULL, which would make the
|
||||||
|
btr_blob_dbg information inconsistent with the
|
||||||
|
record. */
|
||||||
|
b.ref_page_no = page_get_page_no(page_align(rec));
|
||||||
|
b.ref_heap_no = page_rec_get_heap_no(rec);
|
||||||
|
b.ref_field_no = i;
|
||||||
|
btr_blob_dbg_rbt_delete(index, &b, "free");
|
||||||
|
}
|
||||||
|
|
||||||
|
btr_blob_dbg_assert_empty(index, b.blob_page_no);
|
||||||
|
}
|
||||||
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#ifdef UNIV_SYNC_DEBUG
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
buf_block_t* rec_block;
|
buf_block_t* rec_block;
|
||||||
|
@ -36,6 +36,9 @@ Created 1/8/1996 Heikki Tuuri
|
|||||||
#ifndef UNIV_HOTBACKUP
|
#ifndef UNIV_HOTBACKUP
|
||||||
# include "lock0lock.h"
|
# include "lock0lock.h"
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
#endif /* !UNIV_HOTBACKUP */
|
||||||
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
|
# include "ut0rbt.h"
|
||||||
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
|
|
||||||
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
|
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
|
||||||
creating a table or index object */
|
creating a table or index object */
|
||||||
@ -316,6 +319,12 @@ dict_mem_index_free(
|
|||||||
{
|
{
|
||||||
ut_ad(index);
|
ut_ad(index);
|
||||||
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
|
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
|
||||||
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
|
if (index->blobs) {
|
||||||
|
mutex_free(&index->blobs_mutex);
|
||||||
|
rbt_free(index->blobs);
|
||||||
|
}
|
||||||
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
|
|
||||||
mem_heap_free(index->heap);
|
mem_heap_free(index->heap);
|
||||||
}
|
}
|
||||||
|
@ -782,10 +782,6 @@ err_exit:
|
|||||||
|
|
||||||
ut_ad(error == DB_SUCCESS);
|
ut_ad(error == DB_SUCCESS);
|
||||||
|
|
||||||
/* We will need to rebuild index translation table. Set
|
|
||||||
valid index entry count in the translation table to zero */
|
|
||||||
share->idx_trans_tbl.index_count = 0;
|
|
||||||
|
|
||||||
/* Commit the data dictionary transaction in order to release
|
/* Commit the data dictionary transaction in order to release
|
||||||
the table locks on the system tables. This means that if
|
the table locks on the system tables. This means that if
|
||||||
MySQL crashes while creating a new primary key inside
|
MySQL crashes while creating a new primary key inside
|
||||||
@ -911,6 +907,14 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
convert_error:
|
convert_error:
|
||||||
|
if (error == DB_SUCCESS) {
|
||||||
|
/* Build index is successful. We will need to
|
||||||
|
rebuild index translation table. Reset the
|
||||||
|
index entry count in the translation table
|
||||||
|
to zero, so that translation table will be rebuilt */
|
||||||
|
share->idx_trans_tbl.index_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
error = convert_error_code_to_mysql(error,
|
error = convert_error_code_to_mysql(error,
|
||||||
innodb_table->flags,
|
innodb_table->flags,
|
||||||
user_thd);
|
user_thd);
|
||||||
|
@ -81,6 +81,91 @@ UNIQUE definition on secondary indexes when we decide if we can use
|
|||||||
the insert buffer to speed up inserts */
|
the insert buffer to speed up inserts */
|
||||||
#define BTR_IGNORE_SEC_UNIQUE 2048
|
#define BTR_IGNORE_SEC_UNIQUE 2048
|
||||||
|
|
||||||
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
|
# include "ut0rbt.h"
|
||||||
|
/** An index->blobs entry for keeping track of off-page column references */
|
||||||
|
struct btr_blob_dbg_struct
|
||||||
|
{
|
||||||
|
unsigned blob_page_no:32; /*!< first BLOB page number */
|
||||||
|
unsigned ref_page_no:32; /*!< referring page number */
|
||||||
|
unsigned ref_heap_no:16; /*!< referring heap number */
|
||||||
|
unsigned ref_field_no:10; /*!< referring field number */
|
||||||
|
unsigned owner:1; /*!< TRUE if BLOB owner */
|
||||||
|
unsigned always_owner:1; /*!< TRUE if always
|
||||||
|
has been the BLOB owner;
|
||||||
|
reset to TRUE on B-tree
|
||||||
|
page splits and merges */
|
||||||
|
unsigned del:1; /*!< TRUE if currently
|
||||||
|
delete-marked */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Add a reference to an off-page column to the index->blobs map. */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_add_blob(
|
||||||
|
/*==================*/
|
||||||
|
const rec_t* rec, /*!< in: clustered index record */
|
||||||
|
ulint field_no, /*!< in: number of off-page column */
|
||||||
|
ulint page_no, /*!< in: start page of the column */
|
||||||
|
dict_index_t* index, /*!< in/out: index tree */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
__attribute__((nonnull));
|
||||||
|
/**************************************************************//**
|
||||||
|
Display the references to off-page columns.
|
||||||
|
This function is to be called from a debugger,
|
||||||
|
for example when a breakpoint on ut_dbg_assertion_failed is hit. */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_print(
|
||||||
|
/*===============*/
|
||||||
|
const dict_index_t* index) /*!< in: index tree */
|
||||||
|
__attribute__((nonnull));
|
||||||
|
/**************************************************************//**
|
||||||
|
Check that there are no references to off-page columns from or to
|
||||||
|
the given page. Invoked when freeing or clearing a page.
|
||||||
|
@return TRUE when no orphan references exist */
|
||||||
|
UNIV_INTERN
|
||||||
|
ibool
|
||||||
|
btr_blob_dbg_is_empty(
|
||||||
|
/*==================*/
|
||||||
|
dict_index_t* index, /*!< in: index */
|
||||||
|
ulint page_no) /*!< in: page number */
|
||||||
|
__attribute__((nonnull, warn_unused_result));
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Modify the 'deleted' flag of a record. */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_set_deleted_flag(
|
||||||
|
/*==========================*/
|
||||||
|
const rec_t* rec, /*!< in: record */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const ulint* offsets,/*!< in: rec_get_offs(rec, index) */
|
||||||
|
ibool del) /*!< in: TRUE=deleted, FALSE=exists */
|
||||||
|
__attribute__((nonnull));
|
||||||
|
/**************************************************************//**
|
||||||
|
Change the ownership of an off-page column. */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_owner(
|
||||||
|
/*===============*/
|
||||||
|
const rec_t* rec, /*!< in: record */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const ulint* offsets,/*!< in: rec_get_offs(rec, index) */
|
||||||
|
ulint i, /*!< in: ith field in rec */
|
||||||
|
ibool own) /*!< in: TRUE=owned, FALSE=disowned */
|
||||||
|
__attribute__((nonnull));
|
||||||
|
/** Assert that there are no BLOB references to or from the given page. */
|
||||||
|
# define btr_blob_dbg_assert_empty(index, page_no) \
|
||||||
|
ut_a(btr_blob_dbg_is_empty(index, page_no))
|
||||||
|
#else /* UNIV_BLOB_DEBUG */
|
||||||
|
# define btr_blob_dbg_add_blob(rec, field_no, page, index, ctx) ((void) 0)
|
||||||
|
# define btr_blob_dbg_set_deleted_flag(rec, index, offsets, del)((void) 0)
|
||||||
|
# define btr_blob_dbg_owner(rec, index, offsets, i, val) ((void) 0)
|
||||||
|
# define btr_blob_dbg_assert_empty(index, page_no) ((void) 0)
|
||||||
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
|
|
||||||
/**************************************************************//**
|
/**************************************************************//**
|
||||||
Gets the root node of a tree and x-latches it.
|
Gets the root node of a tree and x-latches it.
|
||||||
@return root page, x-latched */
|
@return root page, x-latched */
|
||||||
|
@ -38,6 +38,131 @@ typedef struct btr_cur_struct btr_cur_t;
|
|||||||
/** B-tree search information for the adaptive hash index */
|
/** B-tree search information for the adaptive hash index */
|
||||||
typedef struct btr_search_struct btr_search_t;
|
typedef struct btr_search_struct btr_search_t;
|
||||||
|
|
||||||
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
|
# include "buf0types.h"
|
||||||
|
/** An index->blobs entry for keeping track of off-page column references */
|
||||||
|
typedef struct btr_blob_dbg_struct btr_blob_dbg_t;
|
||||||
|
|
||||||
|
/** Insert to index->blobs a reference to an off-page column.
|
||||||
|
@param index the index tree
|
||||||
|
@param b the reference
|
||||||
|
@param ctx context (for logging) */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_rbt_insert(
|
||||||
|
/*====================*/
|
||||||
|
dict_index_t* index, /*!< in/out: index tree */
|
||||||
|
const btr_blob_dbg_t* b, /*!< in: the reference */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
__attribute__((nonnull));
|
||||||
|
|
||||||
|
/** Remove from index->blobs a reference to an off-page column.
|
||||||
|
@param index the index tree
|
||||||
|
@param b the reference
|
||||||
|
@param ctx context (for logging) */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_rbt_delete(
|
||||||
|
/*====================*/
|
||||||
|
dict_index_t* index, /*!< in/out: index tree */
|
||||||
|
const btr_blob_dbg_t* b, /*!< in: the reference */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
__attribute__((nonnull));
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Add to index->blobs any references to off-page columns from a record.
|
||||||
|
@return number of references added */
|
||||||
|
UNIV_INTERN
|
||||||
|
ulint
|
||||||
|
btr_blob_dbg_add_rec(
|
||||||
|
/*=================*/
|
||||||
|
const rec_t* rec, /*!< in: record */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const ulint* offsets,/*!< in: offsets */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
__attribute__((nonnull));
|
||||||
|
/**************************************************************//**
|
||||||
|
Remove from index->blobs any references to off-page columns from a record.
|
||||||
|
@return number of references removed */
|
||||||
|
UNIV_INTERN
|
||||||
|
ulint
|
||||||
|
btr_blob_dbg_remove_rec(
|
||||||
|
/*====================*/
|
||||||
|
const rec_t* rec, /*!< in: record */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const ulint* offsets,/*!< in: offsets */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
__attribute__((nonnull));
|
||||||
|
/**************************************************************//**
|
||||||
|
Count and add to index->blobs any references to off-page columns
|
||||||
|
from records on a page.
|
||||||
|
@return number of references added */
|
||||||
|
UNIV_INTERN
|
||||||
|
ulint
|
||||||
|
btr_blob_dbg_add(
|
||||||
|
/*=============*/
|
||||||
|
const page_t* page, /*!< in: rewritten page */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
__attribute__((nonnull));
|
||||||
|
/**************************************************************//**
|
||||||
|
Count and remove from index->blobs any references to off-page columns
|
||||||
|
from records on a page.
|
||||||
|
Used when reorganizing a page, before copying the records.
|
||||||
|
@return number of references removed */
|
||||||
|
UNIV_INTERN
|
||||||
|
ulint
|
||||||
|
btr_blob_dbg_remove(
|
||||||
|
/*================*/
|
||||||
|
const page_t* page, /*!< in: b-tree page */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
__attribute__((nonnull));
|
||||||
|
/**************************************************************//**
|
||||||
|
Restore in index->blobs any references to off-page columns
|
||||||
|
Used when page reorganize fails due to compressed page overflow. */
|
||||||
|
UNIV_INTERN
|
||||||
|
void
|
||||||
|
btr_blob_dbg_restore(
|
||||||
|
/*=================*/
|
||||||
|
const page_t* npage, /*!< in: page that failed to compress */
|
||||||
|
const page_t* page, /*!< in: copy of original page */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const char* ctx) /*!< in: context (for logging) */
|
||||||
|
__attribute__((nonnull));
|
||||||
|
|
||||||
|
/** Operation that processes the BLOB references of an index record
|
||||||
|
@param[in] rec record on index page
|
||||||
|
@param[in/out] index the index tree of the record
|
||||||
|
@param[in] offsets rec_get_offsets(rec,index)
|
||||||
|
@param[in] ctx context (for logging)
|
||||||
|
@return number of BLOB references processed */
|
||||||
|
typedef ulint (*btr_blob_dbg_op_f)
|
||||||
|
(const rec_t* rec,dict_index_t* index,const ulint* offsets,const char* ctx);
|
||||||
|
|
||||||
|
/**************************************************************//**
|
||||||
|
Count and process all references to off-page columns on a page.
|
||||||
|
@return number of references processed */
|
||||||
|
UNIV_INTERN
|
||||||
|
ulint
|
||||||
|
btr_blob_dbg_op(
|
||||||
|
/*============*/
|
||||||
|
const page_t* page, /*!< in: B-tree leaf page */
|
||||||
|
const rec_t* rec, /*!< in: record to start from
|
||||||
|
(NULL to process the whole page) */
|
||||||
|
dict_index_t* index, /*!< in/out: index */
|
||||||
|
const char* ctx, /*!< in: context (for logging) */
|
||||||
|
const btr_blob_dbg_op_f op) /*!< in: operation on records */
|
||||||
|
__attribute__((nonnull(1,3,4,5)));
|
||||||
|
#else /* UNIV_BLOB_DEBUG */
|
||||||
|
# define btr_blob_dbg_add_rec(rec, index, offsets, ctx) ((void) 0)
|
||||||
|
# define btr_blob_dbg_add(page, index, ctx) ((void) 0)
|
||||||
|
# define btr_blob_dbg_remove_rec(rec, index, offsets, ctx) ((void) 0)
|
||||||
|
# define btr_blob_dbg_remove(page, index, ctx) ((void) 0)
|
||||||
|
# define btr_blob_dbg_restore(npage, page, index, ctx) ((void) 0)
|
||||||
|
# define btr_blob_dbg_op(page, rec, index, ctx, op) ((void) 0)
|
||||||
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
|
|
||||||
/** The size of a reference to data stored on a different page.
|
/** The size of a reference to data stored on a different page.
|
||||||
The reference is stored at the end of the prefix of the field
|
The reference is stored at the end of the prefix of the field
|
||||||
in the index record. */
|
in the index record. */
|
||||||
|
@ -340,6 +340,13 @@ struct dict_index_struct{
|
|||||||
index, or 0 if the index existed
|
index, or 0 if the index existed
|
||||||
when InnoDB was started up */
|
when InnoDB was started up */
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
#endif /* !UNIV_HOTBACKUP */
|
||||||
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
|
mutex_t blobs_mutex;
|
||||||
|
/*!< mutex protecting blobs */
|
||||||
|
void* blobs; /*!< map of (page_no,heap_no,field_no)
|
||||||
|
to first_blob_page_no; protected by
|
||||||
|
blobs_mutex; @see btr_blob_dbg_t */
|
||||||
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
ulint magic_n;/*!< magic number */
|
ulint magic_n;/*!< magic number */
|
||||||
/** Value of dict_index_struct::magic_n */
|
/** Value of dict_index_struct::magic_n */
|
||||||
|
@ -420,7 +420,7 @@ page_zip_copy_recs(
|
|||||||
const page_t* src, /*!< in: page */
|
const page_t* src, /*!< in: page */
|
||||||
dict_index_t* index, /*!< in: index of the B-tree */
|
dict_index_t* index, /*!< in: index of the B-tree */
|
||||||
mtr_t* mtr) /*!< in: mini-transaction */
|
mtr_t* mtr) /*!< in: mini-transaction */
|
||||||
__attribute__((nonnull(1,2,3,4)));
|
__attribute__((nonnull));
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
#endif /* !UNIV_HOTBACKUP */
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
|
@ -46,7 +46,7 @@ Created 1/20/1994 Heikki Tuuri
|
|||||||
|
|
||||||
#define INNODB_VERSION_MAJOR 1
|
#define INNODB_VERSION_MAJOR 1
|
||||||
#define INNODB_VERSION_MINOR 0
|
#define INNODB_VERSION_MINOR 0
|
||||||
#define INNODB_VERSION_BUGFIX 15
|
#define INNODB_VERSION_BUGFIX 16
|
||||||
|
|
||||||
/* The following is the InnoDB version as shown in
|
/* The following is the InnoDB version as shown in
|
||||||
SELECT plugin_version FROM information_schema.plugins;
|
SELECT plugin_version FROM information_schema.plugins;
|
||||||
@ -194,6 +194,8 @@ this will break redo log file compatibility, but it may be useful when
|
|||||||
debugging redo log application problems. */
|
debugging redo log application problems. */
|
||||||
#define UNIV_MEM_DEBUG /* detect memory leaks etc */
|
#define UNIV_MEM_DEBUG /* detect memory leaks etc */
|
||||||
#define UNIV_IBUF_DEBUG /* debug the insert buffer */
|
#define UNIV_IBUF_DEBUG /* debug the insert buffer */
|
||||||
|
#define UNIV_BLOB_DEBUG /* track BLOB ownership;
|
||||||
|
assumes that no BLOBs survive server restart */
|
||||||
#define UNIV_IBUF_COUNT_DEBUG /* debug the insert buffer;
|
#define UNIV_IBUF_COUNT_DEBUG /* debug the insert buffer;
|
||||||
this limits the database to IBUF_COUNT_N_SPACES and IBUF_COUNT_N_PAGES,
|
this limits the database to IBUF_COUNT_N_SPACES and IBUF_COUNT_N_PAGES,
|
||||||
and the insert buffer must be empty when the database is started */
|
and the insert buffer must be empty when the database is started */
|
||||||
|
@ -1149,6 +1149,8 @@ use_heap:
|
|||||||
current_rec, index, mtr);
|
current_rec, index, mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btr_blob_dbg_add_rec(insert_rec, index, offsets, "insert");
|
||||||
|
|
||||||
return(insert_rec);
|
return(insert_rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1195,10 +1197,12 @@ page_cur_insert_rec_zip_reorg(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Out of space: restore the page */
|
/* Out of space: restore the page */
|
||||||
|
btr_blob_dbg_remove(page, index, "insert_zip_fail");
|
||||||
if (!page_zip_decompress(page_zip, page, FALSE)) {
|
if (!page_zip_decompress(page_zip, page, FALSE)) {
|
||||||
ut_error; /* Memory corrupted? */
|
ut_error; /* Memory corrupted? */
|
||||||
}
|
}
|
||||||
ut_ad(page_validate(page, index));
|
ut_ad(page_validate(page, index));
|
||||||
|
btr_blob_dbg_add(page, index, "insert_zip_fail");
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1490,6 +1494,8 @@ use_heap:
|
|||||||
|
|
||||||
page_zip_write_rec(page_zip, insert_rec, index, offsets, 1);
|
page_zip_write_rec(page_zip, insert_rec, index, offsets, 1);
|
||||||
|
|
||||||
|
btr_blob_dbg_add_rec(insert_rec, index, offsets, "insert_zip_ok");
|
||||||
|
|
||||||
/* 9. Write log record of the insert */
|
/* 9. Write log record of the insert */
|
||||||
if (UNIV_LIKELY(mtr != NULL)) {
|
if (UNIV_LIKELY(mtr != NULL)) {
|
||||||
page_cur_insert_rec_write_log(insert_rec, rec_size,
|
page_cur_insert_rec_write_log(insert_rec, rec_size,
|
||||||
@ -1697,6 +1703,9 @@ page_copy_rec_list_end_to_created_page(
|
|||||||
|
|
||||||
heap_top += rec_size;
|
heap_top += rec_size;
|
||||||
|
|
||||||
|
rec_offs_make_valid(insert_rec, index, offsets);
|
||||||
|
btr_blob_dbg_add_rec(insert_rec, index, offsets, "copy_end");
|
||||||
|
|
||||||
page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec,
|
page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec,
|
||||||
index, mtr);
|
index, mtr);
|
||||||
prev_rec = insert_rec;
|
prev_rec = insert_rec;
|
||||||
@ -1944,6 +1953,7 @@ page_cur_delete_rec(
|
|||||||
page_dir_slot_set_n_owned(cur_dir_slot, page_zip, cur_n_owned - 1);
|
page_dir_slot_set_n_owned(cur_dir_slot, page_zip, cur_n_owned - 1);
|
||||||
|
|
||||||
/* 6. Free the memory occupied by the record */
|
/* 6. Free the memory occupied by the record */
|
||||||
|
btr_blob_dbg_remove_rec(current_rec, index, offsets, "delete");
|
||||||
page_mem_free(page, page_zip, current_rec, index, offsets);
|
page_mem_free(page, page_zip, current_rec, index, offsets);
|
||||||
|
|
||||||
/* 7. Now we have decremented the number of owned records of the slot.
|
/* 7. Now we have decremented the number of owned records of the slot.
|
||||||
|
@ -685,12 +685,16 @@ page_copy_rec_list_end(
|
|||||||
if (UNIV_UNLIKELY
|
if (UNIV_UNLIKELY
|
||||||
(!page_zip_reorganize(new_block, index, mtr))) {
|
(!page_zip_reorganize(new_block, index, mtr))) {
|
||||||
|
|
||||||
|
btr_blob_dbg_remove(new_page, index,
|
||||||
|
"copy_end_reorg_fail");
|
||||||
if (UNIV_UNLIKELY
|
if (UNIV_UNLIKELY
|
||||||
(!page_zip_decompress(new_page_zip,
|
(!page_zip_decompress(new_page_zip,
|
||||||
new_page, FALSE))) {
|
new_page, FALSE))) {
|
||||||
ut_error;
|
ut_error;
|
||||||
}
|
}
|
||||||
ut_ad(page_validate(new_page, index));
|
ut_ad(page_validate(new_page, index));
|
||||||
|
btr_blob_dbg_add(new_page, index,
|
||||||
|
"copy_end_reorg_fail");
|
||||||
return(NULL);
|
return(NULL);
|
||||||
} else {
|
} else {
|
||||||
/* The page was reorganized:
|
/* The page was reorganized:
|
||||||
@ -803,12 +807,16 @@ page_copy_rec_list_start(
|
|||||||
if (UNIV_UNLIKELY
|
if (UNIV_UNLIKELY
|
||||||
(!page_zip_reorganize(new_block, index, mtr))) {
|
(!page_zip_reorganize(new_block, index, mtr))) {
|
||||||
|
|
||||||
|
btr_blob_dbg_remove(new_page, index,
|
||||||
|
"copy_start_reorg_fail");
|
||||||
if (UNIV_UNLIKELY
|
if (UNIV_UNLIKELY
|
||||||
(!page_zip_decompress(new_page_zip,
|
(!page_zip_decompress(new_page_zip,
|
||||||
new_page, FALSE))) {
|
new_page, FALSE))) {
|
||||||
ut_error;
|
ut_error;
|
||||||
}
|
}
|
||||||
ut_ad(page_validate(new_page, index));
|
ut_ad(page_validate(new_page, index));
|
||||||
|
btr_blob_dbg_add(new_page, index,
|
||||||
|
"copy_start_reorg_fail");
|
||||||
return(NULL);
|
return(NULL);
|
||||||
} else {
|
} else {
|
||||||
/* The page was reorganized:
|
/* The page was reorganized:
|
||||||
@ -1080,6 +1088,9 @@ page_delete_rec_list_end(
|
|||||||
/* Remove the record chain segment from the record chain */
|
/* Remove the record chain segment from the record chain */
|
||||||
page_rec_set_next(prev_rec, page_get_supremum_rec(page));
|
page_rec_set_next(prev_rec, page_get_supremum_rec(page));
|
||||||
|
|
||||||
|
btr_blob_dbg_op(page, rec, index, "delete_end",
|
||||||
|
btr_blob_dbg_remove_rec);
|
||||||
|
|
||||||
/* Catenate the deleted chain segment to the page free list */
|
/* Catenate the deleted chain segment to the page free list */
|
||||||
|
|
||||||
page_rec_set_next(last_rec, page_header_get_ptr(page, PAGE_FREE));
|
page_rec_set_next(last_rec, page_header_get_ptr(page, PAGE_FREE));
|
||||||
|
@ -4451,6 +4451,8 @@ page_zip_reorganize(
|
|||||||
/* Copy the old page to temporary space */
|
/* Copy the old page to temporary space */
|
||||||
buf_frame_copy(temp_page, page);
|
buf_frame_copy(temp_page, page);
|
||||||
|
|
||||||
|
btr_blob_dbg_remove(page, index, "zip_reorg");
|
||||||
|
|
||||||
/* Recreate the page: note that global data on page (possible
|
/* Recreate the page: note that global data on page (possible
|
||||||
segment headers, next page-field, etc.) is preserved intact */
|
segment headers, next page-field, etc.) is preserved intact */
|
||||||
|
|
||||||
@ -4509,7 +4511,7 @@ page_zip_copy_recs(
|
|||||||
mtr_t* mtr) /*!< in: mini-transaction */
|
mtr_t* mtr) /*!< in: mini-transaction */
|
||||||
{
|
{
|
||||||
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
|
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
|
||||||
ut_ad(mtr_memo_contains_page(mtr, (page_t*) src, MTR_MEMO_PAGE_X_FIX));
|
ut_ad(mtr_memo_contains_page(mtr, src, MTR_MEMO_PAGE_X_FIX));
|
||||||
ut_ad(!dict_index_is_ibuf(index));
|
ut_ad(!dict_index_is_ibuf(index));
|
||||||
#ifdef UNIV_ZIP_DEBUG
|
#ifdef UNIV_ZIP_DEBUG
|
||||||
/* The B-tree operations that call this function may set
|
/* The B-tree operations that call this function may set
|
||||||
@ -4579,6 +4581,7 @@ page_zip_copy_recs(
|
|||||||
#ifdef UNIV_ZIP_DEBUG
|
#ifdef UNIV_ZIP_DEBUG
|
||||||
ut_a(page_zip_validate(page_zip, page));
|
ut_a(page_zip_validate(page_zip, page));
|
||||||
#endif /* UNIV_ZIP_DEBUG */
|
#endif /* UNIV_ZIP_DEBUG */
|
||||||
|
btr_blob_dbg_add(page, index, "page_zip_copy_recs");
|
||||||
|
|
||||||
page_zip_compress_write_log(page_zip, page, index, mtr);
|
page_zip_compress_write_log(page_zip, page, index, mtr);
|
||||||
}
|
}
|
||||||
|
@ -498,14 +498,49 @@ row_upd_rec_in_place(
|
|||||||
n_fields = upd_get_n_fields(update);
|
n_fields = upd_get_n_fields(update);
|
||||||
|
|
||||||
for (i = 0; i < n_fields; i++) {
|
for (i = 0; i < n_fields; i++) {
|
||||||
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
|
btr_blob_dbg_t b;
|
||||||
|
const byte* field_ref = NULL;
|
||||||
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
|
|
||||||
upd_field = upd_get_nth_field(update, i);
|
upd_field = upd_get_nth_field(update, i);
|
||||||
new_val = &(upd_field->new_val);
|
new_val = &(upd_field->new_val);
|
||||||
ut_ad(!dfield_is_ext(new_val) ==
|
ut_ad(!dfield_is_ext(new_val) ==
|
||||||
!rec_offs_nth_extern(offsets, upd_field->field_no));
|
!rec_offs_nth_extern(offsets, upd_field->field_no));
|
||||||
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
|
if (dfield_is_ext(new_val)) {
|
||||||
|
ulint len;
|
||||||
|
field_ref = rec_get_nth_field(rec, offsets, i, &len);
|
||||||
|
ut_a(len != UNIV_SQL_NULL);
|
||||||
|
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||||
|
field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
|
||||||
|
|
||||||
|
b.ref_page_no = page_get_page_no(page_align(rec));
|
||||||
|
b.ref_heap_no = page_rec_get_heap_no(rec);
|
||||||
|
b.ref_field_no = i;
|
||||||
|
b.blob_page_no = mach_read_from_4(
|
||||||
|
field_ref + BTR_EXTERN_PAGE_NO);
|
||||||
|
ut_a(b.ref_field_no >= index->n_uniq);
|
||||||
|
btr_blob_dbg_rbt_delete(index, &b, "upd_in_place");
|
||||||
|
}
|
||||||
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
|
|
||||||
rec_set_nth_field(rec, offsets, upd_field->field_no,
|
rec_set_nth_field(rec, offsets, upd_field->field_no,
|
||||||
dfield_get_data(new_val),
|
dfield_get_data(new_val),
|
||||||
dfield_get_len(new_val));
|
dfield_get_len(new_val));
|
||||||
|
|
||||||
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
|
if (dfield_is_ext(new_val)) {
|
||||||
|
b.blob_page_no = mach_read_from_4(
|
||||||
|
field_ref + BTR_EXTERN_PAGE_NO);
|
||||||
|
b.always_owner = b.owner = !(field_ref[BTR_EXTERN_LEN]
|
||||||
|
& BTR_EXTERN_OWNER_FLAG);
|
||||||
|
b.del = rec_get_deleted_flag(
|
||||||
|
rec, rec_offs_comp(offsets));
|
||||||
|
|
||||||
|
btr_blob_dbg_rbt_insert(index, &b, "upd_in_place");
|
||||||
|
}
|
||||||
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||||
|
@ -1061,6 +1061,12 @@ innobase_start_or_create_for_mysql(void)
|
|||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: !!!!!!!! UNIV_BLOB_DEBUG switched on !!!!!!!!!\n"
|
||||||
|
"InnoDB: Server restart may fail with UNIV_BLOB_DEBUG\n");
|
||||||
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
|
|
||||||
#ifdef UNIV_SYNC_DEBUG
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: !!!!!!!! UNIV_SYNC_DEBUG switched on !!!!!!!!!\n");
|
"InnoDB: !!!!!!!! UNIV_SYNC_DEBUG switched on !!!!!!!!!\n");
|
||||||
|
@ -260,6 +260,9 @@ rw_lock_create_func(
|
|||||||
contains garbage at initialization and cannot be used for
|
contains garbage at initialization and cannot be used for
|
||||||
recursive x-locking. */
|
recursive x-locking. */
|
||||||
lock->recursive = FALSE;
|
lock->recursive = FALSE;
|
||||||
|
/* Silence Valgrind when UNIV_DEBUG_VALGRIND is not enabled. */
|
||||||
|
memset((void*) &lock->writer_thread, 0, sizeof lock->writer_thread);
|
||||||
|
UNIV_MEM_INVALID(&lock->writer_thread, sizeof lock->writer_thread);
|
||||||
|
|
||||||
#ifdef UNIV_SYNC_DEBUG
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
UT_LIST_INIT(lock->debug_list);
|
UT_LIST_INIT(lock->debug_list);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user