Commit 34212233 authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.4 into 10.5

parents a569dc55 cf9b3b25
...@@ -15,7 +15,13 @@ INSERT INTO t1 VALUES (2); ...@@ -15,7 +15,13 @@ INSERT INTO t1 VALUES (2);
INSERT INTO t1 VALUES (3); INSERT INTO t1 VALUES (3);
INSERT INTO t1 VALUES (4); INSERT INTO t1 VALUES (4);
INSERT INTO t1 VALUES (5); INSERT INTO t1 VALUES (5);
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1a;
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2a;
connection node_2; connection node_2;
ROLLBACK; ROLLBACK;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
DROP TABLE t1; DROP TABLE t1;
disconnect node_1a;
disconnect node_2a;
...@@ -17,17 +17,25 @@ SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; ...@@ -17,17 +17,25 @@ SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT COUNT(*) AS EXPECT_0 FROM t1; SELECT COUNT(*) AS EXPECT_0 FROM t1;
EXPECT_0 EXPECT_0
0 0
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
EXPECT_0
0
INSERT INTO t1 SELECT 1 FROM ten AS t1, ten AS t2, ten AS t3; INSERT INTO t1 SELECT 1 FROM ten AS t1, ten AS t2, ten AS t3;
SELECT COUNT(*) AS EXPECT_1000 FROM t1; SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000 EXPECT_1000
1000 1000
connection node_1a; connection node_1;
SET GLOBAL wsrep_sync_wait=15; SET GLOBAL wsrep_sync_wait=15;
SELECT COUNT(*) AS EXPECT_1000 FROM t1; SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000 EXPECT_1000
1000 1000
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
EXPECT_0
0
connection node_2;
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
EXPECT_0
0
connection node_1;
DROP TABLE t1; DROP TABLE t1;
DROP TABLE ten; DROP TABLE ten;
...@@ -2,9 +2,9 @@ connection node_2; ...@@ -2,9 +2,9 @@ connection node_2;
connection node_1; connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2; connection node_2;
SELECT COUNT(*) = 0 FROM t1; SELECT COUNT(*) AS EXPECT_0 FROM t1;
COUNT(*) = 0 EXPECT_0
1 0
connection node_1; connection node_1;
CREATE TABLE t2 (f1 INTEGER); CREATE TABLE t2 (f1 INTEGER);
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
...@@ -39,16 +39,16 @@ INSERT INTO t1 VALUES (13); ...@@ -39,16 +39,16 @@ INSERT INTO t1 VALUES (13);
INSERT INTO t1 VALUES (14); INSERT INTO t1 VALUES (14);
INSERT INTO t1 VALUES (15); INSERT INTO t1 VALUES (15);
COMMIT; COMMIT;
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
COUNT(*) = 0 EXPECT_0
1 0
connection node_2; connection node_2;
SELECT COUNT(*) = 15 FROM t1; SELECT COUNT(*) AS EXPECT_15 FROM t1;
COUNT(*) = 15 EXPECT_15
1 15
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
COUNT(*) = 0 EXPECT_0
1 0
connection node_1; connection node_1;
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
...@@ -22,8 +22,21 @@ INSERT INTO t1 VALUES (3); ...@@ -22,8 +22,21 @@ INSERT INTO t1 VALUES (3);
INSERT INTO t1 VALUES (4); INSERT INTO t1 VALUES (4);
INSERT INTO t1 VALUES (5); INSERT INTO t1 VALUES (5);
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
--connection node_1a
--let $wait_condition = SELECT COUNT(*) = 5 FROM mysql.wsrep_streaming_log
--source include/wait_condition.inc
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--connection node_2a
--let $wait_condition = SELECT COUNT(*) = 5 FROM mysql.wsrep_streaming_log
--source include/wait_condition.inc
--connection node_2 --connection node_2
--error ER_LOCK_DEADLOCK --error ER_LOCK_DEADLOCK
ROLLBACK; ROLLBACK;
DROP TABLE t1; DROP TABLE t1;
\ No newline at end of file
--disconnect node_1a
--disconnect node_2a
...@@ -33,18 +33,27 @@ SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; ...@@ -33,18 +33,27 @@ SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
# Confirm that the kill caused the updates made so far to be removed # Confirm that the kill caused the updates made so far to be removed
--connection node_2 --connection node_2
--let $wait_condition = SELECT COUNT(*) = 0 FROM t1
--source include/wait_condition.inc
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT COUNT(*) AS EXPECT_0 FROM t1; SELECT COUNT(*) AS EXPECT_0 FROM t1;
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
# Confirm that the transaction can be reissued in its entirety on the slave without a conflict # Confirm that the transaction can be reissued in its entirety on the slave without a conflict
INSERT INTO t1 SELECT 1 FROM ten AS t1, ten AS t2, ten AS t3; INSERT INTO t1 SELECT 1 FROM ten AS t1, ten AS t2, ten AS t3;
SELECT COUNT(*) AS EXPECT_1000 FROM t1; SELECT COUNT(*) AS EXPECT_1000 FROM t1;
--connection node_1a --connection node_1
SET GLOBAL wsrep_sync_wait=15; SET GLOBAL wsrep_sync_wait=15;
--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1;
--source include/wait_condition.inc
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
--connection node_2
SELECT COUNT(*) AS EXPECT_1000 FROM t1; SELECT COUNT(*) AS EXPECT_1000 FROM t1;
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
--connection node_1
DROP TABLE t1; DROP TABLE t1;
DROP TABLE ten; DROP TABLE ten;
...@@ -13,12 +13,17 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; ...@@ -13,12 +13,17 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
# Block node #2's applier before table t1's inserts have come into play # Block node #2's applier before table t1's inserts have come into play
--connection node_2 --connection node_2
SELECT COUNT(*) = 0 FROM t1; --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'
--source include/wait_condition.inc
SELECT COUNT(*) AS EXPECT_0 FROM t1;
--connection node_1 --connection node_1
CREATE TABLE t2 (f1 INTEGER); CREATE TABLE t2 (f1 INTEGER);
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 --connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'
--source include/wait_condition.inc
LOCK TABLE t2 WRITE; LOCK TABLE t2 WRITE;
--connection node_1 --connection node_1
...@@ -39,11 +44,8 @@ INSERT INTO t1 VALUES (3); ...@@ -39,11 +44,8 @@ INSERT INTO t1 VALUES (3);
INSERT INTO t1 VALUES (4); INSERT INTO t1 VALUES (4);
INSERT INTO t1 VALUES (5); INSERT INTO t1 VALUES (5);
--sleep 2
--connection node_2 --connection node_2
--source include/kill_galera.inc --source include/kill_galera.inc
--sleep 1
--connection node_1 --connection node_1
INSERT INTO t1 VALUES (6); INSERT INTO t1 VALUES (6);
...@@ -54,8 +56,6 @@ INSERT INTO t1 VALUES (10); ...@@ -54,8 +56,6 @@ INSERT INTO t1 VALUES (10);
--connection node_2 --connection node_2
--source include/start_mysqld.inc --source include/start_mysqld.inc
--sleep 1
--source include/wait_until_connected_again.inc --source include/wait_until_connected_again.inc
--source include/galera_wait_ready.inc --source include/galera_wait_ready.inc
...@@ -67,12 +67,17 @@ INSERT INTO t1 VALUES (14); ...@@ -67,12 +67,17 @@ INSERT INTO t1 VALUES (14);
INSERT INTO t1 VALUES (15); INSERT INTO t1 VALUES (15);
COMMIT; COMMIT;
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; --let $wait_condition = SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log
--source include/wait_condition.inc
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
--connection node_2 --connection node_2
--sleep 5 --let $wait_condition = SELECT COUNT(*) = 15 FROM t1
SELECT COUNT(*) = 15 FROM t1; --source include/wait_condition.inc
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log;
SELECT COUNT(*) AS EXPECT_15 FROM t1;
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
--connection node_1 --connection node_1
......
...@@ -736,6 +736,17 @@ t2 CREATE TABLE `t2` ( ...@@ -736,6 +736,17 @@ t2 CREATE TABLE `t2` (
CREATE TABLE t2 (f1 INT NOT NULL)ENGINE=InnoDB; CREATE TABLE t2 (f1 INT NOT NULL)ENGINE=InnoDB;
ERROR 42S01: Table 't2' already exists ERROR 42S01: Table 't2' already exists
DROP TABLE t2, t1; DROP TABLE t2, t1;
#
# MDEV-23685 SIGSEGV on ADD FOREIGN KEY after failed attempt
# to create unique key on virtual column
#
CREATE TABLE t1 (pk INT PRIMARY KEY, a INT, b INT AS (a)) ENGINE=InnODB;
INSERT INTO t1 (pk,a) VALUES (1,10),(2,10);
ALTER TABLE t1 ADD UNIQUE INDEX ind9 (b), LOCK=SHARED;
ERROR 23000: Duplicate entry '10' for key 'ind9'
SET FOREIGN_KEY_CHECKS= 0;
ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (pk);
DROP TABLE t1;
# End of 10.2 tests # End of 10.2 tests
CREATE TABLE t1 (a GEOMETRY, INDEX(a(8)), CREATE TABLE t1 (a GEOMETRY, INDEX(a(8)),
FOREIGN KEY (a) REFERENCES x (xx)) ENGINE=InnoDB; FOREIGN KEY (a) REFERENCES x (xx)) ENGINE=InnoDB;
......
...@@ -720,6 +720,19 @@ SHOW CREATE TABLE t2; ...@@ -720,6 +720,19 @@ SHOW CREATE TABLE t2;
CREATE TABLE t2 (f1 INT NOT NULL)ENGINE=InnoDB; CREATE TABLE t2 (f1 INT NOT NULL)ENGINE=InnoDB;
DROP TABLE t2, t1; DROP TABLE t2, t1;
--echo #
--echo # MDEV-23685 SIGSEGV on ADD FOREIGN KEY after failed attempt
--echo # to create unique key on virtual column
--echo #
CREATE TABLE t1 (pk INT PRIMARY KEY, a INT, b INT AS (a)) ENGINE=InnODB;
INSERT INTO t1 (pk,a) VALUES (1,10),(2,10);
--error ER_DUP_ENTRY
ALTER TABLE t1 ADD UNIQUE INDEX ind9 (b), LOCK=SHARED;
SET FOREIGN_KEY_CHECKS= 0;
ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (pk);
DROP TABLE t1;
--echo # End of 10.2 tests --echo # End of 10.2 tests
# MDEV-21792 Server aborts upon attempt to create foreign key on spatial field # MDEV-21792 Server aborts upon attempt to create foreign key on spatial field
......
...@@ -1025,8 +1025,7 @@ btr_create( ...@@ -1025,8 +1025,7 @@ btr_create(
if (UNIV_UNLIKELY(type & DICT_IBUF)) { if (UNIV_UNLIKELY(type & DICT_IBUF)) {
/* Allocate first the ibuf header page */ /* Allocate first the ibuf header page */
buf_block_t* ibuf_hdr_block = fseg_create( buf_block_t* ibuf_hdr_block = fseg_create(
space, 0, space, IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr);
IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr);
if (ibuf_hdr_block == NULL) { if (ibuf_hdr_block == NULL) {
return(FIL_NULL); return(FIL_NULL);
...@@ -1056,8 +1055,8 @@ btr_create( ...@@ -1056,8 +1055,8 @@ btr_create(
flst_init(block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr); flst_init(block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr);
} else { } else {
block = fseg_create(space, 0, block = fseg_create(space, PAGE_HEADER + PAGE_BTR_SEG_TOP,
PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr); mtr);
if (block == NULL) { if (block == NULL) {
return(FIL_NULL); return(FIL_NULL);
...@@ -1065,8 +1064,8 @@ btr_create( ...@@ -1065,8 +1064,8 @@ btr_create(
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW); buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
if (!fseg_create(space, block->page.id().page_no(), if (!fseg_create(space, PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr,
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) { false, block)) {
/* Not enough space for new segment, free root /* Not enough space for new segment, free root
segment before return. */ segment before return. */
btr_free_root(block, mtr); btr_free_root(block, mtr);
......
...@@ -3823,6 +3823,7 @@ buf_page_create(fil_space_t *space, uint32_t offset, ...@@ -3823,6 +3823,7 @@ buf_page_create(fil_space_t *space, uint32_t offset,
ut_ad(page_id.space() != 0 || !zip_size); ut_ad(page_id.space() != 0 || !zip_size);
space->free_page(offset, false); space->free_page(offset, false);
loop:
buf_block_t *free_block= buf_LRU_get_free_block(false); buf_block_t *free_block= buf_LRU_get_free_block(false);
free_block->initialise(page_id, zip_size, 1); free_block->initialise(page_id, zip_size, 1);
...@@ -3837,35 +3838,71 @@ buf_page_create(fil_space_t *space, uint32_t offset, ...@@ -3837,35 +3838,71 @@ buf_page_create(fil_space_t *space, uint32_t offset,
!buf_pool.watch_is_sentinel(block->page)) !buf_pool.watch_is_sentinel(block->page))
{ {
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
const bool drop_hash_entry= block->page.state() == BUF_BLOCK_FILE_PAGE && const dict_index_t *drop_hash_entry= nullptr;
UNIV_LIKELY_NULL(block->index); #endif
if (UNIV_UNLIKELY(drop_hash_entry)) switch (block->page.state()) {
default:
ut_ad(0);
break;
case BUF_BLOCK_FILE_PAGE:
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
{
const auto num_fix_count= mtr->get_fix_count(block) + 1;
while (block->page.io_fix() != BUF_IO_NONE ||
num_fix_count != block->page.buf_fix_count())
{
mutex_exit(&buf_pool.mutex);
os_thread_yield();
mutex_enter(&buf_pool.mutex);
}
}
rw_lock_x_lock(&block->lock); rw_lock_x_lock(&block->lock);
#endif /* BTR_CUR_HASH_ADAPT */ #ifdef BTR_CUR_HASH_ADAPT
drop_hash_entry= block->index;
#endif
buf_LRU_block_free_non_file_page(free_block);
break;
case BUF_BLOCK_ZIP_PAGE:
page_hash_latch *hash_lock= buf_pool.page_hash.lock_get(fold);
hash_lock->write_lock();
if (block->page.io_fix() != BUF_IO_NONE)
{
hash_lock->write_unlock();
buf_LRU_block_free_non_file_page(block);
mutex_exit(&buf_pool.mutex);
goto loop;
}
rw_lock_x_lock(&free_block->lock);
buf_relocate(&block->page, &free_block->page);
if (block->page.oldest_modification() > 0)
buf_flush_relocate_on_flush_list(&block->page, &free_block->page);
#ifdef UNIV_DEBUG
else
UT_LIST_REMOVE(buf_pool.zip_clean, &block->page);
#endif
free_block->page.set_state(BUF_BLOCK_FILE_PAGE);
free_block->lock_hash_val= lock_rec_hash(
page_id.space(), page_id.page_no());
buf_unzip_LRU_add_block(free_block, FALSE);
hash_lock->write_unlock();
buf_page_free_descriptor(&block->page);
block= free_block;
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
break;
}
/* Page can be found in buf_pool */
buf_LRU_block_free_non_file_page(free_block);
mutex_exit(&buf_pool.mutex); mutex_exit(&buf_pool.mutex);
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
if (UNIV_UNLIKELY(drop_hash_entry)) if (drop_hash_entry)
{
btr_search_drop_page_hash_index(block); btr_search_drop_page_hash_index(block);
rw_lock_x_unlock(&block->lock);
}
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
if (!recv_recovery_is_on()) mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
/* FIXME: Remove the redundant lookup and avoid
the unnecessary invocation of buf_zip_decompress().
We may have to convert buf_page_t to buf_block_t,
but we are going to initialize the page. */
return buf_page_get_gen(page_id, zip_size, RW_NO_LATCH,
block, BUF_GET_POSSIBLY_FREED,
__FILE__, __LINE__, mtr);
mutex_exit(&recv_sys.mutex);
block= buf_page_get_with_no_latch(page_id, zip_size, mtr);
mutex_enter(&recv_sys.mutex);
return block; return block;
} }
...@@ -3889,13 +3926,13 @@ buf_page_create(fil_space_t *space, uint32_t offset, ...@@ -3889,13 +3926,13 @@ buf_page_create(fil_space_t *space, uint32_t offset,
ut_d(block->page.in_page_hash= true); ut_d(block->page.in_page_hash= true);
HASH_INSERT(buf_page_t, hash, &buf_pool.page_hash, fold, &block->page); HASH_INSERT(buf_page_t, hash, &buf_pool.page_hash, fold, &block->page);
rw_lock_x_lock(&block->lock);
if (UNIV_UNLIKELY(zip_size)) if (UNIV_UNLIKELY(zip_size))
{ {
/* Prevent race conditions during buf_buddy_alloc(), which may /* Prevent race conditions during buf_buddy_alloc(), which may
release and reacquire buf_pool.mutex, by IO-fixing and X-latching release and reacquire buf_pool.mutex, by IO-fixing and X-latching
the block. */ the block. */
block->page.set_io_fix(BUF_IO_READ); block->page.set_io_fix(BUF_IO_READ);
rw_lock_x_lock(&block->lock);
hash_lock->write_unlock(); hash_lock->write_unlock();
/* buf_pool.mutex may be released and reacquired by /* buf_pool.mutex may be released and reacquired by
...@@ -3911,14 +3948,13 @@ buf_page_create(fil_space_t *space, uint32_t offset, ...@@ -3911,14 +3948,13 @@ buf_page_create(fil_space_t *space, uint32_t offset,
buf_unzip_LRU_add_block(block, FALSE); buf_unzip_LRU_add_block(block, FALSE);
block->page.set_io_fix(BUF_IO_NONE); block->page.set_io_fix(BUF_IO_NONE);
rw_lock_x_unlock(&block->lock);
} }
else else
hash_lock->write_unlock(); hash_lock->write_unlock();
mutex_exit(&buf_pool.mutex); mutex_exit(&buf_pool.mutex);
mtr->memo_push(block, MTR_MEMO_BUF_FIX); mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX);
block->page.set_accessed(); block->page.set_accessed();
buf_pool.stat.n_pages_created++; buf_pool.stat.n_pages_created++;
......
...@@ -166,9 +166,9 @@ buf_dblwr_create() ...@@ -166,9 +166,9 @@ buf_dblwr_create()
} }
} }
block2 = fseg_create(fil_system.sys_space, TRX_SYS_PAGE_NO, block2 = fseg_create(fil_system.sys_space,
TRX_SYS_DOUBLEWRITE TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG,
+ TRX_SYS_DOUBLEWRITE_FSEG, &mtr); &mtr, false, trx_sys_block);
if (block2 == NULL) { if (block2 == NULL) {
too_small: too_small:
......
...@@ -134,7 +134,7 @@ dict_hdr_create( ...@@ -134,7 +134,7 @@ dict_hdr_create(
/* Create the dictionary header file block in a new, allocated file /* Create the dictionary header file block in a new, allocated file
segment in the system tablespace */ segment in the system tablespace */
block = fseg_create(fil_system.sys_space, 0, block = fseg_create(fil_system.sys_space,
DICT_HDR + DICT_HDR_FSEG_HEADER, mtr); DICT_HDR + DICT_HDR_FSEG_HEADER, mtr);
ut_a(block->page.id() == page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO)); ut_a(block->page.id() == page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO));
......
...@@ -5027,7 +5027,11 @@ dict_foreign_qualify_index( ...@@ -5027,7 +5027,11 @@ dict_foreign_qualify_index(
return(false); return(false);
} }
if (index->type & (DICT_SPATIAL | DICT_FTS)) { if (index->type & (DICT_SPATIAL | DICT_FTS | DICT_CORRUPT)) {
return false;
}
if (index->online_status >= ONLINE_INDEX_ABORTED) {
return false; return false;
} }
......
This diff is collapsed.
...@@ -362,26 +362,18 @@ fsp_header_init_fields( ...@@ -362,26 +362,18 @@ fsp_header_init_fields(
void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr) void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr)
MY_ATTRIBUTE((nonnull)); MY_ATTRIBUTE((nonnull));
/**********************************************************************//** /** Create a new segment.
Creates a new segment. @param space tablespace
@return the block where the segment header is placed, x-latched, NULL @param byte_offset byte offset of the created segment header
if could not create segment because of lack of space */ @param mtr mini-transaction
@param has_done_reservation whether fsp_reserve_free_extents() was invoked
@param block block where segment header is placed,
or NULL to allocate an additional page for that
@return the block where the segment header is placed, x-latched
@retval NULL if could not create segment because of lack of space */
buf_block_t* buf_block_t*
fseg_create( fseg_create(fil_space_t *space, ulint byte_offset, mtr_t *mtr,
fil_space_t* space, /*!< in,out: tablespace */ bool has_done_reservation= false, buf_block_t *block= NULL);
ulint page, /*!< in: page where the segment header is placed: if
this is != 0, the page must belong to another segment,
if this is 0, a new page will be allocated and it
will belong to the created segment */
ulint byte_offset, /*!< in: byte offset of the created segment header
on the page */
mtr_t* mtr,
bool has_done_reservation = false); /*!< in: whether the caller
has already done the reservation for the pages with
fsp_reserve_free_extents (at least 2 extents: one for
the inode and the other for the segment) then there is
no need to do the check for this individual
operation */
/** Calculate the number of pages reserved by a segment, /** Calculate the number of pages reserved by a segment,
and how many pages are currently used. and how many pages are currently used.
......
...@@ -591,6 +591,11 @@ struct mtr_t { ...@@ -591,6 +591,11 @@ struct mtr_t {
m_freed_pages->add_value(id.page_no()); m_freed_pages->add_value(id.page_no());
} }
/** Determine the added buffer fix count of a block.
@param block block to be checked
@return number of buffer count added by this mtr */
uint32_t get_fix_count(const buf_block_t *block) const;
private: private:
/** Log a write of a byte string to a page. /** Log a write of a byte string to a page.
@param block buffer page @param block buffer page
......
...@@ -2592,7 +2592,6 @@ inline buf_block_t *recv_sys_t::recover_low(const page_id_t page_id, ...@@ -2592,7 +2592,6 @@ inline buf_block_t *recv_sys_t::recover_low(const page_id_t page_id,
ut_ad(&recs == &p->second); ut_ad(&recs == &p->second);
i.created= true; i.created= true;
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
mtr.x_latch_at_savepoint(0, block);
recv_recover_page(block, mtr, p, space, &i); recv_recover_page(block, mtr, p, space, &i);
ut_ad(mtr.has_committed()); ut_ad(mtr.has_committed());
recs.log.clear(); recs.log.clear();
......
...@@ -702,6 +702,31 @@ inline lsn_t mtr_t::finish_write(ulint len) ...@@ -702,6 +702,31 @@ inline lsn_t mtr_t::finish_write(ulint len)
return start_lsn; return start_lsn;
} }
/** Find buffer fix count of the given block acquired by the
mini-transaction */
struct FindBlock
{
int32_t num_fix;
const buf_block_t *const block;
FindBlock(const buf_block_t *block_buf): num_fix(0), block(block_buf) {}
bool operator()(const mtr_memo_slot_t* slot)
{
if (slot->object == block)
num_fix++;
return true;
}
};
uint32_t mtr_t::get_fix_count(const buf_block_t *block) const
{
Iterate<FindBlock> iteration((FindBlock(block)));
if (m_memo.for_each_block(iteration))
return iteration.functor.num_fix;
return 0;
}
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/** Check if we are holding an rw-latch in this mini-transaction /** Check if we are holding an rw-latch in this mini-transaction
@param lock latch to search for @param lock latch to search for
......
...@@ -3178,20 +3178,46 @@ row_sel_build_prev_vers_for_mysql( ...@@ -3178,20 +3178,46 @@ row_sel_build_prev_vers_for_mysql(
return(err); return(err);
} }
/** Helper class to cache clust_rec and old_ver */ /** Helper class to cache clust_rec and old_vers */
class Row_sel_get_clust_rec_for_mysql class Row_sel_get_clust_rec_for_mysql
{ {
const rec_t *cached_clust_rec; const rec_t *cached_clust_rec;
rec_t *cached_old_vers; rec_t *cached_old_vers;
lsn_t cached_lsn;
page_id_t cached_page_id;
public: #ifdef UNIV_DEBUG
Row_sel_get_clust_rec_for_mysql() : void check_eq(const dict_index_t *index, const rec_offs *offsets) const
cached_clust_rec(NULL), cached_old_vers(NULL) {} {
rec_offs vers_offs[REC_OFFS_HEADER_SIZE + MAX_REF_PARTS];
rec_offs_init(vers_offs);
mem_heap_t *heap= nullptr;
ut_ad(rec_offs_validate(cached_clust_rec, index, offsets));
ut_ad(index->first_user_field() <= rec_offs_n_fields(offsets));
ut_ad(vers_offs == rec_get_offsets(cached_old_vers, index, vers_offs, true,
index->db_trx_id(), &heap));
ut_ad(!heap);
for (auto n= index->db_trx_id(); n--; )
{
const dict_col_t *col= dict_index_get_nth_col(index, n);
ulint len1, len2;
const byte *b1= rec_get_nth_field(cached_clust_rec, offsets, n, &len1);
const byte *b2= rec_get_nth_field(cached_old_vers, vers_offs, n, &len2);
ut_ad(!cmp_data_data(col->mtype, col->prtype, b1, len1, b2, len2));
}
}
#endif
dberr_t operator()(row_prebuilt_t *prebuilt, dict_index_t *sec_index, public:
const rec_t *rec, que_thr_t *thr, const rec_t **out_rec, Row_sel_get_clust_rec_for_mysql() :
rec_offs **offsets, mem_heap_t **offset_heap, cached_clust_rec(NULL), cached_old_vers(NULL), cached_lsn(0),
dtuple_t **vrow, mtr_t *mtr); cached_page_id(page_id_t(0,0)) {}
dberr_t operator()(row_prebuilt_t *prebuilt, dict_index_t *sec_index,
const rec_t *rec, que_thr_t *thr, const rec_t **out_rec,
rec_offs **offsets, mem_heap_t **offset_heap,
dtuple_t **vrow, mtr_t *mtr);
}; };
/*********************************************************************//** /*********************************************************************//**
...@@ -3391,8 +3417,15 @@ Row_sel_get_clust_rec_for_mysql::operator()( ...@@ -3391,8 +3417,15 @@ Row_sel_get_clust_rec_for_mysql::operator()(
&& !lock_clust_rec_cons_read_sees( && !lock_clust_rec_cons_read_sees(
clust_rec, clust_index, *offsets, clust_rec, clust_index, *offsets,
&trx->read_view)) { &trx->read_view)) {
const buf_page_t& bpage = btr_pcur_get_block(
prebuilt->clust_pcur)->page;
const lsn_t lsn = mach_read_from_8(
page_align(clust_rec) + FIL_PAGE_LSN);
if (clust_rec != cached_clust_rec) { if (lsn != cached_lsn
|| bpage.id() != cached_page_id
|| clust_rec != cached_clust_rec) {
/* The following call returns 'offsets' associated with /* The following call returns 'offsets' associated with
'old_vers' */ 'old_vers' */
err = row_sel_build_prev_vers_for_mysql( err = row_sel_build_prev_vers_for_mysql(
...@@ -3404,6 +3437,8 @@ Row_sel_get_clust_rec_for_mysql::operator()( ...@@ -3404,6 +3437,8 @@ Row_sel_get_clust_rec_for_mysql::operator()(
goto err_exit; goto err_exit;
} }
cached_lsn = lsn;
cached_page_id = bpage.id();
cached_clust_rec = clust_rec; cached_clust_rec = clust_rec;
cached_old_vers = old_vers; cached_old_vers = old_vers;
} else { } else {
...@@ -3414,7 +3449,8 @@ Row_sel_get_clust_rec_for_mysql::operator()( ...@@ -3414,7 +3449,8 @@ Row_sel_get_clust_rec_for_mysql::operator()(
version of clust_rec and its old version version of clust_rec and its old version
old_vers. Re-calculate the offsets for old_vers. */ old_vers. Re-calculate the offsets for old_vers. */
if (old_vers != NULL) { if (old_vers) {
ut_d(check_eq(clust_index, *offsets));
*offsets = rec_get_offsets( *offsets = rec_get_offsets(
old_vers, clust_index, *offsets, old_vers, clust_index, *offsets,
true, ULINT_UNDEFINED, offset_heap); true, ULINT_UNDEFINED, offset_heap);
......
...@@ -316,7 +316,7 @@ trx_rseg_header_create( ...@@ -316,7 +316,7 @@ trx_rseg_header_create(
ut_ad(!sys_header == (space == fil_system.temp_space)); ut_ad(!sys_header == (space == fil_system.temp_space));
/* Allocate a new file segment for the rollback segment */ /* Allocate a new file segment for the rollback segment */
block = fseg_create(space, 0, TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr); block = fseg_create(space, TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr);
if (block == NULL) { if (block == NULL) {
/* No space left */ /* No space left */
......
...@@ -158,7 +158,7 @@ trx_sysf_create( ...@@ -158,7 +158,7 @@ trx_sysf_create(
compile_time_assert(TRX_SYS_SPACE == 0); compile_time_assert(TRX_SYS_SPACE == 0);
/* Create the trx sys file block in a new allocated file segment */ /* Create the trx sys file block in a new allocated file segment */
block = fseg_create(fil_system.sys_space, 0, block = fseg_create(fil_system.sys_space,
TRX_SYS + TRX_SYS_FSEG_HEADER, TRX_SYS + TRX_SYS_FSEG_HEADER,
mtr); mtr);
buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER); buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
......
...@@ -383,7 +383,7 @@ trx_undo_seg_create(fil_space_t *space, buf_block_t *rseg_hdr, ulint *id, ...@@ -383,7 +383,7 @@ trx_undo_seg_create(fil_space_t *space, buf_block_t *rseg_hdr, ulint *id,
} }
/* Allocate a new file segment for the undo log */ /* Allocate a new file segment for the undo log */
block = fseg_create(space, 0, TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER, block = fseg_create(space, TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER,
mtr, true); mtr, true);
space->release_free_extents(n_reserved); space->release_free_extents(n_reserved);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment