1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

Merge 10.7 into 10.8

This commit is contained in:
Marko Mäkelä
2022-11-17 21:35:12 +02:00
98 changed files with 2993 additions and 3544 deletions

View File

@@ -26,9 +26,9 @@ then
sed '/Add support for verbose builds/,/^$/d' -i debian/rules
elif [ -d storage/columnstore/columnstore/debian ]
then
# ColumnStore is explicitly disabled in the native Debian build, so allow it
# ColumnStore is explicitly disabled in the native Debian build. Enable it
# now when build is triggered by autobake-deb.sh (MariaDB.org) and when the
# build is not running on Travis or Gitlab-CI
# build is not running on Gitlab-CI.
sed '/-DPLUGIN_COLUMNSTORE=NO/d' -i debian/rules
# Take the files and part of control from MCS directory
if [ ! -f debian/mariadb-plugin-columnstore.install ]
@@ -59,13 +59,13 @@ replace_uring_with_aio()
{
sed 's/liburing-dev/libaio-dev/g' -i debian/control
sed -e '/-DIGNORE_AIO_CHECK=YES/d' \
-e '/-DWITH_URING=yes/d' -i debian/rules
-e '/-DWITH_URING=YES/d' -i debian/rules
}
disable_pmem()
{
sed '/libpmem-dev/d' -i debian/control
sed '/-DWITH_PMEM=yes/d' -i debian/rules
sed '/-DWITH_PMEM=YES/d' -i debian/rules
}
disable_libfmt()
@@ -76,15 +76,34 @@ disable_libfmt()
architecture=$(dpkg-architecture -q DEB_BUILD_ARCH)
# Parse release name and number from Linux standard base release
# Example:
# $ lsb_release -a
# No LSB modules are available.
# Distributor ID: Debian
# Description: Debian GNU/Linux bookworm/sid
# Release: n/a
# Codename: n/a
LSBID="$(lsb_release -si | tr '[:upper:]' '[:lower:]')"
LSBVERSION="$(lsb_release -sr | sed -e "s#\.##g")"
LSBNAME="$(lsb_release -sc)"
# If 'n/a', assume 'sid'
if [ "${LSBVERSION}" == "n/a" ] || [ "${LSBNAME}" == "n/a" ]
then
LSBVERSION="sid"
LSBNAME="sid"
fi
# If not known, use 'unknown' in .deb version identifier
if [ -z "${LSBID}" ]
then
LSBID="unknown"
fi
case "${LSBNAME}" in
case "${LSBNAME}"
in
# Debian
stretch)
# MDEV-16525 libzstd-dev-1.1.3 minimum version
sed -e '/libzstd-dev/d' \
@@ -113,10 +132,10 @@ case "${LSBNAME}" in
fi
;&
sid)
# should always be empty here.
# need to match here to avoid the default Error however
# The default packaging should always target Debian Sid, so in this case
# there is intentionally no customizations whatsoever.
;;
# UBUNTU
# Ubuntu
bionic)
remove_rocksdb_tools
[ "$architecture" != amd64 ] && disable_pmem
@@ -143,7 +162,7 @@ case "${LSBNAME}" in
fi
;;
*)
echo "Error - unknown release codename $LSBNAME" >&2
echo "Error: Unknown release '$LSBNAME'" >&2
exit 1
esac
@@ -162,7 +181,7 @@ LOGSTRING="MariaDB build"
EPOCH="1:"
VERSION="${EPOCH}${UPSTREAM}${PATCHLEVEL}~${LSBID:0:3}${LSBVERSION}"
dch -b -D ${LSBNAME} -v "${VERSION}" "Automatic build with ${LOGSTRING}." --controlmaint
dch -b -D "${LSBNAME}" -v "${VERSION}" "Automatic build with ${LOGSTRING}." --controlmaint
echo "Creating package version ${VERSION} ... "

View File

@@ -21,9 +21,18 @@ test -x /usr/sbin/mariadbd || exit 0
. /lib/lsb/init-functions
SELF=$(cd $(dirname $0); pwd -P)/$(basename $0)
SELF=$(cd "$(dirname $0)"; pwd -P)/$(basename $0)
MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf"
if [ -f /usr/bin/mariadb-admin ]
then
MYADMIN="/usr/bin/mariadb-admin --defaults-file=/etc/mysql/debian.cnf"
elif [ -f /usr/bin/mysqladmin ]
then
MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf"
else
log_failure_msg "Command mariadb-admin/mysqladmin not found! This SysV init script depends on it."
exit -1
fi
# priority can be overridden and "-s" adds output to stderr
ERR_LOGGER="logger -p daemon.err -t /etc/init.d/mariadb -i"

19
debian/rules vendored
View File

@@ -5,7 +5,13 @@ export DEB_BUILD_HARDENING=1
# enable Debian Hardening
# see: https://wiki.debian.org/Hardening
export DEB_BUILD_MAINT_OPTIONS = hardening=+all optimize=-lto
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
# Disable LTO on Ubuntu, see LP: #1970634 and https://jira.mariadb.org/browse/MDEV-25633
ifeq ($(shell dpkg-vendor --derives-from Ubuntu && echo yes), yes)
export DEB_BUILD_MAINT_OPTIONS += optimize=-lto
endif
DPKG_EXPORT_BUILDFLAGS = 1
# Include all defaults, including buildflags.mk
include /usr/share/dpkg/default.mk
@@ -46,11 +52,6 @@ ifeq (32,$(DEB_HOST_ARCH_BITS))
CMAKEFLAGS += -DPLUGIN_ROCKSDB=NO
endif
# ColumnStore can build only on amd64 and arm64
ifneq (,$(filter $(DEB_HOST_ARCH_CPU),amd64 arm64))
CMAKEFLAGS += -DPLUGIN_COLUMNSTORE=NO
endif
# Cross building requires stack direction instruction
ifneq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH))
ifneq (,$(filter $(DEB_HOST_ARCH_CPU),alpha amd64 arm arm64 i386 ia64 m68k mips64el mipsel powerpc ppc64 ppc64el riscv64 s390x sh4 sparc64))
@@ -64,7 +65,7 @@ endif
# Only attempt to build with PMEM on archs that have package libpmem-dev available
# See https://packages.debian.org/search?searchon=names&keywords=libpmem-dev
ifneq (,$(filter $(DEB_HOST_ARCH_CPU),amd64 arm64 ppc64el riscv64))
CMAKEFLAGS += -DWITH_PMEM=yes
CMAKEFLAGS += -DWITH_PMEM=YES
endif
# Add support for verbose builds
@@ -107,7 +108,7 @@ endif
-DPLUGIN_AWS_KEY_MANAGEMENT=NO \
-DPLUGIN_COLUMNSTORE=NO \
-DIGNORE_AIO_CHECK=YES \
-DWITH_URING=yes \
-DWITH_URING=YES \
-DDEB=$(DEB_VENDOR)
# This is needed, otherwise 'make test' will run before binaries have been built
@@ -120,6 +121,7 @@ override_dh_auto_build:
override_dh_auto_test:
@echo "RULES.$@"
dh_testdir
# Ensure at least an empty file exists
touch mysql-test/unstable-tests
[ ! -f debian/unstable-tests.$(DEB_HOST_ARCH) ] || cat debian/unstable-tests.$(DEB_HOST_ARCH) >> mysql-test/unstable-tests
# Run testsuite
@@ -203,6 +205,7 @@ override_dh_installinit-arch:
dh_installinit --name=mariadb --no-start -- defaults 19 21
dh_systemd_start --restart-after-upgrade
# Use custom server version string variable
override_dh_gencontrol:
dh_gencontrol -- -Tdebian/substvars

77
debian/salsa-ci.yml vendored
View File

