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 sed '/Add support for verbose builds/,/^$/d' -i debian/rules
elif [ -d storage/columnstore/columnstore/debian ] elif [ -d storage/columnstore/columnstore/debian ]
then 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 # 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 sed '/-DPLUGIN_COLUMNSTORE=NO/d' -i debian/rules
# Take the files and part of control from MCS directory # Take the files and part of control from MCS directory
if [ ! -f debian/mariadb-plugin-columnstore.install ] 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 's/liburing-dev/libaio-dev/g' -i debian/control
sed -e '/-DIGNORE_AIO_CHECK=YES/d' \ 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() disable_pmem()
{ {
sed '/libpmem-dev/d' -i debian/control 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() disable_libfmt()
@@ -76,15 +76,34 @@ disable_libfmt()
architecture=$(dpkg-architecture -q DEB_BUILD_ARCH) 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:]')" LSBID="$(lsb_release -si | tr '[:upper:]' '[:lower:]')"
LSBVERSION="$(lsb_release -sr | sed -e "s#\.##g")" LSBVERSION="$(lsb_release -sr | sed -e "s#\.##g")"
LSBNAME="$(lsb_release -sc)" 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}" ] if [ -z "${LSBID}" ]
then then
LSBID="unknown" LSBID="unknown"
fi fi
case "${LSBNAME}" in
case "${LSBNAME}"
in
# Debian
stretch) stretch)
# MDEV-16525 libzstd-dev-1.1.3 minimum version # MDEV-16525 libzstd-dev-1.1.3 minimum version
sed -e '/libzstd-dev/d' \ sed -e '/libzstd-dev/d' \
@@ -113,10 +132,10 @@ case "${LSBNAME}" in
fi fi
;& ;&
sid) sid)
# should always be empty here. # The default packaging should always target Debian Sid, so in this case
# need to match here to avoid the default Error however # there is intentionally no customizations whatsoever.
;; ;;
# UBUNTU # Ubuntu
bionic) bionic)
remove_rocksdb_tools remove_rocksdb_tools
[ "$architecture" != amd64 ] && disable_pmem [ "$architecture" != amd64 ] && disable_pmem
@@ -143,7 +162,7 @@ case "${LSBNAME}" in
fi fi
;; ;;
*) *)
echo "Error - unknown release codename $LSBNAME" >&2 echo "Error: Unknown release '$LSBNAME'" >&2
exit 1 exit 1
esac esac
@@ -162,7 +181,7 @@ LOGSTRING="MariaDB build"
EPOCH="1:" EPOCH="1:"
VERSION="${EPOCH}${UPSTREAM}${PATCHLEVEL}~${LSBID:0:3}${LSBVERSION}" 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} ... " echo "Creating package version ${VERSION} ... "

View File

@@ -21,9 +21,18 @@ test -x /usr/sbin/mariadbd || exit 0
. /lib/lsb/init-functions . /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 # priority can be overridden and "-s" adds output to stderr
ERR_LOGGER="logger -p daemon.err -t /etc/init.d/mariadb -i" 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 # enable Debian Hardening
# see: https://wiki.debian.org/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 DPKG_EXPORT_BUILDFLAGS = 1
# Include all defaults, including buildflags.mk # Include all defaults, including buildflags.mk
include /usr/share/dpkg/default.mk include /usr/share/dpkg/default.mk
@@ -46,11 +52,6 @@ ifeq (32,$(DEB_HOST_ARCH_BITS))
CMAKEFLAGS += -DPLUGIN_ROCKSDB=NO CMAKEFLAGS += -DPLUGIN_ROCKSDB=NO
endif 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 # Cross building requires stack direction instruction
ifneq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH)) 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)) 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 # 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 # See https://packages.debian.org/search?searchon=names&keywords=libpmem-dev
ifneq (,$(filter $(DEB_HOST_ARCH_CPU),amd64 arm64 ppc64el riscv64)) ifneq (,$(filter $(DEB_HOST_ARCH_CPU),amd64 arm64 ppc64el riscv64))
CMAKEFLAGS += -DWITH_PMEM=yes CMAKEFLAGS += -DWITH_PMEM=YES
endif endif
# Add support for verbose builds # Add support for verbose builds
@@ -107,7 +108,7 @@ endif
-DPLUGIN_AWS_KEY_MANAGEMENT=NO \ -DPLUGIN_AWS_KEY_MANAGEMENT=NO \
-DPLUGIN_COLUMNSTORE=NO \ -DPLUGIN_COLUMNSTORE=NO \
-DIGNORE_AIO_CHECK=YES \ -DIGNORE_AIO_CHECK=YES \
-DWITH_URING=yes \ -DWITH_URING=YES \
-DDEB=$(DEB_VENDOR) -DDEB=$(DEB_VENDOR)
# This is needed, otherwise 'make test' will run before binaries have been built # 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: override_dh_auto_test:
@echo "RULES.$@" @echo "RULES.$@"
dh_testdir dh_testdir
# Ensure at least an empty file exists
touch mysql-test/unstable-tests touch mysql-test/unstable-tests
[ ! -f debian/unstable-tests.$(DEB_HOST_ARCH) ] || cat debian/unstable-tests.$(DEB_HOST_ARCH) >> mysql-test/unstable-tests [ ! -f debian/unstable-tests.$(DEB_HOST_ARCH) ] || cat debian/unstable-tests.$(DEB_HOST_ARCH) >> mysql-test/unstable-tests
# Run testsuite # Run testsuite
@@ -203,6 +205,7 @@ override_dh_installinit-arch:
dh_installinit --name=mariadb --no-start -- defaults 19 21 dh_installinit --name=mariadb --no-start -- defaults 19 21
dh_systemd_start --restart-after-upgrade dh_systemd_start --restart-after-upgrade
# Use custom server version string variable
override_dh_gencontrol: override_dh_gencontrol:
dh_gencontrol -- -Tdebian/substvars dh_gencontrol -- -Tdebian/substvars

77
debian/salsa-ci.yml vendored
View File

