Merge 10.3 into 10.4

This commit is contained in:
Marko Mäkelä 2022-10-05 20:30:57 +03:00
commit 65d0c57c1a
46 changed files with 838 additions and 511 deletions

View File

@ -22,4 +22,3 @@ eval SET PASSWORD FOR testuser1@'$IPv6' = PASSWORD ('9876');
--replace_result ::1 localhost --replace_result ::1 localhost
SELECT USER(); SELECT USER();
eval DROP USER testuser1@'$IPv6'; eval DROP USER testuser1@'$IPv6';

View File

@ -1,3 +1,5 @@
--source include/no_valgrind_without_big.inc
# ==== Purpose ==== # ==== Purpose ====
# #
# Configure two servers to be replication master and slave. # Configure two servers to be replication master and slave.

View File

@ -1,3 +1,5 @@
--source include/no_valgrind_without_big.inc
# #
# Testing of slow log query options # Testing of slow log query options
# #

View File

@ -2,6 +2,7 @@
--source include/not_embedded.inc --source include/not_embedded.inc
--source include/mysql_upgrade_preparation.inc --source include/mysql_upgrade_preparation.inc
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/no_valgrind_without_big.inc
SET GLOBAL SQL_MODE=""; SET GLOBAL SQL_MODE="";
SET LOCAL SQL_MODE=""; SET LOCAL SQL_MODE="";

View File

@ -4,11 +4,31 @@
# It will create 'wsrep' schema and two tables in it: 'membeship' and 'status' # It will create 'wsrep' schema and two tables in it: 'membeship' and 'status'
# and fill them on every membership or node status change. # and fill them on every membership or node status change.
# #
# Edit parameters below to specify the address and login to server. # Edit parameters below to specify the address and login to server:
#
USER=root USER=root
PSWD=
#
# If these parameters are not set, then the values
# passed by the server are taken:
#
HOST=127.0.0.1 HOST=127.0.0.1
PORT=$NODE_MYPORT_1 PORT=$NODE_MYPORT_1
#
# Edit parameters below to specify SSL parameters:
#
ssl_key=
ssl_cert=
ssl_ca=
ssl_capath=
ssl_cipher=
ssl_crl=
ssl_crlpath=
ssl_verify_server_cert=0
#
# Client executable path:
#
CLIENT="$EXE_MYSQL"
SCHEMA="mtr_wsrep_notify" SCHEMA="mtr_wsrep_notify"
MEMB_TABLE="$SCHEMA.membership" MEMB_TABLE="$SCHEMA.membership"
@ -40,7 +60,7 @@ configuration_change()
local idx=0 local idx=0
for NODE in $(echo $MEMBERS | sed s/,/\ /g) for NODE in $(echo "$MEMBERS" | sed s/,/\ /g)
do do
echo "INSERT INTO $MEMB_TABLE VALUES ( $idx, " echo "INSERT INTO $MEMB_TABLE VALUES ( $idx, "
# Don't forget to properly quote string values # Don't forget to properly quote string values
@ -59,17 +79,44 @@ status_update()
echo "$BEGIN; UPDATE $STATUS_TABLE SET status='$STATUS'; $END;" echo "$BEGIN; UPDATE $STATUS_TABLE SET status='$STATUS'; $END;"
} }
trim_string()
{
if [ -n "${BASH_VERSION:-}" ]; then
local pattern="[![:space:]${2:-}]"
local x="${1#*$pattern}"
local z=${#1}
x=${#x}
if [ $x -ne $z ]; then
local y="${1%$pattern*}"
y=${#y}
x=$(( z-x-1 ))
y=$(( y-x+1 ))
printf '%s' "${1:$x:$y}"
else
printf ''
fi
else
local pattern="[[:space:]${2:-}]"
echo "$1" | sed -E "s/^$pattern+|$pattern+\$//g"
fi
}
COM=status_update # not a configuration change by default COM=status_update # not a configuration change by default
while [ $# -gt 0 ] STATUS=""
do CLUSTER_UUID=""
PRIMARY="0"
INDEX=""
MEMBERS=""
while [ $# -gt 0 ]; do
case $1 in case $1 in
--status) --status)
STATUS=$2 STATUS=$(trim_string "$2")
shift shift
;; ;;
--uuid) --uuid)
CLUSTER_UUID=$2 CLUSTER_UUID=$(trim_string "$2")
shift shift
;; ;;
--primary) --primary)
@ -78,22 +125,75 @@ do
shift shift
;; ;;
--index) --index)
INDEX=$2 INDEX=$(trim_string "$2")
shift shift
;; ;;
--members) --members)
MEMBERS=$2 MEMBERS=$(trim_string "$2")
shift shift
;; ;;
esac esac
shift shift
done done
case $STATUS in USER=$(trim_string "$USER")
"joined" | "donor" | "synced") PSWD=$(trim_string "$PSWD")
$COM | mysql -B -u$USER -h$HOST -P$PORT
;; HOST=$(trim_string "$HOST")
*) PORT=$(trim_string "$PORT")
exit 0
case "$HOST" in
\[*)
HOST="${HOST##\[}"
HOST=$(trim_string "${HOST%%\]}")
;; ;;
esac esac
if [ -z "$HOST" ]; then
HOST="${NOTIFY_HOST:-}"
fi
if [ -z "$PORT" ]; then
PORT="${NOTIFY_PORT:-}"
fi
ssl_key=$(trim_string "$ssl_key");
ssl_cert=$(trim_string "$ssl_cert");
ssl_ca=$(trim_string "$ssl_ca");
ssl_capath=$(trim_string "$ssl_capath");
ssl_cipher=$(trim_string "$ssl_cipher");
ssl_crl=$(trim_string "$ssl_crl");
ssl_crlpath=$(trim_string "$ssl_crlpath");
ssl_verify_server_cert=$(trim_string "$ssl_verify_server_cert");
SSL_PARAM=""
if [ -n "$ssl_key" -o -n "$ssl_cert" -o \
-n "$ssl_ca" -o -n "$ssl_capath" -o \
-n "$ssl_cipher" ]
then
SSL_PARAM=' --ssl'
[ -n "$ssl_key" ] && SSL_PARAM="$SSL_PARAM --ssl-key='$ssl_key'"
[ -n "$ssl_cert" ] && SSL_PARAM="$SSL_PARAM --ssl-cert='$ssl_cert'"
[ -n "$ssl_ca" ] && SSL_PARAM="$SSL_PARAM --ssl-ca='$ssl_ca'"
[ -n "$ssl_capath" ] && SSL_PARAM="$SSL_PARAM --ssl-capath='$ssl_capath'"
[ -n "$ssl_cipher" ] && SSL_PARAM="$SSL_PARAM --ssl-cipher='$ssl_cipher'"
[ -n "$ssl_crl" ] && SSL_PARAM="$SSL_PARAM --ssl-crl='$ssl_crl'"
[ -n "$ssl_crlpath" ] && SSL_PARAM="$SSL_PARAM --ssl-crlpath='$ssl_crlpath'"
if [ -n "$ssl_verify_server_cert" ]; then
if [ $ssl_verify_server_cert -ne 0 ]; then
SSL_PARAM+=' --ssl-verify-server-cert'
fi
fi
fi
case $STATUS in
"joined" | "donor" | "synced")
"$COM" | eval "$CLIENT" -B "-u'$USER'"${PSWD:+" -p'$PSWD'"}\
"-h'$HOST'" "-P$PORT"$SSL_PARAM
;;
*)
# The node might be shutting down
;;
esac
exit 0

View File

@ -0,0 +1,195 @@
#!/bin/sh -eu
# This is a simple example of wsrep notification script (wsrep_notify_cmd).
# It will create 'wsrep' schema and two tables in it: 'membeship' and 'status'
# and fill them on every membership or node status change.
#
# Edit parameters below to specify the address and login to server:
#
USER=root
PSWD=
#
# If these parameters are not set, then the values
# passed by the server are taken:
#
HOST=127.0.0.1
PORT=$NODE_MYPORT_1
#
# Edit parameters below to specify SSL parameters:
#
ssl_cert="$MYSQL_TEST_DIR/std_data/client-cert.pem"
ssl_key="$MYSQL_TEST_DIR/std_data/client-key.pem"
ssl_ca="$MYSQL_TEST_DIR/std_data/cacert.pem"
ssl_capath=
ssl_cipher=
ssl_crl=
ssl_crlpath=
ssl_verify_server_cert=0
#
# Client executable path:
#
CLIENT="$EXE_MYSQL"
SCHEMA="mtr_wsrep_notify"
MEMB_TABLE="$SCHEMA.membership"
STATUS_TABLE="$SCHEMA.status"
BEGIN="
SET wsrep_on=0;
CREATE SCHEMA IF NOT EXISTS $SCHEMA;
CREATE TABLE IF NOT EXISTS $MEMB_TABLE (
idx INT,
uuid CHAR(40), /* node UUID */
name VARCHAR(32), /* node name */
addr VARCHAR(256) /* node address */
) ENGINE=MEMORY;
CREATE TABLE IF NOT EXISTS $STATUS_TABLE (
size INT, /* component size */
idx INT, /* this node index */
status CHAR(16), /* this node status */
uuid CHAR(40), /* cluster UUID */
prim BOOLEAN /* if component is primary */
) ENGINE=MEMORY;
BEGIN;
"
END="COMMIT;"
configuration_change()
{
echo "$BEGIN;"
local idx=0
for NODE in $(echo "$MEMBERS" | sed s/,/\ /g)
do
echo "INSERT INTO $MEMB_TABLE VALUES ( $idx, "
# Don't forget to properly quote string values
echo "'$NODE'" | sed s/\\//\',\'/g
echo ");"
idx=$(( $idx + 1 ))
done
echo "INSERT INTO $STATUS_TABLE VALUES($idx, $INDEX, '$STATUS', '$CLUSTER_UUID', $PRIMARY);"
echo "$END"
}
status_update()
{
echo "SET wsrep_on=0; BEGIN; UPDATE $STATUS_TABLE SET status='$STATUS'; COMMIT;"
}
trim_string()
{
if [ -n "${BASH_VERSION:-}" ]; then
local pattern="[![:space:]${2:-}]"
local x="${1#*$pattern}"
local z=${#1}
x=${#x}
if [ $x -ne $z ]; then
local y="${1%$pattern*}"
y=${#y}
x=$(( z-x-1 ))
y=$(( y-x+1 ))
printf '%s' "${1:$x:$y}"
else
printf ''
fi
else
local pattern="[[:space:]${2:-}]"
echo "$1" | sed -E "s/^$pattern+|$pattern+\$//g"
fi
}
COM=status_update # not a configuration change by default
STATUS=""
CLUSTER_UUID=""
PRIMARY="0"
INDEX=""
MEMBERS=""
while [ $# -gt 0 ]; do
case $1 in
--status)
STATUS=$(trim_string "$2")
shift
;;
--uuid)
CLUSTER_UUID=$(trim_string "$2")
shift
;;
--primary)
[ "$2" = "yes" ] && PRIMARY="1" || PRIMARY="0"
COM=configuration_change
shift
;;
--index)
INDEX=$(trim_string "$2")
shift
;;
--members)
MEMBERS=$(trim_string "$2")
shift
;;
esac
shift
done
USER=$(trim_string "$USER")
PSWD=$(trim_string "$PSWD")
HOST=$(trim_string "$HOST")
PORT=$(trim_string "$PORT")
case "$HOST" in
\[*)
HOST="${HOST##\[}"
HOST=$(trim_string "${HOST%%\]}")
;;
esac
if [ -z "$HOST" ]; then
HOST="${NOTIFY_HOST:-}"
fi
if [ -z "$PORT" ]; then
PORT="${NOTIFY_PORT:-}"
fi
ssl_key=$(trim_string "$ssl_key");
ssl_cert=$(trim_string "$ssl_cert");
ssl_ca=$(trim_string "$ssl_ca");
ssl_capath=$(trim_string "$ssl_capath");
ssl_cipher=$(trim_string "$ssl_cipher");
ssl_crl=$(trim_string "$ssl_crl");
ssl_crlpath=$(trim_string "$ssl_crlpath");
ssl_verify_server_cert=$(trim_string "$ssl_verify_server_cert");
SSL_PARAM=""
if [ -n "$ssl_key" -o -n "$ssl_cert" -o \
-n "$ssl_ca" -o -n "$ssl_capath" -o \
-n "$ssl_cipher" ]
then
SSL_PARAM=' --ssl'
[ -n "$ssl_key" ] && SSL_PARAM="$SSL_PARAM --ssl-key='$ssl_key'"
[ -n "$ssl_cert" ] && SSL_PARAM="$SSL_PARAM --ssl-cert='$ssl_cert'"
[ -n "$ssl_ca" ] && SSL_PARAM="$SSL_PARAM --ssl-ca='$ssl_ca'"
[ -n "$ssl_capath" ] && SSL_PARAM="$SSL_PARAM --ssl-capath='$ssl_capath'"
[ -n "$ssl_cipher" ] && SSL_PARAM="$SSL_PARAM --ssl-cipher='$ssl_cipher'"
[ -n "$ssl_crl" ] && SSL_PARAM="$SSL_PARAM --ssl-crl='$ssl_crl'"
[ -n "$ssl_crlpath" ] && SSL_PARAM="$SSL_PARAM --ssl-crlpath='$ssl_crlpath'"
if [ -n "$ssl_verify_server_cert" ]; then
if [ $ssl_verify_server_cert -ne 0 ]; then
SSL_PARAM+=' --ssl-verify-server-cert'
fi
fi
fi
# Undefined means node is shutting down
if [ "$STATUS" != 'Undefined' ]; then
"$COM" | eval "$CLIENT" -B "-u'$USER'"${PSWD:+" -p'$PSWD'"}\
"-h'$HOST'" "-P$PORT"$SSL_PARAM
fi
exit 0