@@ -16,12 +16,17 @@ variables:
GIT_SUBMODULE_STRATEGY: recursive
SALSA_CI_GBP_BUILDPACKAGE_ARGS: "--git-submodules" # did not apply to extract-sources
# Extend Salsa-CI build jobs to have longer timeout as the default GitLab
# timeout (1h) is often not enough
.build-package:
timeout: 3h
stages:
- provisioning
- build
- test
- upgrade in Sid
- upgrade from Bullseye/Buster
- upgrade from Bullseye
- upgrade extras
- test extras
- publish # Stage referenced by Salsa-CI template aptly stanza, so must exist even though not used
@@ -134,6 +139,17 @@ blhc:
apt-get update
apt-get install -y apt
.test-enable-buster-backports-repos: &test-enable-buster-backports-repos |
# Enable buster-backports (assumes environment already Debian Buster)
echo 'deb http://deb.debian.org/debian buster-backports main' > /etc/apt/sources.list.d/buster-backports.list
# Increase default backports priority policy from '100' to '500' so it can actually be used
cat << EOF > /etc/apt/preferences.d/enable-backports-to-satisfy-dependencies
Package: *
Pin: release n=buster-*
Pin-Priority: 500
EOF
apt-get update
.test-install: &test-install |
# Install MariaDB built in this commit
apt-get install -y ./*.deb
@@ -213,7 +229,7 @@ fresh install:
script:
- *test-prepare-container
- *test-install
- service mariadb status # There is no init.d/mysql in MariaDB 10.8
- service mariadb status # There is no init.d/mysql in MariaDB 10.5+
- *test-verify-final
variables:
GIT_STRATEGY: none
@@ -234,7 +250,7 @@ mariadb-10.8 Sid upgrade:
script:
- *test-prepare-container
- *test-install
- service mariadb status # There is no init.d/mysql in MariaDB 10.8
- service mariadb status # There is no init.d/mysql in MariaDB 10.5+
- *test-verify-final
variables:
GIT_STRATEGY: none
@@ -243,7 +259,7 @@ mariadb-10.8 Sid upgrade:
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
mariadb-10.5 Bullseye to mariadb-10.8 upgrade:
stage: upgrade from Bullseye/Buster
stage: upgrade from Bullseye
needs:
- job: build
image: debian:bullseye
@@ -268,10 +284,12 @@ mariadb-10.5 Bullseye to mariadb-10.8 upgrade:
variables:
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
mariadb-10.3 Buster to mariadb-10.8 upgrade:
stage: upgrade from Bullseye/Buster
# Upgrade of libcrypt.so.1 no longer possible from Buster to Sid,
# so test upgrade only inside Buster (https://bugs.debian.org/993755)
mariadb-10.3 to mariadb-10.8 upgrade in Buster:
stage: upgrade extras
needs:
- job: build
- job: build buster-backports
image: debian:buster
artifacts:
when: always
@@ -284,7 +302,7 @@ mariadb-10.3 Buster to mariadb-10.8 upgrade:
- apt-get install -y 'default-mysql*' 'mariadb-*' 'libmariadb*'
# Verify installation of MariaDB from Buster
- *test-verify-initial
- *test-enable-sid-repos
- *test-enable-buster-backports-repos
- *test-install
- service mysql status
- *test-verify-final
@@ -307,7 +325,7 @@ test basic features:
script:
- *test-prepare-container
- *test-install
- service mariadb status # There is no init.d/mysql in MariaDB 10.8
- service mariadb status # There is no init.d/mysql in MariaDB 10.5+
- *test-verify-final
- |
# Print info about server
@@ -452,7 +470,7 @@ default-libmysqlclient-dev Sid upgrade:
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
default-libmysqlclient-dev Bullseye upgrade:
stage: upgrade from Bullseye/Buster
stage: upgrade from Bullseye
needs:
- job: build
image: debian:bullseye
@@ -472,10 +490,12 @@ default-libmysqlclient-dev Bullseye upgrade:
variables:
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
default-libmysqlclient-dev Buster upgrade:
stage: upgrade from Bullseye/Buster
# Upgrade of libcrypt.so.1 no longer possible from Buster to Sid,
# so test upgrade only inside Buster (https://bugs.debian.org/993755)
default-libmysqlclient-dev upgrade in Buster:
stage: upgrade extras
needs:
- job: build
- job: build buster-backports
image: debian:buster
artifacts:
when: always
@@ -486,7 +506,7 @@ default-libmysqlclient-dev Buster upgrade:
- *test-prepare-container
- apt-get install -y pkg-config default-libmysqlclient-dev
- pkg-config --list-all
- *test-enable-sid-repos
- *test-enable-buster-backports-repos
- *test-install-all-libs
- *test-verify-libs
except:
@@ -511,8 +531,20 @@ mysql-8.0 Sid to mariadb-10.8 upgrade:
- apt-get install -y procps mysql-server 'libmysqlc*'
- *test-verify-initial
- *test-install
- service mysql status
# The Debian version of MariaDB 10.6 still maintains compatibility and there
# running 'service mysql status' in Salsa-CI job 'mysql-8.0 Sid to
# mariadb-10.6 upgrade' still works.
#
# However, due to debian/control changes, the upstream MariaDB 10.6 when
# installed on a system with a previous installation of MySQL 8.0 will first
# fully remove MySQL, including the /etc/init.d/mysql file, so previous
# techniques in mariadb-server-10.6.postinst to maintain backwards
# compatibility with 'service mysql status' after installing MariaDB on top
# MySQL no longer works, and thus the step to test it now intentionally has
# a fallback to use the service name 'mariadb' instead, and the fallback is
# always used.
- sleep 5 # Give the mysql_upgrade a bit of time to complete before querying the server
- service mysql status || service mariadb status
- *test-verify-final
variables:
GIT_STRATEGY: none
@@ -522,7 +554,7 @@ mysql-8.0 Sid to mariadb-10.8 upgrade:
# Upgrading from MySQL 8.0 with datadir in place is not possible. Users need to do a data dump.
# The Debian maintainer scripts detect this situation and simply moves old datadir aside and start fresh.
mysql-8.0 Focal to mariadb-10.8 upgrade:
mysql-8.0 Focal to mariadb-10.8 upgrade in Buster:
stage: upgrade extras
needs:
- job: build buster-backports
@@ -622,18 +654,13 @@ mariadb.org-10.6 to mariadb-10.8 upgrade:
# Verify installation of MariaDB built in this commit
- dpkg -l | grep -iE 'maria|mysql|galera' || true # List installed
- mariadb --version # Client version
- service mariadb status # There is no init.d/mysql in MariaDB 10.8
- service mariadb status # There is no init.d/mysql in MariaDB 10.5+
- *test-verify-final
variables:
GIT_STRATEGY: none
except:
variables:
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
allow_failure: true
# Installation on Sid fails on missing liburing1 because upstream 10.8
# MariaDB.org buildbot has not run 'apt upgrade' for a long time.
# Remove this allow_failure once buildbot has built a new 10.8
# release using latest liburing-dev in Debian Sid.
mariadb.org-10.5 to mariadb-10.8 upgrade:
stage: upgrade extras
@@ -657,7 +684,7 @@ mariadb.org-10.5 to mariadb-10.8 upgrade:
# Verify installation of MariaDB built in this commit
- dpkg -l | grep -iE 'maria|mysql|galera' || true # List installed
- mariadb --version # Client version
- service mariadb status # There is no init.d/mysql in MariaDB 10.5
- service mariadb status # There is no init.d/mysql in MariaDB 10.5+
- *test-verify-final
variables:
GIT_STRATEGY: none
@@ -768,7 +795,7 @@ mariadb.org-10.2 to mariadb-10.8 upgrade:
variables:
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
mysql.com-5.7 to mariadb-10.8 upgrade:
mysql.com-5.7 to mariadb-10.8 upgrade in Buster:
stage: upgrade extras
needs:
- job: build buster-backports
@@ -799,7 +826,7 @@ mysql.com-5.7 to mariadb-10.8 upgrade:
variables:
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
percona-xtradb-5.7 to mariadb-10.8 upgrade (MDEV-22679):
percona-xtradb-5.7 to mariadb-10.8 upgrade in Buster (MDEV-22679):
stage: upgrade extras
needs:
- job: build buster-backports

View File

@@ -48,7 +48,7 @@ very-long-line-length-in-source-file mysql-test/std_data/init_file_longline_3816
very-long-line-length-in-source-file scripts/fill_help_tables.sql *
very-long-line-length-in-source-file scripts/mysql_system_tables.sql *
very-long-line-length-in-source-file scripts/mysql_test_data_timezone.sql *
# Machine formated HTML
# Machine formatted HTML
very-long-line-length-in-source-file sql/share/charsets/languages.html *
very-long-line-length-in-source-file sql/share/errmsg-utf8.txt *
# Very long test string

24
debian/tests/upstream vendored
View File

@@ -10,6 +10,8 @@ echo "Running test 'testsuite'"
set -e
SKIP_TEST_LST="/tmp/skip-test.lst"
ARCH=$(dpkg --print-architecture)
WORKDIR=$(mktemp -d)
trap 'rm -rf $WORKDIR $SKIP_TEST_LST' 0 INT QUIT ABRT PIPE TERM
cd "$WORKDIR"
@@ -22,16 +24,15 @@ echo "using tmpdir: $WORKDIR/tmp"
echo "Setting up skip-tests-list"
touch $SKIP_TEST_LST
# Use unstable-tests list as base to skip all tests considered unstable
# or create an empty file if that upstream file does not exists on this branch
cp /usr/share/mysql/mysql-test/unstable-tests $SKIP_TEST_LST || touch $SKIP_TEST_LST
# Also use arch specific skiplists if such files exist
for filename in /usr/share/mysql/mysql-test/unstable-tests.*
do
# Check for case that no files matched and glob is returned
[ -e "$filename" ] || continue
# Append file to the main skip test list file
cat "$filename" >> $SKIP_TEST_LST
done
# Also use the arch specific skiplists if exist
if [ -f /usr/share/mysql/mysql-test/unstable-tests.$ARCH ]
then
cat /usr/share/mysql/mysql-test/unstable-tests.$ARCH >> $SKIP_TEST_LST
fi
# Skip tests that cannot run properly on ci.debian.net / autopkgtests.ubuntu.com
cat >> $SKIP_TEST_LST << EOF
@@ -48,7 +49,6 @@ main.mysqld--help : For unknown reason table-cache is 4000 instead of default 42
EOF
fi
ARCH=$(dpkg --print-architecture)
if [ "$ARCH" = "s390x" ]
then
echo "main.func_regexp_pcre : recursion fails on s390x https://bugs.launchpad.net/ubuntu/+source/mariadb-10.1/+bug/1723947" >> $SKIP_TEST_LST
@@ -57,6 +57,10 @@ then
echo "main.failed_auth_unixsocket : Test returns wrong exit code on armhf and i386 (but only in debci) https://jira.mariadb.org/browse/MDEV-23933" >> $SKIP_TEST_LST
fi
# Store skipped test list in artifacts so it can be viewed while debugging
# failed autopkgtest runs
cp -v $SKIP_TEST_LST $AUTOPKGTEST_ARTIFACTS
cd /usr/share/mysql/mysql-test
echo "starting mysql-test-tun.pl..."
eatmydata perl -I. ./mysql-test-run.pl --suite=main \

View File

@@ -1,3 +1,4 @@
RESET MASTER;
CREATE TEMPORARY SEQUENCE seq_1;
XA START '3';
CREATE TEMPORARY TABLE tmp_1(c INT);

View File

@@ -1,3 +1,4 @@
RESET MASTER;
#
# Verify that SET string values and character sets can be printed correctly
#

View File

@@ -1,3 +1,4 @@
RESET MASTER;
#
# Verify that SET string values and character sets can be printed correctly
#

View File

@@ -1,3 +1,4 @@
RESET MASTER;
#
# Verify that SET string values and character sets can be printed correctly
#

View File

@@ -4,7 +4,7 @@
--source include/have_binlog_format_mixed.inc
--source include/have_innodb.inc
RESET MASTER; # clear binlogs
# MDEV-22420 DDL on temporary object is prohibited when XA is in prepare state
# Temporary sequnce may not be created within a transaction

View File

@@ -20,6 +20,7 @@
--let $MYSQLD_DATADIR= `select @@datadir`
--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001
RESET MASTER;
--echo #
--echo # Verify that SET string values and character sets can be printed correctly
--echo #

View File

@@ -21,6 +21,7 @@
--let $MYSQLD_DATADIR= `select @@datadir`
--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001
RESET MASTER;
--echo #
--echo # Verify that SET string values and character sets can be printed correctly
--echo #

View File

@@ -21,6 +21,7 @@
--let $MYSQLD_DATADIR= `select @@datadir`
--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001
RESET MASTER;
--echo #
--echo # Verify that SET string values and character sets can be printed correctly
--echo #

View File

@@ -3268,3 +3268,78 @@ a
This is db1.pkg1.p1
DROP DATABASE db1;
DROP DATABASE db2;
#
# MDEV-29370 Functions in packages are slow and seems to ignore deterministic
#
SET SQL_MODE=ORACLE;
CREATE TABLE t1 (c1 CHAR(1));
CREATE FUNCTION f1_deterministic()
RETURN CHAR(1)
DETERMINISTIC
IS
BEGIN
RETURN 'X';
END;
//
CREATE FUNCTION f2_not_deterministic()
RETURN CHAR(1)
IS
BEGIN
RETURN 'X';
END;
//
CREATE PACKAGE pkg1
IS
PROCEDURE t1_populate(numrows INTEGER);
FUNCTION f3_deterministic() RETURN CHAR(1) DETERMINISTIC;
FUNCTION f4_not_deterministic() RETURN CHAR(1);
END;
//
CREATE PACKAGE BODY pkg1
IS
PROCEDURE t1_populate(numrounds INTEGER)
IS
i INTEGER;
BEGIN
INSERT INTO t1 VALUES('Y');
FOR i IN 1..numrounds LOOP
INSERT INTO t1 SELECT * FROM t1;
END LOOP;
END;
FUNCTION f3_deterministic() RETURN CHAR(1) DETERMINISTIC COMMENT 'xxx'
IS
BEGIN
RETURN 'X';
END;
FUNCTION f4_not_deterministic() RETURN CHAR(1)
IS
BEGIN
RETURN 'X';
END;
END;
//
CALL pkg1.t1_populate(3);
EXPLAIN EXTENDED SELECT 'Deterministic function', COUNT(*) FROM t1 WHERE c1 = f1_deterministic();
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
Warnings:
Note 1003 select 'Deterministic function' AS "Deterministic function",count(0) AS "COUNT(*)" from "test"."t1" where "test"."t1"."c1" = <cache>("f1_deterministic"())
EXPLAIN EXTENDED SELECT 'Non-deterministic function', COUNT(*) FROM t1 WHERE c1 = f2_not_deterministic();
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
Warnings:
Note 1003 select 'Non-deterministic function' AS "Non-deterministic function",count(0) AS "COUNT(*)" from "test"."t1" where "test"."t1"."c1" = "f2_not_deterministic"()
EXPLAIN EXTENDED SELECT 'Deterministic package function', COUNT(*) FROM t1 WHERE c1 = pkg1.f3_deterministic();
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
Warnings:
Note 1003 select 'Deterministic package function' AS "Deterministic package function",count(0) AS "COUNT(*)" from "test"."t1" where "test"."t1"."c1" = <cache>("test"."pkg1"."f3_deterministic"())
EXPLAIN EXTENDED SELECT 'Non-deterministic package function', COUNT(*) FROM t1 WHERE c1 = pkg1.f4_not_deterministic();
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
Warnings:
Note 1003 select 'Non-deterministic package function' AS "Non-deterministic package function",count(0) AS "COUNT(*)" from "test"."t1" where "test"."t1"."c1" = "test"."pkg1"."f4_not_deterministic"()
DROP TABLE t1;
DROP FUNCTION f1_deterministic;
DROP FUNCTION f2_not_deterministic;
DROP PACKAGE pkg1;

View File

@@ -3016,3 +3016,75 @@ CALL db2.pkg1.p2_db1_pkg1_p1;
DROP DATABASE db1;
DROP DATABASE db2;
--echo #
--echo # MDEV-29370 Functions in packages are slow and seems to ignore deterministic
--echo #
SET SQL_MODE=ORACLE;
CREATE TABLE t1 (c1 CHAR(1));
DELIMITER //;
CREATE FUNCTION f1_deterministic()
RETURN CHAR(1)
DETERMINISTIC
IS
BEGIN
RETURN 'X';
END;
//
CREATE FUNCTION f2_not_deterministic()
RETURN CHAR(1)
IS
BEGIN
RETURN 'X';
END;
//
CREATE PACKAGE pkg1
IS
PROCEDURE t1_populate(numrows INTEGER);
FUNCTION f3_deterministic() RETURN CHAR(1) DETERMINISTIC;
FUNCTION f4_not_deterministic() RETURN CHAR(1);
END;
//
CREATE PACKAGE BODY pkg1
IS
PROCEDURE t1_populate(numrounds INTEGER)
IS
i INTEGER;
BEGIN
INSERT INTO t1 VALUES('Y');
FOR i IN 1..numrounds LOOP
INSERT INTO t1 SELECT * FROM t1;
END LOOP;
END;
FUNCTION f3_deterministic() RETURN CHAR(1) DETERMINISTIC COMMENT 'xxx'
IS
BEGIN
RETURN 'X';
END;
FUNCTION f4_not_deterministic() RETURN CHAR(1)
IS
BEGIN
RETURN 'X';
END;
END;
//
DELIMITER ;//
CALL pkg1.t1_populate(3);
EXPLAIN EXTENDED SELECT 'Deterministic function', COUNT(*) FROM t1 WHERE c1 = f1_deterministic();
EXPLAIN EXTENDED SELECT 'Non-deterministic function', COUNT(*) FROM t1 WHERE c1 = f2_not_deterministic();
EXPLAIN EXTENDED SELECT 'Deterministic package function', COUNT(*) FROM t1 WHERE c1 = pkg1.f3_deterministic();
EXPLAIN EXTENDED SELECT 'Non-deterministic package function', COUNT(*) FROM t1 WHERE c1 = pkg1.f4_not_deterministic();
DROP TABLE t1;
DROP FUNCTION f1_deterministic;
DROP FUNCTION f2_not_deterministic;
DROP PACKAGE pkg1;

View File

@@ -9,6 +9,7 @@
-- source include/have_file_key_management_plugin.inc
-- source include/innodb_page_size_small.inc
-- source include/innodb_checksum_algorithm.inc
-- source include/maybe_debug.inc
if (!$INNOCHECKSUM) {
--echo Need innochecksum binary
@@ -18,6 +19,10 @@ if (!$INNOCHECKSUM) {
--disable_query_log
# This may be triggered on a slow system or one that lacks native AIO.
call mtr.add_suppression("InnoDB: Trying to delete tablespace.*pending operations");
if ($have_debug) {
SET GLOBAL DEBUG_DBUG='+d,ib_log_checkpoint_avoid_hard';
call mtr.add_suppression("InnoDB: Crash recovery is broken due to insufficient innodb_log_file_size");
}
--enable_query_log
let $checksum_algorithm = `SELECT @@innodb_checksum_algorithm`;
@@ -259,6 +264,15 @@ print FILE pack("H*", "c00lcafedeadb017");
close FILE or die "close";
EOF
if (0 && $have_debug) { # these messages sometimes fail to appear
--let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err
--let SEARCH_PATTERN= InnoDB: Crash recovery is broken due to insufficient innodb_log_file_size; last checkpoint LSN=\\d+, current LSN=\\d+\\. Shutdown is in progress\\..*InnoDB: Crash recovery was broken.*
--echo # FOUND 1 is expected for both.
--source include/search_pattern_in_file.inc
--let SEARCH_PATTERN= InnoDB: Crash recovery was broken
--source include/search_pattern_in_file.inc
}
-- disable_result_log
--error 1
--exec $INNOCHECKSUM $t1_IBD

View File

@@ -0,0 +1,9 @@
@@ -377,8 +377,6 @@
c09 text, c10 text, c11 text, c12 text) ENGINE=InnoDB;
SET GLOBAL INNODB_DEFAULT_ROW_FORMAT= COMPACT;
ALTER TABLE t1 FORCE;
-Warnings:
-Warning 139 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
INSERT IGNORE INTO t1 VALUES
(1, REPEAT('x',4805), REPEAT('t',2211), REPEAT('u',974), REPEAT('e',871), REPEAT('z',224), REPEAT('j',978), REPEAT('n',190), REPEAT('t',888), REPEAT('x',32768), REPEAT('e',968), REPEAT('b',913), REPEAT('x',12107)),
(2, REPEAT('x',4805), REPEAT('t',2211), REPEAT('u',974), REPEAT('e',871), REPEAT('z',224), REPEAT('j',978), REPEAT('n',190), REPEAT('t',888), REPEAT('x',32768), REPEAT('e',968), REPEAT('b',913), REPEAT('x',12107));

View File

@@ -0,0 +1,9 @@
@@ -377,8 +377,6 @@
c09 text, c10 text, c11 text, c12 text) ENGINE=InnoDB;
SET GLOBAL INNODB_DEFAULT_ROW_FORMAT= COMPACT;
ALTER TABLE t1 FORCE;
-Warnings:
-Warning 139 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
INSERT IGNORE INTO t1 VALUES
(1, REPEAT('x',4805), REPEAT('t',2211), REPEAT('u',974), REPEAT('e',871), REPEAT('z',224), REPEAT('j',978), REPEAT('n',190), REPEAT('t',888), REPEAT('x',32768), REPEAT('e',968), REPEAT('b',913), REPEAT('x',12107)),
(2, REPEAT('x',4805), REPEAT('t',2211), REPEAT('u',974), REPEAT('e',871), REPEAT('z',224), REPEAT('j',978), REPEAT('n',190), REPEAT('t',888), REPEAT('x',32768), REPEAT('e',968), REPEAT('b',913), REPEAT('x',12107));

View File

@@ -186,12 +186,31 @@ DROP TABLE t;
# MDEV-28327 InnoDB persistent statistics fail to update
# after bulk insert
#
CREATE TABLE t1 (a INT PRIMARY KEY)ENGINE=InnoDB;
CREATE TABLE t1 (a INT PRIMARY KEY)ENGINE=InnoDB
STATS_PERSISTENT=1 STATS_AUTO_RECALC=1;
INSERT INTO t1 SELECT * FROM seq_1_to_4096;
# Wait till statistics update after bulk insert operation
SELECT n_rows FROM mysql.innodb_table_stats WHERE TABLE_NAME="t1";
n_rows
4096
SELECT n_rows>=4000 FROM mysql.innodb_table_stats WHERE TABLE_NAME="t1";
n_rows>=4000
1
DROP TABLE t1;
#
# MDEV-27214 Import with disabled keys corrupts meta-data like rows, indexes, ...
#
SET UNIQUE_CHECKS=0;
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE `t1` (
`id` int(11) NOT NULL,
`a` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
STATS_PERSISTENT=1 STATS_AUTO_RECALC=1;
INSERT INTO `t1` VALUES (1,2),(2,3),(3,4);
# Wait till statistics update after bulk insert operation
SELECT TABLE_ROWS, AVG_ROW_LENGTH>0 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test';
TABLE_ROWS AVG_ROW_LENGTH>0
3 1
DROP TABLE t1;
# End of 10.6 tests
#
@@ -351,7 +370,7 @@ DROP TABLE t1, t2;
# MDEV-29801 Inconsistent ER_TOO_BIG_ROWSIZE during bulk
# insert operation
#
call mtr.add_suppression("InnoDB: Cannot add field `c11` in table");
call mtr.add_suppression("InnoDB: Cannot add field `(c0[36]|c11)` in table");
SET @format= @@innodb_default_row_format;
CREATE TABLE t1 (pk int primary key, c01 text, c02 text, c03 text,
c04 text, c05 text, c06 text, c07 text, c08 text,

View File

@@ -0,0 +1,30 @@
#
# Start of 10.6 tests
#
#
# MDEV-27214 Import with disabled keys corrupts meta-data like rows, indexes, ...
#
CREATE DATABASE db1;
CREATE TABLE db1.t1 (id int, a int,PRIMARY KEY (id)) ENGINE=InnoDB
STATS_PERSISTENT=1 STATS_AUTO_RECALC=1;
INSERT INTO db1.t1 VALUES (1,2),(2,3),(3,4);
DROP DATABASE IF EXISTS db1;
CREATE DATABASE db1;
# Wait till statistics update after bulk insert operation
SELECT TABLE_ROWS, AVG_ROW_LENGTH>0 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='db1';
TABLE_ROWS AVG_ROW_LENGTH>0
3 1
OPTIMIZE TABLE db1.t1;
Table Op Msg_type Msg_text
db1.t1 optimize note Table does not support optimize, doing recreate + analyze instead
db1.t1 optimize status OK
# Wait till statistics update after bulk insert operation
SELECT TABLE_ROWS, AVG_ROW_LENGTH>0 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='db1';
TABLE_ROWS AVG_ROW_LENGTH>0
3 1
DROP DATABASE db1;
#
# End of 10.6 tests
#

View File

@@ -789,4 +789,16 @@ CHECK TABLE t EXTENDED;
Table Op Msg_type Msg_text
test.t check status OK
DROP TEMPORARY TABLE t;
#
# MDEV-29978 Corruption errors upon CHECK on temporary InnoDB table
#
CREATE TEMPORARY TABLE t (f INT UNIQUE) ENGINE=InnoDB;
INSERT INTO t (f) VALUES (1),(2);
CHECK TABLE t;
Table Op Msg_type Msg_text
test.t check status OK
CHECK TABLE t EXTENDED;
Table Op Msg_type Msg_text
test.t check status OK
DROP TEMPORARY TABLE t;
# End of 10.6 tests

View File

@@ -1,5 +1,5 @@
--source include/have_innodb.inc
--source include/innodb_page_size.inc
--source include/have_sequence.inc
--source include/maybe_debug.inc
--source include/have_partition.inc
@@ -199,15 +199,41 @@ DROP TABLE t;
--echo # MDEV-28327 InnoDB persistent statistics fail to update
--echo # after bulk insert
--echo #
CREATE TABLE t1 (a INT PRIMARY KEY)ENGINE=InnoDB;
CREATE TABLE t1 (a INT PRIMARY KEY)ENGINE=InnoDB
STATS_PERSISTENT=1 STATS_AUTO_RECALC=1;
INSERT INTO t1 SELECT * FROM seq_1_to_4096;
--echo # Wait till statistics update after bulk insert operation
let $wait_condition= select n_rows > 100 from mysql.innodb_table_stats
where table_name="t1";
source include/wait_condition.inc;
SELECT n_rows FROM mysql.innodb_table_stats WHERE TABLE_NAME="t1";
# At innodb_page_size=4k this will be only 4075, not 4096. Add some slack.
# This is related to MDEV-24621 and possibly MDEV-26740.
SELECT n_rows>=4000 FROM mysql.innodb_table_stats WHERE TABLE_NAME="t1";
DROP TABLE t1;
--echo #
--echo # MDEV-27214 Import with disabled keys corrupts meta-data like rows, indexes, ...
--echo #
SET UNIQUE_CHECKS=0;
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE `t1` (
`id` int(11) NOT NULL,
`a` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
STATS_PERSISTENT=1 STATS_AUTO_RECALC=1;
INSERT INTO `t1` VALUES (1,2),(2,3),(3,4);
--echo # Wait till statistics update after bulk insert operation
let $wait_condition= select n_rows > 0 from mysql.innodb_table_stats
where database_name='test' and table_name='t1';
source include/wait_condition.inc;
SELECT TABLE_ROWS, AVG_ROW_LENGTH>0 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test';
DROP TABLE t1;
--echo # End of 10.6 tests
--echo #
@@ -363,13 +389,14 @@ DROP TABLE t1, t2;
--echo # MDEV-29801 Inconsistent ER_TOO_BIG_ROWSIZE during bulk
--echo # insert operation
--echo #
call mtr.add_suppression("InnoDB: Cannot add field `c11` in table");
call mtr.add_suppression("InnoDB: Cannot add field `(c0[36]|c11)` in table");
SET @format= @@innodb_default_row_format;
CREATE TABLE t1 (pk int primary key, c01 text, c02 text, c03 text,
c04 text, c05 text, c06 text, c07 text, c08 text,
c09 text, c10 text, c11 text, c12 text) ENGINE=InnoDB;
SET GLOBAL INNODB_DEFAULT_ROW_FORMAT= COMPACT;
--replace_result 1982 8126 4030 8126
ALTER TABLE t1 FORCE;
INSERT IGNORE INTO t1 VALUES
(1, REPEAT('x',4805), REPEAT('t',2211), REPEAT('u',974), REPEAT('e',871), REPEAT('z',224), REPEAT('j',978), REPEAT('n',190), REPEAT('t',888), REPEAT('x',32768), REPEAT('e',968), REPEAT('b',913), REPEAT('x',12107)),

View File

@@ -0,0 +1,43 @@
--source include/not_embedded.inc
--source include/have_innodb.inc
--source include/innodb_page_size.inc
--source include/maybe_debug.inc
--echo #
--echo # Start of 10.6 tests
--echo #
--echo #
--echo # MDEV-27214 Import with disabled keys corrupts meta-data like rows, indexes, ...
--echo #
CREATE DATABASE db1;
CREATE TABLE db1.t1 (id int, a int,PRIMARY KEY (id)) ENGINE=InnoDB
STATS_PERSISTENT=1 STATS_AUTO_RECALC=1;
INSERT INTO db1.t1 VALUES (1,2),(2,3),(3,4);
--let $file = $MYSQLTEST_VARDIR/tmp/dump.sql
--exec $MYSQL_DUMP db1 t1 >$file
DROP DATABASE IF EXISTS db1;
CREATE DATABASE db1;
--exec $MYSQL db1 < $file
--remove_file $file
--echo # Wait till statistics update after bulk insert operation
let $wait_condition= select n_rows > 0 from mysql.innodb_table_stats
where database_name='db1' and table_name='t1';
source include/wait_condition.inc;
SELECT TABLE_ROWS, AVG_ROW_LENGTH>0 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='db1';
OPTIMIZE TABLE db1.t1;
--echo # Wait till statistics update after bulk insert operation
let $wait_condition= select n_rows > 0 from mysql.innodb_table_stats
where database_name='db1' and table_name='t1';
source include/wait_condition.inc;
SELECT TABLE_ROWS, AVG_ROW_LENGTH>0 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='db1';
DROP DATABASE db1;
--echo #
--echo # End of 10.6 tests
--echo #

View File

@@ -624,4 +624,15 @@ UPDATE t SET a=2;
CHECK TABLE t;
CHECK TABLE t EXTENDED;
DROP TEMPORARY TABLE t;
--echo #
--echo # MDEV-29978 Corruption errors upon CHECK on temporary InnoDB table
--echo #
CREATE TEMPORARY TABLE t (f INT UNIQUE) ENGINE=InnoDB;
INSERT INTO t (f) VALUES (1),(2);
CHECK TABLE t;
CHECK TABLE t EXTENDED;
DROP TEMPORARY TABLE t;
--echo # End of 10.6 tests

View File

@@ -1,3 +1,4 @@
reset master;
call mtr.add_suppression("Table was marked as crashed");
call mtr.add_suppression("Checking table: .*");
create table t1 (a int primary key auto_increment, b int) engine=aria transactional= 1;

View File

@@ -3,6 +3,8 @@
# no-protocol doesn't print warnings about repaired tables
--source include/no_protocol.inc
reset master; # clear binlogs
call mtr.add_suppression("Table was marked as crashed");
call mtr.add_suppression("Checking table: .*");

View File

@@ -1,6 +1,7 @@
call mtr.add_suppression("InnoDB: Expected tablespace id .*");
# Mariabackup --backup with page0 INIT_PAGE redo record
# and there is no FILE_CREATE for the tablespace t1
SET @save_dbug = @@SESSION.debug_dbug;
SET DEBUG_DBUG="+d,checkpoint_after_file_create";
CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
@@ -14,7 +15,7 @@ SELECT * FROM t1;
f1
1
DROP TABLE t1;
SET DEBUG_DBUG="-d,checkpoint_after_file_create";
SET @@SESSION.DEBUG_DBUG= @save_debug;
# Mariabackup fails after corrupting the page0 in disk
# and there is no INIT_PAGE for page0
CREATE TABLE t1(c INT) ENGINE=INNODB;

View File

@@ -6,6 +6,7 @@
call mtr.add_suppression("InnoDB: Expected tablespace id .*");
--echo # Mariabackup --backup with page0 INIT_PAGE redo record
--echo # and there is no FILE_CREATE for the tablespace t1
SET @save_dbug = @@SESSION.debug_dbug;
SET DEBUG_DBUG="+d,checkpoint_after_file_create";
CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
@@ -26,7 +27,7 @@ exec $XTRABACKUP --prepare --target-dir=$targetdir;
SELECT * FROM t1;
DROP TABLE t1;
rmdir $targetdir;
SET DEBUG_DBUG="-d,checkpoint_after_file_create";
SET @@SESSION.DEBUG_DBUG= @save_debug;
--echo # Mariabackup fails after corrupting the page0 in disk
--echo # and there is no INIT_PAGE for page0
@@ -39,16 +40,13 @@ let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
--echo # Corrupt the table
perl;
use strict;
use warnings;
use Fcntl qw(:DEFAULT :seek);
my $page_size = $ENV{INNODB_PAGE_SIZE};
my $ps = $ENV{INNODB_PAGE_SIZE};
sysopen FILE, "$ENV{MYSQLD_DATADIR}/test/t1.ibd", O_RDWR
|| die "Cannot open t1.ibd\n";
sysseek(FILE, 0, SEEK_SET) || die "Cannot seek t1.ibd\n";
my $page=chr(0) x $page_size;
syswrite(FILE, $page, $page_size)==$page_size;
my $file = "$ENV{MYSQLD_DATADIR}/test/t1.ibd";
open(FILE, "+<$file") || die "Unable to open $file";
binmode FILE;
seek (FILE, 0, SEEK_SET) or die "seek";
print FILE chr(0x00) x $ps;
close FILE or die "close";
EOF

View File

@@ -1,4 +1,5 @@
--source include/not_embedded.inc
--source include/have_wsrep.inc
#
# @@global.wsrep_on is not allowed if there

View File

@@ -96,6 +96,16 @@ with system versioning
partition by system_time (
partition p0 history,
partition pn current);
create or replace table t1 (a int)
partition by range (a) (
partition p0 history,
partition p1 current);
ERROR HY000: Wrong partition type `SYSTEM_TIME` for partitioning by `RANGE`
create or replace table t1 (b int)
partition by range (a) (
partition p0 current,
partition p1 history);
ERROR HY000: Wrong partition type `SYSTEM_TIME` for partitioning by `RANGE`
## ALTER TABLE
alter table t1 add partition (
partition p1 current);
@@ -150,7 +160,7 @@ partition by system_time limit 1;
alter table t1 change x big int;
create or replace table t1 (i int) engine myisam partition by hash(i) partitions 2;
alter table t1 add partition (partition px history);
ERROR HY000: Wrong partitioning type, expected type: `SYSTEM_TIME`
ERROR HY000: Wrong partition type `SYSTEM_TIME` for partitioning by `HASH`
## INSERT, UPDATE, DELETE
create or replace table t1 (x int)
with system versioning
@@ -1105,7 +1115,7 @@ drop table t1;
create table t1 (a int) with system versioning partition by system_time
(partition p1 history, partition pn current);
alter table t1 add partition (partition p2);
ERROR HY000: Wrong partitioning type, expected type: `SYSTEM_TIME`
ERROR HY000: Wrong partition type `HASH` for partitioning by `SYSTEM_TIME`
# MDEV-17891 Assertion failures in select_insert::abort_result_set and
# mysql_load upon attempt to replace into a full table
set @@max_heap_table_size= 1024*1024;

View File

@@ -106,6 +106,18 @@ partition by system_time (
partition p0 history,
partition pn current);
--error ER_PARTITION_WRONG_TYPE
create or replace table t1 (a int)
partition by range (a) (
partition p0 history,
partition p1 current);
--error ER_PARTITION_WRONG_TYPE
create or replace table t1 (b int)
partition by range (a) (
partition p0 current,
partition p1 history);
--echo ## ALTER TABLE

View File

@@ -116,7 +116,7 @@ my_bool my_gethwaddr(uchar *to)
uint i;
for (i= 0; res && i < ifc.ifc_len / sizeof(ifr[0]); i++)
{
#if !defined(_AIX) || !defined(__linux__)
#if defined(_AIX) || defined(__linux__)
#if defined(__linux__)
#define HWADDR_DATA ifr[i].ifr_hwaddr.sa_data
#else

View File

@@ -429,8 +429,13 @@ public:
return NULL;
}
uint next_part_no(uint new_parts) const;
int gen_part_type(THD *thd, String *str) const;
};
void part_type_error(THD *thd, partition_info *work_part_info,
const char *part_type, partition_info *tab_part_info);
uint32 get_next_partition_id_range(struct st_partition_iter* part_iter);
bool check_partition_dirs(partition_info *part_info);

View File

@@ -9773,9 +9773,9 @@ ER_UNUSED_23
spa "Nunca debería vd de ver esto"
ER_PARTITION_WRONG_TYPE
chi "错误的分区类型,预期类型:%`s"
eng "Wrong partitioning type, expected type: %`s"
spa "Tipo de partición equivocada, tipo esperado: %`s"
chi "错误的分区类型,预期类型:%`s for partitioning by %`s"
eng "Wrong partition type %`s for partitioning by %`s"
spa "Tipo de partición equivocada, tipo esperado: %`s for partitioning by %`s"
WARN_VERS_PART_FULL
chi "版本化表%`s.%`spartition%`s已满添加更多历史分区(out of %s)"

View File

@@ -9754,6 +9754,7 @@ bool Lex_ident_sys_st::to_size_number(ulonglong *to) const
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
bool LEX::part_values_current(THD *thd)
{
partition_element *elem= part_info->curr_part_elem;
@@ -9761,7 +9762,7 @@ bool LEX::part_values_current(THD *thd)
{
if (unlikely(part_info->part_type != VERSIONING_PARTITION))
{
my_error(ER_PARTITION_WRONG_TYPE, MYF(0), "SYSTEM_TIME");
part_type_error(thd, NULL, "SYSTEM_TIME", part_info);
return true;
}
}
@@ -9788,7 +9789,7 @@ bool LEX::part_values_history(THD *thd)
{
if (unlikely(part_info->part_type != VERSIONING_PARTITION))
{
my_error(ER_PARTITION_WRONG_TYPE, MYF(0), "SYSTEM_TIME");
part_type_error(thd, NULL, "SYSTEM_TIME", part_info);
return true;
}
}
@@ -9809,6 +9810,7 @@ bool LEX::part_values_history(THD *thd)
elem->type= partition_element::HISTORY;
return false;
}
#endif /* WITH_PARTITION_STORAGE_ENGINE */
bool LEX::last_field_generated_always_as_row_start_or_end(Lex_ident *p,

View File

@@ -3776,8 +3776,10 @@ public:
bool table_or_sp_used();
bool is_partition_management() const;
#ifdef WITH_PARTITION_STORAGE_ENGINE
bool part_values_current(THD *thd);
bool part_values_history(THD *thd);
#endif
/**
@brief check if the statement is a single-level join

View File

@@ -2470,7 +2470,7 @@ end:
@retval != 0 Failure
*/
static int add_key_with_algorithm(String *str, partition_info *part_info)
static int add_key_with_algorithm(String *str, const partition_info *part_info)
{
int err= 0;
err+= str->append(STRING_WITH_LEN("KEY "));
@@ -2499,6 +2499,78 @@ char *generate_partition_syntax_for_frm(THD *thd, partition_info *part_info,
return res;
}
/*
Generate the partition type syntax from the partition data structure.
@return Operation status.
@retval 0 Success
@retval > 0 Failure
@retval -1 Fatal error
*/
int partition_info::gen_part_type(THD *thd, String *str) const
{
int err= 0;
switch (part_type)
{
case RANGE_PARTITION:
err+= str->append(STRING_WITH_LEN("RANGE "));
break;
case LIST_PARTITION:
err+= str->append(STRING_WITH_LEN("LIST "));
break;
case HASH_PARTITION:
if (linear_hash_ind)
err+= str->append(STRING_WITH_LEN("LINEAR "));
if (list_of_part_fields)
{
err+= add_key_with_algorithm(str, this);
err+= add_part_field_list(thd, str, part_field_list);
}
else
err+= str->append(STRING_WITH_LEN("HASH "));
break;
case VERSIONING_PARTITION:
err+= str->append(STRING_WITH_LEN("SYSTEM_TIME "));
break;
default:
DBUG_ASSERT(0);
/* We really shouldn't get here, no use in continuing from here */
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL));
return -1;
}
return err;
}
void part_type_error(THD *thd, partition_info *work_part_info,
const char *part_type,
partition_info *tab_part_info)
{
StringBuffer<256> tab_part_type;
if (tab_part_info->gen_part_type(thd, &tab_part_type) < 0)
return;
tab_part_type.length(tab_part_type.length() - 1);
if (work_part_info)
{
DBUG_ASSERT(!part_type);
StringBuffer<256> work_part_type;
if (work_part_info->gen_part_type(thd, &work_part_type) < 0)
return;
work_part_type.length(work_part_type.length() - 1);
my_error(ER_PARTITION_WRONG_TYPE, MYF(0), work_part_type.c_ptr(),
tab_part_type.c_ptr());
}
else
{
DBUG_ASSERT(part_type);
my_error(ER_PARTITION_WRONG_TYPE, MYF(0), part_type,
tab_part_type.c_ptr());
}
}
/*
Generate the partition syntax from the partition data structure.
Useful for support of generating defaults, SHOW CREATE TABLES
@@ -2542,34 +2614,10 @@ char *generate_partition_syntax(THD *thd, partition_info *part_info,
DBUG_ENTER("generate_partition_syntax");
err+= str.append(STRING_WITH_LEN(" PARTITION BY "));
switch (part_info->part_type)
{
case RANGE_PARTITION:
err+= str.append(STRING_WITH_LEN("RANGE "));
break;
case LIST_PARTITION:
err+= str.append(STRING_WITH_LEN("LIST "));
break;
case HASH_PARTITION:
if (part_info->linear_hash_ind)
err+= str.append(STRING_WITH_LEN("LINEAR "));
if (part_info->list_of_part_fields)
{
err+= add_key_with_algorithm(&str, part_info);
err+= add_part_field_list(thd, &str, part_info->part_field_list);
}
else
err+= str.append(STRING_WITH_LEN("HASH "));
break;
case VERSIONING_PARTITION:
err+= str.append(STRING_WITH_LEN("SYSTEM_TIME "));
break;
default:
DBUG_ASSERT(0);
/* We really shouldn't get here, no use in continuing from here */
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL));
int err2= part_info->gen_part_type(thd, &str);
if (err2 < 0)
DBUG_RETURN(NULL);
}
err+= err2;
if (part_info->part_type == VERSIONING_PARTITION)
{
Vers_part_info *vers_info= part_info->vers_info;
@@ -5069,7 +5117,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
else if (thd->work_part_info->part_type == VERSIONING_PARTITION ||
tab_part_info->part_type == VERSIONING_PARTITION)
{
my_error(ER_PARTITION_WRONG_TYPE, MYF(0), "SYSTEM_TIME");
part_type_error(thd, thd->work_part_info, NULL, tab_part_info);
}
else
{

View File

@@ -7901,6 +7901,7 @@ void append_drop_column(THD *thd, String *str, Field *field)
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
static inline
void rename_field_in_list(Create_field *field, List<const char> *field_list)
{
@@ -7913,6 +7914,7 @@ void rename_field_in_list(Create_field *field, List<const char> *field_list)
it.replace(field->field_name.str);
}
}
#endif
/**

View File

@@ -4803,13 +4803,17 @@ opt_part_values:
part_values_in {}
| CURRENT_SYM
{
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (Lex->part_values_current(thd))
MYSQL_YYABORT;
#endif
}
| HISTORY_SYM
{
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (Lex->part_values_history(thd))
MYSQL_YYABORT;
#endif
}
| DEFAULT
{
@@ -18874,6 +18878,7 @@ package_implementation_function_body:
sp_head *sp= pkg->m_current_routine->sphead;
thd->lex= pkg->m_current_routine;
sp->reset_thd_mem_root(thd);
sp->set_c_chistics(thd->lex->sp_chistics);
sp->set_body_start(thd, YYLIP->get_cpp_tok_start());
}
sp_body opt_package_routine_end_name
@@ -18892,6 +18897,7 @@ package_implementation_procedure_body:
sp_head *sp= pkg->m_current_routine->sphead;
thd->lex= pkg->m_current_routine;
sp->reset_thd_mem_root(thd);
sp->set_c_chistics(thd->lex->sp_chistics);
sp->set_body_start(thd, YYLIP->get_cpp_tok_start());
}
sp_body opt_package_routine_end_name

View File

@@ -270,8 +270,7 @@ SET(INNOBASE_SOURCES
include/handler0alter.h
include/hash0hash.h
include/ibuf0ibuf.h
include/ibuf0ibuf.inl/
include/ibuf0types.h
include/ibuf0ibuf.inl
include/lock0iter.h
include/lock0lock.h
include/lock0lock.inl
@@ -289,7 +288,6 @@ SET(INNOBASE_SOURCES
include/mem0mem.inl
include/mtr0log.h
include/mtr0mtr.h
include/mtr0mtr.inl
include/mtr0types.h
include/os0file.h
include/os0file.inl

File diff suppressed because it is too large Load Diff

View File

@@ -827,7 +827,6 @@ PageBulk::storeExt(
btr_pcur_t btr_pcur;
btr_pcur.pos_state = BTR_PCUR_IS_POSITIONED;
btr_pcur.latch_mode = BTR_MODIFY_LEAF;
btr_pcur.btr_cur.index = m_index;
btr_pcur.btr_cur.page_cur.index = m_index;
btr_pcur.btr_cur.page_cur.rec = m_cur_rec;
btr_pcur.btr_cur.page_cur.offsets = offsets;

File diff suppressed because it is too large Load Diff

View File

@@ -169,7 +169,7 @@ btr_defragment_find_index(
@return whether the operation was interrupted */
bool btr_defragment_add_index(btr_pcur_t *pcur, THD *thd)
{
dict_stats_empty_defrag_summary(pcur->btr_cur.index);
dict_stats_empty_defrag_summary(pcur->index());
pthread_cond_t cond;
pthread_cond_init(&cond, nullptr);
btr_defragment_item_t item(pcur, &cond);
@@ -209,7 +209,7 @@ btr_defragment_remove_table(
mysql_mutex_lock(&btr_defragment_mutex);
for (auto item : btr_defragment_wq)
{
if (item->cond && table == item->pcur->btr_cur.index->table)
if (item->cond && table == item->pcur->index()->table)
{
pthread_cond_signal(item->cond);
item->cond= nullptr;
@@ -405,7 +405,10 @@ btr_defragment_merge_pages(
}
}
btr_cur_t parent;
if (!btr_page_get_father(index, from_block, mtr, &parent)) {
parent.page_cur.index = index;
parent.page_cur.block = from_block;
if (!btr_page_get_father(mtr, &parent)) {
to_block = nullptr;
} else if (n_recs_to_move == n_recs) {
/* The whole page is merged with the previous page,
@@ -690,7 +693,7 @@ processed:
}
log_free_check();
mtr_start(&mtr);
dict_index_t *index = item->pcur->btr_cur.index;
dict_index_t *index = item->pcur->index();
index->set_modified(mtr);
/* To follow the latching order defined in WL#6326,
acquire index->lock X-latch. This entitles us to

View File

@@ -29,25 +29,6 @@ Created 2/23/1996 Heikki Tuuri
#include "rem0cmp.h"
#include "trx0trx.h"
/**************************************************************//**
Allocates memory for a persistent cursor object and initializes the cursor.
@return own: persistent cursor */
btr_pcur_t*
btr_pcur_create_for_mysql(void)
/*============================*/
{
btr_pcur_t* pcur;
DBUG_ENTER("btr_pcur_create_for_mysql");
pcur = (btr_pcur_t*) ut_malloc_nokey(sizeof(btr_pcur_t));
pcur->btr_cur.index = NULL;
btr_pcur_init(pcur);
DBUG_PRINT("btr_pcur_create_for_mysql", ("pcur: %p", pcur));
DBUG_RETURN(pcur);
}
/**************************************************************//**
Resets a persistent cursor object, freeing ::old_rec_buf if it is
allocated and resetting the other members to their initial values. */
@@ -56,34 +37,17 @@ btr_pcur_reset(
/*===========*/
btr_pcur_t* cursor) /*!< in, out: persistent cursor */
{
btr_pcur_free(cursor);
ut_free(cursor->old_rec_buf);
memset(&cursor->btr_cur.page_cur, 0, sizeof(page_cur_t));
cursor->old_rec_buf = NULL;
cursor->btr_cur.index = NULL;
cursor->btr_cur.page_cur.rec = NULL;
cursor->old_rec = NULL;
cursor->old_n_core_fields = 0;
cursor->old_n_fields = 0;
cursor->old_stored = false;
cursor->latch_mode = BTR_NO_LATCHES;
cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
}
/**************************************************************//**
Frees the memory for a persistent cursor object. */
void
btr_pcur_free_for_mysql(
/*====================*/
btr_pcur_t* cursor) /*!< in, own: persistent cursor */
{
DBUG_ENTER("btr_pcur_free_for_mysql");
DBUG_PRINT("btr_pcur_free_for_mysql", ("pcur: %p", cursor));
btr_pcur_free(cursor);
ut_free(cursor);
DBUG_VOID_RETURN;
}
/**************************************************************//**
The position of the cursor is stored by taking an initial segment of the
record the cursor is positioned on, before, or after, and copying it to the
@@ -125,8 +89,6 @@ btr_pcur_store_position(
&& mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK)));
cursor->old_stored = true;
if (page_is_empty(block->page.frame)) {
/* It must be an empty index tree; NOTE that in this case
we do not store the modify_clock, but always do a search
@@ -256,11 +218,12 @@ otherwise. */
struct optimistic_latch_leaves
{
btr_pcur_t *const cursor;
ulint *latch_mode;
btr_latch_mode *latch_mode;
mtr_t *const mtr;
optimistic_latch_leaves(btr_pcur_t *cursor, ulint *latch_mode, mtr_t *mtr)
:cursor(cursor), latch_mode(latch_mode), mtr(mtr) {}
optimistic_latch_leaves(btr_pcur_t *cursor, btr_latch_mode *latch_mode,
mtr_t *mtr)
: cursor(cursor), latch_mode(latch_mode), mtr(mtr) {}
bool operator() (buf_block_t *hint) const
{
@@ -292,7 +255,7 @@ record with the same unique field values as in the stored record,
btr_pcur_t::NOT_SAME cursor position is not on user rec or points on
the record with not the samebuniq field values as in the stored */
btr_pcur_t::restore_status
btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
btr_pcur_t::restore_position(btr_latch_mode restore_latch_mode, mtr_t *mtr)
{
dict_index_t* index;
dtuple_t* tuple;
@@ -301,7 +264,6 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
mem_heap_t* heap;
ut_ad(mtr->is_active());
//ut_ad(cursor->old_stored);
ut_ad(pos_state == BTR_PCUR_WAS_POSITIONED
|| pos_state == BTR_PCUR_IS_POSITIONED);
@@ -313,10 +275,9 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
/* In these cases we do not try an optimistic restoration,
but always do a search */
if (btr_cur_open_at_index_side(
rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
index, restore_latch_mode,
&btr_cur, 0, mtr) != DB_SUCCESS) {
if (btr_cur.open_leaf(rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
index, restore_latch_mode, mtr)
!= DB_SUCCESS) {
return restore_status::CORRUPTED;
}
@@ -333,9 +294,10 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
ut_a(old_n_core_fields <= index->n_core_fields);
ut_a(old_n_fields);
switch (restore_latch_mode) {
case BTR_SEARCH_LEAF:
case BTR_MODIFY_LEAF:
static_assert(BTR_SEARCH_PREV == (4 | BTR_SEARCH_LEAF), "");
static_assert(BTR_MODIFY_PREV == (4 | BTR_MODIFY_LEAF), "");
switch (restore_latch_mode | 4) {
case BTR_SEARCH_PREV:
case BTR_MODIFY_PREV:
/* Try optimistic restoration. */
@@ -420,7 +382,7 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
mode = PAGE_CUR_UNSUPP;
}
if (btr_pcur_open_with_no_init(index, tuple, mode, restore_latch_mode,
if (btr_pcur_open_with_no_init(tuple, mode, restore_latch_mode,
this, mtr) != DB_SUCCESS) {
mem_heap_free(heap);
return restore_status::CORRUPTED;
@@ -450,7 +412,6 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
block_when_stored.store(btr_pcur_get_block(this));
modify_clock= buf_block_get_modify_clock(
block_when_stored.block());
old_stored= true;
mem_heap_free(heap);
@@ -487,7 +448,7 @@ btr_pcur_move_to_next_page(
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
ut_ad(btr_pcur_is_after_last_on_page(cursor));
cursor->old_stored = false;
cursor->old_rec = nullptr;
const page_t* page = btr_pcur_get_page(cursor);
const uint32_t next_page_no = btr_page_get_next(page);
@@ -515,7 +476,7 @@ btr_pcur_move_to_next_page(
dberr_t err;
buf_block_t* next_block = btr_block_get(
*btr_pcur_get_btr_cur(cursor)->index, next_page_no, mode,
*cursor->index(), next_page_no, mode,
page_is_leaf(page), mtr, &err);
if (UNIV_UNLIKELY(!next_block)) {
@@ -529,12 +490,13 @@ btr_pcur_move_to_next_page(
return DB_CORRUPTION;
}
btr_leaf_page_release(btr_pcur_get_block(cursor), mode, mtr);
page_cur_set_before_first(next_block, btr_pcur_get_page_cur(cursor));
ut_d(page_check_dir(next_page));
return err;
const auto s = mtr->get_savepoint();
mtr->rollback_to_savepoint(s - 2, s - 1);
return DB_SUCCESS;
}
MY_ATTRIBUTE((nonnull,warn_unused_result))
@@ -558,7 +520,7 @@ btr_pcur_move_backward_from_page(
ut_ad(btr_pcur_is_before_first_on_page(cursor));
ut_ad(!btr_pcur_is_before_first_in_tree(cursor));
const ulint latch_mode = cursor->latch_mode;
const auto latch_mode = cursor->latch_mode;
ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF);
btr_pcur_store_position(cursor, mtr);
@@ -570,31 +532,32 @@ btr_pcur_move_backward_from_page(
static_assert(BTR_SEARCH_PREV == (4 | BTR_SEARCH_LEAF), "");
static_assert(BTR_MODIFY_PREV == (4 | BTR_MODIFY_LEAF), "");
if (UNIV_UNLIKELY(cursor->restore_position(4 | latch_mode, mtr)
if (UNIV_UNLIKELY(cursor->restore_position(
btr_latch_mode(4 | latch_mode), mtr)
== btr_pcur_t::CORRUPTED)) {
return true;
}
buf_block_t* prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
buf_block_t* release_block = nullptr;
if (!page_has_prev(btr_pcur_get_page(cursor))) {
} else if (btr_pcur_is_before_first_on_page(cursor)) {
btr_leaf_page_release(btr_pcur_get_block(cursor),
latch_mode, mtr);
page_cur_set_after_last(prev_block,
release_block = btr_pcur_get_block(cursor);
page_cur_set_after_last(cursor->btr_cur.left_block,
btr_pcur_get_page_cur(cursor));
} else {
/* The repositioned cursor did not end on an infimum
record on a page. Cursor repositioning acquired a latch
also on the previous page, but we do not need the latch:
release it. */
prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
btr_leaf_page_release(prev_block, latch_mode, mtr);
release_block = cursor->btr_cur.left_block;
}
cursor->latch_mode = latch_mode;
cursor->old_stored = false;
cursor->old_rec = nullptr;
if (release_block) {
mtr->release(*release_block);
}
return false;
}
@@ -612,7 +575,7 @@ btr_pcur_move_to_prev(
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
cursor->old_stored = false;
cursor->old_rec = nullptr;
if (btr_pcur_is_before_first_on_page(cursor)) {
return (!btr_pcur_is_before_first_in_tree(cursor)

View File

@@ -302,7 +302,7 @@ are consistent.
@param[in] cursor cursor which was just positioned */
static void btr_search_info_update_hash(btr_search_t *info, btr_cur_t *cursor)
{
dict_index_t* index = cursor->index;
dict_index_t* index = cursor->index();
int cmp;
if (dict_index_is_ibuf(index)) {
@@ -704,14 +704,14 @@ btr_search_update_hash_ref(
return;
}
if (index != cursor->index) {
ut_ad(index->id == cursor->index->id);
if (index != cursor->index()) {
ut_ad(index->id == cursor->index()->id);
btr_search_drop_page_hash_index(block);
return;
}
ut_ad(block->page.id().space() == index->table->space_id);
ut_ad(index == cursor->index);
ut_ad(index == cursor->index());
ut_ad(!dict_index_is_ibuf(index));
auto part = btr_search_sys.get_part(*index);
part->latch.wr_lock(SRW_LOCK_CALL);
@@ -784,7 +784,7 @@ btr_search_check_guess(
bool success = false;
rec_offs_init(offsets_);
n_unique = dict_index_get_n_unique_in_tree(cursor->index);
n_unique = dict_index_get_n_unique_in_tree(cursor->index());
rec = btr_cur_get_rec(cursor);
@@ -792,7 +792,7 @@ btr_search_check_guess(
|| !page_rec_is_leaf(rec))) {
ut_ad("corrupted index" == 0);
return false;
} else if (cursor->index->table->not_redundant()) {
} else if (cursor->index()->table->not_redundant()) {
switch (rec_get_status(rec)) {
case REC_STATUS_INSTANT:
case REC_STATUS_ORDINARY:
@@ -805,10 +805,10 @@ btr_search_check_guess(
match = 0;
offsets = rec_get_offsets(rec, cursor->index, offsets,
cursor->index->n_core_fields,
offsets = rec_get_offsets(rec, cursor->index(), offsets,
cursor->index()->n_core_fields,
n_unique, &heap);
cmp = cmp_dtuple_rec_with_match(tuple, rec, cursor->index, offsets,
cmp = cmp_dtuple_rec_with_match(tuple, rec, cursor->index(), offsets,
&match);
if (mode == PAGE_CUR_GE) {
@@ -860,7 +860,7 @@ btr_search_check_guess(
goto exit_func;
}
if (cursor->index->table->not_redundant()) {
if (cursor->index()->table->not_redundant()) {
switch (rec_get_status(prev_rec)) {
case REC_STATUS_INSTANT:
case REC_STATUS_ORDINARY:
@@ -871,11 +871,12 @@ btr_search_check_guess(
}
}
offsets = rec_get_offsets(prev_rec, cursor->index, offsets,
cursor->index->n_core_fields,
offsets = rec_get_offsets(prev_rec, cursor->index(), offsets,
cursor->index()->n_core_fields,
n_unique, &heap);
cmp = cmp_dtuple_rec_with_match(
tuple, prev_rec, cursor->index, offsets, &match);
cmp = cmp_dtuple_rec_with_match(tuple, prev_rec,
cursor->index(), offsets,
&match);
if (mode == PAGE_CUR_GE) {
success = cmp > 0;
} else {
@@ -900,7 +901,7 @@ btr_search_check_guess(
goto exit_func;
}
if (cursor->index->table->not_redundant()) {
if (cursor->index()->table->not_redundant()) {
switch (rec_get_status(next_rec)) {
case REC_STATUS_INSTANT:
case REC_STATUS_ORDINARY:
@@ -911,11 +912,11 @@ btr_search_check_guess(
}
}
offsets = rec_get_offsets(next_rec, cursor->index, offsets,
cursor->index->n_core_fields,
offsets = rec_get_offsets(next_rec, cursor->index(), offsets,
cursor->index()->n_core_fields,
n_unique, &heap);
cmp = cmp_dtuple_rec_with_match(
tuple, next_rec, cursor->index, offsets, &match);
tuple, next_rec, cursor->index(), offsets, &match);
if (mode == PAGE_CUR_LE) {
success = cmp < 0;
cursor->up_match = match;
@@ -1099,16 +1100,16 @@ btr_search_guess_on_hash(
part->latch.rd_lock(SRW_LOCK_CALL);
if (!btr_search_enabled) {
goto fail;
goto ahi_release_and_fail;
}
rec = static_cast<const rec_t*>(
ha_search_and_get_data(&part->table, fold));
if (!rec) {
fail:
ahi_release_and_fail:
part->latch.rd_unlock();
fail:
btr_search_failure(info, cursor);
return false;
}
@@ -1117,66 +1118,52 @@ fail:
buf_pool_t::hash_chain& chain = buf_pool.page_hash.cell_get(
block->page.id().fold());
bool fail, got_latch;
bool got_latch;
{
transactional_shared_lock_guard<page_hash_latch> g{
buf_pool.page_hash.lock_get(chain)};
const auto state = block->page.state();
if (state == buf_page_t::REMOVE_HASH) {
/* Another thread is just freeing the block
from the LRU list of the buffer pool: do not
try to access this page. */
goto fail;
}
if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED)) {
#ifndef NO_ELISION
xend();
#endif
ut_error;
}
fail = index != block->index && index_id == block->index->id;
got_latch = (latch_mode == BTR_SEARCH_LEAF)
? block->page.lock.s_lock_try()
: block->page.lock.x_lock_try();
}
ut_a(!fail || block->index->freed());
if (!got_latch) {
goto fail;
goto ahi_release_and_fail;
}
const auto state = block->page.state();
if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED)) {
ut_ad(state == buf_page_t::REMOVE_HASH);
block_and_ahi_release_and_fail:
if (latch_mode == BTR_SEARCH_LEAF) {
block->page.lock.s_unlock();
} else {
block->page.lock.x_unlock();
}
goto ahi_release_and_fail;
}
ut_ad(state < buf_page_t::READ_FIX || state >= buf_page_t::WRITE_FIX);
ut_ad(state < buf_page_t::READ_FIX || latch_mode == BTR_SEARCH_LEAF);
if (index != block->index && index_id == block->index->id) {
ut_a(block->index->freed());
goto block_and_ahi_release_and_fail;
}
block->page.fix();
block->page.set_accessed();
buf_page_make_young_if_needed(&block->page);
ut_ad(!block->page.is_read_fixed());
ut_ad(latch_mode == BTR_SEARCH_LEAF || !block->page.is_io_fixed());
static_assert(ulint{MTR_MEMO_PAGE_S_FIX} == ulint{BTR_SEARCH_LEAF},
"");
static_assert(ulint{MTR_MEMO_PAGE_X_FIX} == ulint{BTR_MODIFY_LEAF},
"");
mtr->memo_push(block, mtr_memo_type_t(latch_mode));
++buf_pool.stat.n_page_gets;
part->latch.rd_unlock();
if (UNIV_UNLIKELY(fail)) {
goto fail_and_release_page;
}
++buf_pool.stat.n_page_gets;
DBUG_ASSERT(!block->page.is_freed());
if (!block->page.in_file()) {
ut_ad(block->page.state() == buf_page_t::REMOVE_HASH);
fail_and_release_page:
btr_leaf_page_release(block, latch_mode, mtr);
btr_search_failure(info, cursor);
return false;
}
mtr->memo_push(block, mtr_memo_type_t(latch_mode));
ut_ad(page_rec_is_user_rec(rec));
@@ -1191,7 +1178,8 @@ fail_and_release_page:
right. */
if (index_id != btr_page_get_index_id(block->page.frame)
|| !btr_search_check_guess(cursor, false, tuple, mode)) {
goto fail_and_release_page;
mtr->release_last_page();
goto fail;
}
if (info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5) {
@@ -1199,41 +1187,6 @@ fail_and_release_page:
info->n_hash_potential++;
}
#ifdef notdefined
/* These lines of code can be used in a debug version to check
the correctness of the searched cursor position: */
info->last_hash_succ = FALSE;
/* Currently, does not work if the following fails: */
ut_ad(!ahi_latch);
btr_leaf_page_release(block, latch_mode, mtr);
btr_cur_search_to_nth_level(
index, 0, tuple, mode, latch_mode, &cursor2, 0, mtr);
if (mode == PAGE_CUR_GE
&& page_rec_is_supremum(btr_cur_get_rec(&cursor2))) {
/* If mode is PAGE_CUR_GE, then the binary search
in the index tree may actually take us to the supremum
of the previous page */
info->last_hash_succ = FALSE;
btr_pcur_open_on_user_rec(
index, tuple, mode, latch_mode, &pcur, mtr);
ut_ad(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor));
} else {
ut_ad(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor));
}
/* NOTE that it is theoretically possible that the above assertions
fail if the page of the cursor gets removed from the buffer pool
meanwhile! Thus it might not be a bug. */
#endif
info->last_hash_succ = TRUE;
#ifdef UNIV_SEARCH_PERF_STAT
@@ -1691,7 +1644,7 @@ exit_func:
@param[in,out] cursor cursor which was just positioned */
void btr_search_info_update_slow(btr_search_t *info, btr_cur_t *cursor)
{
srw_spin_lock* ahi_latch = &btr_search_sys.get_part(*cursor->index)
srw_spin_lock* ahi_latch = &btr_search_sys.get_part(*cursor->index())
->latch;
buf_block_t* block = btr_cur_get_block(cursor);
@@ -1706,7 +1659,7 @@ void btr_search_info_update_slow(btr_search_t *info, btr_cur_t *cursor)
if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
btr_search_check_free_space_in_heap(cursor->index);
btr_search_check_free_space_in_heap(cursor->index());
}
if (cursor->flag == BTR_CUR_HASH_FAIL) {
@@ -1723,7 +1676,7 @@ void btr_search_info_update_slow(btr_search_t *info, btr_cur_t *cursor)
/* Note that since we did not protect block->n_fields etc.
with any semaphore, the values can be inconsistent. We have
to check inside the function call that they make sense. */
btr_search_build_page_hash_index(cursor->index, block,
btr_search_build_page_hash_index(cursor->index(), block,
ahi_latch,
block->n_fields,
block->n_bytes,
@@ -1835,15 +1788,15 @@ void btr_search_update_hash_on_delete(btr_cur_t *cursor)
return;
}
ut_ad(!cursor->index->table->is_temporary());
ut_ad(!cursor->index()->table->is_temporary());
if (index != cursor->index) {
if (index != cursor->index()) {
btr_search_drop_page_hash_index(block);
return;
}
ut_ad(block->page.id().space() == index->table->space_id);
ut_a(index == cursor->index);
ut_a(index == cursor->index());
ut_a(block->curr_n_fields > 0 || block->curr_n_bytes > 0);
ut_ad(!dict_index_is_ibuf(index));
@@ -1890,7 +1843,7 @@ void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
dict_index_t* index;
rec_t* rec;
ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index)->latch);
ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index())->latch);
if (!btr_search_enabled) {
return;
@@ -1909,15 +1862,15 @@ void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
return;
}
ut_ad(!cursor->index->table->is_temporary());
ut_ad(!cursor->index()->table->is_temporary());
if (index != cursor->index) {
ut_ad(index->id == cursor->index->id);
if (index != cursor->index()) {
ut_ad(index->id == cursor->index()->id);
btr_search_drop_page_hash_index(block);
return;
}
ut_a(cursor->index == index);
ut_a(cursor->index() == index);
ut_ad(!dict_index_is_ibuf(index));
ahi_latch->wr_lock(SRW_LOCK_CALL);
@@ -1934,7 +1887,7 @@ void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
&& !block->curr_left_side) {
if (const rec_t *new_rec = page_rec_get_next_const(rec)) {
if (ha_search_and_update_if_found(
&btr_search_sys.get_part(*cursor->index)
&btr_search_sys.get_part(*cursor->index())
->table,
cursor->fold, rec, block, new_rec)) {
MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_UPDATED);
@@ -1977,7 +1930,7 @@ void btr_search_update_hash_on_insert(btr_cur_t *cursor,
rec_offs* offsets = offsets_;
rec_offs_init(offsets_);
ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index)->latch);
ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index())->latch);
ut_ad(page_is_leaf(btr_cur_get_page(cursor)));
if (!btr_search_enabled) {
@@ -2001,16 +1954,16 @@ void btr_search_update_hash_on_insert(btr_cur_t *cursor,
rec = btr_cur_get_rec(cursor);
ut_ad(!cursor->index->table->is_temporary());
ut_ad(!cursor->index()->table->is_temporary());
if (index != cursor->index) {
ut_ad(index->id == cursor->index->id);
if (index != cursor->index()) {
ut_ad(index->id == cursor->index()->id);
drop:
btr_search_drop_page_hash_index(block);
return;
}
ut_a(index == cursor->index);
ut_a(index == cursor->index());
ut_ad(!dict_index_is_ibuf(index));
n_fields = block->curr_n_fields;

View File

@@ -1712,6 +1712,14 @@ inline void log_t::write_checkpoint(lsn_t end_lsn) noexcept
DBUG_PRINT("ib_log", ("checkpoint ended at " LSN_PF ", flushed to " LSN_PF,
next_checkpoint_lsn, get_flushed_lsn()));
if (overwrite_warned)
{
sql_print_information("InnoDB: Crash recovery was broken "
"between LSN=" LSN_PF
" and checkpoint LSN=" LSN_PF ".",
overwrite_warned, next_checkpoint_lsn);
overwrite_warned= 0;
}
latch.wr_unlock();
}
@@ -1884,6 +1892,7 @@ ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn)
record from a previous fil_names_clear() call, which we must
write out before we can advance the checkpoint. */
log_write_up_to(sync_lsn, true);
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", return;);
log_checkpoint();
}
}
@@ -1898,6 +1907,8 @@ ATTRIBUTE_COLD void buf_flush_ahead(lsn_t lsn, bool furious)
if (recv_recovery_is_on())
recv_sys.apply(true);
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", return;);
Atomic_relaxed<lsn_t> &limit= furious
? buf_flush_sync_lsn : buf_flush_async_lsn;
@@ -2252,6 +2263,7 @@ unemployed:
buf_pool.page_cleaner_set_idle(true);
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", continue;);
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", continue;);
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
@@ -2335,6 +2347,7 @@ do_checkpoint:
here should not affect correctness, because log_free_check()
should still be invoking checkpoints when needed. */
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", goto next;);
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", goto next;);
if (!recv_recovery_is_on() && srv_operation == SRV_OPERATION_NORMAL)
log_checkpoint();

View File

@@ -755,11 +755,12 @@ dict_create_index_tree_step(
search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
node->page_no = FIL_NULL;
pcur.btr_cur.page_cur.index =
UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes);
dberr_t err =
btr_pcur_open(UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes),
search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
&pcur, &mtr);
btr_pcur_open(search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
&pcur, 0, &mtr);
if (err != DB_SUCCESS) {
func_exit:

View File

@@ -4147,8 +4147,9 @@ void dict_set_corrupted(dict_index_t *index, const char *ctx)
dfield_set_data(dfield, buf, 8);
dict_index_copy_types(tuple, sys_index, 2);
cursor.page_cur.index = sys_index;
if (btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_LE,
if (btr_cur_search_to_nth_level(0, tuple, PAGE_CUR_LE,
BTR_MODIFY_LEAF, &cursor, &mtr)
!= DB_SUCCESS) {
goto fail;
@@ -4222,8 +4223,9 @@ dict_index_set_merge_threshold(
dfield_set_data(dfield, buf, 8);
dict_index_copy_types(tuple, sys_index, 2);
cursor.page_cur.index = sys_index;
if (btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE,
if (btr_cur_search_to_nth_level(0, tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF, &cursor, &mtr)
!= DB_SUCCESS) {
goto func_exit;

View File

@@ -215,8 +215,9 @@ dict_startscan_system(
mtr_t* mtr, /*!< in: the mini-transaction */
dict_table_t* table) /*!< in: system table */
{
if (btr_pcur_open_at_index_side(true, table->indexes.start, BTR_SEARCH_LEAF,
pcur, true, 0, mtr) != DB_SUCCESS)
btr_pcur_init(pcur);
if (pcur->open_leaf(true, table->indexes.start, BTR_SEARCH_LEAF, mtr) !=
DB_SUCCESS)
return nullptr;
const rec_t *rec;
do
@@ -1316,8 +1317,9 @@ static dberr_t dict_load_columns(dict_table_t *table, unsigned use_uncommitted,
mach_write_to_8(table_id, table->id);
dfield_set_data(&dfield, table_id, 8);
dict_index_copy_types(&tuple, sys_index, 1);
pcur.btr_cur.page_cur.index = sys_index;
dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) {
goto func_exit;
@@ -1446,9 +1448,9 @@ dict_load_virtual_col(dict_table_t *table, bool uncommitted, ulint nth_v_col)
dfield_set_data(&dfield[1], vcol_pos, 4);
dict_index_copy_types(&tuple, sys_virtual_index, 2);
pcur.btr_cur.page_cur.index = sys_virtual_index;
dberr_t err = btr_pcur_open_on_user_rec(sys_virtual_index, &tuple,
PAGE_CUR_GE,
dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) {
goto func_exit;
@@ -1686,8 +1688,9 @@ static dberr_t dict_load_fields(dict_index_t *index, bool uncommitted,
mach_write_to_8(index_id, index->id);
dfield_set_data(&dfield, index_id, 8);
dict_index_copy_types(&tuple, sys_index, 1);
pcur.btr_cur.page_cur.index = sys_index;
dberr_t error = btr_pcur_open_on_user_rec(sys_index, &tuple,
dberr_t error = btr_pcur_open_on_user_rec(&tuple,
PAGE_CUR_GE, BTR_SEARCH_LEAF,
&pcur, &mtr);
if (error != DB_SUCCESS) {
@@ -1944,8 +1947,9 @@ dberr_t dict_load_indexes(dict_table_t *table, bool uncommitted,
mach_write_to_8(table_id, table->id);
dfield_set_data(&dfield, table_id, 8);
dict_index_copy_types(&tuple, sys_index, 1);
pcur.btr_cur.page_cur.index = sys_index;
dberr_t error = btr_pcur_open_on_user_rec(sys_index, &tuple,
dberr_t error = btr_pcur_open_on_user_rec(&tuple,
PAGE_CUR_GE, BTR_SEARCH_LEAF,
&pcur, &mtr);
if (error != DB_SUCCESS) {
@@ -2338,11 +2342,12 @@ static dict_table_t *dict_load_table_one(const span<const char> &name,
};
dfield_set_data(&dfield, name.data(), name.size());
dict_index_copy_types(&tuple, sys_index, 1);
pcur.btr_cur.page_cur.index = sys_index;
bool uncommitted = false;
reload:
mtr.start();
dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS || !btr_pcur_is_on_user_rec(&pcur)) {
@@ -2596,10 +2601,11 @@ dict_load_table_on_id(
mach_write_to_8(id_buf, table_id);
dfield_set_data(&dfield, id_buf, 8);
dict_index_copy_types(&tuple, sys_table_ids, 1);
pcur.btr_cur.page_cur.index = sys_table_ids;
dict_table_t* table = nullptr;
if (btr_pcur_open_on_user_rec(sys_table_ids, &tuple, PAGE_CUR_GE,
if (btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr)
== DB_SUCCESS
&& btr_pcur_is_on_user_rec(&pcur)) {
@@ -2703,9 +2709,10 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id)
dfield_set_data(&dfield, foreign->id, id_len);
dict_index_copy_types(&tuple, sys_index, 1);
pcur.btr_cur.page_cur.index = sys_index;
mem_heap_t* heap = nullptr;
dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) {
goto func_exit;
@@ -2877,11 +2884,12 @@ dict_load_foreign(
};
dfield_set_data(&dfield, id.data(), id.size());
dict_index_copy_types(&tuple, sys_index, 1);
pcur.btr_cur.page_cur.index = sys_index;
mtr.start();
mem_heap_t* heap = nullptr;
dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) {
goto err_exit;
@@ -3090,8 +3098,9 @@ start_load:
mtr.start();
dfield_set_data(&dfield, table_name, strlen(table_name));
dict_index_copy_types(&tuple, sec_index, 1);
pcur.btr_cur.page_cur.index = sec_index;
dberr_t err = btr_pcur_open_on_user_rec(sec_index, &tuple, PAGE_CUR_GE,
dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) {
DBUG_RETURN(err);
@@ -3192,7 +3201,6 @@ next_rec:
load_next_index:
mtr.commit();
ut_free(pcur.old_rec_buf);
if ((sec_index = dict_table_get_next_index(sec_index))) {
/* Switch to scan index on REF_NAME, fk_max_recusive_level
@@ -3202,5 +3210,6 @@ load_next_index:
goto start_load;
}
ut_free(pcur.old_rec_buf);
DBUG_RETURN(DB_SUCCESS);
}

View File

@@ -1560,6 +1560,96 @@ empty_table:
return err;
}
/** Open a cursor at the first page in a tree level.
@param page_cur cursor
@param level level to search for (0=leaf)
@param mtr mini-transaction */
static dberr_t page_cur_open_level(page_cur_t *page_cur, ulint level,
mtr_t *mtr)
{
mem_heap_t *heap= nullptr;
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
rec_offs *offsets= offsets_;
dberr_t err;
dict_index_t *const index= page_cur->index;
rec_offs_init(offsets_);
ut_ad(level != ULINT_UNDEFINED);
ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_SX_LOCK));
ut_ad(mtr->get_savepoint() == 1);
uint32_t page= index->page;
for (ulint height = ULINT_UNDEFINED;; height--)
{
buf_block_t* block=
btr_block_get(*index, page, RW_S_LATCH,
!height && !index->is_clust(), mtr, &err);
if (!block)
break;
const uint32_t l= btr_page_get_level(block->page.frame);
if (height == ULINT_UNDEFINED)
{
ut_ad(!heap);
/* We are in the root node */
height= l;
if (UNIV_UNLIKELY(height < level))
return DB_CORRUPTION;
}
else if (UNIV_UNLIKELY(height != l) || page_has_prev(block->page.frame))
{
err= DB_CORRUPTION;
break;
}
page_cur_set_before_first(block, page_cur);
if (height == level)
break;
ut_ad(height);
if (!page_cur_move_to_next(page_cur))
{
err= DB_CORRUPTION;
break;
}
offsets= rec_get_offsets(page_cur->rec, index, offsets, 0, ULINT_UNDEFINED,
&heap);
page= btr_node_ptr_get_child_page_no(page_cur->rec, offsets);
}
if (UNIV_LIKELY_NULL(heap))
mem_heap_free(heap);
/* Release all page latches except the one on the desired page. */
const auto end= mtr->get_savepoint();
if (end > 1)
mtr->rollback_to_savepoint(1, end - 1);
return err;
}
/** Open a cursor at the first page in a tree level.
@param page_cur cursor
@param level level to search for (0=leaf)
@param mtr mini-transaction
@param index index tree */
static dberr_t btr_pcur_open_level(btr_pcur_t *pcur, ulint level, mtr_t *mtr,
dict_index_t *index)
{
pcur->latch_mode= BTR_SEARCH_TREE;
pcur->search_mode= PAGE_CUR_G;
pcur->pos_state= BTR_PCUR_IS_POSITIONED;
pcur->btr_cur.page_cur.index= index;
return page_cur_open_level(&pcur->btr_cur.page_cur, level, mtr);
}
/* @{ Pseudo code about the relation between the following functions
let N = N_SAMPLE_PAGES(index)
@@ -1616,7 +1706,8 @@ dict_stats_analyze_index_level(
DEBUG_PRINTF(" %s(table=%s, index=%s, level=" ULINTPF ")\n",
__func__, index->table->name, index->name, level);
ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK));
*total_recs = 0;
*total_pages = 0;
n_uniq = dict_index_get_n_unique(index);
@@ -1649,9 +1740,7 @@ dict_stats_analyze_index_level(
/* Position pcur on the leftmost record on the leftmost page
on the desired level. */
if (btr_pcur_open_at_index_side(
true, index, BTR_SEARCH_TREE_ALREADY_S_LATCHED,
&pcur, true, level, mtr) != DB_SUCCESS
if (btr_pcur_open_level(&pcur, level, mtr, index) != DB_SUCCESS
|| !btr_pcur_move_to_next_on_page(&pcur)) {
goto func_exit;
}
@@ -1661,21 +1750,10 @@ dict_stats_analyze_index_level(
/* The page must not be empty, except when
it is the root page (and the whole index is empty). */
ut_ad(btr_pcur_is_on_user_rec(&pcur) || page_is_leaf(page));
ut_ad(btr_pcur_get_rec(&pcur)
== page_rec_get_next_const(page_get_infimum_rec(page)));
prev_rec = NULL;
prev_rec_is_copied = false;
/* no records by default */
*total_recs = 0;
*total_pages = 0;
if (page_has_prev(page) || btr_page_get_level(page) != level) {
goto func_exit;
}
if (REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
btr_pcur_get_rec(&pcur), page_is_comp(page))) {
ut_ad(btr_pcur_is_on_user_rec(&pcur));
@@ -1728,10 +1806,7 @@ dict_stats_analyze_index_level(
if (level == 0
&& !srv_stats_include_delete_marked
&& rec_get_deleted_flag(
rec,
page_is_comp(btr_pcur_get_page(&pcur)))) {
&& rec_get_deleted_flag(rec, page_rec_is_comp(rec))) {
if (rec_is_last_on_page
&& !prev_rec_is_copied
&& prev_rec != NULL) {
@@ -1811,7 +1886,7 @@ dict_stats_analyze_index_level(
records on this level at some point we will jump from
one page to the next and then rec and prev_rec will
be on different pages and
btr_pcur_move_to_next_user_rec() will release the
btr_cur_move_to_next_user_rec() will release the
latch on the page that prev_rec is on */
prev_rec = rec_copy_prefix_to_buf(
rec, index, n_uniq,
@@ -1820,7 +1895,7 @@ dict_stats_analyze_index_level(
} else {
/* still on the same page, the next call to
btr_pcur_move_to_next_user_rec() will not jump
btr_cur_move_to_next_user_rec() will not jump
on the next page, we can simply assign pointers
instead of copying the records like above */
@@ -1891,7 +1966,6 @@ dict_stats_analyze_index_level(
}
#endif /* UNIV_STATS_DEBUG */
btr_leaf_page_release(btr_pcur_get_block(&pcur), BTR_SEARCH_LEAF, mtr);
func_exit:
ut_free(prev_rec_buf);
mem_heap_free(heap);
@@ -2280,7 +2354,6 @@ dict_stats_analyze_index_for_n_prefix(
n_prefix, n_diff_data->n_diff_on_level);
#endif
ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK));
ut_ad(n_diff_data->level);
/* Position pcur on the leftmost record on the leftmost page
@@ -2289,9 +2362,7 @@ dict_stats_analyze_index_for_n_prefix(
n_diff_data->n_diff_all_analyzed_pages = 0;
n_diff_data->n_external_pages_sum = 0;
if (btr_pcur_open_at_index_side(true, index,
BTR_SEARCH_TREE_ALREADY_S_LATCHED,
&pcur, true, n_diff_data->level, mtr)
if (btr_pcur_open_level(&pcur, n_diff_data->level, mtr, index)
!= DB_SUCCESS
|| !btr_pcur_move_to_next_on_page(&pcur)) {
return;
@@ -2680,6 +2751,7 @@ empty_index:
mtr.commit();
mtr.start();
mtr_sx_lock_index(index, &mtr);
ut_ad(mtr.get_savepoint() == 1);
buf_block_t *root = btr_root_block_get(index, RW_S_LATCH,
&mtr, &err);
if (!root || root_level != btr_page_get_level(root->page.frame)
@@ -2695,7 +2767,7 @@ empty_index:
break;
}
mtr.memo_release(root, MTR_MEMO_PAGE_S_FIX);
mtr.rollback_to_savepoint(1);
/* check whether we should pick the current level;
we pick level 1 even if it does not have enough
@@ -2757,6 +2829,7 @@ empty_index:
break;
}
mtr.rollback_to_savepoint(1);
dict_stats_analyze_index_level(index,
level,
n_diff_on_level,
@@ -2764,7 +2837,7 @@ empty_index:
&total_pages,
n_diff_boundaries,
&mtr);
mtr.rollback_to_savepoint(1);
level_is_analyzed = true;
if (level == 1

View File

@@ -1831,7 +1831,6 @@ fil_crypt_rotate_page(
} else {
/* If block read failed mtr memo and log should be empty. */
ut_ad(!mtr.has_modifications());
ut_ad(!mtr.is_dirty());
ut_ad(mtr.is_empty());
mtr.commit();
}

View File

@@ -3347,7 +3347,6 @@ fts_add_doc_by_id(
is_id_cluster = (clust_index == fts_id_index);
mtr_start(&mtr);
btr_pcur_init(&pcur);
/* Search based on Doc ID. Here, we'll need to consider the case
when there is no primary index on Doc ID */
@@ -3358,9 +3357,10 @@ fts_add_doc_by_id(
mach_write_to_8((byte*) &temp_doc_id, doc_id);
dfield_set_data(dfield, &temp_doc_id, sizeof(temp_doc_id));
pcur.btr_cur.page_cur.index = fts_id_index;
/* If we have a match, add the data to doc structure */
if (btr_pcur_open_with_no_init(fts_id_index, tuple, PAGE_CUR_LE,
if (btr_pcur_open_with_no_init(tuple, PAGE_CUR_LE,
BTR_SEARCH_LEAF, &pcur, &mtr)
== DB_SUCCESS
&& btr_pcur_get_low_match(&pcur) == 1) {
@@ -3387,7 +3387,6 @@ fts_add_doc_by_id(
dtuple_t* clust_ref;
ulint n_fields;
btr_pcur_init(&clust_pcur);
n_fields = dict_index_get_n_unique(clust_index);
clust_ref = dtuple_create(heap, n_fields);
@@ -3395,8 +3394,9 @@ fts_add_doc_by_id(
row_build_row_ref_in_tuple(
clust_ref, rec, fts_id_index, NULL);
clust_pcur.btr_cur.page_cur.index = clust_index;
if (btr_pcur_open_with_no_init(clust_index, clust_ref,
if (btr_pcur_open_with_no_init(clust_ref,
PAGE_CUR_LE,
BTR_SEARCH_LEAF,
&clust_pcur, &mtr)
@@ -3552,12 +3552,11 @@ fts_get_max_doc_id(
ut_ad(innobase_strcasecmp(FTS_DOC_ID_COL_NAME, dfield->name) == 0);
#endif
mtr_start(&mtr);
mtr.start();
/* fetch the largest indexes value */
if (btr_pcur_open_at_index_side(false, index, BTR_SEARCH_LEAF, &pcur,
true, 0, &mtr) != DB_SUCCESS) {
} else if (!page_is_empty(btr_pcur_get_page(&pcur))) {
if (pcur.open_leaf(false, index, BTR_SEARCH_LEAF, &mtr) == DB_SUCCESS
&& !page_is_empty(btr_pcur_get_page(&pcur))) {
const rec_t* rec = NULL;
do {
@@ -3576,7 +3575,7 @@ fts_get_max_doc_id(
}
func_exit:
mtr_commit(&mtr);
mtr.commit();
return(doc_id);
}

View File

@@ -70,7 +70,7 @@ rtr_page_split_initialize_nodes(
block = btr_cur_get_block(cursor);
page = buf_block_get_frame(block);
n_uniq = dict_index_get_n_unique_in_tree(cursor->index);
n_uniq = dict_index_get_n_unique_in_tree(cursor->index());
n_recs = ulint(page_get_n_recs(page)) + 1;
@@ -88,8 +88,8 @@ rtr_page_split_initialize_nodes(
rec = page_rec_get_next(page_get_infimum_rec(page));
const ulint n_core = page_is_leaf(page)
? cursor->index->n_core_fields : 0;
*offsets = rec_get_offsets(rec, cursor->index, *offsets, n_core,
? cursor->index()->n_core_fields : 0;
*offsets = rec_get_offsets(rec, cursor->index(), *offsets, n_core,
n_uniq, &heap);
source_cur = rec_get_nth_field(rec, *offsets, 0, &len);
@@ -101,7 +101,7 @@ rtr_page_split_initialize_nodes(
memcpy(cur->coords, source_cur, DATA_MBR_LEN);
rec = page_rec_get_next(rec);
*offsets = rec_get_offsets(rec, cursor->index, *offsets,
*offsets = rec_get_offsets(rec, cursor->index(), *offsets,
n_core, n_uniq, &heap);
source_cur = rec_get_nth_field(rec, *offsets, 0, &len);
}
@@ -111,9 +111,9 @@ rtr_page_split_initialize_nodes(
dtuple_get_nth_field(tuple, 0)));
cur->coords = reserve_coords(buf_pos, SPDIMS);
rec = (byte*) mem_heap_alloc(
heap, rec_get_converted_size(cursor->index, tuple, 0));
heap, rec_get_converted_size(cursor->index(), tuple, 0));
rec = rec_convert_dtuple_to_rec(rec, cursor->index, tuple, 0);
rec = rec_convert_dtuple_to_rec(rec, cursor->index(), tuple, 0);
cur->key = rec;
memcpy(cur->coords, source_cur, DATA_MBR_LEN);
@@ -200,7 +200,7 @@ rtr_update_mbr_field(
rec_t* new_rec, /*!< in: rec to use */
mtr_t* mtr) /*!< in: mtr */
{
dict_index_t* index = cursor->index;
dict_index_t* index = cursor->index();
mem_heap_t* heap;
page_t* page;
rec_t* rec;
@@ -245,6 +245,7 @@ rtr_update_mbr_field(
/* We need to remember the child page no of cursor2, since page could be
reorganized or insert a new rec before it. */
if (cursor2) {
ut_ad(cursor2->index() == index);
rec_t* del_rec = btr_cur_get_rec(cursor2);
offsets2 = rec_get_offsets(btr_cur_get_rec(cursor2),
index, NULL, 0,
@@ -268,7 +269,7 @@ rtr_update_mbr_field(
if (!btr_cur_update_alloc_zip(
page_zip,
btr_cur_get_page_cur(cursor),
index, offsets,
offsets,
rec_offs_size(offsets),
false, mtr)) {
@@ -321,7 +322,7 @@ rtr_update_mbr_field(
offsets2));
page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
index, offsets2, mtr);
offsets2, mtr);
}
} else if (page_get_n_recs(page) == 1) {
/* When there's only one rec in the page, we do insert/delete to
@@ -352,9 +353,10 @@ rtr_update_mbr_field(
ut_ad(old_rec != insert_rec);
page_cur_position(old_rec, block, &page_cur);
page_cur.index = index;
offsets2 = rec_get_offsets(old_rec, index, NULL, n_core,
ULINT_UNDEFINED, &heap);
page_cur_delete_rec(&page_cur, index, offsets2, mtr);
page_cur_delete_rec(&page_cur, offsets2, mtr);
} else {
update_mbr:
@@ -366,8 +368,7 @@ update_mbr:
/* Delete the rec which cursor point to. */
next_rec = page_rec_get_next(rec);
page_cur_delete_rec(btr_cur_get_page_cur(cursor),
index, offsets, mtr);
page_cur_delete_rec(&cursor->page_cur, offsets, mtr);
if (!ins_suc) {
ut_ad(rec_info & REC_INFO_MIN_REC_FLAG);
@@ -400,13 +401,12 @@ update_mbr:
== btr_node_ptr_get_child_page_no(cur2_rec,
offsets2));
page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
index, offsets2, mtr);
offsets2, mtr);
cursor2 = NULL;
}
/* Insert the new rec. */
if (page_cur_search_with_match(block, index, node_ptr,
PAGE_CUR_LE,
if (page_cur_search_with_match(node_ptr, PAGE_CUR_LE,
&up_match, &low_match,
btr_cur_get_page_cur(cursor),
NULL)) {
@@ -424,7 +424,7 @@ update_mbr:
} else if (ins_suc) {
ut_ad(err == DB_FAIL);
err = btr_page_reorganize(btr_cur_get_page_cur(cursor),
index, mtr);
mtr);
if (err == DB_SUCCESS) {
err = btr_cur_optimistic_insert(
flags, cursor, &insert_offsets, &heap,
@@ -505,7 +505,7 @@ update_mbr:
ut_ad(cur2_pno == del_page_no && cur2_rec != insert_rec);
page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
index, offsets2, mtr);
offsets2, mtr);
}
if (!ins_suc) {
@@ -556,7 +556,6 @@ rtr_adjust_upper_level(
{
ulint page_no;
ulint new_page_no;
dict_index_t* index = sea_cur->index;
btr_cur_t cursor;
rec_offs* offsets;
mem_heap_t* heap;
@@ -570,9 +569,10 @@ rtr_adjust_upper_level(
/* Create a memory heap where the data tuple is stored */
heap = mem_heap_create(1024);
cursor.init();
cursor.thr = sea_cur->thr;
cursor.page_cur.index = sea_cur->index();
cursor.page_cur.block = block;
/* Get the level of the split pages */
level = btr_page_get_level(buf_block_get_frame(block));
@@ -584,8 +584,7 @@ rtr_adjust_upper_level(
/* Set new mbr for the old page on the upper level. */
/* Look up the index for the node pointer to page */
offsets = rtr_page_get_father_block(
NULL, heap, index, block, mtr, sea_cur, &cursor);
offsets = rtr_page_get_father_block(NULL, heap, mtr, sea_cur, &cursor);
page_cursor = btr_cur_get_page_cur(&cursor);
@@ -607,10 +606,9 @@ rtr_adjust_upper_level(
page_get_infimum_rec(new_block->page.frame))) {
/* Insert the node for the new page. */
node_ptr_upper = rtr_index_build_node_ptr(
index, new_mbr, first, new_page_no, heap);
sea_cur->index(), new_mbr, first, new_page_no, heap);
ulint up_match = 0, low_match = 0;
err = page_cur_search_with_match(btr_cur_get_block(&cursor),
index, node_ptr_upper,
err = page_cur_search_with_match(node_ptr_upper,
PAGE_CUR_LE,
&up_match, &low_match,
btr_cur_get_page_cur(&cursor),
@@ -660,7 +658,7 @@ rtr_adjust_upper_level(
mem_heap_free(heap);
ut_ad(block->zip_size() == index->table->space->zip_size());
ut_ad(block->zip_size() == sea_cur->index()->table->space->zip_size());
if (err != DB_SUCCESS) {
return err;
@@ -670,7 +668,7 @@ rtr_adjust_upper_level(
if (next_page_no == FIL_NULL) {
} else if (buf_block_t* next_block =
btr_block_get(*index, next_page_no, RW_X_LATCH,
btr_block_get(*sea_cur->index(), next_page_no, RW_X_LATCH,
false, mtr, &err)) {
if (UNIV_UNLIKELY(memcmp_aligned<4>(next_block->page.frame
+ FIL_PAGE_PREV,
@@ -740,6 +738,7 @@ rtr_split_page_move_rec_list(
page_cur_set_before_first(block, &page_cursor);
page_cur_set_before_first(new_block, &new_page_cursor);
page_cursor.index = new_page_cursor.index = index;
page = buf_block_get_frame(block);
new_page = buf_block_get_frame(new_block);
@@ -774,7 +773,7 @@ rtr_split_page_move_rec_list(
rec = page_cur_insert_rec_low(
&new_page_cursor,
index, cur_split_node->key, offsets, mtr);
cur_split_node->key, offsets, mtr);
if (UNIV_UNLIKELY
(!rec
@@ -841,8 +840,7 @@ rtr_split_page_move_rec_list(
page_cur_get_rec(&page_cursor), index,
offsets, n_core, ULINT_UNDEFINED,
&heap);
page_cur_delete_rec(&page_cursor,
index, offsets, mtr);
page_cur_delete_rec(&page_cursor, offsets, mtr);
}
}
@@ -877,7 +875,6 @@ rtr_page_split_and_insert(
buf_block_t* new_block;
page_zip_des_t* page_zip;
page_zip_des_t* new_page_zip;
buf_block_t* insert_block;
page_cur_t* page_cursor;
rec_t* rec = 0;
ulint n_recs;
@@ -906,12 +903,10 @@ func_start:
mem_heap_empty(*heap);
*offsets = NULL;
ut_ad(mtr->memo_contains_flagged(&cursor->index->lock, MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
ut_ad(!dict_index_is_online_ddl(cursor->index)
|| (flags & BTR_CREATE_FLAG)
|| dict_index_is_clust(cursor->index));
ut_ad(cursor->index->lock.have_u_or_x());
ut_ad(mtr->memo_contains_flagged(&cursor->index()->lock,
MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
ut_ad(!dict_index_is_online_ddl(cursor->index()));
ut_ad(cursor->index()->lock.have_u_or_x());
block = btr_cur_get_block(cursor);
page = buf_block_get_frame(block);
@@ -954,7 +949,7 @@ corrupted:
}
#endif
insert_size = rec_get_converted_size(cursor->index, tuple, n_ext);
insert_size = rec_get_converted_size(cursor->index(), tuple, n_ext);
total_data = page_get_data_size(page) + insert_size;
first_rec_group = split_rtree_node(rtr_split_node_array,
static_cast<int>(n_recs),
@@ -965,7 +960,7 @@ corrupted:
/* Allocate a new page to the index */
const uint16_t page_level = btr_page_get_level(page);
new_block = btr_page_alloc(cursor->index, page_id.page_no() + 1,
new_block = btr_page_alloc(cursor->index(), page_id.page_no() + 1,
FSP_UP, page_level, mtr, mtr, err);
if (UNIV_UNLIKELY(!new_block)) {
return nullptr;
@@ -977,7 +972,7 @@ corrupted:
to contain FIL_NULL in FIL_PAGE_PREV at this stage. */
memset_aligned<4>(new_block->page.frame + FIL_PAGE_PREV, 0, 4);
}
btr_page_create(new_block, new_page_zip, cursor->index,
btr_page_create(new_block, new_page_zip, cursor->index(),
page_level, mtr);
new_page = buf_block_get_frame(new_block);
@@ -985,7 +980,7 @@ corrupted:
/* Set new ssn to the new page and page. */
page_set_ssn_id(new_block, new_page_zip, current_ssn, mtr);
next_ssn = rtr_get_new_ssn_id(cursor->index);
next_ssn = rtr_get_new_ssn_id(cursor->index());
page_set_ssn_id(block, page_zip, next_ssn, mtr);
@@ -998,7 +993,7 @@ corrupted:
|| (*err = rtr_split_page_move_rec_list(rtr_split_node_array,
first_rec_group,
new_block, block,
first_rec, cursor->index,
first_rec, cursor->index(),
*heap, mtr))) {
if (*err != DB_FAIL) {
return nullptr;
@@ -1021,7 +1016,7 @@ corrupted:
ut_a(new_page_zip);
page_zip_copy_recs(new_block,
page_zip, page, cursor->index, mtr);
page_zip, page, cursor->index(), mtr);
page_cursor = btr_cur_get_page_cur(cursor);
@@ -1056,7 +1051,7 @@ corrupted:
lock_rtr_move_rec_list(new_block, block, rec_move, moved);
const ulint n_core = page_level
? 0 : cursor->index->n_core_fields;
? 0 : cursor->index()->n_core_fields;
/* Delete recs in first group from the new page. */
for (cur_split_node = rtr_split_node_array;
@@ -1076,11 +1071,11 @@ corrupted:
*offsets = rec_get_offsets(
page_cur_get_rec(page_cursor),
cursor->index, *offsets, n_core,
cursor->index(), *offsets, n_core,
ULINT_UNDEFINED, heap);
page_cur_delete_rec(page_cursor,
cursor->index, *offsets, mtr);
*offsets, mtr);
n++;
}
}
@@ -1093,32 +1088,30 @@ corrupted:
block, page_cursor);
*offsets = rec_get_offsets(
page_cur_get_rec(page_cursor),
cursor->index, *offsets, n_core,
page_cursor->index, *offsets, n_core,
ULINT_UNDEFINED, heap);
page_cur_delete_rec(page_cursor,
cursor->index, *offsets, mtr);
page_cur_delete_rec(page_cursor, *offsets,
mtr);
}
}
#ifdef UNIV_GIS_DEBUG
ut_ad(page_validate(new_page, cursor->index));
ut_ad(page_validate(page, cursor->index));
ut_ad(page_validate(new_page, cursor->index()));
ut_ad(page_validate(page, cursor->index()));
#endif
}
/* Insert the new rec to the proper page. */
cur_split_node = end_split_node - 1;
if (cur_split_node->n_node != first_rec_group) {
insert_block = new_block;
} else {
insert_block = block;
}
/* Reposition the cursor for insert and try insertion */
page_cursor = btr_cur_get_page_cur(cursor);
page_cursor->block = cur_split_node->n_node != first_rec_group
? new_block : block;
ulint up_match = 0, low_match = 0;
if (page_cur_search_with_match(insert_block, cursor->index, tuple,
if (page_cur_search_with_match(tuple,
PAGE_CUR_LE, &up_match, &low_match,
page_cursor, nullptr)) {
goto corrupted;
@@ -1133,7 +1126,7 @@ corrupted:
goto after_insert; }
);
rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index,
rec = page_cur_tuple_insert(page_cursor, tuple,
offsets, heap, n_ext, mtr);
/* If insert did not fit, try page reorganization.
@@ -1141,14 +1134,13 @@ corrupted:
attempted this already. */
if (rec == NULL) {
if (!is_page_cur_get_page_zip(page_cursor)
&& btr_page_reorganize(page_cursor, cursor->index, mtr)) {
&& btr_page_reorganize(page_cursor, mtr)) {
rec = page_cur_tuple_insert(page_cursor, tuple,
cursor->index, offsets,
offsets,
heap, n_ext, mtr);
}
/* If insert fail, we will try to split the insert_block
again. */
/* If insert fail, we will try to split the block again. */
}
#ifdef UNIV_DEBUG
@@ -1156,8 +1148,8 @@ after_insert:
#endif
/* Calculate the mbr on the upper half-page, and the mbr on
original page. */
rtr_page_cal_mbr(cursor->index, block, &mbr, *heap);
rtr_page_cal_mbr(cursor->index, new_block, &new_mbr, *heap);
rtr_page_cal_mbr(cursor->index(), block, &mbr, *heap);
rtr_page_cal_mbr(cursor->index(), new_block, &new_mbr, *heap);
prdt.data = &mbr;
new_prdt.data = &new_mbr;
@@ -1175,7 +1167,8 @@ after_insert:
/* Save the new ssn to the root page, since we need to reinit
the first ssn value from it after restart server. */
root_block = btr_root_block_get(cursor->index, RW_SX_LATCH, mtr, err);
root_block = btr_root_block_get(cursor->index(), RW_SX_LATCH,
mtr, err);
if (UNIV_UNLIKELY(!root_block)) {
return nullptr;
}
@@ -1187,8 +1180,8 @@ after_insert:
again. */
if (!rec) {
/* We play safe and reset the free bits for new_page */
if (!dict_index_is_clust(cursor->index)
&& !cursor->index->table->is_temporary()) {
if (!dict_index_is_clust(cursor->index())
&& !cursor->index()->table->is_temporary()) {
ibuf_reset_free_bits(new_block);
ibuf_reset_free_bits(block);
}
@@ -1205,16 +1198,16 @@ after_insert:
if (UNIV_UNLIKELY(!i_rec)) {
goto corrupted;
}
btr_cur_position(cursor->index, i_rec, block, cursor);
btr_cur_position(cursor->index(), i_rec, block, cursor);
goto func_start;
}
#ifdef UNIV_GIS_DEBUG
ut_ad(page_validate(buf_block_get_frame(block), cursor->index));
ut_ad(page_validate(buf_block_get_frame(new_block), cursor->index));
ut_ad(page_validate(buf_block_get_frame(block), cursor->index()));
ut_ad(page_validate(buf_block_get_frame(new_block), cursor->index()));
ut_ad(!rec || rec_offs_validate(rec, cursor->index, *offsets));
ut_ad(!rec || rec_offs_validate(rec, cursor->index(), *offsets));
#endif
MONITOR_INC(MONITOR_INDEX_SPLIT);
@@ -1234,14 +1227,13 @@ rtr_ins_enlarge_mbr(
rtr_mbr_t new_mbr;
buf_block_t* block;
mem_heap_t* heap;
dict_index_t* index = btr_cur->index;
page_cur_t* page_cursor;
rec_offs* offsets;
node_visit_t* node_visit;
btr_cur_t cursor;
page_t* page;
ut_ad(dict_index_is_spatial(index));
ut_ad(btr_cur->index()->is_spatial());
/* If no rtr_info or rtree is one level tree, return. */
if (!btr_cur->rtr_info || btr_cur->tree_height == 1) {
@@ -1269,20 +1261,20 @@ rtr_ins_enlarge_mbr(
}
/* Calculate the mbr of the child page. */
rtr_page_cal_mbr(index, block, &new_mbr, heap);
rtr_page_cal_mbr(page_cursor->index, block, &new_mbr, heap);
/* Get father block. */
cursor.init();
cursor.page_cur.index = page_cursor->index;
cursor.page_cur.block = block;
offsets = rtr_page_get_father_block(
NULL, heap, index, block, mtr, btr_cur, &cursor);
NULL, heap, mtr, btr_cur, &cursor);
page = buf_block_get_frame(block);
/* Update the mbr field of the rec. */
rtr_update_mbr_field(&cursor, offsets, NULL, page,
&new_mbr, NULL, mtr);
page_cursor = btr_cur_get_page_cur(&cursor);
block = page_cur_get_block(page_cursor);
block = btr_cur_get_block(&cursor);
}
mem_heap_free(heap);
@@ -1338,6 +1330,7 @@ rtr_page_copy_rec_list_end_no_locks(
return DB_CORRUPTION;
}
page_cur_position(cur_rec, new_block, &page_cur);
page_cur.index = index;
/* Copy records from the original page to the new page */
while (!page_cur_is_after_last(&cur1)) {
@@ -1399,7 +1392,7 @@ move_to_prev:
offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core,
ULINT_UNDEFINED, &heap);
ins_rec = page_cur_insert_rec_low(&page_cur, index,
ins_rec = page_cur_insert_rec_low(&page_cur,
cur1_rec, offsets1, mtr);
if (UNIV_UNLIKELY(!ins_rec || moved >= max_move)) {
return DB_CORRUPTION;
@@ -1461,6 +1454,7 @@ rtr_page_copy_rec_list_start_no_locks(
return DB_CORRUPTION;
}
page_cur_position(cur_rec, new_block, &page_cur);
page_cur.index = index;
while (page_cur_get_rec(&cur1) != rec) {
rec_t* cur1_rec = page_cur_get_rec(&cur1);
@@ -1522,7 +1516,7 @@ move_to_prev:
offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core,
ULINT_UNDEFINED, &heap);
ins_rec = page_cur_insert_rec_low(&page_cur, index,
ins_rec = page_cur_insert_rec_low(&page_cur,
cur1_rec, offsets1, mtr);
if (UNIV_UNLIKELY(!ins_rec || moved >= max_move)) {
return DB_CORRUPTION;
@@ -1560,7 +1554,7 @@ rtr_merge_mbr_changed(
ulint len;
bool changed = false;
ut_ad(dict_index_is_spatial(cursor->index));
ut_ad(cursor->index()->is_spatial());
rec = btr_cur_get_rec(cursor);
@@ -1640,11 +1634,11 @@ rtr_check_same_block(
btr_cur_t* cursor, /*!< in/out: position at the parent entry
pointing to the child if successful */
buf_block_t* parentb,/*!< in: parent page to check */
buf_block_t* childb, /*!< in: child Page */
mem_heap_t* heap) /*!< in: memory heap */
{
ulint page_no = childb->page.id().page_no();
const uint32_t page_no =
btr_cur_get_block(cursor)->page.id().page_no();
rec_offs* offsets;
rec_t* rec = page_get_infimum_rec(parentb->page.frame);

View File

@@ -95,14 +95,13 @@ rtr_pcur_getnext_from_path(
/*!< in: index tree locked */
mtr_t* mtr) /*!< in: mtr */
{
dict_index_t* index = btr_cur->index;
dict_index_t* index = btr_cur->index();
bool found = false;
page_cur_t* page_cursor;
ulint level = 0;
node_visit_t next_rec;
rtr_info_t* rtr_info = btr_cur->rtr_info;
node_seq_t page_ssn;
ulint my_latch_mode;
ulint skip_parent = false;
bool new_split = false;
bool for_delete = false;
@@ -115,7 +114,7 @@ rtr_pcur_getnext_from_path(
ut_ad(dtuple_get_n_fields_cmp(tuple));
my_latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
const auto my_latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
for_delete = latch_mode & BTR_RTREE_DELETE_MARK;
for_undo_ins = latch_mode & BTR_RTREE_UNDO_INS;
@@ -299,6 +298,7 @@ rtr_pcur_getnext_from_path(
page_cursor = btr_cur_get_page_cur(btr_cur);
page_cursor->rec = NULL;
page_cursor->block = block;
if (mode == PAGE_CUR_RTREE_LOCATE) {
if (target_level == 0 && level == 0) {
@@ -307,7 +307,7 @@ rtr_pcur_getnext_from_path(
found = false;
if (!page_cur_search_with_match(
block, index, tuple, PAGE_CUR_LE,
tuple, PAGE_CUR_LE,
&up_match, &low_match,
btr_cur_get_page_cur(btr_cur), nullptr)
&& low_match
@@ -351,17 +351,12 @@ rtr_pcur_getnext_from_path(
BTR_PCUR_IS_POSITIONED;
r_cursor->latch_mode = my_latch_mode;
btr_pcur_store_position(r_cursor, mtr);
#ifdef UNIV_DEBUG
ulint num_stored =
ut_d(ulint num_stored =)
rtr_store_parent_path(
block, btr_cur,
rw_latch, level, mtr);
ut_ad(num_stored > 0);
#else
rtr_store_parent_path(
block, btr_cur, rw_latch,
btr_latch_mode(rw_latch),
level, mtr);
#endif /* UNIV_DEBUG */
ut_ad(num_stored > 0);
}
}
} else {
@@ -443,11 +438,11 @@ rtr_pcur_getnext_from_path(
const rec_t* rec = btr_cur_get_rec(btr_cur);
if (page_rec_is_infimum(rec) || page_rec_is_supremum(rec)) {
mtr_commit(mtr);
mtr_start(mtr);
if (!page_rec_is_user_rec(rec)) {
mtr->commit();
mtr->start();
} else if (!index_locked) {
mtr_memo_release(mtr, &index->lock, MTR_MEMO_X_LOCK);
mtr->release(index->lock);
}
return(found);
@@ -521,7 +516,7 @@ bool
rtr_pcur_open(
dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
mtr_t* mtr) /*!< in: mtr */
{
@@ -539,6 +534,7 @@ rtr_pcur_open(
/* Search with the tree cursor */
btr_cur_t* btr_cursor = btr_pcur_get_btr_cur(cursor);
btr_cursor->page_cur.index = index;
btr_cursor->rtr_info = rtr_create_rtr_info(false, false,
btr_cursor, index);
@@ -554,7 +550,7 @@ rtr_pcur_open(
mtr->lock_upgrade(index->lock);
}
if (btr_cur_search_to_nth_level(index, 0, tuple, PAGE_CUR_RTREE_LOCATE,
if (btr_cur_search_to_nth_level(0, tuple, PAGE_CUR_RTREE_LOCATE,
latch_mode,
btr_cursor, mtr) != DB_SUCCESS) {
return true;
@@ -606,24 +602,16 @@ rtr_pcur_open(
}
/* Get the rtree page father.
@param[in] index rtree index
@param[in] block child page in the index
@param[in,out] mtr mtr
@param[in] sea_cur search cursor, contains information
about parent nodes in search
@param[out] cursor cursor on node pointer record,
its page x-latched
@return whether the cursor was successfully positioned */
bool
rtr_page_get_father(
dict_index_t* index,
buf_block_t* block,
mtr_t* mtr,
btr_cur_t* sea_cur,
btr_cur_t* cursor)
bool rtr_page_get_father(mtr_t *mtr, btr_cur_t *sea_cur, btr_cur_t *cursor)
{
mem_heap_t *heap = mem_heap_create(100);
rec_offs *offsets= rtr_page_get_father_block(nullptr, heap, index, block,
rec_offs *offsets= rtr_page_get_father_block(nullptr, heap,
mtr, sea_cur, cursor);
mem_heap_free(heap);
return offsets != nullptr;
@@ -634,7 +622,6 @@ MY_ATTRIBUTE((warn_unused_result))
Returns the upper level node pointer to a R-Tree page. It is assumed
that mtr holds an x-latch on the tree. */
static const rec_t* rtr_get_father_node(
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: the tree level of search */
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in
tuple must be set so that it cannot get
@@ -647,6 +634,7 @@ static const rec_t* rtr_get_father_node(
{
const rec_t* rec = nullptr;
auto had_rtr = btr_cur->rtr_info;
dict_index_t* const index = btr_cur->index();
/* Try to optimally locate the parent node. Level should always
less than sea_cur->tree_height unless the root is splitting */
@@ -680,7 +668,7 @@ static const rec_t* rtr_get_father_node(
btr_cur->rtr_info = rtr_create_rtr_info(false, false, btr_cur, index);
if (btr_cur_search_to_nth_level(index, level, tuple,
if (btr_cur_search_to_nth_level(level, tuple,
PAGE_CUR_RTREE_LOCATE,
BTR_CONT_MODIFY_TREE, btr_cur, mtr)
!= DB_SUCCESS) {
@@ -764,7 +752,7 @@ rtr_page_get_father_node_ptr(
sea_cur = NULL;
}
const rec_t* node_ptr = rtr_get_father_node(index, level + 1, tuple,
const rec_t* node_ptr = rtr_get_father_node(level + 1, tuple,
sea_cur, cursor,
page_no, mtr);
if (!node_ptr) {
@@ -792,23 +780,18 @@ rtr_page_get_father_block(
/*======================*/
rec_offs* offsets,/*!< in: work area for the return value */
mem_heap_t* heap, /*!< in: memory heap to use */
dict_index_t* index, /*!< in: b-tree index */
buf_block_t* block, /*!< in: child page in the index */
mtr_t* mtr, /*!< in: mtr */
btr_cur_t* sea_cur,/*!< in: search cursor, contains information
about parent nodes in search */
btr_cur_t* cursor) /*!< out: cursor on node pointer record,
its page x-latched */
{
rec_t* rec = page_rec_get_next(
page_get_infimum_rec(buf_block_get_frame(block)));
if (!rec) {
rec_t *rec=
page_rec_get_next(page_get_infimum_rec(cursor->block()->page.frame));
if (!rec)
return nullptr;
}
btr_cur_position(index, rec, block, cursor);
return(rtr_page_get_father_node_ptr(offsets, heap, sea_cur,
cursor, mtr));
cursor->page_cur.rec= rec;
return rtr_page_get_father_node_ptr(offsets, heap, sea_cur, cursor, mtr);
}
/*******************************************************************//**
@@ -826,7 +809,7 @@ rtr_create_rtr_info(
{
rtr_info_t* rtr_info;
index = index ? index : cursor->index;
index = index ? index : cursor->index();
ut_ad(index);
rtr_info = static_cast<rtr_info_t*>(ut_zalloc_nokey(sizeof(*rtr_info)));
@@ -1163,6 +1146,7 @@ rtr_cur_restore_position(
ut_ad(mtr->is_active());
index = btr_cur_get_index(btr_cur);
ut_ad(r_cursor->index() == btr_cur->index());
if (r_cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
|| r_cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
@@ -1222,7 +1206,6 @@ rtr_cur_restore_position(
/* Page has changed, for R-Tree, the page cannot be shrunk away,
so we search the page and its right siblings */
buf_block_t* block;
node_seq_t page_ssn;
const page_t* page;
page_cur_t* page_cursor;
@@ -1242,21 +1225,21 @@ rtr_cur_restore_position(
search_again:
ulint up_match = 0, low_match = 0;
block = buf_page_get_gen(
page_cursor->block = buf_page_get_gen(
page_id_t(index->table->space_id, page_no),
zip_size, RW_X_LATCH, NULL, BUF_GET, mtr);
if (!block) {
if (!page_cursor->block) {
corrupted:
ret = false;
goto func_exit;
}
/* Get the page SSN */
page = buf_block_get_frame(block);
page = buf_block_get_frame(page_cursor->block);
page_ssn = page_get_ssn_id(page);
if (page_cur_search_with_match(block, index, tuple, PAGE_CUR_LE,
if (page_cur_search_with_match(tuple, PAGE_CUR_LE,
&up_match, &low_match, page_cursor,
nullptr)) {
goto corrupted;
@@ -1352,7 +1335,7 @@ rtr_store_parent_path(
/*==================*/
const buf_block_t* block, /*!< in: block of the page */
btr_cur_t* btr_cur,/*!< in/out: persistent cursor */
ulint latch_mode,
btr_latch_mode latch_mode,
/*!< in: latch_mode */
ulint level, /*!< in: index level */
mtr_t* mtr) /*!< in: mtr */
@@ -1411,7 +1394,7 @@ rtr_non_leaf_insert_stack_push(
page_cur_position(rec, block, btr_pcur_get_page_cur(my_cursor));
(btr_pcur_get_btr_cur(my_cursor))->index = index;
btr_pcur_get_page_cur(my_cursor)->index = index;
new_seq = rtr_get_current_ssn_id(index);
rtr_non_leaf_stack_push(path, block->page.id().page_no(),

View File

@@ -1542,7 +1542,8 @@ static void innodb_drop_database(handlerton*, char *path)
std::vector<pfs_os_file_t> to_close;
mtr_t mtr;
mtr.start();
err= btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
pcur.btr_cur.page_cur.index = sys_index;
err= btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS)
goto err_exit;
@@ -2000,9 +2001,8 @@ static void drop_garbage_tables_after_restore()
ut_d(purge_sys.stop_FTS());
mtr.start();
if (btr_pcur_open_at_index_side(true, dict_sys.sys_tables->indexes.start,
BTR_SEARCH_LEAF, &pcur, true, 0, &mtr) !=
DB_SUCCESS)
if (pcur.open_leaf(true, dict_sys.sys_tables->indexes.start, BTR_SEARCH_LEAF,
&mtr) != DB_SUCCESS)
goto all_fail;
for (;;)
{
@@ -14997,14 +14997,10 @@ inline int ha_innobase::defragment_table()
}
btr_pcur_t pcur;
pcur.btr_cur.index = nullptr;
btr_pcur_init(&pcur);
mtr_t mtr;
mtr.start();
if (dberr_t err= btr_pcur_open_at_index_side(true, index,
BTR_SEARCH_LEAF, &pcur,
true, 0, &mtr))
if (dberr_t err= pcur.open_leaf(true, index, BTR_SEARCH_LEAF, &mtr))
{
mtr.commit();
return convert_error_code_to_mysql(err, 0, m_user_thd);
@@ -15018,9 +15014,9 @@ inline int ha_innobase::defragment_table()
btr_pcur_move_to_next(&pcur, &mtr);
btr_pcur_store_position(&pcur, &mtr);
mtr.commit();
ut_ad(pcur.btr_cur.index == index);
ut_ad(pcur.index() == index);
const bool interrupted= btr_defragment_add_index(&pcur, m_user_thd);
btr_pcur_free(&pcur);
ut_free(pcur.old_rec_buf);
if (interrupted)
return ER_QUERY_INTERRUPTED;
}

View File

@@ -2128,8 +2128,7 @@ static bool innobase_table_is_empty(const dict_table_t *table,
bool next_page= false;
mtr.start();
if (btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF,
&pcur, true, 0, &mtr) != DB_SUCCESS)
if (pcur.open_leaf(true, clust_index, BTR_SEARCH_LEAF, &mtr) != DB_SUCCESS)
{
non_empty:
mtr.commit();
@@ -2159,10 +2158,11 @@ next_page:
&mtr);
if (!block)
goto non_empty;
btr_leaf_page_release(page_cur_get_block(cur), BTR_SEARCH_LEAF, &mtr);
page_cur_set_before_first(block, cur);
if (UNIV_UNLIKELY(!page_cur_move_to_next(cur)))
goto non_empty;
const auto s= mtr.get_savepoint();
mtr.rollback_to_savepoint(s - 2, s - 1);
}
rec= page_cur_get_rec(cur);
@@ -6038,8 +6038,7 @@ add_all_virtual:
mtr.start();
index->set_modified(mtr);
btr_pcur_t pcur;
dberr_t err = btr_pcur_open_at_index_side(true, index, BTR_MODIFY_TREE,
&pcur, true, 0, &mtr);
dberr_t err= pcur.open_leaf(true, index, BTR_MODIFY_TREE, &mtr);
if (err != DB_SUCCESS) {
func_exit:
mtr.commit();

View File

@@ -466,9 +466,8 @@ err_exit:
ib::info() << "Dumping the change buffer";
ibuf_mtr_start(&mtr);
btr_pcur_t pcur;
if (DB_SUCCESS == btr_pcur_open_at_index_side(
true, ibuf.index, BTR_SEARCH_LEAF, &pcur,
true, 0, &mtr)) {
if (DB_SUCCESS
== pcur.open_leaf(true, ibuf.index, BTR_SEARCH_LEAF, &mtr)) {
while (btr_pcur_move_to_next_user_rec(&pcur, &mtr)) {
rec_print_old(stderr, btr_pcur_get_rec(&pcur));
}
@@ -2337,9 +2336,11 @@ work_around:
space_id, page_nos[i], heap);
loop:
btr_pcur_t pcur;
pcur.btr_cur.page_cur.index = ibuf.index;
ibuf_mtr_start(&mtr);
if (btr_pcur_open(ibuf.index, tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF, &pcur, &mtr)
if (btr_pcur_open(tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF, &pcur, 0, &mtr)
!= DB_SUCCESS) {
goto done;
}
@@ -2386,16 +2387,11 @@ done:
#endif
}
/*********************************************************************//**
Contracts insert buffer trees by reading pages to the buffer pool.
/** Contract the change buffer by reading pages to the buffer pool.
@return a lower limit for the combined size in bytes of entries which
will be merged from ibuf trees to the pages read, 0 if ibuf is
empty */
static
ulint
ibuf_merge_pages(
/*=============*/
ulint* n_pages) /*!< out: number of pages to which merged */
will be merged from ibuf trees to the pages read
@retval 0 if ibuf.empty */
ulint ibuf_contract()
{
mtr_t mtr;
btr_pcur_t pcur;
@@ -2403,15 +2399,13 @@ ibuf_merge_pages(
uint32_t page_nos[IBUF_MAX_N_PAGES_MERGED];
uint32_t space_ids[IBUF_MAX_N_PAGES_MERGED];
*n_pages = 0;
ibuf_mtr_start(&mtr);
/* Open a cursor to a randomly chosen leaf of the tree, at a random
position within the leaf */
pcur.pos_state = BTR_PCUR_IS_POSITIONED;
pcur.old_stored = false;
pcur.trx_if_known = NULL;
pcur.old_rec = nullptr;
pcur.trx_if_known = nullptr;
pcur.search_mode = PAGE_CUR_G;
pcur.latch_mode = BTR_SEARCH_LEAF;
@@ -2437,13 +2431,14 @@ ibuf_merge_pages(
return(0);
}
ulint n_pages = 0;
sum_sizes = ibuf_get_merge_page_nos(TRUE,
btr_pcur_get_rec(&pcur), &mtr,
space_ids,
page_nos, n_pages);
page_nos, &n_pages);
ibuf_mtr_commit(&mtr);
ibuf_read_merge_pages(space_ids, page_nos, *n_pages);
ibuf_read_merge_pages(space_ids, page_nos, n_pages);
return(sum_sizes + 1);
}
@@ -2470,8 +2465,9 @@ ibuf_merge_space(
/* Position the cursor on the first matching record. */
dberr_t err = btr_pcur_open(ibuf.index, tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
pcur.btr_cur.page_cur.index = ibuf.index;
dberr_t err = btr_pcur_open(tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, 0, &mtr);
ut_ad(err != DB_SUCCESS || page_validate(btr_pcur_get_page(&pcur),
ibuf.index));
@@ -2515,73 +2511,6 @@ ibuf_merge_space(
return(n_pages);
}
/** Contract the change buffer by reading pages to the buffer pool.
@param[out] n_pages number of pages merged
@param[in] sync whether the caller waits for
the issued reads to complete
@return a lower limit for the combined size in bytes of entries which
will be merged from ibuf trees to the pages read, 0 if ibuf is
empty */
MY_ATTRIBUTE((warn_unused_result))
static ulint ibuf_merge(ulint* n_pages)
{
*n_pages = 0;
/* We perform a dirty read of ibuf.empty, without latching
the insert buffer root page. We trust this dirty read except
when a slow shutdown is being executed. During a slow
shutdown, the insert buffer merge must be completed. */
if (ibuf.empty && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) {
return(0);
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
} else if (ibuf_debug) {
return(0);
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
} else {
return ibuf_merge_pages(n_pages);
}
}
/** Contract the change buffer by reading pages to the buffer pool.
@return a lower limit for the combined size in bytes of entries which
will be merged from ibuf trees to the pages read, 0 if ibuf is empty */
static ulint ibuf_contract()
{
ulint n_pages;
return ibuf_merge_pages(&n_pages);
}
/** Contract the change buffer by reading pages to the buffer pool.
@return a lower limit for the combined size in bytes of entries which
will be merged from ibuf trees to the pages read, 0 if ibuf is
empty */
ulint ibuf_merge_all()
{
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
if (ibuf_debug) {
return(0);
}
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
ulint sum_bytes = 0;
ulint n_pages = srv_io_capacity;
for (ulint sum_pages = 0; sum_pages < n_pages; ) {
log_free_check();
ulint n_pag2;
ulint n_bytes = ibuf_merge(&n_pag2);
if (n_bytes == 0) {
break;
}
sum_bytes += n_bytes;
}
return sum_bytes;
}
/*********************************************************************//**
Contract insert buffer trees after insert if they are too big. */
UNIV_INLINE
@@ -2591,13 +2520,7 @@ ibuf_contract_after_insert(
ulint entry_size) /*!< in: size of a record which was inserted
into an ibuf tree */
{
/* Perform dirty reads of ibuf.size and ibuf.max_size, to
reduce ibuf_mutex contention. ibuf.max_size remains constant
after ibuf_init_at_db_start(), but ibuf.size should be
protected by ibuf_mutex. Given that ibuf.size fits in a
machine word, this should be OK; at worst we are doing some
excessive ibuf_contract() or occasionally skipping a
ibuf_contract(). */
/* dirty comparison, to avoid contention on ibuf_mutex */
if (ibuf.size < ibuf.max_size) {
return;
}
@@ -2991,8 +2914,8 @@ ibuf_update_max_tablespace_id(void)
ibuf_mtr_start(&mtr);
if (btr_pcur_open_at_index_side(false, ibuf.index, BTR_SEARCH_LEAF,
&pcur, true, 0, &mtr) != DB_SUCCESS) {
if (pcur.open_leaf(false, ibuf.index, BTR_SEARCH_LEAF, &mtr)
!= DB_SUCCESS) {
func_exit:
ibuf_mtr_commit(&mtr);
return;
@@ -3170,7 +3093,7 @@ ibuf_index_page_calc_free_from_bits(ulint physical_size, ulint bits)
/** Buffer an operation in the insert/delete buffer, instead of doing it
directly to the disk page, if this is possible.
@param[in] mode BTR_MODIFY_PREV or BTR_MODIFY_TREE
@param[in] mode BTR_MODIFY_PREV or BTR_INSERT_TREE
@param[in] op operation type
@param[in] no_counter TRUE=use 5.0.3 format; FALSE=allow delete
buffering
@@ -3185,7 +3108,7 @@ or clustered
static TRANSACTIONAL_TARGET MY_ATTRIBUTE((warn_unused_result))
dberr_t
ibuf_insert_low(
ulint mode,
btr_latch_mode mode,
ibuf_op_t op,
ibool no_counter,
const dtuple_t* entry,
@@ -3225,16 +3148,17 @@ ibuf_insert_low(
do_merge = FALSE;
/* Perform dirty reads of ibuf.size and ibuf.max_size, to
reduce ibuf_mutex contention. Given that ibuf.max_size and
ibuf.size fit in a machine word, this should be OK; at worst
we are doing some excessive ibuf_contract() or occasionally
/* Perform dirty comparison of ibuf.max_size and ibuf.size to
reduce ibuf_mutex contention. This should be OK; at worst we
are doing some excessive ibuf_contract() or occasionally
skipping an ibuf_contract(). */
if (ibuf.max_size == 0) {
const ulint max_size = ibuf.max_size;
if (max_size == 0) {
return(DB_STRONG_FAIL);
}
if (ibuf.size >= ibuf.max_size + IBUF_CONTRACT_DO_NOT_INSERT) {
if (ibuf.size >= max_size + IBUF_CONTRACT_DO_NOT_INSERT) {
/* Insert buffer is now too big, contract it but do not try
to insert */
@@ -3265,7 +3189,7 @@ ibuf_insert_low(
the new entry to it without exceeding the free space limit for the
page. */
if (BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE) {
if (mode == BTR_INSERT_TREE) {
for (;;) {
mysql_mutex_lock(&ibuf_pessimistic_insert_mutex);
mysql_mutex_lock(&ibuf_mutex);
@@ -3287,18 +3211,16 @@ ibuf_insert_low(
}
ibuf_mtr_start(&mtr);
pcur.btr_cur.page_cur.index = ibuf.index;
err = btr_pcur_open(ibuf.index, ibuf_entry, PAGE_CUR_LE, mode, &pcur,
&mtr);
err = btr_pcur_open(ibuf_entry, PAGE_CUR_LE, mode, &pcur, 0, &mtr);
if (err != DB_SUCCESS) {
func_exit:
ibuf_mtr_commit(&mtr);
ut_free(pcur.old_rec_buf);
mem_heap_free(heap);
if (err == DB_SUCCESS
&& BTR_LATCH_MODE_WITHOUT_INTENTION(mode)
== BTR_MODIFY_TREE) {
if (err == DB_SUCCESS && mode == BTR_INSERT_TREE) {
ibuf_contract_after_insert(entry_size);
}
@@ -3345,7 +3267,7 @@ func_exit:
until after the IBUF_OP_DELETE has been buffered. */
fail_exit:
if (BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE) {
if (mode == BTR_INSERT_TREE) {
mysql_mutex_unlock(&ibuf_mutex);
mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex);
}
@@ -3461,8 +3383,7 @@ commit_exit:
ibuf.empty = page_is_empty(root);
}
} else {
ut_ad(BTR_LATCH_MODE_WITHOUT_INTENTION(mode)
== BTR_MODIFY_TREE);
ut_ad(mode == BTR_INSERT_TREE);
/* We acquire an sx-latch to the root page before the insert,
because a pessimistic insert releases the tree x-latch,
@@ -3637,7 +3558,7 @@ skip_watch:
entry, entry_size,
index, page_id, zip_size, thr);
if (err == DB_FAIL) {
err = ibuf_insert_low(BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT,
err = ibuf_insert_low(BTR_INSERT_TREE,
op, no_counter, entry, entry_size,
index, page_id, zip_size, thr);
}
@@ -3658,30 +3579,27 @@ dberr_t
ibuf_insert_to_index_page_low(
/*==========================*/
const dtuple_t* entry, /*!< in: buffered entry to insert */
buf_block_t* block, /*!< in/out: index page where the buffered
entry should be placed */
dict_index_t* index, /*!< in: record descriptor */
rec_offs** offsets,/*!< out: offsets on *rec */
mem_heap_t* heap, /*!< in/out: memory heap */
mtr_t* mtr, /*!< in/out: mtr */
page_cur_t* page_cur)/*!< in/out: cursor positioned on the record
after which to insert the buffered entry */
{
if (page_cur_tuple_insert(page_cur, entry, index, offsets, &heap, 0, mtr))
if (page_cur_tuple_insert(page_cur, entry, offsets, &heap, 0, mtr))
return DB_SUCCESS;
/* Page reorganization or recompression should already have been
attempted by page_cur_tuple_insert(). Besides, per
ibuf_index_page_calc_free_zip() the page should not have been
recompressed or reorganized. */
ut_ad(!is_buf_block_get_page_zip(block));
ut_ad(!is_buf_block_get_page_zip(page_cur->block));
/* If the record did not fit, reorganize */
if (dberr_t err= btr_page_reorganize(page_cur, index, mtr))
if (dberr_t err= btr_page_reorganize(page_cur, mtr))
return err;
/* This time the record must fit */
if (page_cur_tuple_insert(page_cur, entry, index, offsets, &heap, 0, mtr))
if (page_cur_tuple_insert(page_cur, entry, offsets, &heap, 0, mtr))
return DB_SUCCESS;
return DB_CORRUPTION;
@@ -3738,8 +3656,10 @@ ibuf_insert_to_index_page(
}
ulint up_match = 0, low_match = 0;
page_cur.index = index;
page_cur.block = block;
if (page_cur_search_with_match(block, index, entry, PAGE_CUR_LE,
if (page_cur_search_with_match(entry, PAGE_CUR_LE,
&up_match, &low_match, &page_cur,
nullptr)) {
return DB_CORRUPTION;
@@ -3786,7 +3706,7 @@ ibuf_insert_to_index_page(
if (!row_upd_changes_field_size_or_external(index, offsets,
update)
&& (!page_zip || btr_cur_update_alloc_zip(
page_zip, &page_cur, index, offsets,
page_zip, &page_cur, offsets,
rec_offs_size(offsets), false, mtr))) {
/* This is the easy case. Do something similar
to btr_cur_update_in_place(). */
@@ -3827,7 +3747,7 @@ ibuf_insert_to_index_page(
/* Delete the different-length record, and insert the
buffered one. */
page_cur_delete_rec(&page_cur, index, offsets, mtr);
page_cur_delete_rec(&page_cur, offsets, mtr);
if (!(page_cur_move_to_prev(&page_cur))) {
err = DB_CORRUPTION;
goto updated_in_place;
@@ -3836,8 +3756,8 @@ ibuf_insert_to_index_page(
offsets = NULL;
}
err = ibuf_insert_to_index_page_low(entry, block, index,
&offsets, heap, mtr, &page_cur);
err = ibuf_insert_to_index_page_low(entry, &offsets, heap, mtr,
&page_cur);
updated_in_place:
mem_heap_free(heap);
@@ -3853,16 +3773,18 @@ ibuf_set_del_mark(
/*==============*/
const dtuple_t* entry, /*!< in: entry */
buf_block_t* block, /*!< in/out: block */
const dict_index_t* index, /*!< in: record descriptor */
dict_index_t* index, /*!< in: record descriptor */
mtr_t* mtr) /*!< in: mtr */
{
page_cur_t page_cur;
page_cur.block = block;
page_cur.index = index;
ulint up_match = 0, low_match = 0;
ut_ad(ibuf_inside(mtr));
ut_ad(dtuple_check_typed(entry));
if (!page_cur_search_with_match(block, index, entry, PAGE_CUR_LE,
if (!page_cur_search_with_match(entry, PAGE_CUR_LE,
&up_match, &low_match, &page_cur,
nullptr)
&& low_match == dtuple_get_n_fields(entry)) {
@@ -3914,6 +3836,8 @@ ibuf_delete(
before latching any further pages */
{
page_cur_t page_cur;
page_cur.block = block;
page_cur.index = index;
ulint up_match = 0, low_match = 0;
ut_ad(ibuf_inside(mtr));
@@ -3921,7 +3845,7 @@ ibuf_delete(
ut_ad(!index->is_spatial());
ut_ad(!index->is_clust());
if (!page_cur_search_with_match(block, index, entry, PAGE_CUR_LE,
if (!page_cur_search_with_match(entry, PAGE_CUR_LE,
&up_match, &low_match, &page_cur,
nullptr)
&& low_match == dtuple_get_n_fields(entry)) {
@@ -3974,7 +3898,7 @@ ibuf_delete(
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index));
#endif /* UNIV_ZIP_DEBUG */
page_cur_delete_rec(&page_cur, index, offsets, mtr);
page_cur_delete_rec(&page_cur, offsets, mtr);
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index));
#endif /* UNIV_ZIP_DEBUG */
@@ -4001,13 +3925,12 @@ ibuf_restore_pos(
const page_id_t page_id,/*!< in: page identifier */
const dtuple_t* search_tuple,
/*!< in: search tuple for entries of page_no */
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_PURGE_TREE */
btr_pcur_t* pcur, /*!< in/out: persistent cursor whose
position is to be restored */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
ut_ad(mode == BTR_MODIFY_LEAF
|| BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE);
ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_PURGE_TREE);
if (UNIV_LIKELY(pcur->restore_position(mode, mtr) ==
btr_pcur_t::SAME_ALL)) {
@@ -4090,8 +4013,7 @@ bool ibuf_delete_rec(const page_id_t page_id, btr_pcur_t* pcur,
ibuf_mtr_start(mtr);
mysql_mutex_lock(&ibuf_mutex);
if (!ibuf_restore_pos(page_id, search_tuple,
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
if (!ibuf_restore_pos(page_id, search_tuple, BTR_PURGE_TREE,
pcur, mtr)) {
mysql_mutex_unlock(&ibuf_mutex);
@@ -4278,13 +4200,14 @@ dberr_t ibuf_merge_or_delete_for_page(buf_block_t *block,
memset(mops, 0, sizeof(mops));
memset(dops, 0, sizeof(dops));
pcur.btr_cur.page_cur.index = ibuf.index;
loop:
ibuf_mtr_start(&mtr);
/* Position pcur in the insert buffer at the first entry for this
index page */
if (btr_pcur_open_on_user_rec(ibuf.index, search_tuple, PAGE_CUR_GE,
if (btr_pcur_open_on_user_rec(search_tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF, &pcur, &mtr)
!= DB_SUCCESS) {
err = DB_CORRUPTION;
@@ -4437,7 +4360,6 @@ loop:
goto loop;
} else if (btr_pcur_is_after_last_on_page(&pcur)) {
ibuf_mtr_commit(&mtr);
ut_free(pcur.old_rec_buf);
goto loop;
}
}
@@ -4485,13 +4407,15 @@ void ibuf_delete_for_discarded_space(uint32_t space)
search_tuple = ibuf_search_tuple_build(space, 0, heap);
memset(dops, 0, sizeof(dops));
pcur.btr_cur.page_cur.index = ibuf.index;
loop:
log_free_check();
ibuf_mtr_start(&mtr);
/* Position pcur in the insert buffer at the first entry for the
space */
if (btr_pcur_open_on_user_rec(ibuf.index, search_tuple, PAGE_CUR_GE,
if (btr_pcur_open_on_user_rec(search_tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF, &pcur, &mtr)
!= DB_SUCCESS) {
goto leave_loop;
@@ -4577,7 +4501,7 @@ ibuf_print(
fprintf(file,
"Ibuf: size " ULINTPF ", free list len " ULINTPF ","
" seg size " ULINTPF ", " ULINTPF " merges\n",
ibuf.size,
ulint{ibuf.size},
ibuf.free_list_len,
ibuf.seg_size,
ulint{ibuf.n_merges});

View File

@@ -55,103 +55,8 @@ not acceptable for it to lead to mysterious memory corruption, but it
is acceptable for the program to die with a clear assert failure. */
#define BTR_MAX_LEVELS 100
/** Latching modes for btr_cur_search_to_nth_level(). */
enum btr_latch_mode {
/** Search a record on a leaf page and S-latch it. */
BTR_SEARCH_LEAF = RW_S_LATCH,
/** (Prepare to) modify a record on a leaf page and X-latch it. */
BTR_MODIFY_LEAF = RW_X_LATCH,
/** Obtain no latches. */
BTR_NO_LATCHES = RW_NO_LATCH,
/** Search the previous record. */
BTR_SEARCH_PREV = 4 | BTR_SEARCH_LEAF,
/** Modify the previous record. */
BTR_MODIFY_PREV = 4 | BTR_MODIFY_LEAF,
/** Start searching the entire B-tree. */
BTR_SEARCH_TREE = 8 | BTR_SEARCH_LEAF,
/** Start modifying1 the entire B-tree. */
BTR_MODIFY_TREE = 8 | BTR_MODIFY_LEAF,
/** Continue searching the entire B-tree. */
BTR_CONT_SEARCH_TREE = 4 | BTR_SEARCH_TREE,
/** Continue modifying the entire B-tree. */
BTR_CONT_MODIFY_TREE = 4 | BTR_MODIFY_TREE,
/* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually
exclusive. */
/** The search tuple will be inserted to the secondary index
at the searched position. When the leaf page is not in the
buffer pool, try to use the change buffer. */
BTR_INSERT = 64,
/** Try to delete mark a secondary index leaf page record at
the searched position using the change buffer when the page is
not in the buffer pool. */
BTR_DELETE_MARK = 128,
/** Try to purge the record using the change buffer when the
secondary index leaf page is not in the buffer pool. */
BTR_DELETE = BTR_INSERT | BTR_DELETE_MARK,
/** The caller is already holding dict_index_t::lock S-latch. */
BTR_ALREADY_S_LATCHED = 256,
/** Search and S-latch a leaf page, assuming that the
dict_index_t::lock S-latch is being held. */
BTR_SEARCH_LEAF_ALREADY_S_LATCHED = BTR_SEARCH_LEAF
| BTR_ALREADY_S_LATCHED,
/** Search the entire index tree, assuming that the
dict_index_t::lock S-latch is being held. */
BTR_SEARCH_TREE_ALREADY_S_LATCHED = BTR_SEARCH_TREE
| BTR_ALREADY_S_LATCHED,
/** Search and X-latch a leaf page, assuming that the
dict_index_t::lock S-latch is being held. */
BTR_MODIFY_LEAF_ALREADY_S_LATCHED = BTR_MODIFY_LEAF
| BTR_ALREADY_S_LATCHED,
/** Attempt to delete-mark a secondary index record. */
BTR_DELETE_MARK_LEAF = BTR_MODIFY_LEAF | BTR_DELETE_MARK,
/** Attempt to delete-mark a secondary index record
while holding the dict_index_t::lock S-latch. */
BTR_DELETE_MARK_LEAF_ALREADY_S_LATCHED = BTR_DELETE_MARK_LEAF
| BTR_ALREADY_S_LATCHED,
/** Attempt to purge a secondary index record. */
BTR_PURGE_LEAF = BTR_MODIFY_LEAF | BTR_DELETE,
/** Attempt to purge a secondary index record
while holding the dict_index_t::lock S-latch. */
BTR_PURGE_LEAF_ALREADY_S_LATCHED = BTR_PURGE_LEAF
| BTR_ALREADY_S_LATCHED,
/** In the case of BTR_MODIFY_TREE, the caller specifies
the intention to delete record only. It is used to optimize
block->lock range.*/
BTR_LATCH_FOR_DELETE = 512,
/** Attempt to purge a secondary index record in the tree. */
BTR_PURGE_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE
};
/** This flag ORed to BTR_INSERT says that we can ignore possible
UNIQUE definition on secondary indexes when we decide if we can use
the insert buffer to speed up inserts */
#define BTR_IGNORE_SEC_UNIQUE 2048U
/** In the case of BTR_MODIFY_TREE, the caller specifies the intention
to insert record only. It is used to optimize block->lock range.*/
#define BTR_LATCH_FOR_INSERT 4096U
/** This flag is for undo insert of rtree. For rtree, we need this flag
to find proper rec to undo insert.*/
#define BTR_RTREE_UNDO_INS 8192U
/** In the case of BTR_MODIFY_LEAF, the caller intends to allocate or
free the pages of externally stored fields. */
#define BTR_MODIFY_EXTERNAL 16384U
/** Try to delete mark the record at the searched position when the
record is in spatial index */
#define BTR_RTREE_DELETE_MARK 32768U
#define BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode) \
((latch_mode) & ulint(~(BTR_INSERT \
btr_latch_mode((latch_mode) & ~(BTR_INSERT \
| BTR_DELETE_MARK \
| BTR_RTREE_UNDO_INS \
| BTR_RTREE_DELETE_MARK \
@@ -159,13 +64,11 @@ record is in spatial index */
| BTR_IGNORE_SEC_UNIQUE \
| BTR_ALREADY_S_LATCHED \
| BTR_LATCH_FOR_INSERT \
| BTR_LATCH_FOR_DELETE \
| BTR_MODIFY_EXTERNAL)))
| BTR_LATCH_FOR_DELETE))
#define BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode) \
((latch_mode) & ulint(~(BTR_LATCH_FOR_INSERT \
| BTR_LATCH_FOR_DELETE \
| BTR_MODIFY_EXTERNAL)))
btr_latch_mode((latch_mode) \
& ~(BTR_LATCH_FOR_INSERT | BTR_LATCH_FOR_DELETE))
/**************************************************************//**
Checks and adjusts the root node of a tree during IMPORT TABLESPACE.
@@ -228,17 +131,6 @@ inline uint32_t btr_page_get_prev(const page_t* page)
return mach_read_from_4(my_assume_aligned<4>(page + FIL_PAGE_PREV));
}
/**************************************************************//**
Releases the latch on a leaf page and bufferunfixes it. */
UNIV_INLINE
void
btr_leaf_page_release(
/*==================*/
buf_block_t* block, /*!< in: buffer block */
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
BTR_MODIFY_LEAF */
mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((nonnull));
/**************************************************************//**
Gets the child node file address in a node pointer.
NOTE: the offsets array must contain all offsets for the record since
@@ -359,14 +251,11 @@ be done either within the same mini-transaction, or by invoking
ibuf_reset_free_bits() before mtr_commit(). On uncompressed pages,
IBUF_BITMAP_FREE is unaffected by reorganization.
@param cursor page cursor
@param mtr mini-transaction
@return error code
@retval DB_FAIL if reorganizing a ROW_FORMAT=COMPRESSED page failed */
dberr_t
btr_page_reorganize(
/*================*/
page_cur_t* cursor, /*!< in/out: page cursor */
dict_index_t* index, /*!< in: the index tree of the page */
mtr_t* mtr) /*!< in/out: mini-transaction */
dberr_t btr_page_reorganize(page_cur_t *cursor, mtr_t *mtr)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Decide if the page should be split at the convergence point of inserts
converging to the left.
@@ -445,13 +334,10 @@ inline void btr_set_min_rec_mark(rec_t *rec, const buf_block_t &block,
}
/** Seek to the parent page of a B-tree page.
@param[in,out] index b-tree
@param[in] block child page
@param[in,out] mtr mini-transaction
@param[out] cursor cursor pointing to the x-latched parent page
@param[in,out] cursor cursor pointing to the x-latched parent page
@return whether the cursor was successfully positioned */
bool btr_page_get_father(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
btr_cur_t* cursor)
bool btr_page_get_father(mtr_t* mtr, btr_cur_t* cursor)
MY_ATTRIBUTE((nonnull,warn_unused_result));
#ifdef UNIV_DEBUG
/************************************************************//**

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2021, MariaDB Corporation.
Copyright (c) 2015, 2022, MariaDB Corporation.
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
@@ -24,10 +24,7 @@ The B-tree
Created 6/2/1994 Heikki Tuuri
*******************************************************/
#include "mach0data.h"
#include "mtr0mtr.h"
#include "mtr0log.h"
#include "page0zip.h"
/**************************************************************//**
Gets the index id field of a page.
@@ -112,38 +109,3 @@ btr_node_ptr_get_child_page_no(
return(page_no);
}
/**************************************************************//**
Releases the latches on a leaf page and bufferunfixes it. */
UNIV_INLINE
void
btr_leaf_page_release(
/*==================*/
buf_block_t* block, /*!< in: buffer block */
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
BTR_MODIFY_LEAF */
mtr_t* mtr) /*!< in: mtr */
{
ut_ad(latch_mode == BTR_SEARCH_LEAF
|| latch_mode == BTR_MODIFY_LEAF
|| latch_mode == BTR_NO_LATCHES);
ut_ad(!mtr->memo_contains_flagged(block, MTR_MEMO_MODIFY));
mtr_memo_type_t mode;
switch (latch_mode) {
case BTR_SEARCH_LEAF:
mode = MTR_MEMO_PAGE_S_FIX;
break;
case BTR_MODIFY_LEAF:
mode = MTR_MEMO_PAGE_X_FIX;
break;
case BTR_NO_LATCHES:
mode = MTR_MEMO_BUF_FIX;
break;
default:
ut_a(0);
}
mtr->memo_release(block, mode);
}

View File

@@ -96,7 +96,7 @@ btr_cur_get_page(
Returns the index of a cursor.
@param cursor b-tree cursor
@return index */
#define btr_cur_get_index(cursor) ((cursor)->index)
#define btr_cur_get_index(cursor) ((cursor)->index())
/*********************************************************//**
Positions a tree cursor at a given record. */
UNIV_INLINE
@@ -137,7 +137,7 @@ bool
btr_cur_optimistic_latch_leaves(
buf_block_t* block,
ib_uint64_t modify_clock,
ulint* latch_mode,
btr_latch_mode* latch_mode,
btr_cur_t* cursor,
mtr_t* mtr);
@@ -148,7 +148,6 @@ 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
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.
@param index index
@param level the tree level of search
@param tuple data tuple; NOTE: n_fields_cmp in tuple must be set so that
it cannot get compared to the node ptr page number field!
@@ -166,27 +165,13 @@ If mode is PAGE_CUR_GE, then up_match will a have a sensible value.
@param mtr mini-transaction
@param autoinc PAGE_ROOT_AUTO_INC to be written (0 if none)
@return DB_SUCCESS on success or error code otherwise */
dberr_t btr_cur_search_to_nth_level(dict_index_t *index, ulint level,
dberr_t btr_cur_search_to_nth_level(ulint level,
const dtuple_t *tuple,
page_cur_mode_t mode, ulint latch_mode,
page_cur_mode_t mode,
btr_latch_mode latch_mode,
btr_cur_t *cursor, mtr_t *mtr,
ib_uint64_t autoinc= 0);
/*****************************************************************//**
Opens a cursor at either end of an index.
@return DB_SUCCESS or error code */
dberr_t
btr_cur_open_at_index_side(
bool from_left, /*!< in: true if open to the low end,
false if to the high end */
dict_index_t* index, /*!< in: index */
ulint latch_mode, /*!< in: latch mode */
btr_cur_t* cursor, /*!< in/out: cursor */
ulint level, /*!< in: level to search for
(0=leaf) */
mtr_t* mtr) /*!< in/out: mini-transaction */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/**********************************************************************//**
Positions a cursor at a randomly chosen position within a B-tree.
@return true if the index is available and we have put the cursor, false
@@ -194,7 +179,7 @@ if the index is unavailable */
bool
btr_cur_open_at_rnd_pos(
dict_index_t* index, /*!< in: index */
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
btr_latch_mode latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
btr_cur_t* cursor, /*!< in/out: B-tree cursor */
mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((nonnull,warn_unused_result));
@@ -281,7 +266,6 @@ btr_cur_update_alloc_zip_func(
/*==========================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page */
page_cur_t* cursor, /*!< in/out: B-tree page cursor */
dict_index_t* index, /*!< in: the index corresponding to cursor */
#ifdef UNIV_DEBUG
rec_offs* offsets,/*!< in/out: offsets of the cursor record */
#endif /* UNIV_DEBUG */
@@ -291,11 +275,11 @@ btr_cur_update_alloc_zip_func(
mtr_t* mtr) /*!< in/out: mini-transaction */
MY_ATTRIBUTE((nonnull, warn_unused_result));
#ifdef UNIV_DEBUG
# define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \
btr_cur_update_alloc_zip_func(page_zip,cursor,index,offsets,len,cr,mtr)
# define btr_cur_update_alloc_zip(page_zip,cursor,offsets,len,cr,mtr) \
btr_cur_update_alloc_zip_func(page_zip,cursor,offsets,len,cr,mtr)
#else /* UNIV_DEBUG */
# define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \
btr_cur_update_alloc_zip_func(page_zip,cursor,index,len,cr,mtr)
# define btr_cur_update_alloc_zip(page_zip,cursor,offsets,len,cr,mtr) \
btr_cur_update_alloc_zip_func(page_zip,cursor,len,cr,mtr)
#endif /* UNIV_DEBUG */
/** Apply an update vector to a record. No field size changes are allowed.
@@ -689,7 +673,7 @@ btr_rec_copy_externally_stored_field(
void
btr_cur_latch_leaves(
buf_block_t* block,
ulint latch_mode,
btr_latch_mode latch_mode,
btr_cur_t* cursor,
mtr_t* mtr,
btr_latch_leaves_t* latch_leaves = nullptr);
@@ -752,7 +736,6 @@ enum btr_cur_method {
/** The tree cursor: the definition appears here only for the compiler
to know struct size! */
struct btr_cur_t {
dict_index_t* index; /*!< index where positioned */
page_cur_t page_cur; /*!< page cursor */
purge_node_t* purge_node; /*!< purge node, for BTR_DELETE */
buf_block_t* left_block; /*!< this field is used to store
@@ -817,28 +800,19 @@ struct btr_cur_t {
information of the path through
the tree */
rtr_info_t* rtr_info; /*!< rtree search info */
btr_cur_t():thr(NULL), rtr_info(NULL) {}
/* default values */
/** Zero-initialize all fields */
void init()
{
index = NULL;
memset(&page_cur, 0, sizeof page_cur);
purge_node = NULL;
left_block = NULL;
thr = NULL;
flag = btr_cur_method(0);
tree_height = 0;
up_match = 0;
up_bytes = 0;
low_match = 0;
low_bytes = 0;
n_fields = 0;
n_bytes = 0;
fold = 0;
path_arr = NULL;
rtr_info = NULL;
}
btr_cur_t() { memset((void*) this, 0, sizeof *this); }
dict_index_t *index() const { return page_cur.index; }
buf_block_t *block() const { return page_cur.block; }
/** Open the cursor on the first or last record.
@param first true=first record, false=last record
@param index B-tree
@param latch_mode which latches to acquire
@param mtr mini-transaction
@return error code */
dberr_t open_leaf(bool first, dict_index_t *index, btr_latch_mode latch_mode,
mtr_t *mtr);
};
/** Modify the delete-mark flag of a record.

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, 2021, MariaDB Corporation.
Copyright (c) 2018, 2022, MariaDB Corporation.
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
@@ -72,7 +72,7 @@ btr_cur_position(
btr_cur_t* cursor) /*!< out: cursor */
{
page_cur_position(rec, block, btr_cur_get_page_cur(cursor));
cursor->index = index;
cursor->page_cur.index = index;
}
/*********************************************************************//**
@@ -98,14 +98,14 @@ btr_cur_compress_recommendation(
if (!page_has_siblings(page)
|| page_get_data_size(page)
< BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) {
< BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index())) {
/* The page fillfactor has dropped below a predefined
minimum value OR the level in the B-tree contains just
one page: we recommend compression if this is not the
root page. */
return cursor->index->page
return cursor->index()->page
!= btr_cur_get_block(cursor)->page.id().page_no();
}
@@ -133,14 +133,14 @@ btr_cur_can_delete_without_compress(
if (!page_has_siblings(page) || page_get_n_recs(page) < 2
|| page_get_data_size(page) - rec_size
< BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) {
< BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index())) {
/* The page fillfactor will drop below a predefined
minimum value, OR the level in the B-tree contains just
one page, OR the page will become empty: we recommend
compression if this is not the root page. */
return cursor->index->page
return cursor->index()->page
== btr_cur_get_block(cursor)->page.id().page_no();
}

View File

@@ -45,13 +45,6 @@ of a scroll cursor easier */
BTR_PCUR_AFTER_LAST_IN_TREE = 5 /* in an empty tree */
};
/**************************************************************//**
Allocates memory for a persistent cursor object and initializes the cursor.
@return own: persistent cursor */
btr_pcur_t*
btr_pcur_create_for_mysql(void);
/*============================*/
/**************************************************************//**
Resets a persistent cursor object, freeing ::old_rec_buf if it is
allocated and resetting the other members to their initial values. */
@@ -61,12 +54,6 @@ btr_pcur_reset(
btr_pcur_t* cursor);/*!< in, out: persistent cursor */
/**************************************************************//**
Frees the memory for a persistent cursor object. */
void
btr_pcur_free_for_mysql(
/*====================*/
btr_pcur_t* cursor); /*!< in, own: persistent cursor */
/**************************************************************//**
Copies the stored position of a pcur to another pcur. */
void
btr_pcur_copy_stored_position(
@@ -83,21 +70,11 @@ btr_pcur_init(
/*==========*/
btr_pcur_t* pcur); /*!< in: persistent cursor */
/** Free old_rec_buf.
@param[in] pcur Persistent cursor holding old_rec to be freed. */
UNIV_INLINE
void
btr_pcur_free(
btr_pcur_t* pcur);
/**************************************************************//**
Initializes and opens a persistent cursor to an index tree. */
inline
dberr_t
btr_pcur_open_low(
/*==============*/
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: level in the btree */
btr_pcur_open(
const dtuple_t* tuple, /*!< in: tuple on which search done */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
NOTE that if the search is made using a unique
@@ -105,17 +82,14 @@ btr_pcur_open_low(
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
may end up on the previous page from the
record! */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written
(0 if none) */
mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((nonnull, warn_unused_result));
#define btr_pcur_open(i,t,md,l,c,m) \
btr_pcur_open_low(i,0,t,md,l,c,0,m)
/** Opens an persistent cursor to an index tree without initializing the
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
@@ -126,26 +100,11 @@ cursor.
@param mtr mini-transaction
@return DB_SUCCESS on success or error code otherwise. */
inline
dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple,
page_cur_mode_t mode, ulint latch_mode,
dberr_t btr_pcur_open_with_no_init(const dtuple_t *tuple,
page_cur_mode_t mode,
btr_latch_mode latch_mode,
btr_pcur_t *cursor, mtr_t *mtr);
/*****************************************************************//**
Opens a persistent cursor at either end of an index. */
UNIV_INLINE
dberr_t
btr_pcur_open_at_index_side(
/*========================*/
bool from_left, /*!< in: true if open to the low end,
false if to the high end */
dict_index_t* index, /*!< in: index */
ulint latch_mode, /*!< in: latch mode */
btr_pcur_t* pcur, /*!< in/out: cursor */
bool init_pcur, /*!< in: whether to initialize pcur */
ulint level, /*!< in: level to search for
(0=leaf) */
mtr_t* mtr) /*!< in/out: mini-transaction */
MY_ATTRIBUTE((nonnull,warn_unused_result));
/**************************************************************//**
Gets the up_match value for a pcur after a search.
@return number of matched fields at the cursor or to the right if
@@ -356,7 +315,8 @@ enum pcur_pos_t {
/* The persistent B-tree cursor structure. This is used mainly for SQL
selects, updates, and deletes. */
struct btr_pcur_t{
struct btr_pcur_t
{
/** Return value of restore_position() */
enum restore_status {
/** cursor position on user rec and points on the record with
@@ -373,61 +333,42 @@ struct btr_pcur_t{
};
/** a B-tree cursor */
btr_cur_t btr_cur;
/** see TODO note below!
/** @see BTR_PCUR_WAS_POSITIONED
BTR_SEARCH_LEAF, BTR_MODIFY_LEAF, BTR_MODIFY_TREE or BTR_NO_LATCHES,
depending on the latching state of the page and tree where the cursor
is positioned; BTR_NO_LATCHES means that the cursor is not currently
positioned:
we say then that the cursor is detached; it can be restored to
attached if the old position was stored in old_rec */
ulint latch_mode;
/** true if old_rec is stored */
bool old_stored;
btr_latch_mode latch_mode= BTR_NO_LATCHES;
/** if cursor position is stored, contains an initial segment of the
latest record cursor was positioned either on, before or after */
rec_t* old_rec;
/** btr_cur.index->n_core_fields when old_rec was copied */
uint16 old_n_core_fields;
rec_t *old_rec= nullptr;
/** btr_cur.index()->n_core_fields when old_rec was copied */
uint16 old_n_core_fields= 0;
/** number of fields in old_rec */
uint16 old_n_fields;
uint16 old_n_fields= 0;
/** BTR_PCUR_ON, BTR_PCUR_BEFORE, or BTR_PCUR_AFTER, depending on
whether cursor was on, before, or after the old_rec record */
enum btr_pcur_pos_t rel_pos;
btr_pcur_pos_t rel_pos= btr_pcur_pos_t(0);
/** buffer block when the position was stored */
buf::Block_hint block_when_stored;
/** the modify clock value of the buffer block when the cursor position
was stored */
ib_uint64_t modify_clock;
ib_uint64_t modify_clock= 0;
/** btr_pcur_store_position() and btr_pcur_restore_position() state. */
enum pcur_pos_t pos_state;
/** PAGE_CUR_G, ... */
page_cur_mode_t search_mode;
enum pcur_pos_t pos_state= BTR_PCUR_NOT_POSITIONED;
page_cur_mode_t search_mode= PAGE_CUR_UNSUPP;
/** the transaction, if we know it; otherwise this field is not defined;
can ONLY BE USED in error prints in fatal assertion failures! */
trx_t* trx_if_known;
/*-----------------------------*/
/* NOTE that the following fields may possess dynamically allocated
memory which should be freed if not needed anymore! */
/** NULL, or a dynamically allocated buffer for old_rec */
byte* old_rec_buf;
trx_t *trx_if_known= nullptr;
/** a dynamically allocated buffer for old_rec */
byte *old_rec_buf= nullptr;
/** old_rec_buf size if old_rec_buf is not NULL */
ulint buf_size;
btr_pcur_t() :
btr_cur(), latch_mode(RW_NO_LATCH),
old_stored(false), old_rec(NULL),
old_n_fields(0), rel_pos(btr_pcur_pos_t(0)),
block_when_stored(),
modify_clock(0), pos_state(BTR_PCUR_NOT_POSITIONED),
search_mode(PAGE_CUR_UNSUPP), trx_if_known(NULL),
old_rec_buf(NULL), buf_size(0)
{
btr_cur.init();
}
ulint buf_size= 0;
/** Return the index of this persistent cursor */
dict_index_t* index() const { return(btr_cur.index); }
dict_index_t *index() const { return(btr_cur.index()); }
MY_ATTRIBUTE((nonnull, warn_unused_result))
/** Restores the stored position of a persistent cursor bufferfixing
the page and obtaining the specified latches. If the cursor position
@@ -451,7 +392,26 @@ struct btr_pcur_t{
@retval NOT_SAME cursor position is not on user rec or points on
the record with not the same uniq field values as in the stored
@retval CORRUPTED if the index is corrupted */
restore_status restore_position(ulint latch_mode, mtr_t *mtr);
restore_status restore_position(btr_latch_mode latch_mode, mtr_t *mtr);
/** Open the cursor on the first or last record.
@param first true=first record, false=last record
@param index B-tree
@param latch_mode which latches to acquire
@param mtr mini-transaction
@return error code */
dberr_t open_leaf(bool first, dict_index_t *index, btr_latch_mode latch_mode,
mtr_t *mtr)
{
this->latch_mode= BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
search_mode= first ? PAGE_CUR_G : PAGE_CUR_L;
pos_state= BTR_PCUR_IS_POSITIONED;
old_rec= nullptr;
return btr_cur.open_leaf(first, index,
BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode), mtr);
}
};
inline buf_block_t *btr_pcur_get_block(btr_pcur_t *cursor)
@@ -479,10 +439,9 @@ MY_ATTRIBUTE((nonnull, warn_unused_result))
inline
dberr_t
btr_pcur_open_on_user_rec(
dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ... */
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
btr_latch_mode latch_mode, /*!< in: BTR_SEARCH_LEAF or
BTR_MODIFY_LEAF */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent
cursor */
@@ -490,7 +449,7 @@ btr_pcur_open_on_user_rec(
{
ut_ad(mode == PAGE_CUR_GE || mode == PAGE_CUR_G);
ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF);
if (dberr_t err= btr_pcur_open(index, tuple, mode, latch_mode, cursor, mtr))
if (dberr_t err= btr_pcur_open(tuple, mode, latch_mode, cursor, 0, mtr))
return err;
if (!btr_pcur_is_after_last_on_page(cursor) ||
btr_pcur_is_after_last_in_tree(cursor))

View File

@@ -36,7 +36,6 @@ btr_pcur_get_rel_pos(
{
ut_ad(cursor);
ut_ad(cursor->old_rec);
ut_ad(cursor->old_stored);
ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
|| cursor->pos_state == BTR_PCUR_IS_POSITIONED);
@@ -163,7 +162,7 @@ btr_pcur_move_to_next_on_page(
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
cursor->old_stored = false;
cursor->old_rec = nullptr;
return page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
}
@@ -177,7 +176,7 @@ btr_pcur_move_to_prev_on_page(
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
cursor->old_stored = false;
cursor->old_rec = nullptr;
return page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
}
@@ -196,7 +195,7 @@ btr_pcur_move_to_next_user_rec(
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
cursor->old_stored = false;
cursor->old_rec = nullptr;
loop:
if (btr_pcur_is_after_last_on_page(cursor)) {
if (btr_pcur_is_after_last_in_tree(cursor)
@@ -230,7 +229,7 @@ btr_pcur_move_to_next(
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
cursor->old_stored= false;
cursor->old_rec= nullptr;
if (btr_pcur_is_after_last_on_page(cursor))
return !btr_pcur_is_after_last_in_tree(cursor) &&
@@ -294,31 +293,17 @@ btr_pcur_init(
/*==========*/
btr_pcur_t* pcur) /*!< in: persistent cursor */
{
pcur->old_stored = false;
pcur->old_rec_buf = NULL;
pcur->old_rec = NULL;
pcur->btr_cur.rtr_info = NULL;
}
/** Free old_rec_buf.
@param[in] pcur Persistent cursor holding old_rec to be freed. */
UNIV_INLINE
void
btr_pcur_free(
btr_pcur_t* pcur)
{
ut_free(pcur->old_rec_buf);
}
/**************************************************************//**
Initializes and opens a persistent cursor to an index tree. */
inline
dberr_t
btr_pcur_open_low(
/*==============*/
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: level in the btree */
btr_pcur_open(
const dtuple_t* tuple, /*!< in: tuple on which search done */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
NOTE that if the search is made using a unique
@@ -326,26 +311,24 @@ btr_pcur_open_low(
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
may end up on the previous page from the
record! */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written
(0 if none) */
mtr_t* mtr) /*!< in: mtr */
{
ut_ad(!index->is_spatial());
btr_pcur_init(cursor);
ut_ad(!cursor->index()->is_spatial());
cursor->latch_mode= BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
cursor->search_mode= mode;
cursor->pos_state= BTR_PCUR_IS_POSITIONED;
cursor->trx_if_known= nullptr;
return btr_cur_search_to_nth_level(index, level, tuple, mode, latch_mode,
return btr_cur_search_to_nth_level(0, tuple, mode, latch_mode,
btr_pcur_get_btr_cur(cursor),
mtr, autoinc);
}
/** Opens an persistent cursor to an index tree without initializing the
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
@@ -356,59 +339,21 @@ cursor.
@param mtr mini-transaction
@return DB_SUCCESS on success or error code otherwise. */
inline
dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple,
page_cur_mode_t mode, ulint latch_mode,
dberr_t btr_pcur_open_with_no_init(const dtuple_t *tuple,
page_cur_mode_t mode,
btr_latch_mode latch_mode,
btr_pcur_t *cursor, mtr_t *mtr)
{
cursor->latch_mode= BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode);
cursor->search_mode= mode;
cursor->pos_state= BTR_PCUR_IS_POSITIONED;
cursor->old_stored= false;
cursor->trx_if_known= nullptr;
/* Search with the tree cursor */
return btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
return btr_cur_search_to_nth_level(0, tuple, mode, latch_mode,
btr_pcur_get_btr_cur(cursor), mtr);
}
/*****************************************************************//**
Opens a persistent cursor at either end of an index. */
UNIV_INLINE
dberr_t
btr_pcur_open_at_index_side(
/*========================*/
bool from_left, /*!< in: true if open to the low end,
false if to the high end */
dict_index_t* index, /*!< in: index */
ulint latch_mode, /*!< in: latch mode */
btr_pcur_t* pcur, /*!< in/out: cursor */
bool init_pcur, /*!< in: whether to initialize pcur */
ulint level, /*!< in: level to search for
(0=leaf) */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
dberr_t err = DB_SUCCESS;
pcur->latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
pcur->search_mode = from_left ? PAGE_CUR_G : PAGE_CUR_L;
if (init_pcur) {
btr_pcur_init(pcur);
}
err = btr_cur_open_at_index_side(
from_left, index, latch_mode,
btr_pcur_get_btr_cur(pcur), level, mtr);
pcur->pos_state = BTR_PCUR_IS_POSITIONED;
pcur->old_stored = false;
pcur->trx_if_known = NULL;
return (err);
}
/**************************************************************//**
Frees the possible memory heap of a persistent cursor and sets the latch
mode of the persistent cursor to BTR_NO_LATCHES.
@@ -427,23 +372,19 @@ btr_pcur_close(
{
ut_free(cursor->old_rec_buf);
if (cursor->btr_cur.rtr_info) {
if (cursor->btr_cur.rtr_info)
rtr_clean_rtr_info(cursor->btr_cur.rtr_info, true);
cursor->btr_cur.rtr_info = NULL;
}
cursor->old_rec = NULL;
cursor->old_rec_buf = NULL;
cursor->btr_cur.page_cur.rec = NULL;
cursor->btr_cur.page_cur.block = NULL;
cursor->old_rec = NULL;
cursor->old_stored = false;
cursor->btr_cur.rtr_info= nullptr;
cursor->old_rec = nullptr;
cursor->old_rec_buf = nullptr;
cursor->btr_cur.page_cur.rec = nullptr;
cursor->btr_cur.page_cur.block = nullptr;
cursor->latch_mode = BTR_NO_LATCHES;
cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
cursor->trx_if_known = NULL;
cursor->trx_if_known = nullptr;
}
/*********************************************************//**
@@ -459,5 +400,5 @@ btr_pcur_move_before_first_on_page(
page_cur_set_before_first(btr_pcur_get_block(cursor),
btr_pcur_get_page_cur(cursor));
cursor->old_stored = false;
cursor->old_rec = nullptr;
}

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, 2019, MariaDB Corporation.
Copyright (c) 2018, 2022, MariaDB Corporation.
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
@@ -24,8 +24,7 @@ The index tree general types
Created 2/17/1996 Heikki Tuuri
*************************************************************************/
#ifndef btr0types_h
#define btr0types_h
#pragma once
#include "page0types.h"
#include "rem0types.h"
@@ -56,4 +55,93 @@ in the index record. */
#define BTR_EXTERN_LOCAL_STORED_MAX_SIZE \
(BTR_EXTERN_FIELD_REF_SIZE * 2)
#endif
/** Latching modes for btr_cur_search_to_nth_level(). */
enum btr_latch_mode {
/** Search a record on a leaf page and S-latch it. */
BTR_SEARCH_LEAF = RW_S_LATCH,
/** (Prepare to) modify a record on a leaf page and X-latch it. */
BTR_MODIFY_LEAF = RW_X_LATCH,
/** Obtain no latches. */
BTR_NO_LATCHES = RW_NO_LATCH,
/** Search the previous record. */
BTR_SEARCH_PREV = 4 | BTR_SEARCH_LEAF,
/** Modify the previous record. */
BTR_MODIFY_PREV = 4 | BTR_MODIFY_LEAF,
/** Start searching the entire B-tree. */
BTR_SEARCH_TREE = 8 | BTR_SEARCH_LEAF,
/** Start modifying1 the entire B-tree. */
BTR_MODIFY_TREE = 8 | BTR_MODIFY_LEAF,
/** Continue searching the entire B-tree. */
BTR_CONT_SEARCH_TREE = 4 | BTR_SEARCH_TREE,
/** Continue modifying the entire B-tree. */
BTR_CONT_MODIFY_TREE = 4 | BTR_MODIFY_TREE,
/* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually
exclusive. */
/** The search tuple will be inserted to the secondary index
at the searched position. When the leaf page is not in the
buffer pool, try to use the change buffer. */
BTR_INSERT = 64,
/** Try to delete mark a secondary index leaf page record at
the searched position using the change buffer when the page is
not in the buffer pool. */
BTR_DELETE_MARK = 128,
/** Try to purge the record using the change buffer when the
secondary index leaf page is not in the buffer pool. */
BTR_DELETE = BTR_INSERT | BTR_DELETE_MARK,
/** The caller is already holding dict_index_t::lock S-latch. */
BTR_ALREADY_S_LATCHED = 256,
/** Search and S-latch a leaf page, assuming that the
dict_index_t::lock S-latch is being held. */
BTR_SEARCH_LEAF_ALREADY_S_LATCHED = BTR_SEARCH_LEAF
| BTR_ALREADY_S_LATCHED,
/** Search the entire index tree, assuming that the
dict_index_t::lock S-latch is being held. */
BTR_SEARCH_TREE_ALREADY_S_LATCHED = BTR_SEARCH_TREE
| BTR_ALREADY_S_LATCHED,
/** Search and X-latch a leaf page, assuming that the
dict_index_t::lock is being held in non-exclusive mode. */
BTR_MODIFY_LEAF_ALREADY_LATCHED = BTR_MODIFY_LEAF
| BTR_ALREADY_S_LATCHED,
/** Attempt to delete-mark a secondary index record. */
BTR_DELETE_MARK_LEAF = BTR_MODIFY_LEAF | BTR_DELETE_MARK,
/** Attempt to delete-mark a secondary index record
while holding the dict_index_t::lock S-latch. */
BTR_DELETE_MARK_LEAF_ALREADY_S_LATCHED = BTR_DELETE_MARK_LEAF
| BTR_ALREADY_S_LATCHED,
/** Attempt to purge a secondary index record. */
BTR_PURGE_LEAF = BTR_MODIFY_LEAF | BTR_DELETE,
/** Attempt to purge a secondary index record
while holding the dict_index_t::lock S-latch. */
BTR_PURGE_LEAF_ALREADY_S_LATCHED = BTR_PURGE_LEAF
| BTR_ALREADY_S_LATCHED,
/** In the case of BTR_MODIFY_TREE, the caller specifies
the intention to delete record only. It is used to optimize
block->lock range.*/
BTR_LATCH_FOR_DELETE = 512,
/** In the case of BTR_MODIFY_TREE, the caller specifies
the intention to delete record only. It is used to optimize
block->lock range.*/
BTR_LATCH_FOR_INSERT = 1024,
/** Attempt to delete a record in the tree. */
BTR_PURGE_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
/** Attempt to insert a record into the tree. */
BTR_INSERT_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT,
/** This flag ORed to BTR_INSERT says that we can ignore possible
UNIQUE definition on secondary indexes when we decide if we can use
the insert buffer to speed up inserts */
BTR_IGNORE_SEC_UNIQUE = 2048,
/** Rollback in spatial index */
BTR_RTREE_UNDO_INS = 4096,
/** Try to delete mark a spatial index record */
BTR_RTREE_DELETE_MARK = 8192
};

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, 2020, MariaDB Corporation.
Copyright (c) 2018, 2022, MariaDB Corporation.
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
@@ -313,67 +313,13 @@ public:
return(m_size);
}
/**
Iterate over each block and call the functor.
@return false if iteration was terminated. */
template <typename Functor>
bool for_each_block(Functor& functor) const
{
for (list_t::iterator it = m_list.begin(), end = m_list.end();
it != end; ++it) {
if (!functor(&*it)) {
return false;
}
}
return(true);
}
/**
Iterate over each block and call the functor.
@return false if iteration was terminated. */
template <typename Functor>
bool for_each_block(const Functor& functor) const
{
for (typename list_t::iterator it = m_list.begin(),
end = m_list.end();
it != end; ++it) {
if (!functor(&*it)) {
return false;
}
}
return(true);
}
/**
Iterate over all the blocks in reverse and call the iterator
@return false if iteration was terminated. */
template <typename Functor>
bool for_each_block_in_reverse(Functor& functor) const
{
for (list_t::reverse_iterator it = m_list.rbegin(),
end = m_list.rend();
it != end; ++it) {
if (!functor(&*it)) {
return false;
}
}
return(true);
}
/**
Iterate over all the blocks in reverse and call the iterator
@return false if iteration was terminated. */
template <typename Functor>
bool for_each_block_in_reverse(const Functor& functor) const
{
for (list_t::reverse_iterator it = m_list.rbegin(),
end = m_list.rend();
for (list_t::iterator it = m_list.begin(), end = m_list.end();
it != end; ++it) {
if (!functor(&*it)) {

View File

@@ -256,23 +256,14 @@ rtr_get_mbr_from_tuple(
rtr_mbr* mbr); /*!< out: mbr to fill */
/* Get the rtree page father.
@param[in] offsets work area for the return value
@param[in] index rtree index
@param[in] block child page in the index
@param[in,out] mtr mtr
@param[in] sea_cur search cursor, contains information
about parent nodes in search
@param[out] cursor cursor on node pointer record,
@param[in,out] cursor cursor on node pointer record,
its page x-latched
@return whether the cursor was successfully positioned */
bool
rtr_page_get_father(
dict_index_t* index,
buf_block_t* block,
mtr_t* mtr,
btr_cur_t* sea_cur,
btr_cur_t* cursor)
MY_ATTRIBUTE((nonnull(1,2,3,5), warn_unused_result));
bool rtr_page_get_father(mtr_t *mtr, btr_cur_t *sea_cur, btr_cur_t *cursor)
MY_ATTRIBUTE((nonnull(1,3), warn_unused_result));
/************************************************************//**
Returns the father block to a page. It is assumed that mtr holds
@@ -283,8 +274,6 @@ rtr_page_get_father_block(
/*======================*/
rec_offs* offsets,/*!< in: work area for the return value */
mem_heap_t* heap, /*!< in: memory heap to use */
dict_index_t* index, /*!< in: b-tree index */
buf_block_t* block, /*!< in: child page in the index */
mtr_t* mtr, /*!< in: mtr */
btr_cur_t* sea_cur,/*!< in: search cursor, contains information
about parent nodes in search */
@@ -298,7 +287,7 @@ rtr_store_parent_path(
/*==================*/
const buf_block_t* block, /*!< in: block of the page */
btr_cur_t* btr_cur,/*!< in/out: persistent cursor */
ulint latch_mode,
btr_latch_mode latch_mode,
/*!< in: latch_mode */
ulint level, /*!< in: index level */
mtr_t* mtr); /*!< in: mtr */
@@ -310,7 +299,7 @@ bool
rtr_pcur_open(
dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((warn_unused_result));
@@ -432,7 +421,6 @@ rtr_check_same_block(
btr_cur_t* cur, /*!< in/out: position at the parent entry
pointing to the child if successful */
buf_block_t* parentb,/*!< in: parent page to check */
buf_block_t* childb, /*!< in: child Page */
mem_heap_t* heap); /*!< in: memory heap */
/*********************************************************************//**

View File

@@ -30,7 +30,6 @@ Created 7/19/1997 Heikki Tuuri
#include "mtr0mtr.h"
#include "dict0mem.h"
#include "fsp0fsp.h"
#include "ibuf0types.h"
/** Default value for maximum on-disk size of change buffer in terms
of percentage of the buffer pool. */
@@ -61,6 +60,37 @@ enum ibuf_use_t {
/** Operations that can currently be buffered. */
extern ulong innodb_change_buffering;
/** Insert buffer struct */
struct ibuf_t{
Atomic_relaxed<ulint> size; /*!< current size of the ibuf index
tree, in pages */
Atomic_relaxed<ulint> max_size; /*!< recommended maximum size of the
ibuf index tree, in pages */
ulint seg_size; /*!< allocated pages of the file
segment containing ibuf header and
tree */
bool empty; /*!< Protected by the page
latch of the root page of the
insert buffer tree
(FSP_IBUF_TREE_ROOT_PAGE_NO). true
if and only if the insert
buffer tree is empty. */
ulint free_list_len; /*!< length of the free list */
ulint height; /*!< tree height */
dict_index_t* index; /*!< insert buffer index */
/** number of pages merged */
Atomic_counter<ulint> n_merges;
Atomic_counter<ulint> n_merged_ops[IBUF_OP_COUNT];
/*!< number of operations of each type
merged to index pages */
Atomic_counter<ulint> n_discarded_ops[IBUF_OP_COUNT];
/*!< number of operations of each type
discarded without merging due to the
tablespace being deleted or the
index being dropped */
};
/** The insert buffer control structure */
extern ibuf_t ibuf;
@@ -339,9 +369,9 @@ void ibuf_delete_for_discarded_space(uint32_t space);
/** Contract the change buffer by reading pages to the buffer pool.
@return a lower limit for the combined size in bytes of entries which
will be merged from ibuf trees to the pages read, 0 if ibuf is
empty */
ulint ibuf_merge_all();
will be merged from ibuf trees to the pages read
@retval 0 if ibuf.empty */
ulint ibuf_contract();
/** Contracts insert buffer trees by reading pages referring to space_id
to the buffer pool.

View File

@@ -65,37 +65,6 @@ ibuf_mtr_commit(
mtr_commit(mtr);
}
/** Insert buffer struct */
struct ibuf_t{
ulint size; /*!< current size of the ibuf index
tree, in pages */
ulint max_size; /*!< recommended maximum size of the
ibuf index tree, in pages */
ulint seg_size; /*!< allocated pages of the file
segment containing ibuf header and
tree */
bool empty; /*!< Protected by the page
latch of the root page of the
insert buffer tree
(FSP_IBUF_TREE_ROOT_PAGE_NO). true
if and only if the insert
buffer tree is empty. */
ulint free_list_len; /*!< length of the free list */
ulint height; /*!< tree height */
dict_index_t* index; /*!< insert buffer index */
/** number of pages merged */
Atomic_counter<ulint> n_merges;
Atomic_counter<ulint> n_merged_ops[IBUF_OP_COUNT];
/*!< number of operations of each type
merged to index pages */
Atomic_counter<ulint> n_discarded_ops[IBUF_OP_COUNT];
/*!< number of operations of each type
discarded without merging due to the
tablespace being deleted or the
index being dropped */
};
/************************************************************************//**
Sets the free bit of the page in the ibuf bitmap. This is done in a separate
mini-transaction, hence this operation does not restrict further work to only

View File

@@ -1,31 +0,0 @@
/*****************************************************************************
Copyright (c) 1997, 2009, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
*****************************************************************************/
/**************************************************//**
@file include/ibuf0types.h
Insert buffer global types
Created 7/29/1997 Heikki Tuuri
*******************************************************/
#ifndef ibuf0types_h
#define ibuf0types_h
struct ibuf_t;
#endif

View File

@@ -214,6 +214,11 @@ public:
/** number of std::swap(buf, flush_buf) and writes from buf to log;
protected by latch.wr_lock() */
ulint write_to_log;
/** Log sequence number when a log file overwrite (broken crash recovery)
was noticed. Protected by latch.wr_lock(). */
lsn_t overwrite_warned;
/** innodb_log_buffer_size (size of buf and flush_buf, in bytes) */
size_t buf_size;

View File

@@ -28,6 +28,8 @@ Created 11/26/1995 Heikki Tuuri
#include "fil0fil.h"
#include "dyn0buf.h"
#include "buf0buf.h"
#include <vector>
/** Start a mini-transaction. */
#define mtr_start(m) (m)->start()
@@ -48,11 +50,6 @@ savepoint. */
@return old mode */
#define mtr_set_log_mode(m, d) (m)->set_log_mode((d))
/** Release an object in the memo stack.
@return true if released */
#define mtr_memo_release(m, o, t) \
(m)->memo_release((o), (t))
#ifdef UNIV_PFS_RWLOCK
# define mtr_s_lock_index(i,m) (m)->s_lock(__FILE__, __LINE__, &(i)->lock)
# define mtr_x_lock_index(i,m) (m)->x_lock(__FILE__, __LINE__, &(i)->lock)
@@ -66,19 +63,16 @@ savepoint. */
#define mtr_release_block_at_savepoint(m, s, b) \
(m)->release_block_at_savepoint((s), (b))
#define mtr_block_sx_latch_at_savepoint(m, s, b) \
(m)->sx_latch_at_savepoint((s), (b))
#define mtr_block_x_latch_at_savepoint(m, s, b) \
(m)->x_latch_at_savepoint((s), (b))
/** Mini-transaction memo stack slot. */
struct mtr_memo_slot_t {
/** pointer to the object */
void* object;
struct mtr_memo_slot_t
{
/** pointer to the object, or nullptr if released */
void *object;
/** type of the stored object */
mtr_memo_type_t type;
/** Release the object */
void release() const;
};
/** Mini-transaction handle and buffer */
@@ -89,14 +83,19 @@ struct mtr_t {
/** Commit the mini-transaction. */
void commit();
/** Release latches till savepoint. To simplify the code only
MTR_MEMO_S_LOCK and MTR_MEMO_PAGE_S_FIX slot types are allowed to be
released, otherwise it would be neccesary to add one more argument in the
function to point out what slot types are allowed for rollback, and this
would be overengineering as currently the function is used only in one place
in the code.
@param savepoint savepoint, can be obtained with get_savepoint */
void rollback_to_savepoint(ulint savepoint);
/** Release latches of unmodified buffer pages.
@param begin first slot to release
@param end last slot to release, or get_savepoint() */
void rollback_to_savepoint(ulint begin, ulint end);
/** Release latches of unmodified buffer pages.
@param begin first slot to release */
void rollback_to_savepoint(ulint begin)
{ rollback_to_savepoint(begin, m_memo->size()); }
/** Release the last acquired buffer page latch. */
void release_last_page()
{ auto s= m_memo->size(); rollback_to_savepoint(s - 1, s); }
/** Commit a mini-transaction that is shrinking a tablespace.
@param space tablespace that is being shrunk */
@@ -118,26 +117,89 @@ struct mtr_t {
lsn_t commit_files(lsn_t checkpoint_lsn= 0);
/** @return mini-transaction savepoint (current size of m_memo) */
ulint get_savepoint() const { ut_ad(is_active()); return m_memo.size(); }
/** Release the (index tree) s-latch stored in an mtr memo after a
savepoint.
@param savepoint value returned by @see set_savepoint.
@param lock latch to release */
inline void release_s_latch_at_savepoint(
ulint savepoint,
index_lock* lock);
ulint get_savepoint() const
{
ut_ad(is_active());
return m_memo ? m_memo->size() : 0;
}
/** Release the (index tree) s-latch stored in an mtr memo after a savepoint.
@param savepoint value returned by get_savepoint()
@param lock index latch to release */
void release_s_latch_at_savepoint(ulint savepoint, index_lock *lock)
{
ut_ad(is_active());
mtr_memo_slot_t &slot= m_memo->at(savepoint);
ut_ad(slot.object == lock);
ut_ad(slot.type == MTR_MEMO_S_LOCK);
slot.object= nullptr;
lock->s_unlock();
}
/** Release the block in an mtr memo after a savepoint. */
inline void release_block_at_savepoint(
ulint savepoint,
buf_block_t* block);
void release_block_at_savepoint(ulint savepoint, buf_block_t *block)
{
ut_ad(is_active());
mtr_memo_slot_t &slot= m_memo->at(savepoint);
ut_ad(slot.object == block);
ut_ad(!(slot.type & MTR_MEMO_MODIFY));
slot.object= nullptr;
block->page.unfix();
/** SX-latch a not yet latched block after a savepoint. */
inline void sx_latch_at_savepoint(ulint savepoint, buf_block_t* block);
switch (slot.type) {
case MTR_MEMO_PAGE_S_FIX:
block->page.lock.s_unlock();
break;
case MTR_MEMO_PAGE_SX_FIX:
case MTR_MEMO_PAGE_X_FIX:
block->page.lock.u_or_x_unlock(slot.type == MTR_MEMO_PAGE_SX_FIX);
break;
default:
break;
}
}
/** @return if we are about to make a clean buffer block dirty */
static bool is_block_dirtied(const buf_page_t &b)
{
ut_ad(b.in_file());
ut_ad(b.frame);
ut_ad(b.buf_fix_count());
return b.oldest_modification() <= 1 && b.id().space() < SRV_TMP_SPACE_ID;
}
/** X-latch a not yet latched block after a savepoint. */
inline void x_latch_at_savepoint(ulint savepoint, buf_block_t* block);
void x_latch_at_savepoint(ulint savepoint, buf_block_t *block)
{
ut_ad(is_active());
ut_ad(!memo_contains_flagged(block, MTR_MEMO_PAGE_S_FIX |
MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
mtr_memo_slot_t &slot= m_memo->at(savepoint);
ut_ad(slot.object == block);
ut_ad(slot.type == MTR_MEMO_BUF_FIX);
slot.type= MTR_MEMO_PAGE_X_FIX;
block->page.lock.x_lock();
ut_ad(!block->page.is_io_fixed());
if (!m_made_dirty)
m_made_dirty= is_block_dirtied(block->page);
}
/** U-latch a not yet latched block after a savepoint. */
void sx_latch_at_savepoint(ulint savepoint, buf_block_t *block)
{
ut_ad(is_active());
ut_ad(!memo_contains_flagged(block, MTR_MEMO_PAGE_S_FIX |
MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
mtr_memo_slot_t &slot= m_memo->at(savepoint);
ut_ad(slot.object == block);
ut_ad(slot.type == MTR_MEMO_BUF_FIX);
slot.type= MTR_MEMO_PAGE_SX_FIX;
block->page.lock.u_lock();
ut_ad(!block->page.is_io_fixed());
if (!m_made_dirty)
m_made_dirty= is_block_dirtied(block->page);
}
/** @return the logging mode */
mtr_log_t get_log_mode() const
@@ -291,19 +353,17 @@ struct mtr_t {
/** Acquire an exclusive tablespace latch.
@param space tablespace */
void x_lock_space(fil_space_t *space);
/** Release an object in the memo stack.
@param object object
@param type object type
@return bool if lock released */
bool memo_release(const void *object, ulint type);
/** Release a page latch.
@param[in] ptr pointer to within a page frame
@param[in] type object type: MTR_MEMO_PAGE_X_FIX, ... */
void release_page(const void *ptr, mtr_memo_type_t type);
/** Release an index latch. */
void release(const index_lock &lock) { release(&lock); }
/** Release a latch to an unmodified page. */
void release(const buf_block_t &block) { release(&block); }
/** Note that the mini-transaction will modify data. */
void flag_modified() { m_modifications = true; }
private:
/** Release an unmodified object. */
void release(const void *object);
/** Mark the given latched page as modified.
@param block page that will be modified */
void modify(const buf_block_t& block);
@@ -338,73 +398,93 @@ public:
@param rw_latch RW_S_LATCH, RW_SX_LATCH, RW_X_LATCH, RW_NO_LATCH */
void page_lock(buf_block_t *block, ulint rw_latch);
/** Acquire a latch on a buffer-fixed buffer pool block.
@param savepoint savepoint location of the buffer-fixed block
@param rw_latch latch to acquire */
void upgrade_buffer_fix(ulint savepoint, rw_lock_type_t rw_latch);
/** Register a page latch on a buffer-fixed block was buffer-fixed.
@param latch latch type */
void u_lock_register(ulint savepoint)
{
mtr_memo_slot_t *slot= m_memo.at<mtr_memo_slot_t*>(savepoint);
ut_ad(slot->type == MTR_MEMO_BUF_FIX);
slot->type= MTR_MEMO_PAGE_SX_FIX;
mtr_memo_slot_t &slot= m_memo->at(savepoint);
ut_ad(slot.type == MTR_MEMO_BUF_FIX);
slot.type= MTR_MEMO_PAGE_SX_FIX;
}
/** Register a page latch on a buffer-fixed block was buffer-fixed.
@param latch latch type */
void s_lock_register(ulint savepoint)
{
mtr_memo_slot_t &slot= m_memo->at(savepoint);
ut_ad(slot.type == MTR_MEMO_BUF_FIX);
slot.type= MTR_MEMO_PAGE_S_FIX;
}
/** Upgrade U locks on a block to X */
void page_lock_upgrade(const buf_block_t &block);
/** Upgrade X lock to X */
/** Upgrade U lock to X */
void lock_upgrade(const index_lock &lock);
/** Check if we are holding tablespace latch
@param space tablespace to search for
@param shared whether to look for shared latch, instead of exclusive
@return whether space.latch is being held */
bool memo_contains(const fil_space_t& space, bool shared= false)
bool memo_contains(const fil_space_t& space, bool shared= false) const
MY_ATTRIBUTE((warn_unused_result));
#ifdef UNIV_DEBUG
/** Check if we are holding an rw-latch in this mini-transaction
@param lock latch to search for
@param type held latch type
@return whether (lock,type) is contained */
bool memo_contains(const index_lock &lock, mtr_memo_type_t type)
bool memo_contains(const index_lock &lock, mtr_memo_type_t type) const
MY_ATTRIBUTE((warn_unused_result));
/** Check if memo contains the given item.
/** Check if memo contains an index or buffer block latch.
@param object object to search
@param flags specify types of object (can be ORred) of
MTR_MEMO_PAGE_S_FIX ... values
@param flags specify types of object latches
@return true if contains */
bool memo_contains_flagged(const void* ptr, ulint flags) const;
bool memo_contains_flagged(const void *object, ulint flags) const
MY_ATTRIBUTE((warn_unused_result, nonnull));
/** Check if memo contains the given page.
@param[in] ptr pointer to within buffer frame
@param[in] flags specify types of object with OR of
MTR_MEMO_PAGE_S_FIX... values
@param ptr pointer to within page frame
@param flags types latch to look for
@return the block
@retval NULL if not found */
buf_block_t* memo_contains_page_flagged(
const byte* ptr,
ulint flags) const;
@retval nullptr if not found */
buf_block_t *memo_contains_page_flagged(const byte *ptr, ulint flags) const;
/** @return true if mini-transaction contains modifications. */
bool has_modifications() const { return m_modifications; }
#endif /* UNIV_DEBUG */
/** @return true if a record was added to the mini-transaction */
bool is_dirty() const { return m_made_dirty; }
/** Push an object to an mtr memo stack.
@param object object
@param type object type: MTR_MEMO_S_LOCK, ... */
inline void memo_push(void* object, mtr_memo_type_t type);
void memo_push(void *object, mtr_memo_type_t type) __attribute__((nonnull))
{
ut_ad(is_active());
/* If this mtr has U or X latched a clean page then we set
the m_made_dirty flag. This tells us if we need to
grab log_sys.flush_order_mutex at mtr_t::commit() so that we
can insert the dirtied page into the buf_pool.flush_list.
/** Check if this mini-transaction is dirtying a clean page.
@param block block being x-fixed
@return true if the mtr is dirtying a clean page. */
static inline bool is_block_dirtied(const buf_block_t* block)
MY_ATTRIBUTE((warn_unused_result));
FIXME: Do this only when the MTR_MEMO_MODIFY flag is set! */
if (!m_made_dirty &&
(type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)))
m_made_dirty=
is_block_dirtied(*static_cast<const buf_page_t*>(object));
if (!m_memo)
m_memo= new std::vector<mtr_memo_slot_t>(1, {object, type});
else
m_memo->emplace_back(mtr_memo_slot_t{object, type});
}
/** @return the size of the log is empty */
size_t get_log_size() const { return m_log.size(); }
/** @return whether the log and memo are empty */
bool is_empty() const { return m_memo.size() == 0 && m_log.size() == 0; }
bool is_empty() const { return !get_savepoint() && !get_log_size(); }
/** Write an OPT_PAGE_CHECKSUM record. */
inline void page_checksum(const buf_page_t &bpage);
@@ -670,6 +750,8 @@ private:
@return {start_lsn,flush_ahead} */
std::pair<lsn_t,page_flush_ahead> finish_write(size_t len);
/** Release all latches. */
void release();
/** Release the resources */
inline void release_resources();
@@ -727,7 +809,7 @@ private:
#endif /* UNIV_DEBUG */
/** acquired dict_index_t::lock, fil_space_t::latch, buf_block_t */
mtr_buf_t m_memo;
std::vector<mtr_memo_slot_t> *m_memo= nullptr;
/** mini-transaction log */
mtr_buf_t m_log;
@@ -743,5 +825,3 @@ private:
/** set of freed page ids */
range_set *m_freed_pages= nullptr;
};
#include "mtr0mtr.inl"

View File

@@ -1,179 +0,0 @@
/*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2022, MariaDB Corporation.
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
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
*****************************************************************************/
/**************************************************//**
@file include/mtr0mtr.ic
Mini-transaction buffer
Created 11/26/1995 Heikki Tuuri
*******************************************************/
#include "buf0buf.h"
/** Check if a mini-transaction is dirtying a clean page.
@return true if the mtr is dirtying a clean page. */
inline bool mtr_t::is_block_dirtied(const buf_block_t *block)
{
ut_ad(block->page.in_file());
ut_ad(block->page.frame);
ut_ad(block->page.buf_fix_count());
return block->page.oldest_modification() <= 1 &&
block->page.id().space() < SRV_TMP_SPACE_ID;
}
/**
Pushes an object to an mtr memo stack. */
void
mtr_t::memo_push(void* object, mtr_memo_type_t type)
{
ut_ad(is_active());
ut_ad(object != NULL);
ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
ut_ad(type <= MTR_MEMO_SPACE_S_LOCK);
ut_ad(type == MTR_MEMO_PAGE_X_MODIFY || ut_is_2pow(type));
/* If this mtr has U or X latched a clean page then we set
the m_made_dirty flag. This tells us if we need to
grab log_sys.flush_order_mutex at mtr_t::commit() so that we
can insert the dirtied page into the buf_pool.flush_list. */
if (!m_made_dirty
&& (type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX))) {
m_made_dirty = is_block_dirtied(
reinterpret_cast<const buf_block_t*>(object));
}
mtr_memo_slot_t* slot = m_memo.push<mtr_memo_slot_t*>(sizeof(*slot));
slot->type = type;
slot->object = object;
}
/**
Releases the (index tree) s-latch stored in an mtr memo after a
savepoint. */
void
mtr_t::release_s_latch_at_savepoint(
ulint savepoint,
index_lock* lock)
{
ut_ad(is_active());
ut_ad(m_memo.size() > savepoint);
mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
ut_ad(slot->object == lock);
ut_ad(slot->type == MTR_MEMO_S_LOCK);
lock->s_unlock();
slot->object = NULL;
}
/**
SX-latches the not yet latched block after a savepoint. */
void
mtr_t::sx_latch_at_savepoint(
ulint savepoint,
buf_block_t* block)
{
ut_ad(is_active());
ut_ad(m_memo.size() > savepoint);
ut_ad(!memo_contains_flagged(
block,
MTR_MEMO_PAGE_S_FIX
| MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX));
mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
ut_ad(slot->object == block);
ut_ad(slot->type == MTR_MEMO_BUF_FIX); /* == RW_NO_LATCH */
slot->type = MTR_MEMO_PAGE_SX_FIX;
block->page.lock.u_lock();
ut_ad(!block->page.is_io_fixed());
if (!m_made_dirty) {
m_made_dirty = is_block_dirtied(block);
}
}
/**
X-latches the not yet latched block after a savepoint. */
void
mtr_t::x_latch_at_savepoint(
ulint savepoint,
buf_block_t* block)
{
ut_ad(is_active());
ut_ad(m_memo.size() > savepoint);
ut_ad(!memo_contains_flagged(
block,
MTR_MEMO_PAGE_S_FIX
| MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX));
mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
ut_ad(slot->object == block);
ut_ad(slot->type == MTR_MEMO_BUF_FIX); /* == RW_NO_LATCH */
slot->type = MTR_MEMO_PAGE_X_FIX;
block->page.lock.x_lock();
ut_ad(!block->page.is_io_fixed());
if (!m_made_dirty) {
m_made_dirty = is_block_dirtied(block);
}
}
/**
Releases the block in an mtr memo after a savepoint. */
void
mtr_t::release_block_at_savepoint(
ulint savepoint,
buf_block_t* block)
{
ut_ad(is_active());
mtr_memo_slot_t *slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
ut_a(slot->object == block);
slot->object= nullptr;
block->page.unfix();
switch (slot->type) {
case MTR_MEMO_PAGE_S_FIX:
block->page.lock.s_unlock();
break;
case MTR_MEMO_PAGE_SX_FIX:
case MTR_MEMO_PAGE_X_FIX:
block->page.lock.u_or_x_unlock(slot->type == MTR_MEMO_PAGE_SX_FIX);
break;
default:
break;
}
}

View File

@@ -129,7 +129,6 @@ page_cur_tuple_insert(
/*==================*/
page_cur_t* cursor, /*!< in/out: a page cursor */
const dtuple_t* tuple, /*!< in: pointer to a data tuple */
dict_index_t* index, /*!< in: record descriptor */
rec_offs** offsets,/*!< out: offsets on *rec */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
ulint n_ext, /*!< in: number of externally stored columns */
@@ -143,7 +142,6 @@ rec_t*
page_cur_insert_rec_low(
/*====================*/
const page_cur_t*cur, /*!< in: page cursor */
dict_index_t* index, /*!< in: record descriptor */
const rec_t* rec, /*!< in: record to insert after cur */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -165,7 +163,6 @@ page_cur_insert_rec_zip(
/*====================*/
page_cur_t* cursor, /*!< in/out: page cursor,
logical position unchanged */
dict_index_t* index, /*!< in: record descriptor */
const rec_t* rec, /*!< in: pointer to a physical record */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -177,7 +174,6 @@ void
page_cur_delete_rec(
/*================*/
page_cur_t* cursor, /*!< in/out: a page cursor */
const dict_index_t* index, /*!< in: record descriptor */
const rec_offs* offsets,/*!< in: rec_get_offsets(
cursor->rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -239,8 +235,6 @@ Searches the right position for a page cursor. */
bool
page_cur_search_with_match(
/*=======================*/
const buf_block_t* block, /*!< in: buffer block */
const dict_index_t* index, /*!< in: record descriptor */
const dtuple_t* tuple, /*!< in: data tuple */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L,
PAGE_CUR_LE, PAGE_CUR_G, or
@@ -251,13 +245,11 @@ page_cur_search_with_match(
ulint* ilow_matched_fields,
/*!< in/out: already matched
fields in lower limit record */
page_cur_t* cursor, /*!< out: page cursor */
page_cur_t* cursor, /*!< in/out: page cursor */
rtr_info_t* rtr_info);/*!< in/out: rtree search stack */
#ifdef BTR_CUR_HASH_ADAPT
MY_ATTRIBUTE((warn_unused_result))
/** Search the right position for a page cursor.
@param[in] block buffer block
@param[in] index index tree
@param[in] tuple key to be searched for
@param[in] mode search mode
@param[in,out] iup_matched_fields already matched fields in the
@@ -268,11 +260,9 @@ first partially matched field in the upper limit record
lower limit record
@param[in,out] ilow_matched_bytes already matched bytes in the
first partially matched field in the lower limit record
@param[out] cursor page cursor */
@param[in,out] cursor page cursor */
bool
page_cur_search_with_match_bytes(
const buf_block_t* block,
const dict_index_t* index,
const dtuple_t* tuple,
page_cur_mode_t mode,
ulint* iup_matched_fields,
@@ -284,16 +274,12 @@ page_cur_search_with_match_bytes(
/***********************************************************//**
Positions a page cursor on a randomly chosen user record on a page. If there
are no user records, sets the cursor on the infimum record. */
void
page_cur_open_on_rnd_user_rec(
/*==========================*/
buf_block_t* block, /*!< in: page */
page_cur_t* cursor);/*!< out: page cursor */
void page_cur_open_on_rnd_user_rec(page_cur_t *cursor);
/** Index page cursor */
struct page_cur_t{
const dict_index_t* index;
dict_index_t* index;
rec_t* rec; /*!< pointer to a record on page */
rec_offs* offsets;
buf_block_t* block; /*!< pointer to the block containing rec */

View File

@@ -167,14 +167,12 @@ page_cur_tuple_insert(
/*==================*/
page_cur_t* cursor, /*!< in/out: a page cursor */
const dtuple_t* tuple, /*!< in: pointer to a data tuple */
dict_index_t* index, /*!< in: record descriptor */
rec_offs** offsets,/*!< out: offsets on *rec */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
ulint n_ext, /*!< in: number of externally stored columns */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
rec_t* rec;
ulint size = rec_get_converted_size(index, tuple, n_ext);
ulint size = rec_get_converted_size(cursor->index, tuple, n_ext);
if (!*heap) {
*heap = mem_heap_create(size
@@ -183,24 +181,23 @@ page_cur_tuple_insert(
* sizeof **offsets);
}
rec = rec_convert_dtuple_to_rec((byte*) mem_heap_alloc(*heap, size),
index, tuple, n_ext);
rec_t* rec = rec_convert_dtuple_to_rec(
static_cast<byte*>(mem_heap_alloc(*heap, size)),
cursor->index, tuple, n_ext);
*offsets = rec_get_offsets(rec, index, *offsets,
*offsets = rec_get_offsets(rec, cursor->index, *offsets,
page_is_leaf(cursor->block->page.frame)
? index->n_core_fields : 0,
? cursor->index->n_core_fields : 0,
ULINT_UNDEFINED, heap);
ut_ad(size == rec_offs_size(*offsets));
if (is_buf_block_get_page_zip(cursor->block)) {
rec = page_cur_insert_rec_zip(
cursor, index, rec, *offsets, mtr);
rec = page_cur_insert_rec_zip(cursor, rec, *offsets, mtr);
} else {
rec = page_cur_insert_rec_low(cursor,
index, rec, *offsets, mtr);
rec = page_cur_insert_rec_low(cursor, rec, *offsets, mtr);
}
ut_ad(!rec || !cmp_dtuple_rec(tuple, rec, index, *offsets));
ut_ad(!rec || !cmp_dtuple_rec(tuple, rec, cursor->index, *offsets));
return(rec);
}

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, 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
the terms of the GNU General Public License as published by the Free Software
@@ -78,7 +78,7 @@ dberr_t
row_ins_clust_index_entry_low(
/*==========================*/
ulint flags, /*!< in: undo logging and locking flags */
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
depending on whether we wish optimistic or
pessimistic descent down the index tree */
dict_index_t* index, /*!< in: clustered index */
@@ -94,13 +94,13 @@ same fields is found, the other record is necessarily marked deleted.
It is then unmarked. Otherwise, the entry is just inserted to the index.
@retval DB_SUCCESS on success
@retval DB_LOCK_WAIT on lock wait when !(flags & BTR_NO_LOCKING_FLAG)
@retval DB_FAIL if retry with BTR_MODIFY_TREE is needed
@retval DB_FAIL if retry with BTR_INSERT_TREE is needed
@return error code */
dberr_t
row_ins_sec_index_entry_low(
/*========================*/
ulint flags, /*!< in: undo logging and locking flags */
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE,
depending on whether we wish optimistic or
pessimistic descent down the index tree */
dict_index_t* index, /*!< in: secondary index */

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, 2020, MariaDB Corporation.
Copyright (c) 2016, 2022, MariaDB Corporation.
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
@@ -303,13 +303,13 @@ row_build_row_ref_fast(
/***************************************************************//**
Searches the clustered index record for a row, if we have the row
reference.
@return TRUE if found */
ibool
@return true if found */
bool
row_search_on_row_ref(
/*==================*/
btr_pcur_t* pcur, /*!< out: persistent cursor, which must
be closed by the caller */
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
const dict_table_t* table, /*!< in: table */
const dtuple_t* ref, /*!< in: row reference */
mtr_t* mtr) /*!< in/out: mtr */
@@ -321,7 +321,7 @@ on the secondary index record are preserved.
rec_t*
row_get_clust_rec(
/*==============*/
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
const rec_t* rec, /*!< in: record in a secondary index */
dict_index_t* index, /*!< in: secondary index */
dict_index_t** clust_index,/*!< out: clustered index */
@@ -363,9 +363,8 @@ Searches an index record.
enum row_search_result
row_search_index_entry(
/*===================*/
dict_index_t* index, /*!< in: index */
const dtuple_t* entry, /*!< in: index entry */
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must
be closed by the caller */
mtr_t* mtr) /*!< in: mtr */

View File

@@ -812,10 +812,14 @@ func_exit:
if (lsn <= sync_lsn)
{
#ifndef DBUG_OFF
skip_checkpoint:
#endif
log_sys.set_check_flush_or_checkpoint(false);
goto func_exit;
}
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", goto skip_checkpoint;);
log_sys.latch.rd_unlock();
/* We must wait to prevent the tail of the log overwriting the head. */
@@ -912,13 +916,9 @@ loop:
}
/* We need these threads to stop early in shutdown. */
const char* thread_name;
if (srv_fast_shutdown != 2 && trx_rollback_is_active) {
thread_name = "rollback of recovered transactions";
} else {
thread_name = NULL;
}
const char* thread_name = srv_fast_shutdown != 2
&& trx_rollback_is_active
? "rollback of recovered transactions" : nullptr;
if (thread_name) {
ut_ad(!srv_read_only_mode);

View File

@@ -1148,6 +1148,7 @@ public:
}
mtr.commit();
clear();
}
/** Clear the data structure */
@@ -1174,14 +1175,6 @@ inline void recv_sys_t::trim(const page_id_t page_id, lsn_t lsn)
pages.erase(r);
}
}
if (fil_space_t* space = fil_space_get(page_id.space())) {
ut_ad(UT_LIST_GET_LEN(space->chain) == 1);
fil_node_t* file = UT_LIST_GET_FIRST(space->chain);
ut_ad(file->is_open());
os_file_truncate(file->name, file->handle,
os_offset_t{page_id.page_no()}
<< srv_page_size_shift, true);
}
DBUG_VOID_RETURN;
}
@@ -3485,7 +3478,17 @@ void recv_sys_t::apply(bool last_batch)
{
const trunc& t= truncated_undo_spaces[id];
if (t.lsn)
trim(page_id_t(id + srv_undo_space_id_start, t.pages), t.lsn);
{
trim(page_id_t(id + srv_undo_space_id_start, 0), t.lsn);
if (fil_space_t *space = fil_space_get(id + srv_undo_space_id_start))
{
ut_ad(UT_LIST_GET_LEN(space->chain) == 1);
fil_node_t *file= UT_LIST_GET_FIRST(space->chain);
ut_ad(file->is_open());
os_file_truncate(file->name, file->handle,
os_offset_t{t.pages} << srv_page_size_shift, true);
}
}
}
fil_system.extend_to_recv_size();

File diff suppressed because it is too large Load Diff

View File

@@ -277,8 +277,6 @@ Searches the right position for a page cursor. */
bool
page_cur_search_with_match(
/*=======================*/
const buf_block_t* block, /*!< in: buffer block */
const dict_index_t* index, /*!< in/out: record descriptor */
const dtuple_t* tuple, /*!< in: data tuple */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L,
PAGE_CUR_LE, PAGE_CUR_G, or
@@ -303,6 +301,8 @@ page_cur_search_with_match(
ulint low_matched_fields;
ulint cur_matched_fields;
int cmp;
const dict_index_t* const index = cursor->index;
const buf_block_t* const block = cursor->block;
#ifdef UNIV_ZIP_DEBUG
const page_zip_des_t* page_zip = buf_block_get_page_zip(block);
#endif /* UNIV_ZIP_DEBUG */
@@ -552,8 +552,6 @@ first partially matched field in the lower limit record
@param[out] cursor page cursor */
bool
page_cur_search_with_match_bytes(
const buf_block_t* block,
const dict_index_t* index,
const dtuple_t* tuple,
page_cur_mode_t mode,
ulint* iup_matched_fields,
@@ -575,6 +573,8 @@ page_cur_search_with_match_bytes(
ulint cur_matched_fields;
ulint cur_matched_bytes;
int cmp;
const dict_index_t* const index = cursor->index;
const buf_block_t* const block = cursor->block;
#ifdef UNIV_ZIP_DEBUG
const page_zip_des_t* page_zip = buf_block_get_page_zip(block);
#endif /* UNIV_ZIP_DEBUG */
@@ -802,18 +802,13 @@ up_rec_match:
/***********************************************************//**
Positions a page cursor on a randomly chosen user record on a page. If there
are no user records, sets the cursor on the infimum record. */
void
page_cur_open_on_rnd_user_rec(
/*==========================*/
buf_block_t* block, /*!< in: page */
page_cur_t* cursor) /*!< out: page cursor */
void page_cur_open_on_rnd_user_rec(page_cur_t *cursor)
{
cursor->block= block;
if (const ulint n_recs= page_get_n_recs(block->page.frame))
if ((cursor->rec= page_rec_get_nth(block->page.frame,
if (const ulint n_recs= page_get_n_recs(cursor->block->page.frame))
if ((cursor->rec= page_rec_get_nth(cursor->block->page.frame,
ut_rnd_interval(n_recs) + 1)))
return;
cursor->rec= page_get_infimum_rec(block->page.frame);
cursor->rec= page_get_infimum_rec(cursor->block->page.frame);
}
/**
@@ -1361,12 +1356,12 @@ rec_t*
page_cur_insert_rec_low(
/*====================*/
const page_cur_t*cur, /*!< in: page cursor */
dict_index_t* index, /*!< in: record descriptor */
const rec_t* rec, /*!< in: record to insert after cur */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
buf_block_t* block= cur->block;
buf_block_t *block= cur->block;
dict_index_t * const index= cur->index;
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(rec_offs_n_fields(offsets) > 0);
@@ -1786,13 +1781,13 @@ page_cur_insert_rec_zip(
/*====================*/
page_cur_t* cursor, /*!< in/out: page cursor,
logical position unchanged */
dict_index_t* index, /*!< in: record descriptor */
const rec_t* rec, /*!< in: pointer to a physical record */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
page_zip_des_t * const page_zip= page_cur_get_page_zip(cursor);
page_t * const page= cursor->block->page.frame;
dict_index_t * const index = cursor->index;
ut_ad(page_zip);
ut_ad(rec_offs_validate(rec, index, offsets));
@@ -1894,8 +1889,7 @@ page_cur_insert_rec_zip(
/* Try compressing the whole page afterwards. */
const mtr_log_t log_mode= mtr->set_log_mode(MTR_LOG_NONE);
rec_t *insert_rec= page_cur_insert_rec_low(cursor, index, rec, offsets,
mtr);
rec_t *insert_rec= page_cur_insert_rec_low(cursor, rec, offsets, mtr);
mtr->set_log_mode(log_mode);
if (insert_rec)
@@ -2243,7 +2237,6 @@ void
page_cur_delete_rec(
/*================*/
page_cur_t* cursor, /*!< in/out: a page cursor */
const dict_index_t* index, /*!< in: record descriptor */
const rec_offs* offsets,/*!< in: rec_get_offsets(
cursor->rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -2265,6 +2258,7 @@ page_cur_delete_rec(
in the smallest user record, it cannot be used here either. */
current_rec = cursor->rec;
const dict_index_t* const index = cursor->index;
buf_block_t* const block = cursor->block;
ut_ad(rec_offs_validate(current_rec, index, offsets));
ut_ad(!!page_is_comp(block->page.frame)

View File

@@ -458,6 +458,7 @@ page_copy_rec_list_end_no_locks(
rec_offs* offsets = offsets_;
rec_offs_init(offsets_);
cur1.index = cur2.index = index;
page_cur_position(rec, block, &cur1);
if (page_cur_is_before_first(&cur1) && !page_cur_move_to_next(&cur1)) {
@@ -483,8 +484,8 @@ page_copy_rec_list_end_no_locks(
rec_t* ins_rec;
offsets = rec_get_offsets(cur1.rec, index, offsets, n_core,
ULINT_UNDEFINED, &heap);
ins_rec = page_cur_insert_rec_low(&cur2, index,
cur1.rec, offsets, mtr);
ins_rec = page_cur_insert_rec_low(&cur2, cur1.rec, offsets,
mtr);
if (UNIV_UNLIKELY(!ins_rec || !page_cur_move_to_next(&cur1))) {
err = DB_CORRUPTION;
break;
@@ -733,6 +734,7 @@ corrupted:
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
}
cur2.index = index;
page_cur_position(ret, new_block, &cur2);
const ulint n_core = page_rec_is_leaf(rec) ? index->n_core_fields : 0;
@@ -763,9 +765,8 @@ corrupted:
offsets = rec_get_offsets(cur1.rec, index, offsets,
n_core,
ULINT_UNDEFINED, &heap);
cur2.rec = page_cur_insert_rec_low(&cur2, index,
cur1.rec, offsets,
mtr);
cur2.rec = page_cur_insert_rec_low(&cur2, cur1.rec,
offsets, mtr);
if (UNIV_UNLIKELY(!cur2.rec
|| !page_cur_move_to_next(&cur1))) {
*err = DB_CORRUPTION;
@@ -931,13 +932,14 @@ page_delete_rec_list_end(
{
page_cur_t cur;
page_cur_position(rec, block, &cur);
cur.index= index;
offsets= rec_get_offsets(rec, index, offsets, n_core,
ULINT_UNDEFINED, &heap);
rec= const_cast<rec_t*>(page_rec_get_next_low(rec, true));
#ifdef UNIV_ZIP_DEBUG
ut_a(page_zip_validate(&block->page.zip, page, index));
#endif /* UNIV_ZIP_DEBUG */
page_cur_delete_rec(&cur, index, offsets, mtr);
page_cur_delete_rec(&cur, offsets, mtr);
}
while (page_offset(rec) != PAGE_NEW_SUPREMUM);
@@ -1134,6 +1136,7 @@ page_delete_rec_list_start(
return;
}
cur1.index = index;
page_cur_set_before_first(block, &cur1);
if (UNIV_UNLIKELY(!page_cur_move_to_next(&cur1))) {
ut_ad("corrupted page" == 0);
@@ -1147,7 +1150,7 @@ page_delete_rec_list_start(
offsets = rec_get_offsets(page_cur_get_rec(&cur1), index,
offsets, n_core,
ULINT_UNDEFINED, &heap);
page_cur_delete_rec(&cur1, index, offsets, mtr);
page_cur_delete_rec(&cur1, offsets, mtr);
}
if (UNIV_LIKELY_NULL(heap)) {

View File

@@ -322,13 +322,9 @@ que_graph_free_recursive(
case QUE_NODE_UPDATE:
upd = static_cast<upd_node_t*>(node);
if (upd->in_mysql_interface) {
btr_pcur_free_for_mysql(upd->pcur);
upd->in_mysql_interface = false;
}
que_graph_free_recursive(upd->cascade_node);
ut_free(upd->pcur->old_rec_buf);
upd->pcur->old_rec_buf = NULL;
if (upd->cascade_heap) {
mem_heap_free(upd->cascade_heap);

View File

@@ -611,7 +611,7 @@ rec_init_offsets(
ulint i = 0;
rec_offs offs;
/* This assertion was relaxed for the btr_cur_open_at_index_side()
/* This assertion was relaxed for the btr_cur_t::open_leaf()
call in btr_cur_instant_init_low(). We cannot invoke
index->is_instant(), because the same assertion would fail there
until btr_cur_instant_init_low() has invoked
@@ -839,7 +839,7 @@ rec_get_offsets_func(
bool alter_metadata = false;
ut_ad(index->n_core_fields >= n_core);
/* This assertion was relaxed for the btr_cur_open_at_index_side()
/* This assertion was relaxed for the btr_cur_t::open_leaf()
call in btr_cur_instant_init_low(). We cannot invoke
index->is_instant(), because the same assertion would fail there
until btr_cur_instant_init_low() has invoked

View File

@@ -253,9 +253,10 @@ public:
}
/** Position the cursor on the first user record. */
rec_t* open(buf_block_t* block) noexcept
rec_t* open(buf_block_t* block, const dict_index_t* index) noexcept
MY_ATTRIBUTE((warn_unused_result))
{
m_cur.index = const_cast<dict_index_t*>(index);
page_cur_set_before_first(block, &m_cur);
return next();
}
@@ -285,10 +286,9 @@ public:
/** Remove the current record
@return true on success */
bool remove(
const dict_index_t* index,
rec_offs* offsets) UNIV_NOTHROW
bool remove(rec_offs* offsets) UNIV_NOTHROW
{
const dict_index_t* const index = m_cur.index;
ut_ad(page_is_leaf(m_cur.block->page.frame));
/* We can't end up with an empty page unless it is root. */
if (page_get_n_recs(m_cur.block->page.frame) <= 1) {
@@ -311,7 +311,7 @@ public:
page_zip, m_cur.block->page.frame, index));
#endif /* UNIV_ZIP_DEBUG */
page_cur_delete_rec(&m_cur, index, offsets, &m_mtr);
page_cur_delete_rec(&m_cur, offsets, &m_mtr);
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(
@@ -1513,8 +1513,9 @@ inline bool IndexPurge::open() noexcept
m_mtr.start();
m_mtr.set_log_mode(MTR_LOG_NO_REDO);
if (btr_pcur_open_at_index_side(true, m_index, BTR_MODIFY_LEAF,
&m_pcur, true, 0, &m_mtr) != DB_SUCCESS)
btr_pcur_init(&m_pcur);
if (m_pcur.open_leaf(true, m_index, BTR_MODIFY_LEAF, &m_mtr) != DB_SUCCESS)
return false;
rec_t *rec= page_rec_get_next(btr_pcur_get_rec(&m_pcur));
@@ -1559,7 +1560,7 @@ dberr_t IndexPurge::next() noexcept
return DB_CORRUPTION;
}
/* The following is based on btr_pcur_move_to_next_user_rec(). */
m_pcur.old_stored = false;
m_pcur.old_rec = nullptr;
ut_ad(m_pcur.latch_mode == BTR_MODIFY_LEAF);
do {
if (btr_pcur_is_after_last_on_page(&m_pcur)) {
@@ -1586,8 +1587,7 @@ tree structure may be changed during a pessimistic delete. */
inline dberr_t IndexPurge::purge_pessimistic_delete() noexcept
{
dberr_t err;
if (m_pcur.restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
&m_mtr) != btr_pcur_t::CORRUPTED)
if (m_pcur.restore_position(BTR_PURGE_TREE, &m_mtr) != btr_pcur_t::CORRUPTED)
{
ut_ad(rec_get_deleted_flag(btr_pcur_get_rec(&m_pcur),
m_index->table->not_redundant()));
@@ -1722,10 +1722,8 @@ re-organising the B+tree.
@return true if purge succeeded */
inline bool PageConverter::purge() UNIV_NOTHROW
{
const dict_index_t* index = m_index->m_srv_index;
/* We can't have a page that is empty and not root. */
if (m_rec_iter.remove(index, m_offsets)) {
if (m_rec_iter.remove(m_offsets)) {
++m_index->m_stats.m_n_purged;
@@ -1789,7 +1787,7 @@ PageConverter::update_records(
/* This will also position the cursor on the first user record. */
if (!m_rec_iter.open(block)) {
if (!m_rec_iter.open(block, m_index->m_srv_index)) {
return DB_CORRUPTION;
}
@@ -2289,8 +2287,8 @@ row_import_set_sys_max_row_id(
mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
if (btr_pcur_open_at_index_side(false, index, BTR_SEARCH_LEAF,
&pcur, true, 0, &mtr) == DB_SUCCESS) {
if (pcur.open_leaf(false, index, BTR_SEARCH_LEAF, &mtr)
== DB_SUCCESS) {
rec = btr_pcur_move_to_prev_on_page(&pcur);
if (!rec) {

View File

@@ -174,7 +174,7 @@ dberr_t
row_ins_sec_index_entry_by_modify(
/*==============================*/
ulint flags, /*!< in: undo logging and locking flags */
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE,
depending on whether mtr holds just a leaf
latch or also a tree latch */
btr_cur_t* cursor, /*!< in: B-tree cursor */
@@ -194,8 +194,8 @@ row_ins_sec_index_entry_by_modify(
rec = btr_cur_get_rec(cursor);
ut_ad(!dict_index_is_clust(cursor->index));
ut_ad(rec_offs_validate(rec, cursor->index, *offsets));
ut_ad(!cursor->index()->is_clust());
ut_ad(rec_offs_validate(rec, cursor->index(), *offsets));
ut_ad(!entry->info_bits);
/* We know that in the alphabetical ordering, entry and rec are
@@ -204,7 +204,7 @@ row_ins_sec_index_entry_by_modify(
difference. */
update = row_upd_build_sec_rec_difference_binary(
rec, cursor->index, *offsets, entry, heap);
rec, cursor->index(), *offsets, entry, heap);
if (!rec_get_deleted_flag(rec, rec_offs_comp(*offsets))) {
/* We should never insert in place of a record that
@@ -218,8 +218,8 @@ row_ins_sec_index_entry_by_modify(
returns. After that point, set_committed(true)
would be invoked in commit_inplace_alter_table(). */
ut_a(update->n_fields == 0);
ut_a(!cursor->index->is_committed());
ut_ad(!dict_index_is_online_ddl(cursor->index));
ut_a(!cursor->index()->is_committed());
ut_ad(!dict_index_is_online_ddl(cursor->index()));
return(DB_SUCCESS);
}
@@ -241,7 +241,7 @@ row_ins_sec_index_entry_by_modify(
break;
}
} else {
ut_a(mode == BTR_MODIFY_TREE);
ut_ad(mode == BTR_INSERT_TREE);
if (buf_pool.running_out()) {
return(DB_LOCK_TABLE_FULL);
@@ -288,15 +288,15 @@ row_ins_clust_index_entry_by_modify(
dberr_t err = DB_SUCCESS;
btr_cur_t* cursor = btr_pcur_get_btr_cur(pcur);
TABLE* mysql_table = NULL;
ut_ad(dict_index_is_clust(cursor->index));
ut_ad(cursor->index()->is_clust());
rec = btr_cur_get_rec(cursor);
ut_ad(rec_get_deleted_flag(rec,
dict_table_is_comp(cursor->index->table)));
cursor->index()->table->not_redundant()));
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(rec_get_trx_id(rec, cursor->index));
ut_ad(rec_get_trx_id(rec, cursor->index()));
/* Build an update vector containing all the fields to be modified;
NOTE that this vector may NOT contain system columns trx_id or
@@ -307,7 +307,7 @@ row_ins_clust_index_entry_by_modify(
}
update = row_upd_build_difference_binary(
cursor->index, entry, rec, NULL, true, true,
cursor->index(), entry, rec, NULL, true, true,
thr_get_trx(thr), heap, mysql_table, &err);
if (err != DB_SUCCESS) {
return(err);
@@ -1115,7 +1115,7 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
index = btr_pcur_get_btr_cur(pcur)->index;
index = pcur->index();
ut_a(index == foreign->foreign_index);
@@ -1138,7 +1138,9 @@ row_ins_foreign_check_on_constraint(
ref = row_build_row_ref(ROW_COPY_POINTERS, index, rec,
tmp_heap);
err = btr_pcur_open_with_no_init(clust_index, ref,
cascade->pcur->old_rec = nullptr;
cascade->pcur->btr_cur.page_cur.index = clust_index;
err = btr_pcur_open_with_no_init(ref,
PAGE_CUR_LE, BTR_SEARCH_LEAF,
cascade->pcur, mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
@@ -1622,9 +1624,9 @@ row_ins_check_foreign_constraint(
n_fields_cmp = dtuple_get_n_fields_cmp(entry);
dtuple_set_n_fields_cmp(entry, foreign->n_fields);
err = btr_pcur_open(check_index, entry, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
pcur.btr_cur.page_cur.index = check_index;
err = btr_pcur_open(entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, 0,
&mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
goto end_scan;
}
@@ -2064,9 +2066,9 @@ row_ins_scan_sec_index_for_duplicate(
dtuple_set_n_fields_cmp(entry, n_unique);
const auto allow_duplicates = thr_get_trx(thr)->duplicates;
dberr_t err = btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF,
&pcur, mtr);
pcur.btr_cur.page_cur.index = index;
dberr_t err = btr_pcur_open(entry, PAGE_CUR_GE, BTR_SEARCH_LEAF,
&pcur, 0, mtr);
if (err != DB_SUCCESS) {
goto end_scan;
}
@@ -2220,14 +2222,14 @@ row_ins_duplicate_error_in_clust_online(
dberr_t err = DB_SUCCESS;
const rec_t* rec = btr_cur_get_rec(cursor);
ut_ad(!cursor->index->is_instant());
ut_ad(!cursor->index()->is_instant());
if (cursor->low_match >= n_uniq && !page_rec_is_infimum(rec)) {
*offsets = rec_get_offsets(rec, cursor->index, *offsets,
cursor->index->n_fields,
*offsets = rec_get_offsets(rec, cursor->index(), *offsets,
cursor->index()->n_fields,
ULINT_UNDEFINED, heap);
err = row_ins_duplicate_online(n_uniq, entry,
rec, cursor->index, *offsets);
rec, cursor->index(), *offsets);
if (err != DB_SUCCESS) {
return(err);
}
@@ -2238,11 +2240,11 @@ row_ins_duplicate_error_in_clust_online(
}
if (cursor->up_match >= n_uniq && !page_rec_is_supremum(rec)) {
*offsets = rec_get_offsets(rec, cursor->index, *offsets,
cursor->index->n_fields,
*offsets = rec_get_offsets(rec, cursor->index(), *offsets,
cursor->index()->n_fields,
ULINT_UNDEFINED, heap);
err = row_ins_duplicate_online(n_uniq, entry,
rec, cursor->index, *offsets);
rec, cursor->index(), *offsets);
}
return(err);
@@ -2273,7 +2275,7 @@ row_ins_duplicate_error_in_clust(
rec_offs* offsets = offsets_;
rec_offs_init(offsets_);
ut_ad(dict_index_is_clust(cursor->index));
ut_ad(cursor->index()->is_clust());
/* NOTE: For unique non-clustered indexes there may be any number
of delete marked records with the same value for the non-clustered
@@ -2288,15 +2290,17 @@ row_ins_duplicate_error_in_clust(
user records on the leaf level. So, even if low_match would suggest
that a duplicate key violation may occur, this may not be the case. */
n_unique = dict_index_get_n_unique(cursor->index);
n_unique = dict_index_get_n_unique(cursor->index());
if (cursor->low_match >= n_unique) {
rec = btr_cur_get_rec(cursor);
if (!page_rec_is_infimum(rec)) {
offsets = rec_get_offsets(rec, cursor->index, offsets,
cursor->index->n_core_fields,
offsets = rec_get_offsets(rec, cursor->index(),
offsets,
cursor->index()
->n_core_fields,
ULINT_UNDEFINED, &heap);
/* We set a lock on the possible duplicate: this
@@ -2317,13 +2321,13 @@ row_ins_duplicate_error_in_clust(
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor),
rec, cursor->index, offsets, thr);
rec, cursor->index(), offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor), rec,
cursor->index, offsets, thr);
cursor->index(), offsets, thr);
}
switch (err) {
@@ -2335,11 +2339,11 @@ row_ins_duplicate_error_in_clust(
}
if (row_ins_dupl_error_with_rec(
rec, entry, cursor->index, offsets)) {
rec, entry, cursor->index(), offsets)) {
duplicate:
trx->error_info = cursor->index;
trx->error_info = cursor->index();
err = DB_DUPLICATE_KEY;
if (cursor->index->table->versioned()
if (cursor->index()->table->versioned()
&& entry->vers_history_row())
{
ulint trx_id_len;
@@ -2363,8 +2367,10 @@ duplicate:
rec = page_rec_get_next(btr_cur_get_rec(cursor));
if (rec && !page_rec_is_supremum(rec)) {
offsets = rec_get_offsets(rec, cursor->index, offsets,
cursor->index->n_core_fields,
offsets = rec_get_offsets(rec, cursor->index(),
offsets,
cursor->index()
->n_core_fields,
ULINT_UNDEFINED, &heap);
if (trx->duplicates) {
@@ -2377,13 +2383,13 @@ duplicate:
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor),
rec, cursor->index, offsets, thr);
rec, cursor->index(), offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor),
rec, cursor->index, offsets, thr);
rec, cursor->index(), offsets, thr);
}
switch (err) {
@@ -2394,7 +2400,7 @@ duplicate:
/* fall through */
case DB_SUCCESS:
if (row_ins_dupl_error_with_rec(
rec, entry, cursor->index,
rec, entry, cursor->index(),
offsets)) {
goto duplicate;
}
@@ -2436,7 +2442,7 @@ row_ins_must_modify_rec(
and a secondary index node pointer contains all index fields. */
return(cursor->low_match
>= dict_index_get_n_unique_in_tree(cursor->index)
>= dict_index_get_n_unique_in_tree(cursor->index())
&& !page_rec_is_infimum(btr_cur_get_rec(cursor)));
}
@@ -2465,6 +2471,7 @@ row_ins_index_entry_big_rec(
btr_pcur_t pcur;
rec_t* rec;
pcur.btr_cur.page_cur.index = index;
ut_ad(index->is_primary());
DEBUG_SYNC_C_IF_THD(thd, "before_row_ins_extern_latch");
@@ -2476,8 +2483,8 @@ row_ins_index_entry_big_rec(
index->set_modified(mtr);
}
dberr_t error = btr_pcur_open(index, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &pcur, &mtr);
dberr_t error = btr_pcur_open(entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &pcur, 0, &mtr);
if (error != DB_SUCCESS) {
return error;
}
@@ -2525,7 +2532,7 @@ dberr_t
row_ins_clust_index_entry_low(
/*==========================*/
ulint flags, /*!< in: undo logging and locking flags */
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
depending on whether we wish optimistic or
pessimistic descent down the index tree */
dict_index_t* index, /*!< in: clustered index */
@@ -2578,7 +2585,7 @@ row_ins_clust_index_entry_low(
} else {
if (mode == BTR_MODIFY_LEAF
&& dict_index_is_online_ddl(index)) {
mode = BTR_MODIFY_LEAF_ALREADY_S_LATCHED;
mode = BTR_MODIFY_LEAF_ALREADY_LATCHED;
mtr_s_lock_index(index, &mtr);
}
@@ -2603,8 +2610,8 @@ row_ins_clust_index_entry_low(
/* Note that we use PAGE_CUR_LE as the search mode, because then
the function will return in both low_match and up_match of the
cursor sensible values */
err = btr_pcur_open_low(index, 0, entry, PAGE_CUR_LE, mode, &pcur,
auto_inc, &mtr);
pcur.btr_cur.page_cur.index = index;
err = btr_pcur_open(entry, PAGE_CUR_LE, mode, &pcur, auto_inc, &mtr);
if (err != DB_SUCCESS) {
index->table->file_unreadable = true;
commit_exit:
@@ -2732,7 +2739,7 @@ skip_bulk_insert:
/* fall through */
case DB_SUCCESS_LOCKED_REC:
case DB_DUPLICATE_KEY:
trx->error_info = cursor->index;
trx->error_info = cursor->index();
}
} else {
/* Note that the following may return also
@@ -2769,8 +2776,8 @@ do_insert:
rec_t* insert_rec;
if (mode != BTR_MODIFY_TREE) {
ut_ad((mode & ulint(~BTR_ALREADY_S_LATCHED))
== BTR_MODIFY_LEAF);
ut_ad(mode == BTR_MODIFY_LEAF ||
mode == BTR_MODIFY_LEAF_ALREADY_LATCHED);
err = btr_cur_optimistic_insert(
flags, cursor, &offsets, &offsets_heap,
entry, &insert_rec, &big_rec,
@@ -2846,13 +2853,13 @@ same fields is found, the other record is necessarily marked deleted.
It is then unmarked. Otherwise, the entry is just inserted to the index.
@retval DB_SUCCESS on success
@retval DB_LOCK_WAIT on lock wait when !(flags & BTR_NO_LOCKING_FLAG)
@retval DB_FAIL if retry with BTR_MODIFY_TREE is needed
@retval DB_FAIL if retry with BTR_INSERT_TREE is needed
@return error code */
dberr_t
row_ins_sec_index_entry_low(
/*========================*/
ulint flags, /*!< in: undo logging and locking flags */
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE,
depending on whether we wish optimistic or
pessimistic descent down the index tree */
dict_index_t* index, /*!< in: secondary index */
@@ -2867,7 +2874,7 @@ row_ins_sec_index_entry_low(
DBUG_ENTER("row_ins_sec_index_entry_low");
btr_cur_t cursor;
ulint search_mode = mode;
btr_latch_mode search_mode = mode;
dberr_t err;
ulint n_unique;
mtr_t mtr;
@@ -2877,10 +2884,11 @@ row_ins_sec_index_entry_low(
rtr_info_t rtr_info;
ut_ad(!dict_index_is_clust(index));
ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_MODIFY_TREE);
ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_INSERT_TREE);
cursor.thr = thr;
cursor.rtr_info = NULL;
cursor.page_cur.index = index;
ut_ad(thr_get_trx(thr)->id != 0);
mtr.start();
@@ -2892,24 +2900,19 @@ row_ins_sec_index_entry_low(
mtr.set_log_mode(MTR_LOG_NO_REDO);
} else {
index->set_modified(mtr);
if (!dict_index_is_spatial(index)) {
search_mode |= BTR_INSERT;
}
}
/* Note that we use PAGE_CUR_LE as the search mode, because then
the function will return in both low_match and up_match of the
cursor sensible values */
if (dict_index_is_spatial(index)) {
cursor.index = index;
if (index->is_spatial()) {
rtr_init_rtr_info(&rtr_info, false, &cursor, index, false);
rtr_info_update_btr(&cursor, &rtr_info);
err = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_RTREE_INSERT,
search_mode,
&cursor, &mtr);
err = btr_cur_search_to_nth_level(0, entry,
PAGE_CUR_RTREE_INSERT,
search_mode, &cursor, &mtr);
if (err == DB_SUCCESS && search_mode == BTR_MODIFY_LEAF
&& rtr_info.mbr_adj) {
@@ -2926,9 +2929,8 @@ row_ins_sec_index_entry_low(
index->set_modified(mtr);
}
err = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_RTREE_INSERT,
search_mode,
&cursor, &mtr);
0, entry, PAGE_CUR_RTREE_INSERT,
search_mode, &cursor, &mtr);
}
DBUG_EXECUTE_IF(
@@ -2936,14 +2938,16 @@ row_ins_sec_index_entry_low(
goto func_exit;});
} else {
if (!thr_get_trx(thr)->check_unique_secondary) {
search_mode |= BTR_IGNORE_SEC_UNIQUE;
if (!index->table->is_temporary()) {
search_mode = btr_latch_mode(
search_mode
| (thr_get_trx(thr)->check_unique_secondary
? BTR_INSERT | BTR_IGNORE_SEC_UNIQUE
: BTR_INSERT));
}
err = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE,
search_mode,
&cursor, &mtr);
err = btr_cur_search_to_nth_level(0, entry, PAGE_CUR_LE,
search_mode, &cursor, &mtr);
}
if (err != DB_SUCCESS) {
@@ -3018,11 +3022,12 @@ row_ins_sec_index_entry_low(
locked with s-locks the necessary records to
prevent any insertion of a duplicate by another
transaction. Let us now reposition the cursor and
continue the insertion. */
continue the insertion (bypassing the change buffer). */
err = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE,
(search_mode
& ~(BTR_INSERT | BTR_IGNORE_SEC_UNIQUE)),
0, entry, PAGE_CUR_LE,
btr_latch_mode(search_mode
& ~(BTR_INSERT
| BTR_IGNORE_SEC_UNIQUE)),
&cursor, &mtr);
if (err != DB_SUCCESS) {
goto func_exit;
@@ -3061,7 +3066,6 @@ row_ins_sec_index_entry_low(
err = rtr_ins_enlarge_mbr(&cursor, &mtr);
}
} else {
ut_ad(mode == BTR_MODIFY_TREE);
if (buf_pool.running_out()) {
err = DB_LOCK_TABLE_FULL;
goto func_exit;
@@ -3264,7 +3268,7 @@ row_ins_sec_index_entry(
log_free_check();
err = row_ins_sec_index_entry_low(
flags, BTR_MODIFY_TREE, index,
flags, BTR_INSERT_TREE, index,
offsets_heap, heap, entry, 0, thr);
}

View File

@@ -1583,7 +1583,7 @@ row_log_table_apply_insert_low(
entry = row_build_index_entry(row, NULL, index, heap);
error = row_ins_sec_index_entry_low(
flags, BTR_MODIFY_TREE,
flags, BTR_INSERT_TREE,
index, offsets_heap, heap, entry,
thr_get_trx(thr)->id, thr);
@@ -1658,7 +1658,7 @@ row_log_table_apply_delete_low(
dberr_t error;
row_ext_t* ext;
dtuple_t* row;
dict_index_t* index = btr_pcur_get_btr_cur(pcur)->index;
dict_index_t* index = pcur->index();
ut_ad(dict_index_is_clust(index));
@@ -1695,9 +1695,9 @@ err_exit:
row, ext, index, heap);
mtr->start();
index->set_modified(*mtr);
error = btr_pcur_open(index, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
pcur, mtr);
pcur->btr_cur.page_cur.index = index;
error = btr_pcur_open(entry, PAGE_CUR_LE,
BTR_PURGE_TREE, pcur, 0, mtr);
if (error) {
goto err_exit;
}
@@ -1761,6 +1761,7 @@ row_log_table_apply_delete(
btr_pcur_t pcur;
rec_offs* offsets;
pcur.btr_cur.page_cur.index = index;
ut_ad(rec_offs_n_fields(moffsets) == index->first_user_field());
ut_ad(!rec_offs_any_extern(moffsets));
@@ -1779,9 +1780,8 @@ row_log_table_apply_delete(
mtr_start(&mtr);
index->set_modified(mtr);
dberr_t err = btr_pcur_open(index, old_pk, PAGE_CUR_LE,
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
&pcur, &mtr);
dberr_t err = btr_pcur_open(old_pk, PAGE_CUR_LE,
BTR_PURGE_TREE, &pcur, 0, &mtr);
if (err != DB_SUCCESS) {
goto all_done;
}
@@ -1893,6 +1893,8 @@ row_log_table_apply_update(
dberr_t error;
ulint n_index = 0;
pcur.btr_cur.page_cur.index = index;
ut_ad(dtuple_get_n_fields_cmp(old_pk)
== dict_index_get_n_unique(index));
ut_ad(dtuple_get_n_fields(old_pk) - (log->same_pk ? 0 : 2)
@@ -1915,8 +1917,8 @@ row_log_table_apply_update(
mtr.start();
index->set_modified(mtr);
error = btr_pcur_open(index, old_pk, PAGE_CUR_LE,
BTR_MODIFY_TREE, &pcur, &mtr);
error = btr_pcur_open(old_pk, PAGE_CUR_LE,
BTR_MODIFY_TREE, &pcur, 0, &mtr);
if (error != DB_SUCCESS) {
func_exit:
mtr.commit();
@@ -2061,7 +2063,7 @@ func_exit_committed:
for (n_index += index->type != DICT_CLUSTERED;
(index = dict_table_get_next_index(index)); n_index++) {
if (index->type & DICT_FTS) {
if (!index->is_btree()) {
continue;
}
@@ -2089,9 +2091,10 @@ func_exit_committed:
mtr.start();
index->set_modified(mtr);
pcur.btr_cur.page_cur.index = index;
if (ROW_FOUND != row_search_index_entry(
index, entry, BTR_MODIFY_TREE, &pcur, &mtr)) {
entry, BTR_MODIFY_TREE, &pcur, &mtr)) {
ut_ad(0);
error = DB_CORRUPTION;
break;
@@ -2111,7 +2114,7 @@ func_exit_committed:
error = row_ins_sec_index_entry_low(
BTR_CREATE_FLAG | BTR_NO_LOCKING_FLAG
| BTR_NO_UNDO_LOG_FLAG | BTR_KEEP_SYS_FLAG,
BTR_MODIFY_TREE, index, offsets_heap, heap,
BTR_INSERT_TREE, index, offsets_heap, heap,
entry, thr_get_trx(thr)->id, thr);
/* Report correct index name for duplicate key error. */
@@ -3071,13 +3074,14 @@ row_log_apply_op_low(
mtr_start(&mtr);
index->set_modified(mtr);
cursor.page_cur.index = index;
/* We perform the pessimistic variant of the operations if we
already hold index->lock exclusively. First, search the
record. The operation may already have been performed,
depending on when the row in the clustered index was
scanned. */
*error = btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
*error = btr_cur_search_to_nth_level(0, entry, PAGE_CUR_LE,
has_index_lock
? BTR_MODIFY_TREE
: BTR_MODIFY_LEAF,
@@ -3132,7 +3136,7 @@ row_log_apply_op_low(
mtr_start(&mtr);
index->set_modified(mtr);
*error = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE,
0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, &mtr);
if (UNIV_UNLIKELY(*error != DB_SUCCESS)) {
goto func_exit;
@@ -3236,7 +3240,7 @@ insert_the_rec:
mtr_start(&mtr);
index->set_modified(mtr);
*error = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE,
0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, &mtr);
if (*error != DB_SUCCESS) {
break;
@@ -3951,8 +3955,8 @@ void UndorecApplier::log_insert(const dtuple_t &tuple,
}
bool success= true;
dict_index_t *index= dict_table_get_next_index(clust_index);
while (index)
for (dict_index_t *index= clust_index;
(index= dict_table_get_next_index(index)) != nullptr; )
{
index->lock.s_lock(SRW_LOCK_CALL);
if (index->online_log &&
@@ -3971,7 +3975,6 @@ void UndorecApplier::log_insert(const dtuple_t &tuple,
row_log_mark_other_online_index_abort(index->table);
return;
}
index= dict_table_get_next_index(index);
}
}
}

View File

@@ -145,13 +145,13 @@ public:
mtr.start();
index->set_modified(mtr);
ins_cur.index = index;
ins_cur.page_cur.index = index;
rtr_init_rtr_info(&rtr_info, false, &ins_cur, index,
false);
rtr_info_update_btr(&ins_cur, &rtr_info);
error = btr_cur_search_to_nth_level(
index, 0, dtuple, PAGE_CUR_RTREE_INSERT,
0, dtuple, PAGE_CUR_RTREE_INSERT,
BTR_MODIFY_LEAF, &ins_cur, &mtr);
/* It need to update MBR in parent entry,
@@ -165,7 +165,7 @@ public:
mtr.start();
index->set_modified(mtr);
error = btr_cur_search_to_nth_level(
index, 0, dtuple,
0, dtuple,
PAGE_CUR_RTREE_INSERT,
BTR_MODIFY_TREE, &ins_cur, &mtr);
}
@@ -190,7 +190,7 @@ public:
rtr_info_update_btr(&ins_cur, &rtr_info);
error = btr_cur_search_to_nth_level(
index, 0, dtuple,
0, dtuple,
PAGE_CUR_RTREE_INSERT,
BTR_MODIFY_TREE,
&ins_cur, &mtr);
@@ -1999,8 +1999,7 @@ row_merge_read_clustered_index(
? col_map[old_trx_id_col] : old_trx_id_col;
uint64_t n_rows = 0;
err = btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF,
&pcur, true, 0, &mtr);
err = pcur.open_leaf(true, clust_index, BTR_SEARCH_LEAF, &mtr);
if (err != DB_SUCCESS) {
err_exit:
trx->error_key_num = 0;
@@ -2232,13 +2231,15 @@ end_of_index:
if (!block) {
goto err_exit;
}
btr_leaf_page_release(page_cur_get_block(cur),
BTR_SEARCH_LEAF, &mtr);
page_cur_set_before_first(block, cur);
if (!page_cur_move_to_next(cur)
|| page_cur_is_after_last(cur)) {
goto corrupted_rec;
}
const auto s = mtr.get_savepoint();
mtr.rollback_to_savepoint(s - 2, s - 1);
}
} else {
mem_heap_empty(row_heap);

View File

@@ -1456,11 +1456,8 @@ row_create_update_node_for_mysql(
node->in_mysql_interface = true;
node->is_delete = NO_DELETE;
node->searched_update = FALSE;
node->select = NULL;
node->pcur = btr_pcur_create_for_mysql();
DBUG_PRINT("info", ("node: %p, pcur: %p", node, node->pcur));
node->pcur = new (mem_heap_alloc(heap, sizeof(btr_pcur_t)))
btr_pcur_t();
node->table = table;
@@ -1472,10 +1469,6 @@ row_create_update_node_for_mysql(
UT_LIST_INIT(node->columns, &sym_node_t::col_var_list);
node->has_clust_rec_x_lock = TRUE;
node->cmpl_info = 0;
node->table_sym = NULL;
node->col_assign_list = NULL;
DBUG_RETURN(node);
}
@@ -1650,8 +1643,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt)
clust_index = dict_table_get_first_index(table);
btr_pcur_copy_stored_position(node->pcur,
prebuilt->pcur->btr_cur.index
== clust_index
prebuilt->pcur->index() == clust_index
? prebuilt->pcur
: prebuilt->clust_pcur);
@@ -1804,7 +1796,7 @@ row_unlock_for_mysql(
}
rec = btr_pcur_get_rec(pcur);
index = btr_pcur_get_btr_cur(pcur)->index;
index = pcur->index();
/* If the record has been modified by this
transaction, do not unlock it. */

View File

@@ -67,7 +67,7 @@ static
ibool
row_purge_reposition_pcur(
/*======================*/
ulint mode, /*!< in: latching mode */
btr_latch_mode mode, /*!< in: latching mode */
purge_node_t* node, /*!< in: row purge node */
mtr_t* mtr) /*!< in: mtr */
{
@@ -104,7 +104,7 @@ bool
row_purge_remove_clust_if_poss_low(
/*===============================*/
purge_node_t* node, /*!< in/out: row purge node */
ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
btr_latch_mode mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
{
dict_index_t* index = dict_table_get_first_index(node->table);
table_id_t table_id = 0;
@@ -216,7 +216,7 @@ close_and_exit:
btr_pcur_get_btr_cur(&node->pcur), 0, &mtr);
} else {
dberr_t err;
ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE));
ut_ad(mode == BTR_PURGE_TREE);
btr_cur_pessimistic_delete(
&err, FALSE, btr_pcur_get_btr_cur(&node->pcur), 0,
false, &mtr);
@@ -257,8 +257,7 @@ row_purge_remove_clust_if_poss(
for (ulint n_tries = 0;
n_tries < BTR_CUR_RETRY_DELETE_N_TIMES;
n_tries++) {
if (row_purge_remove_clust_if_poss_low(
node, BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE)) {
if (row_purge_remove_clust_if_poss_low(node, BTR_PURGE_TREE)) {
return(true);
}
@@ -348,10 +347,9 @@ row_purge_remove_sec_if_poss_tree(
log_free_check();
mtr.start();
index->set_modified(mtr);
pcur.btr_cur.page_cur.index = index;
search_result = row_search_index_entry(
index, entry,
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
search_result = row_search_index_entry(entry, BTR_PURGE_TREE,
&pcur, &mtr);
switch (search_result) {
@@ -455,6 +453,7 @@ row_purge_remove_sec_if_poss_leaf(
virtual index. */
mode = (index->type & (DICT_SPATIAL | DICT_VIRTUAL))
? BTR_MODIFY_LEAF : BTR_PURGE_LEAF;
pcur.btr_cur.page_cur.index = index;
/* Set the purge node for the call to row_purge_poss_sec(). */
pcur.btr_cur.purge_node = node;
@@ -462,7 +461,7 @@ row_purge_remove_sec_if_poss_leaf(
pcur.btr_cur.thr = NULL;
index->lock.u_lock(SRW_LOCK_CALL);
search_result = row_search_index_entry(
index, entry, mode, &pcur, &mtr);
entry, mode, &pcur, &mtr);
index->lock.u_unlock();
} else {
/* Set the query thread, so that ibuf_insert_low() will be
@@ -470,7 +469,7 @@ row_purge_remove_sec_if_poss_leaf(
pcur.btr_cur.thr = static_cast<que_thr_t*>(
que_node_get_parent(node));
search_result = row_search_index_entry(
index, entry, mode, &pcur, &mtr);
entry, mode, &pcur, &mtr);
}
switch (search_result) {
@@ -1343,11 +1342,11 @@ purge_node_t::validate_pcur()
return(true);
}
if (!pcur.old_stored) {
if (!pcur.old_rec) {
return(true);
}
dict_index_t* clust_index = pcur.btr_cur.index;
dict_index_t* clust_index = pcur.index();
rec_offs* offsets = rec_get_offsets(
pcur.old_rec, clust_index, NULL, pcur.old_n_core_fields,

View File

@@ -1183,32 +1183,28 @@ row_build_row_ref_in_tuple(
/***************************************************************//**
Searches the clustered index record for a row, if we have the row reference.
@return TRUE if found */
ibool
bool
row_search_on_row_ref(
/*==================*/
btr_pcur_t* pcur, /*!< out: persistent cursor, which must
be closed by the caller */
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
const dict_table_t* table, /*!< in: table */
const dtuple_t* ref, /*!< in: row reference */
mtr_t* mtr) /*!< in/out: mtr */
{
ulint low_match;
rec_t* rec;
dict_index_t* index;
ut_ad(dtuple_check_typed(ref));
index = dict_table_get_first_index(table);
dict_index_t *index = dict_table_get_first_index(table);
btr_pcur_init(pcur);
pcur->btr_cur.page_cur.index = index;
if (UNIV_UNLIKELY(ref->info_bits != 0)) {
ut_ad(ref->is_metadata());
ut_ad(ref->n_fields <= index->n_uniq);
if (btr_pcur_open_at_index_side(
true, index, mode, pcur, true, 0, mtr)
!= DB_SUCCESS
if (pcur->open_leaf(true, index, mode, mtr) != DB_SUCCESS
|| !btr_pcur_move_to_next_user_rec(pcur, mtr)) {
return FALSE;
return false;
}
/* We do not necessarily have index->is_instant() here,
because we could be executing a rollback of an
@@ -1220,27 +1216,14 @@ row_search_on_row_ref(
& REC_INFO_MIN_REC_FLAG;
} else {
ut_a(ref->n_fields == index->n_uniq);
if (btr_pcur_open(index, ref, PAGE_CUR_LE, mode, pcur, mtr)
if (btr_pcur_open(ref, PAGE_CUR_LE, mode, pcur, 0, mtr)
!= DB_SUCCESS) {
return FALSE;
return false;
}
}
low_match = btr_pcur_get_low_match(pcur);
rec = btr_pcur_get_rec(pcur);
if (page_rec_is_infimum(rec)) {
return(FALSE);
}
if (low_match != dtuple_get_n_fields(ref)) {
return(FALSE);
}
return(TRUE);
return !page_rec_is_infimum(btr_pcur_get_rec(pcur))
&& btr_pcur_get_low_match(pcur) == dtuple_get_n_fields(ref);
}
/*********************************************************************//**
@@ -1250,7 +1233,7 @@ on the secondary index record are preserved.
rec_t*
row_get_clust_rec(
/*==============*/
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
const rec_t* rec, /*!< in: record in a secondary index */
dict_index_t* index, /*!< in: secondary index */
dict_index_t** clust_index,/*!< out: clustered index */
@@ -1283,9 +1266,8 @@ Searches an index record.
enum row_search_result
row_search_index_entry(
/*===================*/
dict_index_t* index, /*!< in: index */
const dtuple_t* entry, /*!< in: index entry */
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must
be closed by the caller */
mtr_t* mtr) /*!< in: mtr */
@@ -1296,12 +1278,12 @@ row_search_index_entry(
ut_ad(dtuple_check_typed(entry));
if (index->is_spatial()) {
if (rtr_pcur_open(index, entry, mode, pcur, mtr)) {
if (pcur->index()->is_spatial()) {
if (rtr_pcur_open(pcur->index(), entry, mode, pcur, mtr)) {
return ROW_NOT_FOUND;
}
} else {
if (btr_pcur_open(index, entry, PAGE_CUR_LE, mode, pcur, mtr)
if (btr_pcur_open(entry, PAGE_CUR_LE, mode, pcur, 0, mtr)
!= DB_SUCCESS) {
return ROW_NOT_FOUND;
}
@@ -1310,7 +1292,7 @@ row_search_index_entry(
switch (btr_pcur_get_btr_cur(pcur)->flag) {
case BTR_CUR_DELETE_REF:
ut_ad(!(~mode & BTR_DELETE));
ut_ad(!index->is_spatial());
ut_ad(!pcur->index()->is_spatial());
return(ROW_NOT_DELETED_REF);
case BTR_CUR_DEL_MARK_IBUF:

View File

@@ -1008,17 +1008,16 @@ row_sel_get_clust_rec(
*out_rec = NULL;
offsets = rec_get_offsets(rec,
btr_pcur_get_btr_cur(&plan->pcur)->index,
offsets,
btr_pcur_get_btr_cur(&plan->pcur)->index
->n_core_fields, ULINT_UNDEFINED, &heap);
offsets = rec_get_offsets(rec, plan->pcur.index(), offsets,
plan->pcur.index()->n_core_fields,
ULINT_UNDEFINED, &heap);
row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec, offsets);
index = dict_table_get_first_index(plan->table);
dberr_t err = btr_pcur_open_with_no_init(index, plan->clust_ref,
plan->clust_pcur.old_rec = nullptr;
plan->clust_pcur.btr_cur.page_cur.index = index;
dberr_t err = btr_pcur_open_with_no_init(plan->clust_ref,
PAGE_CUR_LE, BTR_SEARCH_LEAF,
&plan->clust_pcur, mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
@@ -1410,6 +1409,9 @@ row_sel_open_pcur(
cond = UT_LIST_GET_NEXT(cond_list, cond);
}
plan->pcur.old_rec = nullptr;
plan->pcur.btr_cur.page_cur.index = index;
dberr_t err;
if (plan->tuple) {
@@ -1429,13 +1431,12 @@ row_sel_open_pcur(
que_node_get_val(exp));
}
err = btr_pcur_open_with_no_init(index, plan->tuple,
err = btr_pcur_open_with_no_init(plan->tuple,
plan->mode, BTR_SEARCH_LEAF,
&plan->pcur, mtr);
} else {
err = btr_pcur_open_at_index_side(plan->asc, index,
BTR_SEARCH_LEAF, &plan->pcur,
false, 0, mtr);
err = plan->pcur.open_leaf(plan->asc, index, BTR_SEARCH_LEAF,
mtr);
}
plan->pcur_is_open = err == DB_SUCCESS;
@@ -3370,6 +3371,7 @@ Row_sel_get_clust_rec_for_mysql::operator()(
rec_t* old_vers;
trx_t* trx;
prebuilt->clust_pcur->old_rec = nullptr;
*out_rec = NULL;
trx = thr_get_trx(thr);
@@ -3380,9 +3382,9 @@ Row_sel_get_clust_rec_for_mysql::operator()(
sec_index, *offsets);
clust_index = dict_table_get_first_index(sec_index->table);
prebuilt->clust_pcur->btr_cur.page_cur.index = clust_index;
dberr_t err = btr_pcur_open_with_no_init(clust_index,
prebuilt->clust_ref,
dberr_t err = btr_pcur_open_with_no_init(prebuilt->clust_ref,
PAGE_CUR_LE, BTR_SEARCH_LEAF,
prebuilt->clust_pcur, mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
@@ -3447,9 +3449,10 @@ Row_sel_get_clust_rec_for_mysql::operator()(
rec, sec_index, true,
sec_index->n_fields, heap);
page_cur_t page_cursor;
page_cursor.block = block;
page_cursor.index = sec_index;
ulint up_match = 0, low_match = 0;
ut_ad(!page_cur_search_with_match(block, sec_index,
tuple, PAGE_CUR_LE,
ut_ad(!page_cur_search_with_match(tuple, PAGE_CUR_LE,
&up_match,
&low_match,
&page_cursor,
@@ -3639,7 +3642,8 @@ record with the same ordering prefix in in the B-tree index
@return true if we may need to process the record the cursor is now
positioned on (i.e. we should not go to the next record yet) */
static bool sel_restore_position_for_mysql(bool *same_user_rec,
ulint latch_mode, btr_pcur_t *pcur,
btr_latch_mode latch_mode,
btr_pcur_t *pcur,
bool moves_up, mtr_t *mtr)
{
auto status = pcur->restore_position(latch_mode, mtr);
@@ -3668,7 +3672,7 @@ static bool sel_restore_position_for_mysql(bool *same_user_rec,
next:
if (btr_pcur_move_to_next(pcur, mtr)
&& rec_is_metadata(btr_pcur_get_rec(pcur),
*pcur->btr_cur.index)) {
*pcur->index())) {
btr_pcur_move_to_next(pcur, mtr);
}
@@ -3684,7 +3688,7 @@ next:
prev:
if (btr_pcur_is_on_user_rec(pcur) && !moves_up
&& !rec_is_metadata(btr_pcur_get_rec(pcur),
*pcur->btr_cur.index)) {
*pcur->index())) {
if (!btr_pcur_move_to_prev(pcur, mtr)) {
return true;
}
@@ -3964,8 +3968,9 @@ row_sel_try_search_shortcut_for_mysql(
ut_ad(!index->table->is_temporary());
ut_ad(!prebuilt->templ_contains_blob);
ut_ad(trx->read_view.is_open());
pcur->old_rec = nullptr;
if (btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
if (btr_pcur_open_with_no_init(search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur, mtr)
!= DB_SUCCESS) {
return SEL_RETRY;
@@ -4395,6 +4400,8 @@ row_search_mvcc(
DBUG_RETURN(DB_CORRUPTION);
}
pcur->btr_cur.page_cur.index = index;
/* We need to get the virtual column values stored in secondary
index key, if this is covered index scan or virtual key read is
requested. */
@@ -4766,6 +4773,7 @@ wait_table_again:
} else if (dtuple_get_n_fields(search_tuple) > 0) {
pcur->btr_cur.thr = thr;
pcur->old_rec = nullptr;
if (dict_index_is_spatial(index)) {
if (!prebuilt->rtr_info) {
@@ -4785,7 +4793,7 @@ wait_table_again:
}
}
err = btr_pcur_open_with_no_init(index, search_tuple, mode,
err = btr_pcur_open_with_no_init(search_tuple, mode,
BTR_SEARCH_LEAF, pcur, &mtr);
if (err != DB_SUCCESS) {
@@ -4831,9 +4839,8 @@ page_corrupted:
}
}
} else if (mode == PAGE_CUR_G || mode == PAGE_CUR_L) {
err = btr_pcur_open_at_index_side(
mode == PAGE_CUR_G, index, BTR_SEARCH_LEAF,
pcur, false, 0, &mtr);
err = pcur->open_leaf(mode == PAGE_CUR_G, index,
BTR_SEARCH_LEAF, &mtr);
if (err != DB_SUCCESS) {
if (err == DB_DECRYPTION_FAILED) {
@@ -5019,7 +5026,7 @@ wrong_offs:
page_cur_set_after_last(btr_pcur_get_block(pcur),
btr_pcur_get_page_cur(pcur));
pcur->old_stored = false;
pcur->old_rec = nullptr;
goto next_rec;
}
}
@@ -5786,7 +5793,7 @@ next_rec_after_check:
/* This is based on btr_pcur_move_to_next() */
ut_ad(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(pcur->latch_mode != BTR_NO_LATCHES);
pcur->old_stored = false;
pcur->old_rec = nullptr;
if (btr_pcur_is_after_last_on_page(pcur)) {
if (btr_pcur_is_after_last_in_tree(pcur)) {
goto not_moved;
@@ -6198,8 +6205,6 @@ dberr_t row_check_index(row_prebuilt_t *prebuilt, ulint *n_rows)
*n_rows= 0;
dict_index_t *const index= prebuilt->index;
prebuilt->fetch_direction= ROW_SEL_NEXT;
if (!index->is_btree())
return DB_CORRUPTION;
@@ -6210,9 +6215,8 @@ dberr_t row_check_index(row_prebuilt_t *prebuilt, ulint *n_rows)
mtr.start();
dict_index_t *clust_index= dict_table_get_first_index(prebuilt->table);
dberr_t err= btr_pcur_open_at_index_side(true, index, BTR_SEARCH_LEAF,
prebuilt->pcur, false, 0, &mtr);
prebuilt->clust_pcur->btr_cur.page_cur.index = clust_index;
dberr_t err= prebuilt->pcur->open_leaf(true, index, BTR_SEARCH_LEAF, &mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS))
{
func_exit:
@@ -6300,14 +6304,16 @@ rec_loop:
goto next_rec;
}
if (index->is_clust())
if (prebuilt->table->is_temporary())
{
if (prebuilt->trx->isolation_level == TRX_ISO_READ_UNCOMMITTED)
{
if (!rec_deleted)
goto count_row;
count_or_not:
if (rec_deleted)
goto next_rec;
}
else if (index->is_clust())
{
if (prebuilt->trx->isolation_level == TRX_ISO_READ_UNCOMMITTED)
goto count_or_not;
trx_id_t rec_trx_id= row_get_rec_trx_id(rec, index, offsets);
@@ -6371,10 +6377,7 @@ rec_loop:
ER_NOT_KEYFILE, "InnoDB: %s", w.m_oss.str().c_str());
}
if (!rec_deleted)
goto count_row;
goto next_rec;
goto count_or_not;
}
else if (const trx_id_t page_trx_id= page_get_max_trx_id(page_align(rec)))
{
@@ -6388,7 +6391,7 @@ rec_loop:
const auto savepoint= mtr.get_savepoint();
row_build_row_ref_in_tuple(prebuilt->clust_ref, rec, index, offsets);
err= btr_pcur_open_with_no_init(clust_index, prebuilt->clust_ref,
err= btr_pcur_open_with_no_init(prebuilt->clust_ref,
PAGE_CUR_LE, BTR_SEARCH_LEAF,
prebuilt->clust_pcur, &mtr);
if (err != DB_SUCCESS)
@@ -6887,8 +6890,7 @@ row_search_get_max_rec(
const rec_t* rec;
const bool desc = index->fields[0].descending;
if (btr_pcur_open_at_index_side(desc, index, BTR_SEARCH_LEAF, &pcur,
true, 0, mtr) != DB_SUCCESS) {
if (pcur.open_leaf(desc, index, BTR_SEARCH_LEAF, mtr) != DB_SUCCESS) {
return nullptr;
}

View File

@@ -68,7 +68,7 @@ row_undo_ins_remove_clust_rec(
dberr_t err;
ulint n_tries = 0;
mtr_t mtr;
dict_index_t* index = node->pcur.btr_cur.index;
dict_index_t* index = node->pcur.index();
table_id_t table_id = 0;
const bool dict_locked = node->trx->dict_operation_lock_mode;
restart:
@@ -207,9 +207,8 @@ retry:
} else {
index->set_modified(mtr);
}
ut_a(
node->pcur.restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
&mtr) == btr_pcur_t::SAME_ALL);
ut_a(node->pcur.restore_position(BTR_PURGE_TREE, &mtr)
== btr_pcur_t::SAME_ALL);
btr_cur_pessimistic_delete(&err, FALSE, &node->pcur.btr_cur, 0, true,
&mtr);
@@ -254,7 +253,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t
row_undo_ins_remove_sec_low(
/*========================*/
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
depending on whether we wish optimistic or
pessimistic descent down the index tree */
dict_index_t* index, /*!< in: index */
@@ -266,25 +265,27 @@ row_undo_ins_remove_sec_low(
mtr_t mtr;
const bool modify_leaf = mode == BTR_MODIFY_LEAF;
pcur.btr_cur.page_cur.index = index;
row_mtr_start(&mtr, index, !modify_leaf);
if (modify_leaf) {
mode = BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED;
mode = BTR_MODIFY_LEAF_ALREADY_LATCHED;
mtr_s_lock_index(index, &mtr);
} else {
ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE));
ut_ad(mode == BTR_PURGE_TREE);
mtr_sx_lock_index(index, &mtr);
}
if (dict_index_is_spatial(index)) {
if (modify_leaf) {
mode |= BTR_RTREE_DELETE_MARK;
}
if (index->is_spatial()) {
mode = modify_leaf
? btr_latch_mode(BTR_MODIFY_LEAF_ALREADY_LATCHED
| BTR_RTREE_DELETE_MARK
| BTR_RTREE_UNDO_INS)
: btr_latch_mode(BTR_PURGE_TREE | BTR_RTREE_UNDO_INS);
btr_pcur_get_btr_cur(&pcur)->thr = thr;
mode |= BTR_RTREE_UNDO_INS;
}
switch (row_search_index_entry(index, entry, mode, &pcur, &mtr)) {
switch (row_search_index_entry(entry, mode, &pcur, &mtr)) {
case ROW_BUFFERED:
case ROW_NOT_DELETED_REF:
/* These are invalid outcomes, because the mode passed
@@ -349,9 +350,7 @@ row_undo_ins_remove_sec(
/* Try then pessimistic descent to the B-tree */
retry:
err = row_undo_ins_remove_sec_low(
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
index, entry, thr);
err = row_undo_ins_remove_sec_low(BTR_PURGE_TREE, index, entry, thr);
/* The delete operation may fail if we have little
file space left: TODO: easiest to crash the database

View File

@@ -84,7 +84,7 @@ row_undo_mod_clust_low(
que_thr_t* thr, /*!< in: query thread */
mtr_t* mtr, /*!< in: mtr; must be committed before
latching any further pages */
ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
btr_latch_mode mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
{
btr_pcur_t* pcur;
btr_cur_t* btr_cur;
@@ -106,8 +106,8 @@ row_undo_mod_clust_low(
|| node->update->info_bits == REC_INFO_METADATA_ALTER);
if (mode != BTR_MODIFY_TREE) {
ut_ad((mode & ulint(~BTR_ALREADY_S_LATCHED))
== BTR_MODIFY_LEAF);
ut_ad(mode == BTR_MODIFY_LEAF
|| mode == BTR_MODIFY_LEAF_ALREADY_LATCHED);
err = btr_cur_optimistic_update(
BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG
@@ -224,14 +224,14 @@ static bool row_undo_mod_must_purge(const undo_node_t &node)
ut_ad(!node.table->is_temporary());
const btr_cur_t &btr_cur= node.pcur.btr_cur;
ut_ad(btr_cur.index->is_primary());
ut_ad(btr_cur.index()->is_primary());
DEBUG_SYNC_C("rollback_purge_clust");
if (!purge_sys.is_purgeable(node.new_trx_id))
return false;
const rec_t *rec= btr_cur_get_rec(&btr_cur);
return trx_read_trx_id(rec + row_trx_id_offset(rec, btr_cur.index)) ==
return trx_read_trx_id(rec + row_trx_id_offset(rec, btr_cur.index())) ==
node.new_trx_id;
}
@@ -356,8 +356,7 @@ row_undo_mod_clust(
}
mtr.start();
if (pcur->restore_position(
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, &mtr) !=
if (pcur->restore_position(BTR_PURGE_TREE, &mtr) !=
btr_pcur_t::SAME_ALL) {
goto mtr_commit_exit;
}
@@ -483,7 +482,7 @@ row_undo_mod_del_mark_or_remove_sec_low(
que_thr_t* thr, /*!< in: query thread */
dict_index_t* index, /*!< in: index */
dtuple_t* entry, /*!< in: index entry */
ulint mode) /*!< in: latch mode BTR_MODIFY_LEAF or
btr_latch_mode mode) /*!< in: latch mode BTR_MODIFY_LEAF or
BTR_MODIFY_TREE */
{
btr_pcur_t pcur;
@@ -496,15 +495,25 @@ row_undo_mod_del_mark_or_remove_sec_low(
row_mtr_start(&mtr, index, !modify_leaf);
if (!index->is_committed()) {
pcur.btr_cur.page_cur.index = index;
btr_cur = btr_pcur_get_btr_cur(&pcur);
if (index->is_spatial()) {
mode = modify_leaf
? btr_latch_mode(BTR_MODIFY_LEAF
| BTR_RTREE_DELETE_MARK
| BTR_RTREE_UNDO_INS)
: btr_latch_mode(BTR_PURGE_TREE | BTR_RTREE_UNDO_INS);
btr_cur->thr = thr;
} else if (!index->is_committed()) {
/* The index->online_status may change if the index is
or was being created online, but not committed yet. It
is protected by index->lock. */
if (modify_leaf) {
mode = BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED;
mode = BTR_MODIFY_LEAF_ALREADY_LATCHED;
mtr_s_lock_index(index, &mtr);
} else {
ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE));
ut_ad(mode == BTR_PURGE_TREE);
mtr_sx_lock_index(index, &mtr);
}
} else {
@@ -514,18 +523,7 @@ row_undo_mod_del_mark_or_remove_sec_low(
ut_ad(!dict_index_is_online_ddl(index));
}
btr_cur = btr_pcur_get_btr_cur(&pcur);
if (dict_index_is_spatial(index)) {
if (modify_leaf) {
btr_cur->thr = thr;
mode |= BTR_RTREE_DELETE_MARK;
}
mode |= BTR_RTREE_UNDO_INS;
}
search_result = row_search_index_entry(index, entry, mode,
&pcur, &mtr);
search_result = row_search_index_entry(entry, mode, &pcur, &mtr);
switch (UNIV_EXPECT(search_result, ROW_FOUND)) {
case ROW_NOT_FOUND:
@@ -634,7 +632,7 @@ row_undo_mod_del_mark_or_remove_sec(
}
err = row_undo_mod_del_mark_or_remove_sec_low(node, thr, index,
entry, BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE);
entry, BTR_PURGE_TREE);
return(err);
}
@@ -652,7 +650,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t
row_undo_mod_del_unmark_sec_and_undo_update(
/*========================================*/
ulint mode, /*!< in: search mode: BTR_MODIFY_LEAF or
btr_latch_mode mode, /*!< in: search mode: BTR_MODIFY_LEAF or
BTR_MODIFY_TREE */
que_thr_t* thr, /*!< in: query thread */
dict_index_t* index, /*!< in: index */
@@ -668,8 +666,9 @@ row_undo_mod_del_unmark_sec_and_undo_update(
const ulint flags
= BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG;
row_search_result search_result;
ulint orig_mode = mode;
const auto orig_mode = mode;
pcur.btr_cur.page_cur.index = index;
ut_ad(trx->id != 0);
if (dict_index_is_spatial(index)) {
@@ -679,7 +678,7 @@ row_undo_mod_del_unmark_sec_and_undo_update(
secondary index updates to avoid this. */
static_assert(BTR_MODIFY_TREE == (8 | BTR_MODIFY_LEAF), "");
ut_ad(!(mode & 8));
mode |= BTR_RTREE_DELETE_MARK;
mode = btr_latch_mode(mode | BTR_RTREE_DELETE_MARK);
}
try_again:
@@ -687,8 +686,7 @@ try_again:
btr_cur->thr = thr;
search_result = row_search_index_entry(index, entry, mode,
&pcur, &mtr);
search_result = row_search_index_entry(entry, mode, &pcur, &mtr);
switch (search_result) {
mem_heap_t* heap;

View File

@@ -1840,7 +1840,7 @@ row_upd_sec_index_entry(
btr_cur_t* btr_cur;
dberr_t err = DB_SUCCESS;
trx_t* trx = thr_get_trx(thr);
ulint mode;
btr_latch_mode mode;
ulint flags;
enum row_search_result search_result;
@@ -1870,14 +1870,16 @@ row_upd_sec_index_entry(
"before_row_upd_sec_index_entry");
mtr.start();
mode = BTR_MODIFY_LEAF;
switch (index->table->space_id) {
case SRV_TMP_SPACE_ID:
mtr.set_log_mode(MTR_LOG_NO_REDO);
flags = BTR_NO_LOCKING_FLAG;
mode = index->is_spatial()
? ulint(BTR_MODIFY_LEAF | BTR_RTREE_DELETE_MARK)
: ulint(BTR_MODIFY_LEAF);
if (index->is_spatial()) {
mode = btr_latch_mode(BTR_MODIFY_LEAF
| BTR_RTREE_DELETE_MARK);
}
break;
default:
index->set_modified(mtr);
@@ -1887,18 +1889,19 @@ row_upd_sec_index_entry(
/* We can only buffer delete-mark operations if there
are no foreign key constraints referring to the index. */
mode = index->is_spatial()
? ulint(BTR_MODIFY_LEAF | BTR_RTREE_DELETE_MARK)
? btr_latch_mode(BTR_MODIFY_LEAF
| BTR_RTREE_DELETE_MARK)
: referenced
? ulint(BTR_MODIFY_LEAF) : ulint(BTR_DELETE_MARK_LEAF);
? BTR_MODIFY_LEAF : BTR_DELETE_MARK_LEAF;
break;
}
/* Set the query thread, so that ibuf_insert_low() will be
able to invoke thd_get_trx(). */
btr_pcur_get_btr_cur(&pcur)->thr = thr;
pcur.btr_cur.page_cur.index = index;
search_result = row_search_index_entry(index, entry, mode,
&pcur, &mtr);
search_result = row_search_index_entry(entry, mode, &pcur, &mtr);
btr_cur = btr_pcur_get_btr_cur(&pcur);
@@ -2590,13 +2593,13 @@ row_upd_clust_step(
ut_a(pcur->rel_pos == BTR_PCUR_ON);
ulint mode;
btr_latch_mode mode;
DEBUG_SYNC_C_IF_THD(trx->mysql_thd, "innodb_row_upd_clust_step_enter");
if (dict_index_is_online_ddl(index)) {
ut_ad(node->table->id != DICT_INDEXES_ID);
mode = BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED;
mode = BTR_MODIFY_LEAF_ALREADY_LATCHED;
mtr_s_lock_index(index, &mtr);
} else {
mode = BTR_MODIFY_LEAF;

View File

@@ -392,9 +392,6 @@ mysql_mutex_t srv_misc_tmpfile_mutex;
/** Temporary file for miscellanous diagnostic output */
FILE* srv_misc_tmpfile;
static ulint srv_main_thread_process_no;
static ulint srv_main_thread_id;
/* The following counts are used by the srv_master_callback. */
/** Iterations of the loop bounded by 'srv_active' label. */
@@ -887,12 +884,7 @@ srv_printf_innodb_monitor(
n_reserved);
}
fprintf(file,
"Process ID=" ULINTPF
", Main thread ID=" ULINTPF
", state: %s\n",
srv_main_thread_process_no,
srv_main_thread_id,
fprintf(file, "Process ID=0, Main thread ID=0, state: %s\n",
srv_main_thread_op_info);
fprintf(file,
"Number of rows inserted " ULINTPF
@@ -1456,30 +1448,28 @@ static void srv_sync_log_buffer_in_background()
}
}
/*********************************************************************//**
This function prints progress message every 60 seconds during server
shutdown, for any activities that master thread is pending on. */
static
void
srv_shutdown_print_master_pending(
/*==============================*/
time_t* last_print_time, /*!< last time the function
print the message */
ulint n_bytes_merged) /*!< number of change buffer
just merged */
/** Report progress during shutdown.
@param last time of last output
@param n_read number of page reads initiated for change buffer merge */
static void srv_shutdown_print(time_t &last, ulint n_read)
{
time_t current_time = time(NULL);
time_t now= time(nullptr);
if (now - last >= 15)
{
last= now;
if (difftime(current_time, *last_print_time) > 60) {
*last_print_time = current_time;
/* Check change buffer merge, we only wait for change buffer
merge if it is a slow shutdown */
if (!srv_fast_shutdown && n_bytes_merged) {
ib::info() << "Waiting for change buffer merge to"
" complete number of bytes of change buffer"
" just merged: " << n_bytes_merged;
}
const ulint ibuf_size= ibuf.size;
sql_print_information("Completing change buffer merge;"
" %zu page reads initiated;"
" %zu change buffer pages remain",
n_read, ibuf_size);
#if defined HAVE_SYSTEMD && !defined EMBEDDED_LIBRARY
service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL,
"Completing change buffer merge;"
" %zu page reads initiated;"
" %zu change buffer pages remain",
n_read, ibuf_size);
#endif
}
}
@@ -1525,7 +1515,7 @@ Complete the shutdown tasks such as background DROP TABLE,
and optionally change buffer merge (on innodb_fast_shutdown=0). */
void srv_shutdown(bool ibuf_merge)
{
ulint n_bytes_merged = 0;
ulint n_read = 0;
time_t now = time(NULL);
do {
@@ -1534,21 +1524,12 @@ void srv_shutdown(bool ibuf_merge)
++srv_main_shutdown_loops;
if (ibuf_merge) {
srv_main_thread_op_info = "checking free log space";
log_free_check();
srv_main_thread_op_info = "doing insert buffer merge";
n_bytes_merged = ibuf_merge_all();
/* Flush logs if needed */
srv_sync_log_buffer_in_background();
log_free_check();
n_read = ibuf_contract();
srv_shutdown_print(now, n_read);
}
/* Print progress message every 60 seconds during shutdown */
if (srv_print_verbose_log) {
srv_shutdown_print_master_pending(&now,
n_bytes_merged);
}
} while (n_bytes_merged);
} while (n_read);
}
/** The periodic master task controlling the server. */

View File

@@ -594,7 +594,7 @@ static dberr_t trx_resurrect_table_locks(trx_t *trx, const trx_undo_t &undo)
if (undo_block != block)
{
mtr.memo_release(undo_block, MTR_MEMO_PAGE_S_FIX);
mtr.release(*undo_block);
undo_block= block;
}
trx_undo_rec_get_pars(undo_rec, &type, &cmpl_info,