Skip to content

Commit

Permalink
Merge 10.5 into 10.6
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-m committed Feb 27, 2023
2 parents db245e1 + 0de3be8 commit 3e2ad0e
Show file tree
Hide file tree
Showing 16 changed files with 201 additions and 214 deletions.
7 changes: 6 additions & 1 deletion mysql-test/suite/gcol/r/gcol_purge.result
@@ -1,7 +1,11 @@
SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET @save_dbug=@@GLOBAL.debug_dbug;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
CREATE TABLE t1(f1 INT NOT NULL, f2 int not null,
f3 int generated always as (f2 * 2) VIRTUAL,
primary key(f1), INDEX (f3))ENGINE=InnoDB;
connect con1,localhost,root,,,;
InnoDB 0 transactions not purged
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
INSERT INTO t1(f1, f2) VALUES(1,2);
Expand All @@ -18,5 +22,6 @@ commit;
disconnect con1;
disconnect con2;
connection default;
set global debug_dbug=default;
SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency;
SET GLOBAL debug_dbug=@save_dbug;
DROP TABLE t1;
8 changes: 7 additions & 1 deletion mysql-test/suite/gcol/t/gcol_purge.test
@@ -1,9 +1,14 @@
--source include/have_innodb.inc
--source include/have_debug.inc

SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET @save_dbug=@@GLOBAL.debug_dbug;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
CREATE TABLE t1(f1 INT NOT NULL, f2 int not null,
f3 int generated always as (f2 * 2) VIRTUAL,
primary key(f1), INDEX (f3))ENGINE=InnoDB;
connect(con1,localhost,root,,,);
--source ../innodb/include/wait_all_purged.inc
START TRANSACTION WITH CONSISTENT SNAPSHOT;

connection default;
Expand All @@ -26,5 +31,6 @@ commit;
disconnect con1;
disconnect con2;
connection default;
set global debug_dbug=default;
SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency;
SET GLOBAL debug_dbug=@save_dbug;
DROP TABLE t1;
4 changes: 4 additions & 0 deletions mysql-test/suite/innodb/r/cursor-restore-locking.result
@@ -1,4 +1,7 @@
SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB;
InnoDB 0 transactions not purged
connect prevent_purge,localhost,root,,;
start transaction with consistent snapshot;
connect con_del_1,localhost,root,,;
Expand Down Expand Up @@ -34,3 +37,4 @@ disconnect con_del_2;
connection default;
SET DEBUG_SYNC = 'RESET';
DROP TABLE t;
SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_freq;
5 changes: 5 additions & 0 deletions mysql-test/suite/innodb/r/dml_purge.result
Expand Up @@ -7,6 +7,7 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
CREATE TABLE t1(a INT PRIMARY KEY, b INT NOT NULL)
ROW_FORMAT=REDUNDANT ENGINE=InnoDB;
InnoDB 0 transactions not purged
connect prevent_purge,localhost,root;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
Expand All @@ -19,7 +20,11 @@ UPDATE t1 SET b=4 WHERE a=3;
disconnect prevent_purge;
connection default;
InnoDB 0 transactions not purged
connection con1;
ROLLBACK;
disconnect con1;
connection default;
InnoDB 0 transactions not purged
FLUSH TABLE t1 FOR EXPORT;
Clustered index root page contents:
N_RECS=3; LEVEL=0
Expand Down
1 change: 1 addition & 0 deletions mysql-test/suite/innodb/r/gap_lock_split.result
Expand Up @@ -3,6 +3,7 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
CREATE TABLE t1(id INT PRIMARY key, val VARCHAR(16000)) ENGINE=InnoDB;
INSERT INTO t1 (id,val) SELECT 2*seq,'x' FROM seq_0_to_1023;
connect con1,localhost,root,,;
InnoDB 0 transactions not purged
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
DELETE FROM t1 WHERE id=1788;
Expand Down
9 changes: 6 additions & 3 deletions mysql-test/suite/innodb/r/innodb_bug84958.result
Expand Up @@ -9,12 +9,10 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency= 1;
CREATE PROCEDURE insert_n(start int, end int)
BEGIN
DECLARE i INT DEFAULT start;
START TRANSACTION;
WHILE i <= end do
INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = i;
SET i = i + 1;
END WHILE;
COMMIT;
END~~
CREATE FUNCTION num_pages_get()
RETURNS INT
Expand All @@ -30,6 +28,7 @@ END~~
#
CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY(a,b), KEY (b,c))
ENGINE=InnoDB STATS_PERSISTENT=0;
InnoDB 0 transactions not purged
BEGIN;
SELECT * FROM t1;
a b c
Expand All @@ -38,20 +37,24 @@ a b c
#
connect con2, localhost, root,,;
connection con2;
BEGIN;
INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = NULL;
CALL insert_n(1, 50);;
connect con3, localhost, root,,;
connection con3;
BEGIN;
CALL insert_n(51, 100);;
connection con2;
COMMIT;
connection con3;
INSERT INTO t1 VALUES (1, 2, 1) ON DUPLICATE KEY UPDATE c = NULL;
COMMIT;
connection default;
#
# Connect to default and record how many pages were accessed
# when selecting the record using the secondary key.
#
InnoDB 4 transactions not purged
InnoDB 2 transactions not purged
SET @num_pages_1 = num_pages_get();
SELECT * FROM t1 force index (b);
a b c
Expand Down
4 changes: 4 additions & 0 deletions mysql-test/suite/innodb/t/cursor-restore-locking.test
Expand Up @@ -3,8 +3,11 @@
source include/have_debug.inc;
source include/have_debug_sync.inc;

SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB;

--source include/wait_all_purged.inc
--connect(prevent_purge,localhost,root,,)
start transaction with consistent snapshot;

Expand Down Expand Up @@ -80,4 +83,5 @@ INSERT INTO t VALUES(30, 20);

SET DEBUG_SYNC = 'RESET';
DROP TABLE t;
SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_freq;
--source include/wait_until_count_sessions.inc
6 changes: 6 additions & 0 deletions mysql-test/suite/innodb/t/dml_purge.test
Expand Up @@ -14,6 +14,7 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;

CREATE TABLE t1(a INT PRIMARY KEY, b INT NOT NULL)
ROW_FORMAT=REDUNDANT ENGINE=InnoDB;
--source include/wait_all_purged.inc

--connect (prevent_purge,localhost,root)
START TRANSACTION WITH CONSISTENT SNAPSHOT;
Expand All @@ -33,7 +34,12 @@ UPDATE t1 SET b=4 WHERE a=3;
# Initiate a full purge, which should reset the DB_TRX_ID except for a=3.
--source include/wait_all_purged.inc
# Initiate a ROLLBACK of the update, which should reset the DB_TRX_ID for a=3.
--connection con1
ROLLBACK;
--disconnect con1
--connection default
# Reset the DB_TRX_ID for the hidden ADD COLUMN metadata record.
--source include/wait_all_purged.inc

FLUSH TABLE t1 FOR EXPORT;
# The following is based on innodb.table_flags:
Expand Down
1 change: 1 addition & 0 deletions mysql-test/suite/innodb/t/gap_lock_split.test
Expand Up @@ -9,6 +9,7 @@ CREATE TABLE t1(id INT PRIMARY key, val VARCHAR(16000)) ENGINE=InnoDB;
INSERT INTO t1 (id,val) SELECT 2*seq,'x' FROM seq_0_to_1023;

connect(con1,localhost,root,,);
source include/wait_all_purged.inc;
# Prevent purge.
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
Expand Down
9 changes: 6 additions & 3 deletions mysql-test/suite/innodb/t/innodb_bug84958.test
Expand Up @@ -13,12 +13,10 @@ DELIMITER ~~;
CREATE PROCEDURE insert_n(start int, end int)
BEGIN
DECLARE i INT DEFAULT start;
START TRANSACTION;
WHILE i <= end do
INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = i;
SET i = i + 1;
END WHILE;
COMMIT;
END~~

CREATE FUNCTION num_pages_get()
Expand All @@ -37,6 +35,7 @@ DELIMITER ;~~
--echo #
CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY(a,b), KEY (b,c))
ENGINE=InnoDB STATS_PERSISTENT=0;
--source include/wait_all_purged.inc
BEGIN;
SELECT * FROM t1;

Expand All @@ -45,26 +44,30 @@ SELECT * FROM t1;
--echo #
connect (con2, localhost, root,,);
connection con2;
BEGIN;
INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = NULL;
--send CALL insert_n(1, 50);

connect (con3, localhost, root,,);
connection con3;
BEGIN;
--send CALL insert_n(51, 100);

connection con2;
reap;
COMMIT;
connection con3;
reap;
INSERT INTO t1 VALUES (1, 2, 1) ON DUPLICATE KEY UPDATE c = NULL;
COMMIT;

connection default;

--echo #
--echo # Connect to default and record how many pages were accessed
--echo # when selecting the record using the secondary key.
--echo #
--let $wait_all_purged=4
--let $wait_all_purged=2
--source include/wait_all_purged.inc
SET @num_pages_1 = num_pages_get();
SELECT * FROM t1 force index (b);
Expand Down
55 changes: 20 additions & 35 deletions storage/innobase/include/trx0rseg.h
Expand Up @@ -65,53 +65,44 @@ struct alignas(CPU_LEVEL1_DCACHE_LINESIZE) trx_rseg_t
/** length of the TRX_RSEG_HISTORY list (number of transactions) */
uint32_t history_size;

/** Last known transaction that has not been purged yet,
or 0 if everything has been purged. */
trx_id_t needs_purge;

private:
/** Reference counter to track rseg allocated transactions,
with SKIP and NEEDS_PURGE flags. */
/** Reference counter to track is_persistent() transactions,
with SKIP flag. */
std::atomic<uint32_t> ref;