View File

@ -0,0 +1,11 @@
connection node_1;
SELECT COUNT(DISTINCT uuid) AS EXPECT_2 FROM mtr_wsrep_notify.membership;
EXPECT_2
2
SELECT MAX(size) AS EXPECT_2 FROM mtr_wsrep_notify.status;
EXPECT_2
2
SELECT COUNT(DISTINCT idx) AS EXPECT_2 FROM mtr_wsrep_notify.status;
EXPECT_2
2
DROP SCHEMA mtr_wsrep_notify;

View File

@ -0,0 +1 @@
--wsrep_notify_cmd=$MYSQL_TEST_DIR/std_data/wsrep_notify_ssl.sh --wsrep-sync-wait=0

View File

@ -0,0 +1,20 @@
!include ../galera_2nodes.cnf
[mysqld]
ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/server-cert.pem
ssl-key=@ENV.MYSQL_TEST_DIR/std_data/server-key.pem
ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem
bind-address=::
[mysqld.1]
wsrep_provider_options='base_port=@mysqld.1.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.1.#galera_port;ist.recv_addr=[::1]:@mysqld.1.#ist_port;gcache.size=1;pc.ignore_sb=true'
wsrep_node_incoming_address='[::1]:@mysqld.1.port'
wsrep_node_address=::1
wsrep_sst_receive_address='[::1]:@mysqld.1.#sst_port'
[mysqld.2]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port'
wsrep_provider_options='base_port=@mysqld.2.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.2.#galera_port;ist.recv_addr=[::1]:@mysqld.2.#ist_port;gcache.size=1;pc.ignore_sb=true'
wsrep_node_address=::1
wsrep_node_incoming_address='[::1]:@mysqld.2.port'
wsrep_sst_receive_address='[::1]:@mysqld.2.#sst_port'

View File

@ -0,0 +1,20 @@
#
# Test wsrep_notify_cmd. We use a version of the support-files/wsrep_notify.sh script that writes
# notifications into a table.
#
--source include/galera_cluster.inc
--source include/have_ssl_communication.inc
--source include/check_ipv6.inc
--source include/force_restart.inc
--connection node_1
--let $wait_condition = SELECT COUNT(DISTINCT uuid) = 2 FROM mtr_wsrep_notify.membership;
--source include/wait_condition.inc
SELECT COUNT(DISTINCT uuid) AS EXPECT_2 FROM mtr_wsrep_notify.membership;
SELECT MAX(size) AS EXPECT_2 FROM mtr_wsrep_notify.status;
SELECT COUNT(DISTINCT idx) AS EXPECT_2 FROM mtr_wsrep_notify.status;
# CLEANUP
DROP SCHEMA mtr_wsrep_notify;

View File

@ -148,10 +148,7 @@ lock table t write;
connection prevent_purge; connection prevent_purge;
commit; commit;
connection default; connection default;
InnoDB 0 transactions not purged
disconnect lock_table; disconnect lock_table;
start transaction with consistent snapshot;
commit;
InnoDB 0 transactions not purged InnoDB 0 transactions not purged
set global debug_dbug=@old_dbug; set global debug_dbug=@old_dbug;
drop table t; drop table t;

View File

@ -189,10 +189,7 @@ lock table t write;
connection prevent_purge; connection prevent_purge;
commit; commit;
connection default; connection default;
--source ../../innodb/include/wait_all_purged.inc
disconnect lock_table; disconnect lock_table;
start transaction with consistent snapshot;
commit;
--source ../../innodb/include/wait_all_purged.inc --source ../../innodb/include/wait_all_purged.inc
set global debug_dbug=@old_dbug; set global debug_dbug=@old_dbug;
drop table t; drop table t;

View File

@ -167,4 +167,19 @@ buffer_LRU_batch_evict_total_pages buffer
# FLUSH TABLES t1 FOR EXPORT; # FLUSH TABLES t1 FOR EXPORT;
# UNLOCK TABLES; # UNLOCK TABLES;
DROP TABLE t1; DROP TABLE t1;
#
# MDEV-29666 InnoDB fails to purge secondary index records
# when indexed virtual columns exist
#
CREATE TABLE t1 (a INT, b INT, a1 INT AS(a) VIRTUAL,
INDEX(a1),INDEX(b)) ENGINE=InnoDB;
INSERT INTO t1 SET a=1, b=1;
UPDATE t1 SET a=2, b=3;
InnoDB 0 transactions not purged
FLUSH TABLE t1 FOR EXPORT;
page 4: N_RECS=0x0001
page 5: N_RECS=0x0001
UNLOCK TABLES;
DROP TABLE t1;
# End of 10.3 tests
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;

View File

@ -1,5 +1,6 @@
--source include/not_embedded.inc --source include/not_embedded.inc
--source include/innodb_page_size.inc --source include/innodb_page_size.inc
--source include/no_valgrind_without_big.inc
--echo # --echo #
--echo # Bug#13955083 ALLOW IN-PLACE DDL OPERATIONS ON MISSING --echo # Bug#13955083 ALLOW IN-PLACE DDL OPERATIONS ON MISSING

View File

@ -5,6 +5,7 @@
--source include/not_embedded.inc --source include/not_embedded.inc
# The test is not big enough to use change buffering with larger page size. # The test is not big enough to use change buffering with larger page size.
--source include/have_innodb_max_16k.inc --source include/have_innodb_max_16k.inc
--source include/no_valgrind_without_big.inc
SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
--disable_query_log --disable_query_log

View File