@@ -16,12 +16,17 @@ variables:
GIT_SUBMODULE_STRATEGY: recursive GIT_SUBMODULE_STRATEGY: recursive
SALSA_CI_GBP_BUILDPACKAGE_ARGS: "--git-submodules" # did not apply to extract-sources 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: stages:
- provisioning - provisioning
- build - build
- test - test
- upgrade in Sid - upgrade in Sid
- upgrade from Bullseye/Buster - upgrade from Bullseye
- upgrade extras - upgrade extras
- test extras - test extras
- publish # Stage referenced by Salsa-CI template aptly stanza, so must exist even though not used - 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 update
apt-get install -y apt 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 | .test-install: &test-install |
# Install MariaDB built in this commit # Install MariaDB built in this commit
apt-get install -y ./*.deb apt-get install -y ./*.deb
@@ -213,7 +229,7 @@ fresh install:
script: script:
- *test-prepare-container - *test-prepare-container
- *test-install - *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 - *test-verify-final
variables: variables:
GIT_STRATEGY: none GIT_STRATEGY: none
@@ -234,7 +250,7 @@ mariadb-10.8 Sid upgrade:
script: script:
- *test-prepare-container - *test-prepare-container
- *test-install - *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 - *test-verify-final
variables: variables:
GIT_STRATEGY: none 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)$/ - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
mariadb-10.5 Bullseye to mariadb-10.8 upgrade: mariadb-10.5 Bullseye to mariadb-10.8 upgrade:
stage: upgrade from Bullseye/Buster stage: upgrade from Bullseye
needs: needs:
- job: build - job: build
image: debian:bullseye image: debian:bullseye
@@ -268,10 +284,12 @@ mariadb-10.5 Bullseye to mariadb-10.8 upgrade:
variables: variables:
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
mariadb-10.3 Buster to mariadb-10.8 upgrade: # Upgrade of libcrypt.so.1 no longer possible from Buster to Sid,
stage: upgrade from Bullseye/Buster # 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: needs:
- job: build - job: build buster-backports
image: debian:buster image: debian:buster
artifacts: artifacts:
when: always when: always
@@ -284,7 +302,7 @@ mariadb-10.3 Buster to mariadb-10.8 upgrade:
- apt-get install -y 'default-mysql*' 'mariadb-*' 'libmariadb*' - apt-get install -y 'default-mysql*' 'mariadb-*' 'libmariadb*'
# Verify installation of MariaDB from Buster # Verify installation of MariaDB from Buster
- *test-verify-initial - *test-verify-initial
- *test-enable-sid-repos - *test-enable-buster-backports-repos
- *test-install - *test-install
- service mysql status - service mysql status
- *test-verify-final - *test-verify-final
@@ -307,7 +325,7 @@ test basic features:
script: script:
- *test-prepare-container - *test-prepare-container
- *test-install - *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 - *test-verify-final
- | - |
# Print info about server # 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)$/ - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
default-libmysqlclient-dev Bullseye upgrade: default-libmysqlclient-dev Bullseye upgrade:
stage: upgrade from Bullseye/Buster stage: upgrade from Bullseye
needs: needs:
- job: build - job: build
image: debian:bullseye image: debian:bullseye
@@ -472,10 +490,12 @@ default-libmysqlclient-dev Bullseye upgrade:
variables: variables:
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
default-libmysqlclient-dev Buster upgrade: # Upgrade of libcrypt.so.1 no longer possible from Buster to Sid,
stage: upgrade from Bullseye/Buster # so test upgrade only inside Buster (https://bugs.debian.org/993755)
default-libmysqlclient-dev upgrade in Buster:
stage: upgrade extras
needs: needs:
- job: build - job: build buster-backports
image: debian:buster image: debian:buster
artifacts: artifacts:
when: always when: always
@@ -486,7 +506,7 @@ default-libmysqlclient-dev Buster upgrade:
- *test-prepare-container - *test-prepare-container
- apt-get install -y pkg-config default-libmysqlclient-dev - apt-get install -y pkg-config default-libmysqlclient-dev
- pkg-config --list-all - pkg-config --list-all
- *test-enable-sid-repos - *test-enable-buster-backports-repos
- *test-install-all-libs - *test-install-all-libs
- *test-verify-libs - *test-verify-libs
except: except:
@@ -511,8 +531,20 @@ mysql-8.0 Sid to mariadb-10.8 upgrade:
- apt-get install -y procps mysql-server 'libmysqlc*' - apt-get install -y procps mysql-server 'libmysqlc*'
- *test-verify-initial - *test-verify-initial
- *test-install - *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 - 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 - *test-verify-final
variables: variables:
GIT_STRATEGY: none 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. # 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. # 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 stage: upgrade extras
needs: needs:
- job: build buster-backports - 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 # Verify installation of MariaDB built in this commit
- dpkg -l | grep -iE 'maria|mysql|galera' || true # List installed - dpkg -l | grep -iE 'maria|mysql|galera' || true # List installed
- mariadb --version # Client version - 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 - *test-verify-final
variables: variables:
GIT_STRATEGY: none GIT_STRATEGY: none
except: except:
variables: variables:
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ - $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: mariadb.org-10.5 to mariadb-10.8 upgrade:
stage: upgrade extras stage: upgrade extras
@@ -657,7 +684,7 @@ mariadb.org-10.5 to mariadb-10.8 upgrade:
# Verify installation of MariaDB built in this commit # Verify installation of MariaDB built in this commit
- dpkg -l | grep -iE 'maria|mysql|galera' || true # List installed - dpkg -l | grep -iE 'maria|mysql|galera' || true # List installed
- mariadb --version # Client version - 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 - *test-verify-final
variables: variables:
GIT_STRATEGY: none GIT_STRATEGY: none
@@ -768,7 +795,7 @@ mariadb.org-10.2 to mariadb-10.8 upgrade:
variables: variables:
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ - $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 stage: upgrade extras
needs: needs:
- job: build buster-backports - job: build buster-backports
@@ -799,7 +826,7 @@ mysql.com-5.7 to mariadb-10.8 upgrade:
variables: variables:
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ - $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 stage: upgrade extras
needs: needs:
- job: build buster-backports - 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/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_system_tables.sql *
very-long-line-length-in-source-file scripts/mysql_test_data_timezone.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/charsets/languages.html *
very-long-line-length-in-source-file sql/share/errmsg-utf8.txt * very-long-line-length-in-source-file sql/share/errmsg-utf8.txt *
# Very long test string # Very long test string

24
debian/tests/upstream vendored
View File

@@ -10,6 +10,8 @@ echo "Running test 'testsuite'"
set -e set -e
SKIP_TEST_LST="/tmp/skip-test.lst" SKIP_TEST_LST="/tmp/skip-test.lst"
ARCH=$(dpkg --print-architecture)
WORKDIR=$(mktemp -d) WORKDIR=$(mktemp -d)
trap 'rm -rf $WORKDIR $SKIP_TEST_LST' 0 INT QUIT ABRT PIPE TERM trap 'rm -rf $WORKDIR $SKIP_TEST_LST' 0 INT QUIT ABRT PIPE TERM
cd "$WORKDIR" cd "$WORKDIR"
@@ -22,16 +24,15 @@ echo "using tmpdir: $WORKDIR/tmp"
echo "Setting up skip-tests-list" 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 # Also use the arch specific skiplists if exist
for filename in /usr/share/mysql/mysql-test/unstable-tests.* if [ -f /usr/share/mysql/mysql-test/unstable-tests.$ARCH ]
do then
# Check for case that no files matched and glob is returned cat /usr/share/mysql/mysql-test/unstable-tests.$ARCH >> $SKIP_TEST_LST
[ -e "$filename" ] || continue fi
# Append file to the main skip test list file
cat "$filename" >> $SKIP_TEST_LST
done
# Skip tests that cannot run properly on ci.debian.net / autopkgtests.ubuntu.com # Skip tests that cannot run properly on ci.debian.net / autopkgtests.ubuntu.com
cat >> $SKIP_TEST_LST << EOF cat >> $SKIP_TEST_LST << EOF
@@ -48,7 +49,6 @@ main.mysqld--help : For unknown reason table-cache is 4000 instead of default 42
EOF EOF
fi fi
ARCH=$(dpkg --print-architecture)
if [ "$ARCH" = "s390x" ] if [ "$ARCH" = "s390x" ]
then then
echo "main.func_regexp_pcre : recursion fails on s390x https://bugs.launchpad.net/ubuntu/+source/mariadb-10.1/+bug/1723947" >> $SKIP_TEST_LST 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 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 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 cd /usr/share/mysql/mysql-test
echo "starting mysql-test-tun.pl..." echo "starting mysql-test-tun.pl..."
eatmydata perl -I. ./mysql-test-run.pl --suite=main \ eatmydata perl -I. ./mysql-test-run.pl --suite=main \

View File

@@ -1,3 +1,4 @@
RESET MASTER;
CREATE TEMPORARY SEQUENCE seq_1; CREATE TEMPORARY SEQUENCE seq_1;
XA START '3'; XA START '3';
CREATE TEMPORARY TABLE tmp_1(c INT); 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 # 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 # 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 # 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_binlog_format_mixed.inc
--source include/have_innodb.inc --source include/have_innodb.inc
RESET MASTER; # clear binlogs
# MDEV-22420 DDL on temporary object is prohibited when XA is in prepare state # MDEV-22420 DDL on temporary object is prohibited when XA is in prepare state
# Temporary sequnce may not be created within a transaction # Temporary sequnce may not be created within a transaction

View File

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

View File

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

View File

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

View File

@@ -3268,3 +3268,78 @@ a
This is db1.pkg1.p1 This is db1.pkg1.p1
DROP DATABASE db1; DROP DATABASE db1;
DROP DATABASE db2; 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 db1;
DROP DATABASE db2; 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/have_file_key_management_plugin.inc
-- source include/innodb_page_size_small.inc -- source include/innodb_page_size_small.inc
-- source include/innodb_checksum_algorithm.inc -- source include/innodb_checksum_algorithm.inc
-- source include/maybe_debug.inc
if (!$INNOCHECKSUM) { if (!$INNOCHECKSUM) {
--echo Need innochecksum binary --echo Need innochecksum binary
@@ -18,6 +19,10 @@ if (!$INNOCHECKSUM) {
--disable_query_log --disable_query_log
# This may be triggered on a slow system or one that lacks native AIO. # 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"); 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 --enable_query_log
let $checksum_algorithm = `SELECT @@innodb_checksum_algorithm`; let $checksum_algorithm = `SELECT @@innodb_checksum_algorithm`;
@@ -259,6 +264,15 @@ print FILE pack("H*", "c00lcafedeadb017");
close FILE or die "close"; close FILE or die "close";
EOF 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 -- disable_result_log
--error 1 --error 1
--exec $INNOCHECKSUM $t1_IBD --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 # MDEV-28327 InnoDB persistent statistics fail to update
# after bulk insert # 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; INSERT INTO t1 SELECT * FROM seq_1_to_4096;
# Wait till statistics update after bulk insert operation # Wait till statistics update after bulk insert operation
SELECT n_rows FROM mysql.innodb_table_stats WHERE TABLE_NAME="t1"; SELECT n_rows>=4000 FROM mysql.innodb_table_stats WHERE TABLE_NAME="t1";
n_rows n_rows>=4000
4096 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; DROP TABLE t1;
# End of 10.6 tests # End of 10.6 tests
# #
@@ -351,7 +370,7 @@ DROP TABLE t1, t2;
# MDEV-29801 Inconsistent ER_TOO_BIG_ROWSIZE during bulk # MDEV-29801 Inconsistent ER_TOO_BIG_ROWSIZE during bulk
# insert operation # 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; SET @format= @@innodb_default_row_format;
CREATE TABLE t1 (pk int primary key, c01 text, c02 text, c03 text, CREATE TABLE t1 (pk int primary key, c01 text, c02 text, c03 text,
c04 text, c05 text, c06 text, c07 text, c08 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 Table Op Msg_type Msg_text
test.t check status OK test.t check status OK
DROP TEMPORARY TABLE t; 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 # End of 10.6 tests

View File

@@ -1,5 +1,5 @@
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/innodb_page_size.inc
--source include/have_sequence.inc --source include/have_sequence.inc
--source include/maybe_debug.inc --source include/maybe_debug.inc
--source include/have_partition.inc --source include/have_partition.inc
@@ -199,15 +199,41 @@ DROP TABLE t;
--echo # MDEV-28327 InnoDB persistent statistics fail to update --echo # MDEV-28327 InnoDB persistent statistics fail to update
--echo # after bulk insert --echo # after bulk insert
--echo # --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; INSERT INTO t1 SELECT * FROM seq_1_to_4096;
--echo # Wait till statistics update after bulk insert operation --echo # Wait till statistics update after bulk insert operation
let $wait_condition= select n_rows > 100 from mysql.innodb_table_stats let $wait_condition= select n_rows > 100 from mysql.innodb_table_stats
where table_name="t1"; where table_name="t1";
source include/wait_condition.inc; 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; 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 # End of 10.6 tests
--echo # --echo #
@@ -363,13 +389,14 @@ DROP TABLE t1, t2;
--echo # MDEV-29801 Inconsistent ER_TOO_BIG_ROWSIZE during bulk --echo # MDEV-29801 Inconsistent ER_TOO_BIG_ROWSIZE during bulk
--echo # insert operation --echo # insert operation
--echo # --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; SET @format= @@innodb_default_row_format;
CREATE TABLE t1 (pk int primary key, c01 text, c02 text, c03 text, CREATE TABLE t1 (pk int primary key, c01 text, c02 text, c03 text,
c04 text, c05 text, c06 text, c07 text, c08 text, c04 text, c05 text, c06 text, c07 text, c08 text,
c09 text, c10 text, c11 text, c12 text) ENGINE=InnoDB; c09 text, c10 text, c11 text, c12 text) ENGINE=InnoDB;
SET GLOBAL INNODB_DEFAULT_ROW_FORMAT= COMPACT; SET GLOBAL INNODB_DEFAULT_ROW_FORMAT= COMPACT;
--replace_result 1982 8126 4030 8126
ALTER TABLE t1 FORCE; ALTER TABLE t1 FORCE;
INSERT IGNORE INTO t1 VALUES 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)), (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;
CHECK TABLE t EXTENDED; CHECK TABLE t EXTENDED;
DROP TEMPORARY TABLE t; 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 --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("Table was marked as crashed");
call mtr.add_suppression("Checking table: .*"); call mtr.add_suppression("Checking table: .*");
create table t1 (a int primary key auto_increment, b int) engine=aria transactional= 1; 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 # no-protocol doesn't print warnings about repaired tables
--source include/no_protocol.inc --source include/no_protocol.inc
reset master; # clear binlogs
call mtr.add_suppression("Table was marked as crashed"); call mtr.add_suppression("Table was marked as crashed");
call mtr.add_suppression("Checking table: .*"); call mtr.add_suppression("Checking table: .*");

View File

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

View File

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

View File

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

View File

@@ -96,6 +96,16 @@ with system versioning
partition by system_time ( partition by system_time (
partition p0 history, partition p0 history,
partition pn current); 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
alter table t1 add partition ( alter table t1 add partition (
partition p1 current); partition p1 current);
@@ -150,7 +160,7 @@ partition by system_time limit 1;
alter table t1 change x big int; alter table t1 change x big int;
create or replace table t1 (i int) engine myisam partition by hash(i) partitions 2; create or replace table t1 (i int) engine myisam partition by hash(i) partitions 2;
alter table t1 add partition (partition px history); 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 ## INSERT, UPDATE, DELETE
create or replace table t1 (x int) create or replace table t1 (x int)
with system versioning with system versioning
@@ -1105,7 +1115,7 @@ drop table t1;
create table t1 (a int) with system versioning partition by system_time create table t1 (a int) with system versioning partition by system_time
(partition p1 history, partition pn current); (partition p1 history, partition pn current);
alter table t1 add partition (partition p2); 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 # MDEV-17891 Assertion failures in select_insert::abort_result_set and
# mysql_load upon attempt to replace into a full table # mysql_load upon attempt to replace into a full table
set @@max_heap_table_size= 1024*1024; set @@max_heap_table_size= 1024*1024;

View File

@@ -106,6 +106,18 @@ partition by system_time (
partition p0 history, partition p0 history,
partition pn current); 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 --echo ## ALTER TABLE

View File

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

View File

@@ -429,8 +429,13 @@ public:
return NULL; return NULL;
} }
uint next_part_no(uint new_parts) const; 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); uint32 get_next_partition_id_range(struct st_partition_iter* part_iter);
bool check_partition_dirs(partition_info *part_info); 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" spa "Nunca debería vd de ver esto"
ER_PARTITION_WRONG_TYPE ER_PARTITION_WRONG_TYPE
chi "错误的分区类型,预期类型:%`s" chi "错误的分区类型,预期类型:%`s for partitioning by %`s"
eng "Wrong partitioning type, expected type: %`s" eng "Wrong partition type %`s for partitioning by %`s"
spa "Tipo de partición equivocada, tipo esperado: %`s" spa "Tipo de partición equivocada, tipo esperado: %`s for partitioning by %`s"
WARN_VERS_PART_FULL WARN_VERS_PART_FULL
chi "版本化表%`s.%`spartition%`s已满添加更多历史分区(out of %s)" 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) bool LEX::part_values_current(THD *thd)
{ {
partition_element *elem= part_info->curr_part_elem; 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)) 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; return true;
} }
} }
@@ -9788,7 +9789,7 @@ bool LEX::part_values_history(THD *thd)
{ {
if (unlikely(part_info->part_type != VERSIONING_PARTITION)) 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; return true;
} }
} }
@@ -9809,6 +9810,7 @@ bool LEX::part_values_history(THD *thd)
elem->type= partition_element::HISTORY; elem->type= partition_element::HISTORY;
return false; return false;
} }
#endif /* WITH_PARTITION_STORAGE_ENGINE */
bool LEX::last_field_generated_always_as_row_start_or_end(Lex_ident *p, 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 table_or_sp_used();
bool is_partition_management() const; bool is_partition_management() const;
#ifdef WITH_PARTITION_STORAGE_ENGINE
bool part_values_current(THD *thd); bool part_values_current(THD *thd);
bool part_values_history(THD *thd); bool part_values_history(THD *thd);
#endif
/** /**
@brief check if the statement is a single-level join @brief check if the statement is a single-level join

View File

@@ -2470,7 +2470,7 @@ end:
@retval != 0 Failure @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; int err= 0;
err+= str->append(STRING_WITH_LEN("KEY ")); 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; 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. Generate the partition syntax from the partition data structure.
Useful for support of generating defaults, SHOW CREATE TABLES 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"); DBUG_ENTER("generate_partition_syntax");
err+= str.append(STRING_WITH_LEN(" PARTITION BY ")); err+= str.append(STRING_WITH_LEN(" PARTITION BY "));
switch (part_info->part_type) int err2= part_info->gen_part_type(thd, &str);
{ if (err2 < 0)
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));
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
} err+= err2;
if (part_info->part_type == VERSIONING_PARTITION) if (part_info->part_type == VERSIONING_PARTITION)
{ {
Vers_part_info *vers_info= part_info->vers_info; 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 || else if (thd->work_part_info->part_type == VERSIONING_PARTITION ||
tab_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 else
{ {

View File

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

View File

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

View File

@@ -270,8 +270,7 @@ SET(INNOBASE_SOURCES
include/handler0alter.h include/handler0alter.h
include/hash0hash.h include/hash0hash.h
include/ibuf0ibuf.h include/ibuf0ibuf.h
include/ibuf0ibuf.inl/ include/ibuf0ibuf.inl
include/ibuf0types.h
include/lock0iter.h include/lock0iter.h
include/lock0lock.h include/lock0lock.h
include/lock0lock.inl include/lock0lock.inl
@@ -289,7 +288,6 @@ SET(INNOBASE_SOURCES
include/mem0mem.inl include/mem0mem.inl
include/mtr0log.h include/mtr0log.h
include/mtr0mtr.h include/mtr0mtr.h
include/mtr0mtr.inl
include/mtr0types.h include/mtr0types.h
include/os0file.h include/os0file.h
include/os0file.inl 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_t btr_pcur;
btr_pcur.pos_state = BTR_PCUR_IS_POSITIONED; btr_pcur.pos_state = BTR_PCUR_IS_POSITIONED;
btr_pcur.latch_mode = BTR_MODIFY_LEAF; 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.index = m_index;
btr_pcur.btr_cur.page_cur.rec = m_cur_rec; btr_pcur.btr_cur.page_cur.rec = m_cur_rec;
btr_pcur.btr_cur.page_cur.offsets = offsets; 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 */ @return whether the operation was interrupted */
bool btr_defragment_add_index(btr_pcur_t *pcur, THD *thd) 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_t cond;
pthread_cond_init(&cond, nullptr); pthread_cond_init(&cond, nullptr);
btr_defragment_item_t item(pcur, &cond); btr_defragment_item_t item(pcur, &cond);
@@ -209,7 +209,7 @@ btr_defragment_remove_table(
mysql_mutex_lock(&btr_defragment_mutex); mysql_mutex_lock(&btr_defragment_mutex);
for (auto item : btr_defragment_wq) 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); pthread_cond_signal(item->cond);
item->cond= nullptr; item->cond= nullptr;
@@ -405,7 +405,10 @@ btr_defragment_merge_pages(
} }
} }
btr_cur_t parent; 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; to_block = nullptr;
} else if (n_recs_to_move == n_recs) { } else if (n_recs_to_move == n_recs) {
/* The whole page is merged with the previous page, /* The whole page is merged with the previous page,
@@ -690,7 +693,7 @@ processed:
} }
log_free_check(); log_free_check();
mtr_start(&mtr); mtr_start(&mtr);
dict_index_t *index = item->pcur->btr_cur.index; dict_index_t *index = item->pcur->index();
index->set_modified(mtr); index->set_modified(mtr);
/* To follow the latching order defined in WL#6326, /* To follow the latching order defined in WL#6326,
acquire index->lock X-latch. This entitles us to 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 "rem0cmp.h"
#include "trx0trx.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 Resets a persistent cursor object, freeing ::old_rec_buf if it is
allocated and resetting the other members to their initial values. */ 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_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->old_rec_buf = NULL;
cursor->btr_cur.index = NULL;
cursor->btr_cur.page_cur.rec = NULL;
cursor->old_rec = NULL; cursor->old_rec = NULL;
cursor->old_n_core_fields = 0; cursor->old_n_core_fields = 0;
cursor->old_n_fields = 0; cursor->old_n_fields = 0;
cursor->old_stored = false;
cursor->latch_mode = BTR_NO_LATCHES; cursor->latch_mode = BTR_NO_LATCHES;
cursor->pos_state = BTR_PCUR_NOT_POSITIONED; 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 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 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_contains_flagged(&index->lock, MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK))); | MTR_MEMO_SX_LOCK)));
cursor->old_stored = true;
if (page_is_empty(block->page.frame)) { if (page_is_empty(block->page.frame)) {
/* It must be an empty index tree; NOTE that in this case /* It must be an empty index tree; NOTE that in this case
we do not store the modify_clock, but always do a search we do not store the modify_clock, but always do a search
@@ -256,11 +218,12 @@ otherwise. */
struct optimistic_latch_leaves struct optimistic_latch_leaves
{ {
btr_pcur_t *const cursor; btr_pcur_t *const cursor;
ulint *latch_mode; btr_latch_mode *latch_mode;
mtr_t *const mtr; mtr_t *const mtr;
optimistic_latch_leaves(btr_pcur_t *cursor, ulint *latch_mode, mtr_t *mtr) optimistic_latch_leaves(btr_pcur_t *cursor, btr_latch_mode *latch_mode,
:cursor(cursor), latch_mode(latch_mode), mtr(mtr) {} mtr_t *mtr)
: cursor(cursor), latch_mode(latch_mode), mtr(mtr) {}
bool operator() (buf_block_t *hint) const 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 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 */ the record with not the samebuniq field values as in the stored */
btr_pcur_t::restore_status 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; dict_index_t* index;
dtuple_t* tuple; dtuple_t* tuple;
@@ -301,7 +264,6 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
mem_heap_t* heap; mem_heap_t* heap;
ut_ad(mtr->is_active()); ut_ad(mtr->is_active());
//ut_ad(cursor->old_stored);
ut_ad(pos_state == BTR_PCUR_WAS_POSITIONED ut_ad(pos_state == BTR_PCUR_WAS_POSITIONED
|| pos_state == BTR_PCUR_IS_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, /* In these cases we do not try an optimistic restoration,
but always do a search */ but always do a search */
if (btr_cur_open_at_index_side( if (btr_cur.open_leaf(rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE, index, restore_latch_mode, mtr)
index, restore_latch_mode, != DB_SUCCESS) {
&btr_cur, 0, mtr) != DB_SUCCESS) {
return restore_status::CORRUPTED; 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_core_fields <= index->n_core_fields);
ut_a(old_n_fields); ut_a(old_n_fields);
switch (restore_latch_mode) { static_assert(BTR_SEARCH_PREV == (4 | BTR_SEARCH_LEAF), "");
case BTR_SEARCH_LEAF: static_assert(BTR_MODIFY_PREV == (4 | BTR_MODIFY_LEAF), "");
case BTR_MODIFY_LEAF:
switch (restore_latch_mode | 4) {
case BTR_SEARCH_PREV: case BTR_SEARCH_PREV:
case BTR_MODIFY_PREV: case BTR_MODIFY_PREV:
/* Try optimistic restoration. */ /* Try optimistic restoration. */
@@ -420,7 +382,7 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
mode = PAGE_CUR_UNSUPP; 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) { this, mtr) != DB_SUCCESS) {
mem_heap_free(heap); mem_heap_free(heap);
return restore_status::CORRUPTED; 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)); block_when_stored.store(btr_pcur_get_block(this));
modify_clock= buf_block_get_modify_clock( modify_clock= buf_block_get_modify_clock(
block_when_stored.block()); block_when_stored.block());
old_stored= true;
mem_heap_free(heap); mem_heap_free(heap);
@@ -487,7 +448,7 @@ btr_pcur_move_to_next_page(
ut_ad(cursor->latch_mode != BTR_NO_LATCHES); ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
ut_ad(btr_pcur_is_after_last_on_page(cursor)); 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 page_t* page = btr_pcur_get_page(cursor);
const uint32_t next_page_no = btr_page_get_next(page); const uint32_t next_page_no = btr_page_get_next(page);
@@ -515,7 +476,7 @@ btr_pcur_move_to_next_page(
dberr_t err; dberr_t err;
buf_block_t* next_block = btr_block_get( 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); page_is_leaf(page), mtr, &err);
if (UNIV_UNLIKELY(!next_block)) { if (UNIV_UNLIKELY(!next_block)) {
@@ -529,12 +490,13 @@ btr_pcur_move_to_next_page(
return DB_CORRUPTION; 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)); page_cur_set_before_first(next_block, btr_pcur_get_page_cur(cursor));
ut_d(page_check_dir(next_page)); 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)) 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_on_page(cursor));
ut_ad(!btr_pcur_is_before_first_in_tree(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); ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF);
btr_pcur_store_position(cursor, mtr); 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_SEARCH_PREV == (4 | BTR_SEARCH_LEAF), "");
static_assert(BTR_MODIFY_PREV == (4 | BTR_MODIFY_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)) { == btr_pcur_t::CORRUPTED)) {
return true; 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))) { if (!page_has_prev(btr_pcur_get_page(cursor))) {
} else if (btr_pcur_is_before_first_on_page(cursor)) { } else if (btr_pcur_is_before_first_on_page(cursor)) {
btr_leaf_page_release(btr_pcur_get_block(cursor), release_block = btr_pcur_get_block(cursor);
latch_mode, mtr); page_cur_set_after_last(cursor->btr_cur.left_block,
page_cur_set_after_last(prev_block,
btr_pcur_get_page_cur(cursor)); btr_pcur_get_page_cur(cursor));
} else { } else {
/* The repositioned cursor did not end on an infimum /* The repositioned cursor did not end on an infimum
record on a page. Cursor repositioning acquired a latch record on a page. Cursor repositioning acquired a latch
also on the previous page, but we do not need the latch: also on the previous page, but we do not need the latch:
release it. */ release it. */
prev_block = btr_pcur_get_btr_cur(cursor)->left_block; release_block = cursor->btr_cur.left_block;
btr_leaf_page_release(prev_block, latch_mode, mtr);
} }
cursor->latch_mode = latch_mode; cursor->latch_mode = latch_mode;
cursor->old_stored = false; cursor->old_rec = nullptr;
if (release_block) {
mtr->release(*release_block);
}
return false; return false;
} }
@@ -612,7 +575,7 @@ btr_pcur_move_to_prev(
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES); 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)) { if (btr_pcur_is_before_first_on_page(cursor)) {
return (!btr_pcur_is_before_first_in_tree(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 */ @param[in] cursor cursor which was just positioned */
static void btr_search_info_update_hash(btr_search_t *info, btr_cur_t *cursor) 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; int cmp;
if (dict_index_is_ibuf(index)) { if (dict_index_is_ibuf(index)) {
@@ -704,14 +704,14 @@ btr_search_update_hash_ref(
return; return;
} }
if (index != cursor->index) { if (index != cursor->index()) {
ut_ad(index->id == cursor->index->id); ut_ad(index->id == cursor->index()->id);
btr_search_drop_page_hash_index(block); btr_search_drop_page_hash_index(block);
return; return;
} }
ut_ad(block->page.id().space() == index->table->space_id); 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)); ut_ad(!dict_index_is_ibuf(index));
auto part = btr_search_sys.get_part(*index); auto part = btr_search_sys.get_part(*index);
part->latch.wr_lock(SRW_LOCK_CALL); part->latch.wr_lock(SRW_LOCK_CALL);
@@ -784,7 +784,7 @@ btr_search_check_guess(
bool success = false; bool success = false;
rec_offs_init(offsets_); 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); rec = btr_cur_get_rec(cursor);
@@ -792,7 +792,7 @@ btr_search_check_guess(
|| !page_rec_is_leaf(rec))) { || !page_rec_is_leaf(rec))) {
ut_ad("corrupted index" == 0); ut_ad("corrupted index" == 0);
return false; return false;
} else if (cursor->index->table->not_redundant()) { } else if (cursor->index()->table->not_redundant()) {
switch (rec_get_status(rec)) { switch (rec_get_status(rec)) {
case REC_STATUS_INSTANT: case REC_STATUS_INSTANT:
case REC_STATUS_ORDINARY: case REC_STATUS_ORDINARY:
@@ -805,10 +805,10 @@ btr_search_check_guess(
match = 0; match = 0;
offsets = rec_get_offsets(rec, cursor->index, offsets, offsets = rec_get_offsets(rec, cursor->index(), offsets,
cursor->index->n_core_fields, cursor->index()->n_core_fields,
n_unique, &heap); 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); &match);
if (mode == PAGE_CUR_GE) { if (mode == PAGE_CUR_GE) {
@@ -860,7 +860,7 @@ btr_search_check_guess(
goto exit_func; goto exit_func;
} }
if (cursor->index->table->not_redundant()) { if (cursor->index()->table->not_redundant()) {
switch (rec_get_status(prev_rec)) { switch (rec_get_status(prev_rec)) {
case REC_STATUS_INSTANT: case REC_STATUS_INSTANT:
case REC_STATUS_ORDINARY: case REC_STATUS_ORDINARY:
@@ -871,11 +871,12 @@ btr_search_check_guess(
} }
} }
offsets = rec_get_offsets(prev_rec, cursor->index, offsets, offsets = rec_get_offsets(prev_rec, cursor->index(), offsets,
cursor->index->n_core_fields, cursor->index()->n_core_fields,
n_unique, &heap); n_unique, &heap);
cmp = cmp_dtuple_rec_with_match( cmp = cmp_dtuple_rec_with_match(tuple, prev_rec,
tuple, prev_rec, cursor->index, offsets, &match); cursor->index(), offsets,
&match);
if (mode == PAGE_CUR_GE) { if (mode == PAGE_CUR_GE) {
success = cmp > 0; success = cmp > 0;
} else { } else {
@@ -900,7 +901,7 @@ btr_search_check_guess(
goto exit_func; goto exit_func;
} }
if (cursor->index->table->not_redundant()) { if (cursor->index()->table->not_redundant()) {
switch (rec_get_status(next_rec)) { switch (rec_get_status(next_rec)) {
case REC_STATUS_INSTANT: case REC_STATUS_INSTANT:
case REC_STATUS_ORDINARY: case REC_STATUS_ORDINARY:
@@ -911,11 +912,11 @@ btr_search_check_guess(
} }
} }
offsets = rec_get_offsets(next_rec, cursor->index, offsets, offsets = rec_get_offsets(next_rec, cursor->index(), offsets,
cursor->index->n_core_fields, cursor->index()->n_core_fields,
n_unique, &heap); n_unique, &heap);
cmp = cmp_dtuple_rec_with_match( 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) { if (mode == PAGE_CUR_LE) {
success = cmp < 0; success = cmp < 0;
cursor->up_match = match; cursor->up_match = match;
@@ -1099,16 +1100,16 @@ btr_search_guess_on_hash(
part->latch.rd_lock(SRW_LOCK_CALL); part->latch.rd_lock(SRW_LOCK_CALL);
if (!btr_search_enabled) { if (!btr_search_enabled) {
goto fail; goto ahi_release_and_fail;
} }
rec = static_cast<const rec_t*>( rec = static_cast<const rec_t*>(
ha_search_and_get_data(&part->table, fold)); ha_search_and_get_data(&part->table, fold));
if (!rec) { if (!rec) {
fail: ahi_release_and_fail:
part->latch.rd_unlock(); part->latch.rd_unlock();
fail:
btr_search_failure(info, cursor); btr_search_failure(info, cursor);
return false; return false;
} }
@@ -1117,66 +1118,52 @@ fail:
buf_pool_t::hash_chain& chain = buf_pool.page_hash.cell_get( buf_pool_t::hash_chain& chain = buf_pool.page_hash.cell_get(
block->page.id().fold()); block->page.id().fold());
bool fail, got_latch; bool got_latch;
{ {
transactional_shared_lock_guard<page_hash_latch> g{ transactional_shared_lock_guard<page_hash_latch> g{
buf_pool.page_hash.lock_get(chain)}; 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) got_latch = (latch_mode == BTR_SEARCH_LEAF)
? block->page.lock.s_lock_try() ? block->page.lock.s_lock_try()
: block->page.lock.x_lock_try(); : block->page.lock.x_lock_try();
} }
ut_a(!fail || block->index->freed());
if (!got_latch) { 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.fix();
block->page.set_accessed(); block->page.set_accessed();
buf_page_make_young_if_needed(&block->page); 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_S_FIX} == ulint{BTR_SEARCH_LEAF},
""); "");
static_assert(ulint{MTR_MEMO_PAGE_X_FIX} == ulint{BTR_MODIFY_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(); part->latch.rd_unlock();
if (UNIV_UNLIKELY(fail)) { ++buf_pool.stat.n_page_gets;
goto fail_and_release_page;
}
DBUG_ASSERT(!block->page.is_freed()); mtr->memo_push(block, mtr_memo_type_t(latch_mode));
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;
}
ut_ad(page_rec_is_user_rec(rec)); ut_ad(page_rec_is_user_rec(rec));
@@ -1191,7 +1178,8 @@ fail_and_release_page:
right. */ right. */
if (index_id != btr_page_get_index_id(block->page.frame) if (index_id != btr_page_get_index_id(block->page.frame)
|| !btr_search_check_guess(cursor, false, tuple, mode)) { || !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) { if (info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5) {
@@ -1199,41 +1187,6 @@ fail_and_release_page:
info->n_hash_potential++; 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; info->last_hash_succ = TRUE;
#ifdef UNIV_SEARCH_PERF_STAT #ifdef UNIV_SEARCH_PERF_STAT
@@ -1691,7 +1644,7 @@ exit_func:
@param[in,out] cursor cursor which was just positioned */ @param[in,out] cursor cursor which was just positioned */
void btr_search_info_update_slow(btr_search_t *info, btr_cur_t *cursor) 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; ->latch;
buf_block_t* block = btr_cur_get_block(cursor); 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)) { 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) { 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. /* Note that since we did not protect block->n_fields etc.
with any semaphore, the values can be inconsistent. We have with any semaphore, the values can be inconsistent. We have
to check inside the function call that they make sense. */ 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, ahi_latch,
block->n_fields, block->n_fields,
block->n_bytes, block->n_bytes,
@@ -1835,15 +1788,15 @@ void btr_search_update_hash_on_delete(btr_cur_t *cursor)
return; 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); btr_search_drop_page_hash_index(block);
return; return;
} }
ut_ad(block->page.id().space() == index->table->space_id); 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_a(block->curr_n_fields > 0 || block->curr_n_bytes > 0);
ut_ad(!dict_index_is_ibuf(index)); 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; dict_index_t* index;
rec_t* rec; 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) { if (!btr_search_enabled) {
return; return;
@@ -1909,15 +1862,15 @@ void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
return; return;
} }
ut_ad(!cursor->index->table->is_temporary()); ut_ad(!cursor->index()->table->is_temporary());
if (index != cursor->index) { if (index != cursor->index()) {
ut_ad(index->id == cursor->index->id); ut_ad(index->id == cursor->index()->id);
btr_search_drop_page_hash_index(block); btr_search_drop_page_hash_index(block);
return; return;
} }
ut_a(cursor->index == index); ut_a(cursor->index() == index);
ut_ad(!dict_index_is_ibuf(index)); ut_ad(!dict_index_is_ibuf(index));
ahi_latch->wr_lock(SRW_LOCK_CALL); 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) { && !block->curr_left_side) {
if (const rec_t *new_rec = page_rec_get_next_const(rec)) { if (const rec_t *new_rec = page_rec_get_next_const(rec)) {
if (ha_search_and_update_if_found( if (ha_search_and_update_if_found(
&btr_search_sys.get_part(*cursor->index) &btr_search_sys.get_part(*cursor->index())
->table, ->table,
cursor->fold, rec, block, new_rec)) { cursor->fold, rec, block, new_rec)) {
MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_UPDATED); 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* offsets = offsets_;
rec_offs_init(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))); ut_ad(page_is_leaf(btr_cur_get_page(cursor)));
if (!btr_search_enabled) { 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); rec = btr_cur_get_rec(cursor);
ut_ad(!cursor->index->table->is_temporary()); ut_ad(!cursor->index()->table->is_temporary());
if (index != cursor->index) { if (index != cursor->index()) {
ut_ad(index->id == cursor->index->id); ut_ad(index->id == cursor->index()->id);
drop: drop:
btr_search_drop_page_hash_index(block); btr_search_drop_page_hash_index(block);
return; return;
} }
ut_a(index == cursor->index); ut_a(index == cursor->index());
ut_ad(!dict_index_is_ibuf(index)); ut_ad(!dict_index_is_ibuf(index));
n_fields = block->curr_n_fields; 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, DBUG_PRINT("ib_log", ("checkpoint ended at " LSN_PF ", flushed to " LSN_PF,
next_checkpoint_lsn, get_flushed_lsn())); 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(); 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 record from a previous fil_names_clear() call, which we must
write out before we can advance the checkpoint. */ write out before we can advance the checkpoint. */
log_write_up_to(sync_lsn, true); log_write_up_to(sync_lsn, true);
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", return;);
log_checkpoint(); log_checkpoint();
} }
} }
@@ -1898,6 +1907,8 @@ ATTRIBUTE_COLD void buf_flush_ahead(lsn_t lsn, bool furious)
if (recv_recovery_is_on()) if (recv_recovery_is_on())
recv_sys.apply(true); recv_sys.apply(true);
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", return;);
Atomic_relaxed<lsn_t> &limit= furious Atomic_relaxed<lsn_t> &limit= furious
? buf_flush_sync_lsn : buf_flush_async_lsn; ? buf_flush_sync_lsn : buf_flush_async_lsn;
@@ -2252,6 +2263,7 @@ unemployed:
buf_pool.page_cleaner_set_idle(true); buf_pool.page_cleaner_set_idle(true);
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", continue;); 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); mysql_mutex_unlock(&buf_pool.flush_list_mutex);
@@ -2335,6 +2347,7 @@ do_checkpoint:
here should not affect correctness, because log_free_check() here should not affect correctness, because log_free_check()
should still be invoking checkpoints when needed. */ should still be invoking checkpoints when needed. */
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", goto next;); 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) if (!recv_recovery_is_on() && srv_operation == SRV_OPERATION_NORMAL)
log_checkpoint(); log_checkpoint();

View File

@@ -755,11 +755,12 @@ dict_create_index_tree_step(
search_tuple = dict_create_search_tuple(node->ind_row, node->heap); search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
node->page_no = FIL_NULL; node->page_no = FIL_NULL;
pcur.btr_cur.page_cur.index =
UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes);
dberr_t err = dberr_t err =
btr_pcur_open(UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes), btr_pcur_open(search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF, &pcur, 0, &mtr);
&pcur, &mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
func_exit: 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); dfield_set_data(dfield, buf, 8);
dict_index_copy_types(tuple, sys_index, 2); 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) BTR_MODIFY_LEAF, &cursor, &mtr)
!= DB_SUCCESS) { != DB_SUCCESS) {
goto fail; goto fail;
@@ -4222,8 +4223,9 @@ dict_index_set_merge_threshold(
dfield_set_data(dfield, buf, 8); dfield_set_data(dfield, buf, 8);
dict_index_copy_types(tuple, sys_index, 2); 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) BTR_MODIFY_LEAF, &cursor, &mtr)
!= DB_SUCCESS) { != DB_SUCCESS) {
goto func_exit; goto func_exit;

View File

@@ -215,8 +215,9 @@ dict_startscan_system(
mtr_t* mtr, /*!< in: the mini-transaction */ mtr_t* mtr, /*!< in: the mini-transaction */
dict_table_t* table) /*!< in: system table */ dict_table_t* table) /*!< in: system table */
{ {
if (btr_pcur_open_at_index_side(true, table->indexes.start, BTR_SEARCH_LEAF, btr_pcur_init(pcur);
pcur, true, 0, mtr) != DB_SUCCESS) if (pcur->open_leaf(true, table->indexes.start, BTR_SEARCH_LEAF, mtr) !=
DB_SUCCESS)
return nullptr; return nullptr;
const rec_t *rec; const rec_t *rec;
do 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); mach_write_to_8(table_id, table->id);
dfield_set_data(&dfield, table_id, 8); dfield_set_data(&dfield, table_id, 8);
dict_index_copy_types(&tuple, sys_index, 1); 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); BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
goto func_exit; 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); dfield_set_data(&dfield[1], vcol_pos, 4);
dict_index_copy_types(&tuple, sys_virtual_index, 2); 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, dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr); BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
goto func_exit; 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); mach_write_to_8(index_id, index->id);
dfield_set_data(&dfield, index_id, 8); dfield_set_data(&dfield, index_id, 8);
dict_index_copy_types(&tuple, sys_index, 1); 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, PAGE_CUR_GE, BTR_SEARCH_LEAF,
&pcur, &mtr); &pcur, &mtr);
if (error != DB_SUCCESS) { 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); mach_write_to_8(table_id, table->id);
dfield_set_data(&dfield, table_id, 8); dfield_set_data(&dfield, table_id, 8);
dict_index_copy_types(&tuple, sys_index, 1); 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, PAGE_CUR_GE, BTR_SEARCH_LEAF,
&pcur, &mtr); &pcur, &mtr);
if (error != DB_SUCCESS) { 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()); dfield_set_data(&dfield, name.data(), name.size());
dict_index_copy_types(&tuple, sys_index, 1); dict_index_copy_types(&tuple, sys_index, 1);
pcur.btr_cur.page_cur.index = sys_index;
bool uncommitted = false; bool uncommitted = false;
reload: reload:
mtr.start(); 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); BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS || !btr_pcur_is_on_user_rec(&pcur)) { 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); mach_write_to_8(id_buf, table_id);
dfield_set_data(&dfield, id_buf, 8); dfield_set_data(&dfield, id_buf, 8);
dict_index_copy_types(&tuple, sys_table_ids, 1); dict_index_copy_types(&tuple, sys_table_ids, 1);
pcur.btr_cur.page_cur.index = sys_table_ids;
dict_table_t* table = nullptr; 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) BTR_SEARCH_LEAF, &pcur, &mtr)
== DB_SUCCESS == DB_SUCCESS
&& btr_pcur_is_on_user_rec(&pcur)) { && 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); dfield_set_data(&dfield, foreign->id, id_len);
dict_index_copy_types(&tuple, sys_index, 1); dict_index_copy_types(&tuple, sys_index, 1);
pcur.btr_cur.page_cur.index = sys_index;
mem_heap_t* heap = nullptr; 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); BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
goto func_exit; goto func_exit;
@@ -2877,11 +2884,12 @@ dict_load_foreign(
}; };
dfield_set_data(&dfield, id.data(), id.size()); dfield_set_data(&dfield, id.data(), id.size());
dict_index_copy_types(&tuple, sys_index, 1); dict_index_copy_types(&tuple, sys_index, 1);
pcur.btr_cur.page_cur.index = sys_index;
mtr.start(); mtr.start();
mem_heap_t* heap = nullptr; 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); BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
goto err_exit; goto err_exit;
@@ -3090,8 +3098,9 @@ start_load:
mtr.start(); mtr.start();
dfield_set_data(&dfield, table_name, strlen(table_name)); dfield_set_data(&dfield, table_name, strlen(table_name));
dict_index_copy_types(&tuple, sec_index, 1); 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); BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
DBUG_RETURN(err); DBUG_RETURN(err);
@@ -3192,7 +3201,6 @@ next_rec:
load_next_index: load_next_index:
mtr.commit(); mtr.commit();
ut_free(pcur.old_rec_buf);
if ((sec_index = dict_table_get_next_index(sec_index))) { if ((sec_index = dict_table_get_next_index(sec_index))) {
/* Switch to scan index on REF_NAME, fk_max_recusive_level /* Switch to scan index on REF_NAME, fk_max_recusive_level
@@ -3202,5 +3210,6 @@ load_next_index:
goto start_load; goto start_load;
} }
ut_free(pcur.old_rec_buf);
DBUG_RETURN(DB_SUCCESS); DBUG_RETURN(DB_SUCCESS);
} }

View File

@@ -1560,6 +1560,96 @@ empty_table:
return err; 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 /* @{ Pseudo code about the relation between the following functions
let N = N_SAMPLE_PAGES(index) 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", DEBUG_PRINTF(" %s(table=%s, index=%s, level=" ULINTPF ")\n",
__func__, index->table->name, index->name, level); __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); 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 /* Position pcur on the leftmost record on the leftmost page
on the desired level. */ on the desired level. */
if (btr_pcur_open_at_index_side( if (btr_pcur_open_level(&pcur, level, mtr, index) != DB_SUCCESS
true, index, BTR_SEARCH_TREE_ALREADY_S_LATCHED,
&pcur, true, level, mtr) != DB_SUCCESS
|| !btr_pcur_move_to_next_on_page(&pcur)) { || !btr_pcur_move_to_next_on_page(&pcur)) {
goto func_exit; goto func_exit;
} }
@@ -1661,21 +1750,10 @@ dict_stats_analyze_index_level(
/* The page must not be empty, except when /* The page must not be empty, except when
it is the root page (and the whole index is empty). */ 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_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 = NULL;
prev_rec_is_copied = false; 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( if (REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
btr_pcur_get_rec(&pcur), page_is_comp(page))) { btr_pcur_get_rec(&pcur), page_is_comp(page))) {
ut_ad(btr_pcur_is_on_user_rec(&pcur)); ut_ad(btr_pcur_is_on_user_rec(&pcur));
@@ -1728,10 +1806,7 @@ dict_stats_analyze_index_level(
if (level == 0 if (level == 0
&& !srv_stats_include_delete_marked && !srv_stats_include_delete_marked
&& rec_get_deleted_flag( && rec_get_deleted_flag(rec, page_rec_is_comp(rec))) {
rec,
page_is_comp(btr_pcur_get_page(&pcur)))) {
if (rec_is_last_on_page if (rec_is_last_on_page
&& !prev_rec_is_copied && !prev_rec_is_copied
&& prev_rec != NULL) { && prev_rec != NULL) {
@@ -1811,7 +1886,7 @@ dict_stats_analyze_index_level(
records on this level at some point we will jump from records on this level at some point we will jump from
one page to the next and then rec and prev_rec will one page to the next and then rec and prev_rec will
be on different pages and 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 */ latch on the page that prev_rec is on */
prev_rec = rec_copy_prefix_to_buf( prev_rec = rec_copy_prefix_to_buf(
rec, index, n_uniq, rec, index, n_uniq,
@@ -1820,7 +1895,7 @@ dict_stats_analyze_index_level(
} else { } else {
/* still on the same page, the next call to /* 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 on the next page, we can simply assign pointers
instead of copying the records like above */ instead of copying the records like above */
@@ -1891,7 +1966,6 @@ dict_stats_analyze_index_level(
} }
#endif /* UNIV_STATS_DEBUG */ #endif /* UNIV_STATS_DEBUG */
btr_leaf_page_release(btr_pcur_get_block(&pcur), BTR_SEARCH_LEAF, mtr);
func_exit: func_exit:
ut_free(prev_rec_buf); ut_free(prev_rec_buf);
mem_heap_free(heap); mem_heap_free(heap);
@@ -2280,7 +2354,6 @@ dict_stats_analyze_index_for_n_prefix(
n_prefix, n_diff_data->n_diff_on_level); n_prefix, n_diff_data->n_diff_on_level);
#endif #endif
ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK));
ut_ad(n_diff_data->level); ut_ad(n_diff_data->level);
/* Position pcur on the leftmost record on the leftmost page /* 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_diff_all_analyzed_pages = 0;
n_diff_data->n_external_pages_sum = 0; n_diff_data->n_external_pages_sum = 0;
if (btr_pcur_open_at_index_side(true, index, if (btr_pcur_open_level(&pcur, n_diff_data->level, mtr, index)
BTR_SEARCH_TREE_ALREADY_S_LATCHED,
&pcur, true, n_diff_data->level, mtr)
!= DB_SUCCESS != DB_SUCCESS
|| !btr_pcur_move_to_next_on_page(&pcur)) { || !btr_pcur_move_to_next_on_page(&pcur)) {
return; return;
@@ -2680,6 +2751,7 @@ empty_index:
mtr.commit(); mtr.commit();
mtr.start(); mtr.start();
mtr_sx_lock_index(index, &mtr); mtr_sx_lock_index(index, &mtr);
ut_ad(mtr.get_savepoint() == 1);
buf_block_t *root = btr_root_block_get(index, RW_S_LATCH, buf_block_t *root = btr_root_block_get(index, RW_S_LATCH,
&mtr, &err); &mtr, &err);
if (!root || root_level != btr_page_get_level(root->page.frame) if (!root || root_level != btr_page_get_level(root->page.frame)
@@ -2695,7 +2767,7 @@ empty_index:
break; break;
} }
mtr.memo_release(root, MTR_MEMO_PAGE_S_FIX); mtr.rollback_to_savepoint(1);
/* check whether we should pick the current level; /* check whether we should pick the current level;
we pick level 1 even if it does not have enough we pick level 1 even if it does not have enough
@@ -2757,6 +2829,7 @@ empty_index:
break; break;
} }
mtr.rollback_to_savepoint(1);
dict_stats_analyze_index_level(index, dict_stats_analyze_index_level(index,
level, level,
n_diff_on_level, n_diff_on_level,
@@ -2764,7 +2837,7 @@ empty_index:
&total_pages, &total_pages,
n_diff_boundaries, n_diff_boundaries,
&mtr); &mtr);
mtr.rollback_to_savepoint(1);
level_is_analyzed = true; level_is_analyzed = true;
if (level == 1 if (level == 1

View File

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

View File

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

View File

@@ -70,7 +70,7 @@ rtr_page_split_initialize_nodes(
block = btr_cur_get_block(cursor); block = btr_cur_get_block(cursor);
page = buf_block_get_frame(block); 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; 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)); rec = page_rec_get_next(page_get_infimum_rec(page));
const ulint n_core = page_is_leaf(page) const ulint n_core = page_is_leaf(page)
? cursor->index->n_core_fields : 0; ? cursor->index()->n_core_fields : 0;
*offsets = rec_get_offsets(rec, cursor->index, *offsets, n_core, *offsets = rec_get_offsets(rec, cursor->index(), *offsets, n_core,
n_uniq, &heap); n_uniq, &heap);
source_cur = rec_get_nth_field(rec, *offsets, 0, &len); 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); memcpy(cur->coords, source_cur, DATA_MBR_LEN);
rec = page_rec_get_next(rec); 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); n_core, n_uniq, &heap);
source_cur = rec_get_nth_field(rec, *offsets, 0, &len); 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))); dtuple_get_nth_field(tuple, 0)));
cur->coords = reserve_coords(buf_pos, SPDIMS); cur->coords = reserve_coords(buf_pos, SPDIMS);
rec = (byte*) mem_heap_alloc( 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; cur->key = rec;
memcpy(cur->coords, source_cur, DATA_MBR_LEN); memcpy(cur->coords, source_cur, DATA_MBR_LEN);
@@ -200,7 +200,7 @@ rtr_update_mbr_field(
rec_t* new_rec, /*!< in: rec to use */ rec_t* new_rec, /*!< in: rec to use */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
dict_index_t* index = cursor->index; dict_index_t* index = cursor->index();
mem_heap_t* heap; mem_heap_t* heap;
page_t* page; page_t* page;
rec_t* rec; 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 /* We need to remember the child page no of cursor2, since page could be
reorganized or insert a new rec before it. */ reorganized or insert a new rec before it. */
if (cursor2) { if (cursor2) {
ut_ad(cursor2->index() == index);
rec_t* del_rec = btr_cur_get_rec(cursor2); rec_t* del_rec = btr_cur_get_rec(cursor2);
offsets2 = rec_get_offsets(btr_cur_get_rec(cursor2), offsets2 = rec_get_offsets(btr_cur_get_rec(cursor2),
index, NULL, 0, index, NULL, 0,
@@ -268,7 +269,7 @@ rtr_update_mbr_field(
if (!btr_cur_update_alloc_zip( if (!btr_cur_update_alloc_zip(
page_zip, page_zip,
btr_cur_get_page_cur(cursor), btr_cur_get_page_cur(cursor),
index, offsets, offsets,
rec_offs_size(offsets), rec_offs_size(offsets),
false, mtr)) { false, mtr)) {
@@ -321,7 +322,7 @@ rtr_update_mbr_field(
offsets2)); offsets2));
page_cur_delete_rec(btr_cur_get_page_cur(cursor2), page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
index, offsets2, mtr); offsets2, mtr);
} }
} else if (page_get_n_recs(page) == 1) { } else if (page_get_n_recs(page) == 1) {
/* When there's only one rec in the page, we do insert/delete to /* 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); ut_ad(old_rec != insert_rec);
page_cur_position(old_rec, block, &page_cur); page_cur_position(old_rec, block, &page_cur);
page_cur.index = index;
offsets2 = rec_get_offsets(old_rec, index, NULL, n_core, offsets2 = rec_get_offsets(old_rec, index, NULL, n_core,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
page_cur_delete_rec(&page_cur, index, offsets2, mtr); page_cur_delete_rec(&page_cur, offsets2, mtr);
} else { } else {
update_mbr: update_mbr:
@@ -366,8 +368,7 @@ update_mbr:
/* Delete the rec which cursor point to. */ /* Delete the rec which cursor point to. */
next_rec = page_rec_get_next(rec); next_rec = page_rec_get_next(rec);
page_cur_delete_rec(btr_cur_get_page_cur(cursor), page_cur_delete_rec(&cursor->page_cur, offsets, mtr);
index, offsets, mtr);
if (!ins_suc) { if (!ins_suc) {
ut_ad(rec_info & REC_INFO_MIN_REC_FLAG); ut_ad(rec_info & REC_INFO_MIN_REC_FLAG);
@@ -400,13 +401,12 @@ update_mbr:
== btr_node_ptr_get_child_page_no(cur2_rec, == btr_node_ptr_get_child_page_no(cur2_rec,
offsets2)); offsets2));
page_cur_delete_rec(btr_cur_get_page_cur(cursor2), page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
index, offsets2, mtr); offsets2, mtr);
cursor2 = NULL; cursor2 = NULL;
} }
/* Insert the new rec. */ /* Insert the new rec. */
if (page_cur_search_with_match(block, index, node_ptr, if (page_cur_search_with_match(node_ptr, PAGE_CUR_LE,
PAGE_CUR_LE,
&up_match, &low_match, &up_match, &low_match,
btr_cur_get_page_cur(cursor), btr_cur_get_page_cur(cursor),
NULL)) { NULL)) {
@@ -424,7 +424,7 @@ update_mbr:
} else if (ins_suc) { } else if (ins_suc) {
ut_ad(err == DB_FAIL); ut_ad(err == DB_FAIL);
err = btr_page_reorganize(btr_cur_get_page_cur(cursor), err = btr_page_reorganize(btr_cur_get_page_cur(cursor),
index, mtr); mtr);
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
err = btr_cur_optimistic_insert( err = btr_cur_optimistic_insert(
flags, cursor, &insert_offsets, &heap, flags, cursor, &insert_offsets, &heap,
@@ -505,7 +505,7 @@ update_mbr:
ut_ad(cur2_pno == del_page_no && cur2_rec != insert_rec); ut_ad(cur2_pno == del_page_no && cur2_rec != insert_rec);
page_cur_delete_rec(btr_cur_get_page_cur(cursor2), page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
index, offsets2, mtr); offsets2, mtr);
} }
if (!ins_suc) { if (!ins_suc) {
@@ -556,7 +556,6 @@ rtr_adjust_upper_level(
{ {
ulint page_no; ulint page_no;
ulint new_page_no; ulint new_page_no;
dict_index_t* index = sea_cur->index;
btr_cur_t cursor; btr_cur_t cursor;
rec_offs* offsets; rec_offs* offsets;
mem_heap_t* heap; mem_heap_t* heap;
@@ -570,9 +569,10 @@ rtr_adjust_upper_level(
/* Create a memory heap where the data tuple is stored */ /* Create a memory heap where the data tuple is stored */
heap = mem_heap_create(1024); heap = mem_heap_create(1024);
cursor.init();
cursor.thr = sea_cur->thr; cursor.thr = sea_cur->thr;
cursor.page_cur.index = sea_cur->index();
cursor.page_cur.block = block;
/* Get the level of the split pages */ /* Get the level of the split pages */
level = btr_page_get_level(buf_block_get_frame(block)); 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. */ /* Set new mbr for the old page on the upper level. */
/* Look up the index for the node pointer to page */ /* Look up the index for the node pointer to page */
offsets = rtr_page_get_father_block( offsets = rtr_page_get_father_block(NULL, heap, mtr, sea_cur, &cursor);
NULL, heap, index, block, mtr, sea_cur, &cursor);
page_cursor = btr_cur_get_page_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))) { page_get_infimum_rec(new_block->page.frame))) {
/* Insert the node for the new page. */ /* Insert the node for the new page. */
node_ptr_upper = rtr_index_build_node_ptr( 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; ulint up_match = 0, low_match = 0;
err = page_cur_search_with_match(btr_cur_get_block(&cursor), err = page_cur_search_with_match(node_ptr_upper,
index, node_ptr_upper,
PAGE_CUR_LE, PAGE_CUR_LE,
&up_match, &low_match, &up_match, &low_match,
btr_cur_get_page_cur(&cursor), btr_cur_get_page_cur(&cursor),
@@ -660,7 +658,7 @@ rtr_adjust_upper_level(
mem_heap_free(heap); 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) { if (err != DB_SUCCESS) {
return err; return err;
@@ -670,7 +668,7 @@ rtr_adjust_upper_level(
if (next_page_no == FIL_NULL) { if (next_page_no == FIL_NULL) {
} else if (buf_block_t* next_block = } 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)) { false, mtr, &err)) {
if (UNIV_UNLIKELY(memcmp_aligned<4>(next_block->page.frame if (UNIV_UNLIKELY(memcmp_aligned<4>(next_block->page.frame
+ FIL_PAGE_PREV, + 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(block, &page_cursor);
page_cur_set_before_first(new_block, &new_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); page = buf_block_get_frame(block);
new_page = buf_block_get_frame(new_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( rec = page_cur_insert_rec_low(
&new_page_cursor, &new_page_cursor,
index, cur_split_node->key, offsets, mtr); cur_split_node->key, offsets, mtr);
if (UNIV_UNLIKELY if (UNIV_UNLIKELY
(!rec (!rec
@@ -841,8 +840,7 @@ rtr_split_page_move_rec_list(
page_cur_get_rec(&page_cursor), index, page_cur_get_rec(&page_cursor), index,
offsets, n_core, ULINT_UNDEFINED, offsets, n_core, ULINT_UNDEFINED,
&heap); &heap);
page_cur_delete_rec(&page_cursor, page_cur_delete_rec(&page_cursor, offsets, mtr);
index, offsets, mtr);
} }
} }
@@ -877,7 +875,6 @@ rtr_page_split_and_insert(
buf_block_t* new_block; buf_block_t* new_block;
page_zip_des_t* page_zip; page_zip_des_t* page_zip;
page_zip_des_t* new_page_zip; page_zip_des_t* new_page_zip;
buf_block_t* insert_block;
page_cur_t* page_cursor; page_cur_t* page_cursor;
rec_t* rec = 0; rec_t* rec = 0;
ulint n_recs; ulint n_recs;
@@ -906,12 +903,10 @@ func_start:
mem_heap_empty(*heap); mem_heap_empty(*heap);
*offsets = NULL; *offsets = NULL;
ut_ad(mtr->memo_contains_flagged(&cursor->index->lock, MTR_MEMO_X_LOCK ut_ad(mtr->memo_contains_flagged(&cursor->index()->lock,
| MTR_MEMO_SX_LOCK)); MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
ut_ad(!dict_index_is_online_ddl(cursor->index) ut_ad(!dict_index_is_online_ddl(cursor->index()));
|| (flags & BTR_CREATE_FLAG) ut_ad(cursor->index()->lock.have_u_or_x());
|| dict_index_is_clust(cursor->index));
ut_ad(cursor->index->lock.have_u_or_x());
block = btr_cur_get_block(cursor); block = btr_cur_get_block(cursor);
page = buf_block_get_frame(block); page = buf_block_get_frame(block);
@@ -954,7 +949,7 @@ corrupted:
} }
#endif #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; total_data = page_get_data_size(page) + insert_size;
first_rec_group = split_rtree_node(rtr_split_node_array, first_rec_group = split_rtree_node(rtr_split_node_array,
static_cast<int>(n_recs), static_cast<int>(n_recs),
@@ -965,7 +960,7 @@ corrupted:
/* Allocate a new page to the index */ /* Allocate a new page to the index */
const uint16_t page_level = btr_page_get_level(page); 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); FSP_UP, page_level, mtr, mtr, err);
if (UNIV_UNLIKELY(!new_block)) { if (UNIV_UNLIKELY(!new_block)) {
return nullptr; return nullptr;
@@ -977,7 +972,7 @@ corrupted:
to contain FIL_NULL in FIL_PAGE_PREV at this stage. */ to contain FIL_NULL in FIL_PAGE_PREV at this stage. */
memset_aligned<4>(new_block->page.frame + FIL_PAGE_PREV, 0, 4); 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); page_level, mtr);
new_page = buf_block_get_frame(new_block); new_page = buf_block_get_frame(new_block);
@@ -985,7 +980,7 @@ corrupted:
/* Set new ssn to the new page and page. */ /* Set new ssn to the new page and page. */
page_set_ssn_id(new_block, new_page_zip, current_ssn, mtr); 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); 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, || (*err = rtr_split_page_move_rec_list(rtr_split_node_array,
first_rec_group, first_rec_group,
new_block, block, new_block, block,
first_rec, cursor->index, first_rec, cursor->index(),
*heap, mtr))) { *heap, mtr))) {
if (*err != DB_FAIL) { if (*err != DB_FAIL) {
return nullptr; return nullptr;
@@ -1021,7 +1016,7 @@ corrupted:
ut_a(new_page_zip); ut_a(new_page_zip);
page_zip_copy_recs(new_block, 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); page_cursor = btr_cur_get_page_cur(cursor);
@@ -1056,7 +1051,7 @@ corrupted:
lock_rtr_move_rec_list(new_block, block, rec_move, moved); lock_rtr_move_rec_list(new_block, block, rec_move, moved);
const ulint n_core = page_level 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. */ /* Delete recs in first group from the new page. */
for (cur_split_node = rtr_split_node_array; for (cur_split_node = rtr_split_node_array;
@@ -1076,11 +1071,11 @@ corrupted:
*offsets = rec_get_offsets( *offsets = rec_get_offsets(
page_cur_get_rec(page_cursor), page_cur_get_rec(page_cursor),
cursor->index, *offsets, n_core, cursor->index(), *offsets, n_core,
ULINT_UNDEFINED, heap); ULINT_UNDEFINED, heap);
page_cur_delete_rec(page_cursor, page_cur_delete_rec(page_cursor,
cursor->index, *offsets, mtr); *offsets, mtr);
n++; n++;
} }
} }
@@ -1093,32 +1088,30 @@ corrupted:
block, page_cursor); block, page_cursor);
*offsets = rec_get_offsets( *offsets = rec_get_offsets(
page_cur_get_rec(page_cursor), page_cur_get_rec(page_cursor),
cursor->index, *offsets, n_core, page_cursor->index, *offsets, n_core,
ULINT_UNDEFINED, heap); ULINT_UNDEFINED, heap);
page_cur_delete_rec(page_cursor, page_cur_delete_rec(page_cursor, *offsets,
cursor->index, *offsets, mtr); mtr);
} }
} }
#ifdef UNIV_GIS_DEBUG #ifdef UNIV_GIS_DEBUG
ut_ad(page_validate(new_page, cursor->index)); ut_ad(page_validate(new_page, cursor->index()));
ut_ad(page_validate(page, cursor->index)); ut_ad(page_validate(page, cursor->index()));
#endif #endif
} }
/* Insert the new rec to the proper page. */ /* Insert the new rec to the proper page. */
cur_split_node = end_split_node - 1; 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 */ /* Reposition the cursor for insert and try insertion */
page_cursor = btr_cur_get_page_cur(cursor); 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; 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_CUR_LE, &up_match, &low_match,
page_cursor, nullptr)) { page_cursor, nullptr)) {
goto corrupted; goto corrupted;
@@ -1133,7 +1126,7 @@ corrupted:
goto after_insert; } 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); offsets, heap, n_ext, mtr);
/* If insert did not fit, try page reorganization. /* If insert did not fit, try page reorganization.
@@ -1141,14 +1134,13 @@ corrupted:
attempted this already. */ attempted this already. */
if (rec == NULL) { if (rec == NULL) {
if (!is_page_cur_get_page_zip(page_cursor) 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, rec = page_cur_tuple_insert(page_cursor, tuple,
cursor->index, offsets, offsets,
heap, n_ext, mtr); heap, n_ext, mtr);
} }
/* If insert fail, we will try to split the insert_block /* If insert fail, we will try to split the block again. */
again. */
} }
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
@@ -1156,8 +1148,8 @@ after_insert:
#endif #endif
/* Calculate the mbr on the upper half-page, and the mbr on /* Calculate the mbr on the upper half-page, and the mbr on
original page. */ original page. */
rtr_page_cal_mbr(cursor->index, block, &mbr, *heap); 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(), new_block, &new_mbr, *heap);
prdt.data = &mbr; prdt.data = &mbr;
new_prdt.data = &new_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 /* Save the new ssn to the root page, since we need to reinit
the first ssn value from it after restart server. */ 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)) { if (UNIV_UNLIKELY(!root_block)) {
return nullptr; return nullptr;
} }
@@ -1187,8 +1180,8 @@ after_insert:
again. */ again. */
if (!rec) { if (!rec) {
/* We play safe and reset the free bits for new_page */ /* We play safe and reset the free bits for new_page */
if (!dict_index_is_clust(cursor->index) if (!dict_index_is_clust(cursor->index())
&& !cursor->index->table->is_temporary()) { && !cursor->index()->table->is_temporary()) {
ibuf_reset_free_bits(new_block); ibuf_reset_free_bits(new_block);
ibuf_reset_free_bits(block); ibuf_reset_free_bits(block);
} }
@@ -1205,16 +1198,16 @@ after_insert:
if (UNIV_UNLIKELY(!i_rec)) { if (UNIV_UNLIKELY(!i_rec)) {
goto corrupted; goto corrupted;
} }
btr_cur_position(cursor->index, i_rec, block, cursor); btr_cur_position(cursor->index(), i_rec, block, cursor);
goto func_start; goto func_start;
} }
#ifdef UNIV_GIS_DEBUG #ifdef UNIV_GIS_DEBUG
ut_ad(page_validate(buf_block_get_frame(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(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 #endif
MONITOR_INC(MONITOR_INDEX_SPLIT); MONITOR_INC(MONITOR_INDEX_SPLIT);
@@ -1234,14 +1227,13 @@ rtr_ins_enlarge_mbr(
rtr_mbr_t new_mbr; rtr_mbr_t new_mbr;
buf_block_t* block; buf_block_t* block;
mem_heap_t* heap; mem_heap_t* heap;
dict_index_t* index = btr_cur->index;
page_cur_t* page_cursor; page_cur_t* page_cursor;
rec_offs* offsets; rec_offs* offsets;
node_visit_t* node_visit; node_visit_t* node_visit;
btr_cur_t cursor; btr_cur_t cursor;
page_t* page; 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 no rtr_info or rtree is one level tree, return. */
if (!btr_cur->rtr_info || btr_cur->tree_height == 1) { 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. */ /* 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. */ /* Get father block. */
cursor.init(); cursor.page_cur.index = page_cursor->index;
cursor.page_cur.block = block;
offsets = rtr_page_get_father_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); page = buf_block_get_frame(block);
/* Update the mbr field of the rec. */ /* Update the mbr field of the rec. */
rtr_update_mbr_field(&cursor, offsets, NULL, page, rtr_update_mbr_field(&cursor, offsets, NULL, page,
&new_mbr, NULL, mtr); &new_mbr, NULL, mtr);
page_cursor = btr_cur_get_page_cur(&cursor); block = btr_cur_get_block(&cursor);
block = page_cur_get_block(page_cursor);
} }
mem_heap_free(heap); mem_heap_free(heap);
@@ -1338,6 +1330,7 @@ rtr_page_copy_rec_list_end_no_locks(
return DB_CORRUPTION; return DB_CORRUPTION;
} }
page_cur_position(cur_rec, new_block, &page_cur); page_cur_position(cur_rec, new_block, &page_cur);
page_cur.index = index;
/* Copy records from the original page to the new page */ /* Copy records from the original page to the new page */
while (!page_cur_is_after_last(&cur1)) { while (!page_cur_is_after_last(&cur1)) {
@@ -1399,7 +1392,7 @@ move_to_prev:
offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core, offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core,
ULINT_UNDEFINED, &heap); 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); cur1_rec, offsets1, mtr);
if (UNIV_UNLIKELY(!ins_rec || moved >= max_move)) { if (UNIV_UNLIKELY(!ins_rec || moved >= max_move)) {
return DB_CORRUPTION; return DB_CORRUPTION;
@@ -1461,6 +1454,7 @@ rtr_page_copy_rec_list_start_no_locks(
return DB_CORRUPTION; return DB_CORRUPTION;
} }
page_cur_position(cur_rec, new_block, &page_cur); page_cur_position(cur_rec, new_block, &page_cur);
page_cur.index = index;
while (page_cur_get_rec(&cur1) != rec) { while (page_cur_get_rec(&cur1) != rec) {
rec_t* cur1_rec = page_cur_get_rec(&cur1); 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, offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core,
ULINT_UNDEFINED, &heap); 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); cur1_rec, offsets1, mtr);
if (UNIV_UNLIKELY(!ins_rec || moved >= max_move)) { if (UNIV_UNLIKELY(!ins_rec || moved >= max_move)) {
return DB_CORRUPTION; return DB_CORRUPTION;
@@ -1560,7 +1554,7 @@ rtr_merge_mbr_changed(
ulint len; ulint len;
bool changed = false; bool changed = false;
ut_ad(dict_index_is_spatial(cursor->index)); ut_ad(cursor->index()->is_spatial());
rec = btr_cur_get_rec(cursor); 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 btr_cur_t* cursor, /*!< in/out: position at the parent entry
pointing to the child if successful */ pointing to the child if successful */
buf_block_t* parentb,/*!< in: parent page to check */ buf_block_t* parentb,/*!< in: parent page to check */
buf_block_t* childb, /*!< in: child Page */
mem_heap_t* heap) /*!< in: memory heap */ 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_offs* offsets;
rec_t* rec = page_get_infimum_rec(parentb->page.frame); 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 */ /*!< in: index tree locked */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
dict_index_t* index = btr_cur->index; dict_index_t* index = btr_cur->index();
bool found = false; bool found = false;
page_cur_t* page_cursor; page_cur_t* page_cursor;
ulint level = 0; ulint level = 0;
node_visit_t next_rec; node_visit_t next_rec;
rtr_info_t* rtr_info = btr_cur->rtr_info; rtr_info_t* rtr_info = btr_cur->rtr_info;
node_seq_t page_ssn; node_seq_t page_ssn;
ulint my_latch_mode;
ulint skip_parent = false; ulint skip_parent = false;
bool new_split = false; bool new_split = false;
bool for_delete = false; bool for_delete = false;
@@ -115,7 +114,7 @@ rtr_pcur_getnext_from_path(
ut_ad(dtuple_get_n_fields_cmp(tuple)); 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_delete = latch_mode & BTR_RTREE_DELETE_MARK;
for_undo_ins = latch_mode & BTR_RTREE_UNDO_INS; 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 = btr_cur_get_page_cur(btr_cur);
page_cursor->rec = NULL; page_cursor->rec = NULL;
page_cursor->block = block;
if (mode == PAGE_CUR_RTREE_LOCATE) { if (mode == PAGE_CUR_RTREE_LOCATE) {
if (target_level == 0 && level == 0) { if (target_level == 0 && level == 0) {
@@ -307,7 +307,7 @@ rtr_pcur_getnext_from_path(
found = false; found = false;
if (!page_cur_search_with_match( if (!page_cur_search_with_match(
block, index, tuple, PAGE_CUR_LE, tuple, PAGE_CUR_LE,
&up_match, &low_match, &up_match, &low_match,
btr_cur_get_page_cur(btr_cur), nullptr) btr_cur_get_page_cur(btr_cur), nullptr)
&& low_match && low_match
@@ -351,17 +351,12 @@ rtr_pcur_getnext_from_path(
BTR_PCUR_IS_POSITIONED; BTR_PCUR_IS_POSITIONED;
r_cursor->latch_mode = my_latch_mode; r_cursor->latch_mode = my_latch_mode;
btr_pcur_store_position(r_cursor, mtr); btr_pcur_store_position(r_cursor, mtr);
#ifdef UNIV_DEBUG ut_d(ulint num_stored =)
ulint num_stored =
rtr_store_parent_path( rtr_store_parent_path(
block, btr_cur, block, btr_cur,
rw_latch, level, mtr); btr_latch_mode(rw_latch),
ut_ad(num_stored > 0);
#else
rtr_store_parent_path(
block, btr_cur, rw_latch,
level, mtr); level, mtr);
#endif /* UNIV_DEBUG */ ut_ad(num_stored > 0);
} }
} }
} else { } else {
@@ -443,11 +438,11 @@ rtr_pcur_getnext_from_path(
const rec_t* rec = btr_cur_get_rec(btr_cur); const rec_t* rec = btr_cur_get_rec(btr_cur);
if (page_rec_is_infimum(rec) || page_rec_is_supremum(rec)) { if (!page_rec_is_user_rec(rec)) {
mtr_commit(mtr); mtr->commit();
mtr_start(mtr); mtr->start();
} else if (!index_locked) { } else if (!index_locked) {
mtr_memo_release(mtr, &index->lock, MTR_MEMO_X_LOCK); mtr->release(index->lock);
} }
return(found); return(found);
@@ -521,7 +516,7 @@ bool
rtr_pcur_open( rtr_pcur_open(
dict_index_t* index, /*!< in: index */ dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */ 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 */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
@@ -539,6 +534,7 @@ rtr_pcur_open(
/* Search with the tree cursor */ /* Search with the tree cursor */
btr_cur_t* btr_cursor = btr_pcur_get_btr_cur(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->rtr_info = rtr_create_rtr_info(false, false,
btr_cursor, index); btr_cursor, index);
@@ -554,7 +550,7 @@ rtr_pcur_open(
mtr->lock_upgrade(index->lock); 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, latch_mode,
btr_cursor, mtr) != DB_SUCCESS) { btr_cursor, mtr) != DB_SUCCESS) {
return true; return true;
@@ -606,24 +602,16 @@ rtr_pcur_open(
} }
/* Get the rtree page father. /* 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,out] mtr mtr
@param[in] sea_cur search cursor, contains information @param[in] sea_cur search cursor, contains information
about parent nodes in search about parent nodes in search
@param[out] cursor cursor on node pointer record, @param[out] cursor cursor on node pointer record,
its page x-latched its page x-latched
@return whether the cursor was successfully positioned */ @return whether the cursor was successfully positioned */
bool bool rtr_page_get_father(mtr_t *mtr, btr_cur_t *sea_cur, btr_cur_t *cursor)
rtr_page_get_father(
dict_index_t* index,
buf_block_t* block,
mtr_t* mtr,
btr_cur_t* sea_cur,
btr_cur_t* cursor)
{ {
mem_heap_t *heap = mem_heap_create(100); 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); mtr, sea_cur, cursor);
mem_heap_free(heap); mem_heap_free(heap);
return offsets != nullptr; 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 Returns the upper level node pointer to a R-Tree page. It is assumed
that mtr holds an x-latch on the tree. */ that mtr holds an x-latch on the tree. */
static const rec_t* rtr_get_father_node( static const rec_t* rtr_get_father_node(
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: the tree level of search */ ulint level, /*!< in: the tree level of search */
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in
tuple must be set so that it cannot get 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; const rec_t* rec = nullptr;
auto had_rtr = btr_cur->rtr_info; 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 /* Try to optimally locate the parent node. Level should always
less than sea_cur->tree_height unless the root is splitting */ 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); 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, PAGE_CUR_RTREE_LOCATE,
BTR_CONT_MODIFY_TREE, btr_cur, mtr) BTR_CONT_MODIFY_TREE, btr_cur, mtr)
!= DB_SUCCESS) { != DB_SUCCESS) {
@@ -764,7 +752,7 @@ rtr_page_get_father_node_ptr(
sea_cur = NULL; 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, sea_cur, cursor,
page_no, mtr); page_no, mtr);
if (!node_ptr) { if (!node_ptr) {
@@ -792,23 +780,18 @@ rtr_page_get_father_block(
/*======================*/ /*======================*/
rec_offs* offsets,/*!< in: work area for the return value */ rec_offs* offsets,/*!< in: work area for the return value */
mem_heap_t* heap, /*!< in: memory heap to use */ 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 */ mtr_t* mtr, /*!< in: mtr */
btr_cur_t* sea_cur,/*!< in: search cursor, contains information btr_cur_t* sea_cur,/*!< in: search cursor, contains information
about parent nodes in search */ about parent nodes in search */
btr_cur_t* cursor) /*!< out: cursor on node pointer record, btr_cur_t* cursor) /*!< out: cursor on node pointer record,
its page x-latched */ its page x-latched */
{ {
rec_t* rec = page_rec_get_next( rec_t *rec=
page_get_infimum_rec(buf_block_get_frame(block))); page_rec_get_next(page_get_infimum_rec(cursor->block()->page.frame));
if (!rec) { if (!rec)
return nullptr; return nullptr;
} cursor->page_cur.rec= rec;
btr_cur_position(index, rec, block, cursor); return rtr_page_get_father_node_ptr(offsets, heap, sea_cur, cursor, mtr);
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; rtr_info_t* rtr_info;
index = index ? index : cursor->index; index = index ? index : cursor->index();
ut_ad(index); ut_ad(index);
rtr_info = static_cast<rtr_info_t*>(ut_zalloc_nokey(sizeof(*rtr_info))); 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()); ut_ad(mtr->is_active());
index = btr_cur_get_index(btr_cur); 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 if (r_cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
|| r_cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_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, /* Page has changed, for R-Tree, the page cannot be shrunk away,
so we search the page and its right siblings */ so we search the page and its right siblings */
buf_block_t* block;
node_seq_t page_ssn; node_seq_t page_ssn;
const page_t* page; const page_t* page;
page_cur_t* page_cursor; page_cur_t* page_cursor;
@@ -1242,21 +1225,21 @@ rtr_cur_restore_position(
search_again: search_again:
ulint up_match = 0, low_match = 0; 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), page_id_t(index->table->space_id, page_no),
zip_size, RW_X_LATCH, NULL, BUF_GET, mtr); zip_size, RW_X_LATCH, NULL, BUF_GET, mtr);
if (!block) { if (!page_cursor->block) {
corrupted: corrupted:
ret = false; ret = false;
goto func_exit; goto func_exit;
} }
/* Get the page SSN */ /* 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); 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, &up_match, &low_match, page_cursor,
nullptr)) { nullptr)) {
goto corrupted; goto corrupted;
@@ -1352,7 +1335,7 @@ rtr_store_parent_path(
/*==================*/ /*==================*/
const buf_block_t* block, /*!< in: block of the page */ const buf_block_t* block, /*!< in: block of the page */
btr_cur_t* btr_cur,/*!< in/out: persistent cursor */ btr_cur_t* btr_cur,/*!< in/out: persistent cursor */
ulint latch_mode, btr_latch_mode latch_mode,
/*!< in: latch_mode */ /*!< in: latch_mode */
ulint level, /*!< in: index level */ ulint level, /*!< in: index level */
mtr_t* mtr) /*!< in: mtr */ 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)); 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); new_seq = rtr_get_current_ssn_id(index);
rtr_non_leaf_stack_push(path, block->page.id().page_no(), 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; std::vector<pfs_os_file_t> to_close;
mtr_t mtr; mtr_t mtr;
mtr.start(); 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); BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) if (err != DB_SUCCESS)
goto err_exit; goto err_exit;
@@ -2000,9 +2001,8 @@ static void drop_garbage_tables_after_restore()
ut_d(purge_sys.stop_FTS()); ut_d(purge_sys.stop_FTS());
mtr.start(); mtr.start();
if (btr_pcur_open_at_index_side(true, dict_sys.sys_tables->indexes.start, if (pcur.open_leaf(true, dict_sys.sys_tables->indexes.start, BTR_SEARCH_LEAF,
BTR_SEARCH_LEAF, &pcur, true, 0, &mtr) != &mtr) != DB_SUCCESS)
DB_SUCCESS)
goto all_fail; goto all_fail;
for (;;) for (;;)
{ {
@@ -14997,14 +14997,10 @@ inline int ha_innobase::defragment_table()
} }
btr_pcur_t pcur; btr_pcur_t pcur;
pcur.btr_cur.index = nullptr;
btr_pcur_init(&pcur);
mtr_t mtr; mtr_t mtr;
mtr.start(); mtr.start();
if (dberr_t err= btr_pcur_open_at_index_side(true, index, if (dberr_t err= pcur.open_leaf(true, index, BTR_SEARCH_LEAF, &mtr))
BTR_SEARCH_LEAF, &pcur,
true, 0, &mtr))
{ {
mtr.commit(); mtr.commit();
return convert_error_code_to_mysql(err, 0, m_user_thd); 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_move_to_next(&pcur, &mtr);
btr_pcur_store_position(&pcur, &mtr); btr_pcur_store_position(&pcur, &mtr);
mtr.commit(); 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); const bool interrupted= btr_defragment_add_index(&pcur, m_user_thd);
btr_pcur_free(&pcur); ut_free(pcur.old_rec_buf);
if (interrupted) if (interrupted)
return ER_QUERY_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; bool next_page= false;
mtr.start(); mtr.start();
if (btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF, if (pcur.open_leaf(true, clust_index, BTR_SEARCH_LEAF, &mtr) != DB_SUCCESS)
&pcur, true, 0, &mtr) != DB_SUCCESS)
{ {
non_empty: non_empty:
mtr.commit(); mtr.commit();
@@ -2159,10 +2158,11 @@ next_page:
&mtr); &mtr);
if (!block) if (!block)
goto non_empty; goto non_empty;
btr_leaf_page_release(page_cur_get_block(cur), BTR_SEARCH_LEAF, &mtr);
page_cur_set_before_first(block, cur); page_cur_set_before_first(block, cur);
if (UNIV_UNLIKELY(!page_cur_move_to_next(cur))) if (UNIV_UNLIKELY(!page_cur_move_to_next(cur)))
goto non_empty; goto non_empty;
const auto s= mtr.get_savepoint();
mtr.rollback_to_savepoint(s - 2, s - 1);
} }
rec= page_cur_get_rec(cur); rec= page_cur_get_rec(cur);
@@ -6038,8 +6038,7 @@ add_all_virtual:
mtr.start(); mtr.start();
index->set_modified(mtr); index->set_modified(mtr);
btr_pcur_t pcur; btr_pcur_t pcur;
dberr_t err = btr_pcur_open_at_index_side(true, index, BTR_MODIFY_TREE, dberr_t err= pcur.open_leaf(true, index, BTR_MODIFY_TREE, &mtr);
&pcur, true, 0, &mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
func_exit: func_exit:
mtr.commit(); mtr.commit();

View File

@@ -466,9 +466,8 @@ err_exit:
ib::info() << "Dumping the change buffer"; ib::info() << "Dumping the change buffer";
ibuf_mtr_start(&mtr); ibuf_mtr_start(&mtr);
btr_pcur_t pcur; btr_pcur_t pcur;
if (DB_SUCCESS == btr_pcur_open_at_index_side( if (DB_SUCCESS
true, ibuf.index, BTR_SEARCH_LEAF, &pcur, == pcur.open_leaf(true, ibuf.index, BTR_SEARCH_LEAF, &mtr)) {
true, 0, &mtr)) {
while (btr_pcur_move_to_next_user_rec(&pcur, &mtr)) { while (btr_pcur_move_to_next_user_rec(&pcur, &mtr)) {
rec_print_old(stderr, btr_pcur_get_rec(&pcur)); rec_print_old(stderr, btr_pcur_get_rec(&pcur));
} }
@@ -2337,9 +2336,11 @@ work_around:
space_id, page_nos[i], heap); space_id, page_nos[i], heap);
loop: loop:
btr_pcur_t pcur; btr_pcur_t pcur;
pcur.btr_cur.page_cur.index = ibuf.index;
ibuf_mtr_start(&mtr); ibuf_mtr_start(&mtr);
if (btr_pcur_open(ibuf.index, tuple, PAGE_CUR_GE, if (btr_pcur_open(tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF, &pcur, &mtr) BTR_MODIFY_LEAF, &pcur, 0, &mtr)
!= DB_SUCCESS) { != DB_SUCCESS) {
goto done; goto done;
} }
@@ -2386,16 +2387,11 @@ done:
#endif #endif
} }
/*********************************************************************//** /** Contract the change buffer by reading pages to the buffer pool.
Contracts insert buffer trees by reading pages to the buffer pool.
@return a lower limit for the combined size in bytes of entries which @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 will be merged from ibuf trees to the pages read
empty */ @retval 0 if ibuf.empty */
static ulint ibuf_contract()
ulint
ibuf_merge_pages(
/*=============*/
ulint* n_pages) /*!< out: number of pages to which merged */
{ {
mtr_t mtr; mtr_t mtr;
btr_pcur_t pcur; btr_pcur_t pcur;
@@ -2403,15 +2399,13 @@ ibuf_merge_pages(
uint32_t page_nos[IBUF_MAX_N_PAGES_MERGED]; uint32_t page_nos[IBUF_MAX_N_PAGES_MERGED];
uint32_t space_ids[IBUF_MAX_N_PAGES_MERGED]; uint32_t space_ids[IBUF_MAX_N_PAGES_MERGED];
*n_pages = 0;
ibuf_mtr_start(&mtr); ibuf_mtr_start(&mtr);
/* Open a cursor to a randomly chosen leaf of the tree, at a random /* Open a cursor to a randomly chosen leaf of the tree, at a random
position within the leaf */ position within the leaf */
pcur.pos_state = BTR_PCUR_IS_POSITIONED; pcur.pos_state = BTR_PCUR_IS_POSITIONED;
pcur.old_stored = false; pcur.old_rec = nullptr;
pcur.trx_if_known = NULL; pcur.trx_if_known = nullptr;
pcur.search_mode = PAGE_CUR_G; pcur.search_mode = PAGE_CUR_G;
pcur.latch_mode = BTR_SEARCH_LEAF; pcur.latch_mode = BTR_SEARCH_LEAF;
@@ -2437,13 +2431,14 @@ ibuf_merge_pages(
return(0); return(0);
} }
ulint n_pages = 0;
sum_sizes = ibuf_get_merge_page_nos(TRUE, sum_sizes = ibuf_get_merge_page_nos(TRUE,
btr_pcur_get_rec(&pcur), &mtr, btr_pcur_get_rec(&pcur), &mtr,
space_ids, space_ids,
page_nos, n_pages); page_nos, &n_pages);
ibuf_mtr_commit(&mtr); 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); return(sum_sizes + 1);
} }
@@ -2470,8 +2465,9 @@ ibuf_merge_space(
/* Position the cursor on the first matching record. */ /* Position the cursor on the first matching record. */
dberr_t err = btr_pcur_open(ibuf.index, tuple, PAGE_CUR_GE, pcur.btr_cur.page_cur.index = ibuf.index;
BTR_SEARCH_LEAF, &pcur, &mtr); 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), ut_ad(err != DB_SUCCESS || page_validate(btr_pcur_get_page(&pcur),
ibuf.index)); ibuf.index));
@@ -2515,73 +2511,6 @@ ibuf_merge_space(
return(n_pages); 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. */ Contract insert buffer trees after insert if they are too big. */
UNIV_INLINE UNIV_INLINE
@@ -2591,13 +2520,7 @@ ibuf_contract_after_insert(
ulint entry_size) /*!< in: size of a record which was inserted ulint entry_size) /*!< in: size of a record which was inserted
into an ibuf tree */ into an ibuf tree */
{ {
/* Perform dirty reads of ibuf.size and ibuf.max_size, to /* dirty comparison, to avoid contention on ibuf_mutex */
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(). */
if (ibuf.size < ibuf.max_size) { if (ibuf.size < ibuf.max_size) {
return; return;
} }
@@ -2991,8 +2914,8 @@ ibuf_update_max_tablespace_id(void)
ibuf_mtr_start(&mtr); ibuf_mtr_start(&mtr);
if (btr_pcur_open_at_index_side(false, ibuf.index, BTR_SEARCH_LEAF, if (pcur.open_leaf(false, ibuf.index, BTR_SEARCH_LEAF, &mtr)
&pcur, true, 0, &mtr) != DB_SUCCESS) { != DB_SUCCESS) {
func_exit: func_exit:
ibuf_mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
return; 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 /** Buffer an operation in the insert/delete buffer, instead of doing it
directly to the disk page, if this is possible. 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] op operation type
@param[in] no_counter TRUE=use 5.0.3 format; FALSE=allow delete @param[in] no_counter TRUE=use 5.0.3 format; FALSE=allow delete
buffering buffering
@@ -3185,7 +3108,7 @@ or clustered
static TRANSACTIONAL_TARGET MY_ATTRIBUTE((warn_unused_result)) static TRANSACTIONAL_TARGET MY_ATTRIBUTE((warn_unused_result))
dberr_t dberr_t
ibuf_insert_low( ibuf_insert_low(
ulint mode, btr_latch_mode mode,
ibuf_op_t op, ibuf_op_t op,
ibool no_counter, ibool no_counter,
const dtuple_t* entry, const dtuple_t* entry,
@@ -3225,16 +3148,17 @@ ibuf_insert_low(
do_merge = FALSE; do_merge = FALSE;
/* Perform dirty reads of ibuf.size and ibuf.max_size, to /* Perform dirty comparison of ibuf.max_size and ibuf.size to
reduce ibuf_mutex contention. Given that ibuf.max_size and reduce ibuf_mutex contention. This should be OK; at worst we
ibuf.size fit in a machine word, this should be OK; at worst are doing some excessive ibuf_contract() or occasionally
we are doing some excessive ibuf_contract() or occasionally
skipping an ibuf_contract(). */ skipping an ibuf_contract(). */
if (ibuf.max_size == 0) { const ulint max_size = ibuf.max_size;
if (max_size == 0) {
return(DB_STRONG_FAIL); 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 /* Insert buffer is now too big, contract it but do not try
to insert */ to insert */
@@ -3265,7 +3189,7 @@ ibuf_insert_low(
the new entry to it without exceeding the free space limit for the the new entry to it without exceeding the free space limit for the
page. */ page. */
if (BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE) { if (mode == BTR_INSERT_TREE) {
for (;;) { for (;;) {
mysql_mutex_lock(&ibuf_pessimistic_insert_mutex); mysql_mutex_lock(&ibuf_pessimistic_insert_mutex);
mysql_mutex_lock(&ibuf_mutex); mysql_mutex_lock(&ibuf_mutex);
@@ -3287,18 +3211,16 @@ ibuf_insert_low(
} }
ibuf_mtr_start(&mtr); 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, err = btr_pcur_open(ibuf_entry, PAGE_CUR_LE, mode, &pcur, 0, &mtr);
&mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
func_exit: func_exit:
ibuf_mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
ut_free(pcur.old_rec_buf); ut_free(pcur.old_rec_buf);
mem_heap_free(heap); mem_heap_free(heap);
if (err == DB_SUCCESS if (err == DB_SUCCESS && mode == BTR_INSERT_TREE) {
&& BTR_LATCH_MODE_WITHOUT_INTENTION(mode)
== BTR_MODIFY_TREE) {
ibuf_contract_after_insert(entry_size); ibuf_contract_after_insert(entry_size);
} }
@@ -3345,7 +3267,7 @@ func_exit:
until after the IBUF_OP_DELETE has been buffered. */ until after the IBUF_OP_DELETE has been buffered. */
fail_exit: 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_mutex);
mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex); mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex);
} }
@@ -3461,8 +3383,7 @@ commit_exit:
ibuf.empty = page_is_empty(root); ibuf.empty = page_is_empty(root);
} }
} else { } else {
ut_ad(BTR_LATCH_MODE_WITHOUT_INTENTION(mode) ut_ad(mode == BTR_INSERT_TREE);
== BTR_MODIFY_TREE);
/* We acquire an sx-latch to the root page before the insert, /* We acquire an sx-latch to the root page before the insert,
because a pessimistic insert releases the tree x-latch, because a pessimistic insert releases the tree x-latch,
@@ -3637,7 +3558,7 @@ skip_watch:
entry, entry_size, entry, entry_size,
index, page_id, zip_size, thr); index, page_id, zip_size, thr);
if (err == DB_FAIL) { 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, op, no_counter, entry, entry_size,
index, page_id, zip_size, thr); index, page_id, zip_size, thr);
} }
@@ -3658,30 +3579,27 @@ dberr_t
ibuf_insert_to_index_page_low( ibuf_insert_to_index_page_low(
/*==========================*/ /*==========================*/
const dtuple_t* entry, /*!< in: buffered entry to insert */ 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 */ rec_offs** offsets,/*!< out: offsets on *rec */
mem_heap_t* heap, /*!< in/out: memory heap */ mem_heap_t* heap, /*!< in/out: memory heap */
mtr_t* mtr, /*!< in/out: mtr */ mtr_t* mtr, /*!< in/out: mtr */
page_cur_t* page_cur)/*!< in/out: cursor positioned on the record page_cur_t* page_cur)/*!< in/out: cursor positioned on the record
after which to insert the buffered entry */ 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; return DB_SUCCESS;
/* Page reorganization or recompression should already have been /* Page reorganization or recompression should already have been
attempted by page_cur_tuple_insert(). Besides, per attempted by page_cur_tuple_insert(). Besides, per
ibuf_index_page_calc_free_zip() the page should not have been ibuf_index_page_calc_free_zip() the page should not have been
recompressed or reorganized. */ 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 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; return err;
/* This time the record must fit */ /* 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_SUCCESS;
return DB_CORRUPTION; return DB_CORRUPTION;
@@ -3738,8 +3656,10 @@ ibuf_insert_to_index_page(
} }
ulint up_match = 0, low_match = 0; 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, &up_match, &low_match, &page_cur,
nullptr)) { nullptr)) {
return DB_CORRUPTION; return DB_CORRUPTION;
@@ -3786,7 +3706,7 @@ ibuf_insert_to_index_page(
if (!row_upd_changes_field_size_or_external(index, offsets, if (!row_upd_changes_field_size_or_external(index, offsets,
update) update)
&& (!page_zip || btr_cur_update_alloc_zip( && (!page_zip || btr_cur_update_alloc_zip(
page_zip, &page_cur, index, offsets, page_zip, &page_cur, offsets,
rec_offs_size(offsets), false, mtr))) { rec_offs_size(offsets), false, mtr))) {
/* This is the easy case. Do something similar /* This is the easy case. Do something similar
to btr_cur_update_in_place(). */ to btr_cur_update_in_place(). */
@@ -3827,7 +3747,7 @@ ibuf_insert_to_index_page(
/* Delete the different-length record, and insert the /* Delete the different-length record, and insert the
buffered one. */ 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))) { if (!(page_cur_move_to_prev(&page_cur))) {
err = DB_CORRUPTION; err = DB_CORRUPTION;
goto updated_in_place; goto updated_in_place;
@@ -3836,8 +3756,8 @@ ibuf_insert_to_index_page(
offsets = NULL; offsets = NULL;
} }
err = ibuf_insert_to_index_page_low(entry, block, index, err = ibuf_insert_to_index_page_low(entry, &offsets, heap, mtr,
&offsets, heap, mtr, &page_cur); &page_cur);
updated_in_place: updated_in_place:
mem_heap_free(heap); mem_heap_free(heap);
@@ -3853,16 +3773,18 @@ ibuf_set_del_mark(
/*==============*/ /*==============*/
const dtuple_t* entry, /*!< in: entry */ const dtuple_t* entry, /*!< in: entry */
buf_block_t* block, /*!< in/out: block */ 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 */ mtr_t* mtr) /*!< in: mtr */
{ {
page_cur_t page_cur; page_cur_t page_cur;
page_cur.block = block;
page_cur.index = index;
ulint up_match = 0, low_match = 0; ulint up_match = 0, low_match = 0;
ut_ad(ibuf_inside(mtr)); ut_ad(ibuf_inside(mtr));
ut_ad(dtuple_check_typed(entry)); 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, &up_match, &low_match, &page_cur,
nullptr) nullptr)
&& low_match == dtuple_get_n_fields(entry)) { && low_match == dtuple_get_n_fields(entry)) {
@@ -3914,6 +3836,8 @@ ibuf_delete(
before latching any further pages */ before latching any further pages */
{ {
page_cur_t page_cur; page_cur_t page_cur;
page_cur.block = block;
page_cur.index = index;
ulint up_match = 0, low_match = 0; ulint up_match = 0, low_match = 0;
ut_ad(ibuf_inside(mtr)); ut_ad(ibuf_inside(mtr));
@@ -3921,7 +3845,7 @@ ibuf_delete(
ut_ad(!index->is_spatial()); ut_ad(!index->is_spatial());
ut_ad(!index->is_clust()); 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, &up_match, &low_match, &page_cur,
nullptr) nullptr)
&& low_match == dtuple_get_n_fields(entry)) { && low_match == dtuple_get_n_fields(entry)) {
@@ -3974,7 +3898,7 @@ ibuf_delete(
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index)); ut_a(!page_zip || page_zip_validate(page_zip, page, index));
#endif /* UNIV_ZIP_DEBUG */ #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 #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index)); ut_a(!page_zip || page_zip_validate(page_zip, page, index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
@@ -4001,13 +3925,12 @@ ibuf_restore_pos(
const page_id_t page_id,/*!< in: page identifier */ const page_id_t page_id,/*!< in: page identifier */
const dtuple_t* search_tuple, const dtuple_t* search_tuple,
/*!< in: search tuple for entries of page_no */ /*!< 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 btr_pcur_t* pcur, /*!< in/out: persistent cursor whose
position is to be restored */ position is to be restored */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
ut_ad(mode == BTR_MODIFY_LEAF ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_PURGE_TREE);
|| BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE);
if (UNIV_LIKELY(pcur->restore_position(mode, mtr) == if (UNIV_LIKELY(pcur->restore_position(mode, mtr) ==
btr_pcur_t::SAME_ALL)) { 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); ibuf_mtr_start(mtr);
mysql_mutex_lock(&ibuf_mutex); mysql_mutex_lock(&ibuf_mutex);
if (!ibuf_restore_pos(page_id, search_tuple, if (!ibuf_restore_pos(page_id, search_tuple, BTR_PURGE_TREE,
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
pcur, mtr)) { pcur, mtr)) {
mysql_mutex_unlock(&ibuf_mutex); 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(mops, 0, sizeof(mops));
memset(dops, 0, sizeof(dops)); memset(dops, 0, sizeof(dops));
pcur.btr_cur.page_cur.index = ibuf.index;
loop: loop:
ibuf_mtr_start(&mtr); ibuf_mtr_start(&mtr);
/* Position pcur in the insert buffer at the first entry for this /* Position pcur in the insert buffer at the first entry for this
index page */ 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) BTR_MODIFY_LEAF, &pcur, &mtr)
!= DB_SUCCESS) { != DB_SUCCESS) {
err = DB_CORRUPTION; err = DB_CORRUPTION;
@@ -4437,7 +4360,6 @@ loop:
goto loop; goto loop;
} else if (btr_pcur_is_after_last_on_page(&pcur)) { } else if (btr_pcur_is_after_last_on_page(&pcur)) {
ibuf_mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
ut_free(pcur.old_rec_buf);
goto loop; goto loop;
} }
} }
@@ -4485,13 +4407,15 @@ void ibuf_delete_for_discarded_space(uint32_t space)
search_tuple = ibuf_search_tuple_build(space, 0, heap); search_tuple = ibuf_search_tuple_build(space, 0, heap);
memset(dops, 0, sizeof(dops)); memset(dops, 0, sizeof(dops));
pcur.btr_cur.page_cur.index = ibuf.index;
loop: loop:
log_free_check(); log_free_check();
ibuf_mtr_start(&mtr); ibuf_mtr_start(&mtr);
/* Position pcur in the insert buffer at the first entry for the /* Position pcur in the insert buffer at the first entry for the
space */ 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) BTR_MODIFY_LEAF, &pcur, &mtr)
!= DB_SUCCESS) { != DB_SUCCESS) {
goto leave_loop; goto leave_loop;
@@ -4577,7 +4501,7 @@ ibuf_print(
fprintf(file, fprintf(file,
"Ibuf: size " ULINTPF ", free list len " ULINTPF "," "Ibuf: size " ULINTPF ", free list len " ULINTPF ","
" seg size " ULINTPF ", " ULINTPF " merges\n", " seg size " ULINTPF ", " ULINTPF " merges\n",
ibuf.size, ulint{ibuf.size},
ibuf.free_list_len, ibuf.free_list_len,
ibuf.seg_size, ibuf.seg_size,
ulint{ibuf.n_merges}); 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. */ is acceptable for the program to die with a clear assert failure. */
#define BTR_MAX_LEVELS 100 #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) \ #define BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode) \
((latch_mode) & ulint(~(BTR_INSERT \ btr_latch_mode((latch_mode) & ~(BTR_INSERT \
| BTR_DELETE_MARK \ | BTR_DELETE_MARK \
| BTR_RTREE_UNDO_INS \ | BTR_RTREE_UNDO_INS \
| BTR_RTREE_DELETE_MARK \ | BTR_RTREE_DELETE_MARK \
@@ -159,13 +64,11 @@ record is in spatial index */
| BTR_IGNORE_SEC_UNIQUE \ | BTR_IGNORE_SEC_UNIQUE \
| BTR_ALREADY_S_LATCHED \ | BTR_ALREADY_S_LATCHED \
| BTR_LATCH_FOR_INSERT \ | BTR_LATCH_FOR_INSERT \
| BTR_LATCH_FOR_DELETE \ | BTR_LATCH_FOR_DELETE))
| BTR_MODIFY_EXTERNAL)))
#define BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode) \ #define BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode) \
((latch_mode) & ulint(~(BTR_LATCH_FOR_INSERT \ btr_latch_mode((latch_mode) \
| BTR_LATCH_FOR_DELETE \ & ~(BTR_LATCH_FOR_INSERT | BTR_LATCH_FOR_DELETE))
| BTR_MODIFY_EXTERNAL)))
/**************************************************************//** /**************************************************************//**
Checks and adjusts the root node of a tree during IMPORT TABLESPACE. 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)); 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. Gets the child node file address in a node pointer.
NOTE: the offsets array must contain all offsets for the record since 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_reset_free_bits() before mtr_commit(). On uncompressed pages,
IBUF_BITMAP_FREE is unaffected by reorganization. IBUF_BITMAP_FREE is unaffected by reorganization.
@param cursor page cursor
@param mtr mini-transaction
@return error code @return error code
@retval DB_FAIL if reorganizing a ROW_FORMAT=COMPRESSED page failed */ @retval DB_FAIL if reorganizing a ROW_FORMAT=COMPRESSED page failed */
dberr_t dberr_t btr_page_reorganize(page_cur_t *cursor, mtr_t *mtr)
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 */
MY_ATTRIBUTE((nonnull, warn_unused_result)); MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Decide if the page should be split at the convergence point of inserts /** Decide if the page should be split at the convergence point of inserts
converging to the left. 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. /** 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[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 */ @return whether the cursor was successfully positioned */
bool btr_page_get_father(dict_index_t* index, buf_block_t* block, mtr_t* mtr, bool btr_page_get_father(mtr_t* mtr, btr_cur_t* cursor)
btr_cur_t* cursor)
MY_ATTRIBUTE((nonnull,warn_unused_result)); MY_ATTRIBUTE((nonnull,warn_unused_result));
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/************************************************************//** /************************************************************//**

View File

@@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. 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 This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@@ -24,10 +24,7 @@ The B-tree
Created 6/2/1994 Heikki Tuuri Created 6/2/1994 Heikki Tuuri
*******************************************************/ *******************************************************/
#include "mach0data.h"
#include "mtr0mtr.h"
#include "mtr0log.h" #include "mtr0log.h"
#include "page0zip.h"
/**************************************************************//** /**************************************************************//**
Gets the index id field of a page. Gets the index id field of a page.
@@ -112,38 +109,3 @@ btr_node_ptr_get_child_page_no(
return(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. Returns the index of a cursor.
@param cursor b-tree cursor @param cursor b-tree cursor
@return index */ @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. */ Positions a tree cursor at a given record. */
UNIV_INLINE UNIV_INLINE
@@ -137,7 +137,7 @@ bool
btr_cur_optimistic_latch_leaves( btr_cur_optimistic_latch_leaves(
buf_block_t* block, buf_block_t* block,
ib_uint64_t modify_clock, ib_uint64_t modify_clock,
ulint* latch_mode, btr_latch_mode* latch_mode,
btr_cur_t* cursor, btr_cur_t* cursor,
mtr_t* mtr); 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 Note that if mode is PAGE_CUR_LE, which is used in inserts, then
cursor->up_match and cursor->low_match both will have sensible values. cursor->up_match and cursor->low_match both will have sensible values.
If mode is PAGE_CUR_GE, then up_match will a have a sensible value. If mode is PAGE_CUR_GE, then up_match will a have a sensible value.
@param index index
@param level the tree level of search @param level the tree level of search
@param tuple data tuple; NOTE: n_fields_cmp in tuple must be set so that @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! 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 mtr mini-transaction
@param autoinc PAGE_ROOT_AUTO_INC to be written (0 if none) @param autoinc PAGE_ROOT_AUTO_INC to be written (0 if none)
@return DB_SUCCESS on success or error code otherwise */ @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, 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, btr_cur_t *cursor, mtr_t *mtr,
ib_uint64_t autoinc= 0); 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. 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 @return true if the index is available and we have put the cursor, false
@@ -194,7 +179,7 @@ if the index is unavailable */
bool bool
btr_cur_open_at_rnd_pos( btr_cur_open_at_rnd_pos(
dict_index_t* index, /*!< in: index */ 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 */ btr_cur_t* cursor, /*!< in/out: B-tree cursor */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((nonnull,warn_unused_result)); 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_zip_des_t* page_zip,/*!< in/out: compressed page */
page_cur_t* cursor, /*!< in/out: B-tree page cursor */ page_cur_t* cursor, /*!< in/out: B-tree page cursor */
dict_index_t* index, /*!< in: the index corresponding to cursor */
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
rec_offs* offsets,/*!< in/out: offsets of the cursor record */ rec_offs* offsets,/*!< in/out: offsets of the cursor record */
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
@@ -291,11 +275,11 @@ btr_cur_update_alloc_zip_func(
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in/out: mini-transaction */
MY_ATTRIBUTE((nonnull, warn_unused_result)); MY_ATTRIBUTE((nonnull, warn_unused_result));
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
# define btr_cur_update_alloc_zip(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,index,offsets,len,cr,mtr) btr_cur_update_alloc_zip_func(page_zip,cursor,offsets,len,cr,mtr)
#else /* UNIV_DEBUG */ #else /* UNIV_DEBUG */
# define btr_cur_update_alloc_zip(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,index,len,cr,mtr) btr_cur_update_alloc_zip_func(page_zip,cursor,len,cr,mtr)
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/** Apply an update vector to a record. No field size changes are allowed. /** Apply an update vector to a record. No field size changes are allowed.
@@ -689,7 +673,7 @@ btr_rec_copy_externally_stored_field(
void void
btr_cur_latch_leaves( btr_cur_latch_leaves(
buf_block_t* block, buf_block_t* block,
ulint latch_mode, btr_latch_mode latch_mode,
btr_cur_t* cursor, btr_cur_t* cursor,
mtr_t* mtr, mtr_t* mtr,
btr_latch_leaves_t* latch_leaves = nullptr); 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 /** The tree cursor: the definition appears here only for the compiler
to know struct size! */ to know struct size! */
struct btr_cur_t { struct btr_cur_t {
dict_index_t* index; /*!< index where positioned */
page_cur_t page_cur; /*!< page cursor */ page_cur_t page_cur; /*!< page cursor */
purge_node_t* purge_node; /*!< purge node, for BTR_DELETE */ purge_node_t* purge_node; /*!< purge node, for BTR_DELETE */
buf_block_t* left_block; /*!< this field is used to store buf_block_t* left_block; /*!< this field is used to store
@@ -817,28 +800,19 @@ struct btr_cur_t {
information of the path through information of the path through
the tree */ the tree */
rtr_info_t* rtr_info; /*!< rtree search info */ rtr_info_t* rtr_info; /*!< rtree search info */
btr_cur_t():thr(NULL), rtr_info(NULL) {} btr_cur_t() { memset((void*) this, 0, sizeof *this); }
/* default values */
/** Zero-initialize all fields */ dict_index_t *index() const { return page_cur.index; }
void init() buf_block_t *block() const { return page_cur.block; }
{
index = NULL; /** Open the cursor on the first or last record.
memset(&page_cur, 0, sizeof page_cur); @param first true=first record, false=last record
purge_node = NULL; @param index B-tree
left_block = NULL; @param latch_mode which latches to acquire
thr = NULL; @param mtr mini-transaction
flag = btr_cur_method(0); @return error code */
tree_height = 0; dberr_t open_leaf(bool first, dict_index_t *index, btr_latch_mode latch_mode,
up_match = 0; mtr_t *mtr);
up_bytes = 0;
low_match = 0;
low_bytes = 0;
n_fields = 0;
n_bytes = 0;
fold = 0;
path_arr = NULL;
rtr_info = NULL;
}
}; };
/** Modify the delete-mark flag of a record. /** 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) 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 This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@@ -72,7 +72,7 @@ btr_cur_position(
btr_cur_t* cursor) /*!< out: cursor */ btr_cur_t* cursor) /*!< out: cursor */
{ {
page_cur_position(rec, block, btr_cur_get_page_cur(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) if (!page_has_siblings(page)
|| page_get_data_size(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 /* The page fillfactor has dropped below a predefined
minimum value OR the level in the B-tree contains just minimum value OR the level in the B-tree contains just
one page: we recommend compression if this is not the one page: we recommend compression if this is not the
root page. */ root page. */
return cursor->index->page return cursor->index()->page
!= btr_cur_get_block(cursor)->page.id().page_no(); != 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 if (!page_has_siblings(page) || page_get_n_recs(page) < 2
|| page_get_data_size(page) - rec_size || 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 /* The page fillfactor will drop below a predefined
minimum value, OR the level in the B-tree contains just minimum value, OR the level in the B-tree contains just
one page, OR the page will become empty: we recommend one page, OR the page will become empty: we recommend
compression if this is not the root page. */ 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(); == 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 */ 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 Resets a persistent cursor object, freeing ::old_rec_buf if it is
allocated and resetting the other members to their initial values. */ 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 */ 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. */ Copies the stored position of a pcur to another pcur. */
void void
btr_pcur_copy_stored_position( btr_pcur_copy_stored_position(
@@ -83,21 +70,11 @@ btr_pcur_init(
/*==========*/ /*==========*/
btr_pcur_t* pcur); /*!< in: persistent cursor */ 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. */ Initializes and opens a persistent cursor to an index tree. */
inline inline
dberr_t dberr_t
btr_pcur_open_low( btr_pcur_open(
/*==============*/
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: level in the btree */
const dtuple_t* tuple, /*!< in: tuple on which search done */ const dtuple_t* tuple, /*!< in: tuple on which search done */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...; page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
NOTE that if the search is made using a unique 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 PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
may end up on the previous page from the may end up on the previous page from the
record! */ 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 */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written
(0 if none) */ (0 if none) */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((nonnull, warn_unused_result)); 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 /** Opens an persistent cursor to an index tree without initializing the
cursor. cursor.
@param index index
@param tuple tuple on which search done @param tuple tuple on which search done
@param mode PAGE_CUR_L, ...; NOTE that if the search is made using a @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 unique prefix of a record, mode should be PAGE_CUR_LE, not
@@ -126,26 +100,11 @@ cursor.
@param mtr mini-transaction @param mtr mini-transaction
@return DB_SUCCESS on success or error code otherwise. */ @return DB_SUCCESS on success or error code otherwise. */
inline inline
dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple, dberr_t btr_pcur_open_with_no_init(const dtuple_t *tuple,
page_cur_mode_t mode, ulint latch_mode, page_cur_mode_t mode,
btr_latch_mode latch_mode,
btr_pcur_t *cursor, mtr_t *mtr); 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. Gets the up_match value for a pcur after a search.
@return number of matched fields at the cursor or to the right if @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 /* The persistent B-tree cursor structure. This is used mainly for SQL
selects, updates, and deletes. */ selects, updates, and deletes. */
struct btr_pcur_t{ struct btr_pcur_t
{
/** Return value of restore_position() */ /** Return value of restore_position() */
enum restore_status { enum restore_status {
/** cursor position on user rec and points on the record with /** cursor position on user rec and points on the record with
@@ -373,61 +333,42 @@ struct btr_pcur_t{
}; };
/** a B-tree cursor */ /** a B-tree cursor */
btr_cur_t btr_cur; 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, 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 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 is positioned; BTR_NO_LATCHES means that the cursor is not currently
positioned: positioned:
we say then that the cursor is detached; it can be restored to we say then that the cursor is detached; it can be restored to
attached if the old position was stored in old_rec */ attached if the old position was stored in old_rec */
ulint latch_mode; btr_latch_mode latch_mode= BTR_NO_LATCHES;
/** true if old_rec is stored */
bool old_stored;
/** if cursor position is stored, contains an initial segment of the /** if cursor position is stored, contains an initial segment of the
latest record cursor was positioned either on, before or after */ latest record cursor was positioned either on, before or after */
rec_t* old_rec; rec_t *old_rec= nullptr;
/** btr_cur.index->n_core_fields when old_rec was copied */ /** btr_cur.index()->n_core_fields when old_rec was copied */
uint16 old_n_core_fields; uint16 old_n_core_fields= 0;
/** number of fields in old_rec */ /** 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 /** BTR_PCUR_ON, BTR_PCUR_BEFORE, or BTR_PCUR_AFTER, depending on
whether cursor was on, before, or after the old_rec record */ 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 */ /** buffer block when the position was stored */
buf::Block_hint block_when_stored; buf::Block_hint block_when_stored;
/** the modify clock value of the buffer block when the cursor position /** the modify clock value of the buffer block when the cursor position
was stored */ was stored */
ib_uint64_t modify_clock; ib_uint64_t modify_clock= 0;
/** btr_pcur_store_position() and btr_pcur_restore_position() state. */ /** btr_pcur_store_position() and btr_pcur_restore_position() state. */
enum pcur_pos_t pos_state; enum pcur_pos_t pos_state= BTR_PCUR_NOT_POSITIONED;
/** PAGE_CUR_G, ... */ page_cur_mode_t search_mode= PAGE_CUR_UNSUPP;
page_cur_mode_t search_mode;
/** the transaction, if we know it; otherwise this field is not defined; /** the transaction, if we know it; otherwise this field is not defined;
can ONLY BE USED in error prints in fatal assertion failures! */ can ONLY BE USED in error prints in fatal assertion failures! */
trx_t* trx_if_known; trx_t *trx_if_known= nullptr;
/*-----------------------------*/ /** a dynamically allocated buffer for old_rec */
/* NOTE that the following fields may possess dynamically allocated byte *old_rec_buf= nullptr;
memory which should be freed if not needed anymore! */
/** NULL, or a dynamically allocated buffer for old_rec */
byte* old_rec_buf;
/** old_rec_buf size if old_rec_buf is not NULL */ /** old_rec_buf size if old_rec_buf is not NULL */
ulint buf_size; ulint buf_size= 0;
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();
}
/** Return the index of this persistent cursor */ /** 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)) MY_ATTRIBUTE((nonnull, warn_unused_result))
/** Restores the stored position of a persistent cursor bufferfixing /** Restores the stored position of a persistent cursor bufferfixing
the page and obtaining the specified latches. If the cursor position 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 @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 the record with not the same uniq field values as in the stored
@retval CORRUPTED if the index is corrupted */ @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) inline buf_block_t *btr_pcur_get_block(btr_pcur_t *cursor)
@@ -479,10 +439,9 @@ MY_ATTRIBUTE((nonnull, warn_unused_result))
inline inline
dberr_t dberr_t
btr_pcur_open_on_user_rec( btr_pcur_open_on_user_rec(
dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */ const dtuple_t* tuple, /*!< in: tuple on which search done */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ... */ 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_MODIFY_LEAF */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent btr_pcur_t* cursor, /*!< in: memory buffer for persistent
cursor */ cursor */
@@ -490,7 +449,7 @@ btr_pcur_open_on_user_rec(
{ {
ut_ad(mode == PAGE_CUR_GE || mode == PAGE_CUR_G); ut_ad(mode == PAGE_CUR_GE || mode == PAGE_CUR_G);
ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF); 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; return err;
if (!btr_pcur_is_after_last_on_page(cursor) || if (!btr_pcur_is_after_last_on_page(cursor) ||
btr_pcur_is_after_last_in_tree(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);
ut_ad(cursor->old_rec); ut_ad(cursor->old_rec);
ut_ad(cursor->old_stored);
ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
|| cursor->pos_state == BTR_PCUR_IS_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->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES); 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)); 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->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES); 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)); 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->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES); ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
cursor->old_stored = false; cursor->old_rec = nullptr;
loop: loop:
if (btr_pcur_is_after_last_on_page(cursor)) { if (btr_pcur_is_after_last_on_page(cursor)) {
if (btr_pcur_is_after_last_in_tree(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->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES); 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)) if (btr_pcur_is_after_last_on_page(cursor))
return !btr_pcur_is_after_last_in_tree(cursor) && return !btr_pcur_is_after_last_in_tree(cursor) &&
@@ -294,31 +293,17 @@ btr_pcur_init(
/*==========*/ /*==========*/
btr_pcur_t* pcur) /*!< in: persistent cursor */ btr_pcur_t* pcur) /*!< in: persistent cursor */
{ {
pcur->old_stored = false;
pcur->old_rec_buf = NULL; pcur->old_rec_buf = NULL;
pcur->old_rec = NULL; pcur->old_rec = NULL;
pcur->btr_cur.rtr_info = 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. */ Initializes and opens a persistent cursor to an index tree. */
inline inline
dberr_t dberr_t
btr_pcur_open_low( btr_pcur_open(
/*==============*/
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: level in the btree */
const dtuple_t* tuple, /*!< in: tuple on which search done */ const dtuple_t* tuple, /*!< in: tuple on which search done */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...; page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
NOTE that if the search is made using a unique 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 PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
may end up on the previous page from the may end up on the previous page from the
record! */ 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 */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written
(0 if none) */ (0 if none) */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
ut_ad(!index->is_spatial()); ut_ad(!cursor->index()->is_spatial());
btr_pcur_init(cursor);
cursor->latch_mode= BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode); cursor->latch_mode= BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
cursor->search_mode= mode; cursor->search_mode= mode;
cursor->pos_state= BTR_PCUR_IS_POSITIONED; cursor->pos_state= BTR_PCUR_IS_POSITIONED;
cursor->trx_if_known= nullptr; 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), btr_pcur_get_btr_cur(cursor),
mtr, autoinc); mtr, autoinc);
} }
/** Opens an persistent cursor to an index tree without initializing the /** Opens an persistent cursor to an index tree without initializing the
cursor. cursor.
@param index index
@param tuple tuple on which search done @param tuple tuple on which search done
@param mode PAGE_CUR_L, ...; NOTE that if the search is made using a @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 unique prefix of a record, mode should be PAGE_CUR_LE, not
@@ -356,59 +339,21 @@ cursor.
@param mtr mini-transaction @param mtr mini-transaction
@return DB_SUCCESS on success or error code otherwise. */ @return DB_SUCCESS on success or error code otherwise. */
inline inline
dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple, dberr_t btr_pcur_open_with_no_init(const dtuple_t *tuple,
page_cur_mode_t mode, ulint latch_mode, page_cur_mode_t mode,
btr_latch_mode latch_mode,
btr_pcur_t *cursor, mtr_t *mtr) btr_pcur_t *cursor, mtr_t *mtr)
{ {
cursor->latch_mode= BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode); cursor->latch_mode= BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode);
cursor->search_mode= mode; cursor->search_mode= mode;
cursor->pos_state= BTR_PCUR_IS_POSITIONED; cursor->pos_state= BTR_PCUR_IS_POSITIONED;
cursor->old_stored= false;
cursor->trx_if_known= nullptr; cursor->trx_if_known= nullptr;
/* Search with the tree cursor */ /* 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); 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 Frees the possible memory heap of a persistent cursor and sets the latch
mode of the persistent cursor to BTR_NO_LATCHES. mode of the persistent cursor to BTR_NO_LATCHES.
@@ -427,23 +372,19 @@ btr_pcur_close(
{ {
ut_free(cursor->old_rec_buf); 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); rtr_clean_rtr_info(cursor->btr_cur.rtr_info, true);
cursor->btr_cur.rtr_info = NULL;
}
cursor->old_rec = NULL; cursor->btr_cur.rtr_info= nullptr;
cursor->old_rec_buf = NULL; cursor->old_rec = nullptr;
cursor->btr_cur.page_cur.rec = NULL; cursor->old_rec_buf = nullptr;
cursor->btr_cur.page_cur.block = NULL; cursor->btr_cur.page_cur.rec = nullptr;
cursor->btr_cur.page_cur.block = nullptr;
cursor->old_rec = NULL;
cursor->old_stored = false;
cursor->latch_mode = BTR_NO_LATCHES; cursor->latch_mode = BTR_NO_LATCHES;
cursor->pos_state = BTR_PCUR_NOT_POSITIONED; 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), page_cur_set_before_first(btr_pcur_get_block(cursor),
btr_pcur_get_page_cur(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) 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 This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@@ -24,8 +24,7 @@ The index tree general types
Created 2/17/1996 Heikki Tuuri Created 2/17/1996 Heikki Tuuri
*************************************************************************/ *************************************************************************/
#ifndef btr0types_h #pragma once
#define btr0types_h
#include "page0types.h" #include "page0types.h"
#include "rem0types.h" #include "rem0types.h"
@@ -56,4 +55,93 @@ in the index record. */
#define BTR_EXTERN_LOCAL_STORED_MAX_SIZE \ #define BTR_EXTERN_LOCAL_STORED_MAX_SIZE \
(BTR_EXTERN_FIELD_REF_SIZE * 2) (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) 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 This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@@ -313,67 +313,13 @@ public:
return(m_size); 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. Iterate over each block and call the functor.
@return false if iteration was terminated. */ @return false if iteration was terminated. */
template <typename Functor> template <typename Functor>
bool for_each_block(const Functor& functor) const bool for_each_block(const Functor& functor) const
{ {
for (typename list_t::iterator it = m_list.begin(), for (list_t::iterator it = m_list.begin(), end = m_list.end();
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();
it != end; ++it) { it != end; ++it) {
if (!functor(&*it)) { if (!functor(&*it)) {

View File

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

View File

@@ -30,7 +30,6 @@ Created 7/19/1997 Heikki Tuuri
#include "mtr0mtr.h" #include "mtr0mtr.h"
#include "dict0mem.h" #include "dict0mem.h"
#include "fsp0fsp.h" #include "fsp0fsp.h"
#include "ibuf0types.h"
/** Default value for maximum on-disk size of change buffer in terms /** Default value for maximum on-disk size of change buffer in terms
of percentage of the buffer pool. */ of percentage of the buffer pool. */
@@ -61,6 +60,37 @@ enum ibuf_use_t {
/** Operations that can currently be buffered. */ /** Operations that can currently be buffered. */
extern ulong innodb_change_buffering; 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 */ /** The insert buffer control structure */
extern ibuf_t ibuf; 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. /** Contract the change buffer by reading pages to the buffer pool.
@return a lower limit for the combined size in bytes of entries which @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 will be merged from ibuf trees to the pages read
empty */ @retval 0 if ibuf.empty */
ulint ibuf_merge_all(); ulint ibuf_contract();
/** Contracts insert buffer trees by reading pages referring to space_id /** Contracts insert buffer trees by reading pages referring to space_id
to the buffer pool. to the buffer pool.

View File

@@ -65,37 +65,6 @@ ibuf_mtr_commit(
mtr_commit(mtr); 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 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 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; /** number of std::swap(buf, flush_buf) and writes from buf to log;
protected by latch.wr_lock() */ protected by latch.wr_lock() */
ulint write_to_log; 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) */ /** innodb_log_buffer_size (size of buf and flush_buf, in bytes) */
size_t buf_size; size_t buf_size;

View File

@@ -28,6 +28,8 @@ Created 11/26/1995 Heikki Tuuri
#include "fil0fil.h" #include "fil0fil.h"
#include "dyn0buf.h" #include "dyn0buf.h"
#include "buf0buf.h"
#include <vector>
/** Start a mini-transaction. */ /** Start a mini-transaction. */
#define mtr_start(m) (m)->start() #define mtr_start(m) (m)->start()
@@ -48,11 +50,6 @@ savepoint. */
@return old mode */ @return old mode */
#define mtr_set_log_mode(m, d) (m)->set_log_mode((d)) #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 #ifdef UNIV_PFS_RWLOCK
# define mtr_s_lock_index(i,m) (m)->s_lock(__FILE__, __LINE__, &(i)->lock) # 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) # 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) \ #define mtr_release_block_at_savepoint(m, s, b) \
(m)->release_block_at_savepoint((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. */ /** Mini-transaction memo stack slot. */
struct mtr_memo_slot_t { struct mtr_memo_slot_t
/** pointer to the object */ {
void* object; /** pointer to the object, or nullptr if released */
void *object;
/** type of the stored object */ /** type of the stored object */
mtr_memo_type_t type; mtr_memo_type_t type;
/** Release the object */
void release() const;
}; };
/** Mini-transaction handle and buffer */ /** Mini-transaction handle and buffer */
@@ -89,14 +83,19 @@ struct mtr_t {
/** Commit the mini-transaction. */ /** Commit the mini-transaction. */
void commit(); void commit();
/** Release latches till savepoint. To simplify the code only /** Release latches of unmodified buffer pages.
MTR_MEMO_S_LOCK and MTR_MEMO_PAGE_S_FIX slot types are allowed to be @param begin first slot to release
released, otherwise it would be neccesary to add one more argument in the @param end last slot to release, or get_savepoint() */
function to point out what slot types are allowed for rollback, and this void rollback_to_savepoint(ulint begin, ulint end);
would be overengineering as currently the function is used only in one place
in the code. /** Release latches of unmodified buffer pages.
@param savepoint savepoint, can be obtained with get_savepoint */ @param begin first slot to release */
void rollback_to_savepoint(ulint savepoint); 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. /** Commit a mini-transaction that is shrinking a tablespace.
@param space tablespace that is being shrunk */ @param space tablespace that is being shrunk */
@@ -118,26 +117,89 @@ struct mtr_t {
lsn_t commit_files(lsn_t checkpoint_lsn= 0); lsn_t commit_files(lsn_t checkpoint_lsn= 0);
/** @return mini-transaction savepoint (current size of m_memo) */ /** @return mini-transaction savepoint (current size of m_memo) */
ulint get_savepoint() const { ut_ad(is_active()); return m_memo.size(); } ulint get_savepoint() const
{
/** Release the (index tree) s-latch stored in an mtr memo after a ut_ad(is_active());
savepoint. return m_memo ? m_memo->size() : 0;
@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);
/** 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. */ /** Release the block in an mtr memo after a savepoint. */
inline void release_block_at_savepoint( void release_block_at_savepoint(ulint savepoint, buf_block_t *block)
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. */ switch (slot.type) {
inline void sx_latch_at_savepoint(ulint savepoint, buf_block_t* block); 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. */ /** 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 */ /** @return the logging mode */
mtr_log_t get_log_mode() const mtr_log_t get_log_mode() const
@@ -291,19 +353,17 @@ struct mtr_t {
/** Acquire an exclusive tablespace latch. /** Acquire an exclusive tablespace latch.
@param space tablespace */ @param space tablespace */
void x_lock_space(fil_space_t *space); void x_lock_space(fil_space_t *space);
/** Release an object in the memo stack.
@param object object /** Release an index latch. */
@param type object type void release(const index_lock &lock) { release(&lock); }
@return bool if lock released */ /** Release a latch to an unmodified page. */
bool memo_release(const void *object, ulint type); void release(const buf_block_t &block) { release(&block); }
/** 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);
/** Note that the mini-transaction will modify data. */ /** Note that the mini-transaction will modify data. */
void flag_modified() { m_modifications = true; } void flag_modified() { m_modifications = true; }
private: private:
/** Release an unmodified object. */
void release(const void *object);
/** Mark the given latched page as modified. /** Mark the given latched page as modified.
@param block page that will be modified */ @param block page that will be modified */
void modify(const buf_block_t& block); 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 */ @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); 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. /** Register a page latch on a buffer-fixed block was buffer-fixed.
@param latch latch type */ @param latch latch type */
void u_lock_register(ulint savepoint) void u_lock_register(ulint savepoint)
{ {
mtr_memo_slot_t *slot= m_memo.at<mtr_memo_slot_t*>(savepoint); mtr_memo_slot_t &slot= m_memo->at(savepoint);
ut_ad(slot->type == MTR_MEMO_BUF_FIX); ut_ad(slot.type == MTR_MEMO_BUF_FIX);
slot->type= MTR_MEMO_PAGE_SX_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 */ /** Upgrade U locks on a block to X */
void page_lock_upgrade(const buf_block_t &block); 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); void lock_upgrade(const index_lock &lock);
/** Check if we are holding tablespace latch /** Check if we are holding tablespace latch
@param space tablespace to search for @param space tablespace to search for
@param shared whether to look for shared latch, instead of exclusive @param shared whether to look for shared latch, instead of exclusive
@return whether space.latch is being held */ @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)); MY_ATTRIBUTE((warn_unused_result));
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/** Check if we are holding an rw-latch in this mini-transaction /** Check if we are holding an rw-latch in this mini-transaction
@param lock latch to search for @param lock latch to search for
@param type held latch type @param type held latch type
@return whether (lock,type) is contained */ @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)); 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 object object to search
@param flags specify types of object (can be ORred) of @param flags specify types of object latches
MTR_MEMO_PAGE_S_FIX ... values
@return true if contains */ @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. /** Check if memo contains the given page.
@param[in] ptr pointer to within buffer frame @param ptr pointer to within page frame
@param[in] flags specify types of object with OR of @param flags types latch to look for
MTR_MEMO_PAGE_S_FIX... values
@return the block @return the block
@retval NULL if not found */ @retval nullptr if not found */
buf_block_t* memo_contains_page_flagged( buf_block_t *memo_contains_page_flagged(const byte *ptr, ulint flags) const;
const byte* ptr,
ulint flags) const;
/** @return true if mini-transaction contains modifications. */ /** @return true if mini-transaction contains modifications. */
bool has_modifications() const { return m_modifications; } bool has_modifications() const { return m_modifications; }
#endif /* UNIV_DEBUG */ #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. /** Push an object to an mtr memo stack.
@param object object @param object object
@param type object type: MTR_MEMO_S_LOCK, ... */ @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. FIXME: Do this only when the MTR_MEMO_MODIFY flag is set! */
@param block block being x-fixed if (!m_made_dirty &&
@return true if the mtr is dirtying a clean page. */ (type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)))
static inline bool is_block_dirtied(const buf_block_t* block) m_made_dirty=
MY_ATTRIBUTE((warn_unused_result)); 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 */ /** @return the size of the log is empty */
size_t get_log_size() const { return m_log.size(); } size_t get_log_size() const { return m_log.size(); }
/** @return whether the log and memo are empty */ /** @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. */ /** Write an OPT_PAGE_CHECKSUM record. */
inline void page_checksum(const buf_page_t &bpage); inline void page_checksum(const buf_page_t &bpage);
@@ -670,6 +750,8 @@ private:
@return {start_lsn,flush_ahead} */ @return {start_lsn,flush_ahead} */
std::pair<lsn_t,page_flush_ahead> finish_write(size_t len); std::pair<lsn_t,page_flush_ahead> finish_write(size_t len);
/** Release all latches. */
void release();
/** Release the resources */ /** Release the resources */
inline void release_resources(); inline void release_resources();
@@ -727,7 +809,7 @@ private:
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/** acquired dict_index_t::lock, fil_space_t::latch, buf_block_t */ /** 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 */ /** mini-transaction log */
mtr_buf_t m_log; mtr_buf_t m_log;
@@ -743,5 +825,3 @@ private:
/** set of freed page ids */ /** set of freed page ids */
range_set *m_freed_pages= nullptr; 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 */ page_cur_t* cursor, /*!< in/out: a page cursor */
const dtuple_t* tuple, /*!< in: pointer to a data tuple */ const dtuple_t* tuple, /*!< in: pointer to a data tuple */
dict_index_t* index, /*!< in: record descriptor */
rec_offs** offsets,/*!< out: offsets on *rec */ rec_offs** offsets,/*!< out: offsets on *rec */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
ulint n_ext, /*!< in: number of externally stored columns */ ulint n_ext, /*!< in: number of externally stored columns */
@@ -143,7 +142,6 @@ rec_t*
page_cur_insert_rec_low( page_cur_insert_rec_low(
/*====================*/ /*====================*/
const page_cur_t*cur, /*!< in: page cursor */ 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 */ const rec_t* rec, /*!< in: record to insert after cur */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */ rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -165,7 +163,6 @@ page_cur_insert_rec_zip(
/*====================*/ /*====================*/
page_cur_t* cursor, /*!< in/out: page cursor, page_cur_t* cursor, /*!< in/out: page cursor,
logical position unchanged */ logical position unchanged */
dict_index_t* index, /*!< in: record descriptor */
const rec_t* rec, /*!< in: pointer to a physical record */ const rec_t* rec, /*!< in: pointer to a physical record */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */ rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -177,7 +174,6 @@ void
page_cur_delete_rec( page_cur_delete_rec(
/*================*/ /*================*/
page_cur_t* cursor, /*!< in/out: a page cursor */ 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( const rec_offs* offsets,/*!< in: rec_get_offsets(
cursor->rec, index) */ cursor->rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -239,8 +235,6 @@ Searches the right position for a page cursor. */
bool bool
page_cur_search_with_match( 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 */ const dtuple_t* tuple, /*!< in: data tuple */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, page_cur_mode_t mode, /*!< in: PAGE_CUR_L,
PAGE_CUR_LE, PAGE_CUR_G, or PAGE_CUR_LE, PAGE_CUR_G, or
@@ -251,13 +245,11 @@ page_cur_search_with_match(
ulint* ilow_matched_fields, ulint* ilow_matched_fields,
/*!< in/out: already matched /*!< in/out: already matched
fields in lower limit record */ 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 */ rtr_info_t* rtr_info);/*!< in/out: rtree search stack */
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
MY_ATTRIBUTE((warn_unused_result)) MY_ATTRIBUTE((warn_unused_result))
/** Search the right position for a page cursor. /** 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] tuple key to be searched for
@param[in] mode search mode @param[in] mode search mode
@param[in,out] iup_matched_fields already matched fields in the @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 lower limit record
@param[in,out] ilow_matched_bytes already matched bytes in the @param[in,out] ilow_matched_bytes already matched bytes in the
first partially matched field in the lower limit record first partially matched field in the lower limit record
@param[out] cursor page cursor */ @param[in,out] cursor page cursor */
bool bool
page_cur_search_with_match_bytes( page_cur_search_with_match_bytes(
const buf_block_t* block,
const dict_index_t* index,
const dtuple_t* tuple, const dtuple_t* tuple,
page_cur_mode_t mode, page_cur_mode_t mode,
ulint* iup_matched_fields, 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 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. */ are no user records, sets the cursor on the infimum record. */
void void page_cur_open_on_rnd_user_rec(page_cur_t *cursor);
page_cur_open_on_rnd_user_rec(
/*==========================*/
buf_block_t* block, /*!< in: page */
page_cur_t* cursor);/*!< out: page cursor */
/** Index page cursor */ /** Index page cursor */
struct page_cur_t{ struct page_cur_t{
const dict_index_t* index; dict_index_t* index;
rec_t* rec; /*!< pointer to a record on page */ rec_t* rec; /*!< pointer to a record on page */
rec_offs* offsets; rec_offs* offsets;
buf_block_t* block; /*!< pointer to the block containing rec */ 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 */ page_cur_t* cursor, /*!< in/out: a page cursor */
const dtuple_t* tuple, /*!< in: pointer to a data tuple */ const dtuple_t* tuple, /*!< in: pointer to a data tuple */
dict_index_t* index, /*!< in: record descriptor */
rec_offs** offsets,/*!< out: offsets on *rec */ rec_offs** offsets,/*!< out: offsets on *rec */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
ulint n_ext, /*!< in: number of externally stored columns */ ulint n_ext, /*!< in: number of externally stored columns */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
rec_t* rec; ulint size = rec_get_converted_size(cursor->index, tuple, n_ext);
ulint size = rec_get_converted_size(index, tuple, n_ext);
if (!*heap) { if (!*heap) {
*heap = mem_heap_create(size *heap = mem_heap_create(size
@@ -183,24 +181,23 @@ page_cur_tuple_insert(
* sizeof **offsets); * sizeof **offsets);
} }
rec = rec_convert_dtuple_to_rec((byte*) mem_heap_alloc(*heap, size), rec_t* rec = rec_convert_dtuple_to_rec(
index, tuple, n_ext); 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) page_is_leaf(cursor->block->page.frame)
? index->n_core_fields : 0, ? cursor->index->n_core_fields : 0,
ULINT_UNDEFINED, heap); ULINT_UNDEFINED, heap);
ut_ad(size == rec_offs_size(*offsets)); ut_ad(size == rec_offs_size(*offsets));
if (is_buf_block_get_page_zip(cursor->block)) { if (is_buf_block_get_page_zip(cursor->block)) {
rec = page_cur_insert_rec_zip( rec = page_cur_insert_rec_zip(cursor, rec, *offsets, mtr);
cursor, index, rec, *offsets, mtr);
} else { } else {
rec = page_cur_insert_rec_low(cursor, rec = page_cur_insert_rec_low(cursor, rec, *offsets, mtr);
index, 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); return(rec);
} }

View File

@@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2021, MariaDB Corporation. Copyright (c) 2017, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@@ -78,7 +78,7 @@ dberr_t
row_ins_clust_index_entry_low( row_ins_clust_index_entry_low(
/*==========================*/ /*==========================*/
ulint flags, /*!< in: undo logging and locking flags */ 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 depending on whether we wish optimistic or
pessimistic descent down the index tree */ pessimistic descent down the index tree */
dict_index_t* index, /*!< in: clustered index */ 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. It is then unmarked. Otherwise, the entry is just inserted to the index.
@retval DB_SUCCESS on success @retval DB_SUCCESS on success
@retval DB_LOCK_WAIT on lock wait when !(flags & BTR_NO_LOCKING_FLAG) @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 */ @return error code */
dberr_t dberr_t
row_ins_sec_index_entry_low( row_ins_sec_index_entry_low(
/*========================*/ /*========================*/
ulint flags, /*!< in: undo logging and locking flags */ 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 depending on whether we wish optimistic or
pessimistic descent down the index tree */ pessimistic descent down the index tree */
dict_index_t* index, /*!< in: secondary index */ 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) 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 This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@@ -303,13 +303,13 @@ row_build_row_ref_fast(
/***************************************************************//** /***************************************************************//**
Searches the clustered index record for a row, if we have the row Searches the clustered index record for a row, if we have the row
reference. reference.
@return TRUE if found */ @return true if found */
ibool bool
row_search_on_row_ref( row_search_on_row_ref(
/*==================*/ /*==================*/
btr_pcur_t* pcur, /*!< out: persistent cursor, which must btr_pcur_t* pcur, /*!< out: persistent cursor, which must
be closed by the caller */ 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 dict_table_t* table, /*!< in: table */
const dtuple_t* ref, /*!< in: row reference */ const dtuple_t* ref, /*!< in: row reference */
mtr_t* mtr) /*!< in/out: mtr */ mtr_t* mtr) /*!< in/out: mtr */
@@ -321,7 +321,7 @@ on the secondary index record are preserved.
rec_t* rec_t*
row_get_clust_rec( 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 */ const rec_t* rec, /*!< in: record in a secondary index */
dict_index_t* index, /*!< in: secondary index */ dict_index_t* index, /*!< in: secondary index */
dict_index_t** clust_index,/*!< out: clustered index */ dict_index_t** clust_index,/*!< out: clustered index */
@@ -363,9 +363,8 @@ Searches an index record.
enum row_search_result enum row_search_result
row_search_index_entry( row_search_index_entry(
/*===================*/ /*===================*/
dict_index_t* index, /*!< in: index */
const dtuple_t* entry, /*!< in: index entry */ 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 btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must
be closed by the caller */ be closed by the caller */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */

View File

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

View File

@@ -1148,6 +1148,7 @@ public:
} }
mtr.commit(); mtr.commit();
clear();
} }
/** Clear the data structure */ /** 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); 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; DBUG_VOID_RETURN;
} }
@@ -3485,7 +3478,17 @@ void recv_sys_t::apply(bool last_batch)
{ {
const trunc& t= truncated_undo_spaces[id]; const trunc& t= truncated_undo_spaces[id];
if (t.lsn) 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(); 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 bool
page_cur_search_with_match( 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 */ const dtuple_t* tuple, /*!< in: data tuple */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, page_cur_mode_t mode, /*!< in: PAGE_CUR_L,
PAGE_CUR_LE, PAGE_CUR_G, or PAGE_CUR_LE, PAGE_CUR_G, or
@@ -303,6 +301,8 @@ page_cur_search_with_match(
ulint low_matched_fields; ulint low_matched_fields;
ulint cur_matched_fields; ulint cur_matched_fields;
int cmp; int cmp;
const dict_index_t* const index = cursor->index;
const buf_block_t* const block = cursor->block;
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
const page_zip_des_t* page_zip = buf_block_get_page_zip(block); const page_zip_des_t* page_zip = buf_block_get_page_zip(block);
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
@@ -552,8 +552,6 @@ first partially matched field in the lower limit record
@param[out] cursor page cursor */ @param[out] cursor page cursor */
bool bool
page_cur_search_with_match_bytes( page_cur_search_with_match_bytes(
const buf_block_t* block,
const dict_index_t* index,
const dtuple_t* tuple, const dtuple_t* tuple,
page_cur_mode_t mode, page_cur_mode_t mode,
ulint* iup_matched_fields, ulint* iup_matched_fields,
@@ -575,6 +573,8 @@ page_cur_search_with_match_bytes(
ulint cur_matched_fields; ulint cur_matched_fields;
ulint cur_matched_bytes; ulint cur_matched_bytes;
int cmp; int cmp;
const dict_index_t* const index = cursor->index;
const buf_block_t* const block = cursor->block;
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
const page_zip_des_t* page_zip = buf_block_get_page_zip(block); const page_zip_des_t* page_zip = buf_block_get_page_zip(block);
#endif /* UNIV_ZIP_DEBUG */ #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 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. */ are no user records, sets the cursor on the infimum record. */
void void page_cur_open_on_rnd_user_rec(page_cur_t *cursor)
page_cur_open_on_rnd_user_rec(
/*==========================*/
buf_block_t* block, /*!< in: page */
page_cur_t* cursor) /*!< out: page cursor */
{ {
cursor->block= block; if (const ulint n_recs= page_get_n_recs(cursor->block->page.frame))
if (const ulint n_recs= page_get_n_recs(block->page.frame)) if ((cursor->rec= page_rec_get_nth(cursor->block->page.frame,
if ((cursor->rec= page_rec_get_nth(block->page.frame,
ut_rnd_interval(n_recs) + 1))) ut_rnd_interval(n_recs) + 1)))
return; 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( page_cur_insert_rec_low(
/*====================*/ /*====================*/
const page_cur_t*cur, /*!< in: page cursor */ 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 */ const rec_t* rec, /*!< in: record to insert after cur */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */ rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */ 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_validate(rec, index, offsets));
ut_ad(rec_offs_n_fields(offsets) > 0); 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, page_cur_t* cursor, /*!< in/out: page cursor,
logical position unchanged */ logical position unchanged */
dict_index_t* index, /*!< in: record descriptor */
const rec_t* rec, /*!< in: pointer to a physical record */ const rec_t* rec, /*!< in: pointer to a physical record */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */ rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
page_zip_des_t * const page_zip= page_cur_get_page_zip(cursor); page_zip_des_t * const page_zip= page_cur_get_page_zip(cursor);
page_t * const page= cursor->block->page.frame; page_t * const page= cursor->block->page.frame;
dict_index_t * const index = cursor->index;
ut_ad(page_zip); ut_ad(page_zip);
ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_validate(rec, index, offsets));
@@ -1894,8 +1889,7 @@ page_cur_insert_rec_zip(
/* Try compressing the whole page afterwards. */ /* Try compressing the whole page afterwards. */
const mtr_log_t log_mode= mtr->set_log_mode(MTR_LOG_NONE); 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, rec_t *insert_rec= page_cur_insert_rec_low(cursor, rec, offsets, mtr);
mtr);
mtr->set_log_mode(log_mode); mtr->set_log_mode(log_mode);
if (insert_rec) if (insert_rec)
@@ -2243,7 +2237,6 @@ void
page_cur_delete_rec( page_cur_delete_rec(
/*================*/ /*================*/
page_cur_t* cursor, /*!< in/out: a page cursor */ 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( const rec_offs* offsets,/*!< in: rec_get_offsets(
cursor->rec, index) */ cursor->rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */ 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. */ in the smallest user record, it cannot be used here either. */
current_rec = cursor->rec; current_rec = cursor->rec;
const dict_index_t* const index = cursor->index;
buf_block_t* const block = cursor->block; buf_block_t* const block = cursor->block;
ut_ad(rec_offs_validate(current_rec, index, offsets)); ut_ad(rec_offs_validate(current_rec, index, offsets));
ut_ad(!!page_is_comp(block->page.frame) 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* offsets = offsets_;
rec_offs_init(offsets_); rec_offs_init(offsets_);
cur1.index = cur2.index = index;
page_cur_position(rec, block, &cur1); page_cur_position(rec, block, &cur1);
if (page_cur_is_before_first(&cur1) && !page_cur_move_to_next(&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; rec_t* ins_rec;
offsets = rec_get_offsets(cur1.rec, index, offsets, n_core, offsets = rec_get_offsets(cur1.rec, index, offsets, n_core,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
ins_rec = page_cur_insert_rec_low(&cur2, index, ins_rec = page_cur_insert_rec_low(&cur2, cur1.rec, offsets,
cur1.rec, offsets, mtr); mtr);
if (UNIV_UNLIKELY(!ins_rec || !page_cur_move_to_next(&cur1))) { if (UNIV_UNLIKELY(!ins_rec || !page_cur_move_to_next(&cur1))) {
err = DB_CORRUPTION; err = DB_CORRUPTION;
break; break;
@@ -733,6 +734,7 @@ corrupted:
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
} }
cur2.index = index;
page_cur_position(ret, new_block, &cur2); page_cur_position(ret, new_block, &cur2);
const ulint n_core = page_rec_is_leaf(rec) ? index->n_core_fields : 0; 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, offsets = rec_get_offsets(cur1.rec, index, offsets,
n_core, n_core,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
cur2.rec = page_cur_insert_rec_low(&cur2, index, cur2.rec = page_cur_insert_rec_low(&cur2, cur1.rec,
cur1.rec, offsets, offsets, mtr);
mtr);
if (UNIV_UNLIKELY(!cur2.rec if (UNIV_UNLIKELY(!cur2.rec
|| !page_cur_move_to_next(&cur1))) { || !page_cur_move_to_next(&cur1))) {
*err = DB_CORRUPTION; *err = DB_CORRUPTION;
@@ -931,13 +932,14 @@ page_delete_rec_list_end(
{ {
page_cur_t cur; page_cur_t cur;
page_cur_position(rec, block, &cur); page_cur_position(rec, block, &cur);
cur.index= index;
offsets= rec_get_offsets(rec, index, offsets, n_core, offsets= rec_get_offsets(rec, index, offsets, n_core,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
rec= const_cast<rec_t*>(page_rec_get_next_low(rec, true)); rec= const_cast<rec_t*>(page_rec_get_next_low(rec, true));
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(page_zip_validate(&block->page.zip, page, index)); ut_a(page_zip_validate(&block->page.zip, page, index));
#endif /* UNIV_ZIP_DEBUG */ #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); while (page_offset(rec) != PAGE_NEW_SUPREMUM);
@@ -1134,6 +1136,7 @@ page_delete_rec_list_start(
return; return;
} }
cur1.index = index;
page_cur_set_before_first(block, &cur1); page_cur_set_before_first(block, &cur1);
if (UNIV_UNLIKELY(!page_cur_move_to_next(&cur1))) { if (UNIV_UNLIKELY(!page_cur_move_to_next(&cur1))) {
ut_ad("corrupted page" == 0); 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 = rec_get_offsets(page_cur_get_rec(&cur1), index,
offsets, n_core, offsets, n_core,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
page_cur_delete_rec(&cur1, index, offsets, mtr); page_cur_delete_rec(&cur1, offsets, mtr);
} }
if (UNIV_LIKELY_NULL(heap)) { if (UNIV_LIKELY_NULL(heap)) {

View File

@@ -322,13 +322,9 @@ que_graph_free_recursive(
case QUE_NODE_UPDATE: case QUE_NODE_UPDATE:
upd = static_cast<upd_node_t*>(node); 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); que_graph_free_recursive(upd->cascade_node);
ut_free(upd->pcur->old_rec_buf);
upd->pcur->old_rec_buf = NULL;
if (upd->cascade_heap) { if (upd->cascade_heap) {
mem_heap_free(upd->cascade_heap); mem_heap_free(upd->cascade_heap);

View File

@@ -611,7 +611,7 @@ rec_init_offsets(
ulint i = 0; ulint i = 0;
rec_offs offs; 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 call in btr_cur_instant_init_low(). We cannot invoke
index->is_instant(), because the same assertion would fail there index->is_instant(), because the same assertion would fail there
until btr_cur_instant_init_low() has invoked until btr_cur_instant_init_low() has invoked
@@ -839,7 +839,7 @@ rec_get_offsets_func(
bool alter_metadata = false; bool alter_metadata = false;
ut_ad(index->n_core_fields >= n_core); 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 call in btr_cur_instant_init_low(). We cannot invoke
index->is_instant(), because the same assertion would fail there index->is_instant(), because the same assertion would fail there
until btr_cur_instant_init_low() has invoked until btr_cur_instant_init_low() has invoked

View File

@@ -253,9 +253,10 @@ public:
} }
/** Position the cursor on the first user record. */ /** 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)) MY_ATTRIBUTE((warn_unused_result))
{ {
m_cur.index = const_cast<dict_index_t*>(index);
page_cur_set_before_first(block, &m_cur); page_cur_set_before_first(block, &m_cur);
return next(); return next();
} }
@@ -285,10 +286,9 @@ public:
/** Remove the current record /** Remove the current record
@return true on success */ @return true on success */
bool remove( bool remove(rec_offs* offsets) UNIV_NOTHROW
const dict_index_t* index,
rec_offs* offsets) UNIV_NOTHROW
{ {
const dict_index_t* const index = m_cur.index;
ut_ad(page_is_leaf(m_cur.block->page.frame)); ut_ad(page_is_leaf(m_cur.block->page.frame));
/* We can't end up with an empty page unless it is root. */ /* We can't end up with an empty page unless it is root. */
if (page_get_n_recs(m_cur.block->page.frame) <= 1) { if (page_get_n_recs(m_cur.block->page.frame) <= 1) {
@@ -311,7 +311,7 @@ public:
page_zip, m_cur.block->page.frame, index)); page_zip, m_cur.block->page.frame, index));
#endif /* UNIV_ZIP_DEBUG */ #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 #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate( ut_a(!page_zip || page_zip_validate(
@@ -1513,8 +1513,9 @@ inline bool IndexPurge::open() noexcept
m_mtr.start(); m_mtr.start();
m_mtr.set_log_mode(MTR_LOG_NO_REDO); m_mtr.set_log_mode(MTR_LOG_NO_REDO);
if (btr_pcur_open_at_index_side(true, m_index, BTR_MODIFY_LEAF, btr_pcur_init(&m_pcur);
&m_pcur, true, 0, &m_mtr) != DB_SUCCESS)
if (m_pcur.open_leaf(true, m_index, BTR_MODIFY_LEAF, &m_mtr) != DB_SUCCESS)
return false; return false;
rec_t *rec= page_rec_get_next(btr_pcur_get_rec(&m_pcur)); 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; return DB_CORRUPTION;
} }
/* The following is based on btr_pcur_move_to_next_user_rec(). */ /* 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); ut_ad(m_pcur.latch_mode == BTR_MODIFY_LEAF);
do { do {
if (btr_pcur_is_after_last_on_page(&m_pcur)) { 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 inline dberr_t IndexPurge::purge_pessimistic_delete() noexcept
{ {
dberr_t err; dberr_t err;
if (m_pcur.restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, if (m_pcur.restore_position(BTR_PURGE_TREE, &m_mtr) != btr_pcur_t::CORRUPTED)
&m_mtr) != btr_pcur_t::CORRUPTED)
{ {
ut_ad(rec_get_deleted_flag(btr_pcur_get_rec(&m_pcur), ut_ad(rec_get_deleted_flag(btr_pcur_get_rec(&m_pcur),
m_index->table->not_redundant())); m_index->table->not_redundant()));
@@ -1722,10 +1722,8 @@ re-organising the B+tree.
@return true if purge succeeded */ @return true if purge succeeded */
inline bool PageConverter::purge() UNIV_NOTHROW 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. */ /* 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; ++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. */ /* 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; return DB_CORRUPTION;
} }
@@ -2289,8 +2287,8 @@ row_import_set_sys_max_row_id(
mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
if (btr_pcur_open_at_index_side(false, index, BTR_SEARCH_LEAF, if (pcur.open_leaf(false, index, BTR_SEARCH_LEAF, &mtr)
&pcur, true, 0, &mtr) == DB_SUCCESS) { == DB_SUCCESS) {
rec = btr_pcur_move_to_prev_on_page(&pcur); rec = btr_pcur_move_to_prev_on_page(&pcur);
if (!rec) { if (!rec) {

View File

@@ -174,7 +174,7 @@ dberr_t
row_ins_sec_index_entry_by_modify( row_ins_sec_index_entry_by_modify(
/*==============================*/ /*==============================*/
ulint flags, /*!< in: undo logging and locking flags */ 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 depending on whether mtr holds just a leaf
latch or also a tree latch */ latch or also a tree latch */
btr_cur_t* cursor, /*!< in: B-tree cursor */ 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); rec = btr_cur_get_rec(cursor);
ut_ad(!dict_index_is_clust(cursor->index)); ut_ad(!cursor->index()->is_clust());
ut_ad(rec_offs_validate(rec, cursor->index, *offsets)); ut_ad(rec_offs_validate(rec, cursor->index(), *offsets));
ut_ad(!entry->info_bits); ut_ad(!entry->info_bits);
/* We know that in the alphabetical ordering, entry and rec are /* We know that in the alphabetical ordering, entry and rec are
@@ -204,7 +204,7 @@ row_ins_sec_index_entry_by_modify(
difference. */ difference. */
update = row_upd_build_sec_rec_difference_binary( 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))) { if (!rec_get_deleted_flag(rec, rec_offs_comp(*offsets))) {
/* We should never insert in place of a record that /* 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) returns. After that point, set_committed(true)
would be invoked in commit_inplace_alter_table(). */ would be invoked in commit_inplace_alter_table(). */
ut_a(update->n_fields == 0); ut_a(update->n_fields == 0);
ut_a(!cursor->index->is_committed()); ut_a(!cursor->index()->is_committed());
ut_ad(!dict_index_is_online_ddl(cursor->index)); ut_ad(!dict_index_is_online_ddl(cursor->index()));
return(DB_SUCCESS); return(DB_SUCCESS);
} }
@@ -241,7 +241,7 @@ row_ins_sec_index_entry_by_modify(
break; break;
} }
} else { } else {
ut_a(mode == BTR_MODIFY_TREE); ut_ad(mode == BTR_INSERT_TREE);
if (buf_pool.running_out()) { if (buf_pool.running_out()) {
return(DB_LOCK_TABLE_FULL); return(DB_LOCK_TABLE_FULL);
@@ -288,15 +288,15 @@ row_ins_clust_index_entry_by_modify(
dberr_t err = DB_SUCCESS; dberr_t err = DB_SUCCESS;
btr_cur_t* cursor = btr_pcur_get_btr_cur(pcur); btr_cur_t* cursor = btr_pcur_get_btr_cur(pcur);
TABLE* mysql_table = NULL; TABLE* mysql_table = NULL;
ut_ad(dict_index_is_clust(cursor->index)); ut_ad(cursor->index()->is_clust());
rec = btr_cur_get_rec(cursor); rec = btr_cur_get_rec(cursor);
ut_ad(rec_get_deleted_flag(rec, 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 /* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */ 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; /* Build an update vector containing all the fields to be modified;
NOTE that this vector may NOT contain system columns trx_id or 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( 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); thr_get_trx(thr), heap, mysql_table, &err);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(err); return(err);
@@ -1115,7 +1115,7 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func; goto nonstandard_exit_func;
} }
index = btr_pcur_get_btr_cur(pcur)->index; index = pcur->index();
ut_a(index == foreign->foreign_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, ref = row_build_row_ref(ROW_COPY_POINTERS, index, rec,
tmp_heap); 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, PAGE_CUR_LE, BTR_SEARCH_LEAF,
cascade->pcur, mtr); cascade->pcur, mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) { if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
@@ -1622,9 +1624,9 @@ row_ins_check_foreign_constraint(
n_fields_cmp = dtuple_get_n_fields_cmp(entry); n_fields_cmp = dtuple_get_n_fields_cmp(entry);
dtuple_set_n_fields_cmp(entry, foreign->n_fields); dtuple_set_n_fields_cmp(entry, foreign->n_fields);
pcur.btr_cur.page_cur.index = check_index;
err = btr_pcur_open(check_index, entry, PAGE_CUR_GE, err = btr_pcur_open(entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, 0,
BTR_SEARCH_LEAF, &pcur, &mtr); &mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) { if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
goto end_scan; goto end_scan;
} }
@@ -2064,9 +2066,9 @@ row_ins_scan_sec_index_for_duplicate(
dtuple_set_n_fields_cmp(entry, n_unique); dtuple_set_n_fields_cmp(entry, n_unique);
const auto allow_duplicates = thr_get_trx(thr)->duplicates; const auto allow_duplicates = thr_get_trx(thr)->duplicates;
pcur.btr_cur.page_cur.index = index;
dberr_t err = btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, dberr_t err = btr_pcur_open(entry, PAGE_CUR_GE, BTR_SEARCH_LEAF,
&pcur, mtr); &pcur, 0, mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
goto end_scan; goto end_scan;
} }
@@ -2220,14 +2222,14 @@ row_ins_duplicate_error_in_clust_online(
dberr_t err = DB_SUCCESS; dberr_t err = DB_SUCCESS;
const rec_t* rec = btr_cur_get_rec(cursor); 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)) { if (cursor->low_match >= n_uniq && !page_rec_is_infimum(rec)) {
*offsets = rec_get_offsets(rec, cursor->index, *offsets, *offsets = rec_get_offsets(rec, cursor->index(), *offsets,
cursor->index->n_fields, cursor->index()->n_fields,
ULINT_UNDEFINED, heap); ULINT_UNDEFINED, heap);
err = row_ins_duplicate_online(n_uniq, entry, err = row_ins_duplicate_online(n_uniq, entry,
rec, cursor->index, *offsets); rec, cursor->index(), *offsets);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(err); return(err);
} }
@@ -2238,11 +2240,11 @@ row_ins_duplicate_error_in_clust_online(
} }
if (cursor->up_match >= n_uniq && !page_rec_is_supremum(rec)) { if (cursor->up_match >= n_uniq && !page_rec_is_supremum(rec)) {
*offsets = rec_get_offsets(rec, cursor->index, *offsets, *offsets = rec_get_offsets(rec, cursor->index(), *offsets,
cursor->index->n_fields, cursor->index()->n_fields,
ULINT_UNDEFINED, heap); ULINT_UNDEFINED, heap);
err = row_ins_duplicate_online(n_uniq, entry, err = row_ins_duplicate_online(n_uniq, entry,
rec, cursor->index, *offsets); rec, cursor->index(), *offsets);
} }
return(err); return(err);
@@ -2273,7 +2275,7 @@ row_ins_duplicate_error_in_clust(
rec_offs* offsets = offsets_; rec_offs* offsets = offsets_;
rec_offs_init(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 /* NOTE: For unique non-clustered indexes there may be any number
of delete marked records with the same value for the non-clustered 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 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. */ 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) { if (cursor->low_match >= n_unique) {
rec = btr_cur_get_rec(cursor); rec = btr_cur_get_rec(cursor);
if (!page_rec_is_infimum(rec)) { if (!page_rec_is_infimum(rec)) {
offsets = rec_get_offsets(rec, cursor->index, offsets, offsets = rec_get_offsets(rec, cursor->index(),
cursor->index->n_core_fields, offsets,
cursor->index()
->n_core_fields,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
/* We set a lock on the possible duplicate: this /* 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( err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP, LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor), btr_cur_get_block(cursor),
rec, cursor->index, offsets, thr); rec, cursor->index(), offsets, thr);
} else { } else {
err = row_ins_set_shared_rec_lock( err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP, LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor), rec, btr_cur_get_block(cursor), rec,
cursor->index, offsets, thr); cursor->index(), offsets, thr);
} }
switch (err) { switch (err) {
@@ -2335,11 +2339,11 @@ row_ins_duplicate_error_in_clust(
} }
if (row_ins_dupl_error_with_rec( if (row_ins_dupl_error_with_rec(
rec, entry, cursor->index, offsets)) { rec, entry, cursor->index(), offsets)) {
duplicate: duplicate:
trx->error_info = cursor->index; trx->error_info = cursor->index();
err = DB_DUPLICATE_KEY; err = DB_DUPLICATE_KEY;
if (cursor->index->table->versioned() if (cursor->index()->table->versioned()
&& entry->vers_history_row()) && entry->vers_history_row())
{ {
ulint trx_id_len; ulint trx_id_len;
@@ -2363,8 +2367,10 @@ duplicate:
rec = page_rec_get_next(btr_cur_get_rec(cursor)); rec = page_rec_get_next(btr_cur_get_rec(cursor));
if (rec && !page_rec_is_supremum(rec)) { if (rec && !page_rec_is_supremum(rec)) {
offsets = rec_get_offsets(rec, cursor->index, offsets, offsets = rec_get_offsets(rec, cursor->index(),
cursor->index->n_core_fields, offsets,
cursor->index()
->n_core_fields,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
if (trx->duplicates) { if (trx->duplicates) {
@@ -2377,13 +2383,13 @@ duplicate:
err = row_ins_set_exclusive_rec_lock( err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP, LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor), btr_cur_get_block(cursor),
rec, cursor->index, offsets, thr); rec, cursor->index(), offsets, thr);
} else { } else {
err = row_ins_set_shared_rec_lock( err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP, LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor), btr_cur_get_block(cursor),
rec, cursor->index, offsets, thr); rec, cursor->index(), offsets, thr);
} }
switch (err) { switch (err) {
@@ -2394,7 +2400,7 @@ duplicate:
/* fall through */ /* fall through */
case DB_SUCCESS: case DB_SUCCESS:
if (row_ins_dupl_error_with_rec( if (row_ins_dupl_error_with_rec(
rec, entry, cursor->index, rec, entry, cursor->index(),
offsets)) { offsets)) {
goto duplicate; goto duplicate;
} }
@@ -2436,7 +2442,7 @@ row_ins_must_modify_rec(
and a secondary index node pointer contains all index fields. */ and a secondary index node pointer contains all index fields. */
return(cursor->low_match 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))); && !page_rec_is_infimum(btr_cur_get_rec(cursor)));
} }
@@ -2465,6 +2471,7 @@ row_ins_index_entry_big_rec(
btr_pcur_t pcur; btr_pcur_t pcur;
rec_t* rec; rec_t* rec;
pcur.btr_cur.page_cur.index = index;
ut_ad(index->is_primary()); ut_ad(index->is_primary());
DEBUG_SYNC_C_IF_THD(thd, "before_row_ins_extern_latch"); 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); index->set_modified(mtr);
} }
dberr_t error = btr_pcur_open(index, entry, PAGE_CUR_LE, dberr_t error = btr_pcur_open(entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &pcur, &mtr); BTR_MODIFY_TREE, &pcur, 0, &mtr);
if (error != DB_SUCCESS) { if (error != DB_SUCCESS) {
return error; return error;
} }
@@ -2525,7 +2532,7 @@ dberr_t
row_ins_clust_index_entry_low( row_ins_clust_index_entry_low(
/*==========================*/ /*==========================*/
ulint flags, /*!< in: undo logging and locking flags */ 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 depending on whether we wish optimistic or
pessimistic descent down the index tree */ pessimistic descent down the index tree */
dict_index_t* index, /*!< in: clustered index */ dict_index_t* index, /*!< in: clustered index */
@@ -2578,7 +2585,7 @@ row_ins_clust_index_entry_low(
} else { } else {
if (mode == BTR_MODIFY_LEAF if (mode == BTR_MODIFY_LEAF
&& dict_index_is_online_ddl(index)) { && 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); 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 /* 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 the function will return in both low_match and up_match of the
cursor sensible values */ cursor sensible values */
err = btr_pcur_open_low(index, 0, entry, PAGE_CUR_LE, mode, &pcur, pcur.btr_cur.page_cur.index = index;
auto_inc, &mtr); err = btr_pcur_open(entry, PAGE_CUR_LE, mode, &pcur, auto_inc, &mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
index->table->file_unreadable = true; index->table->file_unreadable = true;
commit_exit: commit_exit:
@@ -2732,7 +2739,7 @@ skip_bulk_insert:
/* fall through */ /* fall through */
case DB_SUCCESS_LOCKED_REC: case DB_SUCCESS_LOCKED_REC:
case DB_DUPLICATE_KEY: case DB_DUPLICATE_KEY:
trx->error_info = cursor->index; trx->error_info = cursor->index();
} }
} else { } else {
/* Note that the following may return also /* Note that the following may return also
@@ -2769,8 +2776,8 @@ do_insert:
rec_t* insert_rec; rec_t* insert_rec;
if (mode != BTR_MODIFY_TREE) { if (mode != BTR_MODIFY_TREE) {
ut_ad((mode & ulint(~BTR_ALREADY_S_LATCHED)) ut_ad(mode == BTR_MODIFY_LEAF ||
== BTR_MODIFY_LEAF); mode == BTR_MODIFY_LEAF_ALREADY_LATCHED);
err = btr_cur_optimistic_insert( err = btr_cur_optimistic_insert(
flags, cursor, &offsets, &offsets_heap, flags, cursor, &offsets, &offsets_heap,
entry, &insert_rec, &big_rec, 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. It is then unmarked. Otherwise, the entry is just inserted to the index.
@retval DB_SUCCESS on success @retval DB_SUCCESS on success
@retval DB_LOCK_WAIT on lock wait when !(flags & BTR_NO_LOCKING_FLAG) @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 */ @return error code */
dberr_t dberr_t
row_ins_sec_index_entry_low( row_ins_sec_index_entry_low(
/*========================*/ /*========================*/
ulint flags, /*!< in: undo logging and locking flags */ 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 depending on whether we wish optimistic or
pessimistic descent down the index tree */ pessimistic descent down the index tree */
dict_index_t* index, /*!< in: secondary index */ 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"); DBUG_ENTER("row_ins_sec_index_entry_low");
btr_cur_t cursor; btr_cur_t cursor;
ulint search_mode = mode; btr_latch_mode search_mode = mode;
dberr_t err; dberr_t err;
ulint n_unique; ulint n_unique;
mtr_t mtr; mtr_t mtr;
@@ -2877,10 +2884,11 @@ row_ins_sec_index_entry_low(
rtr_info_t rtr_info; rtr_info_t rtr_info;
ut_ad(!dict_index_is_clust(index)); 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.thr = thr;
cursor.rtr_info = NULL; cursor.rtr_info = NULL;
cursor.page_cur.index = index;
ut_ad(thr_get_trx(thr)->id != 0); ut_ad(thr_get_trx(thr)->id != 0);
mtr.start(); mtr.start();
@@ -2892,24 +2900,19 @@ row_ins_sec_index_entry_low(
mtr.set_log_mode(MTR_LOG_NO_REDO); mtr.set_log_mode(MTR_LOG_NO_REDO);
} else { } else {
index->set_modified(mtr); 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 /* 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 the function will return in both low_match and up_match of the
cursor sensible values */ cursor sensible values */
if (dict_index_is_spatial(index)) { if (index->is_spatial()) {
cursor.index = index;
rtr_init_rtr_info(&rtr_info, false, &cursor, index, false); rtr_init_rtr_info(&rtr_info, false, &cursor, index, false);
rtr_info_update_btr(&cursor, &rtr_info); rtr_info_update_btr(&cursor, &rtr_info);
err = btr_cur_search_to_nth_level( err = btr_cur_search_to_nth_level(0, entry,
index, 0, entry, PAGE_CUR_RTREE_INSERT, PAGE_CUR_RTREE_INSERT,
search_mode, search_mode, &cursor, &mtr);
&cursor, &mtr);
if (err == DB_SUCCESS && search_mode == BTR_MODIFY_LEAF if (err == DB_SUCCESS && search_mode == BTR_MODIFY_LEAF
&& rtr_info.mbr_adj) { && rtr_info.mbr_adj) {
@@ -2926,9 +2929,8 @@ row_ins_sec_index_entry_low(
index->set_modified(mtr); index->set_modified(mtr);
} }
err = btr_cur_search_to_nth_level( err = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_RTREE_INSERT, 0, entry, PAGE_CUR_RTREE_INSERT,
search_mode, search_mode, &cursor, &mtr);
&cursor, &mtr);
} }
DBUG_EXECUTE_IF( DBUG_EXECUTE_IF(
@@ -2936,14 +2938,16 @@ row_ins_sec_index_entry_low(
goto func_exit;}); goto func_exit;});
} else { } else {
if (!thr_get_trx(thr)->check_unique_secondary) { if (!index->table->is_temporary()) {
search_mode |= BTR_IGNORE_SEC_UNIQUE; 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( err = btr_cur_search_to_nth_level(0, entry, PAGE_CUR_LE,
index, 0, entry, PAGE_CUR_LE, search_mode, &cursor, &mtr);
search_mode,
&cursor, &mtr);
} }
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
@@ -3018,11 +3022,12 @@ row_ins_sec_index_entry_low(
locked with s-locks the necessary records to locked with s-locks the necessary records to
prevent any insertion of a duplicate by another prevent any insertion of a duplicate by another
transaction. Let us now reposition the cursor and 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( err = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE, 0, entry, PAGE_CUR_LE,
(search_mode btr_latch_mode(search_mode
& ~(BTR_INSERT | BTR_IGNORE_SEC_UNIQUE)), & ~(BTR_INSERT
| BTR_IGNORE_SEC_UNIQUE)),
&cursor, &mtr); &cursor, &mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
goto func_exit; goto func_exit;
@@ -3061,7 +3066,6 @@ row_ins_sec_index_entry_low(
err = rtr_ins_enlarge_mbr(&cursor, &mtr); err = rtr_ins_enlarge_mbr(&cursor, &mtr);
} }
} else { } else {
ut_ad(mode == BTR_MODIFY_TREE);
if (buf_pool.running_out()) { if (buf_pool.running_out()) {
err = DB_LOCK_TABLE_FULL; err = DB_LOCK_TABLE_FULL;
goto func_exit; goto func_exit;
@@ -3264,7 +3268,7 @@ row_ins_sec_index_entry(
log_free_check(); log_free_check();
err = row_ins_sec_index_entry_low( err = row_ins_sec_index_entry_low(
flags, BTR_MODIFY_TREE, index, flags, BTR_INSERT_TREE, index,
offsets_heap, heap, entry, 0, thr); 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); entry = row_build_index_entry(row, NULL, index, heap);
error = row_ins_sec_index_entry_low( error = row_ins_sec_index_entry_low(
flags, BTR_MODIFY_TREE, flags, BTR_INSERT_TREE,
index, offsets_heap, heap, entry, index, offsets_heap, heap, entry,
thr_get_trx(thr)->id, thr); thr_get_trx(thr)->id, thr);
@@ -1658,7 +1658,7 @@ row_log_table_apply_delete_low(
dberr_t error; dberr_t error;
row_ext_t* ext; row_ext_t* ext;
dtuple_t* row; 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)); ut_ad(dict_index_is_clust(index));
@@ -1695,9 +1695,9 @@ err_exit:
row, ext, index, heap); row, ext, index, heap);
mtr->start(); mtr->start();
index->set_modified(*mtr); index->set_modified(*mtr);
error = btr_pcur_open(index, entry, PAGE_CUR_LE, pcur->btr_cur.page_cur.index = index;
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, error = btr_pcur_open(entry, PAGE_CUR_LE,
pcur, mtr); BTR_PURGE_TREE, pcur, 0, mtr);
if (error) { if (error) {
goto err_exit; goto err_exit;
} }
@@ -1761,6 +1761,7 @@ row_log_table_apply_delete(
btr_pcur_t pcur; btr_pcur_t pcur;
rec_offs* offsets; 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_n_fields(moffsets) == index->first_user_field());
ut_ad(!rec_offs_any_extern(moffsets)); ut_ad(!rec_offs_any_extern(moffsets));
@@ -1779,9 +1780,8 @@ row_log_table_apply_delete(
mtr_start(&mtr); mtr_start(&mtr);
index->set_modified(mtr); index->set_modified(mtr);
dberr_t err = btr_pcur_open(index, old_pk, PAGE_CUR_LE, dberr_t err = btr_pcur_open(old_pk, PAGE_CUR_LE,
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, BTR_PURGE_TREE, &pcur, 0, &mtr);
&pcur, &mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
goto all_done; goto all_done;
} }
@@ -1893,6 +1893,8 @@ row_log_table_apply_update(
dberr_t error; dberr_t error;
ulint n_index = 0; ulint n_index = 0;
pcur.btr_cur.page_cur.index = index;
ut_ad(dtuple_get_n_fields_cmp(old_pk) ut_ad(dtuple_get_n_fields_cmp(old_pk)
== dict_index_get_n_unique(index)); == dict_index_get_n_unique(index));
ut_ad(dtuple_get_n_fields(old_pk) - (log->same_pk ? 0 : 2) ut_ad(dtuple_get_n_fields(old_pk) - (log->same_pk ? 0 : 2)
@@ -1915,8 +1917,8 @@ row_log_table_apply_update(
mtr.start(); mtr.start();
index->set_modified(mtr); index->set_modified(mtr);
error = btr_pcur_open(index, old_pk, PAGE_CUR_LE, error = btr_pcur_open(old_pk, PAGE_CUR_LE,
BTR_MODIFY_TREE, &pcur, &mtr); BTR_MODIFY_TREE, &pcur, 0, &mtr);
if (error != DB_SUCCESS) { if (error != DB_SUCCESS) {
func_exit: func_exit:
mtr.commit(); mtr.commit();
@@ -2061,7 +2063,7 @@ func_exit_committed:
for (n_index += index->type != DICT_CLUSTERED; for (n_index += index->type != DICT_CLUSTERED;
(index = dict_table_get_next_index(index)); n_index++) { (index = dict_table_get_next_index(index)); n_index++) {
if (index->type & DICT_FTS) { if (!index->is_btree()) {
continue; continue;
} }
@@ -2089,9 +2091,10 @@ func_exit_committed:
mtr.start(); mtr.start();
index->set_modified(mtr); index->set_modified(mtr);
pcur.btr_cur.page_cur.index = index;
if (ROW_FOUND != row_search_index_entry( if (ROW_FOUND != row_search_index_entry(
index, entry, BTR_MODIFY_TREE, &pcur, &mtr)) { entry, BTR_MODIFY_TREE, &pcur, &mtr)) {
ut_ad(0); ut_ad(0);
error = DB_CORRUPTION; error = DB_CORRUPTION;
break; break;
@@ -2111,7 +2114,7 @@ func_exit_committed:
error = row_ins_sec_index_entry_low( error = row_ins_sec_index_entry_low(
BTR_CREATE_FLAG | BTR_NO_LOCKING_FLAG BTR_CREATE_FLAG | BTR_NO_LOCKING_FLAG
| BTR_NO_UNDO_LOG_FLAG | BTR_KEEP_SYS_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); entry, thr_get_trx(thr)->id, thr);
/* Report correct index name for duplicate key error. */ /* Report correct index name for duplicate key error. */
@@ -3071,13 +3074,14 @@ row_log_apply_op_low(
mtr_start(&mtr); mtr_start(&mtr);
index->set_modified(mtr); index->set_modified(mtr);
cursor.page_cur.index = index;
/* We perform the pessimistic variant of the operations if we /* We perform the pessimistic variant of the operations if we
already hold index->lock exclusively. First, search the already hold index->lock exclusively. First, search the
record. The operation may already have been performed, record. The operation may already have been performed,
depending on when the row in the clustered index was depending on when the row in the clustered index was
scanned. */ 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 has_index_lock
? BTR_MODIFY_TREE ? BTR_MODIFY_TREE
: BTR_MODIFY_LEAF, : BTR_MODIFY_LEAF,
@@ -3132,7 +3136,7 @@ row_log_apply_op_low(
mtr_start(&mtr); mtr_start(&mtr);
index->set_modified(mtr); index->set_modified(mtr);
*error = btr_cur_search_to_nth_level( *error = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE, 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, &mtr); BTR_MODIFY_TREE, &cursor, &mtr);
if (UNIV_UNLIKELY(*error != DB_SUCCESS)) { if (UNIV_UNLIKELY(*error != DB_SUCCESS)) {
goto func_exit; goto func_exit;
@@ -3236,7 +3240,7 @@ insert_the_rec:
mtr_start(&mtr); mtr_start(&mtr);
index->set_modified(mtr); index->set_modified(mtr);
*error = btr_cur_search_to_nth_level( *error = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE, 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, &mtr); BTR_MODIFY_TREE, &cursor, &mtr);
if (*error != DB_SUCCESS) { if (*error != DB_SUCCESS) {
break; break;
@@ -3951,8 +3955,8 @@ void UndorecApplier::log_insert(const dtuple_t &tuple,
} }
bool success= true; bool success= true;
dict_index_t *index= dict_table_get_next_index(clust_index); for (dict_index_t *index= clust_index;
while (index) (index= dict_table_get_next_index(index)) != nullptr; )
{ {
index->lock.s_lock(SRW_LOCK_CALL); index->lock.s_lock(SRW_LOCK_CALL);
if (index->online_log && 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); row_log_mark_other_online_index_abort(index->table);
return; return;
} }
index= dict_table_get_next_index(index);
} }
} }
} }

View File

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

View File

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

View File

@@ -67,7 +67,7 @@ static
ibool ibool
row_purge_reposition_pcur( row_purge_reposition_pcur(
/*======================*/ /*======================*/
ulint mode, /*!< in: latching mode */ btr_latch_mode mode, /*!< in: latching mode */
purge_node_t* node, /*!< in: row purge node */ purge_node_t* node, /*!< in: row purge node */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
@@ -104,7 +104,7 @@ bool
row_purge_remove_clust_if_poss_low( row_purge_remove_clust_if_poss_low(
/*===============================*/ /*===============================*/
purge_node_t* node, /*!< in/out: row purge node */ 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); dict_index_t* index = dict_table_get_first_index(node->table);
table_id_t table_id = 0; table_id_t table_id = 0;
@@ -216,7 +216,7 @@ close_and_exit:
btr_pcur_get_btr_cur(&node->pcur), 0, &mtr); btr_pcur_get_btr_cur(&node->pcur), 0, &mtr);
} else { } else {
dberr_t err; dberr_t err;
ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE)); ut_ad(mode == BTR_PURGE_TREE);
btr_cur_pessimistic_delete( btr_cur_pessimistic_delete(
&err, FALSE, btr_pcur_get_btr_cur(&node->pcur), 0, &err, FALSE, btr_pcur_get_btr_cur(&node->pcur), 0,
false, &mtr); false, &mtr);
@@ -257,8 +257,7 @@ row_purge_remove_clust_if_poss(
for (ulint n_tries = 0; for (ulint n_tries = 0;
n_tries < BTR_CUR_RETRY_DELETE_N_TIMES; n_tries < BTR_CUR_RETRY_DELETE_N_TIMES;
n_tries++) { n_tries++) {
if (row_purge_remove_clust_if_poss_low( if (row_purge_remove_clust_if_poss_low(node, BTR_PURGE_TREE)) {
node, BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE)) {
return(true); return(true);
} }
@@ -348,10 +347,9 @@ row_purge_remove_sec_if_poss_tree(
log_free_check(); log_free_check();
mtr.start(); mtr.start();
index->set_modified(mtr); index->set_modified(mtr);
pcur.btr_cur.page_cur.index = index;
search_result = row_search_index_entry( search_result = row_search_index_entry(entry, BTR_PURGE_TREE,
index, entry,
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
&pcur, &mtr); &pcur, &mtr);
switch (search_result) { switch (search_result) {
@@ -455,6 +453,7 @@ row_purge_remove_sec_if_poss_leaf(
virtual index. */ virtual index. */
mode = (index->type & (DICT_SPATIAL | DICT_VIRTUAL)) mode = (index->type & (DICT_SPATIAL | DICT_VIRTUAL))
? BTR_MODIFY_LEAF : BTR_PURGE_LEAF; ? 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(). */ /* Set the purge node for the call to row_purge_poss_sec(). */
pcur.btr_cur.purge_node = node; pcur.btr_cur.purge_node = node;
@@ -462,7 +461,7 @@ row_purge_remove_sec_if_poss_leaf(
pcur.btr_cur.thr = NULL; pcur.btr_cur.thr = NULL;
index->lock.u_lock(SRW_LOCK_CALL); index->lock.u_lock(SRW_LOCK_CALL);
search_result = row_search_index_entry( search_result = row_search_index_entry(
index, entry, mode, &pcur, &mtr); entry, mode, &pcur, &mtr);
index->lock.u_unlock(); index->lock.u_unlock();
} else { } else {
/* Set the query thread, so that ibuf_insert_low() will be /* 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*>( pcur.btr_cur.thr = static_cast<que_thr_t*>(
que_node_get_parent(node)); que_node_get_parent(node));
search_result = row_search_index_entry( search_result = row_search_index_entry(
index, entry, mode, &pcur, &mtr); entry, mode, &pcur, &mtr);
} }
switch (search_result) { switch (search_result) {
@@ -1343,11 +1342,11 @@ purge_node_t::validate_pcur()
return(true); return(true);
} }
if (!pcur.old_stored) { if (!pcur.old_rec) {
return(true); return(true);
} }
dict_index_t* clust_index = pcur.btr_cur.index; dict_index_t* clust_index = pcur.index();
rec_offs* offsets = rec_get_offsets( rec_offs* offsets = rec_get_offsets(
pcur.old_rec, clust_index, NULL, pcur.old_n_core_fields, 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. Searches the clustered index record for a row, if we have the row reference.
@return TRUE if found */ @return TRUE if found */
ibool bool
row_search_on_row_ref( row_search_on_row_ref(
/*==================*/ /*==================*/
btr_pcur_t* pcur, /*!< out: persistent cursor, which must btr_pcur_t* pcur, /*!< out: persistent cursor, which must
be closed by the caller */ 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 dict_table_t* table, /*!< in: table */
const dtuple_t* ref, /*!< in: row reference */ const dtuple_t* ref, /*!< in: row reference */
mtr_t* mtr) /*!< in/out: mtr */ mtr_t* mtr) /*!< in/out: mtr */
{ {
ulint low_match;
rec_t* rec;
dict_index_t* index;
ut_ad(dtuple_check_typed(ref)); 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)) { if (UNIV_UNLIKELY(ref->info_bits != 0)) {
ut_ad(ref->is_metadata()); ut_ad(ref->is_metadata());
ut_ad(ref->n_fields <= index->n_uniq); ut_ad(ref->n_fields <= index->n_uniq);
if (btr_pcur_open_at_index_side( if (pcur->open_leaf(true, index, mode, mtr) != DB_SUCCESS
true, index, mode, pcur, true, 0, mtr)
!= DB_SUCCESS
|| !btr_pcur_move_to_next_user_rec(pcur, mtr)) { || !btr_pcur_move_to_next_user_rec(pcur, mtr)) {
return FALSE; return false;
} }
/* We do not necessarily have index->is_instant() here, /* We do not necessarily have index->is_instant() here,
because we could be executing a rollback of an because we could be executing a rollback of an
@@ -1220,27 +1216,14 @@ row_search_on_row_ref(
& REC_INFO_MIN_REC_FLAG; & REC_INFO_MIN_REC_FLAG;
} else { } else {
ut_a(ref->n_fields == index->n_uniq); 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) { != DB_SUCCESS) {
return FALSE; return false;
} }
} }
low_match = btr_pcur_get_low_match(pcur); return !page_rec_is_infimum(btr_pcur_get_rec(pcur))
&& btr_pcur_get_low_match(pcur) == dtuple_get_n_fields(ref);
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);
} }
/*********************************************************************//** /*********************************************************************//**
@@ -1250,7 +1233,7 @@ on the secondary index record are preserved.
rec_t* rec_t*
row_get_clust_rec( 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 */ const rec_t* rec, /*!< in: record in a secondary index */
dict_index_t* index, /*!< in: secondary index */ dict_index_t* index, /*!< in: secondary index */
dict_index_t** clust_index,/*!< out: clustered index */ dict_index_t** clust_index,/*!< out: clustered index */
@@ -1283,9 +1266,8 @@ Searches an index record.
enum row_search_result enum row_search_result
row_search_index_entry( row_search_index_entry(
/*===================*/ /*===================*/
dict_index_t* index, /*!< in: index */
const dtuple_t* entry, /*!< in: index entry */ 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 btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must
be closed by the caller */ be closed by the caller */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
@@ -1296,12 +1278,12 @@ row_search_index_entry(
ut_ad(dtuple_check_typed(entry)); ut_ad(dtuple_check_typed(entry));
if (index->is_spatial()) { if (pcur->index()->is_spatial()) {
if (rtr_pcur_open(index, entry, mode, pcur, mtr)) { if (rtr_pcur_open(pcur->index(), entry, mode, pcur, mtr)) {
return ROW_NOT_FOUND; return ROW_NOT_FOUND;
} }
} else { } 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) { != DB_SUCCESS) {
return ROW_NOT_FOUND; return ROW_NOT_FOUND;
} }
@@ -1310,7 +1292,7 @@ row_search_index_entry(
switch (btr_pcur_get_btr_cur(pcur)->flag) { switch (btr_pcur_get_btr_cur(pcur)->flag) {
case BTR_CUR_DELETE_REF: case BTR_CUR_DELETE_REF:
ut_ad(!(~mode & BTR_DELETE)); ut_ad(!(~mode & BTR_DELETE));
ut_ad(!index->is_spatial()); ut_ad(!pcur->index()->is_spatial());
return(ROW_NOT_DELETED_REF); return(ROW_NOT_DELETED_REF);
case BTR_CUR_DEL_MARK_IBUF: case BTR_CUR_DEL_MARK_IBUF:

View File

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

View File

@@ -68,7 +68,7 @@ row_undo_ins_remove_clust_rec(
dberr_t err; dberr_t err;
ulint n_tries = 0; ulint n_tries = 0;
mtr_t mtr; 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; table_id_t table_id = 0;
const bool dict_locked = node->trx->dict_operation_lock_mode; const bool dict_locked = node->trx->dict_operation_lock_mode;
restart: restart:
@@ -207,9 +207,8 @@ retry:
} else { } else {
index->set_modified(mtr); index->set_modified(mtr);
} }
ut_a( ut_a(node->pcur.restore_position(BTR_PURGE_TREE, &mtr)
node->pcur.restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, == btr_pcur_t::SAME_ALL);
&mtr) == btr_pcur_t::SAME_ALL);
btr_cur_pessimistic_delete(&err, FALSE, &node->pcur.btr_cur, 0, true, btr_cur_pessimistic_delete(&err, FALSE, &node->pcur.btr_cur, 0, true,
&mtr); &mtr);
@@ -254,7 +253,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t dberr_t
row_undo_ins_remove_sec_low( 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 depending on whether we wish optimistic or
pessimistic descent down the index tree */ pessimistic descent down the index tree */
dict_index_t* index, /*!< in: index */ dict_index_t* index, /*!< in: index */
@@ -266,25 +265,27 @@ row_undo_ins_remove_sec_low(
mtr_t mtr; mtr_t mtr;
const bool modify_leaf = mode == BTR_MODIFY_LEAF; const bool modify_leaf = mode == BTR_MODIFY_LEAF;
pcur.btr_cur.page_cur.index = index;
row_mtr_start(&mtr, index, !modify_leaf); row_mtr_start(&mtr, index, !modify_leaf);
if (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); mtr_s_lock_index(index, &mtr);
} else { } else {
ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE)); ut_ad(mode == BTR_PURGE_TREE);
mtr_sx_lock_index(index, &mtr); mtr_sx_lock_index(index, &mtr);
} }
if (dict_index_is_spatial(index)) { if (index->is_spatial()) {
if (modify_leaf) { mode = modify_leaf
mode |= BTR_RTREE_DELETE_MARK; ? 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; 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_BUFFERED:
case ROW_NOT_DELETED_REF: case ROW_NOT_DELETED_REF:
/* These are invalid outcomes, because the mode passed /* 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 */ /* Try then pessimistic descent to the B-tree */
retry: retry:
err = row_undo_ins_remove_sec_low( err = row_undo_ins_remove_sec_low(BTR_PURGE_TREE, index, entry, thr);
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
index, entry, thr);
/* The delete operation may fail if we have little /* The delete operation may fail if we have little
file space left: TODO: easiest to crash the database 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 */ que_thr_t* thr, /*!< in: query thread */
mtr_t* mtr, /*!< in: mtr; must be committed before mtr_t* mtr, /*!< in: mtr; must be committed before
latching any further pages */ 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_pcur_t* pcur;
btr_cur_t* btr_cur; btr_cur_t* btr_cur;
@@ -106,8 +106,8 @@ row_undo_mod_clust_low(
|| node->update->info_bits == REC_INFO_METADATA_ALTER); || node->update->info_bits == REC_INFO_METADATA_ALTER);
if (mode != BTR_MODIFY_TREE) { if (mode != BTR_MODIFY_TREE) {
ut_ad((mode & ulint(~BTR_ALREADY_S_LATCHED)) ut_ad(mode == BTR_MODIFY_LEAF
== BTR_MODIFY_LEAF); || mode == BTR_MODIFY_LEAF_ALREADY_LATCHED);
err = btr_cur_optimistic_update( err = btr_cur_optimistic_update(
BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG 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()); ut_ad(!node.table->is_temporary());
const btr_cur_t &btr_cur= node.pcur.btr_cur; 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"); DEBUG_SYNC_C("rollback_purge_clust");
if (!purge_sys.is_purgeable(node.new_trx_id)) if (!purge_sys.is_purgeable(node.new_trx_id))
return false; return false;
const rec_t *rec= btr_cur_get_rec(&btr_cur); 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; node.new_trx_id;
} }
@@ -356,8 +356,7 @@ row_undo_mod_clust(
} }
mtr.start(); mtr.start();
if (pcur->restore_position( if (pcur->restore_position(BTR_PURGE_TREE, &mtr) !=
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, &mtr) !=
btr_pcur_t::SAME_ALL) { btr_pcur_t::SAME_ALL) {
goto mtr_commit_exit; goto mtr_commit_exit;
} }
@@ -483,7 +482,7 @@ row_undo_mod_del_mark_or_remove_sec_low(
que_thr_t* thr, /*!< in: query thread */ que_thr_t* thr, /*!< in: query thread */
dict_index_t* index, /*!< in: index */ dict_index_t* index, /*!< in: index */
dtuple_t* entry, /*!< in: index entry */ 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_MODIFY_TREE */
{ {
btr_pcur_t pcur; btr_pcur_t pcur;
@@ -496,15 +495,25 @@ row_undo_mod_del_mark_or_remove_sec_low(
row_mtr_start(&mtr, index, !modify_leaf); 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 /* The index->online_status may change if the index is
or was being created online, but not committed yet. It or was being created online, but not committed yet. It
is protected by index->lock. */ is protected by index->lock. */
if (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); mtr_s_lock_index(index, &mtr);
} else { } else {
ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE)); ut_ad(mode == BTR_PURGE_TREE);
mtr_sx_lock_index(index, &mtr); mtr_sx_lock_index(index, &mtr);
} }
} else { } else {
@@ -514,18 +523,7 @@ row_undo_mod_del_mark_or_remove_sec_low(
ut_ad(!dict_index_is_online_ddl(index)); ut_ad(!dict_index_is_online_ddl(index));
} }
btr_cur = btr_pcur_get_btr_cur(&pcur); search_result = row_search_index_entry(entry, mode, &pcur, &mtr);
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);
switch (UNIV_EXPECT(search_result, ROW_FOUND)) { switch (UNIV_EXPECT(search_result, ROW_FOUND)) {
case ROW_NOT_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, 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); return(err);
} }
@@ -652,7 +650,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t dberr_t
row_undo_mod_del_unmark_sec_and_undo_update( 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 */ BTR_MODIFY_TREE */
que_thr_t* thr, /*!< in: query thread */ que_thr_t* thr, /*!< in: query thread */
dict_index_t* index, /*!< in: index */ dict_index_t* index, /*!< in: index */
@@ -668,8 +666,9 @@ row_undo_mod_del_unmark_sec_and_undo_update(
const ulint flags const ulint flags
= BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG; = BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG;
row_search_result search_result; 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); ut_ad(trx->id != 0);
if (dict_index_is_spatial(index)) { 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. */ secondary index updates to avoid this. */
static_assert(BTR_MODIFY_TREE == (8 | BTR_MODIFY_LEAF), ""); static_assert(BTR_MODIFY_TREE == (8 | BTR_MODIFY_LEAF), "");
ut_ad(!(mode & 8)); ut_ad(!(mode & 8));
mode |= BTR_RTREE_DELETE_MARK; mode = btr_latch_mode(mode | BTR_RTREE_DELETE_MARK);
} }
try_again: try_again:
@@ -687,8 +686,7 @@ try_again:
btr_cur->thr = thr; btr_cur->thr = thr;
search_result = row_search_index_entry(index, entry, mode, search_result = row_search_index_entry(entry, mode, &pcur, &mtr);
&pcur, &mtr);
switch (search_result) { switch (search_result) {
mem_heap_t* heap; mem_heap_t* heap;

View File

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

View File

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