/** Whether undo tablespace truncation is pending */
static constexpr uint32_t SKIP= 1;
/** Whether the log segment needs purge */
static constexpr uint32_t NEEDS_PURGE= 2;
/** Transaction reference count multiplier */
static constexpr uint32_t REF= 4;
static constexpr uint32_t REF= 2;

uint32_t ref_load() const { return ref.load(std::memory_order_relaxed); }

/** Set a bit in ref */
template<bool needs_purge> void ref_set()
/** Set the SKIP bit */
void ref_set_skip()
{
static_assert(SKIP == 1U << 0, "compatibility");
static_assert(NEEDS_PURGE == 1U << 1, "compatibility");
static_assert(SKIP == 1U, "compatibility");
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
if (needs_purge)
__asm__ __volatile__("lock btsl $1, %0" : "+m" (ref));
else
__asm__ __volatile__("lock btsl $0, %0" : "+m" (ref));
__asm__ __volatile__("lock btsl $0, %0" : "+m" (ref));
#elif defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
_interlockedbittestandset(reinterpret_cast<volatile long*>(&ref),
needs_purge);
_interlockedbittestandset(reinterpret_cast<volatile long*>(&ref), 0);
#else
ref.fetch_or(needs_purge ? NEEDS_PURGE : SKIP, std::memory_order_relaxed);
ref.fetch_or(SKIP, std::memory_order_relaxed);
#endif
}
/** Clear a bit in ref */
template<bool needs_purge> void ref_reset()
void ref_reset_skip()
{
static_assert(SKIP == 1U << 0, "compatibility");
static_assert(NEEDS_PURGE == 1U << 1, "compatibility");
static_assert(SKIP == 1U, "compatibility");
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
if (needs_purge)
__asm__ __volatile__("lock btrl $1, %0" : "+m" (ref));
else
__asm__ __volatile__("lock btrl $0, %0" : "+m" (ref));
__asm__ __volatile__("lock btrl $0, %0" : "+m" (ref));
#elif defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
_interlockedbittestandreset(reinterpret_cast<volatile long*>(&ref),
needs_purge);
_interlockedbittestandreset(reinterpret_cast<volatile long*>(&ref), 0);
#else
ref.fetch_and(needs_purge ? ~NEEDS_PURGE : ~SKIP,
std::memory_order_relaxed);
ref.fetch_and(~SKIP, std::memory_order_relaxed);
#endif
}

Expand All @@ -125,26 +116,20 @@ struct alignas(CPU_LEVEL1_DCACHE_LINESIZE) trx_rseg_t
void destroy();

/** Note that undo tablespace truncation was started. */
void set_skip_allocation() { ut_ad(is_persistent()); ref_set<false>(); }
void set_skip_allocation() { ut_ad(is_persistent()); ref_set_skip(); }
/** Note that undo tablespace truncation was completed. */
void clear_skip_allocation()
{
ut_ad(is_persistent());
#if defined DBUG_OFF
ref_reset<false>();
ref_reset_skip();
#else
ut_d(auto r=) ref.fetch_and(~SKIP, std::memory_order_relaxed);
ut_ad(r == SKIP);
#endif
}
/** Note that the rollback segment requires purge. */
void set_needs_purge() { ref_set<true>(); }
/** Note that the rollback segment will not require purge. */
void clear_needs_purge() { ref_reset<true>(); }
/** @return whether the segment is marked for undo truncation */
bool skip_allocation() const { return ref_load() & SKIP; }
/** @return whether the segment needs purge */
bool needs_purge() const { return ref_load() & NEEDS_PURGE; }
/** Increment the reference count */
void acquire()
{ ut_d(auto r=) ref.fetch_add(REF); ut_ad(!(r & SKIP)); }
Expand Down
6 changes: 3 additions & 3 deletions storage/innobase/include/trx0undo.h
Expand Up @@ -246,12 +246,10 @@ trx_undo_free_at_shutdown(trx_t *trx);
@param[in,out] rseg rollback segment
@param[in] id rollback segment slot
@param[in] page_no undo log segment page number
@param[in,out] max_trx_id the largest observed transaction ID
@return the undo log
@retval nullptr on error */
trx_undo_t *
trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no,
trx_id_t &max_trx_id);
trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no);

#endif /* !UNIV_INNOCHECKSUM */

Expand Down Expand Up @@ -493,6 +491,8 @@ or 0 if the transaction has not been committed */
/** Before MariaDB 10.3.1, when purge did not reset DB_TRX_ID of
surviving user records, this used to be called TRX_UNDO_DEL_MARKS.
This field is redundant; it is only being read by some debug assertions.
The value 1 indicates that purge needs to process the undo log segment.
The value 0 indicates that all of it has been processed, and
trx_purge_free_segment() has been invoked, so the log is not safe to access.
Expand Down

0 comments on commit 3e2ad0e

Please sign in to comment.