@ -2,6 +2,8 @@
--source include/default_charset.inc --source include/default_charset.inc
# need to restart server # need to restart server
--source include/not_embedded.inc --source include/not_embedded.inc
--source include/no_valgrind_without_big.inc
CREATE SCHEMA `repro`; CREATE SCHEMA `repro`;
CREATE TABLE `repro`.`crew` ( CREATE TABLE `repro`.`crew` (

View File

@ -4,6 +4,7 @@
--source include/not_embedded.inc --source include/not_embedded.inc
#Windows has trouble creating files/directories with long names #Windows has trouble creating files/directories with long names
--source include/not_windows.inc --source include/not_windows.inc
--source include/no_valgrind_without_big.inc
--echo # --echo #
--echo # Bug#19419026 WHEN A TABLESPACE IS NOT FOUND, DO NOT REPORT "TABLE NOT FOUND" --echo # Bug#19419026 WHEN A TABLESPACE IS NOT FOUND, DO NOT REPORT "TABLE NOT FOUND"

View File

@ -149,4 +149,36 @@ WHERE NAME="buffer_LRU_batch_evict_total_pages" AND COUNT > 0;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-29666 InnoDB fails to purge secondary index records
--echo # when indexed virtual columns exist
--echo #
CREATE TABLE t1 (a INT, b INT, a1 INT AS(a) VIRTUAL,
INDEX(a1),INDEX(b)) ENGINE=InnoDB;
INSERT INTO t1 SET a=1, b=1;
UPDATE t1 SET a=2, b=3;
let DATADIR=`select @@datadir`;
let PAGE_SIZE=`select @@innodb_page_size`;
source include/wait_all_purged.inc;
FLUSH TABLE t1 FOR EXPORT;
perl;
my $ps = $ENV{PAGE_SIZE};
my $file = "$ENV{DATADIR}/test/t1.ibd";
open(FILE, "<", $file) or die "Unable to open $file\n";
die "Unable to read $file\n" unless
sysread(FILE, $_, 6*$ps) == 6*$ps;
close(FILE);
print "page 4: N_RECS=0x", unpack("H*", substr($_, 4 * $ps + 54, 2)), "\n";
print "page 5: N_RECS=0x", unpack("H*", substr($_, 5 * $ps + 54, 2)), "\n";
EOF
UNLOCK TABLES;
DROP TABLE t1;
--echo # End of 10.3 tests
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;

View File

@ -2,6 +2,12 @@
# Embedded server tests do not support restarting # Embedded server tests do not support restarting
--source include/not_embedded.inc --source include/not_embedded.inc
--source include/maybe_debug.inc --source include/maybe_debug.inc
# Slow shutdown may take more than 120 seconds under Valgrind,
# causing the server to be (silently) killed.
# Due to that, crash recovery could "heal" the damage that our
# Perl code is inflicting, and the SELECT statements could succeed
# instead of failing with ER_NO_SUCH_TABLE_IN_ENGINE.
--source include/not_valgrind.inc
--disable_query_log --disable_query_log
call mtr.add_suppression("InnoDB: Table `mysql`\\.`innodb_table_stats` not found"); call mtr.add_suppression("InnoDB: Table `mysql`\\.`innodb_table_stats` not found");

View File

@ -1,6 +1,7 @@
--source include/have_innodb.inc --source include/have_innodb.inc
# Embedded server does not support restarting. # Embedded server does not support restarting.
--source include/not_embedded.inc --source include/not_embedded.inc
--source include/no_valgrind_without_big.inc
# MDEV-8841 - close tables opened by previous tests, # MDEV-8841 - close tables opened by previous tests,
# so they don't get marked crashed when the server gets crashed # so they don't get marked crashed when the server gets crashed

View File

@ -1,4 +1,5 @@
--source include/have_debug.inc --source include/have_debug.inc
--source include/no_valgrind_without_big.inc
--echo ######## --echo ########
--echo # Test for generating "innodb_corrupted_pages" file during full and --echo # Test for generating "innodb_corrupted_pages" file during full and

View File

@ -1,6 +1,7 @@
--let $rpl_topology=1->2 --let $rpl_topology=1->2
--source include/rpl_init.inc --source include/rpl_init.inc
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/no_valgrind_without_big.inc
--echo *** Test normal shutdown/restart of slave server configured as a GTID slave. *** --echo *** Test normal shutdown/restart of slave server configured as a GTID slave. ***

View File

@ -1,6 +1,7 @@
--source include/have_innodb.inc --source include/have_innodb.inc
--let $rpl_topology=1->2 --let $rpl_topology=1->2
--source include/rpl_init.inc --source include/rpl_init.inc
--source include/no_valgrind_without_big.inc
--connection server_2 --connection server_2
call mtr.add_suppression("The automatically created table.*name may not be entirely in lowercase"); call mtr.add_suppression("The automatically created table.*name may not be entirely in lowercase");

View File

@ -5,6 +5,7 @@
-- source include/have_innodb.inc -- source include/have_innodb.inc
# include/restart_mysqld.inc does not work in embedded mode # include/restart_mysqld.inc does not work in embedded mode
-- source include/not_embedded.inc -- source include/not_embedded.inc
-- source include/no_valgrind_without_big.inc
# Check the default value # Check the default value
SET @orig = @@global.innodb_buffer_pool_dump_at_shutdown; SET @orig = @@global.innodb_buffer_pool_dump_at_shutdown;

View File

@ -1,6 +1,8 @@
--source include/have_innodb.inc --source include/have_innodb.inc
# Embedded server tests do not support restarting. # Embedded server tests do not support restarting.
--source include/not_embedded.inc --source include/not_embedded.inc
# InnoDB: Cannot read first page of './ibdata1' I/O error
--source include/not_valgrind.inc
call mtr.add_suppression("InnoDB: Failed to set .*DIRECT"); call mtr.add_suppression("InnoDB: Failed to set .*DIRECT");
--replace_result unbuffered fsync --replace_result unbuffered fsync

View File

@ -884,7 +884,7 @@ btr_page_get_father_node_ptr_func(
err = btr_cur_search_to_nth_level( err = btr_cur_search_to_nth_level(
index, level + 1, tuple, index, level + 1, tuple,
PAGE_CUR_LE, latch_mode, cursor, 0, PAGE_CUR_LE, latch_mode, cursor,
file, line, mtr); file, line, mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
@ -2450,7 +2450,7 @@ btr_insert_on_non_leaf_level_func(
dberr_t err = btr_cur_search_to_nth_level( dberr_t err = btr_cur_search_to_nth_level(
index, level, tuple, PAGE_CUR_LE, index, level, tuple, PAGE_CUR_LE,
BTR_CONT_MODIFY_TREE, BTR_CONT_MODIFY_TREE,
&cursor, 0, file, line, mtr); &cursor, file, line, mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
ib::warn() << " Error code: " << err ib::warn() << " Error code: " << err
@ -2471,7 +2471,7 @@ btr_insert_on_non_leaf_level_func(
btr_cur_search_to_nth_level(index, level, tuple, btr_cur_search_to_nth_level(index, level, tuple,
PAGE_CUR_RTREE_INSERT, PAGE_CUR_RTREE_INSERT,
BTR_CONT_MODIFY_TREE, BTR_CONT_MODIFY_TREE,
&cursor, 0, file, line, mtr); &cursor, file, line, mtr);
} }
ut_ad(cursor.flag == BTR_CUR_BINARY); ut_ad(cursor.flag == BTR_CUR_BINARY);

View File

@ -1237,38 +1237,36 @@ If mode is PAGE_CUR_GE, then up_match will a have a sensible value.
If mode is PAGE_CUR_LE , cursor is left at the place where an insert of the If mode is PAGE_CUR_LE , cursor is left at the place where an insert of the
search tuple should be performed in the B-tree. InnoDB does an insert search tuple should be performed in the B-tree. InnoDB does an insert
immediately after the cursor. Thus, the cursor may end up on a user record, immediately after the cursor. Thus, the cursor may end up on a user record,
or on a page infimum record. */ or on a page infimum record.
dberr_t @param index index
btr_cur_search_to_nth_level_func( @param level the tree level of search
dict_index_t* index, /*!< in: index */ @param tuple data tuple; NOTE: n_fields_cmp in tuple must be set so that
ulint level, /*!< in: the tree level of search */ it cannot get compared to the node ptr page number field!
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in @param mode PAGE_CUR_L, NOTE that if the search is made using a unique
tuple must be set so that it cannot get prefix of a record, mode should be PAGE_CUR_LE, not
compared to the node ptr page number field! */ PAGE_CUR_GE, as the latter may end up on the previous page of
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...; the record! Inserts should always be made using PAGE_CUR_LE
Inserts should always be made using to search the position!
PAGE_CUR_LE to search the position! */ @param latch_mode BTR_SEARCH_LEAF, ..., ORed with at most one of BTR_INSERT,
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ..., ORed with BTR_DELETE_MARK, BTR_DELETE, or BTR_ESTIMATE;
at most one of BTR_INSERT, BTR_DELETE_MARK, cursor->left_block is used to store a pointer to the left
BTR_DELETE, or BTR_ESTIMATE; neighbor page, in the cases BTR_SEARCH_PREV and
cursor->left_block is used to store a pointer BTR_MODIFY_PREV; NOTE that if ahi_latch, we might not have a
to the left neighbor page, in the cases cursor page latch, we assume that ahi_latch protects the
BTR_SEARCH_PREV and BTR_MODIFY_PREV; record!
NOTE that if ahi_latch, we might not have a @param cursor tree cursor; the cursor page is s- or x-latched, but see also
cursor page latch, we assume that ahi_latch above!
protects the record! */ @param file file name
btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is @param line line where called
s- or x-latched, but see also above! */ @param mtr mini-transaction
#ifdef BTR_CUR_HASH_ADAPT @param autoinc PAGE_ROOT_AUTO_INC to be written (0 if none)
rw_lock_t* ahi_latch, @return DB_SUCCESS on success or error code otherwise */
/*!< in: currently held btr_search_latch dberr_t btr_cur_search_to_nth_level(dict_index_t *index, ulint level,
(in RW_S_LATCH mode), or NULL */ const dtuple_t *tuple,
#endif /* BTR_CUR_HASH_ADAPT */ page_cur_mode_t mode, ulint latch_mode,
const char* file, /*!< in: file name */ btr_cur_t *cursor, const char *file,
unsigned line, /*!< in: line where called */ unsigned line, mtr_t *mtr,
mtr_t* mtr, /*!< in: mtr */ ib_uint64_t autoinc)
ib_uint64_t autoinc)/*!< in: PAGE_ROOT_AUTO_INC to be written
(0 if none) */
{ {
page_t* page = NULL; /* remove warning */ page_t* page = NULL; /* remove warning */
buf_block_t* block; buf_block_t* block;
@ -1436,15 +1434,14 @@ btr_cur_search_to_nth_level_func(
&& mode != PAGE_CUR_LE_OR_EXTENDS && mode != PAGE_CUR_LE_OR_EXTENDS
# endif /* PAGE_CUR_LE_OR_EXTENDS */ # endif /* PAGE_CUR_LE_OR_EXTENDS */
&& !dict_index_is_spatial(index) && !dict_index_is_spatial(index)
/* If !ahi_latch, we do a dirty read of /* We do a dirty read of
btr_search_enabled below, and btr_search_guess_on_hash() btr_search_enabled below, and btr_search_guess_on_hash()
will have to check it again. */ will have to check it again. */
&& btr_search_enabled && btr_search_enabled
&& !modify_external && !modify_external
&& !(tuple->info_bits & REC_INFO_MIN_REC_FLAG) && !(tuple->info_bits & REC_INFO_MIN_REC_FLAG)
&& btr_search_guess_on_hash(index, info, tuple, mode, && btr_search_guess_on_hash(index, info, tuple, mode,
latch_mode, cursor, latch_mode, cursor, mtr)) {
ahi_latch, mtr)) {
/* Search using the hash index succeeded */ /* Search using the hash index succeeded */
@ -1465,13 +1462,6 @@ btr_cur_search_to_nth_level_func(
/* If the hash search did not succeed, do binary search down the /* If the hash search did not succeed, do binary search down the
tree */ tree */
#ifdef BTR_CUR_HASH_ADAPT
if (ahi_latch) {
/* Release possible search latch to obey latching order */
rw_lock_s_unlock(ahi_latch);
}
#endif /* BTR_CUR_HASH_ADAPT */
/* Store the position of the tree latch we push to mtr so that we /* Store the position of the tree latch we push to mtr so that we
know how to release it when we have latched leaf node(s) */ know how to release it when we have latched leaf node(s) */
@ -2527,12 +2517,6 @@ func_exit:
cursor->rtr_info->mbr_adj = true; cursor->rtr_info->mbr_adj = true;
} }
#ifdef BTR_CUR_HASH_ADAPT
if (ahi_latch) {
rw_lock_s_lock(ahi_latch);
}
#endif /* BTR_CUR_HASH_ADAPT */
DBUG_RETURN(err); DBUG_RETURN(err);
} }
@ -6510,8 +6494,7 @@ btr_estimate_n_rows_in_range_low(
btr_cur_search_to_nth_level(index, 0, tuple1, mode1, btr_cur_search_to_nth_level(index, 0, tuple1, mode1,
BTR_SEARCH_LEAF | BTR_ESTIMATE, BTR_SEARCH_LEAF | BTR_ESTIMATE,
&cursor, 0, &cursor, __FILE__, __LINE__, &mtr);
__FILE__, __LINE__, &mtr);
ut_ad(!page_rec_is_infimum(btr_cur_get_rec(&cursor))); ut_ad(!page_rec_is_infimum(btr_cur_get_rec(&cursor)));
@ -6564,8 +6547,7 @@ btr_estimate_n_rows_in_range_low(
btr_cur_search_to_nth_level(index, 0, tuple2, mode2, btr_cur_search_to_nth_level(index, 0, tuple2, mode2,
BTR_SEARCH_LEAF | BTR_ESTIMATE, BTR_SEARCH_LEAF | BTR_ESTIMATE,
&cursor, 0, &cursor, __FILE__, __LINE__, &mtr);
__FILE__, __LINE__, &mtr);
const rec_t* rec = btr_cur_get_rec(&cursor); const rec_t* rec = btr_cur_get_rec(&cursor);

View File

@ -421,11 +421,7 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, const char *file,
} }
btr_pcur_open_with_no_init_func(index, tuple, mode, restore_latch_mode, btr_pcur_open_with_no_init_func(index, tuple, mode, restore_latch_mode,
this, this, file, line, mtr);
#ifdef BTR_CUR_HASH_ADAPT
NULL,
#endif /* BTR_CUR_HASH_ADAPT */
file, line, mtr);
/* Restore the old search mode */ /* Restore the old search mode */
search_mode = old_mode; search_mode = old_mode;

View File

@ -888,8 +888,6 @@ both have sensible values.
we assume the caller uses his search latch we assume the caller uses his search latch
to protect the record! to protect the record!
@param[out] cursor tree cursor @param[out] cursor tree cursor
@param[in] ahi_latch the adaptive hash index latch being held,
or NULL
@param[in] mtr mini transaction @param[in] mtr mini transaction
@return whether the search succeeded */ @return whether the search succeeded */
bool bool
@ -900,7 +898,6 @@ btr_search_guess_on_hash(
ulint mode, ulint mode,
ulint latch_mode, ulint latch_mode,
btr_cur_t* cursor, btr_cur_t* cursor,
rw_lock_t* ahi_latch,
mtr_t* mtr) mtr_t* mtr)
{ {
ulint fold; ulint fold;
@ -909,8 +906,6 @@ btr_search_guess_on_hash(
btr_cur_t cursor2; btr_cur_t cursor2;
btr_pcur_t pcur; btr_pcur_t pcur;
#endif #endif
ut_ad(!ahi_latch || rw_lock_own_flagged(
ahi_latch, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
if (!btr_search_enabled) { if (!btr_search_enabled) {
return false; return false;
@ -918,7 +913,6 @@ btr_search_guess_on_hash(
ut_ad(index && info && tuple && cursor && mtr); ut_ad(index && info && tuple && cursor && mtr);
ut_ad(!dict_index_is_ibuf(index)); ut_ad(!dict_index_is_ibuf(index));
ut_ad(!ahi_latch || ahi_latch == btr_get_search_latch(index));
ut_ad((latch_mode == BTR_SEARCH_LEAF) ut_ad((latch_mode == BTR_SEARCH_LEAF)
|| (latch_mode == BTR_MODIFY_LEAF)); || (latch_mode == BTR_MODIFY_LEAF));
@ -949,28 +943,21 @@ btr_search_guess_on_hash(
cursor->fold = fold; cursor->fold = fold;
cursor->flag = BTR_CUR_HASH; cursor->flag = BTR_CUR_HASH;
rw_lock_t* use_latch = ahi_latch ? NULL : btr_get_search_latch(index); rw_lock_t* ahi_latch = btr_get_search_latch(index);
const rec_t* rec; const rec_t* rec;
if (use_latch) { rw_lock_s_lock(ahi_latch);
rw_lock_s_lock(use_latch);
if (!btr_search_enabled) { if (!btr_search_enabled) {
goto fail; goto fail;
} }
} else {
ut_ad(btr_search_enabled);
ut_ad(rw_lock_own(ahi_latch, RW_LOCK_S));
}
rec = static_cast<const rec_t*>( rec = static_cast<const rec_t*>(
ha_search_and_get_data(btr_get_search_table(index), fold)); ha_search_and_get_data(btr_get_search_table(index), fold));
if (!rec) { if (!rec) {
if (use_latch) {
fail: fail:
rw_lock_s_unlock(use_latch); rw_lock_s_unlock(ahi_latch);
}
btr_search_failure(info, cursor); btr_search_failure(info, cursor);
return false; return false;
@ -978,9 +965,7 @@ fail:
buf_block_t* block = buf_block_from_ahi(rec); buf_block_t* block = buf_block_from_ahi(rec);
if (use_latch) { if (!buf_page_get_known_nowait(latch_mode, block, BUF_MAKE_YOUNG,
if (!buf_page_get_known_nowait(
latch_mode, block, BUF_MAKE_YOUNG,
__FILE__, __LINE__, mtr)) { __FILE__, __LINE__, mtr)) {
goto fail; goto fail;
} }
@ -988,26 +973,20 @@ fail:
const bool fail = index != block->index const bool fail = index != block->index
&& index_id == block->index->id; && index_id == block->index->id;
ut_a(!fail || block->index->freed()); ut_a(!fail || block->index->freed());
rw_lock_s_unlock(use_latch); ut_ad(fail || !block->page.file_page_was_freed);
rw_lock_s_unlock(ahi_latch);
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH); buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
if (UNIV_UNLIKELY(fail)) { if (UNIV_UNLIKELY(fail)) {
goto fail_and_release_page; goto fail_and_release_page;
} }
} else if (UNIV_UNLIKELY(index != block->index
&& index_id == block->index->id)) {
ut_a(block->index->freed());
goto fail_and_release_page;
}
if (buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) { if (buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
ut_ad(buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH); ut_ad(buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH);
fail_and_release_page: fail_and_release_page:
if (!ahi_latch) {
btr_leaf_page_release(block, latch_mode, mtr); btr_leaf_page_release(block, latch_mode, mtr);
}
btr_search_failure(info, cursor); btr_search_failure(info, cursor);
return false; return false;
@ -1025,7 +1004,7 @@ fail_and_release_page:
record to determine if our guess for the cursor position is record to determine if our guess for the cursor position is
right. */ right. */
if (index_id != btr_page_get_index_id(block->frame) if (index_id != btr_page_get_index_id(block->frame)
|| !btr_search_check_guess(cursor, !!ahi_latch, tuple, mode)) { || !btr_search_check_guess(cursor, 0, tuple, mode)) {
goto fail_and_release_page; goto fail_and_release_page;
} }
@ -1074,7 +1053,7 @@ fail_and_release_page:
#ifdef UNIV_SEARCH_PERF_STAT #ifdef UNIV_SEARCH_PERF_STAT
btr_search_n_succ++; btr_search_n_succ++;
#endif #endif
if (!ahi_latch && buf_page_peek_if_too_old(&block->page)) { if (buf_page_peek_if_too_old(&block->page)) {
buf_page_make_young(&block->page); buf_page_make_young(&block->page);
} }

View File

@ -4798,6 +4798,10 @@ buf_page_get_known_nowait(
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
/* The check for the page was not freed would already have been
performed when the block descriptor was acquired by the thread for the
first time.*/
buf_block_buf_fix_inc(block, file, line); buf_block_buf_fix_inc(block, file, line);
buf_page_set_accessed(&block->page); buf_page_set_accessed(&block->page);
@ -4844,24 +4848,6 @@ buf_page_get_known_nowait(
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#ifdef UNIV_DEBUG
if (mode != BUF_KEEP_OLD) {
/* If mode == BUF_KEEP_OLD, we are executing an I/O
completion routine. Avoid a bogus assertion failure
when ibuf_merge_or_delete_for_page() is processing a
page that was just freed due to DROP INDEX, or
deleting a record from SYS_INDEXES. This check will be
skipped in recv_recover_page() as well. */
# ifdef BTR_CUR_HASH_ADAPT
ut_ad(!block->page.file_page_was_freed
|| btr_search_check_marked_free_index(block));
# else /* BTR_CUR_HASH_ADAPT */
ut_ad(!block->page.file_page_was_freed);
# endif /* BTR_CUR_HASH_ADAPT */
}
#endif /* UNIV_DEBUG */
buf_pool->stat.n_page_gets++; buf_pool->stat.n_page_gets++;
return(TRUE); return(TRUE);

View File

@ -5253,7 +5253,7 @@ dict_set_corrupted(
btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_LE, btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_LE,
BTR_MODIFY_LEAF, BTR_MODIFY_LEAF,
&cursor, 0, __FILE__, __LINE__, &mtr); &cursor, __FILE__, __LINE__, &mtr);
if (cursor.low_match == dtuple_get_n_fields(tuple)) { if (cursor.low_match == dtuple_get_n_fields(tuple)) {
/* UPDATE SYS_INDEXES SET TYPE=index->type /* UPDATE SYS_INDEXES SET TYPE=index->type
@ -5355,7 +5355,7 @@ dict_index_set_merge_threshold(
btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE, btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF, BTR_MODIFY_LEAF,
&cursor, 0, __FILE__, __LINE__, &mtr); &cursor, __FILE__, __LINE__, &mtr);
if (cursor.up_match == dtuple_get_n_fields(tuple) if (cursor.up_match == dtuple_get_n_fields(tuple)
&& rec_get_n_fields_old(btr_cur_get_rec(&cursor)) && rec_get_n_fields_old(btr_cur_get_rec(&cursor))

View File

@ -3415,7 +3415,7 @@ fts_add_doc_by_id(
btr_pcur_open_with_no_init( btr_pcur_open_with_no_init(
fts_id_index, tuple, PAGE_CUR_LE, BTR_SEARCH_LEAF, fts_id_index, tuple, PAGE_CUR_LE, BTR_SEARCH_LEAF,
&pcur, 0, &mtr); &pcur, &mtr);
/* If we have a match, add the data to doc structure */ /* If we have a match, add the data to doc structure */
if (btr_pcur_get_low_match(&pcur) == 1) { if (btr_pcur_get_low_match(&pcur) == 1) {
@ -3453,7 +3453,7 @@ fts_add_doc_by_id(
btr_pcur_open_with_no_init( btr_pcur_open_with_no_init(
clust_index, clust_ref, PAGE_CUR_LE, clust_index, clust_ref, PAGE_CUR_LE,
BTR_SEARCH_LEAF, &clust_pcur, 0, &mtr); BTR_SEARCH_LEAF, &clust_pcur, &mtr);
doc_pcur = &clust_pcur; doc_pcur = &clust_pcur;
clust_rec = btr_pcur_get_rec(&clust_pcur); clust_rec = btr_pcur_get_rec(&clust_pcur);

View File

@ -588,7 +588,7 @@ rtr_pcur_open_low(
} }
btr_cur_search_to_nth_level(index, level, tuple, mode, latch_mode, btr_cur_search_to_nth_level(index, level, tuple, mode, latch_mode,
btr_cursor, 0, file, line, mtr); btr_cursor, file, line, mtr);
cursor->pos_state = BTR_PCUR_IS_POSITIONED; cursor->pos_state = BTR_PCUR_IS_POSITIONED;
cursor->trx_if_known = NULL; cursor->trx_if_known = NULL;
@ -756,8 +756,7 @@ static void rtr_get_father_node(
/* root split, and search the new root */ /* root split, and search the new root */
btr_cur_search_to_nth_level( btr_cur_search_to_nth_level(
index, level, tuple, PAGE_CUR_RTREE_LOCATE, index, level, tuple, PAGE_CUR_RTREE_LOCATE,
BTR_CONT_MODIFY_TREE, btr_cur, 0, BTR_CONT_MODIFY_TREE, btr_cur, __FILE__, __LINE__, mtr);
__FILE__, __LINE__, mtr);
} else { } else {
/* btr_validate */ /* btr_validate */
@ -766,8 +765,7 @@ static void rtr_get_father_node(
btr_cur_search_to_nth_level( btr_cur_search_to_nth_level(
index, level, tuple, PAGE_CUR_RTREE_LOCATE, index, level, tuple, PAGE_CUR_RTREE_LOCATE,
BTR_CONT_MODIFY_TREE, btr_cur, 0, BTR_CONT_MODIFY_TREE, btr_cur, __FILE__, __LINE__, mtr);
__FILE__, __LINE__, mtr);
rec = btr_cur_get_rec(btr_cur); rec = btr_cur_get_rec(btr_cur);
n_fields = dtuple_get_n_fields_cmp(tuple); n_fields = dtuple_get_n_fields_cmp(tuple);

View File

@ -170,56 +170,41 @@ btr_cur_optimistic_latch_leaves(
unsigned line, unsigned line,
mtr_t* mtr); mtr_t* mtr);
/********************************************************************//** /** Searches an index tree and positions a tree cursor on a given level.
Searches an index tree and positions a tree cursor on a given level.
NOTE: n_fields_cmp in tuple must be set so that it cannot be compared NOTE: n_fields_cmp in tuple must be set so that it cannot be compared
to node pointer page number fields on the upper levels of the tree! to node pointer page number fields on the upper levels of the tree!
Note that if mode is PAGE_CUR_LE, which is used in inserts, then Note that if mode is PAGE_CUR_LE, which is used in inserts, then
cursor->up_match and cursor->low_match both will have sensible values. cursor->up_match and cursor->low_match both will have sensible values.
If mode is PAGE_CUR_GE, then up_match will a have a sensible value. */ If mode is PAGE_CUR_GE, then up_match will a have a sensible value.
dberr_t @param index index
btr_cur_search_to_nth_level_func( @param level the tree level of search
dict_index_t* index, /*!< in: index */ @param tuple data tuple; NOTE: n_fields_cmp in tuple must be set so that
ulint level, /*!< in: the tree level of search */ it cannot get compared to the node ptr page number field!
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in @param mode PAGE_CUR_L, NOTE that if the search is made using a unique
tuple must be set so that it cannot get prefix of a record, mode should be PAGE_CUR_LE, not
compared to the node ptr page number field! */ PAGE_CUR_GE, as the latter may end up on the previous page of
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...; the record! Inserts should always be made using PAGE_CUR_LE
NOTE that if the search is made using a unique to search the position!
prefix of a record, mode should be PAGE_CUR_LE, @param latch_mode BTR_SEARCH_LEAF, ..., ORed with at most one of BTR_INSERT,
not PAGE_CUR_GE, as the latter may end up on BTR_DELETE_MARK, BTR_DELETE, or BTR_ESTIMATE;
the previous page of the record! Inserts cursor->left_block is used to store a pointer to the left
should always be made using PAGE_CUR_LE to neighbor page, in the cases BTR_SEARCH_PREV and
search the position! */ BTR_MODIFY_PREV; NOTE that if ahi_latch, we might not have a
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ..., ORed with cursor page latch, we assume that ahi_latch protects the
at most one of BTR_INSERT, BTR_DELETE_MARK, record!
BTR_DELETE, or BTR_ESTIMATE; @param cursor tree cursor; the cursor page is s- or x-latched, but see also
cursor->left_block is used to store a pointer above!
to the left neighbor page, in the cases @param file file name
BTR_SEARCH_PREV and BTR_MODIFY_PREV; @param line line where called
NOTE that if ahi_latch, we might not have a @param mtr mini-transaction
cursor page latch, we assume that ahi_latch @param autoinc PAGE_ROOT_AUTO_INC to be written (0 if none)
protects the record! */ @return DB_SUCCESS on success or error code otherwise */
btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is dberr_t btr_cur_search_to_nth_level(dict_index_t *index, ulint level,
s- or x-latched, but see also above! */ const dtuple_t *tuple,
#ifdef BTR_CUR_HASH_ADAPT page_cur_mode_t mode, ulint latch_mode,
rw_lock_t* ahi_latch, btr_cur_t *cursor, const char *file,
/*!< in: currently held btr_search_latch unsigned line, mtr_t *mtr,
(in RW_S_LATCH mode), or NULL */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */
mtr_t* mtr, /*!< in/out: mini-transaction */
ib_uint64_t autoinc= 0); ib_uint64_t autoinc= 0);
/*!< in: PAGE_ROOT_AUTO_INC to be written
(0 if none) */
#ifdef BTR_CUR_HASH_ADAPT
# define btr_cur_search_to_nth_level(i,l,t,m,lm,c,a,fi,li,mtr) \
btr_cur_search_to_nth_level_func(i,l,t,m,lm,c,a,fi,li,mtr)
#else /* BTR_CUR_HASH_ADAPT */
# define btr_cur_search_to_nth_level(i,l,t,m,lm,c,a,fi,li,mtr) \
btr_cur_search_to_nth_level_func(i,l,t,m,lm,c,fi,li,mtr)
#endif /* BTR_CUR_HASH_ADAPT */
/*****************************************************************//** /*****************************************************************//**
Opens a cursor at either end of an index. Opens a cursor at either end of an index.

View File

@ -116,41 +116,30 @@ btr_pcur_open_low(
mtr_t* mtr); /*!< in: mtr */ mtr_t* mtr); /*!< in: mtr */
#define btr_pcur_open(i,t,md,l,c,m) \ #define btr_pcur_open(i,t,md,l,c,m) \
btr_pcur_open_low(i,0,t,md,l,c,__FILE__,__LINE__,0,m) btr_pcur_open_low(i,0,t,md,l,c,__FILE__,__LINE__,0,m)
/**************************************************************//** /** Opens an persistent cursor to an index tree without initializing the
Opens an persistent cursor to an index tree without initializing the cursor.
cursor. */ @param index index
@param tuple tuple on which search done
@param mode PAGE_CUR_L, ...; NOTE that if the search is made using a
unique prefix of a record, mode should be PAGE_CUR_LE, not
PAGE_CUR_GE, as the latter may end up on the previous page of
the record!
@param latch_mode BTR_SEARCH_LEAF, ...; NOTE that if ahi_latch then we might
not acquire a cursor page latch, but assume that the
ahi_latch protects the record!
@param cursor memory buffer for persistent cursor
@param file file name
@param line line where called
@param mtr mtr
@return DB_SUCCESS on success or error code otherwise. */
UNIV_INLINE UNIV_INLINE
dberr_t dberr_t btr_pcur_open_with_no_init_func(dict_index_t *index,
btr_pcur_open_with_no_init_func( const dtuple_t *tuple,
/*============================*/ page_cur_mode_t mode, ulint latch_mode,
dict_index_t* index, /*!< in: index */ btr_pcur_t *cursor, const char *file,
const dtuple_t* tuple, /*!< in: tuple on which search done */ unsigned line, mtr_t *mtr);
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...; # define btr_pcur_open_with_no_init(ix,t,md,l,cur,m) \
NOTE that if the search is made using a unique
prefix of a record, mode should be
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
may end up on the previous page of the
record! */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
NOTE that if ahi_latch then we might not
acquire a cursor page latch, but assume
that the ahi_latch protects the record! */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
#ifdef BTR_CUR_HASH_ADAPT
rw_lock_t* ahi_latch,
/*!< in: adaptive hash index latch held
by the caller, or NULL if none */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */
#ifdef BTR_CUR_HASH_ADAPT
# define btr_pcur_open_with_no_init(ix,t,md,l,cur,ahi,m) \
btr_pcur_open_with_no_init_func(ix,t,md,l,cur,ahi,__FILE__,__LINE__,m)
#else /* BTR_CUR_HASH_ADAPT */
# define btr_pcur_open_with_no_init(ix,t,md,l,cur,ahi,m) \
btr_pcur_open_with_no_init_func(ix,t,md,l,cur,__FILE__,__LINE__,m) btr_pcur_open_with_no_init_func(ix,t,md,l,cur,__FILE__,__LINE__,m)
#endif /* BTR_CUR_HASH_ADAPT */
/*****************************************************************//** /*****************************************************************//**
Opens a persistent cursor at either end of an index. */ Opens a persistent cursor at either end of an index. */

View File

@ -438,11 +438,8 @@ btr_pcur_open_low(
ut_ad(!dict_index_is_spatial(index)); ut_ad(!dict_index_is_spatial(index));
err = btr_cur_search_to_nth_level_func( err = btr_cur_search_to_nth_level(
index, level, tuple, mode, latch_mode, btr_cursor, index, level, tuple, mode, latch_mode, btr_cursor,
#ifdef BTR_CUR_HASH_ADAPT
NULL,
#endif /* BTR_CUR_HASH_ADAPT */
file, line, mtr, autoinc); file, line, mtr, autoinc);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) { if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
@ -462,34 +459,28 @@ btr_pcur_open_low(
return(err); return(err);
} }
/**************************************************************//** /** Opens an persistent cursor to an index tree without initializing the
Opens an persistent cursor to an index tree without initializing the cursor.
cursor. */ @param index index
@param tuple tuple on which search done
@param mode PAGE_CUR_L, ...; NOTE that if the search is made using a
unique prefix of a record, mode should be PAGE_CUR_LE, not
PAGE_CUR_GE, as the latter may end up on the previous page of
the record!
@param latch_mode BTR_SEARCH_LEAF, ...; NOTE that if ahi_latch then we might
not acquire a cursor page latch, but assume that the
ahi_latch protects the record!
@param cursor memory buffer for persistent cursor
@param file file name
@param line line where called
@param mtr mtr
@return DB_SUCCESS on success or error code otherwise. */
UNIV_INLINE UNIV_INLINE
dberr_t dberr_t btr_pcur_open_with_no_init_func(dict_index_t *index,
btr_pcur_open_with_no_init_func( const dtuple_t *tuple,
/*============================*/ page_cur_mode_t mode, ulint latch_mode,
dict_index_t* index, /*!< in: index */ btr_pcur_t *cursor, const char *file,
const dtuple_t* tuple, /*!< in: tuple on which search done */ unsigned line, mtr_t *mtr)
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
NOTE that if the search is made using a unique
prefix of a record, mode should be
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
may end up on the previous page of the
record! */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
NOTE that if ahi_latch then we might not
acquire a cursor page latch, but assume
that the ahi_latch protects the record! */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
#ifdef BTR_CUR_HASH_ADAPT
rw_lock_t* ahi_latch,
/*!< in: adaptive hash index latch held
by the caller, or NULL if none */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{ {
btr_cur_t* btr_cursor; btr_cur_t* btr_cursor;
dberr_t err = DB_SUCCESS; dberr_t err = DB_SUCCESS;
@ -501,11 +492,8 @@ btr_pcur_open_with_no_init_func(
btr_cursor = btr_pcur_get_btr_cur(cursor); btr_cursor = btr_pcur_get_btr_cur(cursor);
err = btr_cur_search_to_nth_level_func( err = btr_cur_search_to_nth_level(
index, 0, tuple, mode, latch_mode, btr_cursor, index, 0, tuple, mode, latch_mode, btr_cursor,
#ifdef BTR_CUR_HASH_ADAPT
ahi_latch,
#endif /* BTR_CUR_HASH_ADAPT */
file, line, mtr); file, line, mtr);
cursor->pos_state = BTR_PCUR_IS_POSITIONED; cursor->pos_state = BTR_PCUR_IS_POSITIONED;

View File

@ -80,7 +80,6 @@ btr_search_guess_on_hash(
ulint mode, ulint mode,
ulint latch_mode, ulint latch_mode,
btr_cur_t* cursor, btr_cur_t* cursor,
rw_lock_t* ahi_latch,
mtr_t* mtr); mtr_t* mtr);
/** Move or delete hash entries for moved records, usually in a page split. /** Move or delete hash entries for moved records, usually in a page split.

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2019, MariaDB Corporation. Copyright (c) 2017, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -136,30 +136,6 @@ trx_undo_update_rec_get_update(
mem_heap_t* heap, /*!< in: memory heap from which the memory mem_heap_t* heap, /*!< in: memory heap from which the memory
needed is allocated */ needed is allocated */
upd_t** upd); /*!< out, own: update vector */ upd_t** upd); /*!< out, own: update vector */
/*******************************************************************//**
Builds a partial row from an update undo log record, for purge.
It contains the columns which occur as ordering in any index of the table.
Any missing columns are indicated by col->mtype == DATA_MISSING.
@return pointer to remaining part of undo record */
byte*
trx_undo_rec_get_partial_row(
/*=========================*/
const byte* ptr, /*!< in: remaining part in update undo log
record of a suitable type, at the start of
the stored index columns;
NOTE that this copy of the undo log record must
be preserved as long as the partial row is
used, as we do NOT copy the data in the
record! */
dict_index_t* index, /*!< in: clustered index */
const upd_t* update, /*!< in: updated columns */
dtuple_t** row, /*!< out, own: partial row */
ibool ignore_prefix, /*!< in: flag to indicate if we
expect blob prefixes in undo. Used
only in the assertion. */
mem_heap_t* heap) /*!< in: memory heap from which the memory
needed is allocated */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Report a RENAME TABLE operation. /** Report a RENAME TABLE operation.
@param[in,out] trx transaction @param[in,out] trx transaction
@param[in] table table that is being renamed @param[in] table table that is being renamed

View File

@ -1137,7 +1137,7 @@ row_ins_foreign_check_on_constraint(
tmp_heap); tmp_heap);
btr_pcur_open_with_no_init(clust_index, ref, btr_pcur_open_with_no_init(clust_index, ref,
PAGE_CUR_LE, BTR_SEARCH_LEAF, PAGE_CUR_LE, BTR_SEARCH_LEAF,
cascade->pcur, 0, mtr); cascade->pcur, mtr);
clust_rec = btr_pcur_get_rec(cascade->pcur); clust_rec = btr_pcur_get_rec(cascade->pcur);
clust_block = btr_pcur_get_block(cascade->pcur); clust_block = btr_pcur_get_block(cascade->pcur);
@ -2947,7 +2947,7 @@ row_ins_sec_index_entry_low(
err = btr_cur_search_to_nth_level( err = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_RTREE_INSERT, index, 0, entry, PAGE_CUR_RTREE_INSERT,
search_mode, search_mode,
&cursor, 0, __FILE__, __LINE__, &mtr); &cursor, __FILE__, __LINE__, &mtr);
if (mode == BTR_MODIFY_LEAF && rtr_info.mbr_adj) { if (mode == BTR_MODIFY_LEAF && rtr_info.mbr_adj) {
mtr_commit(&mtr); mtr_commit(&mtr);
@ -2966,7 +2966,7 @@ row_ins_sec_index_entry_low(
err = btr_cur_search_to_nth_level( err = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_RTREE_INSERT, index, 0, entry, PAGE_CUR_RTREE_INSERT,
search_mode, search_mode,
&cursor, 0, __FILE__, __LINE__, &mtr); &cursor, __FILE__, __LINE__, &mtr);
mode = BTR_MODIFY_TREE; mode = BTR_MODIFY_TREE;
} }
@ -2978,7 +2978,7 @@ row_ins_sec_index_entry_low(
err = btr_cur_search_to_nth_level( err = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE, index, 0, entry, PAGE_CUR_LE,
search_mode, search_mode,
&cursor, 0, __FILE__, __LINE__, &mtr); &cursor, __FILE__, __LINE__, &mtr);
} }
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
@ -3072,7 +3072,7 @@ row_ins_sec_index_entry_low(
index, 0, entry, PAGE_CUR_LE, index, 0, entry, PAGE_CUR_LE,
(search_mode (search_mode
& ~(BTR_INSERT | BTR_IGNORE_SEC_UNIQUE)), & ~(BTR_INSERT | BTR_IGNORE_SEC_UNIQUE)),
&cursor, 0, __FILE__, __LINE__, &mtr); &cursor, __FILE__, __LINE__, &mtr);
} }
if (row_ins_must_modify_rec(&cursor)) { if (row_ins_must_modify_rec(&cursor)) {

View File

@ -3359,7 +3359,7 @@ row_log_apply_op_low(
has_index_lock has_index_lock
? BTR_MODIFY_TREE ? BTR_MODIFY_TREE
: BTR_MODIFY_LEAF, : BTR_MODIFY_LEAF,
&cursor, 0, __FILE__, __LINE__, &cursor, __FILE__, __LINE__,
&mtr); &mtr);
ut_ad(dict_index_get_n_unique(index) > 0); ut_ad(dict_index_get_n_unique(index) > 0);
@ -3408,7 +3408,7 @@ row_log_apply_op_low(
index->set_modified(mtr); index->set_modified(mtr);
btr_cur_search_to_nth_level( btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE, index, 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, 0, BTR_MODIFY_TREE, &cursor,
__FILE__, __LINE__, &mtr); __FILE__, __LINE__, &mtr);
/* No other thread than the current one /* No other thread than the current one
@ -3511,7 +3511,7 @@ insert_the_rec:
index->set_modified(mtr); index->set_modified(mtr);
btr_cur_search_to_nth_level( btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE, index, 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, 0, BTR_MODIFY_TREE, &cursor,
__FILE__, __LINE__, &mtr); __FILE__, __LINE__, &mtr);
} }

View File

@ -163,7 +163,7 @@ public:
btr_cur_search_to_nth_level(m_index, 0, dtuple, btr_cur_search_to_nth_level(m_index, 0, dtuple,
PAGE_CUR_RTREE_INSERT, PAGE_CUR_RTREE_INSERT,
BTR_MODIFY_LEAF, &ins_cur, BTR_MODIFY_LEAF, &ins_cur,
0, __FILE__, __LINE__, __FILE__, __LINE__,
&mtr); &mtr);
/* It need to update MBR in parent entry, /* It need to update MBR in parent entry,
@ -179,7 +179,7 @@ public:
btr_cur_search_to_nth_level( btr_cur_search_to_nth_level(
m_index, 0, dtuple, m_index, 0, dtuple,
PAGE_CUR_RTREE_INSERT, PAGE_CUR_RTREE_INSERT,
BTR_MODIFY_TREE, &ins_cur, 0, BTR_MODIFY_TREE, &ins_cur,
__FILE__, __LINE__, &mtr); __FILE__, __LINE__, &mtr);
} }
@ -202,8 +202,7 @@ public:
m_index, 0, dtuple, m_index, 0, dtuple,
PAGE_CUR_RTREE_INSERT, PAGE_CUR_RTREE_INSERT,
BTR_MODIFY_TREE, BTR_MODIFY_TREE,
&ins_cur, 0, &ins_cur, __FILE__, __LINE__, &mtr);
__FILE__, __LINE__, &mtr);
error = btr_cur_pessimistic_insert( error = btr_cur_pessimistic_insert(
flag, &ins_cur, &ins_offsets, flag, &ins_cur, &ins_offsets,

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2021, MariaDB Corporation. Copyright (c) 2017, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -1009,6 +1009,141 @@ skip_secondaries:
row_purge_upd_exist_or_extern_func(node,undo_rec) row_purge_upd_exist_or_extern_func(node,undo_rec)
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/** Build a partial row from an update undo log record for purge.
Any columns which occur as ordering in any index of the table are present.
Any missing columns are indicated by col->mtype == DATA_MISSING.
@param ptr remaining part of the undo log record
@param index clustered index
@param node purge node
@return pointer to remaining part of undo record */
static byte *row_purge_get_partial(const byte *ptr, const dict_index_t &index,
purge_node_t *node)
{
bool first_v_col= true;
bool is_undo_log= true;
ut_ad(index.is_primary());
ut_ad(index.n_uniq == node->ref->n_fields);
node->row= dtuple_create_with_vcol(node->heap, index.table->n_cols,
index.table->n_v_cols);
/* Mark all columns in the row uninitialized, so that
we can distinguish missing fields from fields that are SQL NULL. */
for (ulint i= 0; i < index.table->n_cols; i++)
node->row->fields[i].type.mtype= DATA_MISSING;
dtuple_init_v_fld(node->row);
for (const upd_field_t *uf= node->update->fields, *const ue=
node->update->fields + node->update->n_fields; uf != ue; uf++)
{
if (!uf->old_v_val)
{
const dict_col_t &c= *dict_index_get_nth_col(&index, uf->field_no);
if (!c.is_dropped())
node->row->fields[c.ind]= uf->new_val;
}
}
const byte *end_ptr= ptr + mach_read_from_2(ptr);
ptr+= 2;
while (ptr != end_ptr)
{
dfield_t *dfield;
const byte *field;
const dict_col_t *col;
ulint len;
ulint orig_len;
ulint field_no= mach_read_next_compressed(&ptr);
if (field_no >= REC_MAX_N_FIELDS)
{
ptr= trx_undo_read_v_idx(index.table, ptr, first_v_col, &is_undo_log,
&field_no);
first_v_col= false;
ptr= trx_undo_rec_get_col_val(ptr, &field, &len, &orig_len);
if (field_no == ULINT_UNDEFINED)
continue; /* there no longer is an index on the virtual column */
dict_v_col_t *vcol= dict_table_get_nth_v_col(index.table, field_no);
col =&vcol->m_col;
dfield= dtuple_get_nth_v_field(node->row, vcol->v_pos);
dict_col_copy_type(&vcol->m_col, &dfield->type);
}
else
{
ptr= trx_undo_rec_get_col_val(ptr, &field, &len, &orig_len);
col= dict_index_get_nth_col(&index, field_no);
if (col->is_dropped())
continue;
dfield= dtuple_get_nth_field(node->row, col->ind);
ut_ad(dfield->type.mtype == DATA_MISSING ||
dict_col_type_assert_equal(col, &dfield->type));
ut_ad(dfield->type.mtype == DATA_MISSING ||
dfield->len == len ||
(len != UNIV_SQL_NULL && len >= UNIV_EXTERN_STORAGE_FIELD));
dict_col_copy_type(dict_table_get_nth_col(index.table, col->ind),
&dfield->type);
}
dfield_set_data(dfield, field, len);
if (len == UNIV_SQL_NULL || len < UNIV_EXTERN_STORAGE_FIELD)
continue;
spatial_status_t spatial_status= static_cast<spatial_status_t>
((len & SPATIAL_STATUS_MASK) >> SPATIAL_STATUS_SHIFT);
len&= ~SPATIAL_STATUS_MASK;
/* Keep compatible with 5.7.9 format. */
if (spatial_status == SPATIAL_UNKNOWN)
spatial_status= dict_col_get_spatial_status(col);
switch (UNIV_EXPECT(spatial_status, SPATIAL_NONE)) {
case SPATIAL_ONLY:
ut_ad(len - UNIV_EXTERN_STORAGE_FIELD == DATA_MBR_LEN);
dfield_set_len(dfield, len - UNIV_EXTERN_STORAGE_FIELD);
break;
case SPATIAL_MIXED:
dfield_set_len(dfield, len - UNIV_EXTERN_STORAGE_FIELD - DATA_MBR_LEN);
break;
default:
dfield_set_len(dfield, len - UNIV_EXTERN_STORAGE_FIELD);
break;
}
dfield_set_ext(dfield);
dfield_set_spatial_status(dfield, spatial_status);
if (!col->ord_part || spatial_status == SPATIAL_ONLY ||
node->rec_type == TRX_UNDO_UPD_DEL_REC)
continue;
/* If the prefix of this BLOB column is indexed, ensure that enough
prefix is stored in the undo log record. */
ut_a(dfield_get_len(dfield) >= BTR_EXTERN_FIELD_REF_SIZE);
ut_a(dict_table_has_atomic_blobs(index.table) ||
dfield_get_len(dfield) >=
REC_ANTELOPE_MAX_INDEX_COL_LEN + BTR_EXTERN_FIELD_REF_SIZE);
}
for (ulint i= 0; i < index.n_uniq; i++)
{
dfield_t &field= node->row->fields[index.fields[i].col->ind];
if (field.type.mtype == DATA_MISSING)
field= node->ref->fields[i];
}
return const_cast<byte*>(ptr);
}
/***********************************************************//** /***********************************************************//**
Parses the row reference and other info in a modify undo log record. Parses the row reference and other info in a modify undo log record.
@return true if purge operation required */ @return true if purge operation required */
@ -1158,10 +1293,7 @@ err_exit:
if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
ut_ad(!(node->update->info_bits & REC_INFO_MIN_REC_FLAG)); ut_ad(!(node->update->info_bits & REC_INFO_MIN_REC_FLAG));
ptr = trx_undo_rec_get_partial_row( ptr = row_purge_get_partial(ptr, *clust_index, node);
ptr, clust_index, node->update, &node->row,
type == TRX_UNDO_UPD_DEL_REC,
node->heap);
} else if (node->update->info_bits & REC_INFO_MIN_REC_FLAG) { } else if (node->update->info_bits & REC_INFO_MIN_REC_FLAG) {
node->ref = &trx_undo_metadata; node->ref = &trx_undo_metadata;
} }

View File

@ -988,8 +988,7 @@ row_sel_get_clust_rec(
index = dict_table_get_first_index(plan->table); index = dict_table_get_first_index(plan->table);
btr_pcur_open_with_no_init(index, plan->clust_ref, PAGE_CUR_LE, btr_pcur_open_with_no_init(index, plan->clust_ref, PAGE_CUR_LE,
BTR_SEARCH_LEAF, &plan->clust_pcur, BTR_SEARCH_LEAF, &plan->clust_pcur, mtr);
0, mtr);
clust_rec = btr_pcur_get_rec(&(plan->clust_pcur)); clust_rec = btr_pcur_get_rec(&(plan->clust_pcur));
@ -1397,8 +1396,7 @@ row_sel_open_pcur(
/* Open pcur to the index */ /* Open pcur to the index */
btr_pcur_open_with_no_init(index, plan->tuple, plan->mode, btr_pcur_open_with_no_init(index, plan->tuple, plan->mode,
BTR_SEARCH_LEAF, &plan->pcur, BTR_SEARCH_LEAF, &plan->pcur, mtr);
NULL, mtr);
} else { } else {
/* Open the cursor to the start or the end of the index /* Open the cursor to the start or the end of the index
(FALSE: no init) */ (FALSE: no init) */
@ -3329,7 +3327,7 @@ Row_sel_get_clust_rec_for_mysql::operator()(
btr_pcur_open_with_no_init(clust_index, prebuilt->clust_ref, btr_pcur_open_with_no_init(clust_index, prebuilt->clust_ref,
PAGE_CUR_LE, BTR_SEARCH_LEAF, PAGE_CUR_LE, BTR_SEARCH_LEAF,
prebuilt->clust_pcur, 0, mtr); prebuilt->clust_pcur, mtr);
clust_rec = btr_pcur_get_rec(prebuilt->clust_pcur); clust_rec = btr_pcur_get_rec(prebuilt->clust_pcur);
@ -3912,15 +3910,12 @@ row_sel_try_search_shortcut_for_mysql(
ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(index));
ut_ad(!prebuilt->templ_contains_blob); ut_ad(!prebuilt->templ_contains_blob);
rw_lock_t* ahi_latch = btr_get_search_latch(index);
rw_lock_s_lock(ahi_latch);
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE, btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur, ahi_latch, mtr); BTR_SEARCH_LEAF, pcur, mtr);
rec = btr_pcur_get_rec(pcur); rec = btr_pcur_get_rec(pcur);
if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, *index)) { if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, *index)) {
retry: retry:
rw_lock_s_unlock(ahi_latch);
return(SEL_RETRY); return(SEL_RETRY);
} }
@ -3930,7 +3925,6 @@ retry:
if (btr_pcur_get_up_match(pcur) < dtuple_get_n_fields(search_tuple)) { if (btr_pcur_get_up_match(pcur) < dtuple_get_n_fields(search_tuple)) {
exhausted: exhausted:
rw_lock_s_unlock(ahi_latch);
return(SEL_EXHAUSTED); return(SEL_EXHAUSTED);
} }
@ -3954,7 +3948,6 @@ exhausted:
*out_rec = rec; *out_rec = rec;
rw_lock_s_unlock(ahi_latch);
return(SEL_FOUND); return(SEL_FOUND);
} }
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
@ -4727,8 +4720,7 @@ wait_table_again:
} }
err = btr_pcur_open_with_no_init(index, search_tuple, mode, err = btr_pcur_open_with_no_init(index, search_tuple, mode,
BTR_SEARCH_LEAF, BTR_SEARCH_LEAF, pcur, &mtr);
pcur, 0, &mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
rec = NULL; rec = NULL;

View File

@ -1762,185 +1762,6 @@ trx_undo_update_rec_get_update(
return(const_cast<byte*>(ptr)); return(const_cast<byte*>(ptr));
} }
/*******************************************************************//**
Builds a partial row from an update undo log record, for purge.
It contains the columns which occur as ordering in any index of the table.
Any missing columns are indicated by col->mtype == DATA_MISSING.
@return pointer to remaining part of undo record */
byte*
trx_undo_rec_get_partial_row(
/*=========================*/
const byte* ptr, /*!< in: remaining part in update undo log
record of a suitable type, at the start of
the stored index columns;
NOTE that this copy of the undo log record must
be preserved as long as the partial row is
used, as we do NOT copy the data in the
record! */
dict_index_t* index, /*!< in: clustered index */
const upd_t* update, /*!< in: updated columns */
dtuple_t** row, /*!< out, own: partial row */
ibool ignore_prefix, /*!< in: flag to indicate if we
expect blob prefixes in undo. Used
only in the assertion. */
mem_heap_t* heap) /*!< in: memory heap from which the memory
needed is allocated */
{
const byte* end_ptr;
bool first_v_col = true;
bool is_undo_log = true;
ut_ad(index->is_primary());
*row = dtuple_create_with_vcol(
heap, dict_table_get_n_cols(index->table),
dict_table_get_n_v_cols(index->table));
/* Mark all columns in the row uninitialized, so that
we can distinguish missing fields from fields that are SQL NULL. */
for (ulint i = 0; i < dict_table_get_n_cols(index->table); i++) {
dfield_get_type(dtuple_get_nth_field(*row, i))
->mtype = DATA_MISSING;
}
dtuple_init_v_fld(*row);
for (const upd_field_t* uf = update->fields, * const ue
= update->fields + update->n_fields;
uf != ue; uf++) {
if (uf->old_v_val) {
continue;
}
const dict_col_t& c = *dict_index_get_nth_col(index,
uf->field_no);
if (!c.is_dropped()) {
*dtuple_get_nth_field(*row, c.ind) = uf->new_val;
}
}
end_ptr = ptr + mach_read_from_2(ptr);
ptr += 2;
while (ptr != end_ptr) {
dfield_t* dfield;
const byte* field;
ulint field_no;
const dict_col_t* col;
ulint len;
ulint orig_len;
bool is_virtual;
field_no = mach_read_next_compressed(&ptr);
is_virtual = (field_no >= REC_MAX_N_FIELDS);
if (is_virtual) {
ptr = trx_undo_read_v_idx(
index->table, ptr, first_v_col, &is_undo_log,
&field_no);
first_v_col = false;
}
ptr = trx_undo_rec_get_col_val(ptr, &field, &len, &orig_len);
/* This column could be dropped or no longer indexed */
if (field_no == ULINT_UNDEFINED) {
ut_ad(is_virtual);
continue;
}
if (is_virtual) {
dict_v_col_t* vcol = dict_table_get_nth_v_col(
index->table, field_no);
col = &vcol->m_col;
dfield = dtuple_get_nth_v_field(*row, vcol->v_pos);
dict_col_copy_type(
&vcol->m_col,
dfield_get_type(dfield));
} else {
col = dict_index_get_nth_col(index, field_no);
if (col->is_dropped()) {
continue;
}
dfield = dtuple_get_nth_field(*row, col->ind);
ut_ad(dfield->type.mtype == DATA_MISSING
|| dict_col_type_assert_equal(col,
&dfield->type));
ut_ad(dfield->type.mtype == DATA_MISSING
|| dfield->len == len
|| (len != UNIV_SQL_NULL
&& len >= UNIV_EXTERN_STORAGE_FIELD));
dict_col_copy_type(col, dfield_get_type(dfield));
}
dfield_set_data(dfield, field, len);
if (len != UNIV_SQL_NULL
&& len >= UNIV_EXTERN_STORAGE_FIELD) {
spatial_status_t spatial_status;
/* Decode spatial status. */
spatial_status = static_cast<spatial_status_t>(
(len & SPATIAL_STATUS_MASK)
>> SPATIAL_STATUS_SHIFT);
len &= ~SPATIAL_STATUS_MASK;
/* Keep compatible with 5.7.9 format. */
if (spatial_status == SPATIAL_UNKNOWN) {
spatial_status =
dict_col_get_spatial_status(col);
}
switch (spatial_status) {
case SPATIAL_ONLY:
ut_ad(len - UNIV_EXTERN_STORAGE_FIELD
== DATA_MBR_LEN);
dfield_set_len(
dfield,
len - UNIV_EXTERN_STORAGE_FIELD);
break;
case SPATIAL_MIXED:
dfield_set_len(
dfield,
len - UNIV_EXTERN_STORAGE_FIELD
- DATA_MBR_LEN);
break;
case SPATIAL_NONE:
dfield_set_len(
dfield,
len - UNIV_EXTERN_STORAGE_FIELD);
break;
case SPATIAL_UNKNOWN:
ut_ad(0);
break;
}
dfield_set_ext(dfield);
dfield_set_spatial_status(dfield, spatial_status);
/* If the prefix of this column is indexed,
ensure that enough prefix is stored in the
undo log record. */
if (!ignore_prefix && col->ord_part
&& spatial_status != SPATIAL_ONLY) {
ut_a(dfield_get_len(dfield)
>= BTR_EXTERN_FIELD_REF_SIZE);
ut_a(dict_table_has_atomic_blobs(index->table)
|| dfield_get_len(dfield)
>= REC_ANTELOPE_MAX_INDEX_COL_LEN
+ BTR_EXTERN_FIELD_REF_SIZE);
}
}
}
return(const_cast<byte*>(ptr));
}
/** Erase the unused undo log page end. /** Erase the unused undo log page end.
@param[in,out] undo_page undo log page @param[in,out] undo_page undo log page
@return whether the page contained something */ @return whether the page contained something */

View File

@ -568,8 +568,10 @@ void trx_disconnect_prepared(trx_t *trx)
ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED)); ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED));
ut_ad(trx->mysql_thd); ut_ad(trx->mysql_thd);
trx->read_view.close(); trx->read_view.close();
mutex_enter(&trx_sys.mutex);
trx->is_recovered= true; trx->is_recovered= true;
trx->mysql_thd= NULL; trx->mysql_thd= NULL;
mutex_exit(&trx_sys.mutex);
/* todo/fixme: suggest to do it at innodb prepare */ /* todo/fixme: suggest to do it at innodb prepare */
trx->will_lock= false; trx->will_lock= false;
} }

123
support-files/wsrep_notify.sh Normal file → Executable file
View File

@ -4,12 +4,31 @@
# It will create 'wsrep' schema and two tables in it: 'membeship' and 'status' # It will create 'wsrep' schema and two tables in it: 'membeship' and 'status'
# and fill them on every membership or node status change. # and fill them on every membership or node status change.
# #
# Edit parameters below to specify the address and login to server. # Edit parameters below to specify the address and login to server:
#
USER=root USER=root
PSWD=rootpass PSWD=rootpass
#
# If these parameters are not set, then the values
# passed by the server are taken:
#
HOST=127.0.0.1 HOST=127.0.0.1
PORT=3306 PORT=3306
#
# Edit parameters below to specify SSL parameters:
#
ssl_key=
ssl_cert=
ssl_ca=
ssl_capath=
ssl_cipher=
ssl_crl=
ssl_crlpath=
ssl_verify_server_cert=0
#
# Client executable path:
#
CLIENT="mysql"
SCHEMA="wsrep" SCHEMA="wsrep"
MEMB_TABLE="$SCHEMA.membership" MEMB_TABLE="$SCHEMA.membership"
@ -32,8 +51,6 @@ CREATE TABLE $STATUS_TABLE (
prim BOOLEAN /* if component is primary */ prim BOOLEAN /* if component is primary */
) ENGINE=MEMORY; ) ENGINE=MEMORY;
BEGIN; BEGIN;
DELETE FROM $MEMB_TABLE;
DELETE FROM $STATUS_TABLE;
" "
END="COMMIT;" END="COMMIT;"
@ -43,7 +60,7 @@ configuration_change()
local idx=0 local idx=0
for NODE in $(echo $MEMBERS | sed s/,/\ /g) for NODE in $(echo "$MEMBERS" | sed s/,/\ /g)
do do
echo "INSERT INTO $MEMB_TABLE VALUES ( $idx, " echo "INSERT INTO $MEMB_TABLE VALUES ( $idx, "
# Don't forget to properly quote string values # Don't forget to properly quote string values
@ -62,17 +79,44 @@ status_update()
echo "SET wsrep_on=0; BEGIN; UPDATE $STATUS_TABLE SET status='$STATUS'; COMMIT;" echo "SET wsrep_on=0; BEGIN; UPDATE $STATUS_TABLE SET status='$STATUS'; COMMIT;"
} }
trim_string()
{
if [ -n "${BASH_VERSION:-}" ]; then
local pattern="[![:space:]${2:-}]"
local x="${1#*$pattern}"
local z=${#1}
x=${#x}
if [ $x -ne $z ]; then
local y="${1%$pattern*}"
y=${#y}
x=$(( z-x-1 ))
y=$(( y-x+1 ))
printf '%s' "${1:$x:$y}"
else
printf ''
fi
else
local pattern="[[:space:]${2:-}]"
echo "$1" | sed -E "s/^$pattern+|$pattern+\$//g"
fi
}
COM=status_update # not a configuration change by default COM=status_update # not a configuration change by default
while [ $# -gt 0 ] STATUS=""
do CLUSTER_UUID=""
PRIMARY="0"
INDEX=""
MEMBERS=""
while [ $# -gt 0 ]; do
case $1 in case $1 in
--status) --status)
STATUS=$2 STATUS=$(trim_string "$2")
shift shift
;; ;;
--uuid) --uuid)
CLUSTER_UUID=$2 CLUSTER_UUID=$(trim_string "$2")
shift shift
;; ;;
--primary) --primary)
@ -81,22 +125,71 @@ do
shift shift
;; ;;
--index) --index)
INDEX=$2 INDEX=$(trim_string "$2")
shift shift
;; ;;
--members) --members)
MEMBERS=$2 MEMBERS=$(trim_string "$2")
shift shift
;; ;;
esac esac
shift shift
done done
# Undefined means node is shutting down USER=$(trim_string "$USER")
if [ "$STATUS" != "Undefined" ] PSWD=$(trim_string "$PSWD")
HOST=$(trim_string "$HOST")
PORT=$(trim_string "$PORT")
case "$HOST" in
\[*)
HOST="${HOST##\[}"
HOST=$(trim_string "${HOST%%\]}")
;;
esac
if [ -z "$HOST" ]; then
HOST="${NOTIFY_HOST:-}"
fi
if [ -z "$PORT" ]; then
PORT="${NOTIFY_PORT:-}"
fi
ssl_key=$(trim_string "$ssl_key");
ssl_cert=$(trim_string "$ssl_cert");
ssl_ca=$(trim_string "$ssl_ca");
ssl_capath=$(trim_string "$ssl_capath");
ssl_cipher=$(trim_string "$ssl_cipher");
ssl_crl=$(trim_string "$ssl_crl");
ssl_crlpath=$(trim_string "$ssl_crlpath");
ssl_verify_server_cert=$(trim_string "$ssl_verify_server_cert");
SSL_PARAM=""
if [ -n "$ssl_key" -o -n "$ssl_cert" -o \
-n "$ssl_ca" -o -n "$ssl_capath" -o \
-n "$ssl_cipher" ]
then then
$COM | mysql -B -u$USER -p$PSWD -h$HOST -P$PORT SSL_PARAM=' --ssl'
[ -n "$ssl_key" ] && SSL_PARAM="$SSL_PARAM --ssl-key='$ssl_key'"
[ -n "$ssl_cert" ] && SSL_PARAM="$SSL_PARAM --ssl-cert='$ssl_cert'"
[ -n "$ssl_ca" ] && SSL_PARAM="$SSL_PARAM --ssl-ca='$ssl_ca'"
[ -n "$ssl_capath" ] && SSL_PARAM="$SSL_PARAM --ssl-capath='$ssl_capath'"
[ -n "$ssl_cipher" ] && SSL_PARAM="$SSL_PARAM --ssl-cipher='$ssl_cipher'"
[ -n "$ssl_crl" ] && SSL_PARAM="$SSL_PARAM --ssl-crl='$ssl_crl'"
[ -n "$ssl_crlpath" ] && SSL_PARAM="$SSL_PARAM --ssl-crlpath='$ssl_crlpath'"
if [ -n "$ssl_verify_server_cert" ]; then
if [ $ssl_verify_server_cert -ne 0 ]; then
SSL_PARAM+=' --ssl-verify-server-cert'
fi
fi
fi
# Undefined means node is shutting down
if [ "$STATUS" != 'Undefined' ]; then
"$COM" | eval "$CLIENT" -B "-u'$USER'"${PSWD:+" -p'$PSWD'"}\
"-h'$HOST'" "-P$PORT"$SSL_PARAM
fi fi
exit 0 exit 0
#