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:
39
debian/autobake-deb.sh
vendored
39
debian/autobake-deb.sh
vendored
@@ -26,9 +26,9 @@ then
|
||||
sed '/Add support for verbose builds/,/^$/d' -i debian/rules
|
||||
elif [ -d storage/columnstore/columnstore/debian ]
|
||||
then
|
||||
# ColumnStore is explicitly disabled in the native Debian build, so allow it
|
||||
# ColumnStore is explicitly disabled in the native Debian build. Enable it
|
||||
# now when build is triggered by autobake-deb.sh (MariaDB.org) and when the
|
||||
# build is not running on Travis or Gitlab-CI
|
||||
# build is not running on Gitlab-CI.
|
||||
sed '/-DPLUGIN_COLUMNSTORE=NO/d' -i debian/rules
|
||||
# Take the files and part of control from MCS directory
|
||||
if [ ! -f debian/mariadb-plugin-columnstore.install ]
|
||||
@@ -59,13 +59,13 @@ replace_uring_with_aio()
|
||||
{
|
||||
sed 's/liburing-dev/libaio-dev/g' -i debian/control
|
||||
sed -e '/-DIGNORE_AIO_CHECK=YES/d' \
|
||||
-e '/-DWITH_URING=yes/d' -i debian/rules
|
||||
-e '/-DWITH_URING=YES/d' -i debian/rules
|
||||
}
|
||||
|
||||
disable_pmem()
|
||||
{
|
||||
sed '/libpmem-dev/d' -i debian/control
|
||||
sed '/-DWITH_PMEM=yes/d' -i debian/rules
|
||||
sed '/-DWITH_PMEM=YES/d' -i debian/rules
|
||||
}
|
||||
|
||||
disable_libfmt()
|
||||
@@ -76,15 +76,34 @@ disable_libfmt()
|
||||
|
||||
architecture=$(dpkg-architecture -q DEB_BUILD_ARCH)
|
||||
|
||||
# Parse release name and number from Linux standard base release
|
||||
# Example:
|
||||
# $ lsb_release -a
|
||||
# No LSB modules are available.
|
||||
# Distributor ID: Debian
|
||||
# Description: Debian GNU/Linux bookworm/sid
|
||||
# Release: n/a
|
||||
# Codename: n/a
|
||||
LSBID="$(lsb_release -si | tr '[:upper:]' '[:lower:]')"
|
||||
LSBVERSION="$(lsb_release -sr | sed -e "s#\.##g")"
|
||||
LSBNAME="$(lsb_release -sc)"
|
||||
|
||||
# If 'n/a', assume 'sid'
|
||||
if [ "${LSBVERSION}" == "n/a" ] || [ "${LSBNAME}" == "n/a" ]
|
||||
then
|
||||
LSBVERSION="sid"
|
||||
LSBNAME="sid"
|
||||
fi
|
||||
|
||||
# If not known, use 'unknown' in .deb version identifier
|
||||
if [ -z "${LSBID}" ]
|
||||
then
|
||||
LSBID="unknown"
|
||||
fi
|
||||
case "${LSBNAME}" in
|
||||
|
||||
case "${LSBNAME}"
|
||||
in
|
||||
# Debian
|
||||
stretch)
|
||||
# MDEV-16525 libzstd-dev-1.1.3 minimum version
|
||||
sed -e '/libzstd-dev/d' \
|
||||
@@ -113,10 +132,10 @@ case "${LSBNAME}" in
|
||||
fi
|
||||
;&
|
||||
sid)
|
||||
# should always be empty here.
|
||||
# need to match here to avoid the default Error however
|
||||
# The default packaging should always target Debian Sid, so in this case
|
||||
# there is intentionally no customizations whatsoever.
|
||||
;;
|
||||
# UBUNTU
|
||||
# Ubuntu
|
||||
bionic)
|
||||
remove_rocksdb_tools
|
||||
[ "$architecture" != amd64 ] && disable_pmem
|
||||
@@ -143,7 +162,7 @@ case "${LSBNAME}" in
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Error - unknown release codename $LSBNAME" >&2
|
||||
echo "Error: Unknown release '$LSBNAME'" >&2
|
||||
exit 1
|
||||
esac
|
||||
|
||||
@@ -162,7 +181,7 @@ LOGSTRING="MariaDB build"
|
||||
EPOCH="1:"
|
||||
VERSION="${EPOCH}${UPSTREAM}${PATCHLEVEL}~${LSBID:0:3}${LSBVERSION}"
|
||||
|
||||
dch -b -D ${LSBNAME} -v "${VERSION}" "Automatic build with ${LOGSTRING}." --controlmaint
|
||||
dch -b -D "${LSBNAME}" -v "${VERSION}" "Automatic build with ${LOGSTRING}." --controlmaint
|
||||
|
||||
echo "Creating package version ${VERSION} ... "
|
||||
|
||||
|
13
debian/mariadb-server-10.8.mariadb.init
vendored
13
debian/mariadb-server-10.8.mariadb.init
vendored
@@ -21,9 +21,18 @@ test -x /usr/sbin/mariadbd || exit 0
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
SELF=$(cd $(dirname $0); pwd -P)/$(basename $0)
|
||||
SELF=$(cd "$(dirname $0)"; pwd -P)/$(basename $0)
|
||||
|
||||
MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf"
|
||||
if [ -f /usr/bin/mariadb-admin ]
|
||||
then
|
||||
MYADMIN="/usr/bin/mariadb-admin --defaults-file=/etc/mysql/debian.cnf"
|
||||
elif [ -f /usr/bin/mysqladmin ]
|
||||
then
|
||||
MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf"
|
||||
else
|
||||
log_failure_msg "Command mariadb-admin/mysqladmin not found! This SysV init script depends on it."
|
||||
exit -1
|
||||
fi
|
||||
|
||||
# priority can be overridden and "-s" adds output to stderr
|
||||
ERR_LOGGER="logger -p daemon.err -t /etc/init.d/mariadb -i"
|
||||
|
19
debian/rules
vendored
19
debian/rules
vendored
@@ -5,7 +5,13 @@ export DEB_BUILD_HARDENING=1
|
||||
|
||||
# enable Debian Hardening
|
||||
# see: https://wiki.debian.org/Hardening
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all optimize=-lto
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
# Disable LTO on Ubuntu, see LP: #1970634 and https://jira.mariadb.org/browse/MDEV-25633
|
||||
ifeq ($(shell dpkg-vendor --derives-from Ubuntu && echo yes), yes)
|
||||
export DEB_BUILD_MAINT_OPTIONS += optimize=-lto
|
||||
endif
|
||||
|
||||
DPKG_EXPORT_BUILDFLAGS = 1
|
||||
# Include all defaults, including buildflags.mk
|
||||
include /usr/share/dpkg/default.mk
|
||||
@@ -46,11 +52,6 @@ ifeq (32,$(DEB_HOST_ARCH_BITS))
|
||||
CMAKEFLAGS += -DPLUGIN_ROCKSDB=NO
|
||||
endif
|
||||
|
||||
# ColumnStore can build only on amd64 and arm64
|
||||
ifneq (,$(filter $(DEB_HOST_ARCH_CPU),amd64 arm64))
|
||||
CMAKEFLAGS += -DPLUGIN_COLUMNSTORE=NO
|
||||
endif
|
||||
|
||||
# Cross building requires stack direction instruction
|
||||
ifneq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH))
|
||||
ifneq (,$(filter $(DEB_HOST_ARCH_CPU),alpha amd64 arm arm64 i386 ia64 m68k mips64el mipsel powerpc ppc64 ppc64el riscv64 s390x sh4 sparc64))
|
||||
@@ -64,7 +65,7 @@ endif
|
||||
# Only attempt to build with PMEM on archs that have package libpmem-dev available
|
||||
# See https://packages.debian.org/search?searchon=names&keywords=libpmem-dev
|
||||
ifneq (,$(filter $(DEB_HOST_ARCH_CPU),amd64 arm64 ppc64el riscv64))
|
||||
CMAKEFLAGS += -DWITH_PMEM=yes
|
||||
CMAKEFLAGS += -DWITH_PMEM=YES
|
||||
endif
|
||||
|
||||
# Add support for verbose builds
|
||||
@@ -107,7 +108,7 @@ endif
|
||||
-DPLUGIN_AWS_KEY_MANAGEMENT=NO \
|
||||
-DPLUGIN_COLUMNSTORE=NO \
|
||||
-DIGNORE_AIO_CHECK=YES \
|
||||
-DWITH_URING=yes \
|
||||
-DWITH_URING=YES \
|
||||
-DDEB=$(DEB_VENDOR)
|
||||
|
||||
# This is needed, otherwise 'make test' will run before binaries have been built
|
||||
@@ -120,6 +121,7 @@ override_dh_auto_build:
|
||||
override_dh_auto_test:
|
||||
@echo "RULES.$@"
|
||||
dh_testdir
|
||||
# Ensure at least an empty file exists
|
||||
touch mysql-test/unstable-tests
|
||||
[ ! -f debian/unstable-tests.$(DEB_HOST_ARCH) ] || cat debian/unstable-tests.$(DEB_HOST_ARCH) >> mysql-test/unstable-tests
|
||||
# Run testsuite
|
||||
@@ -203,6 +205,7 @@ override_dh_installinit-arch:
|
||||
dh_installinit --name=mariadb --no-start -- defaults 19 21
|
||||
dh_systemd_start --restart-after-upgrade
|
||||
|
||||
# Use custom server version string variable
|
||||
override_dh_gencontrol:
|
||||
dh_gencontrol -- -Tdebian/substvars
|
||||
|
||||
|
77
debian/salsa-ci.yml
vendored
77
debian/salsa-ci.yml
vendored
@@ -16,12 +16,17 @@ variables:
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
SALSA_CI_GBP_BUILDPACKAGE_ARGS: "--git-submodules" # did not apply to extract-sources
|
||||
|
||||
# Extend Salsa-CI build jobs to have longer timeout as the default GitLab
|
||||
# timeout (1h) is often not enough
|
||||
.build-package:
|
||||
timeout: 3h
|
||||
|
||||
stages:
|
||||
- provisioning
|
||||
- build
|
||||
- test
|
||||
- upgrade in Sid
|
||||
- upgrade from Bullseye/Buster
|
||||
- upgrade from Bullseye
|
||||
- upgrade extras
|
||||
- test extras
|
||||
- publish # Stage referenced by Salsa-CI template aptly stanza, so must exist even though not used
|
||||
@@ -134,6 +139,17 @@ blhc:
|
||||
apt-get update
|
||||
apt-get install -y apt
|
||||
|
||||
.test-enable-buster-backports-repos: &test-enable-buster-backports-repos |
|
||||
# Enable buster-backports (assumes environment already Debian Buster)
|
||||
echo 'deb http://deb.debian.org/debian buster-backports main' > /etc/apt/sources.list.d/buster-backports.list
|
||||
# Increase default backports priority policy from '100' to '500' so it can actually be used
|
||||
cat << EOF > /etc/apt/preferences.d/enable-backports-to-satisfy-dependencies
|
||||
Package: *
|
||||
Pin: release n=buster-*
|
||||
Pin-Priority: 500
|
||||
EOF
|
||||
apt-get update
|
||||
|
||||
.test-install: &test-install |
|
||||
# Install MariaDB built in this commit
|
||||
apt-get install -y ./*.deb
|
||||
@@ -213,7 +229,7 @@ fresh install:
|
||||
script:
|
||||
- *test-prepare-container
|
||||
- *test-install
|
||||
- service mariadb status # There is no init.d/mysql in MariaDB 10.8
|
||||
- service mariadb status # There is no init.d/mysql in MariaDB 10.5+
|
||||
- *test-verify-final
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
@@ -234,7 +250,7 @@ mariadb-10.8 Sid upgrade:
|
||||
script:
|
||||
- *test-prepare-container
|
||||
- *test-install
|
||||
- service mariadb status # There is no init.d/mysql in MariaDB 10.8
|
||||
- service mariadb status # There is no init.d/mysql in MariaDB 10.5+
|
||||
- *test-verify-final
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
@@ -243,7 +259,7 @@ mariadb-10.8 Sid upgrade:
|
||||
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
|
||||
|
||||
mariadb-10.5 Bullseye to mariadb-10.8 upgrade:
|
||||
stage: upgrade from Bullseye/Buster
|
||||
stage: upgrade from Bullseye
|
||||
needs:
|
||||
- job: build
|
||||
image: debian:bullseye
|
||||
@@ -268,10 +284,12 @@ mariadb-10.5 Bullseye to mariadb-10.8 upgrade:
|
||||
variables:
|
||||
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
|
||||
|
||||
mariadb-10.3 Buster to mariadb-10.8 upgrade:
|
||||
stage: upgrade from Bullseye/Buster
|
||||
# Upgrade of libcrypt.so.1 no longer possible from Buster to Sid,
|
||||
# so test upgrade only inside Buster (https://bugs.debian.org/993755)
|
||||
mariadb-10.3 to mariadb-10.8 upgrade in Buster:
|
||||
stage: upgrade extras
|
||||
needs:
|
||||
- job: build
|
||||
- job: build buster-backports
|
||||
image: debian:buster
|
||||
artifacts:
|
||||
when: always
|
||||
@@ -284,7 +302,7 @@ mariadb-10.3 Buster to mariadb-10.8 upgrade:
|
||||
- apt-get install -y 'default-mysql*' 'mariadb-*' 'libmariadb*'
|
||||
# Verify installation of MariaDB from Buster
|
||||
- *test-verify-initial
|
||||
- *test-enable-sid-repos
|
||||
- *test-enable-buster-backports-repos
|
||||
- *test-install
|
||||
- service mysql status
|
||||
- *test-verify-final
|
||||
@@ -307,7 +325,7 @@ test basic features:
|
||||
script:
|
||||
- *test-prepare-container
|
||||
- *test-install
|
||||
- service mariadb status # There is no init.d/mysql in MariaDB 10.8
|
||||
- service mariadb status # There is no init.d/mysql in MariaDB 10.5+
|
||||
- *test-verify-final
|
||||
- |
|
||||
# Print info about server
|
||||
@@ -452,7 +470,7 @@ default-libmysqlclient-dev Sid upgrade:
|
||||
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
|
||||
|
||||
default-libmysqlclient-dev Bullseye upgrade:
|
||||
stage: upgrade from Bullseye/Buster
|
||||
stage: upgrade from Bullseye
|
||||
needs:
|
||||
- job: build
|
||||
image: debian:bullseye
|
||||
@@ -472,10 +490,12 @@ default-libmysqlclient-dev Bullseye upgrade:
|
||||
variables:
|
||||
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
|
||||
|
||||
default-libmysqlclient-dev Buster upgrade:
|
||||
stage: upgrade from Bullseye/Buster
|
||||
# Upgrade of libcrypt.so.1 no longer possible from Buster to Sid,
|
||||
# so test upgrade only inside Buster (https://bugs.debian.org/993755)
|
||||
default-libmysqlclient-dev upgrade in Buster:
|
||||
stage: upgrade extras
|
||||
needs:
|
||||
- job: build
|
||||
- job: build buster-backports
|
||||
image: debian:buster
|
||||
artifacts:
|
||||
when: always
|
||||
@@ -486,7 +506,7 @@ default-libmysqlclient-dev Buster upgrade:
|
||||
- *test-prepare-container
|
||||
- apt-get install -y pkg-config default-libmysqlclient-dev
|
||||
- pkg-config --list-all
|
||||
- *test-enable-sid-repos
|
||||
- *test-enable-buster-backports-repos
|
||||
- *test-install-all-libs
|
||||
- *test-verify-libs
|
||||
except:
|
||||
@@ -511,8 +531,20 @@ mysql-8.0 Sid to mariadb-10.8 upgrade:
|
||||
- apt-get install -y procps mysql-server 'libmysqlc*'
|
||||
- *test-verify-initial
|
||||
- *test-install
|
||||
- service mysql status
|
||||
# The Debian version of MariaDB 10.6 still maintains compatibility and there
|
||||
# running 'service mysql status' in Salsa-CI job 'mysql-8.0 Sid to
|
||||
# mariadb-10.6 upgrade' still works.
|
||||
#
|
||||
# However, due to debian/control changes, the upstream MariaDB 10.6 when
|
||||
# installed on a system with a previous installation of MySQL 8.0 will first
|
||||
# fully remove MySQL, including the /etc/init.d/mysql file, so previous
|
||||
# techniques in mariadb-server-10.6.postinst to maintain backwards
|
||||
# compatibility with 'service mysql status' after installing MariaDB on top
|
||||
# MySQL no longer works, and thus the step to test it now intentionally has
|
||||
# a fallback to use the service name 'mariadb' instead, and the fallback is
|
||||
# always used.
|
||||
- sleep 5 # Give the mysql_upgrade a bit of time to complete before querying the server
|
||||
- service mysql status || service mariadb status
|
||||
- *test-verify-final
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
@@ -522,7 +554,7 @@ mysql-8.0 Sid to mariadb-10.8 upgrade:
|
||||
|
||||
# Upgrading from MySQL 8.0 with datadir in place is not possible. Users need to do a data dump.
|
||||
# The Debian maintainer scripts detect this situation and simply moves old datadir aside and start fresh.
|
||||
mysql-8.0 Focal to mariadb-10.8 upgrade:
|
||||
mysql-8.0 Focal to mariadb-10.8 upgrade in Buster:
|
||||
stage: upgrade extras
|
||||
needs:
|
||||
- job: build buster-backports
|
||||
@@ -622,18 +654,13 @@ mariadb.org-10.6 to mariadb-10.8 upgrade:
|
||||
# Verify installation of MariaDB built in this commit
|
||||
- dpkg -l | grep -iE 'maria|mysql|galera' || true # List installed
|
||||
- mariadb --version # Client version
|
||||
- service mariadb status # There is no init.d/mysql in MariaDB 10.8
|
||||
- service mariadb status # There is no init.d/mysql in MariaDB 10.5+
|
||||
- *test-verify-final
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
except:
|
||||
variables:
|
||||
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
|
||||
allow_failure: true
|
||||
# Installation on Sid fails on missing liburing1 because upstream 10.8
|
||||
# MariaDB.org buildbot has not run 'apt upgrade' for a long time.
|
||||
# Remove this allow_failure once buildbot has built a new 10.8
|
||||
# release using latest liburing-dev in Debian Sid.
|
||||
|
||||
mariadb.org-10.5 to mariadb-10.8 upgrade:
|
||||
stage: upgrade extras
|
||||
@@ -657,7 +684,7 @@ mariadb.org-10.5 to mariadb-10.8 upgrade:
|
||||
# Verify installation of MariaDB built in this commit
|
||||
- dpkg -l | grep -iE 'maria|mysql|galera' || true # List installed
|
||||
- mariadb --version # Client version
|
||||
- service mariadb status # There is no init.d/mysql in MariaDB 10.5
|
||||
- service mariadb status # There is no init.d/mysql in MariaDB 10.5+
|
||||
- *test-verify-final
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
@@ -768,7 +795,7 @@ mariadb.org-10.2 to mariadb-10.8 upgrade:
|
||||
variables:
|
||||
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
|
||||
|
||||
mysql.com-5.7 to mariadb-10.8 upgrade:
|
||||
mysql.com-5.7 to mariadb-10.8 upgrade in Buster:
|
||||
stage: upgrade extras
|
||||
needs:
|
||||
- job: build buster-backports
|
||||
@@ -799,7 +826,7 @@ mysql.com-5.7 to mariadb-10.8 upgrade:
|
||||
variables:
|
||||
- $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/
|
||||
|
||||
percona-xtradb-5.7 to mariadb-10.8 upgrade (MDEV-22679):
|
||||
percona-xtradb-5.7 to mariadb-10.8 upgrade in Buster (MDEV-22679):
|
||||
stage: upgrade extras
|
||||
needs:
|
||||
- job: build buster-backports
|
||||
|
2
debian/source/lintian-overrides
vendored
2
debian/source/lintian-overrides
vendored
@@ -48,7 +48,7 @@ very-long-line-length-in-source-file mysql-test/std_data/init_file_longline_3816
|
||||
very-long-line-length-in-source-file scripts/fill_help_tables.sql *
|
||||
very-long-line-length-in-source-file scripts/mysql_system_tables.sql *
|
||||
very-long-line-length-in-source-file scripts/mysql_test_data_timezone.sql *
|
||||
# Machine formated HTML
|
||||
# Machine formatted HTML
|
||||
very-long-line-length-in-source-file sql/share/charsets/languages.html *
|
||||
very-long-line-length-in-source-file sql/share/errmsg-utf8.txt *
|
||||
# Very long test string
|
||||
|
24
debian/tests/upstream
vendored
24
debian/tests/upstream
vendored
@@ -10,6 +10,8 @@ echo "Running test 'testsuite'"
|
||||
set -e
|
||||
|
||||
SKIP_TEST_LST="/tmp/skip-test.lst"
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
|
||||
WORKDIR=$(mktemp -d)
|
||||
trap 'rm -rf $WORKDIR $SKIP_TEST_LST' 0 INT QUIT ABRT PIPE TERM
|
||||
cd "$WORKDIR"
|
||||
@@ -22,16 +24,15 @@ echo "using tmpdir: $WORKDIR/tmp"
|
||||
|
||||
echo "Setting up skip-tests-list"
|
||||
|
||||
touch $SKIP_TEST_LST
|
||||
# Use unstable-tests list as base to skip all tests considered unstable
|
||||
# or create an empty file if that upstream file does not exists on this branch
|
||||
cp /usr/share/mysql/mysql-test/unstable-tests $SKIP_TEST_LST || touch $SKIP_TEST_LST
|
||||
|
||||
# Also use arch specific skiplists if such files exist
|
||||
for filename in /usr/share/mysql/mysql-test/unstable-tests.*
|
||||
do
|
||||
# Check for case that no files matched and glob is returned
|
||||
[ -e "$filename" ] || continue
|
||||
# Append file to the main skip test list file
|
||||
cat "$filename" >> $SKIP_TEST_LST
|
||||
done
|
||||
# Also use the arch specific skiplists if exist
|
||||
if [ -f /usr/share/mysql/mysql-test/unstable-tests.$ARCH ]
|
||||
then
|
||||
cat /usr/share/mysql/mysql-test/unstable-tests.$ARCH >> $SKIP_TEST_LST
|
||||
fi
|
||||
|
||||
# Skip tests that cannot run properly on ci.debian.net / autopkgtests.ubuntu.com
|
||||
cat >> $SKIP_TEST_LST << EOF
|
||||
@@ -48,7 +49,6 @@ main.mysqld--help : For unknown reason table-cache is 4000 instead of default 42
|
||||
EOF
|
||||
fi
|
||||
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
if [ "$ARCH" = "s390x" ]
|
||||
then
|
||||
echo "main.func_regexp_pcre : recursion fails on s390x https://bugs.launchpad.net/ubuntu/+source/mariadb-10.1/+bug/1723947" >> $SKIP_TEST_LST
|
||||
@@ -57,6 +57,10 @@ then
|
||||
echo "main.failed_auth_unixsocket : Test returns wrong exit code on armhf and i386 (but only in debci) https://jira.mariadb.org/browse/MDEV-23933" >> $SKIP_TEST_LST
|
||||
fi
|
||||
|
||||
# Store skipped test list in artifacts so it can be viewed while debugging
|
||||
# failed autopkgtest runs
|
||||
cp -v $SKIP_TEST_LST $AUTOPKGTEST_ARTIFACTS
|
||||
|
||||
cd /usr/share/mysql/mysql-test
|
||||
echo "starting mysql-test-tun.pl..."
|
||||
eatmydata perl -I. ./mysql-test-run.pl --suite=main \
|
||||
|
@@ -1,3 +1,4 @@
|
||||
RESET MASTER;
|
||||
CREATE TEMPORARY SEQUENCE seq_1;
|
||||
XA START '3';
|
||||
CREATE TEMPORARY TABLE tmp_1(c INT);
|
||||
|
@@ -1,3 +1,4 @@
|
||||
RESET MASTER;
|
||||
#
|
||||
# Verify that SET string values and character sets can be printed correctly
|
||||
#
|
||||
|
@@ -1,3 +1,4 @@
|
||||
RESET MASTER;
|
||||
#
|
||||
# Verify that SET string values and character sets can be printed correctly
|
||||
#
|
||||
|
@@ -1,3 +1,4 @@
|
||||
RESET MASTER;
|
||||
#
|
||||
# Verify that SET string values and character sets can be printed correctly
|
||||
#
|
||||
|
@@ -4,7 +4,7 @@
|
||||
--source include/have_binlog_format_mixed.inc
|
||||
--source include/have_innodb.inc
|
||||
|
||||
|
||||
RESET MASTER; # clear binlogs
|
||||
# MDEV-22420 DDL on temporary object is prohibited when XA is in prepare state
|
||||
|
||||
# Temporary sequnce may not be created within a transaction
|
||||
|
@@ -20,6 +20,7 @@
|
||||
--let $MYSQLD_DATADIR= `select @@datadir`
|
||||
--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001
|
||||
|
||||
RESET MASTER;
|
||||
--echo #
|
||||
--echo # Verify that SET string values and character sets can be printed correctly
|
||||
--echo #
|
||||
|
@@ -21,6 +21,7 @@
|
||||
--let $MYSQLD_DATADIR= `select @@datadir`
|
||||
--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001
|
||||
|
||||
RESET MASTER;
|
||||
--echo #
|
||||
--echo # Verify that SET string values and character sets can be printed correctly
|
||||
--echo #
|
||||
|
@@ -21,6 +21,7 @@
|
||||
--let $MYSQLD_DATADIR= `select @@datadir`
|
||||
--let $binlog_file= $MYSQLD_DATADIR/master-bin.000001
|
||||
|
||||
RESET MASTER;
|
||||
--echo #
|
||||
--echo # Verify that SET string values and character sets can be printed correctly
|
||||
--echo #
|
||||
|
@@ -3268,3 +3268,78 @@ a
|
||||
This is db1.pkg1.p1
|
||||
DROP DATABASE db1;
|
||||
DROP DATABASE db2;
|
||||
#
|
||||
# MDEV-29370 Functions in packages are slow and seems to ignore deterministic
|
||||
#
|
||||
SET SQL_MODE=ORACLE;
|
||||
CREATE TABLE t1 (c1 CHAR(1));
|
||||
CREATE FUNCTION f1_deterministic()
|
||||
RETURN CHAR(1)
|
||||
DETERMINISTIC
|
||||
IS
|
||||
BEGIN
|
||||
RETURN 'X';
|
||||
END;
|
||||
//
|
||||
CREATE FUNCTION f2_not_deterministic()
|
||||
RETURN CHAR(1)
|
||||
IS
|
||||
BEGIN
|
||||
RETURN 'X';
|
||||
END;
|
||||
//
|
||||
CREATE PACKAGE pkg1
|
||||
IS
|
||||
PROCEDURE t1_populate(numrows INTEGER);
|
||||
FUNCTION f3_deterministic() RETURN CHAR(1) DETERMINISTIC;
|
||||
FUNCTION f4_not_deterministic() RETURN CHAR(1);
|
||||
END;
|
||||
//
|
||||
CREATE PACKAGE BODY pkg1
|
||||
IS
|
||||
PROCEDURE t1_populate(numrounds INTEGER)
|
||||
IS
|
||||
i INTEGER;
|
||||
BEGIN
|
||||
INSERT INTO t1 VALUES('Y');
|
||||
FOR i IN 1..numrounds LOOP
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
END LOOP;
|
||||
END;
|
||||
FUNCTION f3_deterministic() RETURN CHAR(1) DETERMINISTIC COMMENT 'xxx'
|
||||
IS
|
||||
BEGIN
|
||||
RETURN 'X';
|
||||
END;
|
||||
FUNCTION f4_not_deterministic() RETURN CHAR(1)
|
||||
IS
|
||||
BEGIN
|
||||
RETURN 'X';
|
||||
END;
|
||||
END;
|
||||
//
|
||||
CALL pkg1.t1_populate(3);
|
||||
EXPLAIN EXTENDED SELECT 'Deterministic function', COUNT(*) FROM t1 WHERE c1 = f1_deterministic();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select 'Deterministic function' AS "Deterministic function",count(0) AS "COUNT(*)" from "test"."t1" where "test"."t1"."c1" = <cache>("f1_deterministic"())
|
||||
EXPLAIN EXTENDED SELECT 'Non-deterministic function', COUNT(*) FROM t1 WHERE c1 = f2_not_deterministic();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select 'Non-deterministic function' AS "Non-deterministic function",count(0) AS "COUNT(*)" from "test"."t1" where "test"."t1"."c1" = "f2_not_deterministic"()
|
||||
EXPLAIN EXTENDED SELECT 'Deterministic package function', COUNT(*) FROM t1 WHERE c1 = pkg1.f3_deterministic();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select 'Deterministic package function' AS "Deterministic package function",count(0) AS "COUNT(*)" from "test"."t1" where "test"."t1"."c1" = <cache>("test"."pkg1"."f3_deterministic"())
|
||||
EXPLAIN EXTENDED SELECT 'Non-deterministic package function', COUNT(*) FROM t1 WHERE c1 = pkg1.f4_not_deterministic();
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select 'Non-deterministic package function' AS "Non-deterministic package function",count(0) AS "COUNT(*)" from "test"."t1" where "test"."t1"."c1" = "test"."pkg1"."f4_not_deterministic"()
|
||||
DROP TABLE t1;
|
||||
DROP FUNCTION f1_deterministic;
|
||||
DROP FUNCTION f2_not_deterministic;
|
||||
DROP PACKAGE pkg1;
|
||||
|
@@ -3016,3 +3016,75 @@ CALL db2.pkg1.p2_db1_pkg1_p1;
|
||||
|
||||
DROP DATABASE db1;
|
||||
DROP DATABASE db2;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-29370 Functions in packages are slow and seems to ignore deterministic
|
||||
--echo #
|
||||
|
||||
SET SQL_MODE=ORACLE;
|
||||
|
||||
CREATE TABLE t1 (c1 CHAR(1));
|
||||
|
||||
DELIMITER //;
|
||||
CREATE FUNCTION f1_deterministic()
|
||||
RETURN CHAR(1)
|
||||
DETERMINISTIC
|
||||
IS
|
||||
BEGIN
|
||||
RETURN 'X';
|
||||
END;
|
||||
//
|
||||
|
||||
CREATE FUNCTION f2_not_deterministic()
|
||||
RETURN CHAR(1)
|
||||
IS
|
||||
BEGIN
|
||||
RETURN 'X';
|
||||
END;
|
||||
//
|
||||
|
||||
CREATE PACKAGE pkg1
|
||||
IS
|
||||
PROCEDURE t1_populate(numrows INTEGER);
|
||||
FUNCTION f3_deterministic() RETURN CHAR(1) DETERMINISTIC;
|
||||
FUNCTION f4_not_deterministic() RETURN CHAR(1);
|
||||
END;
|
||||
//
|
||||
|
||||
CREATE PACKAGE BODY pkg1
|
||||
IS
|
||||
PROCEDURE t1_populate(numrounds INTEGER)
|
||||
IS
|
||||
i INTEGER;
|
||||
BEGIN
|
||||
INSERT INTO t1 VALUES('Y');
|
||||
FOR i IN 1..numrounds LOOP
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
END LOOP;
|
||||
END;
|
||||
FUNCTION f3_deterministic() RETURN CHAR(1) DETERMINISTIC COMMENT 'xxx'
|
||||
IS
|
||||
BEGIN
|
||||
RETURN 'X';
|
||||
END;
|
||||
FUNCTION f4_not_deterministic() RETURN CHAR(1)
|
||||
IS
|
||||
BEGIN
|
||||
RETURN 'X';
|
||||
END;
|
||||
END;
|
||||
//
|
||||
DELIMITER ;//
|
||||
|
||||
CALL pkg1.t1_populate(3);
|
||||
|
||||
EXPLAIN EXTENDED SELECT 'Deterministic function', COUNT(*) FROM t1 WHERE c1 = f1_deterministic();
|
||||
EXPLAIN EXTENDED SELECT 'Non-deterministic function', COUNT(*) FROM t1 WHERE c1 = f2_not_deterministic();
|
||||
EXPLAIN EXTENDED SELECT 'Deterministic package function', COUNT(*) FROM t1 WHERE c1 = pkg1.f3_deterministic();
|
||||
EXPLAIN EXTENDED SELECT 'Non-deterministic package function', COUNT(*) FROM t1 WHERE c1 = pkg1.f4_not_deterministic();
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP FUNCTION f1_deterministic;
|
||||
DROP FUNCTION f2_not_deterministic;
|
||||
DROP PACKAGE pkg1;
|
||||
|
@@ -9,6 +9,7 @@
|
||||
-- source include/have_file_key_management_plugin.inc
|
||||
-- source include/innodb_page_size_small.inc
|
||||
-- source include/innodb_checksum_algorithm.inc
|
||||
-- source include/maybe_debug.inc
|
||||
|
||||
if (!$INNOCHECKSUM) {
|
||||
--echo Need innochecksum binary
|
||||
@@ -18,6 +19,10 @@ if (!$INNOCHECKSUM) {
|
||||
--disable_query_log
|
||||
# This may be triggered on a slow system or one that lacks native AIO.
|
||||
call mtr.add_suppression("InnoDB: Trying to delete tablespace.*pending operations");
|
||||
if ($have_debug) {
|
||||
SET GLOBAL DEBUG_DBUG='+d,ib_log_checkpoint_avoid_hard';
|
||||
call mtr.add_suppression("InnoDB: Crash recovery is broken due to insufficient innodb_log_file_size");
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
let $checksum_algorithm = `SELECT @@innodb_checksum_algorithm`;
|
||||
@@ -259,6 +264,15 @@ print FILE pack("H*", "c00lcafedeadb017");
|
||||
close FILE or die "close";
|
||||
EOF
|
||||
|
||||
if (0 && $have_debug) { # these messages sometimes fail to appear
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err
|
||||
--let SEARCH_PATTERN= InnoDB: Crash recovery is broken due to insufficient innodb_log_file_size; last checkpoint LSN=\\d+, current LSN=\\d+\\. Shutdown is in progress\\..*InnoDB: Crash recovery was broken.*
|
||||
--echo # FOUND 1 is expected for both.
|
||||
--source include/search_pattern_in_file.inc
|
||||
--let SEARCH_PATTERN= InnoDB: Crash recovery was broken
|
||||
--source include/search_pattern_in_file.inc
|
||||
}
|
||||
|
||||
-- disable_result_log
|
||||
--error 1
|
||||
--exec $INNOCHECKSUM $t1_IBD
|
||||
|
9
mysql-test/suite/innodb/r/insert_into_empty,32k.rdiff
Normal file
9
mysql-test/suite/innodb/r/insert_into_empty,32k.rdiff
Normal 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));
|
9
mysql-test/suite/innodb/r/insert_into_empty,64k.rdiff
Normal file
9
mysql-test/suite/innodb/r/insert_into_empty,64k.rdiff
Normal 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));
|
@@ -186,12 +186,31 @@ DROP TABLE t;
|
||||
# MDEV-28327 InnoDB persistent statistics fail to update
|
||||
# after bulk insert
|
||||
#
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY)ENGINE=InnoDB;
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY)ENGINE=InnoDB
|
||||
STATS_PERSISTENT=1 STATS_AUTO_RECALC=1;
|
||||
INSERT INTO t1 SELECT * FROM seq_1_to_4096;
|
||||
# Wait till statistics update after bulk insert operation
|
||||
SELECT n_rows FROM mysql.innodb_table_stats WHERE TABLE_NAME="t1";
|
||||
n_rows
|
||||
4096
|
||||
SELECT n_rows>=4000 FROM mysql.innodb_table_stats WHERE TABLE_NAME="t1";
|
||||
n_rows>=4000
|
||||
1
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-27214 Import with disabled keys corrupts meta-data like rows, indexes, ...
|
||||
#
|
||||
SET UNIQUE_CHECKS=0;
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
CREATE TABLE `t1` (
|
||||
`id` int(11) NOT NULL,
|
||||
`a` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
STATS_PERSISTENT=1 STATS_AUTO_RECALC=1;
|
||||
INSERT INTO `t1` VALUES (1,2),(2,3),(3,4);
|
||||
# Wait till statistics update after bulk insert operation
|
||||
SELECT TABLE_ROWS, AVG_ROW_LENGTH>0 FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test';
|
||||
TABLE_ROWS AVG_ROW_LENGTH>0
|
||||
3 1
|
||||
DROP TABLE t1;
|
||||
# End of 10.6 tests
|
||||
#
|
||||
@@ -351,7 +370,7 @@ DROP TABLE t1, t2;
|
||||
# MDEV-29801 Inconsistent ER_TOO_BIG_ROWSIZE during bulk
|
||||
# insert operation
|
||||
#
|
||||
call mtr.add_suppression("InnoDB: Cannot add field `c11` in table");
|
||||
call mtr.add_suppression("InnoDB: Cannot add field `(c0[36]|c11)` in table");
|
||||
SET @format= @@innodb_default_row_format;
|
||||
CREATE TABLE t1 (pk int primary key, c01 text, c02 text, c03 text,
|
||||
c04 text, c05 text, c06 text, c07 text, c08 text,
|
||||
|
@@ -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
|
||||
#
|
@@ -789,4 +789,16 @@ CHECK TABLE t EXTENDED;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
DROP TEMPORARY TABLE t;
|
||||
#
|
||||
# MDEV-29978 Corruption errors upon CHECK on temporary InnoDB table
|
||||
#
|
||||
CREATE TEMPORARY TABLE t (f INT UNIQUE) ENGINE=InnoDB;
|
||||
INSERT INTO t (f) VALUES (1),(2);
|
||||
CHECK TABLE t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
CHECK TABLE t EXTENDED;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
DROP TEMPORARY TABLE t;
|
||||
# End of 10.6 tests
|
||||
|
@@ -1,5 +1,5 @@
|
||||
--source include/have_innodb.inc
|
||||
|
||||
--source include/innodb_page_size.inc
|
||||
--source include/have_sequence.inc
|
||||
--source include/maybe_debug.inc
|
||||
--source include/have_partition.inc
|
||||
@@ -199,15 +199,41 @@ DROP TABLE t;
|
||||
--echo # MDEV-28327 InnoDB persistent statistics fail to update
|
||||
--echo # after bulk insert
|
||||
--echo #
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY)ENGINE=InnoDB;
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY)ENGINE=InnoDB
|
||||
STATS_PERSISTENT=1 STATS_AUTO_RECALC=1;
|
||||
INSERT INTO t1 SELECT * FROM seq_1_to_4096;
|
||||
--echo # Wait till statistics update after bulk insert operation
|
||||
let $wait_condition= select n_rows > 100 from mysql.innodb_table_stats
|
||||
where table_name="t1";
|
||||
source include/wait_condition.inc;
|
||||
SELECT n_rows FROM mysql.innodb_table_stats WHERE TABLE_NAME="t1";
|
||||
# At innodb_page_size=4k this will be only 4075, not 4096. Add some slack.
|
||||
# This is related to MDEV-24621 and possibly MDEV-26740.
|
||||
SELECT n_rows>=4000 FROM mysql.innodb_table_stats WHERE TABLE_NAME="t1";
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-27214 Import with disabled keys corrupts meta-data like rows, indexes, ...
|
||||
--echo #
|
||||
|
||||
SET UNIQUE_CHECKS=0;
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
CREATE TABLE `t1` (
|
||||
`id` int(11) NOT NULL,
|
||||
`a` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
STATS_PERSISTENT=1 STATS_AUTO_RECALC=1;
|
||||
INSERT INTO `t1` VALUES (1,2),(2,3),(3,4);
|
||||
--echo # Wait till statistics update after bulk insert operation
|
||||
let $wait_condition= select n_rows > 0 from mysql.innodb_table_stats
|
||||
where database_name='test' and table_name='t1';
|
||||
source include/wait_condition.inc;
|
||||
SELECT TABLE_ROWS, AVG_ROW_LENGTH>0 FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test';
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
||||
--echo #
|
||||
@@ -363,13 +389,14 @@ DROP TABLE t1, t2;
|
||||
--echo # MDEV-29801 Inconsistent ER_TOO_BIG_ROWSIZE during bulk
|
||||
--echo # insert operation
|
||||
--echo #
|
||||
call mtr.add_suppression("InnoDB: Cannot add field `c11` in table");
|
||||
call mtr.add_suppression("InnoDB: Cannot add field `(c0[36]|c11)` in table");
|
||||
|
||||
SET @format= @@innodb_default_row_format;
|
||||
CREATE TABLE t1 (pk int primary key, c01 text, c02 text, c03 text,
|
||||
c04 text, c05 text, c06 text, c07 text, c08 text,
|
||||
c09 text, c10 text, c11 text, c12 text) ENGINE=InnoDB;
|
||||
SET GLOBAL INNODB_DEFAULT_ROW_FORMAT= COMPACT;
|
||||
--replace_result 1982 8126 4030 8126
|
||||
ALTER TABLE t1 FORCE;
|
||||
INSERT IGNORE INTO t1 VALUES
|
||||
(1, REPEAT('x',4805), REPEAT('t',2211), REPEAT('u',974), REPEAT('e',871), REPEAT('z',224), REPEAT('j',978), REPEAT('n',190), REPEAT('t',888), REPEAT('x',32768), REPEAT('e',968), REPEAT('b',913), REPEAT('x',12107)),
|
||||
|
43
mysql-test/suite/innodb/t/insert_into_empty_notembedded.test
Normal file
43
mysql-test/suite/innodb/t/insert_into_empty_notembedded.test
Normal 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 #
|
@@ -624,4 +624,15 @@ UPDATE t SET a=2;
|
||||
CHECK TABLE t;
|
||||
CHECK TABLE t EXTENDED;
|
||||
DROP TEMPORARY TABLE t;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-29978 Corruption errors upon CHECK on temporary InnoDB table
|
||||
--echo #
|
||||
|
||||
CREATE TEMPORARY TABLE t (f INT UNIQUE) ENGINE=InnoDB;
|
||||
INSERT INTO t (f) VALUES (1),(2);
|
||||
CHECK TABLE t;
|
||||
CHECK TABLE t EXTENDED;
|
||||
DROP TEMPORARY TABLE t;
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
@@ -1,3 +1,4 @@
|
||||
reset master;
|
||||
call mtr.add_suppression("Table was marked as crashed");
|
||||
call mtr.add_suppression("Checking table: .*");
|
||||
create table t1 (a int primary key auto_increment, b int) engine=aria transactional= 1;
|
||||
|
@@ -3,6 +3,8 @@
|
||||
# no-protocol doesn't print warnings about repaired tables
|
||||
--source include/no_protocol.inc
|
||||
|
||||
reset master; # clear binlogs
|
||||
|
||||
call mtr.add_suppression("Table was marked as crashed");
|
||||
call mtr.add_suppression("Checking table: .*");
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
call mtr.add_suppression("InnoDB: Expected tablespace id .*");
|
||||
# Mariabackup --backup with page0 INIT_PAGE redo record
|
||||
# and there is no FILE_CREATE for the tablespace t1
|
||||
SET @save_dbug = @@SESSION.debug_dbug;
|
||||
SET DEBUG_DBUG="+d,checkpoint_after_file_create";
|
||||
CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
@@ -14,7 +15,7 @@ SELECT * FROM t1;
|
||||
f1
|
||||
1
|
||||
DROP TABLE t1;
|
||||
SET DEBUG_DBUG="-d,checkpoint_after_file_create";
|
||||
SET @@SESSION.DEBUG_DBUG= @save_debug;
|
||||
# Mariabackup fails after corrupting the page0 in disk
|
||||
# and there is no INIT_PAGE for page0
|
||||
CREATE TABLE t1(c INT) ENGINE=INNODB;
|
||||
|
@@ -6,6 +6,7 @@
|
||||
call mtr.add_suppression("InnoDB: Expected tablespace id .*");
|
||||
--echo # Mariabackup --backup with page0 INIT_PAGE redo record
|
||||
--echo # and there is no FILE_CREATE for the tablespace t1
|
||||
SET @save_dbug = @@SESSION.debug_dbug;
|
||||
SET DEBUG_DBUG="+d,checkpoint_after_file_create";
|
||||
CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
@@ -26,7 +27,7 @@ exec $XTRABACKUP --prepare --target-dir=$targetdir;
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
rmdir $targetdir;
|
||||
SET DEBUG_DBUG="-d,checkpoint_after_file_create";
|
||||
SET @@SESSION.DEBUG_DBUG= @save_debug;
|
||||
|
||||
--echo # Mariabackup fails after corrupting the page0 in disk
|
||||
--echo # and there is no INIT_PAGE for page0
|
||||
@@ -39,16 +40,13 @@ let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
|
||||
--echo # Corrupt the table
|
||||
|
||||
perl;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Fcntl qw(:DEFAULT :seek);
|
||||
my $page_size = $ENV{INNODB_PAGE_SIZE};
|
||||
my $ps = $ENV{INNODB_PAGE_SIZE};
|
||||
|
||||
sysopen FILE, "$ENV{MYSQLD_DATADIR}/test/t1.ibd", O_RDWR
|
||||
|| die "Cannot open t1.ibd\n";
|
||||
sysseek(FILE, 0, SEEK_SET) || die "Cannot seek t1.ibd\n";
|
||||
my $page=chr(0) x $page_size;
|
||||
syswrite(FILE, $page, $page_size)==$page_size;
|
||||
my $file = "$ENV{MYSQLD_DATADIR}/test/t1.ibd";
|
||||
open(FILE, "+<$file") || die "Unable to open $file";
|
||||
binmode FILE;
|
||||
seek (FILE, 0, SEEK_SET) or die "seek";
|
||||
print FILE chr(0x00) x $ps;
|
||||
close FILE or die "close";
|
||||
EOF
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
--source include/not_embedded.inc
|
||||
--source include/have_wsrep.inc
|
||||
|
||||
#
|
||||
# @@global.wsrep_on is not allowed if there
|
||||
|
@@ -96,6 +96,16 @@ with system versioning
|
||||
partition by system_time (
|
||||
partition p0 history,
|
||||
partition pn current);
|
||||
create or replace table t1 (a int)
|
||||
partition by range (a) (
|
||||
partition p0 history,
|
||||
partition p1 current);
|
||||
ERROR HY000: Wrong partition type `SYSTEM_TIME` for partitioning by `RANGE`
|
||||
create or replace table t1 (b int)
|
||||
partition by range (a) (
|
||||
partition p0 current,
|
||||
partition p1 history);
|
||||
ERROR HY000: Wrong partition type `SYSTEM_TIME` for partitioning by `RANGE`
|
||||
## ALTER TABLE
|
||||
alter table t1 add partition (
|
||||
partition p1 current);
|
||||
@@ -150,7 +160,7 @@ partition by system_time limit 1;
|
||||
alter table t1 change x big int;
|
||||
create or replace table t1 (i int) engine myisam partition by hash(i) partitions 2;
|
||||
alter table t1 add partition (partition px history);
|
||||
ERROR HY000: Wrong partitioning type, expected type: `SYSTEM_TIME`
|
||||
ERROR HY000: Wrong partition type `SYSTEM_TIME` for partitioning by `HASH`
|
||||
## INSERT, UPDATE, DELETE
|
||||
create or replace table t1 (x int)
|
||||
with system versioning
|
||||
@@ -1105,7 +1115,7 @@ drop table t1;
|
||||
create table t1 (a int) with system versioning partition by system_time
|
||||
(partition p1 history, partition pn current);
|
||||
alter table t1 add partition (partition p2);
|
||||
ERROR HY000: Wrong partitioning type, expected type: `SYSTEM_TIME`
|
||||
ERROR HY000: Wrong partition type `HASH` for partitioning by `SYSTEM_TIME`
|
||||
# MDEV-17891 Assertion failures in select_insert::abort_result_set and
|
||||
# mysql_load upon attempt to replace into a full table
|
||||
set @@max_heap_table_size= 1024*1024;
|
||||
|
@@ -106,6 +106,18 @@ partition by system_time (
|
||||
partition p0 history,
|
||||
partition pn current);
|
||||
|
||||
--error ER_PARTITION_WRONG_TYPE
|
||||
create or replace table t1 (a int)
|
||||
partition by range (a) (
|
||||
partition p0 history,
|
||||
partition p1 current);
|
||||
|
||||
--error ER_PARTITION_WRONG_TYPE
|
||||
create or replace table t1 (b int)
|
||||
partition by range (a) (
|
||||
partition p0 current,
|
||||
partition p1 history);
|
||||
|
||||
|
||||
--echo ## ALTER TABLE
|
||||
|
||||
|
@@ -116,7 +116,7 @@ my_bool my_gethwaddr(uchar *to)
|
||||
uint i;
|
||||
for (i= 0; res && i < ifc.ifc_len / sizeof(ifr[0]); i++)
|
||||
{
|
||||
#if !defined(_AIX) || !defined(__linux__)
|
||||
#if defined(_AIX) || defined(__linux__)
|
||||
#if defined(__linux__)
|
||||
#define HWADDR_DATA ifr[i].ifr_hwaddr.sa_data
|
||||
#else
|
||||
|
@@ -429,8 +429,13 @@ public:
|
||||
return NULL;
|
||||
}
|
||||
uint next_part_no(uint new_parts) const;
|
||||
|
||||
int gen_part_type(THD *thd, String *str) const;
|
||||
};
|
||||
|
||||
void part_type_error(THD *thd, partition_info *work_part_info,
|
||||
const char *part_type, partition_info *tab_part_info);
|
||||
|
||||
uint32 get_next_partition_id_range(struct st_partition_iter* part_iter);
|
||||
bool check_partition_dirs(partition_info *part_info);
|
||||
|
||||
|
@@ -9773,9 +9773,9 @@ ER_UNUSED_23
|
||||
spa "Nunca debería vd de ver esto"
|
||||
|
||||
ER_PARTITION_WRONG_TYPE
|
||||
chi "错误的分区类型,预期类型:%`s"
|
||||
eng "Wrong partitioning type, expected type: %`s"
|
||||
spa "Tipo de partición equivocada, tipo esperado: %`s"
|
||||
chi "错误的分区类型,预期类型:%`s for partitioning by %`s"
|
||||
eng "Wrong partition type %`s for partitioning by %`s"
|
||||
spa "Tipo de partición equivocada, tipo esperado: %`s for partitioning by %`s"
|
||||
|
||||
WARN_VERS_PART_FULL
|
||||
chi "版本化表%`s.%`s:partition%`s已满,添加更多历史分区(out of %s)"
|
||||
|
@@ -9754,6 +9754,7 @@ bool Lex_ident_sys_st::to_size_number(ulonglong *to) const
|
||||
}
|
||||
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
bool LEX::part_values_current(THD *thd)
|
||||
{
|
||||
partition_element *elem= part_info->curr_part_elem;
|
||||
@@ -9761,7 +9762,7 @@ bool LEX::part_values_current(THD *thd)
|
||||
{
|
||||
if (unlikely(part_info->part_type != VERSIONING_PARTITION))
|
||||
{
|
||||
my_error(ER_PARTITION_WRONG_TYPE, MYF(0), "SYSTEM_TIME");
|
||||
part_type_error(thd, NULL, "SYSTEM_TIME", part_info);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -9788,7 +9789,7 @@ bool LEX::part_values_history(THD *thd)
|
||||
{
|
||||
if (unlikely(part_info->part_type != VERSIONING_PARTITION))
|
||||
{
|
||||
my_error(ER_PARTITION_WRONG_TYPE, MYF(0), "SYSTEM_TIME");
|
||||
part_type_error(thd, NULL, "SYSTEM_TIME", part_info);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -9809,6 +9810,7 @@ bool LEX::part_values_history(THD *thd)
|
||||
elem->type= partition_element::HISTORY;
|
||||
return false;
|
||||
}
|
||||
#endif /* WITH_PARTITION_STORAGE_ENGINE */
|
||||
|
||||
|
||||
bool LEX::last_field_generated_always_as_row_start_or_end(Lex_ident *p,
|
||||
|
@@ -3776,8 +3776,10 @@ public:
|
||||
bool table_or_sp_used();
|
||||
|
||||
bool is_partition_management() const;
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
bool part_values_current(THD *thd);
|
||||
bool part_values_history(THD *thd);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@brief check if the statement is a single-level join
|
||||
|
@@ -2470,7 +2470,7 @@ end:
|
||||
@retval != 0 Failure
|
||||
*/
|
||||
|
||||
static int add_key_with_algorithm(String *str, partition_info *part_info)
|
||||
static int add_key_with_algorithm(String *str, const partition_info *part_info)
|
||||
{
|
||||
int err= 0;
|
||||
err+= str->append(STRING_WITH_LEN("KEY "));
|
||||
@@ -2499,6 +2499,78 @@ char *generate_partition_syntax_for_frm(THD *thd, partition_info *part_info,
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Generate the partition type syntax from the partition data structure.
|
||||
|
||||
@return Operation status.
|
||||
@retval 0 Success
|
||||
@retval > 0 Failure
|
||||
@retval -1 Fatal error
|
||||
*/
|
||||
|
||||
int partition_info::gen_part_type(THD *thd, String *str) const
|
||||
{
|
||||
int err= 0;
|
||||
switch (part_type)
|
||||
{
|
||||
case RANGE_PARTITION:
|
||||
err+= str->append(STRING_WITH_LEN("RANGE "));
|
||||
break;
|
||||
case LIST_PARTITION:
|
||||
err+= str->append(STRING_WITH_LEN("LIST "));
|
||||
break;
|
||||
case HASH_PARTITION:
|
||||
if (linear_hash_ind)
|
||||
err+= str->append(STRING_WITH_LEN("LINEAR "));
|
||||
if (list_of_part_fields)
|
||||
{
|
||||
err+= add_key_with_algorithm(str, this);
|
||||
err+= add_part_field_list(thd, str, part_field_list);
|
||||
}
|
||||
else
|
||||
err+= str->append(STRING_WITH_LEN("HASH "));
|
||||
break;
|
||||
case VERSIONING_PARTITION:
|
||||
err+= str->append(STRING_WITH_LEN("SYSTEM_TIME "));
|
||||
break;
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
/* We really shouldn't get here, no use in continuing from here */
|
||||
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL));
|
||||
return -1;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void part_type_error(THD *thd, partition_info *work_part_info,
|
||||
const char *part_type,
|
||||
partition_info *tab_part_info)
|
||||
{
|
||||
StringBuffer<256> tab_part_type;
|
||||
if (tab_part_info->gen_part_type(thd, &tab_part_type) < 0)
|
||||
return;
|
||||
tab_part_type.length(tab_part_type.length() - 1);
|
||||
if (work_part_info)
|
||||
{
|
||||
DBUG_ASSERT(!part_type);
|
||||
StringBuffer<256> work_part_type;
|
||||
if (work_part_info->gen_part_type(thd, &work_part_type) < 0)
|
||||
return;
|
||||
work_part_type.length(work_part_type.length() - 1);
|
||||
my_error(ER_PARTITION_WRONG_TYPE, MYF(0), work_part_type.c_ptr(),
|
||||
tab_part_type.c_ptr());
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(part_type);
|
||||
my_error(ER_PARTITION_WRONG_TYPE, MYF(0), part_type,
|
||||
tab_part_type.c_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Generate the partition syntax from the partition data structure.
|
||||
Useful for support of generating defaults, SHOW CREATE TABLES
|
||||
@@ -2542,34 +2614,10 @@ char *generate_partition_syntax(THD *thd, partition_info *part_info,
|
||||
DBUG_ENTER("generate_partition_syntax");
|
||||
|
||||
err+= str.append(STRING_WITH_LEN(" PARTITION BY "));
|
||||
switch (part_info->part_type)
|
||||
{
|
||||
case RANGE_PARTITION:
|
||||
err+= str.append(STRING_WITH_LEN("RANGE "));
|
||||
break;
|
||||
case LIST_PARTITION:
|
||||
err+= str.append(STRING_WITH_LEN("LIST "));
|
||||
break;
|
||||
case HASH_PARTITION:
|
||||
if (part_info->linear_hash_ind)
|
||||
err+= str.append(STRING_WITH_LEN("LINEAR "));
|
||||
if (part_info->list_of_part_fields)
|
||||
{
|
||||
err+= add_key_with_algorithm(&str, part_info);
|
||||
err+= add_part_field_list(thd, &str, part_info->part_field_list);
|
||||
}
|
||||
else
|
||||
err+= str.append(STRING_WITH_LEN("HASH "));
|
||||
break;
|
||||
case VERSIONING_PARTITION:
|
||||
err+= str.append(STRING_WITH_LEN("SYSTEM_TIME "));
|
||||
break;
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
/* We really shouldn't get here, no use in continuing from here */
|
||||
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL));
|
||||
int err2= part_info->gen_part_type(thd, &str);
|
||||
if (err2 < 0)
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
err+= err2;
|
||||
if (part_info->part_type == VERSIONING_PARTITION)
|
||||
{
|
||||
Vers_part_info *vers_info= part_info->vers_info;
|
||||
@@ -5069,7 +5117,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
|
||||
else if (thd->work_part_info->part_type == VERSIONING_PARTITION ||
|
||||
tab_part_info->part_type == VERSIONING_PARTITION)
|
||||
{
|
||||
my_error(ER_PARTITION_WRONG_TYPE, MYF(0), "SYSTEM_TIME");
|
||||
part_type_error(thd, thd->work_part_info, NULL, tab_part_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -7901,6 +7901,7 @@ void append_drop_column(THD *thd, String *str, Field *field)
|
||||
}
|
||||
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
static inline
|
||||
void rename_field_in_list(Create_field *field, List<const char> *field_list)
|
||||
{
|
||||
@@ -7913,6 +7914,7 @@ void rename_field_in_list(Create_field *field, List<const char> *field_list)
|
||||
it.replace(field->field_name.str);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
|
@@ -4803,13 +4803,17 @@ opt_part_values:
|
||||
part_values_in {}
|
||||
| CURRENT_SYM
|
||||
{
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if (Lex->part_values_current(thd))
|
||||
MYSQL_YYABORT;
|
||||
#endif
|
||||
}
|
||||
| HISTORY_SYM
|
||||
{
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if (Lex->part_values_history(thd))
|
||||
MYSQL_YYABORT;
|
||||
#endif
|
||||
}
|
||||
| DEFAULT
|
||||
{
|
||||
@@ -18874,6 +18878,7 @@ package_implementation_function_body:
|
||||
sp_head *sp= pkg->m_current_routine->sphead;
|
||||
thd->lex= pkg->m_current_routine;
|
||||
sp->reset_thd_mem_root(thd);
|
||||
sp->set_c_chistics(thd->lex->sp_chistics);
|
||||
sp->set_body_start(thd, YYLIP->get_cpp_tok_start());
|
||||
}
|
||||
sp_body opt_package_routine_end_name
|
||||
@@ -18892,6 +18897,7 @@ package_implementation_procedure_body:
|
||||
sp_head *sp= pkg->m_current_routine->sphead;
|
||||
thd->lex= pkg->m_current_routine;
|
||||
sp->reset_thd_mem_root(thd);
|
||||
sp->set_c_chistics(thd->lex->sp_chistics);
|
||||
sp->set_body_start(thd, YYLIP->get_cpp_tok_start());
|
||||
}
|
||||
sp_body opt_package_routine_end_name
|
||||
|
@@ -270,8 +270,7 @@ SET(INNOBASE_SOURCES
|
||||
include/handler0alter.h
|
||||
include/hash0hash.h
|
||||
include/ibuf0ibuf.h
|
||||
include/ibuf0ibuf.inl/
|
||||
include/ibuf0types.h
|
||||
include/ibuf0ibuf.inl
|
||||
include/lock0iter.h
|
||||
include/lock0lock.h
|
||||
include/lock0lock.inl
|
||||
@@ -289,7 +288,6 @@ SET(INNOBASE_SOURCES
|
||||
include/mem0mem.inl
|
||||
include/mtr0log.h
|
||||
include/mtr0mtr.h
|
||||
include/mtr0mtr.inl
|
||||
include/mtr0types.h
|
||||
include/os0file.h
|
||||
include/os0file.inl
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -827,7 +827,6 @@ PageBulk::storeExt(
|
||||
btr_pcur_t btr_pcur;
|
||||
btr_pcur.pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
btr_pcur.latch_mode = BTR_MODIFY_LEAF;
|
||||
btr_pcur.btr_cur.index = m_index;
|
||||
btr_pcur.btr_cur.page_cur.index = m_index;
|
||||
btr_pcur.btr_cur.page_cur.rec = m_cur_rec;
|
||||
btr_pcur.btr_cur.page_cur.offsets = offsets;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -169,7 +169,7 @@ btr_defragment_find_index(
|
||||
@return whether the operation was interrupted */
|
||||
bool btr_defragment_add_index(btr_pcur_t *pcur, THD *thd)
|
||||
{
|
||||
dict_stats_empty_defrag_summary(pcur->btr_cur.index);
|
||||
dict_stats_empty_defrag_summary(pcur->index());
|
||||
pthread_cond_t cond;
|
||||
pthread_cond_init(&cond, nullptr);
|
||||
btr_defragment_item_t item(pcur, &cond);
|
||||
@@ -209,7 +209,7 @@ btr_defragment_remove_table(
|
||||
mysql_mutex_lock(&btr_defragment_mutex);
|
||||
for (auto item : btr_defragment_wq)
|
||||
{
|
||||
if (item->cond && table == item->pcur->btr_cur.index->table)
|
||||
if (item->cond && table == item->pcur->index()->table)
|
||||
{
|
||||
pthread_cond_signal(item->cond);
|
||||
item->cond= nullptr;
|
||||
@@ -405,7 +405,10 @@ btr_defragment_merge_pages(
|
||||
}
|
||||
}
|
||||
btr_cur_t parent;
|
||||
if (!btr_page_get_father(index, from_block, mtr, &parent)) {
|
||||
parent.page_cur.index = index;
|
||||
parent.page_cur.block = from_block;
|
||||
|
||||
if (!btr_page_get_father(mtr, &parent)) {
|
||||
to_block = nullptr;
|
||||
} else if (n_recs_to_move == n_recs) {
|
||||
/* The whole page is merged with the previous page,
|
||||
@@ -690,7 +693,7 @@ processed:
|
||||
}
|
||||
log_free_check();
|
||||
mtr_start(&mtr);
|
||||
dict_index_t *index = item->pcur->btr_cur.index;
|
||||
dict_index_t *index = item->pcur->index();
|
||||
index->set_modified(mtr);
|
||||
/* To follow the latching order defined in WL#6326,
|
||||
acquire index->lock X-latch. This entitles us to
|
||||
|
@@ -29,25 +29,6 @@ Created 2/23/1996 Heikki Tuuri
|
||||
#include "rem0cmp.h"
|
||||
#include "trx0trx.h"
|
||||
|
||||
/**************************************************************//**
|
||||
Allocates memory for a persistent cursor object and initializes the cursor.
|
||||
@return own: persistent cursor */
|
||||
btr_pcur_t*
|
||||
btr_pcur_create_for_mysql(void)
|
||||
/*============================*/
|
||||
{
|
||||
btr_pcur_t* pcur;
|
||||
DBUG_ENTER("btr_pcur_create_for_mysql");
|
||||
|
||||
pcur = (btr_pcur_t*) ut_malloc_nokey(sizeof(btr_pcur_t));
|
||||
|
||||
pcur->btr_cur.index = NULL;
|
||||
btr_pcur_init(pcur);
|
||||
|
||||
DBUG_PRINT("btr_pcur_create_for_mysql", ("pcur: %p", pcur));
|
||||
DBUG_RETURN(pcur);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Resets a persistent cursor object, freeing ::old_rec_buf if it is
|
||||
allocated and resetting the other members to their initial values. */
|
||||
@@ -56,34 +37,17 @@ btr_pcur_reset(
|
||||
/*===========*/
|
||||
btr_pcur_t* cursor) /*!< in, out: persistent cursor */
|
||||
{
|
||||
btr_pcur_free(cursor);
|
||||
ut_free(cursor->old_rec_buf);
|
||||
memset(&cursor->btr_cur.page_cur, 0, sizeof(page_cur_t));
|
||||
cursor->old_rec_buf = NULL;
|
||||
cursor->btr_cur.index = NULL;
|
||||
cursor->btr_cur.page_cur.rec = NULL;
|
||||
cursor->old_rec = NULL;
|
||||
cursor->old_n_core_fields = 0;
|
||||
cursor->old_n_fields = 0;
|
||||
cursor->old_stored = false;
|
||||
|
||||
cursor->latch_mode = BTR_NO_LATCHES;
|
||||
cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Frees the memory for a persistent cursor object. */
|
||||
void
|
||||
btr_pcur_free_for_mysql(
|
||||
/*====================*/
|
||||
btr_pcur_t* cursor) /*!< in, own: persistent cursor */
|
||||
{
|
||||
DBUG_ENTER("btr_pcur_free_for_mysql");
|
||||
DBUG_PRINT("btr_pcur_free_for_mysql", ("pcur: %p", cursor));
|
||||
|
||||
btr_pcur_free(cursor);
|
||||
ut_free(cursor);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
The position of the cursor is stored by taking an initial segment of the
|
||||
record the cursor is positioned on, before, or after, and copying it to the
|
||||
@@ -125,8 +89,6 @@ btr_pcur_store_position(
|
||||
&& mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK
|
||||
| MTR_MEMO_SX_LOCK)));
|
||||
|
||||
cursor->old_stored = true;
|
||||
|
||||
if (page_is_empty(block->page.frame)) {
|
||||
/* It must be an empty index tree; NOTE that in this case
|
||||
we do not store the modify_clock, but always do a search
|
||||
@@ -256,11 +218,12 @@ otherwise. */
|
||||
struct optimistic_latch_leaves
|
||||
{
|
||||
btr_pcur_t *const cursor;
|
||||
ulint *latch_mode;
|
||||
btr_latch_mode *latch_mode;
|
||||
mtr_t *const mtr;
|
||||
|
||||
optimistic_latch_leaves(btr_pcur_t *cursor, ulint *latch_mode, mtr_t *mtr)
|
||||
:cursor(cursor), latch_mode(latch_mode), mtr(mtr) {}
|
||||
optimistic_latch_leaves(btr_pcur_t *cursor, btr_latch_mode *latch_mode,
|
||||
mtr_t *mtr)
|
||||
: cursor(cursor), latch_mode(latch_mode), mtr(mtr) {}
|
||||
|
||||
bool operator() (buf_block_t *hint) const
|
||||
{
|
||||
@@ -292,7 +255,7 @@ record with the same unique field values as in the stored record,
|
||||
btr_pcur_t::NOT_SAME cursor position is not on user rec or points on
|
||||
the record with not the samebuniq field values as in the stored */
|
||||
btr_pcur_t::restore_status
|
||||
btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
|
||||
btr_pcur_t::restore_position(btr_latch_mode restore_latch_mode, mtr_t *mtr)
|
||||
{
|
||||
dict_index_t* index;
|
||||
dtuple_t* tuple;
|
||||
@@ -301,7 +264,6 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
|
||||
mem_heap_t* heap;
|
||||
|
||||
ut_ad(mtr->is_active());
|
||||
//ut_ad(cursor->old_stored);
|
||||
ut_ad(pos_state == BTR_PCUR_WAS_POSITIONED
|
||||
|| pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
|
||||
@@ -313,10 +275,9 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
|
||||
/* In these cases we do not try an optimistic restoration,
|
||||
but always do a search */
|
||||
|
||||
if (btr_cur_open_at_index_side(
|
||||
rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
|
||||
index, restore_latch_mode,
|
||||
&btr_cur, 0, mtr) != DB_SUCCESS) {
|
||||
if (btr_cur.open_leaf(rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
|
||||
index, restore_latch_mode, mtr)
|
||||
!= DB_SUCCESS) {
|
||||
return restore_status::CORRUPTED;
|
||||
}
|
||||
|
||||
@@ -333,9 +294,10 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
|
||||
ut_a(old_n_core_fields <= index->n_core_fields);
|
||||
ut_a(old_n_fields);
|
||||
|
||||
switch (restore_latch_mode) {
|
||||
case BTR_SEARCH_LEAF:
|
||||
case BTR_MODIFY_LEAF:
|
||||
static_assert(BTR_SEARCH_PREV == (4 | BTR_SEARCH_LEAF), "");
|
||||
static_assert(BTR_MODIFY_PREV == (4 | BTR_MODIFY_LEAF), "");
|
||||
|
||||
switch (restore_latch_mode | 4) {
|
||||
case BTR_SEARCH_PREV:
|
||||
case BTR_MODIFY_PREV:
|
||||
/* Try optimistic restoration. */
|
||||
@@ -420,7 +382,7 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
|
||||
mode = PAGE_CUR_UNSUPP;
|
||||
}
|
||||
|
||||
if (btr_pcur_open_with_no_init(index, tuple, mode, restore_latch_mode,
|
||||
if (btr_pcur_open_with_no_init(tuple, mode, restore_latch_mode,
|
||||
this, mtr) != DB_SUCCESS) {
|
||||
mem_heap_free(heap);
|
||||
return restore_status::CORRUPTED;
|
||||
@@ -450,7 +412,6 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
|
||||
block_when_stored.store(btr_pcur_get_block(this));
|
||||
modify_clock= buf_block_get_modify_clock(
|
||||
block_when_stored.block());
|
||||
old_stored= true;
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
||||
@@ -487,7 +448,7 @@ btr_pcur_move_to_next_page(
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
ut_ad(btr_pcur_is_after_last_on_page(cursor));
|
||||
|
||||
cursor->old_stored = false;
|
||||
cursor->old_rec = nullptr;
|
||||
|
||||
const page_t* page = btr_pcur_get_page(cursor);
|
||||
const uint32_t next_page_no = btr_page_get_next(page);
|
||||
@@ -515,7 +476,7 @@ btr_pcur_move_to_next_page(
|
||||
|
||||
dberr_t err;
|
||||
buf_block_t* next_block = btr_block_get(
|
||||
*btr_pcur_get_btr_cur(cursor)->index, next_page_no, mode,
|
||||
*cursor->index(), next_page_no, mode,
|
||||
page_is_leaf(page), mtr, &err);
|
||||
|
||||
if (UNIV_UNLIKELY(!next_block)) {
|
||||
@@ -529,12 +490,13 @@ btr_pcur_move_to_next_page(
|
||||
return DB_CORRUPTION;
|
||||
}
|
||||
|
||||
btr_leaf_page_release(btr_pcur_get_block(cursor), mode, mtr);
|
||||
|
||||
page_cur_set_before_first(next_block, btr_pcur_get_page_cur(cursor));
|
||||
|
||||
ut_d(page_check_dir(next_page));
|
||||
return err;
|
||||
|
||||
const auto s = mtr->get_savepoint();
|
||||
mtr->rollback_to_savepoint(s - 2, s - 1);
|
||||
return DB_SUCCESS;
|
||||
}
|
||||
|
||||
MY_ATTRIBUTE((nonnull,warn_unused_result))
|
||||
@@ -558,7 +520,7 @@ btr_pcur_move_backward_from_page(
|
||||
ut_ad(btr_pcur_is_before_first_on_page(cursor));
|
||||
ut_ad(!btr_pcur_is_before_first_in_tree(cursor));
|
||||
|
||||
const ulint latch_mode = cursor->latch_mode;
|
||||
const auto latch_mode = cursor->latch_mode;
|
||||
ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF);
|
||||
|
||||
btr_pcur_store_position(cursor, mtr);
|
||||
@@ -570,31 +532,32 @@ btr_pcur_move_backward_from_page(
|
||||
static_assert(BTR_SEARCH_PREV == (4 | BTR_SEARCH_LEAF), "");
|
||||
static_assert(BTR_MODIFY_PREV == (4 | BTR_MODIFY_LEAF), "");
|
||||
|
||||
if (UNIV_UNLIKELY(cursor->restore_position(4 | latch_mode, mtr)
|
||||
if (UNIV_UNLIKELY(cursor->restore_position(
|
||||
btr_latch_mode(4 | latch_mode), mtr)
|
||||
== btr_pcur_t::CORRUPTED)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
buf_block_t* prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
|
||||
buf_block_t* release_block = nullptr;
|
||||
|
||||
if (!page_has_prev(btr_pcur_get_page(cursor))) {
|
||||
} else if (btr_pcur_is_before_first_on_page(cursor)) {
|
||||
btr_leaf_page_release(btr_pcur_get_block(cursor),
|
||||
latch_mode, mtr);
|
||||
|
||||
page_cur_set_after_last(prev_block,
|
||||
release_block = btr_pcur_get_block(cursor);
|
||||
page_cur_set_after_last(cursor->btr_cur.left_block,
|
||||
btr_pcur_get_page_cur(cursor));
|
||||
} else {
|
||||
/* The repositioned cursor did not end on an infimum
|
||||
record on a page. Cursor repositioning acquired a latch
|
||||
also on the previous page, but we do not need the latch:
|
||||
release it. */
|
||||
prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
|
||||
btr_leaf_page_release(prev_block, latch_mode, mtr);
|
||||
release_block = cursor->btr_cur.left_block;
|
||||
}
|
||||
|
||||
cursor->latch_mode = latch_mode;
|
||||
cursor->old_stored = false;
|
||||
cursor->old_rec = nullptr;
|
||||
if (release_block) {
|
||||
mtr->release(*release_block);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -612,7 +575,7 @@ btr_pcur_move_to_prev(
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
cursor->old_stored = false;
|
||||
cursor->old_rec = nullptr;
|
||||
|
||||
if (btr_pcur_is_before_first_on_page(cursor)) {
|
||||
return (!btr_pcur_is_before_first_in_tree(cursor)
|
||||
|
@@ -302,7 +302,7 @@ are consistent.
|
||||
@param[in] cursor cursor which was just positioned */
|
||||
static void btr_search_info_update_hash(btr_search_t *info, btr_cur_t *cursor)
|
||||
{
|
||||
dict_index_t* index = cursor->index;
|
||||
dict_index_t* index = cursor->index();
|
||||
int cmp;
|
||||
|
||||
if (dict_index_is_ibuf(index)) {
|
||||
@@ -704,14 +704,14 @@ btr_search_update_hash_ref(
|
||||
return;
|
||||
}
|
||||
|
||||
if (index != cursor->index) {
|
||||
ut_ad(index->id == cursor->index->id);
|
||||
if (index != cursor->index()) {
|
||||
ut_ad(index->id == cursor->index()->id);
|
||||
btr_search_drop_page_hash_index(block);
|
||||
return;
|
||||
}
|
||||
|
||||
ut_ad(block->page.id().space() == index->table->space_id);
|
||||
ut_ad(index == cursor->index);
|
||||
ut_ad(index == cursor->index());
|
||||
ut_ad(!dict_index_is_ibuf(index));
|
||||
auto part = btr_search_sys.get_part(*index);
|
||||
part->latch.wr_lock(SRW_LOCK_CALL);
|
||||
@@ -784,7 +784,7 @@ btr_search_check_guess(
|
||||
bool success = false;
|
||||
rec_offs_init(offsets_);
|
||||
|
||||
n_unique = dict_index_get_n_unique_in_tree(cursor->index);
|
||||
n_unique = dict_index_get_n_unique_in_tree(cursor->index());
|
||||
|
||||
rec = btr_cur_get_rec(cursor);
|
||||
|
||||
@@ -792,7 +792,7 @@ btr_search_check_guess(
|
||||
|| !page_rec_is_leaf(rec))) {
|
||||
ut_ad("corrupted index" == 0);
|
||||
return false;
|
||||
} else if (cursor->index->table->not_redundant()) {
|
||||
} else if (cursor->index()->table->not_redundant()) {
|
||||
switch (rec_get_status(rec)) {
|
||||
case REC_STATUS_INSTANT:
|
||||
case REC_STATUS_ORDINARY:
|
||||
@@ -805,10 +805,10 @@ btr_search_check_guess(
|
||||
|
||||
match = 0;
|
||||
|
||||
offsets = rec_get_offsets(rec, cursor->index, offsets,
|
||||
cursor->index->n_core_fields,
|
||||
offsets = rec_get_offsets(rec, cursor->index(), offsets,
|
||||
cursor->index()->n_core_fields,
|
||||
n_unique, &heap);
|
||||
cmp = cmp_dtuple_rec_with_match(tuple, rec, cursor->index, offsets,
|
||||
cmp = cmp_dtuple_rec_with_match(tuple, rec, cursor->index(), offsets,
|
||||
&match);
|
||||
|
||||
if (mode == PAGE_CUR_GE) {
|
||||
@@ -860,7 +860,7 @@ btr_search_check_guess(
|
||||
goto exit_func;
|
||||
}
|
||||
|
||||
if (cursor->index->table->not_redundant()) {
|
||||
if (cursor->index()->table->not_redundant()) {
|
||||
switch (rec_get_status(prev_rec)) {
|
||||
case REC_STATUS_INSTANT:
|
||||
case REC_STATUS_ORDINARY:
|
||||
@@ -871,11 +871,12 @@ btr_search_check_guess(
|
||||
}
|
||||
}
|
||||
|
||||
offsets = rec_get_offsets(prev_rec, cursor->index, offsets,
|
||||
cursor->index->n_core_fields,
|
||||
offsets = rec_get_offsets(prev_rec, cursor->index(), offsets,
|
||||
cursor->index()->n_core_fields,
|
||||
n_unique, &heap);
|
||||
cmp = cmp_dtuple_rec_with_match(
|
||||
tuple, prev_rec, cursor->index, offsets, &match);
|
||||
cmp = cmp_dtuple_rec_with_match(tuple, prev_rec,
|
||||
cursor->index(), offsets,
|
||||
&match);
|
||||
if (mode == PAGE_CUR_GE) {
|
||||
success = cmp > 0;
|
||||
} else {
|
||||
@@ -900,7 +901,7 @@ btr_search_check_guess(
|
||||
goto exit_func;
|
||||
}
|
||||
|
||||
if (cursor->index->table->not_redundant()) {
|
||||
if (cursor->index()->table->not_redundant()) {
|
||||
switch (rec_get_status(next_rec)) {
|
||||
case REC_STATUS_INSTANT:
|
||||
case REC_STATUS_ORDINARY:
|
||||
@@ -911,11 +912,11 @@ btr_search_check_guess(
|
||||
}
|
||||
}
|
||||
|
||||
offsets = rec_get_offsets(next_rec, cursor->index, offsets,
|
||||
cursor->index->n_core_fields,
|
||||
offsets = rec_get_offsets(next_rec, cursor->index(), offsets,
|
||||
cursor->index()->n_core_fields,
|
||||
n_unique, &heap);
|
||||
cmp = cmp_dtuple_rec_with_match(
|
||||
tuple, next_rec, cursor->index, offsets, &match);
|
||||
tuple, next_rec, cursor->index(), offsets, &match);
|
||||
if (mode == PAGE_CUR_LE) {
|
||||
success = cmp < 0;
|
||||
cursor->up_match = match;
|
||||
@@ -1099,16 +1100,16 @@ btr_search_guess_on_hash(
|
||||
part->latch.rd_lock(SRW_LOCK_CALL);
|
||||
|
||||
if (!btr_search_enabled) {
|
||||
goto fail;
|
||||
goto ahi_release_and_fail;
|
||||
}
|
||||
|
||||
rec = static_cast<const rec_t*>(
|
||||
ha_search_and_get_data(&part->table, fold));
|
||||
|
||||
if (!rec) {
|
||||
fail:
|
||||
ahi_release_and_fail:
|
||||
part->latch.rd_unlock();
|
||||
|
||||
fail:
|
||||
btr_search_failure(info, cursor);
|
||||
return false;
|
||||
}
|
||||
@@ -1117,66 +1118,52 @@ fail:
|
||||
|
||||
buf_pool_t::hash_chain& chain = buf_pool.page_hash.cell_get(
|
||||
block->page.id().fold());
|
||||
bool fail, got_latch;
|
||||
bool got_latch;
|
||||
{
|
||||
transactional_shared_lock_guard<page_hash_latch> g{
|
||||
buf_pool.page_hash.lock_get(chain)};
|
||||
|
||||
const auto state = block->page.state();
|
||||
if (state == buf_page_t::REMOVE_HASH) {
|
||||
/* Another thread is just freeing the block
|
||||
from the LRU list of the buffer pool: do not
|
||||
try to access this page. */
|
||||
goto fail;
|
||||
}
|
||||
if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED)) {
|
||||
#ifndef NO_ELISION
|
||||
xend();
|
||||
#endif
|
||||
ut_error;
|
||||
}
|
||||
|
||||
fail = index != block->index && index_id == block->index->id;
|
||||
got_latch = (latch_mode == BTR_SEARCH_LEAF)
|
||||
? block->page.lock.s_lock_try()
|
||||
: block->page.lock.x_lock_try();
|
||||
}
|
||||
|
||||
ut_a(!fail || block->index->freed());
|
||||
if (!got_latch) {
|
||||
goto fail;
|
||||
goto ahi_release_and_fail;
|
||||
}
|
||||
|
||||
const auto state = block->page.state();
|
||||
if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED)) {
|
||||
ut_ad(state == buf_page_t::REMOVE_HASH);
|
||||
block_and_ahi_release_and_fail:
|
||||
if (latch_mode == BTR_SEARCH_LEAF) {
|
||||
block->page.lock.s_unlock();
|
||||
} else {
|
||||
block->page.lock.x_unlock();
|
||||
}
|
||||
goto ahi_release_and_fail;
|
||||
}
|
||||
|
||||
ut_ad(state < buf_page_t::READ_FIX || state >= buf_page_t::WRITE_FIX);
|
||||
ut_ad(state < buf_page_t::READ_FIX || latch_mode == BTR_SEARCH_LEAF);
|
||||
|
||||
if (index != block->index && index_id == block->index->id) {
|
||||
ut_a(block->index->freed());
|
||||
goto block_and_ahi_release_and_fail;
|
||||
}
|
||||
|
||||
block->page.fix();
|
||||
block->page.set_accessed();
|
||||
buf_page_make_young_if_needed(&block->page);
|
||||
ut_ad(!block->page.is_read_fixed());
|
||||
ut_ad(latch_mode == BTR_SEARCH_LEAF || !block->page.is_io_fixed());
|
||||
static_assert(ulint{MTR_MEMO_PAGE_S_FIX} == ulint{BTR_SEARCH_LEAF},
|
||||
"");
|
||||
static_assert(ulint{MTR_MEMO_PAGE_X_FIX} == ulint{BTR_MODIFY_LEAF},
|
||||
"");
|
||||
mtr->memo_push(block, mtr_memo_type_t(latch_mode));
|
||||
|
||||
++buf_pool.stat.n_page_gets;
|
||||
|
||||
part->latch.rd_unlock();
|
||||
|
||||
if (UNIV_UNLIKELY(fail)) {
|
||||
goto fail_and_release_page;
|
||||
}
|
||||
++buf_pool.stat.n_page_gets;
|
||||
|
||||
DBUG_ASSERT(!block->page.is_freed());
|
||||
|
||||
if (!block->page.in_file()) {
|
||||
ut_ad(block->page.state() == buf_page_t::REMOVE_HASH);
|
||||
|
||||
fail_and_release_page:
|
||||
btr_leaf_page_release(block, latch_mode, mtr);
|
||||
|
||||
btr_search_failure(info, cursor);
|
||||
return false;
|
||||
}
|
||||
mtr->memo_push(block, mtr_memo_type_t(latch_mode));
|
||||
|
||||
ut_ad(page_rec_is_user_rec(rec));
|
||||
|
||||
@@ -1191,7 +1178,8 @@ fail_and_release_page:
|
||||
right. */
|
||||
if (index_id != btr_page_get_index_id(block->page.frame)
|
||||
|| !btr_search_check_guess(cursor, false, tuple, mode)) {
|
||||
goto fail_and_release_page;
|
||||
mtr->release_last_page();
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5) {
|
||||
@@ -1199,41 +1187,6 @@ fail_and_release_page:
|
||||
info->n_hash_potential++;
|
||||
}
|
||||
|
||||
#ifdef notdefined
|
||||
/* These lines of code can be used in a debug version to check
|
||||
the correctness of the searched cursor position: */
|
||||
|
||||
info->last_hash_succ = FALSE;
|
||||
|
||||
/* Currently, does not work if the following fails: */
|
||||
ut_ad(!ahi_latch);
|
||||
|
||||
btr_leaf_page_release(block, latch_mode, mtr);
|
||||
|
||||
btr_cur_search_to_nth_level(
|
||||
index, 0, tuple, mode, latch_mode, &cursor2, 0, mtr);
|
||||
|
||||
if (mode == PAGE_CUR_GE
|
||||
&& page_rec_is_supremum(btr_cur_get_rec(&cursor2))) {
|
||||
|
||||
/* If mode is PAGE_CUR_GE, then the binary search
|
||||
in the index tree may actually take us to the supremum
|
||||
of the previous page */
|
||||
|
||||
info->last_hash_succ = FALSE;
|
||||
|
||||
btr_pcur_open_on_user_rec(
|
||||
index, tuple, mode, latch_mode, &pcur, mtr);
|
||||
|
||||
ut_ad(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor));
|
||||
} else {
|
||||
ut_ad(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor));
|
||||
}
|
||||
|
||||
/* NOTE that it is theoretically possible that the above assertions
|
||||
fail if the page of the cursor gets removed from the buffer pool
|
||||
meanwhile! Thus it might not be a bug. */
|
||||
#endif
|
||||
info->last_hash_succ = TRUE;
|
||||
|
||||
#ifdef UNIV_SEARCH_PERF_STAT
|
||||
@@ -1691,7 +1644,7 @@ exit_func:
|
||||
@param[in,out] cursor cursor which was just positioned */
|
||||
void btr_search_info_update_slow(btr_search_t *info, btr_cur_t *cursor)
|
||||
{
|
||||
srw_spin_lock* ahi_latch = &btr_search_sys.get_part(*cursor->index)
|
||||
srw_spin_lock* ahi_latch = &btr_search_sys.get_part(*cursor->index())
|
||||
->latch;
|
||||
buf_block_t* block = btr_cur_get_block(cursor);
|
||||
|
||||
@@ -1706,7 +1659,7 @@ void btr_search_info_update_slow(btr_search_t *info, btr_cur_t *cursor)
|
||||
|
||||
if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
|
||||
|
||||
btr_search_check_free_space_in_heap(cursor->index);
|
||||
btr_search_check_free_space_in_heap(cursor->index());
|
||||
}
|
||||
|
||||
if (cursor->flag == BTR_CUR_HASH_FAIL) {
|
||||
@@ -1723,7 +1676,7 @@ void btr_search_info_update_slow(btr_search_t *info, btr_cur_t *cursor)
|
||||
/* Note that since we did not protect block->n_fields etc.
|
||||
with any semaphore, the values can be inconsistent. We have
|
||||
to check inside the function call that they make sense. */
|
||||
btr_search_build_page_hash_index(cursor->index, block,
|
||||
btr_search_build_page_hash_index(cursor->index(), block,
|
||||
ahi_latch,
|
||||
block->n_fields,
|
||||
block->n_bytes,
|
||||
@@ -1835,15 +1788,15 @@ void btr_search_update_hash_on_delete(btr_cur_t *cursor)
|
||||
return;
|
||||
}
|
||||
|
||||
ut_ad(!cursor->index->table->is_temporary());
|
||||
ut_ad(!cursor->index()->table->is_temporary());
|
||||
|
||||
if (index != cursor->index) {
|
||||
if (index != cursor->index()) {
|
||||
btr_search_drop_page_hash_index(block);
|
||||
return;
|
||||
}
|
||||
|
||||
ut_ad(block->page.id().space() == index->table->space_id);
|
||||
ut_a(index == cursor->index);
|
||||
ut_a(index == cursor->index());
|
||||
ut_a(block->curr_n_fields > 0 || block->curr_n_bytes > 0);
|
||||
ut_ad(!dict_index_is_ibuf(index));
|
||||
|
||||
@@ -1890,7 +1843,7 @@ void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
|
||||
dict_index_t* index;
|
||||
rec_t* rec;
|
||||
|
||||
ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index)->latch);
|
||||
ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index())->latch);
|
||||
|
||||
if (!btr_search_enabled) {
|
||||
return;
|
||||
@@ -1909,15 +1862,15 @@ void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
|
||||
return;
|
||||
}
|
||||
|
||||
ut_ad(!cursor->index->table->is_temporary());
|
||||
ut_ad(!cursor->index()->table->is_temporary());
|
||||
|
||||
if (index != cursor->index) {
|
||||
ut_ad(index->id == cursor->index->id);
|
||||
if (index != cursor->index()) {
|
||||
ut_ad(index->id == cursor->index()->id);
|
||||
btr_search_drop_page_hash_index(block);
|
||||
return;
|
||||
}
|
||||
|
||||
ut_a(cursor->index == index);
|
||||
ut_a(cursor->index() == index);
|
||||
ut_ad(!dict_index_is_ibuf(index));
|
||||
ahi_latch->wr_lock(SRW_LOCK_CALL);
|
||||
|
||||
@@ -1934,7 +1887,7 @@ void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
|
||||
&& !block->curr_left_side) {
|
||||
if (const rec_t *new_rec = page_rec_get_next_const(rec)) {
|
||||
if (ha_search_and_update_if_found(
|
||||
&btr_search_sys.get_part(*cursor->index)
|
||||
&btr_search_sys.get_part(*cursor->index())
|
||||
->table,
|
||||
cursor->fold, rec, block, new_rec)) {
|
||||
MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_UPDATED);
|
||||
@@ -1977,7 +1930,7 @@ void btr_search_update_hash_on_insert(btr_cur_t *cursor,
|
||||
rec_offs* offsets = offsets_;
|
||||
rec_offs_init(offsets_);
|
||||
|
||||
ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index)->latch);
|
||||
ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index())->latch);
|
||||
ut_ad(page_is_leaf(btr_cur_get_page(cursor)));
|
||||
|
||||
if (!btr_search_enabled) {
|
||||
@@ -2001,16 +1954,16 @@ void btr_search_update_hash_on_insert(btr_cur_t *cursor,
|
||||
|
||||
rec = btr_cur_get_rec(cursor);
|
||||
|
||||
ut_ad(!cursor->index->table->is_temporary());
|
||||
ut_ad(!cursor->index()->table->is_temporary());
|
||||
|
||||
if (index != cursor->index) {
|
||||
ut_ad(index->id == cursor->index->id);
|
||||
if (index != cursor->index()) {
|
||||
ut_ad(index->id == cursor->index()->id);
|
||||
drop:
|
||||
btr_search_drop_page_hash_index(block);
|
||||
return;
|
||||
}
|
||||
|
||||
ut_a(index == cursor->index);
|
||||
ut_a(index == cursor->index());
|
||||
ut_ad(!dict_index_is_ibuf(index));
|
||||
|
||||
n_fields = block->curr_n_fields;
|
||||
|
@@ -1712,6 +1712,14 @@ inline void log_t::write_checkpoint(lsn_t end_lsn) noexcept
|
||||
|
||||
DBUG_PRINT("ib_log", ("checkpoint ended at " LSN_PF ", flushed to " LSN_PF,
|
||||
next_checkpoint_lsn, get_flushed_lsn()));
|
||||
if (overwrite_warned)
|
||||
{
|
||||
sql_print_information("InnoDB: Crash recovery was broken "
|
||||
"between LSN=" LSN_PF
|
||||
" and checkpoint LSN=" LSN_PF ".",
|
||||
overwrite_warned, next_checkpoint_lsn);
|
||||
overwrite_warned= 0;
|
||||
}
|
||||
|
||||
latch.wr_unlock();
|
||||
}
|
||||
@@ -1884,6 +1892,7 @@ ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn)
|
||||
record from a previous fil_names_clear() call, which we must
|
||||
write out before we can advance the checkpoint. */
|
||||
log_write_up_to(sync_lsn, true);
|
||||
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", return;);
|
||||
log_checkpoint();
|
||||
}
|
||||
}
|
||||
@@ -1898,6 +1907,8 @@ ATTRIBUTE_COLD void buf_flush_ahead(lsn_t lsn, bool furious)
|
||||
if (recv_recovery_is_on())
|
||||
recv_sys.apply(true);
|
||||
|
||||
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", return;);
|
||||
|
||||
Atomic_relaxed<lsn_t> &limit= furious
|
||||
? buf_flush_sync_lsn : buf_flush_async_lsn;
|
||||
|
||||
@@ -2252,6 +2263,7 @@ unemployed:
|
||||
buf_pool.page_cleaner_set_idle(true);
|
||||
|
||||
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", continue;);
|
||||
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", continue;);
|
||||
|
||||
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
|
||||
|
||||
@@ -2335,6 +2347,7 @@ do_checkpoint:
|
||||
here should not affect correctness, because log_free_check()
|
||||
should still be invoking checkpoints when needed. */
|
||||
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", goto next;);
|
||||
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", goto next;);
|
||||
|
||||
if (!recv_recovery_is_on() && srv_operation == SRV_OPERATION_NORMAL)
|
||||
log_checkpoint();
|
||||
|
@@ -755,11 +755,12 @@ dict_create_index_tree_step(
|
||||
|
||||
search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
|
||||
node->page_no = FIL_NULL;
|
||||
pcur.btr_cur.page_cur.index =
|
||||
UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes);
|
||||
|
||||
dberr_t err =
|
||||
btr_pcur_open(UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes),
|
||||
search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
|
||||
&pcur, &mtr);
|
||||
btr_pcur_open(search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
|
||||
&pcur, 0, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
func_exit:
|
||||
|
@@ -4147,8 +4147,9 @@ void dict_set_corrupted(dict_index_t *index, const char *ctx)
|
||||
dfield_set_data(dfield, buf, 8);
|
||||
|
||||
dict_index_copy_types(tuple, sys_index, 2);
|
||||
cursor.page_cur.index = sys_index;
|
||||
|
||||
if (btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_LE,
|
||||
if (btr_cur_search_to_nth_level(0, tuple, PAGE_CUR_LE,
|
||||
BTR_MODIFY_LEAF, &cursor, &mtr)
|
||||
!= DB_SUCCESS) {
|
||||
goto fail;
|
||||
@@ -4222,8 +4223,9 @@ dict_index_set_merge_threshold(
|
||||
dfield_set_data(dfield, buf, 8);
|
||||
|
||||
dict_index_copy_types(tuple, sys_index, 2);
|
||||
cursor.page_cur.index = sys_index;
|
||||
|
||||
if (btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE,
|
||||
if (btr_cur_search_to_nth_level(0, tuple, PAGE_CUR_GE,
|
||||
BTR_MODIFY_LEAF, &cursor, &mtr)
|
||||
!= DB_SUCCESS) {
|
||||
goto func_exit;
|
||||
|
@@ -215,8 +215,9 @@ dict_startscan_system(
|
||||
mtr_t* mtr, /*!< in: the mini-transaction */
|
||||
dict_table_t* table) /*!< in: system table */
|
||||
{
|
||||
if (btr_pcur_open_at_index_side(true, table->indexes.start, BTR_SEARCH_LEAF,
|
||||
pcur, true, 0, mtr) != DB_SUCCESS)
|
||||
btr_pcur_init(pcur);
|
||||
if (pcur->open_leaf(true, table->indexes.start, BTR_SEARCH_LEAF, mtr) !=
|
||||
DB_SUCCESS)
|
||||
return nullptr;
|
||||
const rec_t *rec;
|
||||
do
|
||||
@@ -1316,8 +1317,9 @@ static dberr_t dict_load_columns(dict_table_t *table, unsigned use_uncommitted,
|
||||
mach_write_to_8(table_id, table->id);
|
||||
dfield_set_data(&dfield, table_id, 8);
|
||||
dict_index_copy_types(&tuple, sys_index, 1);
|
||||
pcur.btr_cur.page_cur.index = sys_index;
|
||||
|
||||
dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
|
||||
dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
goto func_exit;
|
||||
@@ -1446,9 +1448,9 @@ dict_load_virtual_col(dict_table_t *table, bool uncommitted, ulint nth_v_col)
|
||||
dfield_set_data(&dfield[1], vcol_pos, 4);
|
||||
|
||||
dict_index_copy_types(&tuple, sys_virtual_index, 2);
|
||||
pcur.btr_cur.page_cur.index = sys_virtual_index;
|
||||
|
||||
dberr_t err = btr_pcur_open_on_user_rec(sys_virtual_index, &tuple,
|
||||
PAGE_CUR_GE,
|
||||
dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
goto func_exit;
|
||||
@@ -1686,8 +1688,9 @@ static dberr_t dict_load_fields(dict_index_t *index, bool uncommitted,
|
||||
mach_write_to_8(index_id, index->id);
|
||||
dfield_set_data(&dfield, index_id, 8);
|
||||
dict_index_copy_types(&tuple, sys_index, 1);
|
||||
pcur.btr_cur.page_cur.index = sys_index;
|
||||
|
||||
dberr_t error = btr_pcur_open_on_user_rec(sys_index, &tuple,
|
||||
dberr_t error = btr_pcur_open_on_user_rec(&tuple,
|
||||
PAGE_CUR_GE, BTR_SEARCH_LEAF,
|
||||
&pcur, &mtr);
|
||||
if (error != DB_SUCCESS) {
|
||||
@@ -1944,8 +1947,9 @@ dberr_t dict_load_indexes(dict_table_t *table, bool uncommitted,
|
||||
mach_write_to_8(table_id, table->id);
|
||||
dfield_set_data(&dfield, table_id, 8);
|
||||
dict_index_copy_types(&tuple, sys_index, 1);
|
||||
pcur.btr_cur.page_cur.index = sys_index;
|
||||
|
||||
dberr_t error = btr_pcur_open_on_user_rec(sys_index, &tuple,
|
||||
dberr_t error = btr_pcur_open_on_user_rec(&tuple,
|
||||
PAGE_CUR_GE, BTR_SEARCH_LEAF,
|
||||
&pcur, &mtr);
|
||||
if (error != DB_SUCCESS) {
|
||||
@@ -2338,11 +2342,12 @@ static dict_table_t *dict_load_table_one(const span<const char> &name,
|
||||
};
|
||||
dfield_set_data(&dfield, name.data(), name.size());
|
||||
dict_index_copy_types(&tuple, sys_index, 1);
|
||||
pcur.btr_cur.page_cur.index = sys_index;
|
||||
|
||||
bool uncommitted = false;
|
||||
reload:
|
||||
mtr.start();
|
||||
dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
|
||||
dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS || !btr_pcur_is_on_user_rec(&pcur)) {
|
||||
@@ -2596,10 +2601,11 @@ dict_load_table_on_id(
|
||||
mach_write_to_8(id_buf, table_id);
|
||||
dfield_set_data(&dfield, id_buf, 8);
|
||||
dict_index_copy_types(&tuple, sys_table_ids, 1);
|
||||
pcur.btr_cur.page_cur.index = sys_table_ids;
|
||||
|
||||
dict_table_t* table = nullptr;
|
||||
|
||||
if (btr_pcur_open_on_user_rec(sys_table_ids, &tuple, PAGE_CUR_GE,
|
||||
if (btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr)
|
||||
== DB_SUCCESS
|
||||
&& btr_pcur_is_on_user_rec(&pcur)) {
|
||||
@@ -2703,9 +2709,10 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id)
|
||||
|
||||
dfield_set_data(&dfield, foreign->id, id_len);
|
||||
dict_index_copy_types(&tuple, sys_index, 1);
|
||||
pcur.btr_cur.page_cur.index = sys_index;
|
||||
|
||||
mem_heap_t* heap = nullptr;
|
||||
dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
|
||||
dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
goto func_exit;
|
||||
@@ -2877,11 +2884,12 @@ dict_load_foreign(
|
||||
};
|
||||
dfield_set_data(&dfield, id.data(), id.size());
|
||||
dict_index_copy_types(&tuple, sys_index, 1);
|
||||
pcur.btr_cur.page_cur.index = sys_index;
|
||||
|
||||
mtr.start();
|
||||
|
||||
mem_heap_t* heap = nullptr;
|
||||
dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
|
||||
dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
goto err_exit;
|
||||
@@ -3090,8 +3098,9 @@ start_load:
|
||||
mtr.start();
|
||||
dfield_set_data(&dfield, table_name, strlen(table_name));
|
||||
dict_index_copy_types(&tuple, sec_index, 1);
|
||||
pcur.btr_cur.page_cur.index = sec_index;
|
||||
|
||||
dberr_t err = btr_pcur_open_on_user_rec(sec_index, &tuple, PAGE_CUR_GE,
|
||||
dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
DBUG_RETURN(err);
|
||||
@@ -3192,7 +3201,6 @@ next_rec:
|
||||
|
||||
load_next_index:
|
||||
mtr.commit();
|
||||
ut_free(pcur.old_rec_buf);
|
||||
|
||||
if ((sec_index = dict_table_get_next_index(sec_index))) {
|
||||
/* Switch to scan index on REF_NAME, fk_max_recusive_level
|
||||
@@ -3202,5 +3210,6 @@ load_next_index:
|
||||
goto start_load;
|
||||
}
|
||||
|
||||
ut_free(pcur.old_rec_buf);
|
||||
DBUG_RETURN(DB_SUCCESS);
|
||||
}
|
||||
|
@@ -1560,6 +1560,96 @@ empty_table:
|
||||
return err;
|
||||
}
|
||||
|
||||
/** Open a cursor at the first page in a tree level.
|
||||
@param page_cur cursor
|
||||
@param level level to search for (0=leaf)
|
||||
@param mtr mini-transaction */
|
||||
static dberr_t page_cur_open_level(page_cur_t *page_cur, ulint level,
|
||||
mtr_t *mtr)
|
||||
{
|
||||
mem_heap_t *heap= nullptr;
|
||||
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
|
||||
rec_offs *offsets= offsets_;
|
||||
dberr_t err;
|
||||
|
||||
dict_index_t *const index= page_cur->index;
|
||||
|
||||
rec_offs_init(offsets_);
|
||||
ut_ad(level != ULINT_UNDEFINED);
|
||||
ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_SX_LOCK));
|
||||
ut_ad(mtr->get_savepoint() == 1);
|
||||
|
||||
uint32_t page= index->page;
|
||||
|
||||
for (ulint height = ULINT_UNDEFINED;; height--)
|
||||
{
|
||||
buf_block_t* block=
|
||||
btr_block_get(*index, page, RW_S_LATCH,
|
||||
!height && !index->is_clust(), mtr, &err);
|
||||
if (!block)
|
||||
break;
|
||||
|
||||
const uint32_t l= btr_page_get_level(block->page.frame);
|
||||
|
||||
if (height == ULINT_UNDEFINED)
|
||||
{
|
||||
ut_ad(!heap);
|
||||
/* We are in the root node */
|
||||
height= l;
|
||||
if (UNIV_UNLIKELY(height < level))
|
||||
return DB_CORRUPTION;
|
||||
}
|
||||
else if (UNIV_UNLIKELY(height != l) || page_has_prev(block->page.frame))
|
||||
{
|
||||
err= DB_CORRUPTION;
|
||||
break;
|
||||
}
|
||||
|
||||
page_cur_set_before_first(block, page_cur);
|
||||
|
||||
if (height == level)
|
||||
break;
|
||||
|
||||
ut_ad(height);
|
||||
|
||||
if (!page_cur_move_to_next(page_cur))
|
||||
{
|
||||
err= DB_CORRUPTION;
|
||||
break;
|
||||
}
|
||||
|
||||
offsets= rec_get_offsets(page_cur->rec, index, offsets, 0, ULINT_UNDEFINED,
|
||||
&heap);
|
||||
page= btr_node_ptr_get_child_page_no(page_cur->rec, offsets);
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(heap))
|
||||
mem_heap_free(heap);
|
||||
|
||||
/* Release all page latches except the one on the desired page. */
|
||||
const auto end= mtr->get_savepoint();
|
||||
if (end > 1)
|
||||
mtr->rollback_to_savepoint(1, end - 1);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/** Open a cursor at the first page in a tree level.
|
||||
@param page_cur cursor
|
||||
@param level level to search for (0=leaf)
|
||||
@param mtr mini-transaction
|
||||
@param index index tree */
|
||||
static dberr_t btr_pcur_open_level(btr_pcur_t *pcur, ulint level, mtr_t *mtr,
|
||||
dict_index_t *index)
|
||||
{
|
||||
pcur->latch_mode= BTR_SEARCH_TREE;
|
||||
pcur->search_mode= PAGE_CUR_G;
|
||||
pcur->pos_state= BTR_PCUR_IS_POSITIONED;
|
||||
pcur->btr_cur.page_cur.index= index;
|
||||
return page_cur_open_level(&pcur->btr_cur.page_cur, level, mtr);
|
||||
}
|
||||
|
||||
|
||||
/* @{ Pseudo code about the relation between the following functions
|
||||
|
||||
let N = N_SAMPLE_PAGES(index)
|
||||
@@ -1616,7 +1706,8 @@ dict_stats_analyze_index_level(
|
||||
DEBUG_PRINTF(" %s(table=%s, index=%s, level=" ULINTPF ")\n",
|
||||
__func__, index->table->name, index->name, level);
|
||||
|
||||
ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK));
|
||||
*total_recs = 0;
|
||||
*total_pages = 0;
|
||||
|
||||
n_uniq = dict_index_get_n_unique(index);
|
||||
|
||||
@@ -1649,9 +1740,7 @@ dict_stats_analyze_index_level(
|
||||
/* Position pcur on the leftmost record on the leftmost page
|
||||
on the desired level. */
|
||||
|
||||
if (btr_pcur_open_at_index_side(
|
||||
true, index, BTR_SEARCH_TREE_ALREADY_S_LATCHED,
|
||||
&pcur, true, level, mtr) != DB_SUCCESS
|
||||
if (btr_pcur_open_level(&pcur, level, mtr, index) != DB_SUCCESS
|
||||
|| !btr_pcur_move_to_next_on_page(&pcur)) {
|
||||
goto func_exit;
|
||||
}
|
||||
@@ -1661,21 +1750,10 @@ dict_stats_analyze_index_level(
|
||||
/* The page must not be empty, except when
|
||||
it is the root page (and the whole index is empty). */
|
||||
ut_ad(btr_pcur_is_on_user_rec(&pcur) || page_is_leaf(page));
|
||||
ut_ad(btr_pcur_get_rec(&pcur)
|
||||
== page_rec_get_next_const(page_get_infimum_rec(page)));
|
||||
|
||||
prev_rec = NULL;
|
||||
prev_rec_is_copied = false;
|
||||
|
||||
/* no records by default */
|
||||
*total_recs = 0;
|
||||
|
||||
*total_pages = 0;
|
||||
|
||||
if (page_has_prev(page) || btr_page_get_level(page) != level) {
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
|
||||
btr_pcur_get_rec(&pcur), page_is_comp(page))) {
|
||||
ut_ad(btr_pcur_is_on_user_rec(&pcur));
|
||||
@@ -1728,10 +1806,7 @@ dict_stats_analyze_index_level(
|
||||
|
||||
if (level == 0
|
||||
&& !srv_stats_include_delete_marked
|
||||
&& rec_get_deleted_flag(
|
||||
rec,
|
||||
page_is_comp(btr_pcur_get_page(&pcur)))) {
|
||||
|
||||
&& rec_get_deleted_flag(rec, page_rec_is_comp(rec))) {
|
||||
if (rec_is_last_on_page
|
||||
&& !prev_rec_is_copied
|
||||
&& prev_rec != NULL) {
|
||||
@@ -1811,7 +1886,7 @@ dict_stats_analyze_index_level(
|
||||
records on this level at some point we will jump from
|
||||
one page to the next and then rec and prev_rec will
|
||||
be on different pages and
|
||||
btr_pcur_move_to_next_user_rec() will release the
|
||||
btr_cur_move_to_next_user_rec() will release the
|
||||
latch on the page that prev_rec is on */
|
||||
prev_rec = rec_copy_prefix_to_buf(
|
||||
rec, index, n_uniq,
|
||||
@@ -1820,7 +1895,7 @@ dict_stats_analyze_index_level(
|
||||
|
||||
} else {
|
||||
/* still on the same page, the next call to
|
||||
btr_pcur_move_to_next_user_rec() will not jump
|
||||
btr_cur_move_to_next_user_rec() will not jump
|
||||
on the next page, we can simply assign pointers
|
||||
instead of copying the records like above */
|
||||
|
||||
@@ -1891,7 +1966,6 @@ dict_stats_analyze_index_level(
|
||||
}
|
||||
#endif /* UNIV_STATS_DEBUG */
|
||||
|
||||
btr_leaf_page_release(btr_pcur_get_block(&pcur), BTR_SEARCH_LEAF, mtr);
|
||||
func_exit:
|
||||
ut_free(prev_rec_buf);
|
||||
mem_heap_free(heap);
|
||||
@@ -2280,7 +2354,6 @@ dict_stats_analyze_index_for_n_prefix(
|
||||
n_prefix, n_diff_data->n_diff_on_level);
|
||||
#endif
|
||||
|
||||
ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK));
|
||||
ut_ad(n_diff_data->level);
|
||||
|
||||
/* Position pcur on the leftmost record on the leftmost page
|
||||
@@ -2289,9 +2362,7 @@ dict_stats_analyze_index_for_n_prefix(
|
||||
n_diff_data->n_diff_all_analyzed_pages = 0;
|
||||
n_diff_data->n_external_pages_sum = 0;
|
||||
|
||||
if (btr_pcur_open_at_index_side(true, index,
|
||||
BTR_SEARCH_TREE_ALREADY_S_LATCHED,
|
||||
&pcur, true, n_diff_data->level, mtr)
|
||||
if (btr_pcur_open_level(&pcur, n_diff_data->level, mtr, index)
|
||||
!= DB_SUCCESS
|
||||
|| !btr_pcur_move_to_next_on_page(&pcur)) {
|
||||
return;
|
||||
@@ -2680,6 +2751,7 @@ empty_index:
|
||||
mtr.commit();
|
||||
mtr.start();
|
||||
mtr_sx_lock_index(index, &mtr);
|
||||
ut_ad(mtr.get_savepoint() == 1);
|
||||
buf_block_t *root = btr_root_block_get(index, RW_S_LATCH,
|
||||
&mtr, &err);
|
||||
if (!root || root_level != btr_page_get_level(root->page.frame)
|
||||
@@ -2695,7 +2767,7 @@ empty_index:
|
||||
break;
|
||||
}
|
||||
|
||||
mtr.memo_release(root, MTR_MEMO_PAGE_S_FIX);
|
||||
mtr.rollback_to_savepoint(1);
|
||||
|
||||
/* check whether we should pick the current level;
|
||||
we pick level 1 even if it does not have enough
|
||||
@@ -2757,6 +2829,7 @@ empty_index:
|
||||
break;
|
||||
}
|
||||
|
||||
mtr.rollback_to_savepoint(1);
|
||||
dict_stats_analyze_index_level(index,
|
||||
level,
|
||||
n_diff_on_level,
|
||||
@@ -2764,7 +2837,7 @@ empty_index:
|
||||
&total_pages,
|
||||
n_diff_boundaries,
|
||||
&mtr);
|
||||
|
||||
mtr.rollback_to_savepoint(1);
|
||||
level_is_analyzed = true;
|
||||
|
||||
if (level == 1
|
||||
|
@@ -1831,7 +1831,6 @@ fil_crypt_rotate_page(
|
||||
} else {
|
||||
/* If block read failed mtr memo and log should be empty. */
|
||||
ut_ad(!mtr.has_modifications());
|
||||
ut_ad(!mtr.is_dirty());
|
||||
ut_ad(mtr.is_empty());
|
||||
mtr.commit();
|
||||
}
|
||||
|
@@ -3347,7 +3347,6 @@ fts_add_doc_by_id(
|
||||
is_id_cluster = (clust_index == fts_id_index);
|
||||
|
||||
mtr_start(&mtr);
|
||||
btr_pcur_init(&pcur);
|
||||
|
||||
/* Search based on Doc ID. Here, we'll need to consider the case
|
||||
when there is no primary index on Doc ID */
|
||||
@@ -3358,9 +3357,10 @@ fts_add_doc_by_id(
|
||||
|
||||
mach_write_to_8((byte*) &temp_doc_id, doc_id);
|
||||
dfield_set_data(dfield, &temp_doc_id, sizeof(temp_doc_id));
|
||||
pcur.btr_cur.page_cur.index = fts_id_index;
|
||||
|
||||
/* If we have a match, add the data to doc structure */
|
||||
if (btr_pcur_open_with_no_init(fts_id_index, tuple, PAGE_CUR_LE,
|
||||
if (btr_pcur_open_with_no_init(tuple, PAGE_CUR_LE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr)
|
||||
== DB_SUCCESS
|
||||
&& btr_pcur_get_low_match(&pcur) == 1) {
|
||||
@@ -3387,7 +3387,6 @@ fts_add_doc_by_id(
|
||||
dtuple_t* clust_ref;
|
||||
ulint n_fields;
|
||||
|
||||
btr_pcur_init(&clust_pcur);
|
||||
n_fields = dict_index_get_n_unique(clust_index);
|
||||
|
||||
clust_ref = dtuple_create(heap, n_fields);
|
||||
@@ -3395,8 +3394,9 @@ fts_add_doc_by_id(
|
||||
|
||||
row_build_row_ref_in_tuple(
|
||||
clust_ref, rec, fts_id_index, NULL);
|
||||
clust_pcur.btr_cur.page_cur.index = clust_index;
|
||||
|
||||
if (btr_pcur_open_with_no_init(clust_index, clust_ref,
|
||||
if (btr_pcur_open_with_no_init(clust_ref,
|
||||
PAGE_CUR_LE,
|
||||
BTR_SEARCH_LEAF,
|
||||
&clust_pcur, &mtr)
|
||||
@@ -3552,12 +3552,11 @@ fts_get_max_doc_id(
|
||||
ut_ad(innobase_strcasecmp(FTS_DOC_ID_COL_NAME, dfield->name) == 0);
|
||||
#endif
|
||||
|
||||
mtr_start(&mtr);
|
||||
mtr.start();
|
||||
|
||||
/* fetch the largest indexes value */
|
||||
if (btr_pcur_open_at_index_side(false, index, BTR_SEARCH_LEAF, &pcur,
|
||||
true, 0, &mtr) != DB_SUCCESS) {
|
||||
} else if (!page_is_empty(btr_pcur_get_page(&pcur))) {
|
||||
if (pcur.open_leaf(false, index, BTR_SEARCH_LEAF, &mtr) == DB_SUCCESS
|
||||
&& !page_is_empty(btr_pcur_get_page(&pcur))) {
|
||||
const rec_t* rec = NULL;
|
||||
|
||||
do {
|
||||
@@ -3576,7 +3575,7 @@ fts_get_max_doc_id(
|
||||
}
|
||||
|
||||
func_exit:
|
||||
mtr_commit(&mtr);
|
||||
mtr.commit();
|
||||
return(doc_id);
|
||||
}
|
||||
|
||||
|
@@ -70,7 +70,7 @@ rtr_page_split_initialize_nodes(
|
||||
|
||||
block = btr_cur_get_block(cursor);
|
||||
page = buf_block_get_frame(block);
|
||||
n_uniq = dict_index_get_n_unique_in_tree(cursor->index);
|
||||
n_uniq = dict_index_get_n_unique_in_tree(cursor->index());
|
||||
|
||||
n_recs = ulint(page_get_n_recs(page)) + 1;
|
||||
|
||||
@@ -88,8 +88,8 @@ rtr_page_split_initialize_nodes(
|
||||
|
||||
rec = page_rec_get_next(page_get_infimum_rec(page));
|
||||
const ulint n_core = page_is_leaf(page)
|
||||
? cursor->index->n_core_fields : 0;
|
||||
*offsets = rec_get_offsets(rec, cursor->index, *offsets, n_core,
|
||||
? cursor->index()->n_core_fields : 0;
|
||||
*offsets = rec_get_offsets(rec, cursor->index(), *offsets, n_core,
|
||||
n_uniq, &heap);
|
||||
|
||||
source_cur = rec_get_nth_field(rec, *offsets, 0, &len);
|
||||
@@ -101,7 +101,7 @@ rtr_page_split_initialize_nodes(
|
||||
memcpy(cur->coords, source_cur, DATA_MBR_LEN);
|
||||
|
||||
rec = page_rec_get_next(rec);
|
||||
*offsets = rec_get_offsets(rec, cursor->index, *offsets,
|
||||
*offsets = rec_get_offsets(rec, cursor->index(), *offsets,
|
||||
n_core, n_uniq, &heap);
|
||||
source_cur = rec_get_nth_field(rec, *offsets, 0, &len);
|
||||
}
|
||||
@@ -111,9 +111,9 @@ rtr_page_split_initialize_nodes(
|
||||
dtuple_get_nth_field(tuple, 0)));
|
||||
cur->coords = reserve_coords(buf_pos, SPDIMS);
|
||||
rec = (byte*) mem_heap_alloc(
|
||||
heap, rec_get_converted_size(cursor->index, tuple, 0));
|
||||
heap, rec_get_converted_size(cursor->index(), tuple, 0));
|
||||
|
||||
rec = rec_convert_dtuple_to_rec(rec, cursor->index, tuple, 0);
|
||||
rec = rec_convert_dtuple_to_rec(rec, cursor->index(), tuple, 0);
|
||||
cur->key = rec;
|
||||
|
||||
memcpy(cur->coords, source_cur, DATA_MBR_LEN);
|
||||
@@ -200,7 +200,7 @@ rtr_update_mbr_field(
|
||||
rec_t* new_rec, /*!< in: rec to use */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
dict_index_t* index = cursor->index;
|
||||
dict_index_t* index = cursor->index();
|
||||
mem_heap_t* heap;
|
||||
page_t* page;
|
||||
rec_t* rec;
|
||||
@@ -245,6 +245,7 @@ rtr_update_mbr_field(
|
||||
/* We need to remember the child page no of cursor2, since page could be
|
||||
reorganized or insert a new rec before it. */
|
||||
if (cursor2) {
|
||||
ut_ad(cursor2->index() == index);
|
||||
rec_t* del_rec = btr_cur_get_rec(cursor2);
|
||||
offsets2 = rec_get_offsets(btr_cur_get_rec(cursor2),
|
||||
index, NULL, 0,
|
||||
@@ -268,7 +269,7 @@ rtr_update_mbr_field(
|
||||
if (!btr_cur_update_alloc_zip(
|
||||
page_zip,
|
||||
btr_cur_get_page_cur(cursor),
|
||||
index, offsets,
|
||||
offsets,
|
||||
rec_offs_size(offsets),
|
||||
false, mtr)) {
|
||||
|
||||
@@ -321,7 +322,7 @@ rtr_update_mbr_field(
|
||||
offsets2));
|
||||
|
||||
page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
|
||||
index, offsets2, mtr);
|
||||
offsets2, mtr);
|
||||
}
|
||||
} else if (page_get_n_recs(page) == 1) {
|
||||
/* When there's only one rec in the page, we do insert/delete to
|
||||
@@ -352,9 +353,10 @@ rtr_update_mbr_field(
|
||||
ut_ad(old_rec != insert_rec);
|
||||
|
||||
page_cur_position(old_rec, block, &page_cur);
|
||||
page_cur.index = index;
|
||||
offsets2 = rec_get_offsets(old_rec, index, NULL, n_core,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
page_cur_delete_rec(&page_cur, index, offsets2, mtr);
|
||||
page_cur_delete_rec(&page_cur, offsets2, mtr);
|
||||
|
||||
} else {
|
||||
update_mbr:
|
||||
@@ -366,8 +368,7 @@ update_mbr:
|
||||
|
||||
/* Delete the rec which cursor point to. */
|
||||
next_rec = page_rec_get_next(rec);
|
||||
page_cur_delete_rec(btr_cur_get_page_cur(cursor),
|
||||
index, offsets, mtr);
|
||||
page_cur_delete_rec(&cursor->page_cur, offsets, mtr);
|
||||
if (!ins_suc) {
|
||||
ut_ad(rec_info & REC_INFO_MIN_REC_FLAG);
|
||||
|
||||
@@ -400,13 +401,12 @@ update_mbr:
|
||||
== btr_node_ptr_get_child_page_no(cur2_rec,
|
||||
offsets2));
|
||||
page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
|
||||
index, offsets2, mtr);
|
||||
offsets2, mtr);
|
||||
cursor2 = NULL;
|
||||
}
|
||||
|
||||
/* Insert the new rec. */
|
||||
if (page_cur_search_with_match(block, index, node_ptr,
|
||||
PAGE_CUR_LE,
|
||||
if (page_cur_search_with_match(node_ptr, PAGE_CUR_LE,
|
||||
&up_match, &low_match,
|
||||
btr_cur_get_page_cur(cursor),
|
||||
NULL)) {
|
||||
@@ -424,7 +424,7 @@ update_mbr:
|
||||
} else if (ins_suc) {
|
||||
ut_ad(err == DB_FAIL);
|
||||
err = btr_page_reorganize(btr_cur_get_page_cur(cursor),
|
||||
index, mtr);
|
||||
mtr);
|
||||
if (err == DB_SUCCESS) {
|
||||
err = btr_cur_optimistic_insert(
|
||||
flags, cursor, &insert_offsets, &heap,
|
||||
@@ -505,7 +505,7 @@ update_mbr:
|
||||
ut_ad(cur2_pno == del_page_no && cur2_rec != insert_rec);
|
||||
|
||||
page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
|
||||
index, offsets2, mtr);
|
||||
offsets2, mtr);
|
||||
}
|
||||
|
||||
if (!ins_suc) {
|
||||
@@ -556,7 +556,6 @@ rtr_adjust_upper_level(
|
||||
{
|
||||
ulint page_no;
|
||||
ulint new_page_no;
|
||||
dict_index_t* index = sea_cur->index;
|
||||
btr_cur_t cursor;
|
||||
rec_offs* offsets;
|
||||
mem_heap_t* heap;
|
||||
@@ -570,9 +569,10 @@ rtr_adjust_upper_level(
|
||||
|
||||
/* Create a memory heap where the data tuple is stored */
|
||||
heap = mem_heap_create(1024);
|
||||
cursor.init();
|
||||
|
||||
cursor.thr = sea_cur->thr;
|
||||
cursor.page_cur.index = sea_cur->index();
|
||||
cursor.page_cur.block = block;
|
||||
|
||||
/* Get the level of the split pages */
|
||||
level = btr_page_get_level(buf_block_get_frame(block));
|
||||
@@ -584,8 +584,7 @@ rtr_adjust_upper_level(
|
||||
|
||||
/* Set new mbr for the old page on the upper level. */
|
||||
/* Look up the index for the node pointer to page */
|
||||
offsets = rtr_page_get_father_block(
|
||||
NULL, heap, index, block, mtr, sea_cur, &cursor);
|
||||
offsets = rtr_page_get_father_block(NULL, heap, mtr, sea_cur, &cursor);
|
||||
|
||||
page_cursor = btr_cur_get_page_cur(&cursor);
|
||||
|
||||
@@ -607,10 +606,9 @@ rtr_adjust_upper_level(
|
||||
page_get_infimum_rec(new_block->page.frame))) {
|
||||
/* Insert the node for the new page. */
|
||||
node_ptr_upper = rtr_index_build_node_ptr(
|
||||
index, new_mbr, first, new_page_no, heap);
|
||||
sea_cur->index(), new_mbr, first, new_page_no, heap);
|
||||
ulint up_match = 0, low_match = 0;
|
||||
err = page_cur_search_with_match(btr_cur_get_block(&cursor),
|
||||
index, node_ptr_upper,
|
||||
err = page_cur_search_with_match(node_ptr_upper,
|
||||
PAGE_CUR_LE,
|
||||
&up_match, &low_match,
|
||||
btr_cur_get_page_cur(&cursor),
|
||||
@@ -660,7 +658,7 @@ rtr_adjust_upper_level(
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
||||
ut_ad(block->zip_size() == index->table->space->zip_size());
|
||||
ut_ad(block->zip_size() == sea_cur->index()->table->space->zip_size());
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
return err;
|
||||
@@ -670,7 +668,7 @@ rtr_adjust_upper_level(
|
||||
|
||||
if (next_page_no == FIL_NULL) {
|
||||
} else if (buf_block_t* next_block =
|
||||
btr_block_get(*index, next_page_no, RW_X_LATCH,
|
||||
btr_block_get(*sea_cur->index(), next_page_no, RW_X_LATCH,
|
||||
false, mtr, &err)) {
|
||||
if (UNIV_UNLIKELY(memcmp_aligned<4>(next_block->page.frame
|
||||
+ FIL_PAGE_PREV,
|
||||
@@ -740,6 +738,7 @@ rtr_split_page_move_rec_list(
|
||||
|
||||
page_cur_set_before_first(block, &page_cursor);
|
||||
page_cur_set_before_first(new_block, &new_page_cursor);
|
||||
page_cursor.index = new_page_cursor.index = index;
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
new_page = buf_block_get_frame(new_block);
|
||||
@@ -774,7 +773,7 @@ rtr_split_page_move_rec_list(
|
||||
|
||||
rec = page_cur_insert_rec_low(
|
||||
&new_page_cursor,
|
||||
index, cur_split_node->key, offsets, mtr);
|
||||
cur_split_node->key, offsets, mtr);
|
||||
|
||||
if (UNIV_UNLIKELY
|
||||
(!rec
|
||||
@@ -841,8 +840,7 @@ rtr_split_page_move_rec_list(
|
||||
page_cur_get_rec(&page_cursor), index,
|
||||
offsets, n_core, ULINT_UNDEFINED,
|
||||
&heap);
|
||||
page_cur_delete_rec(&page_cursor,
|
||||
index, offsets, mtr);
|
||||
page_cur_delete_rec(&page_cursor, offsets, mtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -877,7 +875,6 @@ rtr_page_split_and_insert(
|
||||
buf_block_t* new_block;
|
||||
page_zip_des_t* page_zip;
|
||||
page_zip_des_t* new_page_zip;
|
||||
buf_block_t* insert_block;
|
||||
page_cur_t* page_cursor;
|
||||
rec_t* rec = 0;
|
||||
ulint n_recs;
|
||||
@@ -906,12 +903,10 @@ func_start:
|
||||
mem_heap_empty(*heap);
|
||||
*offsets = NULL;
|
||||
|
||||
ut_ad(mtr->memo_contains_flagged(&cursor->index->lock, MTR_MEMO_X_LOCK
|
||||
| MTR_MEMO_SX_LOCK));
|
||||
ut_ad(!dict_index_is_online_ddl(cursor->index)
|
||||
|| (flags & BTR_CREATE_FLAG)
|
||||
|| dict_index_is_clust(cursor->index));
|
||||
ut_ad(cursor->index->lock.have_u_or_x());
|
||||
ut_ad(mtr->memo_contains_flagged(&cursor->index()->lock,
|
||||
MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
|
||||
ut_ad(!dict_index_is_online_ddl(cursor->index()));
|
||||
ut_ad(cursor->index()->lock.have_u_or_x());
|
||||
|
||||
block = btr_cur_get_block(cursor);
|
||||
page = buf_block_get_frame(block);
|
||||
@@ -954,7 +949,7 @@ corrupted:
|
||||
}
|
||||
#endif
|
||||
|
||||
insert_size = rec_get_converted_size(cursor->index, tuple, n_ext);
|
||||
insert_size = rec_get_converted_size(cursor->index(), tuple, n_ext);
|
||||
total_data = page_get_data_size(page) + insert_size;
|
||||
first_rec_group = split_rtree_node(rtr_split_node_array,
|
||||
static_cast<int>(n_recs),
|
||||
@@ -965,7 +960,7 @@ corrupted:
|
||||
|
||||
/* Allocate a new page to the index */
|
||||
const uint16_t page_level = btr_page_get_level(page);
|
||||
new_block = btr_page_alloc(cursor->index, page_id.page_no() + 1,
|
||||
new_block = btr_page_alloc(cursor->index(), page_id.page_no() + 1,
|
||||
FSP_UP, page_level, mtr, mtr, err);
|
||||
if (UNIV_UNLIKELY(!new_block)) {
|
||||
return nullptr;
|
||||
@@ -977,7 +972,7 @@ corrupted:
|
||||
to contain FIL_NULL in FIL_PAGE_PREV at this stage. */
|
||||
memset_aligned<4>(new_block->page.frame + FIL_PAGE_PREV, 0, 4);
|
||||
}
|
||||
btr_page_create(new_block, new_page_zip, cursor->index,
|
||||
btr_page_create(new_block, new_page_zip, cursor->index(),
|
||||
page_level, mtr);
|
||||
|
||||
new_page = buf_block_get_frame(new_block);
|
||||
@@ -985,7 +980,7 @@ corrupted:
|
||||
|
||||
/* Set new ssn to the new page and page. */
|
||||
page_set_ssn_id(new_block, new_page_zip, current_ssn, mtr);
|
||||
next_ssn = rtr_get_new_ssn_id(cursor->index);
|
||||
next_ssn = rtr_get_new_ssn_id(cursor->index());
|
||||
|
||||
page_set_ssn_id(block, page_zip, next_ssn, mtr);
|
||||
|
||||
@@ -998,7 +993,7 @@ corrupted:
|
||||
|| (*err = rtr_split_page_move_rec_list(rtr_split_node_array,
|
||||
first_rec_group,
|
||||
new_block, block,
|
||||
first_rec, cursor->index,
|
||||
first_rec, cursor->index(),
|
||||
*heap, mtr))) {
|
||||
if (*err != DB_FAIL) {
|
||||
return nullptr;
|
||||
@@ -1021,7 +1016,7 @@ corrupted:
|
||||
ut_a(new_page_zip);
|
||||
|
||||
page_zip_copy_recs(new_block,
|
||||
page_zip, page, cursor->index, mtr);
|
||||
page_zip, page, cursor->index(), mtr);
|
||||
|
||||
page_cursor = btr_cur_get_page_cur(cursor);
|
||||
|
||||
@@ -1056,7 +1051,7 @@ corrupted:
|
||||
lock_rtr_move_rec_list(new_block, block, rec_move, moved);
|
||||
|
||||
const ulint n_core = page_level
|
||||
? 0 : cursor->index->n_core_fields;
|
||||
? 0 : cursor->index()->n_core_fields;
|
||||
|
||||
/* Delete recs in first group from the new page. */
|
||||
for (cur_split_node = rtr_split_node_array;
|
||||
@@ -1076,11 +1071,11 @@ corrupted:
|
||||
|
||||
*offsets = rec_get_offsets(
|
||||
page_cur_get_rec(page_cursor),
|
||||
cursor->index, *offsets, n_core,
|
||||
cursor->index(), *offsets, n_core,
|
||||
ULINT_UNDEFINED, heap);
|
||||
|
||||
page_cur_delete_rec(page_cursor,
|
||||
cursor->index, *offsets, mtr);
|
||||
*offsets, mtr);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
@@ -1093,32 +1088,30 @@ corrupted:
|
||||
block, page_cursor);
|
||||
*offsets = rec_get_offsets(
|
||||
page_cur_get_rec(page_cursor),
|
||||
cursor->index, *offsets, n_core,
|
||||
page_cursor->index, *offsets, n_core,
|
||||
ULINT_UNDEFINED, heap);
|
||||
page_cur_delete_rec(page_cursor,
|
||||
cursor->index, *offsets, mtr);
|
||||
page_cur_delete_rec(page_cursor, *offsets,
|
||||
mtr);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNIV_GIS_DEBUG
|
||||
ut_ad(page_validate(new_page, cursor->index));
|
||||
ut_ad(page_validate(page, cursor->index));
|
||||
ut_ad(page_validate(new_page, cursor->index()));
|
||||
ut_ad(page_validate(page, cursor->index()));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Insert the new rec to the proper page. */
|
||||
cur_split_node = end_split_node - 1;
|
||||
if (cur_split_node->n_node != first_rec_group) {
|
||||
insert_block = new_block;
|
||||
} else {
|
||||
insert_block = block;
|
||||
}
|
||||
|
||||
/* Reposition the cursor for insert and try insertion */
|
||||
page_cursor = btr_cur_get_page_cur(cursor);
|
||||
page_cursor->block = cur_split_node->n_node != first_rec_group
|
||||
? new_block : block;
|
||||
|
||||
ulint up_match = 0, low_match = 0;
|
||||
|
||||
if (page_cur_search_with_match(insert_block, cursor->index, tuple,
|
||||
if (page_cur_search_with_match(tuple,
|
||||
PAGE_CUR_LE, &up_match, &low_match,
|
||||
page_cursor, nullptr)) {
|
||||
goto corrupted;
|
||||
@@ -1133,7 +1126,7 @@ corrupted:
|
||||
goto after_insert; }
|
||||
);
|
||||
|
||||
rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index,
|
||||
rec = page_cur_tuple_insert(page_cursor, tuple,
|
||||
offsets, heap, n_ext, mtr);
|
||||
|
||||
/* If insert did not fit, try page reorganization.
|
||||
@@ -1141,14 +1134,13 @@ corrupted:
|
||||
attempted this already. */
|
||||
if (rec == NULL) {
|
||||
if (!is_page_cur_get_page_zip(page_cursor)
|
||||
&& btr_page_reorganize(page_cursor, cursor->index, mtr)) {
|
||||
&& btr_page_reorganize(page_cursor, mtr)) {
|
||||
rec = page_cur_tuple_insert(page_cursor, tuple,
|
||||
cursor->index, offsets,
|
||||
offsets,
|
||||
heap, n_ext, mtr);
|
||||
|
||||
}
|
||||
/* If insert fail, we will try to split the insert_block
|
||||
again. */
|
||||
/* If insert fail, we will try to split the block again. */
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
@@ -1156,8 +1148,8 @@ after_insert:
|
||||
#endif
|
||||
/* Calculate the mbr on the upper half-page, and the mbr on
|
||||
original page. */
|
||||
rtr_page_cal_mbr(cursor->index, block, &mbr, *heap);
|
||||
rtr_page_cal_mbr(cursor->index, new_block, &new_mbr, *heap);
|
||||
rtr_page_cal_mbr(cursor->index(), block, &mbr, *heap);
|
||||
rtr_page_cal_mbr(cursor->index(), new_block, &new_mbr, *heap);
|
||||
prdt.data = &mbr;
|
||||
new_prdt.data = &new_mbr;
|
||||
|
||||
@@ -1175,7 +1167,8 @@ after_insert:
|
||||
/* Save the new ssn to the root page, since we need to reinit
|
||||
the first ssn value from it after restart server. */
|
||||
|
||||
root_block = btr_root_block_get(cursor->index, RW_SX_LATCH, mtr, err);
|
||||
root_block = btr_root_block_get(cursor->index(), RW_SX_LATCH,
|
||||
mtr, err);
|
||||
if (UNIV_UNLIKELY(!root_block)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1187,8 +1180,8 @@ after_insert:
|
||||
again. */
|
||||
if (!rec) {
|
||||
/* We play safe and reset the free bits for new_page */
|
||||
if (!dict_index_is_clust(cursor->index)
|
||||
&& !cursor->index->table->is_temporary()) {
|
||||
if (!dict_index_is_clust(cursor->index())
|
||||
&& !cursor->index()->table->is_temporary()) {
|
||||
ibuf_reset_free_bits(new_block);
|
||||
ibuf_reset_free_bits(block);
|
||||
}
|
||||
@@ -1205,16 +1198,16 @@ after_insert:
|
||||
if (UNIV_UNLIKELY(!i_rec)) {
|
||||
goto corrupted;
|
||||
}
|
||||
btr_cur_position(cursor->index, i_rec, block, cursor);
|
||||
btr_cur_position(cursor->index(), i_rec, block, cursor);
|
||||
|
||||
goto func_start;
|
||||
}
|
||||
|
||||
#ifdef UNIV_GIS_DEBUG
|
||||
ut_ad(page_validate(buf_block_get_frame(block), cursor->index));
|
||||
ut_ad(page_validate(buf_block_get_frame(new_block), cursor->index));
|
||||
ut_ad(page_validate(buf_block_get_frame(block), cursor->index()));
|
||||
ut_ad(page_validate(buf_block_get_frame(new_block), cursor->index()));
|
||||
|
||||
ut_ad(!rec || rec_offs_validate(rec, cursor->index, *offsets));
|
||||
ut_ad(!rec || rec_offs_validate(rec, cursor->index(), *offsets));
|
||||
#endif
|
||||
MONITOR_INC(MONITOR_INDEX_SPLIT);
|
||||
|
||||
@@ -1234,14 +1227,13 @@ rtr_ins_enlarge_mbr(
|
||||
rtr_mbr_t new_mbr;
|
||||
buf_block_t* block;
|
||||
mem_heap_t* heap;
|
||||
dict_index_t* index = btr_cur->index;
|
||||
page_cur_t* page_cursor;
|
||||
rec_offs* offsets;
|
||||
node_visit_t* node_visit;
|
||||
btr_cur_t cursor;
|
||||
page_t* page;
|
||||
|
||||
ut_ad(dict_index_is_spatial(index));
|
||||
ut_ad(btr_cur->index()->is_spatial());
|
||||
|
||||
/* If no rtr_info or rtree is one level tree, return. */
|
||||
if (!btr_cur->rtr_info || btr_cur->tree_height == 1) {
|
||||
@@ -1269,20 +1261,20 @@ rtr_ins_enlarge_mbr(
|
||||
}
|
||||
|
||||
/* Calculate the mbr of the child page. */
|
||||
rtr_page_cal_mbr(index, block, &new_mbr, heap);
|
||||
rtr_page_cal_mbr(page_cursor->index, block, &new_mbr, heap);
|
||||
|
||||
/* Get father block. */
|
||||
cursor.init();
|
||||
cursor.page_cur.index = page_cursor->index;
|
||||
cursor.page_cur.block = block;
|
||||
offsets = rtr_page_get_father_block(
|
||||
NULL, heap, index, block, mtr, btr_cur, &cursor);
|
||||
NULL, heap, mtr, btr_cur, &cursor);
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
/* Update the mbr field of the rec. */
|
||||
rtr_update_mbr_field(&cursor, offsets, NULL, page,
|
||||
&new_mbr, NULL, mtr);
|
||||
page_cursor = btr_cur_get_page_cur(&cursor);
|
||||
block = page_cur_get_block(page_cursor);
|
||||
block = btr_cur_get_block(&cursor);
|
||||
}
|
||||
|
||||
mem_heap_free(heap);
|
||||
@@ -1338,6 +1330,7 @@ rtr_page_copy_rec_list_end_no_locks(
|
||||
return DB_CORRUPTION;
|
||||
}
|
||||
page_cur_position(cur_rec, new_block, &page_cur);
|
||||
page_cur.index = index;
|
||||
|
||||
/* Copy records from the original page to the new page */
|
||||
while (!page_cur_is_after_last(&cur1)) {
|
||||
@@ -1399,7 +1392,7 @@ move_to_prev:
|
||||
offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
ins_rec = page_cur_insert_rec_low(&page_cur, index,
|
||||
ins_rec = page_cur_insert_rec_low(&page_cur,
|
||||
cur1_rec, offsets1, mtr);
|
||||
if (UNIV_UNLIKELY(!ins_rec || moved >= max_move)) {
|
||||
return DB_CORRUPTION;
|
||||
@@ -1461,6 +1454,7 @@ rtr_page_copy_rec_list_start_no_locks(
|
||||
return DB_CORRUPTION;
|
||||
}
|
||||
page_cur_position(cur_rec, new_block, &page_cur);
|
||||
page_cur.index = index;
|
||||
|
||||
while (page_cur_get_rec(&cur1) != rec) {
|
||||
rec_t* cur1_rec = page_cur_get_rec(&cur1);
|
||||
@@ -1522,7 +1516,7 @@ move_to_prev:
|
||||
offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
ins_rec = page_cur_insert_rec_low(&page_cur, index,
|
||||
ins_rec = page_cur_insert_rec_low(&page_cur,
|
||||
cur1_rec, offsets1, mtr);
|
||||
if (UNIV_UNLIKELY(!ins_rec || moved >= max_move)) {
|
||||
return DB_CORRUPTION;
|
||||
@@ -1560,7 +1554,7 @@ rtr_merge_mbr_changed(
|
||||
ulint len;
|
||||
bool changed = false;
|
||||
|
||||
ut_ad(dict_index_is_spatial(cursor->index));
|
||||
ut_ad(cursor->index()->is_spatial());
|
||||
|
||||
rec = btr_cur_get_rec(cursor);
|
||||
|
||||
@@ -1640,11 +1634,11 @@ rtr_check_same_block(
|
||||
btr_cur_t* cursor, /*!< in/out: position at the parent entry
|
||||
pointing to the child if successful */
|
||||
buf_block_t* parentb,/*!< in: parent page to check */
|
||||
buf_block_t* childb, /*!< in: child Page */
|
||||
mem_heap_t* heap) /*!< in: memory heap */
|
||||
|
||||
{
|
||||
ulint page_no = childb->page.id().page_no();
|
||||
const uint32_t page_no =
|
||||
btr_cur_get_block(cursor)->page.id().page_no();
|
||||
rec_offs* offsets;
|
||||
rec_t* rec = page_get_infimum_rec(parentb->page.frame);
|
||||
|
||||
|
@@ -95,14 +95,13 @@ rtr_pcur_getnext_from_path(
|
||||
/*!< in: index tree locked */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
dict_index_t* index = btr_cur->index;
|
||||
dict_index_t* index = btr_cur->index();
|
||||
bool found = false;
|
||||
page_cur_t* page_cursor;
|
||||
ulint level = 0;
|
||||
node_visit_t next_rec;
|
||||
rtr_info_t* rtr_info = btr_cur->rtr_info;
|
||||
node_seq_t page_ssn;
|
||||
ulint my_latch_mode;
|
||||
ulint skip_parent = false;
|
||||
bool new_split = false;
|
||||
bool for_delete = false;
|
||||
@@ -115,7 +114,7 @@ rtr_pcur_getnext_from_path(
|
||||
|
||||
ut_ad(dtuple_get_n_fields_cmp(tuple));
|
||||
|
||||
my_latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
|
||||
const auto my_latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
|
||||
|
||||
for_delete = latch_mode & BTR_RTREE_DELETE_MARK;
|
||||
for_undo_ins = latch_mode & BTR_RTREE_UNDO_INS;
|
||||
@@ -299,6 +298,7 @@ rtr_pcur_getnext_from_path(
|
||||
|
||||
page_cursor = btr_cur_get_page_cur(btr_cur);
|
||||
page_cursor->rec = NULL;
|
||||
page_cursor->block = block;
|
||||
|
||||
if (mode == PAGE_CUR_RTREE_LOCATE) {
|
||||
if (target_level == 0 && level == 0) {
|
||||
@@ -307,7 +307,7 @@ rtr_pcur_getnext_from_path(
|
||||
found = false;
|
||||
|
||||
if (!page_cur_search_with_match(
|
||||
block, index, tuple, PAGE_CUR_LE,
|
||||
tuple, PAGE_CUR_LE,
|
||||
&up_match, &low_match,
|
||||
btr_cur_get_page_cur(btr_cur), nullptr)
|
||||
&& low_match
|
||||
@@ -351,17 +351,12 @@ rtr_pcur_getnext_from_path(
|
||||
BTR_PCUR_IS_POSITIONED;
|
||||
r_cursor->latch_mode = my_latch_mode;
|
||||
btr_pcur_store_position(r_cursor, mtr);
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint num_stored =
|
||||
ut_d(ulint num_stored =)
|
||||
rtr_store_parent_path(
|
||||
block, btr_cur,
|
||||
rw_latch, level, mtr);
|
||||
ut_ad(num_stored > 0);
|
||||
#else
|
||||
rtr_store_parent_path(
|
||||
block, btr_cur, rw_latch,
|
||||
btr_latch_mode(rw_latch),
|
||||
level, mtr);
|
||||
#endif /* UNIV_DEBUG */
|
||||
ut_ad(num_stored > 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -443,11 +438,11 @@ rtr_pcur_getnext_from_path(
|
||||
|
||||
const rec_t* rec = btr_cur_get_rec(btr_cur);
|
||||
|
||||
if (page_rec_is_infimum(rec) || page_rec_is_supremum(rec)) {
|
||||
mtr_commit(mtr);
|
||||
mtr_start(mtr);
|
||||
if (!page_rec_is_user_rec(rec)) {
|
||||
mtr->commit();
|
||||
mtr->start();
|
||||
} else if (!index_locked) {
|
||||
mtr_memo_release(mtr, &index->lock, MTR_MEMO_X_LOCK);
|
||||
mtr->release(index->lock);
|
||||
}
|
||||
|
||||
return(found);
|
||||
@@ -521,7 +516,7 @@ bool
|
||||
rtr_pcur_open(
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const dtuple_t* tuple, /*!< in: tuple on which search done */
|
||||
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
@@ -539,6 +534,7 @@ rtr_pcur_open(
|
||||
/* Search with the tree cursor */
|
||||
|
||||
btr_cur_t* btr_cursor = btr_pcur_get_btr_cur(cursor);
|
||||
btr_cursor->page_cur.index = index;
|
||||
|
||||
btr_cursor->rtr_info = rtr_create_rtr_info(false, false,
|
||||
btr_cursor, index);
|
||||
@@ -554,7 +550,7 @@ rtr_pcur_open(
|
||||
mtr->lock_upgrade(index->lock);
|
||||
}
|
||||
|
||||
if (btr_cur_search_to_nth_level(index, 0, tuple, PAGE_CUR_RTREE_LOCATE,
|
||||
if (btr_cur_search_to_nth_level(0, tuple, PAGE_CUR_RTREE_LOCATE,
|
||||
latch_mode,
|
||||
btr_cursor, mtr) != DB_SUCCESS) {
|
||||
return true;
|
||||
@@ -606,24 +602,16 @@ rtr_pcur_open(
|
||||
}
|
||||
|
||||
/* Get the rtree page father.
|
||||
@param[in] index rtree index
|
||||
@param[in] block child page in the index
|
||||
@param[in,out] mtr mtr
|
||||
@param[in] sea_cur search cursor, contains information
|
||||
about parent nodes in search
|
||||
@param[out] cursor cursor on node pointer record,
|
||||
its page x-latched
|
||||
@return whether the cursor was successfully positioned */
|
||||
bool
|
||||
rtr_page_get_father(
|
||||
dict_index_t* index,
|
||||
buf_block_t* block,
|
||||
mtr_t* mtr,
|
||||
btr_cur_t* sea_cur,
|
||||
btr_cur_t* cursor)
|
||||
bool rtr_page_get_father(mtr_t *mtr, btr_cur_t *sea_cur, btr_cur_t *cursor)
|
||||
{
|
||||
mem_heap_t *heap = mem_heap_create(100);
|
||||
rec_offs *offsets= rtr_page_get_father_block(nullptr, heap, index, block,
|
||||
rec_offs *offsets= rtr_page_get_father_block(nullptr, heap,
|
||||
mtr, sea_cur, cursor);
|
||||
mem_heap_free(heap);
|
||||
return offsets != nullptr;
|
||||
@@ -634,7 +622,6 @@ MY_ATTRIBUTE((warn_unused_result))
|
||||
Returns the upper level node pointer to a R-Tree page. It is assumed
|
||||
that mtr holds an x-latch on the tree. */
|
||||
static const rec_t* rtr_get_father_node(
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint level, /*!< in: the tree level of search */
|
||||
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in
|
||||
tuple must be set so that it cannot get
|
||||
@@ -647,6 +634,7 @@ static const rec_t* rtr_get_father_node(
|
||||
{
|
||||
const rec_t* rec = nullptr;
|
||||
auto had_rtr = btr_cur->rtr_info;
|
||||
dict_index_t* const index = btr_cur->index();
|
||||
|
||||
/* Try to optimally locate the parent node. Level should always
|
||||
less than sea_cur->tree_height unless the root is splitting */
|
||||
@@ -680,7 +668,7 @@ static const rec_t* rtr_get_father_node(
|
||||
|
||||
btr_cur->rtr_info = rtr_create_rtr_info(false, false, btr_cur, index);
|
||||
|
||||
if (btr_cur_search_to_nth_level(index, level, tuple,
|
||||
if (btr_cur_search_to_nth_level(level, tuple,
|
||||
PAGE_CUR_RTREE_LOCATE,
|
||||
BTR_CONT_MODIFY_TREE, btr_cur, mtr)
|
||||
!= DB_SUCCESS) {
|
||||
@@ -764,7 +752,7 @@ rtr_page_get_father_node_ptr(
|
||||
sea_cur = NULL;
|
||||
}
|
||||
|
||||
const rec_t* node_ptr = rtr_get_father_node(index, level + 1, tuple,
|
||||
const rec_t* node_ptr = rtr_get_father_node(level + 1, tuple,
|
||||
sea_cur, cursor,
|
||||
page_no, mtr);
|
||||
if (!node_ptr) {
|
||||
@@ -792,23 +780,18 @@ rtr_page_get_father_block(
|
||||
/*======================*/
|
||||
rec_offs* offsets,/*!< in: work area for the return value */
|
||||
mem_heap_t* heap, /*!< in: memory heap to use */
|
||||
dict_index_t* index, /*!< in: b-tree index */
|
||||
buf_block_t* block, /*!< in: child page in the index */
|
||||
mtr_t* mtr, /*!< in: mtr */
|
||||
btr_cur_t* sea_cur,/*!< in: search cursor, contains information
|
||||
about parent nodes in search */
|
||||
btr_cur_t* cursor) /*!< out: cursor on node pointer record,
|
||||
its page x-latched */
|
||||
{
|
||||
rec_t* rec = page_rec_get_next(
|
||||
page_get_infimum_rec(buf_block_get_frame(block)));
|
||||
if (!rec) {
|
||||
rec_t *rec=
|
||||
page_rec_get_next(page_get_infimum_rec(cursor->block()->page.frame));
|
||||
if (!rec)
|
||||
return nullptr;
|
||||
}
|
||||
btr_cur_position(index, rec, block, cursor);
|
||||
|
||||
return(rtr_page_get_father_node_ptr(offsets, heap, sea_cur,
|
||||
cursor, mtr));
|
||||
cursor->page_cur.rec= rec;
|
||||
return rtr_page_get_father_node_ptr(offsets, heap, sea_cur, cursor, mtr);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
@@ -826,7 +809,7 @@ rtr_create_rtr_info(
|
||||
{
|
||||
rtr_info_t* rtr_info;
|
||||
|
||||
index = index ? index : cursor->index;
|
||||
index = index ? index : cursor->index();
|
||||
ut_ad(index);
|
||||
|
||||
rtr_info = static_cast<rtr_info_t*>(ut_zalloc_nokey(sizeof(*rtr_info)));
|
||||
@@ -1163,6 +1146,7 @@ rtr_cur_restore_position(
|
||||
ut_ad(mtr->is_active());
|
||||
|
||||
index = btr_cur_get_index(btr_cur);
|
||||
ut_ad(r_cursor->index() == btr_cur->index());
|
||||
|
||||
if (r_cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
|
||||
|| r_cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
|
||||
@@ -1222,7 +1206,6 @@ rtr_cur_restore_position(
|
||||
|
||||
/* Page has changed, for R-Tree, the page cannot be shrunk away,
|
||||
so we search the page and its right siblings */
|
||||
buf_block_t* block;
|
||||
node_seq_t page_ssn;
|
||||
const page_t* page;
|
||||
page_cur_t* page_cursor;
|
||||
@@ -1242,21 +1225,21 @@ rtr_cur_restore_position(
|
||||
search_again:
|
||||
ulint up_match = 0, low_match = 0;
|
||||
|
||||
block = buf_page_get_gen(
|
||||
page_cursor->block = buf_page_get_gen(
|
||||
page_id_t(index->table->space_id, page_no),
|
||||
zip_size, RW_X_LATCH, NULL, BUF_GET, mtr);
|
||||
|
||||
if (!block) {
|
||||
if (!page_cursor->block) {
|
||||
corrupted:
|
||||
ret = false;
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
/* Get the page SSN */
|
||||
page = buf_block_get_frame(block);
|
||||
page = buf_block_get_frame(page_cursor->block);
|
||||
page_ssn = page_get_ssn_id(page);
|
||||
|
||||
if (page_cur_search_with_match(block, index, tuple, PAGE_CUR_LE,
|
||||
if (page_cur_search_with_match(tuple, PAGE_CUR_LE,
|
||||
&up_match, &low_match, page_cursor,
|
||||
nullptr)) {
|
||||
goto corrupted;
|
||||
@@ -1352,7 +1335,7 @@ rtr_store_parent_path(
|
||||
/*==================*/
|
||||
const buf_block_t* block, /*!< in: block of the page */
|
||||
btr_cur_t* btr_cur,/*!< in/out: persistent cursor */
|
||||
ulint latch_mode,
|
||||
btr_latch_mode latch_mode,
|
||||
/*!< in: latch_mode */
|
||||
ulint level, /*!< in: index level */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
@@ -1411,7 +1394,7 @@ rtr_non_leaf_insert_stack_push(
|
||||
|
||||
page_cur_position(rec, block, btr_pcur_get_page_cur(my_cursor));
|
||||
|
||||
(btr_pcur_get_btr_cur(my_cursor))->index = index;
|
||||
btr_pcur_get_page_cur(my_cursor)->index = index;
|
||||
|
||||
new_seq = rtr_get_current_ssn_id(index);
|
||||
rtr_non_leaf_stack_push(path, block->page.id().page_no(),
|
||||
|
@@ -1542,7 +1542,8 @@ static void innodb_drop_database(handlerton*, char *path)
|
||||
std::vector<pfs_os_file_t> to_close;
|
||||
mtr_t mtr;
|
||||
mtr.start();
|
||||
err= btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
|
||||
pcur.btr_cur.page_cur.index = sys_index;
|
||||
err= btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
if (err != DB_SUCCESS)
|
||||
goto err_exit;
|
||||
@@ -2000,9 +2001,8 @@ static void drop_garbage_tables_after_restore()
|
||||
ut_d(purge_sys.stop_FTS());
|
||||
|
||||
mtr.start();
|
||||
if (btr_pcur_open_at_index_side(true, dict_sys.sys_tables->indexes.start,
|
||||
BTR_SEARCH_LEAF, &pcur, true, 0, &mtr) !=
|
||||
DB_SUCCESS)
|
||||
if (pcur.open_leaf(true, dict_sys.sys_tables->indexes.start, BTR_SEARCH_LEAF,
|
||||
&mtr) != DB_SUCCESS)
|
||||
goto all_fail;
|
||||
for (;;)
|
||||
{
|
||||
@@ -14997,14 +14997,10 @@ inline int ha_innobase::defragment_table()
|
||||
}
|
||||
|
||||
btr_pcur_t pcur;
|
||||
pcur.btr_cur.index = nullptr;
|
||||
btr_pcur_init(&pcur);
|
||||
|
||||
mtr_t mtr;
|
||||
mtr.start();
|
||||
if (dberr_t err= btr_pcur_open_at_index_side(true, index,
|
||||
BTR_SEARCH_LEAF, &pcur,
|
||||
true, 0, &mtr))
|
||||
if (dberr_t err= pcur.open_leaf(true, index, BTR_SEARCH_LEAF, &mtr))
|
||||
{
|
||||
mtr.commit();
|
||||
return convert_error_code_to_mysql(err, 0, m_user_thd);
|
||||
@@ -15018,9 +15014,9 @@ inline int ha_innobase::defragment_table()
|
||||
btr_pcur_move_to_next(&pcur, &mtr);
|
||||
btr_pcur_store_position(&pcur, &mtr);
|
||||
mtr.commit();
|
||||
ut_ad(pcur.btr_cur.index == index);
|
||||
ut_ad(pcur.index() == index);
|
||||
const bool interrupted= btr_defragment_add_index(&pcur, m_user_thd);
|
||||
btr_pcur_free(&pcur);
|
||||
ut_free(pcur.old_rec_buf);
|
||||
if (interrupted)
|
||||
return ER_QUERY_INTERRUPTED;
|
||||
}
|
||||
|
@@ -2128,8 +2128,7 @@ static bool innobase_table_is_empty(const dict_table_t *table,
|
||||
bool next_page= false;
|
||||
|
||||
mtr.start();
|
||||
if (btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF,
|
||||
&pcur, true, 0, &mtr) != DB_SUCCESS)
|
||||
if (pcur.open_leaf(true, clust_index, BTR_SEARCH_LEAF, &mtr) != DB_SUCCESS)
|
||||
{
|
||||
non_empty:
|
||||
mtr.commit();
|
||||
@@ -2159,10 +2158,11 @@ next_page:
|
||||
&mtr);
|
||||
if (!block)
|
||||
goto non_empty;
|
||||
btr_leaf_page_release(page_cur_get_block(cur), BTR_SEARCH_LEAF, &mtr);
|
||||
page_cur_set_before_first(block, cur);
|
||||
if (UNIV_UNLIKELY(!page_cur_move_to_next(cur)))
|
||||
goto non_empty;
|
||||
const auto s= mtr.get_savepoint();
|
||||
mtr.rollback_to_savepoint(s - 2, s - 1);
|
||||
}
|
||||
|
||||
rec= page_cur_get_rec(cur);
|
||||
@@ -6038,8 +6038,7 @@ add_all_virtual:
|
||||
mtr.start();
|
||||
index->set_modified(mtr);
|
||||
btr_pcur_t pcur;
|
||||
dberr_t err = btr_pcur_open_at_index_side(true, index, BTR_MODIFY_TREE,
|
||||
&pcur, true, 0, &mtr);
|
||||
dberr_t err= pcur.open_leaf(true, index, BTR_MODIFY_TREE, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
func_exit:
|
||||
mtr.commit();
|
||||
|
@@ -466,9 +466,8 @@ err_exit:
|
||||
ib::info() << "Dumping the change buffer";
|
||||
ibuf_mtr_start(&mtr);
|
||||
btr_pcur_t pcur;
|
||||
if (DB_SUCCESS == btr_pcur_open_at_index_side(
|
||||
true, ibuf.index, BTR_SEARCH_LEAF, &pcur,
|
||||
true, 0, &mtr)) {
|
||||
if (DB_SUCCESS
|
||||
== pcur.open_leaf(true, ibuf.index, BTR_SEARCH_LEAF, &mtr)) {
|
||||
while (btr_pcur_move_to_next_user_rec(&pcur, &mtr)) {
|
||||
rec_print_old(stderr, btr_pcur_get_rec(&pcur));
|
||||
}
|
||||
@@ -2337,9 +2336,11 @@ work_around:
|
||||
space_id, page_nos[i], heap);
|
||||
loop:
|
||||
btr_pcur_t pcur;
|
||||
pcur.btr_cur.page_cur.index = ibuf.index;
|
||||
|
||||
ibuf_mtr_start(&mtr);
|
||||
if (btr_pcur_open(ibuf.index, tuple, PAGE_CUR_GE,
|
||||
BTR_MODIFY_LEAF, &pcur, &mtr)
|
||||
if (btr_pcur_open(tuple, PAGE_CUR_GE,
|
||||
BTR_MODIFY_LEAF, &pcur, 0, &mtr)
|
||||
!= DB_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
@@ -2386,16 +2387,11 @@ done:
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Contracts insert buffer trees by reading pages to the buffer pool.
|
||||
/** Contract the change buffer by reading pages to the buffer pool.
|
||||
@return a lower limit for the combined size in bytes of entries which
|
||||
will be merged from ibuf trees to the pages read, 0 if ibuf is
|
||||
empty */
|
||||
static
|
||||
ulint
|
||||
ibuf_merge_pages(
|
||||
/*=============*/
|
||||
ulint* n_pages) /*!< out: number of pages to which merged */
|
||||
will be merged from ibuf trees to the pages read
|
||||
@retval 0 if ibuf.empty */
|
||||
ulint ibuf_contract()
|
||||
{
|
||||
mtr_t mtr;
|
||||
btr_pcur_t pcur;
|
||||
@@ -2403,15 +2399,13 @@ ibuf_merge_pages(
|
||||
uint32_t page_nos[IBUF_MAX_N_PAGES_MERGED];
|
||||
uint32_t space_ids[IBUF_MAX_N_PAGES_MERGED];
|
||||
|
||||
*n_pages = 0;
|
||||
|
||||
ibuf_mtr_start(&mtr);
|
||||
|
||||
/* Open a cursor to a randomly chosen leaf of the tree, at a random
|
||||
position within the leaf */
|
||||
pcur.pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
pcur.old_stored = false;
|
||||
pcur.trx_if_known = NULL;
|
||||
pcur.old_rec = nullptr;
|
||||
pcur.trx_if_known = nullptr;
|
||||
pcur.search_mode = PAGE_CUR_G;
|
||||
pcur.latch_mode = BTR_SEARCH_LEAF;
|
||||
|
||||
@@ -2437,13 +2431,14 @@ ibuf_merge_pages(
|
||||
return(0);
|
||||
}
|
||||
|
||||
ulint n_pages = 0;
|
||||
sum_sizes = ibuf_get_merge_page_nos(TRUE,
|
||||
btr_pcur_get_rec(&pcur), &mtr,
|
||||
space_ids,
|
||||
page_nos, n_pages);
|
||||
page_nos, &n_pages);
|
||||
ibuf_mtr_commit(&mtr);
|
||||
|
||||
ibuf_read_merge_pages(space_ids, page_nos, *n_pages);
|
||||
ibuf_read_merge_pages(space_ids, page_nos, n_pages);
|
||||
|
||||
return(sum_sizes + 1);
|
||||
}
|
||||
@@ -2470,8 +2465,9 @@ ibuf_merge_space(
|
||||
|
||||
/* Position the cursor on the first matching record. */
|
||||
|
||||
dberr_t err = btr_pcur_open(ibuf.index, tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
pcur.btr_cur.page_cur.index = ibuf.index;
|
||||
dberr_t err = btr_pcur_open(tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, 0, &mtr);
|
||||
ut_ad(err != DB_SUCCESS || page_validate(btr_pcur_get_page(&pcur),
|
||||
ibuf.index));
|
||||
|
||||
@@ -2515,73 +2511,6 @@ ibuf_merge_space(
|
||||
return(n_pages);
|
||||
}
|
||||
|
||||
/** Contract the change buffer by reading pages to the buffer pool.
|
||||
@param[out] n_pages number of pages merged
|
||||
@param[in] sync whether the caller waits for
|
||||
the issued reads to complete
|
||||
@return a lower limit for the combined size in bytes of entries which
|
||||
will be merged from ibuf trees to the pages read, 0 if ibuf is
|
||||
empty */
|
||||
MY_ATTRIBUTE((warn_unused_result))
|
||||
static ulint ibuf_merge(ulint* n_pages)
|
||||
{
|
||||
*n_pages = 0;
|
||||
|
||||
/* We perform a dirty read of ibuf.empty, without latching
|
||||
the insert buffer root page. We trust this dirty read except
|
||||
when a slow shutdown is being executed. During a slow
|
||||
shutdown, the insert buffer merge must be completed. */
|
||||
|
||||
if (ibuf.empty && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) {
|
||||
return(0);
|
||||
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
|
||||
} else if (ibuf_debug) {
|
||||
return(0);
|
||||
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
|
||||
} else {
|
||||
return ibuf_merge_pages(n_pages);
|
||||
}
|
||||
}
|
||||
|
||||
/** Contract the change buffer by reading pages to the buffer pool.
|
||||
@return a lower limit for the combined size in bytes of entries which
|
||||
will be merged from ibuf trees to the pages read, 0 if ibuf is empty */
|
||||
static ulint ibuf_contract()
|
||||
{
|
||||
ulint n_pages;
|
||||
return ibuf_merge_pages(&n_pages);
|
||||
}
|
||||
|
||||
/** Contract the change buffer by reading pages to the buffer pool.
|
||||
@return a lower limit for the combined size in bytes of entries which
|
||||
will be merged from ibuf trees to the pages read, 0 if ibuf is
|
||||
empty */
|
||||
ulint ibuf_merge_all()
|
||||
{
|
||||
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
|
||||
if (ibuf_debug) {
|
||||
return(0);
|
||||
}
|
||||
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
|
||||
|
||||
ulint sum_bytes = 0;
|
||||
ulint n_pages = srv_io_capacity;
|
||||
|
||||
for (ulint sum_pages = 0; sum_pages < n_pages; ) {
|
||||
log_free_check();
|
||||
ulint n_pag2;
|
||||
ulint n_bytes = ibuf_merge(&n_pag2);
|
||||
|
||||
if (n_bytes == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
sum_bytes += n_bytes;
|
||||
}
|
||||
|
||||
return sum_bytes;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Contract insert buffer trees after insert if they are too big. */
|
||||
UNIV_INLINE
|
||||
@@ -2591,13 +2520,7 @@ ibuf_contract_after_insert(
|
||||
ulint entry_size) /*!< in: size of a record which was inserted
|
||||
into an ibuf tree */
|
||||
{
|
||||
/* Perform dirty reads of ibuf.size and ibuf.max_size, to
|
||||
reduce ibuf_mutex contention. ibuf.max_size remains constant
|
||||
after ibuf_init_at_db_start(), but ibuf.size should be
|
||||
protected by ibuf_mutex. Given that ibuf.size fits in a
|
||||
machine word, this should be OK; at worst we are doing some
|
||||
excessive ibuf_contract() or occasionally skipping a
|
||||
ibuf_contract(). */
|
||||
/* dirty comparison, to avoid contention on ibuf_mutex */
|
||||
if (ibuf.size < ibuf.max_size) {
|
||||
return;
|
||||
}
|
||||
@@ -2991,8 +2914,8 @@ ibuf_update_max_tablespace_id(void)
|
||||
|
||||
ibuf_mtr_start(&mtr);
|
||||
|
||||
if (btr_pcur_open_at_index_side(false, ibuf.index, BTR_SEARCH_LEAF,
|
||||
&pcur, true, 0, &mtr) != DB_SUCCESS) {
|
||||
if (pcur.open_leaf(false, ibuf.index, BTR_SEARCH_LEAF, &mtr)
|
||||
!= DB_SUCCESS) {
|
||||
func_exit:
|
||||
ibuf_mtr_commit(&mtr);
|
||||
return;
|
||||
@@ -3170,7 +3093,7 @@ ibuf_index_page_calc_free_from_bits(ulint physical_size, ulint bits)
|
||||
|
||||
/** Buffer an operation in the insert/delete buffer, instead of doing it
|
||||
directly to the disk page, if this is possible.
|
||||
@param[in] mode BTR_MODIFY_PREV or BTR_MODIFY_TREE
|
||||
@param[in] mode BTR_MODIFY_PREV or BTR_INSERT_TREE
|
||||
@param[in] op operation type
|
||||
@param[in] no_counter TRUE=use 5.0.3 format; FALSE=allow delete
|
||||
buffering
|
||||
@@ -3185,7 +3108,7 @@ or clustered
|
||||
static TRANSACTIONAL_TARGET MY_ATTRIBUTE((warn_unused_result))
|
||||
dberr_t
|
||||
ibuf_insert_low(
|
||||
ulint mode,
|
||||
btr_latch_mode mode,
|
||||
ibuf_op_t op,
|
||||
ibool no_counter,
|
||||
const dtuple_t* entry,
|
||||
@@ -3225,16 +3148,17 @@ ibuf_insert_low(
|
||||
|
||||
do_merge = FALSE;
|
||||
|
||||
/* Perform dirty reads of ibuf.size and ibuf.max_size, to
|
||||
reduce ibuf_mutex contention. Given that ibuf.max_size and
|
||||
ibuf.size fit in a machine word, this should be OK; at worst
|
||||
we are doing some excessive ibuf_contract() or occasionally
|
||||
/* Perform dirty comparison of ibuf.max_size and ibuf.size to
|
||||
reduce ibuf_mutex contention. This should be OK; at worst we
|
||||
are doing some excessive ibuf_contract() or occasionally
|
||||
skipping an ibuf_contract(). */
|
||||
if (ibuf.max_size == 0) {
|
||||
const ulint max_size = ibuf.max_size;
|
||||
|
||||
if (max_size == 0) {
|
||||
return(DB_STRONG_FAIL);
|
||||
}
|
||||
|
||||
if (ibuf.size >= ibuf.max_size + IBUF_CONTRACT_DO_NOT_INSERT) {
|
||||
if (ibuf.size >= max_size + IBUF_CONTRACT_DO_NOT_INSERT) {
|
||||
/* Insert buffer is now too big, contract it but do not try
|
||||
to insert */
|
||||
|
||||
@@ -3265,7 +3189,7 @@ ibuf_insert_low(
|
||||
the new entry to it without exceeding the free space limit for the
|
||||
page. */
|
||||
|
||||
if (BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE) {
|
||||
if (mode == BTR_INSERT_TREE) {
|
||||
for (;;) {
|
||||
mysql_mutex_lock(&ibuf_pessimistic_insert_mutex);
|
||||
mysql_mutex_lock(&ibuf_mutex);
|
||||
@@ -3287,18 +3211,16 @@ ibuf_insert_low(
|
||||
}
|
||||
|
||||
ibuf_mtr_start(&mtr);
|
||||
pcur.btr_cur.page_cur.index = ibuf.index;
|
||||
|
||||
err = btr_pcur_open(ibuf.index, ibuf_entry, PAGE_CUR_LE, mode, &pcur,
|
||||
&mtr);
|
||||
err = btr_pcur_open(ibuf_entry, PAGE_CUR_LE, mode, &pcur, 0, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
func_exit:
|
||||
ibuf_mtr_commit(&mtr);
|
||||
ut_free(pcur.old_rec_buf);
|
||||
mem_heap_free(heap);
|
||||
|
||||
if (err == DB_SUCCESS
|
||||
&& BTR_LATCH_MODE_WITHOUT_INTENTION(mode)
|
||||
== BTR_MODIFY_TREE) {
|
||||
if (err == DB_SUCCESS && mode == BTR_INSERT_TREE) {
|
||||
ibuf_contract_after_insert(entry_size);
|
||||
}
|
||||
|
||||
@@ -3345,7 +3267,7 @@ func_exit:
|
||||
until after the IBUF_OP_DELETE has been buffered. */
|
||||
|
||||
fail_exit:
|
||||
if (BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE) {
|
||||
if (mode == BTR_INSERT_TREE) {
|
||||
mysql_mutex_unlock(&ibuf_mutex);
|
||||
mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex);
|
||||
}
|
||||
@@ -3461,8 +3383,7 @@ commit_exit:
|
||||
ibuf.empty = page_is_empty(root);
|
||||
}
|
||||
} else {
|
||||
ut_ad(BTR_LATCH_MODE_WITHOUT_INTENTION(mode)
|
||||
== BTR_MODIFY_TREE);
|
||||
ut_ad(mode == BTR_INSERT_TREE);
|
||||
|
||||
/* We acquire an sx-latch to the root page before the insert,
|
||||
because a pessimistic insert releases the tree x-latch,
|
||||
@@ -3637,7 +3558,7 @@ skip_watch:
|
||||
entry, entry_size,
|
||||
index, page_id, zip_size, thr);
|
||||
if (err == DB_FAIL) {
|
||||
err = ibuf_insert_low(BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT,
|
||||
err = ibuf_insert_low(BTR_INSERT_TREE,
|
||||
op, no_counter, entry, entry_size,
|
||||
index, page_id, zip_size, thr);
|
||||
}
|
||||
@@ -3658,30 +3579,27 @@ dberr_t
|
||||
ibuf_insert_to_index_page_low(
|
||||
/*==========================*/
|
||||
const dtuple_t* entry, /*!< in: buffered entry to insert */
|
||||
buf_block_t* block, /*!< in/out: index page where the buffered
|
||||
entry should be placed */
|
||||
dict_index_t* index, /*!< in: record descriptor */
|
||||
rec_offs** offsets,/*!< out: offsets on *rec */
|
||||
mem_heap_t* heap, /*!< in/out: memory heap */
|
||||
mtr_t* mtr, /*!< in/out: mtr */
|
||||
page_cur_t* page_cur)/*!< in/out: cursor positioned on the record
|
||||
after which to insert the buffered entry */
|
||||
{
|
||||
if (page_cur_tuple_insert(page_cur, entry, index, offsets, &heap, 0, mtr))
|
||||
if (page_cur_tuple_insert(page_cur, entry, offsets, &heap, 0, mtr))
|
||||
return DB_SUCCESS;
|
||||
|
||||
/* Page reorganization or recompression should already have been
|
||||
attempted by page_cur_tuple_insert(). Besides, per
|
||||
ibuf_index_page_calc_free_zip() the page should not have been
|
||||
recompressed or reorganized. */
|
||||
ut_ad(!is_buf_block_get_page_zip(block));
|
||||
ut_ad(!is_buf_block_get_page_zip(page_cur->block));
|
||||
|
||||
/* If the record did not fit, reorganize */
|
||||
if (dberr_t err= btr_page_reorganize(page_cur, index, mtr))
|
||||
if (dberr_t err= btr_page_reorganize(page_cur, mtr))
|
||||
return err;
|
||||
|
||||
/* This time the record must fit */
|
||||
if (page_cur_tuple_insert(page_cur, entry, index, offsets, &heap, 0, mtr))
|
||||
if (page_cur_tuple_insert(page_cur, entry, offsets, &heap, 0, mtr))
|
||||
return DB_SUCCESS;
|
||||
|
||||
return DB_CORRUPTION;
|
||||
@@ -3738,8 +3656,10 @@ ibuf_insert_to_index_page(
|
||||
}
|
||||
|
||||
ulint up_match = 0, low_match = 0;
|
||||
page_cur.index = index;
|
||||
page_cur.block = block;
|
||||
|
||||
if (page_cur_search_with_match(block, index, entry, PAGE_CUR_LE,
|
||||
if (page_cur_search_with_match(entry, PAGE_CUR_LE,
|
||||
&up_match, &low_match, &page_cur,
|
||||
nullptr)) {
|
||||
return DB_CORRUPTION;
|
||||
@@ -3786,7 +3706,7 @@ ibuf_insert_to_index_page(
|
||||
if (!row_upd_changes_field_size_or_external(index, offsets,
|
||||
update)
|
||||
&& (!page_zip || btr_cur_update_alloc_zip(
|
||||
page_zip, &page_cur, index, offsets,
|
||||
page_zip, &page_cur, offsets,
|
||||
rec_offs_size(offsets), false, mtr))) {
|
||||
/* This is the easy case. Do something similar
|
||||
to btr_cur_update_in_place(). */
|
||||
@@ -3827,7 +3747,7 @@ ibuf_insert_to_index_page(
|
||||
/* Delete the different-length record, and insert the
|
||||
buffered one. */
|
||||
|
||||
page_cur_delete_rec(&page_cur, index, offsets, mtr);
|
||||
page_cur_delete_rec(&page_cur, offsets, mtr);
|
||||
if (!(page_cur_move_to_prev(&page_cur))) {
|
||||
err = DB_CORRUPTION;
|
||||
goto updated_in_place;
|
||||
@@ -3836,8 +3756,8 @@ ibuf_insert_to_index_page(
|
||||
offsets = NULL;
|
||||
}
|
||||
|
||||
err = ibuf_insert_to_index_page_low(entry, block, index,
|
||||
&offsets, heap, mtr, &page_cur);
|
||||
err = ibuf_insert_to_index_page_low(entry, &offsets, heap, mtr,
|
||||
&page_cur);
|
||||
updated_in_place:
|
||||
mem_heap_free(heap);
|
||||
|
||||
@@ -3853,16 +3773,18 @@ ibuf_set_del_mark(
|
||||
/*==============*/
|
||||
const dtuple_t* entry, /*!< in: entry */
|
||||
buf_block_t* block, /*!< in/out: block */
|
||||
const dict_index_t* index, /*!< in: record descriptor */
|
||||
dict_index_t* index, /*!< in: record descriptor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
page_cur_t page_cur;
|
||||
page_cur.block = block;
|
||||
page_cur.index = index;
|
||||
ulint up_match = 0, low_match = 0;
|
||||
|
||||
ut_ad(ibuf_inside(mtr));
|
||||
ut_ad(dtuple_check_typed(entry));
|
||||
|
||||
if (!page_cur_search_with_match(block, index, entry, PAGE_CUR_LE,
|
||||
if (!page_cur_search_with_match(entry, PAGE_CUR_LE,
|
||||
&up_match, &low_match, &page_cur,
|
||||
nullptr)
|
||||
&& low_match == dtuple_get_n_fields(entry)) {
|
||||
@@ -3914,6 +3836,8 @@ ibuf_delete(
|
||||
before latching any further pages */
|
||||
{
|
||||
page_cur_t page_cur;
|
||||
page_cur.block = block;
|
||||
page_cur.index = index;
|
||||
ulint up_match = 0, low_match = 0;
|
||||
|
||||
ut_ad(ibuf_inside(mtr));
|
||||
@@ -3921,7 +3845,7 @@ ibuf_delete(
|
||||
ut_ad(!index->is_spatial());
|
||||
ut_ad(!index->is_clust());
|
||||
|
||||
if (!page_cur_search_with_match(block, index, entry, PAGE_CUR_LE,
|
||||
if (!page_cur_search_with_match(entry, PAGE_CUR_LE,
|
||||
&up_match, &low_match, &page_cur,
|
||||
nullptr)
|
||||
&& low_match == dtuple_get_n_fields(entry)) {
|
||||
@@ -3974,7 +3898,7 @@ ibuf_delete(
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
ut_a(!page_zip || page_zip_validate(page_zip, page, index));
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
page_cur_delete_rec(&page_cur, index, offsets, mtr);
|
||||
page_cur_delete_rec(&page_cur, offsets, mtr);
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
ut_a(!page_zip || page_zip_validate(page_zip, page, index));
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
@@ -4001,13 +3925,12 @@ ibuf_restore_pos(
|
||||
const page_id_t page_id,/*!< in: page identifier */
|
||||
const dtuple_t* search_tuple,
|
||||
/*!< in: search tuple for entries of page_no */
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
|
||||
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_PURGE_TREE */
|
||||
btr_pcur_t* pcur, /*!< in/out: persistent cursor whose
|
||||
position is to be restored */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
ut_ad(mode == BTR_MODIFY_LEAF
|
||||
|| BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE);
|
||||
ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_PURGE_TREE);
|
||||
|
||||
if (UNIV_LIKELY(pcur->restore_position(mode, mtr) ==
|
||||
btr_pcur_t::SAME_ALL)) {
|
||||
@@ -4090,8 +4013,7 @@ bool ibuf_delete_rec(const page_id_t page_id, btr_pcur_t* pcur,
|
||||
ibuf_mtr_start(mtr);
|
||||
mysql_mutex_lock(&ibuf_mutex);
|
||||
|
||||
if (!ibuf_restore_pos(page_id, search_tuple,
|
||||
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
|
||||
if (!ibuf_restore_pos(page_id, search_tuple, BTR_PURGE_TREE,
|
||||
pcur, mtr)) {
|
||||
|
||||
mysql_mutex_unlock(&ibuf_mutex);
|
||||
@@ -4278,13 +4200,14 @@ dberr_t ibuf_merge_or_delete_for_page(buf_block_t *block,
|
||||
|
||||
memset(mops, 0, sizeof(mops));
|
||||
memset(dops, 0, sizeof(dops));
|
||||
pcur.btr_cur.page_cur.index = ibuf.index;
|
||||
|
||||
loop:
|
||||
ibuf_mtr_start(&mtr);
|
||||
|
||||
/* Position pcur in the insert buffer at the first entry for this
|
||||
index page */
|
||||
if (btr_pcur_open_on_user_rec(ibuf.index, search_tuple, PAGE_CUR_GE,
|
||||
if (btr_pcur_open_on_user_rec(search_tuple, PAGE_CUR_GE,
|
||||
BTR_MODIFY_LEAF, &pcur, &mtr)
|
||||
!= DB_SUCCESS) {
|
||||
err = DB_CORRUPTION;
|
||||
@@ -4437,7 +4360,6 @@ loop:
|
||||
goto loop;
|
||||
} else if (btr_pcur_is_after_last_on_page(&pcur)) {
|
||||
ibuf_mtr_commit(&mtr);
|
||||
ut_free(pcur.old_rec_buf);
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
@@ -4485,13 +4407,15 @@ void ibuf_delete_for_discarded_space(uint32_t space)
|
||||
search_tuple = ibuf_search_tuple_build(space, 0, heap);
|
||||
|
||||
memset(dops, 0, sizeof(dops));
|
||||
pcur.btr_cur.page_cur.index = ibuf.index;
|
||||
|
||||
loop:
|
||||
log_free_check();
|
||||
ibuf_mtr_start(&mtr);
|
||||
|
||||
/* Position pcur in the insert buffer at the first entry for the
|
||||
space */
|
||||
if (btr_pcur_open_on_user_rec(ibuf.index, search_tuple, PAGE_CUR_GE,
|
||||
if (btr_pcur_open_on_user_rec(search_tuple, PAGE_CUR_GE,
|
||||
BTR_MODIFY_LEAF, &pcur, &mtr)
|
||||
!= DB_SUCCESS) {
|
||||
goto leave_loop;
|
||||
@@ -4577,7 +4501,7 @@ ibuf_print(
|
||||
fprintf(file,
|
||||
"Ibuf: size " ULINTPF ", free list len " ULINTPF ","
|
||||
" seg size " ULINTPF ", " ULINTPF " merges\n",
|
||||
ibuf.size,
|
||||
ulint{ibuf.size},
|
||||
ibuf.free_list_len,
|
||||
ibuf.seg_size,
|
||||
ulint{ibuf.n_merges});
|
||||
|
@@ -55,103 +55,8 @@ not acceptable for it to lead to mysterious memory corruption, but it
|
||||
is acceptable for the program to die with a clear assert failure. */
|
||||
#define BTR_MAX_LEVELS 100
|
||||
|
||||
/** Latching modes for btr_cur_search_to_nth_level(). */
|
||||
enum btr_latch_mode {
|
||||
/** Search a record on a leaf page and S-latch it. */
|
||||
BTR_SEARCH_LEAF = RW_S_LATCH,
|
||||
/** (Prepare to) modify a record on a leaf page and X-latch it. */
|
||||
BTR_MODIFY_LEAF = RW_X_LATCH,
|
||||
/** Obtain no latches. */
|
||||
BTR_NO_LATCHES = RW_NO_LATCH,
|
||||
/** Search the previous record. */
|
||||
BTR_SEARCH_PREV = 4 | BTR_SEARCH_LEAF,
|
||||
/** Modify the previous record. */
|
||||
BTR_MODIFY_PREV = 4 | BTR_MODIFY_LEAF,
|
||||
/** Start searching the entire B-tree. */
|
||||
BTR_SEARCH_TREE = 8 | BTR_SEARCH_LEAF,
|
||||
/** Start modifying1 the entire B-tree. */
|
||||
BTR_MODIFY_TREE = 8 | BTR_MODIFY_LEAF,
|
||||
/** Continue searching the entire B-tree. */
|
||||
BTR_CONT_SEARCH_TREE = 4 | BTR_SEARCH_TREE,
|
||||
/** Continue modifying the entire B-tree. */
|
||||
BTR_CONT_MODIFY_TREE = 4 | BTR_MODIFY_TREE,
|
||||
|
||||
/* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually
|
||||
exclusive. */
|
||||
/** The search tuple will be inserted to the secondary index
|
||||
at the searched position. When the leaf page is not in the
|
||||
buffer pool, try to use the change buffer. */
|
||||
BTR_INSERT = 64,
|
||||
|
||||
/** Try to delete mark a secondary index leaf page record at
|
||||
the searched position using the change buffer when the page is
|
||||
not in the buffer pool. */
|
||||
BTR_DELETE_MARK = 128,
|
||||
|
||||
/** Try to purge the record using the change buffer when the
|
||||
secondary index leaf page is not in the buffer pool. */
|
||||
BTR_DELETE = BTR_INSERT | BTR_DELETE_MARK,
|
||||
|
||||
/** The caller is already holding dict_index_t::lock S-latch. */
|
||||
BTR_ALREADY_S_LATCHED = 256,
|
||||
/** Search and S-latch a leaf page, assuming that the
|
||||
dict_index_t::lock S-latch is being held. */
|
||||
BTR_SEARCH_LEAF_ALREADY_S_LATCHED = BTR_SEARCH_LEAF
|
||||
| BTR_ALREADY_S_LATCHED,
|
||||
/** Search the entire index tree, assuming that the
|
||||
dict_index_t::lock S-latch is being held. */
|
||||
BTR_SEARCH_TREE_ALREADY_S_LATCHED = BTR_SEARCH_TREE
|
||||
| BTR_ALREADY_S_LATCHED,
|
||||
/** Search and X-latch a leaf page, assuming that the
|
||||
dict_index_t::lock S-latch is being held. */
|
||||
BTR_MODIFY_LEAF_ALREADY_S_LATCHED = BTR_MODIFY_LEAF
|
||||
| BTR_ALREADY_S_LATCHED,
|
||||
|
||||
/** Attempt to delete-mark a secondary index record. */
|
||||
BTR_DELETE_MARK_LEAF = BTR_MODIFY_LEAF | BTR_DELETE_MARK,
|
||||
/** Attempt to delete-mark a secondary index record
|
||||
while holding the dict_index_t::lock S-latch. */
|
||||
BTR_DELETE_MARK_LEAF_ALREADY_S_LATCHED = BTR_DELETE_MARK_LEAF
|
||||
| BTR_ALREADY_S_LATCHED,
|
||||
/** Attempt to purge a secondary index record. */
|
||||
BTR_PURGE_LEAF = BTR_MODIFY_LEAF | BTR_DELETE,
|
||||
/** Attempt to purge a secondary index record
|
||||
while holding the dict_index_t::lock S-latch. */
|
||||
BTR_PURGE_LEAF_ALREADY_S_LATCHED = BTR_PURGE_LEAF
|
||||
| BTR_ALREADY_S_LATCHED,
|
||||
|
||||
/** In the case of BTR_MODIFY_TREE, the caller specifies
|
||||
the intention to delete record only. It is used to optimize
|
||||
block->lock range.*/
|
||||
BTR_LATCH_FOR_DELETE = 512,
|
||||
|
||||
/** Attempt to purge a secondary index record in the tree. */
|
||||
BTR_PURGE_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE
|
||||
};
|
||||
|
||||
/** This flag ORed to BTR_INSERT says that we can ignore possible
|
||||
UNIQUE definition on secondary indexes when we decide if we can use
|
||||
the insert buffer to speed up inserts */
|
||||
#define BTR_IGNORE_SEC_UNIQUE 2048U
|
||||
|
||||
/** In the case of BTR_MODIFY_TREE, the caller specifies the intention
|
||||
to insert record only. It is used to optimize block->lock range.*/
|
||||
#define BTR_LATCH_FOR_INSERT 4096U
|
||||
|
||||
/** This flag is for undo insert of rtree. For rtree, we need this flag
|
||||
to find proper rec to undo insert.*/
|
||||
#define BTR_RTREE_UNDO_INS 8192U
|
||||
|
||||
/** In the case of BTR_MODIFY_LEAF, the caller intends to allocate or
|
||||
free the pages of externally stored fields. */
|
||||
#define BTR_MODIFY_EXTERNAL 16384U
|
||||
|
||||
/** Try to delete mark the record at the searched position when the
|
||||
record is in spatial index */
|
||||
#define BTR_RTREE_DELETE_MARK 32768U
|
||||
|
||||
#define BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode) \
|
||||
((latch_mode) & ulint(~(BTR_INSERT \
|
||||
btr_latch_mode((latch_mode) & ~(BTR_INSERT \
|
||||
| BTR_DELETE_MARK \
|
||||
| BTR_RTREE_UNDO_INS \
|
||||
| BTR_RTREE_DELETE_MARK \
|
||||
@@ -159,13 +64,11 @@ record is in spatial index */
|
||||
| BTR_IGNORE_SEC_UNIQUE \
|
||||
| BTR_ALREADY_S_LATCHED \
|
||||
| BTR_LATCH_FOR_INSERT \
|
||||
| BTR_LATCH_FOR_DELETE \
|
||||
| BTR_MODIFY_EXTERNAL)))
|
||||
| BTR_LATCH_FOR_DELETE))
|
||||
|
||||
#define BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode) \
|
||||
((latch_mode) & ulint(~(BTR_LATCH_FOR_INSERT \
|
||||
| BTR_LATCH_FOR_DELETE \
|
||||
| BTR_MODIFY_EXTERNAL)))
|
||||
btr_latch_mode((latch_mode) \
|
||||
& ~(BTR_LATCH_FOR_INSERT | BTR_LATCH_FOR_DELETE))
|
||||
|
||||
/**************************************************************//**
|
||||
Checks and adjusts the root node of a tree during IMPORT TABLESPACE.
|
||||
@@ -228,17 +131,6 @@ inline uint32_t btr_page_get_prev(const page_t* page)
|
||||
return mach_read_from_4(my_assume_aligned<4>(page + FIL_PAGE_PREV));
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Releases the latch on a leaf page and bufferunfixes it. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_leaf_page_release(
|
||||
/*==================*/
|
||||
buf_block_t* block, /*!< in: buffer block */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
|
||||
BTR_MODIFY_LEAF */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
MY_ATTRIBUTE((nonnull));
|
||||
/**************************************************************//**
|
||||
Gets the child node file address in a node pointer.
|
||||
NOTE: the offsets array must contain all offsets for the record since
|
||||
@@ -359,14 +251,11 @@ be done either within the same mini-transaction, or by invoking
|
||||
ibuf_reset_free_bits() before mtr_commit(). On uncompressed pages,
|
||||
IBUF_BITMAP_FREE is unaffected by reorganization.
|
||||
|
||||
@param cursor page cursor
|
||||
@param mtr mini-transaction
|
||||
@return error code
|
||||
@retval DB_FAIL if reorganizing a ROW_FORMAT=COMPRESSED page failed */
|
||||
dberr_t
|
||||
btr_page_reorganize(
|
||||
/*================*/
|
||||
page_cur_t* cursor, /*!< in/out: page cursor */
|
||||
dict_index_t* index, /*!< in: the index tree of the page */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
dberr_t btr_page_reorganize(page_cur_t *cursor, mtr_t *mtr)
|
||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||
/** Decide if the page should be split at the convergence point of inserts
|
||||
converging to the left.
|
||||
@@ -445,13 +334,10 @@ inline void btr_set_min_rec_mark(rec_t *rec, const buf_block_t &block,
|
||||
}
|
||||
|
||||
/** Seek to the parent page of a B-tree page.
|
||||
@param[in,out] index b-tree
|
||||
@param[in] block child page
|
||||
@param[in,out] mtr mini-transaction
|
||||
@param[out] cursor cursor pointing to the x-latched parent page
|
||||
@param[in,out] cursor cursor pointing to the x-latched parent page
|
||||
@return whether the cursor was successfully positioned */
|
||||
bool btr_page_get_father(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
|
||||
btr_cur_t* cursor)
|
||||
bool btr_page_get_father(mtr_t* mtr, btr_cur_t* cursor)
|
||||
MY_ATTRIBUTE((nonnull,warn_unused_result));
|
||||
#ifdef UNIV_DEBUG
|
||||
/************************************************************//**
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2015, 2021, MariaDB Corporation.
|
||||
Copyright (c) 2015, 2022, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -24,10 +24,7 @@ The B-tree
|
||||
Created 6/2/1994 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "mach0data.h"
|
||||
#include "mtr0mtr.h"
|
||||
#include "mtr0log.h"
|
||||
#include "page0zip.h"
|
||||
|
||||
/**************************************************************//**
|
||||
Gets the index id field of a page.
|
||||
@@ -112,38 +109,3 @@ btr_node_ptr_get_child_page_no(
|
||||
|
||||
return(page_no);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Releases the latches on a leaf page and bufferunfixes it. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_leaf_page_release(
|
||||
/*==================*/
|
||||
buf_block_t* block, /*!< in: buffer block */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
|
||||
BTR_MODIFY_LEAF */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
ut_ad(latch_mode == BTR_SEARCH_LEAF
|
||||
|| latch_mode == BTR_MODIFY_LEAF
|
||||
|| latch_mode == BTR_NO_LATCHES);
|
||||
|
||||
ut_ad(!mtr->memo_contains_flagged(block, MTR_MEMO_MODIFY));
|
||||
|
||||
mtr_memo_type_t mode;
|
||||
switch (latch_mode) {
|
||||
case BTR_SEARCH_LEAF:
|
||||
mode = MTR_MEMO_PAGE_S_FIX;
|
||||
break;
|
||||
case BTR_MODIFY_LEAF:
|
||||
mode = MTR_MEMO_PAGE_X_FIX;
|
||||
break;
|
||||
case BTR_NO_LATCHES:
|
||||
mode = MTR_MEMO_BUF_FIX;
|
||||
break;
|
||||
default:
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
mtr->memo_release(block, mode);
|
||||
}
|
||||
|
@@ -96,7 +96,7 @@ btr_cur_get_page(
|
||||
Returns the index of a cursor.
|
||||
@param cursor b-tree cursor
|
||||
@return index */
|
||||
#define btr_cur_get_index(cursor) ((cursor)->index)
|
||||
#define btr_cur_get_index(cursor) ((cursor)->index())
|
||||
/*********************************************************//**
|
||||
Positions a tree cursor at a given record. */
|
||||
UNIV_INLINE
|
||||
@@ -137,7 +137,7 @@ bool
|
||||
btr_cur_optimistic_latch_leaves(
|
||||
buf_block_t* block,
|
||||
ib_uint64_t modify_clock,
|
||||
ulint* latch_mode,
|
||||
btr_latch_mode* latch_mode,
|
||||
btr_cur_t* cursor,
|
||||
mtr_t* mtr);
|
||||
|
||||
@@ -148,7 +148,6 @@ to node pointer page number fields on the upper levels of the tree!
|
||||
Note that if mode is PAGE_CUR_LE, which is used in inserts, then
|
||||
cursor->up_match and cursor->low_match both will have sensible values.
|
||||
If mode is PAGE_CUR_GE, then up_match will a have a sensible value.
|
||||
@param index index
|
||||
@param level the tree level of search
|
||||
@param tuple data tuple; NOTE: n_fields_cmp in tuple must be set so that
|
||||
it cannot get compared to the node ptr page number field!
|
||||
@@ -166,27 +165,13 @@ If mode is PAGE_CUR_GE, then up_match will a have a sensible value.
|
||||
@param mtr mini-transaction
|
||||
@param autoinc PAGE_ROOT_AUTO_INC to be written (0 if none)
|
||||
@return DB_SUCCESS on success or error code otherwise */
|
||||
dberr_t btr_cur_search_to_nth_level(dict_index_t *index, ulint level,
|
||||
dberr_t btr_cur_search_to_nth_level(ulint level,
|
||||
const dtuple_t *tuple,
|
||||
page_cur_mode_t mode, ulint latch_mode,
|
||||
page_cur_mode_t mode,
|
||||
btr_latch_mode latch_mode,
|
||||
btr_cur_t *cursor, mtr_t *mtr,
|
||||
ib_uint64_t autoinc= 0);
|
||||
|
||||
/*****************************************************************//**
|
||||
Opens a cursor at either end of an index.
|
||||
@return DB_SUCCESS or error code */
|
||||
dberr_t
|
||||
btr_cur_open_at_index_side(
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
false if to the high end */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint latch_mode, /*!< in: latch mode */
|
||||
btr_cur_t* cursor, /*!< in/out: cursor */
|
||||
ulint level, /*!< in: level to search for
|
||||
(0=leaf) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||
|
||||
/**********************************************************************//**
|
||||
Positions a cursor at a randomly chosen position within a B-tree.
|
||||
@return true if the index is available and we have put the cursor, false
|
||||
@@ -194,7 +179,7 @@ if the index is unavailable */
|
||||
bool
|
||||
btr_cur_open_at_rnd_pos(
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_latch_mode latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_cur_t* cursor, /*!< in/out: B-tree cursor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
MY_ATTRIBUTE((nonnull,warn_unused_result));
|
||||
@@ -281,7 +266,6 @@ btr_cur_update_alloc_zip_func(
|
||||
/*==========================*/
|
||||
page_zip_des_t* page_zip,/*!< in/out: compressed page */
|
||||
page_cur_t* cursor, /*!< in/out: B-tree page cursor */
|
||||
dict_index_t* index, /*!< in: the index corresponding to cursor */
|
||||
#ifdef UNIV_DEBUG
|
||||
rec_offs* offsets,/*!< in/out: offsets of the cursor record */
|
||||
#endif /* UNIV_DEBUG */
|
||||
@@ -291,11 +275,11 @@ btr_cur_update_alloc_zip_func(
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||
#ifdef UNIV_DEBUG
|
||||
# define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \
|
||||
btr_cur_update_alloc_zip_func(page_zip,cursor,index,offsets,len,cr,mtr)
|
||||
# define btr_cur_update_alloc_zip(page_zip,cursor,offsets,len,cr,mtr) \
|
||||
btr_cur_update_alloc_zip_func(page_zip,cursor,offsets,len,cr,mtr)
|
||||
#else /* UNIV_DEBUG */
|
||||
# define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \
|
||||
btr_cur_update_alloc_zip_func(page_zip,cursor,index,len,cr,mtr)
|
||||
# define btr_cur_update_alloc_zip(page_zip,cursor,offsets,len,cr,mtr) \
|
||||
btr_cur_update_alloc_zip_func(page_zip,cursor,len,cr,mtr)
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/** Apply an update vector to a record. No field size changes are allowed.
|
||||
@@ -689,7 +673,7 @@ btr_rec_copy_externally_stored_field(
|
||||
void
|
||||
btr_cur_latch_leaves(
|
||||
buf_block_t* block,
|
||||
ulint latch_mode,
|
||||
btr_latch_mode latch_mode,
|
||||
btr_cur_t* cursor,
|
||||
mtr_t* mtr,
|
||||
btr_latch_leaves_t* latch_leaves = nullptr);
|
||||
@@ -752,7 +736,6 @@ enum btr_cur_method {
|
||||
/** The tree cursor: the definition appears here only for the compiler
|
||||
to know struct size! */
|
||||
struct btr_cur_t {
|
||||
dict_index_t* index; /*!< index where positioned */
|
||||
page_cur_t page_cur; /*!< page cursor */
|
||||
purge_node_t* purge_node; /*!< purge node, for BTR_DELETE */
|
||||
buf_block_t* left_block; /*!< this field is used to store
|
||||
@@ -817,28 +800,19 @@ struct btr_cur_t {
|
||||
information of the path through
|
||||
the tree */
|
||||
rtr_info_t* rtr_info; /*!< rtree search info */
|
||||
btr_cur_t():thr(NULL), rtr_info(NULL) {}
|
||||
/* default values */
|
||||
/** Zero-initialize all fields */
|
||||
void init()
|
||||
{
|
||||
index = NULL;
|
||||
memset(&page_cur, 0, sizeof page_cur);
|
||||
purge_node = NULL;
|
||||
left_block = NULL;
|
||||
thr = NULL;
|
||||
flag = btr_cur_method(0);
|
||||
tree_height = 0;
|
||||
up_match = 0;
|
||||
up_bytes = 0;
|
||||
low_match = 0;
|
||||
low_bytes = 0;
|
||||
n_fields = 0;
|
||||
n_bytes = 0;
|
||||
fold = 0;
|
||||
path_arr = NULL;
|
||||
rtr_info = NULL;
|
||||
}
|
||||
btr_cur_t() { memset((void*) this, 0, sizeof *this); }
|
||||
|
||||
dict_index_t *index() const { return page_cur.index; }
|
||||
buf_block_t *block() const { return page_cur.block; }
|
||||
|
||||
/** Open the cursor on the first or last record.
|
||||
@param first true=first record, false=last record
|
||||
@param index B-tree
|
||||
@param latch_mode which latches to acquire
|
||||
@param mtr mini-transaction
|
||||
@return error code */
|
||||
dberr_t open_leaf(bool first, dict_index_t *index, btr_latch_mode latch_mode,
|
||||
mtr_t *mtr);
|
||||
};
|
||||
|
||||
/** Modify the delete-mark flag of a record.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2018, 2021, MariaDB Corporation.
|
||||
Copyright (c) 2018, 2022, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -72,7 +72,7 @@ btr_cur_position(
|
||||
btr_cur_t* cursor) /*!< out: cursor */
|
||||
{
|
||||
page_cur_position(rec, block, btr_cur_get_page_cur(cursor));
|
||||
cursor->index = index;
|
||||
cursor->page_cur.index = index;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
@@ -98,14 +98,14 @@ btr_cur_compress_recommendation(
|
||||
|
||||
if (!page_has_siblings(page)
|
||||
|| page_get_data_size(page)
|
||||
< BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) {
|
||||
< BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index())) {
|
||||
|
||||
/* The page fillfactor has dropped below a predefined
|
||||
minimum value OR the level in the B-tree contains just
|
||||
one page: we recommend compression if this is not the
|
||||
root page. */
|
||||
|
||||
return cursor->index->page
|
||||
return cursor->index()->page
|
||||
!= btr_cur_get_block(cursor)->page.id().page_no();
|
||||
}
|
||||
|
||||
@@ -133,14 +133,14 @@ btr_cur_can_delete_without_compress(
|
||||
|
||||
if (!page_has_siblings(page) || page_get_n_recs(page) < 2
|
||||
|| page_get_data_size(page) - rec_size
|
||||
< BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) {
|
||||
< BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index())) {
|
||||
|
||||
/* The page fillfactor will drop below a predefined
|
||||
minimum value, OR the level in the B-tree contains just
|
||||
one page, OR the page will become empty: we recommend
|
||||
compression if this is not the root page. */
|
||||
|
||||
return cursor->index->page
|
||||
return cursor->index()->page
|
||||
== btr_cur_get_block(cursor)->page.id().page_no();
|
||||
}
|
||||
|
||||
|
@@ -45,13 +45,6 @@ of a scroll cursor easier */
|
||||
BTR_PCUR_AFTER_LAST_IN_TREE = 5 /* in an empty tree */
|
||||
};
|
||||
|
||||
/**************************************************************//**
|
||||
Allocates memory for a persistent cursor object and initializes the cursor.
|
||||
@return own: persistent cursor */
|
||||
btr_pcur_t*
|
||||
btr_pcur_create_for_mysql(void);
|
||||
/*============================*/
|
||||
|
||||
/**************************************************************//**
|
||||
Resets a persistent cursor object, freeing ::old_rec_buf if it is
|
||||
allocated and resetting the other members to their initial values. */
|
||||
@@ -61,12 +54,6 @@ btr_pcur_reset(
|
||||
btr_pcur_t* cursor);/*!< in, out: persistent cursor */
|
||||
|
||||
/**************************************************************//**
|
||||
Frees the memory for a persistent cursor object. */
|
||||
void
|
||||
btr_pcur_free_for_mysql(
|
||||
/*====================*/
|
||||
btr_pcur_t* cursor); /*!< in, own: persistent cursor */
|
||||
/**************************************************************//**
|
||||
Copies the stored position of a pcur to another pcur. */
|
||||
void
|
||||
btr_pcur_copy_stored_position(
|
||||
@@ -83,21 +70,11 @@ btr_pcur_init(
|
||||
/*==========*/
|
||||
btr_pcur_t* pcur); /*!< in: persistent cursor */
|
||||
|
||||
/** Free old_rec_buf.
|
||||
@param[in] pcur Persistent cursor holding old_rec to be freed. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_free(
|
||||
btr_pcur_t* pcur);
|
||||
|
||||
/**************************************************************//**
|
||||
Initializes and opens a persistent cursor to an index tree. */
|
||||
inline
|
||||
dberr_t
|
||||
btr_pcur_open_low(
|
||||
/*==============*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint level, /*!< in: level in the btree */
|
||||
btr_pcur_open(
|
||||
const dtuple_t* tuple, /*!< in: tuple on which search done */
|
||||
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
|
||||
NOTE that if the search is made using a unique
|
||||
@@ -105,17 +82,14 @@ btr_pcur_open_low(
|
||||
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
|
||||
may end up on the previous page from the
|
||||
record! */
|
||||
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
|
||||
ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written
|
||||
(0 if none) */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||
#define btr_pcur_open(i,t,md,l,c,m) \
|
||||
btr_pcur_open_low(i,0,t,md,l,c,0,m)
|
||||
/** Opens an persistent cursor to an index tree without initializing the
|
||||
cursor.
|
||||
@param index index
|
||||
@param tuple tuple on which search done
|
||||
@param mode PAGE_CUR_L, ...; NOTE that if the search is made using a
|
||||
unique prefix of a record, mode should be PAGE_CUR_LE, not
|
||||
@@ -126,26 +100,11 @@ cursor.
|
||||
@param mtr mini-transaction
|
||||
@return DB_SUCCESS on success or error code otherwise. */
|
||||
inline
|
||||
dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple,
|
||||
page_cur_mode_t mode, ulint latch_mode,
|
||||
dberr_t btr_pcur_open_with_no_init(const dtuple_t *tuple,
|
||||
page_cur_mode_t mode,
|
||||
btr_latch_mode latch_mode,
|
||||
btr_pcur_t *cursor, mtr_t *mtr);
|
||||
|
||||
/*****************************************************************//**
|
||||
Opens a persistent cursor at either end of an index. */
|
||||
UNIV_INLINE
|
||||
dberr_t
|
||||
btr_pcur_open_at_index_side(
|
||||
/*========================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
false if to the high end */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint latch_mode, /*!< in: latch mode */
|
||||
btr_pcur_t* pcur, /*!< in/out: cursor */
|
||||
bool init_pcur, /*!< in: whether to initialize pcur */
|
||||
ulint level, /*!< in: level to search for
|
||||
(0=leaf) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
MY_ATTRIBUTE((nonnull,warn_unused_result));
|
||||
/**************************************************************//**
|
||||
Gets the up_match value for a pcur after a search.
|
||||
@return number of matched fields at the cursor or to the right if
|
||||
@@ -356,7 +315,8 @@ enum pcur_pos_t {
|
||||
/* The persistent B-tree cursor structure. This is used mainly for SQL
|
||||
selects, updates, and deletes. */
|
||||
|
||||
struct btr_pcur_t{
|
||||
struct btr_pcur_t
|
||||
{
|
||||
/** Return value of restore_position() */
|
||||
enum restore_status {
|
||||
/** cursor position on user rec and points on the record with
|
||||
@@ -373,61 +333,42 @@ struct btr_pcur_t{
|
||||
};
|
||||
/** a B-tree cursor */
|
||||
btr_cur_t btr_cur;
|
||||
/** see TODO note below!
|
||||
/** @see BTR_PCUR_WAS_POSITIONED
|
||||
BTR_SEARCH_LEAF, BTR_MODIFY_LEAF, BTR_MODIFY_TREE or BTR_NO_LATCHES,
|
||||
depending on the latching state of the page and tree where the cursor
|
||||
is positioned; BTR_NO_LATCHES means that the cursor is not currently
|
||||
positioned:
|
||||
we say then that the cursor is detached; it can be restored to
|
||||
attached if the old position was stored in old_rec */
|
||||
ulint latch_mode;
|
||||
/** true if old_rec is stored */
|
||||
bool old_stored;
|
||||
btr_latch_mode latch_mode= BTR_NO_LATCHES;
|
||||
/** if cursor position is stored, contains an initial segment of the
|
||||
latest record cursor was positioned either on, before or after */
|
||||
rec_t* old_rec;
|
||||
/** btr_cur.index->n_core_fields when old_rec was copied */
|
||||
uint16 old_n_core_fields;
|
||||
rec_t *old_rec= nullptr;
|
||||
/** btr_cur.index()->n_core_fields when old_rec was copied */
|
||||
uint16 old_n_core_fields= 0;
|
||||
/** number of fields in old_rec */
|
||||
uint16 old_n_fields;
|
||||
uint16 old_n_fields= 0;
|
||||
/** BTR_PCUR_ON, BTR_PCUR_BEFORE, or BTR_PCUR_AFTER, depending on
|
||||
whether cursor was on, before, or after the old_rec record */
|
||||
enum btr_pcur_pos_t rel_pos;
|
||||
btr_pcur_pos_t rel_pos= btr_pcur_pos_t(0);
|
||||
/** buffer block when the position was stored */
|
||||
buf::Block_hint block_when_stored;
|
||||
/** the modify clock value of the buffer block when the cursor position
|
||||
was stored */
|
||||
ib_uint64_t modify_clock;
|
||||
ib_uint64_t modify_clock= 0;
|
||||
/** btr_pcur_store_position() and btr_pcur_restore_position() state. */
|
||||
enum pcur_pos_t pos_state;
|
||||
/** PAGE_CUR_G, ... */
|
||||
page_cur_mode_t search_mode;
|
||||
enum pcur_pos_t pos_state= BTR_PCUR_NOT_POSITIONED;
|
||||
page_cur_mode_t search_mode= PAGE_CUR_UNSUPP;
|
||||
/** the transaction, if we know it; otherwise this field is not defined;
|
||||
can ONLY BE USED in error prints in fatal assertion failures! */
|
||||
trx_t* trx_if_known;
|
||||
/*-----------------------------*/
|
||||
/* NOTE that the following fields may possess dynamically allocated
|
||||
memory which should be freed if not needed anymore! */
|
||||
|
||||
/** NULL, or a dynamically allocated buffer for old_rec */
|
||||
byte* old_rec_buf;
|
||||
trx_t *trx_if_known= nullptr;
|
||||
/** a dynamically allocated buffer for old_rec */
|
||||
byte *old_rec_buf= nullptr;
|
||||
/** old_rec_buf size if old_rec_buf is not NULL */
|
||||
ulint buf_size;
|
||||
|
||||
btr_pcur_t() :
|
||||
btr_cur(), latch_mode(RW_NO_LATCH),
|
||||
old_stored(false), old_rec(NULL),
|
||||
old_n_fields(0), rel_pos(btr_pcur_pos_t(0)),
|
||||
block_when_stored(),
|
||||
modify_clock(0), pos_state(BTR_PCUR_NOT_POSITIONED),
|
||||
search_mode(PAGE_CUR_UNSUPP), trx_if_known(NULL),
|
||||
old_rec_buf(NULL), buf_size(0)
|
||||
{
|
||||
btr_cur.init();
|
||||
}
|
||||
ulint buf_size= 0;
|
||||
|
||||
/** Return the index of this persistent cursor */
|
||||
dict_index_t* index() const { return(btr_cur.index); }
|
||||
dict_index_t *index() const { return(btr_cur.index()); }
|
||||
MY_ATTRIBUTE((nonnull, warn_unused_result))
|
||||
/** Restores the stored position of a persistent cursor bufferfixing
|
||||
the page and obtaining the specified latches. If the cursor position
|
||||
@@ -451,7 +392,26 @@ struct btr_pcur_t{
|
||||
@retval NOT_SAME cursor position is not on user rec or points on
|
||||
the record with not the same uniq field values as in the stored
|
||||
@retval CORRUPTED if the index is corrupted */
|
||||
restore_status restore_position(ulint latch_mode, mtr_t *mtr);
|
||||
restore_status restore_position(btr_latch_mode latch_mode, mtr_t *mtr);
|
||||
|
||||
/** Open the cursor on the first or last record.
|
||||
@param first true=first record, false=last record
|
||||
@param index B-tree
|
||||
@param latch_mode which latches to acquire
|
||||
@param mtr mini-transaction
|
||||
@return error code */
|
||||
dberr_t open_leaf(bool first, dict_index_t *index, btr_latch_mode latch_mode,
|
||||
mtr_t *mtr)
|
||||
|
||||
{
|
||||
this->latch_mode= BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
|
||||
search_mode= first ? PAGE_CUR_G : PAGE_CUR_L;
|
||||
pos_state= BTR_PCUR_IS_POSITIONED;
|
||||
old_rec= nullptr;
|
||||
|
||||
return btr_cur.open_leaf(first, index,
|
||||
BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode), mtr);
|
||||
}
|
||||
};
|
||||
|
||||
inline buf_block_t *btr_pcur_get_block(btr_pcur_t *cursor)
|
||||
@@ -479,10 +439,9 @@ MY_ATTRIBUTE((nonnull, warn_unused_result))
|
||||
inline
|
||||
dberr_t
|
||||
btr_pcur_open_on_user_rec(
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const dtuple_t* tuple, /*!< in: tuple on which search done */
|
||||
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ... */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
|
||||
btr_latch_mode latch_mode, /*!< in: BTR_SEARCH_LEAF or
|
||||
BTR_MODIFY_LEAF */
|
||||
btr_pcur_t* cursor, /*!< in: memory buffer for persistent
|
||||
cursor */
|
||||
@@ -490,7 +449,7 @@ btr_pcur_open_on_user_rec(
|
||||
{
|
||||
ut_ad(mode == PAGE_CUR_GE || mode == PAGE_CUR_G);
|
||||
ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF);
|
||||
if (dberr_t err= btr_pcur_open(index, tuple, mode, latch_mode, cursor, mtr))
|
||||
if (dberr_t err= btr_pcur_open(tuple, mode, latch_mode, cursor, 0, mtr))
|
||||
return err;
|
||||
if (!btr_pcur_is_after_last_on_page(cursor) ||
|
||||
btr_pcur_is_after_last_in_tree(cursor))
|
||||
|
@@ -36,7 +36,6 @@ btr_pcur_get_rel_pos(
|
||||
{
|
||||
ut_ad(cursor);
|
||||
ut_ad(cursor->old_rec);
|
||||
ut_ad(cursor->old_stored);
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
|
||||
|| cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
|
||||
@@ -163,7 +162,7 @@ btr_pcur_move_to_next_on_page(
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
cursor->old_stored = false;
|
||||
cursor->old_rec = nullptr;
|
||||
return page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
|
||||
}
|
||||
|
||||
@@ -177,7 +176,7 @@ btr_pcur_move_to_prev_on_page(
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
cursor->old_stored = false;
|
||||
cursor->old_rec = nullptr;
|
||||
|
||||
return page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
|
||||
}
|
||||
@@ -196,7 +195,7 @@ btr_pcur_move_to_next_user_rec(
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
cursor->old_stored = false;
|
||||
cursor->old_rec = nullptr;
|
||||
loop:
|
||||
if (btr_pcur_is_after_last_on_page(cursor)) {
|
||||
if (btr_pcur_is_after_last_in_tree(cursor)
|
||||
@@ -230,7 +229,7 @@ btr_pcur_move_to_next(
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
cursor->old_stored= false;
|
||||
cursor->old_rec= nullptr;
|
||||
|
||||
if (btr_pcur_is_after_last_on_page(cursor))
|
||||
return !btr_pcur_is_after_last_in_tree(cursor) &&
|
||||
@@ -294,31 +293,17 @@ btr_pcur_init(
|
||||
/*==========*/
|
||||
btr_pcur_t* pcur) /*!< in: persistent cursor */
|
||||
{
|
||||
pcur->old_stored = false;
|
||||
pcur->old_rec_buf = NULL;
|
||||
pcur->old_rec = NULL;
|
||||
|
||||
pcur->btr_cur.rtr_info = NULL;
|
||||
}
|
||||
|
||||
/** Free old_rec_buf.
|
||||
@param[in] pcur Persistent cursor holding old_rec to be freed. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_free(
|
||||
btr_pcur_t* pcur)
|
||||
{
|
||||
ut_free(pcur->old_rec_buf);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Initializes and opens a persistent cursor to an index tree. */
|
||||
inline
|
||||
dberr_t
|
||||
btr_pcur_open_low(
|
||||
/*==============*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint level, /*!< in: level in the btree */
|
||||
btr_pcur_open(
|
||||
const dtuple_t* tuple, /*!< in: tuple on which search done */
|
||||
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
|
||||
NOTE that if the search is made using a unique
|
||||
@@ -326,26 +311,24 @@ btr_pcur_open_low(
|
||||
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
|
||||
may end up on the previous page from the
|
||||
record! */
|
||||
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
|
||||
ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written
|
||||
(0 if none) */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
ut_ad(!index->is_spatial());
|
||||
btr_pcur_init(cursor);
|
||||
ut_ad(!cursor->index()->is_spatial());
|
||||
cursor->latch_mode= BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
|
||||
cursor->search_mode= mode;
|
||||
cursor->pos_state= BTR_PCUR_IS_POSITIONED;
|
||||
cursor->trx_if_known= nullptr;
|
||||
return btr_cur_search_to_nth_level(index, level, tuple, mode, latch_mode,
|
||||
return btr_cur_search_to_nth_level(0, tuple, mode, latch_mode,
|
||||
btr_pcur_get_btr_cur(cursor),
|
||||
mtr, autoinc);
|
||||
}
|
||||
|
||||
/** Opens an persistent cursor to an index tree without initializing the
|
||||
cursor.
|
||||
@param index index
|
||||
@param tuple tuple on which search done
|
||||
@param mode PAGE_CUR_L, ...; NOTE that if the search is made using a
|
||||
unique prefix of a record, mode should be PAGE_CUR_LE, not
|
||||
@@ -356,59 +339,21 @@ cursor.
|
||||
@param mtr mini-transaction
|
||||
@return DB_SUCCESS on success or error code otherwise. */
|
||||
inline
|
||||
dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple,
|
||||
page_cur_mode_t mode, ulint latch_mode,
|
||||
dberr_t btr_pcur_open_with_no_init(const dtuple_t *tuple,
|
||||
page_cur_mode_t mode,
|
||||
btr_latch_mode latch_mode,
|
||||
btr_pcur_t *cursor, mtr_t *mtr)
|
||||
{
|
||||
cursor->latch_mode= BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode);
|
||||
cursor->search_mode= mode;
|
||||
cursor->pos_state= BTR_PCUR_IS_POSITIONED;
|
||||
cursor->old_stored= false;
|
||||
cursor->trx_if_known= nullptr;
|
||||
|
||||
/* Search with the tree cursor */
|
||||
return btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
|
||||
return btr_cur_search_to_nth_level(0, tuple, mode, latch_mode,
|
||||
btr_pcur_get_btr_cur(cursor), mtr);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Opens a persistent cursor at either end of an index. */
|
||||
UNIV_INLINE
|
||||
dberr_t
|
||||
btr_pcur_open_at_index_side(
|
||||
/*========================*/
|
||||
bool from_left, /*!< in: true if open to the low end,
|
||||
false if to the high end */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint latch_mode, /*!< in: latch mode */
|
||||
btr_pcur_t* pcur, /*!< in/out: cursor */
|
||||
bool init_pcur, /*!< in: whether to initialize pcur */
|
||||
ulint level, /*!< in: level to search for
|
||||
(0=leaf) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
pcur->latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
|
||||
|
||||
pcur->search_mode = from_left ? PAGE_CUR_G : PAGE_CUR_L;
|
||||
|
||||
if (init_pcur) {
|
||||
btr_pcur_init(pcur);
|
||||
}
|
||||
|
||||
err = btr_cur_open_at_index_side(
|
||||
from_left, index, latch_mode,
|
||||
btr_pcur_get_btr_cur(pcur), level, mtr);
|
||||
pcur->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
|
||||
pcur->old_stored = false;
|
||||
|
||||
pcur->trx_if_known = NULL;
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Frees the possible memory heap of a persistent cursor and sets the latch
|
||||
mode of the persistent cursor to BTR_NO_LATCHES.
|
||||
@@ -427,23 +372,19 @@ btr_pcur_close(
|
||||
{
|
||||
ut_free(cursor->old_rec_buf);
|
||||
|
||||
if (cursor->btr_cur.rtr_info) {
|
||||
if (cursor->btr_cur.rtr_info)
|
||||
rtr_clean_rtr_info(cursor->btr_cur.rtr_info, true);
|
||||
cursor->btr_cur.rtr_info = NULL;
|
||||
}
|
||||
|
||||
cursor->old_rec = NULL;
|
||||
cursor->old_rec_buf = NULL;
|
||||
cursor->btr_cur.page_cur.rec = NULL;
|
||||
cursor->btr_cur.page_cur.block = NULL;
|
||||
|
||||
cursor->old_rec = NULL;
|
||||
cursor->old_stored = false;
|
||||
cursor->btr_cur.rtr_info= nullptr;
|
||||
cursor->old_rec = nullptr;
|
||||
cursor->old_rec_buf = nullptr;
|
||||
cursor->btr_cur.page_cur.rec = nullptr;
|
||||
cursor->btr_cur.page_cur.block = nullptr;
|
||||
|
||||
cursor->latch_mode = BTR_NO_LATCHES;
|
||||
cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
|
||||
|
||||
cursor->trx_if_known = NULL;
|
||||
cursor->trx_if_known = nullptr;
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
@@ -459,5 +400,5 @@ btr_pcur_move_before_first_on_page(
|
||||
page_cur_set_before_first(btr_pcur_get_block(cursor),
|
||||
btr_pcur_get_page_cur(cursor));
|
||||
|
||||
cursor->old_stored = false;
|
||||
cursor->old_rec = nullptr;
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2018, 2019, MariaDB Corporation.
|
||||
Copyright (c) 2018, 2022, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -24,8 +24,7 @@ The index tree general types
|
||||
Created 2/17/1996 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef btr0types_h
|
||||
#define btr0types_h
|
||||
#pragma once
|
||||
|
||||
#include "page0types.h"
|
||||
#include "rem0types.h"
|
||||
@@ -56,4 +55,93 @@ in the index record. */
|
||||
#define BTR_EXTERN_LOCAL_STORED_MAX_SIZE \
|
||||
(BTR_EXTERN_FIELD_REF_SIZE * 2)
|
||||
|
||||
#endif
|
||||
/** Latching modes for btr_cur_search_to_nth_level(). */
|
||||
enum btr_latch_mode {
|
||||
/** Search a record on a leaf page and S-latch it. */
|
||||
BTR_SEARCH_LEAF = RW_S_LATCH,
|
||||
/** (Prepare to) modify a record on a leaf page and X-latch it. */
|
||||
BTR_MODIFY_LEAF = RW_X_LATCH,
|
||||
/** Obtain no latches. */
|
||||
BTR_NO_LATCHES = RW_NO_LATCH,
|
||||
/** Search the previous record. */
|
||||
BTR_SEARCH_PREV = 4 | BTR_SEARCH_LEAF,
|
||||
/** Modify the previous record. */
|
||||
BTR_MODIFY_PREV = 4 | BTR_MODIFY_LEAF,
|
||||
/** Start searching the entire B-tree. */
|
||||
BTR_SEARCH_TREE = 8 | BTR_SEARCH_LEAF,
|
||||
/** Start modifying1 the entire B-tree. */
|
||||
BTR_MODIFY_TREE = 8 | BTR_MODIFY_LEAF,
|
||||
/** Continue searching the entire B-tree. */
|
||||
BTR_CONT_SEARCH_TREE = 4 | BTR_SEARCH_TREE,
|
||||
/** Continue modifying the entire B-tree. */
|
||||
BTR_CONT_MODIFY_TREE = 4 | BTR_MODIFY_TREE,
|
||||
|
||||
/* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually
|
||||
exclusive. */
|
||||
/** The search tuple will be inserted to the secondary index
|
||||
at the searched position. When the leaf page is not in the
|
||||
buffer pool, try to use the change buffer. */
|
||||
BTR_INSERT = 64,
|
||||
|
||||
/** Try to delete mark a secondary index leaf page record at
|
||||
the searched position using the change buffer when the page is
|
||||
not in the buffer pool. */
|
||||
BTR_DELETE_MARK = 128,
|
||||
|
||||
/** Try to purge the record using the change buffer when the
|
||||
secondary index leaf page is not in the buffer pool. */
|
||||
BTR_DELETE = BTR_INSERT | BTR_DELETE_MARK,
|
||||
|
||||
/** The caller is already holding dict_index_t::lock S-latch. */
|
||||
BTR_ALREADY_S_LATCHED = 256,
|
||||
/** Search and S-latch a leaf page, assuming that the
|
||||
dict_index_t::lock S-latch is being held. */
|
||||
BTR_SEARCH_LEAF_ALREADY_S_LATCHED = BTR_SEARCH_LEAF
|
||||
| BTR_ALREADY_S_LATCHED,
|
||||
/** Search the entire index tree, assuming that the
|
||||
dict_index_t::lock S-latch is being held. */
|
||||
BTR_SEARCH_TREE_ALREADY_S_LATCHED = BTR_SEARCH_TREE
|
||||
| BTR_ALREADY_S_LATCHED,
|
||||
/** Search and X-latch a leaf page, assuming that the
|
||||
dict_index_t::lock is being held in non-exclusive mode. */
|
||||
BTR_MODIFY_LEAF_ALREADY_LATCHED = BTR_MODIFY_LEAF
|
||||
| BTR_ALREADY_S_LATCHED,
|
||||
|
||||
/** Attempt to delete-mark a secondary index record. */
|
||||
BTR_DELETE_MARK_LEAF = BTR_MODIFY_LEAF | BTR_DELETE_MARK,
|
||||
/** Attempt to delete-mark a secondary index record
|
||||
while holding the dict_index_t::lock S-latch. */
|
||||
BTR_DELETE_MARK_LEAF_ALREADY_S_LATCHED = BTR_DELETE_MARK_LEAF
|
||||
| BTR_ALREADY_S_LATCHED,
|
||||
/** Attempt to purge a secondary index record. */
|
||||
BTR_PURGE_LEAF = BTR_MODIFY_LEAF | BTR_DELETE,
|
||||
/** Attempt to purge a secondary index record
|
||||
while holding the dict_index_t::lock S-latch. */
|
||||
BTR_PURGE_LEAF_ALREADY_S_LATCHED = BTR_PURGE_LEAF
|
||||
| BTR_ALREADY_S_LATCHED,
|
||||
|
||||
/** In the case of BTR_MODIFY_TREE, the caller specifies
|
||||
the intention to delete record only. It is used to optimize
|
||||
block->lock range.*/
|
||||
BTR_LATCH_FOR_DELETE = 512,
|
||||
|
||||
/** In the case of BTR_MODIFY_TREE, the caller specifies
|
||||
the intention to delete record only. It is used to optimize
|
||||
block->lock range.*/
|
||||
BTR_LATCH_FOR_INSERT = 1024,
|
||||
|
||||
/** Attempt to delete a record in the tree. */
|
||||
BTR_PURGE_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
|
||||
|
||||
/** Attempt to insert a record into the tree. */
|
||||
BTR_INSERT_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT,
|
||||
|
||||
/** This flag ORed to BTR_INSERT says that we can ignore possible
|
||||
UNIQUE definition on secondary indexes when we decide if we can use
|
||||
the insert buffer to speed up inserts */
|
||||
BTR_IGNORE_SEC_UNIQUE = 2048,
|
||||
/** Rollback in spatial index */
|
||||
BTR_RTREE_UNDO_INS = 4096,
|
||||
/** Try to delete mark a spatial index record */
|
||||
BTR_RTREE_DELETE_MARK = 8192
|
||||
};
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2018, 2020, MariaDB Corporation.
|
||||
Copyright (c) 2018, 2022, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -313,67 +313,13 @@ public:
|
||||
return(m_size);
|
||||
}
|
||||
|
||||
/**
|
||||
Iterate over each block and call the functor.
|
||||
@return false if iteration was terminated. */
|
||||
template <typename Functor>
|
||||
bool for_each_block(Functor& functor) const
|
||||
{
|
||||
for (list_t::iterator it = m_list.begin(), end = m_list.end();
|
||||
it != end; ++it) {
|
||||
|
||||
if (!functor(&*it)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Iterate over each block and call the functor.
|
||||
@return false if iteration was terminated. */
|
||||
template <typename Functor>
|
||||
bool for_each_block(const Functor& functor) const
|
||||
{
|
||||
for (typename list_t::iterator it = m_list.begin(),
|
||||
end = m_list.end();
|
||||
it != end; ++it) {
|
||||
|
||||
if (!functor(&*it)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Iterate over all the blocks in reverse and call the iterator
|
||||
@return false if iteration was terminated. */
|
||||
template <typename Functor>
|
||||
bool for_each_block_in_reverse(Functor& functor) const
|
||||
{
|
||||
for (list_t::reverse_iterator it = m_list.rbegin(),
|
||||
end = m_list.rend();
|
||||
it != end; ++it) {
|
||||
|
||||
if (!functor(&*it)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Iterate over all the blocks in reverse and call the iterator
|
||||
@return false if iteration was terminated. */
|
||||
template <typename Functor>
|
||||
bool for_each_block_in_reverse(const Functor& functor) const
|
||||
{
|
||||
for (list_t::reverse_iterator it = m_list.rbegin(),
|
||||
end = m_list.rend();
|
||||
for (list_t::iterator it = m_list.begin(), end = m_list.end();
|
||||
it != end; ++it) {
|
||||
|
||||
if (!functor(&*it)) {
|
||||
|
@@ -256,23 +256,14 @@ rtr_get_mbr_from_tuple(
|
||||
rtr_mbr* mbr); /*!< out: mbr to fill */
|
||||
|
||||
/* Get the rtree page father.
|
||||
@param[in] offsets work area for the return value
|
||||
@param[in] index rtree index
|
||||
@param[in] block child page in the index
|
||||
@param[in,out] mtr mtr
|
||||
@param[in] sea_cur search cursor, contains information
|
||||
about parent nodes in search
|
||||
@param[out] cursor cursor on node pointer record,
|
||||
@param[in,out] cursor cursor on node pointer record,
|
||||
its page x-latched
|
||||
@return whether the cursor was successfully positioned */
|
||||
bool
|
||||
rtr_page_get_father(
|
||||
dict_index_t* index,
|
||||
buf_block_t* block,
|
||||
mtr_t* mtr,
|
||||
btr_cur_t* sea_cur,
|
||||
btr_cur_t* cursor)
|
||||
MY_ATTRIBUTE((nonnull(1,2,3,5), warn_unused_result));
|
||||
bool rtr_page_get_father(mtr_t *mtr, btr_cur_t *sea_cur, btr_cur_t *cursor)
|
||||
MY_ATTRIBUTE((nonnull(1,3), warn_unused_result));
|
||||
|
||||
/************************************************************//**
|
||||
Returns the father block to a page. It is assumed that mtr holds
|
||||
@@ -283,8 +274,6 @@ rtr_page_get_father_block(
|
||||
/*======================*/
|
||||
rec_offs* offsets,/*!< in: work area for the return value */
|
||||
mem_heap_t* heap, /*!< in: memory heap to use */
|
||||
dict_index_t* index, /*!< in: b-tree index */
|
||||
buf_block_t* block, /*!< in: child page in the index */
|
||||
mtr_t* mtr, /*!< in: mtr */
|
||||
btr_cur_t* sea_cur,/*!< in: search cursor, contains information
|
||||
about parent nodes in search */
|
||||
@@ -298,7 +287,7 @@ rtr_store_parent_path(
|
||||
/*==================*/
|
||||
const buf_block_t* block, /*!< in: block of the page */
|
||||
btr_cur_t* btr_cur,/*!< in/out: persistent cursor */
|
||||
ulint latch_mode,
|
||||
btr_latch_mode latch_mode,
|
||||
/*!< in: latch_mode */
|
||||
ulint level, /*!< in: index level */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
@@ -310,7 +299,7 @@ bool
|
||||
rtr_pcur_open(
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const dtuple_t* tuple, /*!< in: tuple on which search done */
|
||||
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
MY_ATTRIBUTE((warn_unused_result));
|
||||
@@ -432,7 +421,6 @@ rtr_check_same_block(
|
||||
btr_cur_t* cur, /*!< in/out: position at the parent entry
|
||||
pointing to the child if successful */
|
||||
buf_block_t* parentb,/*!< in: parent page to check */
|
||||
buf_block_t* childb, /*!< in: child Page */
|
||||
mem_heap_t* heap); /*!< in: memory heap */
|
||||
|
||||
/*********************************************************************//**
|
||||
|
@@ -30,7 +30,6 @@ Created 7/19/1997 Heikki Tuuri
|
||||
#include "mtr0mtr.h"
|
||||
#include "dict0mem.h"
|
||||
#include "fsp0fsp.h"
|
||||
#include "ibuf0types.h"
|
||||
|
||||
/** Default value for maximum on-disk size of change buffer in terms
|
||||
of percentage of the buffer pool. */
|
||||
@@ -61,6 +60,37 @@ enum ibuf_use_t {
|
||||
/** Operations that can currently be buffered. */
|
||||
extern ulong innodb_change_buffering;
|
||||
|
||||
/** Insert buffer struct */
|
||||
struct ibuf_t{
|
||||
Atomic_relaxed<ulint> size; /*!< current size of the ibuf index
|
||||
tree, in pages */
|
||||
Atomic_relaxed<ulint> max_size; /*!< recommended maximum size of the
|
||||
ibuf index tree, in pages */
|
||||
ulint seg_size; /*!< allocated pages of the file
|
||||
segment containing ibuf header and
|
||||
tree */
|
||||
bool empty; /*!< Protected by the page
|
||||
latch of the root page of the
|
||||
insert buffer tree
|
||||
(FSP_IBUF_TREE_ROOT_PAGE_NO). true
|
||||
if and only if the insert
|
||||
buffer tree is empty. */
|
||||
ulint free_list_len; /*!< length of the free list */
|
||||
ulint height; /*!< tree height */
|
||||
dict_index_t* index; /*!< insert buffer index */
|
||||
|
||||
/** number of pages merged */
|
||||
Atomic_counter<ulint> n_merges;
|
||||
Atomic_counter<ulint> n_merged_ops[IBUF_OP_COUNT];
|
||||
/*!< number of operations of each type
|
||||
merged to index pages */
|
||||
Atomic_counter<ulint> n_discarded_ops[IBUF_OP_COUNT];
|
||||
/*!< number of operations of each type
|
||||
discarded without merging due to the
|
||||
tablespace being deleted or the
|
||||
index being dropped */
|
||||
};
|
||||
|
||||
/** The insert buffer control structure */
|
||||
extern ibuf_t ibuf;
|
||||
|
||||
@@ -339,9 +369,9 @@ void ibuf_delete_for_discarded_space(uint32_t space);
|
||||
|
||||
/** Contract the change buffer by reading pages to the buffer pool.
|
||||
@return a lower limit for the combined size in bytes of entries which
|
||||
will be merged from ibuf trees to the pages read, 0 if ibuf is
|
||||
empty */
|
||||
ulint ibuf_merge_all();
|
||||
will be merged from ibuf trees to the pages read
|
||||
@retval 0 if ibuf.empty */
|
||||
ulint ibuf_contract();
|
||||
|
||||
/** Contracts insert buffer trees by reading pages referring to space_id
|
||||
to the buffer pool.
|
||||
|
@@ -65,37 +65,6 @@ ibuf_mtr_commit(
|
||||
mtr_commit(mtr);
|
||||
}
|
||||
|
||||
/** Insert buffer struct */
|
||||
struct ibuf_t{
|
||||
ulint size; /*!< current size of the ibuf index
|
||||
tree, in pages */
|
||||
ulint max_size; /*!< recommended maximum size of the
|
||||
ibuf index tree, in pages */
|
||||
ulint seg_size; /*!< allocated pages of the file
|
||||
segment containing ibuf header and
|
||||
tree */
|
||||
bool empty; /*!< Protected by the page
|
||||
latch of the root page of the
|
||||
insert buffer tree
|
||||
(FSP_IBUF_TREE_ROOT_PAGE_NO). true
|
||||
if and only if the insert
|
||||
buffer tree is empty. */
|
||||
ulint free_list_len; /*!< length of the free list */
|
||||
ulint height; /*!< tree height */
|
||||
dict_index_t* index; /*!< insert buffer index */
|
||||
|
||||
/** number of pages merged */
|
||||
Atomic_counter<ulint> n_merges;
|
||||
Atomic_counter<ulint> n_merged_ops[IBUF_OP_COUNT];
|
||||
/*!< number of operations of each type
|
||||
merged to index pages */
|
||||
Atomic_counter<ulint> n_discarded_ops[IBUF_OP_COUNT];
|
||||
/*!< number of operations of each type
|
||||
discarded without merging due to the
|
||||
tablespace being deleted or the
|
||||
index being dropped */
|
||||
};
|
||||
|
||||
/************************************************************************//**
|
||||
Sets the free bit of the page in the ibuf bitmap. This is done in a separate
|
||||
mini-transaction, hence this operation does not restrict further work to only
|
||||
|
@@ -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
|
@@ -214,6 +214,11 @@ public:
|
||||
/** number of std::swap(buf, flush_buf) and writes from buf to log;
|
||||
protected by latch.wr_lock() */
|
||||
ulint write_to_log;
|
||||
|
||||
/** Log sequence number when a log file overwrite (broken crash recovery)
|
||||
was noticed. Protected by latch.wr_lock(). */
|
||||
lsn_t overwrite_warned;
|
||||
|
||||
/** innodb_log_buffer_size (size of buf and flush_buf, in bytes) */
|
||||
size_t buf_size;
|
||||
|
||||
|
@@ -28,6 +28,8 @@ Created 11/26/1995 Heikki Tuuri
|
||||
|
||||
#include "fil0fil.h"
|
||||
#include "dyn0buf.h"
|
||||
#include "buf0buf.h"
|
||||
#include <vector>
|
||||
|
||||
/** Start a mini-transaction. */
|
||||
#define mtr_start(m) (m)->start()
|
||||
@@ -48,11 +50,6 @@ savepoint. */
|
||||
@return old mode */
|
||||
#define mtr_set_log_mode(m, d) (m)->set_log_mode((d))
|
||||
|
||||
/** Release an object in the memo stack.
|
||||
@return true if released */
|
||||
#define mtr_memo_release(m, o, t) \
|
||||
(m)->memo_release((o), (t))
|
||||
|
||||
#ifdef UNIV_PFS_RWLOCK
|
||||
# define mtr_s_lock_index(i,m) (m)->s_lock(__FILE__, __LINE__, &(i)->lock)
|
||||
# define mtr_x_lock_index(i,m) (m)->x_lock(__FILE__, __LINE__, &(i)->lock)
|
||||
@@ -66,19 +63,16 @@ savepoint. */
|
||||
#define mtr_release_block_at_savepoint(m, s, b) \
|
||||
(m)->release_block_at_savepoint((s), (b))
|
||||
|
||||
#define mtr_block_sx_latch_at_savepoint(m, s, b) \
|
||||
(m)->sx_latch_at_savepoint((s), (b))
|
||||
|
||||
#define mtr_block_x_latch_at_savepoint(m, s, b) \
|
||||
(m)->x_latch_at_savepoint((s), (b))
|
||||
|
||||
/** Mini-transaction memo stack slot. */
|
||||
struct mtr_memo_slot_t {
|
||||
/** pointer to the object */
|
||||
void* object;
|
||||
|
||||
struct mtr_memo_slot_t
|
||||
{
|
||||
/** pointer to the object, or nullptr if released */
|
||||
void *object;
|
||||
/** type of the stored object */
|
||||
mtr_memo_type_t type;
|
||||
|
||||
/** Release the object */
|
||||
void release() const;
|
||||
};
|
||||
|
||||
/** Mini-transaction handle and buffer */
|
||||
@@ -89,14 +83,19 @@ struct mtr_t {
|
||||
/** Commit the mini-transaction. */
|
||||
void commit();
|
||||
|
||||
/** Release latches till savepoint. To simplify the code only
|
||||
MTR_MEMO_S_LOCK and MTR_MEMO_PAGE_S_FIX slot types are allowed to be
|
||||
released, otherwise it would be neccesary to add one more argument in the
|
||||
function to point out what slot types are allowed for rollback, and this
|
||||
would be overengineering as currently the function is used only in one place
|
||||
in the code.
|
||||
@param savepoint savepoint, can be obtained with get_savepoint */
|
||||
void rollback_to_savepoint(ulint savepoint);
|
||||
/** Release latches of unmodified buffer pages.
|
||||
@param begin first slot to release
|
||||
@param end last slot to release, or get_savepoint() */
|
||||
void rollback_to_savepoint(ulint begin, ulint end);
|
||||
|
||||
/** Release latches of unmodified buffer pages.
|
||||
@param begin first slot to release */
|
||||
void rollback_to_savepoint(ulint begin)
|
||||
{ rollback_to_savepoint(begin, m_memo->size()); }
|
||||
|
||||
/** Release the last acquired buffer page latch. */
|
||||
void release_last_page()
|
||||
{ auto s= m_memo->size(); rollback_to_savepoint(s - 1, s); }
|
||||
|
||||
/** Commit a mini-transaction that is shrinking a tablespace.
|
||||
@param space tablespace that is being shrunk */
|
||||
@@ -118,26 +117,89 @@ struct mtr_t {
|
||||
lsn_t commit_files(lsn_t checkpoint_lsn= 0);
|
||||
|
||||
/** @return mini-transaction savepoint (current size of m_memo) */
|
||||
ulint get_savepoint() const { ut_ad(is_active()); return m_memo.size(); }
|
||||
|
||||
/** Release the (index tree) s-latch stored in an mtr memo after a
|
||||
savepoint.
|
||||
@param savepoint value returned by @see set_savepoint.
|
||||
@param lock latch to release */
|
||||
inline void release_s_latch_at_savepoint(
|
||||
ulint savepoint,
|
||||
index_lock* lock);
|
||||
ulint get_savepoint() const
|
||||
{
|
||||
ut_ad(is_active());
|
||||
return m_memo ? m_memo->size() : 0;
|
||||
}
|
||||
|
||||
/** Release the (index tree) s-latch stored in an mtr memo after a savepoint.
|
||||
@param savepoint value returned by get_savepoint()
|
||||
@param lock index latch to release */
|
||||
void release_s_latch_at_savepoint(ulint savepoint, index_lock *lock)
|
||||
{
|
||||
ut_ad(is_active());
|
||||
mtr_memo_slot_t &slot= m_memo->at(savepoint);
|
||||
ut_ad(slot.object == lock);
|
||||
ut_ad(slot.type == MTR_MEMO_S_LOCK);
|
||||
slot.object= nullptr;
|
||||
lock->s_unlock();
|
||||
}
|
||||
/** Release the block in an mtr memo after a savepoint. */
|
||||
inline void release_block_at_savepoint(
|
||||
ulint savepoint,
|
||||
buf_block_t* block);
|
||||
void release_block_at_savepoint(ulint savepoint, buf_block_t *block)
|
||||
{
|
||||
ut_ad(is_active());
|
||||
mtr_memo_slot_t &slot= m_memo->at(savepoint);
|
||||
ut_ad(slot.object == block);
|
||||
ut_ad(!(slot.type & MTR_MEMO_MODIFY));
|
||||
slot.object= nullptr;
|
||||
block->page.unfix();
|
||||
|
||||
/** SX-latch a not yet latched block after a savepoint. */
|
||||
inline void sx_latch_at_savepoint(ulint savepoint, buf_block_t* block);
|
||||
switch (slot.type) {
|
||||
case MTR_MEMO_PAGE_S_FIX:
|
||||
block->page.lock.s_unlock();
|
||||
break;
|
||||
case MTR_MEMO_PAGE_SX_FIX:
|
||||
case MTR_MEMO_PAGE_X_FIX:
|
||||
block->page.lock.u_or_x_unlock(slot.type == MTR_MEMO_PAGE_SX_FIX);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @return if we are about to make a clean buffer block dirty */
|
||||
static bool is_block_dirtied(const buf_page_t &b)
|
||||
{
|
||||
ut_ad(b.in_file());
|
||||
ut_ad(b.frame);
|
||||
ut_ad(b.buf_fix_count());
|
||||
return b.oldest_modification() <= 1 && b.id().space() < SRV_TMP_SPACE_ID;
|
||||
}
|
||||
|
||||
/** X-latch a not yet latched block after a savepoint. */
|
||||
inline void x_latch_at_savepoint(ulint savepoint, buf_block_t* block);
|
||||
void x_latch_at_savepoint(ulint savepoint, buf_block_t *block)
|
||||
{
|
||||
ut_ad(is_active());
|
||||
ut_ad(!memo_contains_flagged(block, MTR_MEMO_PAGE_S_FIX |
|
||||
MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
|
||||
mtr_memo_slot_t &slot= m_memo->at(savepoint);
|
||||
ut_ad(slot.object == block);
|
||||
ut_ad(slot.type == MTR_MEMO_BUF_FIX);
|
||||
slot.type= MTR_MEMO_PAGE_X_FIX;
|
||||
block->page.lock.x_lock();
|
||||
ut_ad(!block->page.is_io_fixed());
|
||||
|
||||
if (!m_made_dirty)
|
||||
m_made_dirty= is_block_dirtied(block->page);
|
||||
}
|
||||
|
||||
/** U-latch a not yet latched block after a savepoint. */
|
||||
void sx_latch_at_savepoint(ulint savepoint, buf_block_t *block)
|
||||
{
|
||||
ut_ad(is_active());
|
||||
ut_ad(!memo_contains_flagged(block, MTR_MEMO_PAGE_S_FIX |
|
||||
MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
|
||||
mtr_memo_slot_t &slot= m_memo->at(savepoint);
|
||||
ut_ad(slot.object == block);
|
||||
ut_ad(slot.type == MTR_MEMO_BUF_FIX);
|
||||
slot.type= MTR_MEMO_PAGE_SX_FIX;
|
||||
block->page.lock.u_lock();
|
||||
ut_ad(!block->page.is_io_fixed());
|
||||
|
||||
if (!m_made_dirty)
|
||||
m_made_dirty= is_block_dirtied(block->page);
|
||||
}
|
||||
|
||||
/** @return the logging mode */
|
||||
mtr_log_t get_log_mode() const
|
||||
@@ -291,19 +353,17 @@ struct mtr_t {
|
||||
/** Acquire an exclusive tablespace latch.
|
||||
@param space tablespace */
|
||||
void x_lock_space(fil_space_t *space);
|
||||
/** Release an object in the memo stack.
|
||||
@param object object
|
||||
@param type object type
|
||||
@return bool if lock released */
|
||||
bool memo_release(const void *object, ulint type);
|
||||
/** Release a page latch.
|
||||
@param[in] ptr pointer to within a page frame
|
||||
@param[in] type object type: MTR_MEMO_PAGE_X_FIX, ... */
|
||||
void release_page(const void *ptr, mtr_memo_type_t type);
|
||||
|
||||
/** Release an index latch. */
|
||||
void release(const index_lock &lock) { release(&lock); }
|
||||
/** Release a latch to an unmodified page. */
|
||||
void release(const buf_block_t &block) { release(&block); }
|
||||
|
||||
/** Note that the mini-transaction will modify data. */
|
||||
void flag_modified() { m_modifications = true; }
|
||||
private:
|
||||
/** Release an unmodified object. */
|
||||
void release(const void *object);
|
||||
/** Mark the given latched page as modified.
|
||||
@param block page that will be modified */
|
||||
void modify(const buf_block_t& block);
|
||||
@@ -338,73 +398,93 @@ public:
|
||||
@param rw_latch RW_S_LATCH, RW_SX_LATCH, RW_X_LATCH, RW_NO_LATCH */
|
||||
void page_lock(buf_block_t *block, ulint rw_latch);
|
||||
|
||||
/** Acquire a latch on a buffer-fixed buffer pool block.
|
||||
@param savepoint savepoint location of the buffer-fixed block
|
||||
@param rw_latch latch to acquire */
|
||||
void upgrade_buffer_fix(ulint savepoint, rw_lock_type_t rw_latch);
|
||||
|
||||
/** Register a page latch on a buffer-fixed block was buffer-fixed.
|
||||
@param latch latch type */
|
||||
void u_lock_register(ulint savepoint)
|
||||
{
|
||||
mtr_memo_slot_t *slot= m_memo.at<mtr_memo_slot_t*>(savepoint);
|
||||
ut_ad(slot->type == MTR_MEMO_BUF_FIX);
|
||||
slot->type= MTR_MEMO_PAGE_SX_FIX;
|
||||
mtr_memo_slot_t &slot= m_memo->at(savepoint);
|
||||
ut_ad(slot.type == MTR_MEMO_BUF_FIX);
|
||||
slot.type= MTR_MEMO_PAGE_SX_FIX;
|
||||
}
|
||||
|
||||
/** Register a page latch on a buffer-fixed block was buffer-fixed.
|
||||
@param latch latch type */
|
||||
void s_lock_register(ulint savepoint)
|
||||
{
|
||||
mtr_memo_slot_t &slot= m_memo->at(savepoint);
|
||||
ut_ad(slot.type == MTR_MEMO_BUF_FIX);
|
||||
slot.type= MTR_MEMO_PAGE_S_FIX;
|
||||
}
|
||||
|
||||
/** Upgrade U locks on a block to X */
|
||||
void page_lock_upgrade(const buf_block_t &block);
|
||||
/** Upgrade X lock to X */
|
||||
/** Upgrade U lock to X */
|
||||
void lock_upgrade(const index_lock &lock);
|
||||
|
||||
/** Check if we are holding tablespace latch
|
||||
@param space tablespace to search for
|
||||
@param shared whether to look for shared latch, instead of exclusive
|
||||
@return whether space.latch is being held */
|
||||
bool memo_contains(const fil_space_t& space, bool shared= false)
|
||||
bool memo_contains(const fil_space_t& space, bool shared= false) const
|
||||
MY_ATTRIBUTE((warn_unused_result));
|
||||
#ifdef UNIV_DEBUG
|
||||
/** Check if we are holding an rw-latch in this mini-transaction
|
||||
@param lock latch to search for
|
||||
@param type held latch type
|
||||
@return whether (lock,type) is contained */
|
||||
bool memo_contains(const index_lock &lock, mtr_memo_type_t type)
|
||||
bool memo_contains(const index_lock &lock, mtr_memo_type_t type) const
|
||||
MY_ATTRIBUTE((warn_unused_result));
|
||||
|
||||
/** Check if memo contains the given item.
|
||||
/** Check if memo contains an index or buffer block latch.
|
||||
@param object object to search
|
||||
@param flags specify types of object (can be ORred) of
|
||||
MTR_MEMO_PAGE_S_FIX ... values
|
||||
@param flags specify types of object latches
|
||||
@return true if contains */
|
||||
bool memo_contains_flagged(const void* ptr, ulint flags) const;
|
||||
bool memo_contains_flagged(const void *object, ulint flags) const
|
||||
MY_ATTRIBUTE((warn_unused_result, nonnull));
|
||||
|
||||
/** Check if memo contains the given page.
|
||||
@param[in] ptr pointer to within buffer frame
|
||||
@param[in] flags specify types of object with OR of
|
||||
MTR_MEMO_PAGE_S_FIX... values
|
||||
@param ptr pointer to within page frame
|
||||
@param flags types latch to look for
|
||||
@return the block
|
||||
@retval NULL if not found */
|
||||
buf_block_t* memo_contains_page_flagged(
|
||||
const byte* ptr,
|
||||
ulint flags) const;
|
||||
@retval nullptr if not found */
|
||||
buf_block_t *memo_contains_page_flagged(const byte *ptr, ulint flags) const;
|
||||
|
||||
/** @return true if mini-transaction contains modifications. */
|
||||
bool has_modifications() const { return m_modifications; }
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/** @return true if a record was added to the mini-transaction */
|
||||
bool is_dirty() const { return m_made_dirty; }
|
||||
|
||||
/** Push an object to an mtr memo stack.
|
||||
@param object object
|
||||
@param type object type: MTR_MEMO_S_LOCK, ... */
|
||||
inline void memo_push(void* object, mtr_memo_type_t type);
|
||||
void memo_push(void *object, mtr_memo_type_t type) __attribute__((nonnull))
|
||||
{
|
||||
ut_ad(is_active());
|
||||
/* If this mtr has U or X latched a clean page then we set
|
||||
the m_made_dirty flag. This tells us if we need to
|
||||
grab log_sys.flush_order_mutex at mtr_t::commit() so that we
|
||||
can insert the dirtied page into the buf_pool.flush_list.
|
||||
|
||||
/** Check if this mini-transaction is dirtying a clean page.
|
||||
@param block block being x-fixed
|
||||
@return true if the mtr is dirtying a clean page. */
|
||||
static inline bool is_block_dirtied(const buf_block_t* block)
|
||||
MY_ATTRIBUTE((warn_unused_result));
|
||||
FIXME: Do this only when the MTR_MEMO_MODIFY flag is set! */
|
||||
if (!m_made_dirty &&
|
||||
(type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)))
|
||||
m_made_dirty=
|
||||
is_block_dirtied(*static_cast<const buf_page_t*>(object));
|
||||
|
||||
if (!m_memo)
|
||||
m_memo= new std::vector<mtr_memo_slot_t>(1, {object, type});
|
||||
else
|
||||
m_memo->emplace_back(mtr_memo_slot_t{object, type});
|
||||
}
|
||||
|
||||
/** @return the size of the log is empty */
|
||||
size_t get_log_size() const { return m_log.size(); }
|
||||
/** @return whether the log and memo are empty */
|
||||
bool is_empty() const { return m_memo.size() == 0 && m_log.size() == 0; }
|
||||
bool is_empty() const { return !get_savepoint() && !get_log_size(); }
|
||||
|
||||
/** Write an OPT_PAGE_CHECKSUM record. */
|
||||
inline void page_checksum(const buf_page_t &bpage);
|
||||
@@ -670,6 +750,8 @@ private:
|
||||
@return {start_lsn,flush_ahead} */
|
||||
std::pair<lsn_t,page_flush_ahead> finish_write(size_t len);
|
||||
|
||||
/** Release all latches. */
|
||||
void release();
|
||||
/** Release the resources */
|
||||
inline void release_resources();
|
||||
|
||||
@@ -727,7 +809,7 @@ private:
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/** acquired dict_index_t::lock, fil_space_t::latch, buf_block_t */
|
||||
mtr_buf_t m_memo;
|
||||
std::vector<mtr_memo_slot_t> *m_memo= nullptr;
|
||||
|
||||
/** mini-transaction log */
|
||||
mtr_buf_t m_log;
|
||||
@@ -743,5 +825,3 @@ private:
|
||||
/** set of freed page ids */
|
||||
range_set *m_freed_pages= nullptr;
|
||||
};
|
||||
|
||||
#include "mtr0mtr.inl"
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -129,7 +129,6 @@ page_cur_tuple_insert(
|
||||
/*==================*/
|
||||
page_cur_t* cursor, /*!< in/out: a page cursor */
|
||||
const dtuple_t* tuple, /*!< in: pointer to a data tuple */
|
||||
dict_index_t* index, /*!< in: record descriptor */
|
||||
rec_offs** offsets,/*!< out: offsets on *rec */
|
||||
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
|
||||
ulint n_ext, /*!< in: number of externally stored columns */
|
||||
@@ -143,7 +142,6 @@ rec_t*
|
||||
page_cur_insert_rec_low(
|
||||
/*====================*/
|
||||
const page_cur_t*cur, /*!< in: page cursor */
|
||||
dict_index_t* index, /*!< in: record descriptor */
|
||||
const rec_t* rec, /*!< in: record to insert after cur */
|
||||
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
@@ -165,7 +163,6 @@ page_cur_insert_rec_zip(
|
||||
/*====================*/
|
||||
page_cur_t* cursor, /*!< in/out: page cursor,
|
||||
logical position unchanged */
|
||||
dict_index_t* index, /*!< in: record descriptor */
|
||||
const rec_t* rec, /*!< in: pointer to a physical record */
|
||||
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
@@ -177,7 +174,6 @@ void
|
||||
page_cur_delete_rec(
|
||||
/*================*/
|
||||
page_cur_t* cursor, /*!< in/out: a page cursor */
|
||||
const dict_index_t* index, /*!< in: record descriptor */
|
||||
const rec_offs* offsets,/*!< in: rec_get_offsets(
|
||||
cursor->rec, index) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
@@ -239,8 +235,6 @@ Searches the right position for a page cursor. */
|
||||
bool
|
||||
page_cur_search_with_match(
|
||||
/*=======================*/
|
||||
const buf_block_t* block, /*!< in: buffer block */
|
||||
const dict_index_t* index, /*!< in: record descriptor */
|
||||
const dtuple_t* tuple, /*!< in: data tuple */
|
||||
page_cur_mode_t mode, /*!< in: PAGE_CUR_L,
|
||||
PAGE_CUR_LE, PAGE_CUR_G, or
|
||||
@@ -251,13 +245,11 @@ page_cur_search_with_match(
|
||||
ulint* ilow_matched_fields,
|
||||
/*!< in/out: already matched
|
||||
fields in lower limit record */
|
||||
page_cur_t* cursor, /*!< out: page cursor */
|
||||
page_cur_t* cursor, /*!< in/out: page cursor */
|
||||
rtr_info_t* rtr_info);/*!< in/out: rtree search stack */
|
||||
#ifdef BTR_CUR_HASH_ADAPT
|
||||
MY_ATTRIBUTE((warn_unused_result))
|
||||
/** Search the right position for a page cursor.
|
||||
@param[in] block buffer block
|
||||
@param[in] index index tree
|
||||
@param[in] tuple key to be searched for
|
||||
@param[in] mode search mode
|
||||
@param[in,out] iup_matched_fields already matched fields in the
|
||||
@@ -268,11 +260,9 @@ first partially matched field in the upper limit record
|
||||
lower limit record
|
||||
@param[in,out] ilow_matched_bytes already matched bytes in the
|
||||
first partially matched field in the lower limit record
|
||||
@param[out] cursor page cursor */
|
||||
@param[in,out] cursor page cursor */
|
||||
bool
|
||||
page_cur_search_with_match_bytes(
|
||||
const buf_block_t* block,
|
||||
const dict_index_t* index,
|
||||
const dtuple_t* tuple,
|
||||
page_cur_mode_t mode,
|
||||
ulint* iup_matched_fields,
|
||||
@@ -284,16 +274,12 @@ page_cur_search_with_match_bytes(
|
||||
/***********************************************************//**
|
||||
Positions a page cursor on a randomly chosen user record on a page. If there
|
||||
are no user records, sets the cursor on the infimum record. */
|
||||
void
|
||||
page_cur_open_on_rnd_user_rec(
|
||||
/*==========================*/
|
||||
buf_block_t* block, /*!< in: page */
|
||||
page_cur_t* cursor);/*!< out: page cursor */
|
||||
void page_cur_open_on_rnd_user_rec(page_cur_t *cursor);
|
||||
|
||||
/** Index page cursor */
|
||||
|
||||
struct page_cur_t{
|
||||
const dict_index_t* index;
|
||||
dict_index_t* index;
|
||||
rec_t* rec; /*!< pointer to a record on page */
|
||||
rec_offs* offsets;
|
||||
buf_block_t* block; /*!< pointer to the block containing rec */
|
||||
|
@@ -167,14 +167,12 @@ page_cur_tuple_insert(
|
||||
/*==================*/
|
||||
page_cur_t* cursor, /*!< in/out: a page cursor */
|
||||
const dtuple_t* tuple, /*!< in: pointer to a data tuple */
|
||||
dict_index_t* index, /*!< in: record descriptor */
|
||||
rec_offs** offsets,/*!< out: offsets on *rec */
|
||||
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
|
||||
ulint n_ext, /*!< in: number of externally stored columns */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
rec_t* rec;
|
||||
ulint size = rec_get_converted_size(index, tuple, n_ext);
|
||||
ulint size = rec_get_converted_size(cursor->index, tuple, n_ext);
|
||||
|
||||
if (!*heap) {
|
||||
*heap = mem_heap_create(size
|
||||
@@ -183,24 +181,23 @@ page_cur_tuple_insert(
|
||||
* sizeof **offsets);
|
||||
}
|
||||
|
||||
rec = rec_convert_dtuple_to_rec((byte*) mem_heap_alloc(*heap, size),
|
||||
index, tuple, n_ext);
|
||||
rec_t* rec = rec_convert_dtuple_to_rec(
|
||||
static_cast<byte*>(mem_heap_alloc(*heap, size)),
|
||||
cursor->index, tuple, n_ext);
|
||||
|
||||
*offsets = rec_get_offsets(rec, index, *offsets,
|
||||
*offsets = rec_get_offsets(rec, cursor->index, *offsets,
|
||||
page_is_leaf(cursor->block->page.frame)
|
||||
? index->n_core_fields : 0,
|
||||
? cursor->index->n_core_fields : 0,
|
||||
ULINT_UNDEFINED, heap);
|
||||
ut_ad(size == rec_offs_size(*offsets));
|
||||
|
||||
if (is_buf_block_get_page_zip(cursor->block)) {
|
||||
rec = page_cur_insert_rec_zip(
|
||||
cursor, index, rec, *offsets, mtr);
|
||||
rec = page_cur_insert_rec_zip(cursor, rec, *offsets, mtr);
|
||||
} else {
|
||||
rec = page_cur_insert_rec_low(cursor,
|
||||
index, rec, *offsets, mtr);
|
||||
rec = page_cur_insert_rec_low(cursor, rec, *offsets, mtr);
|
||||
}
|
||||
|
||||
ut_ad(!rec || !cmp_dtuple_rec(tuple, rec, index, *offsets));
|
||||
ut_ad(!rec || !cmp_dtuple_rec(tuple, rec, cursor->index, *offsets));
|
||||
return(rec);
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2017, 2021, MariaDB Corporation.
|
||||
Copyright (c) 2017, 2022, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -78,7 +78,7 @@ dberr_t
|
||||
row_ins_clust_index_entry_low(
|
||||
/*==========================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags */
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
|
||||
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
|
||||
depending on whether we wish optimistic or
|
||||
pessimistic descent down the index tree */
|
||||
dict_index_t* index, /*!< in: clustered index */
|
||||
@@ -94,13 +94,13 @@ same fields is found, the other record is necessarily marked deleted.
|
||||
It is then unmarked. Otherwise, the entry is just inserted to the index.
|
||||
@retval DB_SUCCESS on success
|
||||
@retval DB_LOCK_WAIT on lock wait when !(flags & BTR_NO_LOCKING_FLAG)
|
||||
@retval DB_FAIL if retry with BTR_MODIFY_TREE is needed
|
||||
@retval DB_FAIL if retry with BTR_INSERT_TREE is needed
|
||||
@return error code */
|
||||
dberr_t
|
||||
row_ins_sec_index_entry_low(
|
||||
/*========================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags */
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
|
||||
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE,
|
||||
depending on whether we wish optimistic or
|
||||
pessimistic descent down the index tree */
|
||||
dict_index_t* index, /*!< in: secondary index */
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2016, 2020, MariaDB Corporation.
|
||||
Copyright (c) 2016, 2022, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -303,13 +303,13 @@ row_build_row_ref_fast(
|
||||
/***************************************************************//**
|
||||
Searches the clustered index record for a row, if we have the row
|
||||
reference.
|
||||
@return TRUE if found */
|
||||
ibool
|
||||
@return true if found */
|
||||
bool
|
||||
row_search_on_row_ref(
|
||||
/*==================*/
|
||||
btr_pcur_t* pcur, /*!< out: persistent cursor, which must
|
||||
be closed by the caller */
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
|
||||
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
|
||||
const dict_table_t* table, /*!< in: table */
|
||||
const dtuple_t* ref, /*!< in: row reference */
|
||||
mtr_t* mtr) /*!< in/out: mtr */
|
||||
@@ -321,7 +321,7 @@ on the secondary index record are preserved.
|
||||
rec_t*
|
||||
row_get_clust_rec(
|
||||
/*==============*/
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
|
||||
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
|
||||
const rec_t* rec, /*!< in: record in a secondary index */
|
||||
dict_index_t* index, /*!< in: secondary index */
|
||||
dict_index_t** clust_index,/*!< out: clustered index */
|
||||
@@ -363,9 +363,8 @@ Searches an index record.
|
||||
enum row_search_result
|
||||
row_search_index_entry(
|
||||
/*===================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const dtuple_t* entry, /*!< in: index entry */
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
|
||||
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
|
||||
btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must
|
||||
be closed by the caller */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
|
@@ -812,10 +812,14 @@ func_exit:
|
||||
|
||||
if (lsn <= sync_lsn)
|
||||
{
|
||||
#ifndef DBUG_OFF
|
||||
skip_checkpoint:
|
||||
#endif
|
||||
log_sys.set_check_flush_or_checkpoint(false);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", goto skip_checkpoint;);
|
||||
log_sys.latch.rd_unlock();
|
||||
|
||||
/* We must wait to prevent the tail of the log overwriting the head. */
|
||||
@@ -912,13 +916,9 @@ loop:
|
||||
}
|
||||
|
||||
/* We need these threads to stop early in shutdown. */
|
||||
const char* thread_name;
|
||||
|
||||
if (srv_fast_shutdown != 2 && trx_rollback_is_active) {
|
||||
thread_name = "rollback of recovered transactions";
|
||||
} else {
|
||||
thread_name = NULL;
|
||||
}
|
||||
const char* thread_name = srv_fast_shutdown != 2
|
||||
&& trx_rollback_is_active
|
||||
? "rollback of recovered transactions" : nullptr;
|
||||
|
||||
if (thread_name) {
|
||||
ut_ad(!srv_read_only_mode);
|
||||
|
@@ -1148,6 +1148,7 @@ public:
|
||||
}
|
||||
|
||||
mtr.commit();
|
||||
clear();
|
||||
}
|
||||
|
||||
/** Clear the data structure */
|
||||
@@ -1174,14 +1175,6 @@ inline void recv_sys_t::trim(const page_id_t page_id, lsn_t lsn)
|
||||
pages.erase(r);
|
||||
}
|
||||
}
|
||||
if (fil_space_t* space = fil_space_get(page_id.space())) {
|
||||
ut_ad(UT_LIST_GET_LEN(space->chain) == 1);
|
||||
fil_node_t* file = UT_LIST_GET_FIRST(space->chain);
|
||||
ut_ad(file->is_open());
|
||||
os_file_truncate(file->name, file->handle,
|
||||
os_offset_t{page_id.page_no()}
|
||||
<< srv_page_size_shift, true);
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@@ -3485,7 +3478,17 @@ void recv_sys_t::apply(bool last_batch)
|
||||
{
|
||||
const trunc& t= truncated_undo_spaces[id];
|
||||
if (t.lsn)
|
||||
trim(page_id_t(id + srv_undo_space_id_start, t.pages), t.lsn);
|
||||
{
|
||||
trim(page_id_t(id + srv_undo_space_id_start, 0), t.lsn);
|
||||
if (fil_space_t *space = fil_space_get(id + srv_undo_space_id_start))
|
||||
{
|
||||
ut_ad(UT_LIST_GET_LEN(space->chain) == 1);
|
||||
fil_node_t *file= UT_LIST_GET_FIRST(space->chain);
|
||||
ut_ad(file->is_open());
|
||||
os_file_truncate(file->name, file->handle,
|
||||
os_offset_t{t.pages} << srv_page_size_shift, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fil_system.extend_to_recv_size();
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -277,8 +277,6 @@ Searches the right position for a page cursor. */
|
||||
bool
|
||||
page_cur_search_with_match(
|
||||
/*=======================*/
|
||||
const buf_block_t* block, /*!< in: buffer block */
|
||||
const dict_index_t* index, /*!< in/out: record descriptor */
|
||||
const dtuple_t* tuple, /*!< in: data tuple */
|
||||
page_cur_mode_t mode, /*!< in: PAGE_CUR_L,
|
||||
PAGE_CUR_LE, PAGE_CUR_G, or
|
||||
@@ -303,6 +301,8 @@ page_cur_search_with_match(
|
||||
ulint low_matched_fields;
|
||||
ulint cur_matched_fields;
|
||||
int cmp;
|
||||
const dict_index_t* const index = cursor->index;
|
||||
const buf_block_t* const block = cursor->block;
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
const page_zip_des_t* page_zip = buf_block_get_page_zip(block);
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
@@ -552,8 +552,6 @@ first partially matched field in the lower limit record
|
||||
@param[out] cursor page cursor */
|
||||
bool
|
||||
page_cur_search_with_match_bytes(
|
||||
const buf_block_t* block,
|
||||
const dict_index_t* index,
|
||||
const dtuple_t* tuple,
|
||||
page_cur_mode_t mode,
|
||||
ulint* iup_matched_fields,
|
||||
@@ -575,6 +573,8 @@ page_cur_search_with_match_bytes(
|
||||
ulint cur_matched_fields;
|
||||
ulint cur_matched_bytes;
|
||||
int cmp;
|
||||
const dict_index_t* const index = cursor->index;
|
||||
const buf_block_t* const block = cursor->block;
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
const page_zip_des_t* page_zip = buf_block_get_page_zip(block);
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
@@ -802,18 +802,13 @@ up_rec_match:
|
||||
/***********************************************************//**
|
||||
Positions a page cursor on a randomly chosen user record on a page. If there
|
||||
are no user records, sets the cursor on the infimum record. */
|
||||
void
|
||||
page_cur_open_on_rnd_user_rec(
|
||||
/*==========================*/
|
||||
buf_block_t* block, /*!< in: page */
|
||||
page_cur_t* cursor) /*!< out: page cursor */
|
||||
void page_cur_open_on_rnd_user_rec(page_cur_t *cursor)
|
||||
{
|
||||
cursor->block= block;
|
||||
if (const ulint n_recs= page_get_n_recs(block->page.frame))
|
||||
if ((cursor->rec= page_rec_get_nth(block->page.frame,
|
||||
if (const ulint n_recs= page_get_n_recs(cursor->block->page.frame))
|
||||
if ((cursor->rec= page_rec_get_nth(cursor->block->page.frame,
|
||||
ut_rnd_interval(n_recs) + 1)))
|
||||
return;
|
||||
cursor->rec= page_get_infimum_rec(block->page.frame);
|
||||
cursor->rec= page_get_infimum_rec(cursor->block->page.frame);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1361,12 +1356,12 @@ rec_t*
|
||||
page_cur_insert_rec_low(
|
||||
/*====================*/
|
||||
const page_cur_t*cur, /*!< in: page cursor */
|
||||
dict_index_t* index, /*!< in: record descriptor */
|
||||
const rec_t* rec, /*!< in: record to insert after cur */
|
||||
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
buf_block_t* block= cur->block;
|
||||
buf_block_t *block= cur->block;
|
||||
dict_index_t * const index= cur->index;
|
||||
|
||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||
ut_ad(rec_offs_n_fields(offsets) > 0);
|
||||
@@ -1786,13 +1781,13 @@ page_cur_insert_rec_zip(
|
||||
/*====================*/
|
||||
page_cur_t* cursor, /*!< in/out: page cursor,
|
||||
logical position unchanged */
|
||||
dict_index_t* index, /*!< in: record descriptor */
|
||||
const rec_t* rec, /*!< in: pointer to a physical record */
|
||||
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
page_zip_des_t * const page_zip= page_cur_get_page_zip(cursor);
|
||||
page_t * const page= cursor->block->page.frame;
|
||||
dict_index_t * const index = cursor->index;
|
||||
|
||||
ut_ad(page_zip);
|
||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||
@@ -1894,8 +1889,7 @@ page_cur_insert_rec_zip(
|
||||
|
||||
/* Try compressing the whole page afterwards. */
|
||||
const mtr_log_t log_mode= mtr->set_log_mode(MTR_LOG_NONE);
|
||||
rec_t *insert_rec= page_cur_insert_rec_low(cursor, index, rec, offsets,
|
||||
mtr);
|
||||
rec_t *insert_rec= page_cur_insert_rec_low(cursor, rec, offsets, mtr);
|
||||
mtr->set_log_mode(log_mode);
|
||||
|
||||
if (insert_rec)
|
||||
@@ -2243,7 +2237,6 @@ void
|
||||
page_cur_delete_rec(
|
||||
/*================*/
|
||||
page_cur_t* cursor, /*!< in/out: a page cursor */
|
||||
const dict_index_t* index, /*!< in: record descriptor */
|
||||
const rec_offs* offsets,/*!< in: rec_get_offsets(
|
||||
cursor->rec, index) */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
@@ -2265,6 +2258,7 @@ page_cur_delete_rec(
|
||||
in the smallest user record, it cannot be used here either. */
|
||||
|
||||
current_rec = cursor->rec;
|
||||
const dict_index_t* const index = cursor->index;
|
||||
buf_block_t* const block = cursor->block;
|
||||
ut_ad(rec_offs_validate(current_rec, index, offsets));
|
||||
ut_ad(!!page_is_comp(block->page.frame)
|
||||
|
@@ -458,6 +458,7 @@ page_copy_rec_list_end_no_locks(
|
||||
rec_offs* offsets = offsets_;
|
||||
rec_offs_init(offsets_);
|
||||
|
||||
cur1.index = cur2.index = index;
|
||||
page_cur_position(rec, block, &cur1);
|
||||
|
||||
if (page_cur_is_before_first(&cur1) && !page_cur_move_to_next(&cur1)) {
|
||||
@@ -483,8 +484,8 @@ page_copy_rec_list_end_no_locks(
|
||||
rec_t* ins_rec;
|
||||
offsets = rec_get_offsets(cur1.rec, index, offsets, n_core,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
ins_rec = page_cur_insert_rec_low(&cur2, index,
|
||||
cur1.rec, offsets, mtr);
|
||||
ins_rec = page_cur_insert_rec_low(&cur2, cur1.rec, offsets,
|
||||
mtr);
|
||||
if (UNIV_UNLIKELY(!ins_rec || !page_cur_move_to_next(&cur1))) {
|
||||
err = DB_CORRUPTION;
|
||||
break;
|
||||
@@ -733,6 +734,7 @@ corrupted:
|
||||
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
|
||||
}
|
||||
|
||||
cur2.index = index;
|
||||
page_cur_position(ret, new_block, &cur2);
|
||||
|
||||
const ulint n_core = page_rec_is_leaf(rec) ? index->n_core_fields : 0;
|
||||
@@ -763,9 +765,8 @@ corrupted:
|
||||
offsets = rec_get_offsets(cur1.rec, index, offsets,
|
||||
n_core,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
cur2.rec = page_cur_insert_rec_low(&cur2, index,
|
||||
cur1.rec, offsets,
|
||||
mtr);
|
||||
cur2.rec = page_cur_insert_rec_low(&cur2, cur1.rec,
|
||||
offsets, mtr);
|
||||
if (UNIV_UNLIKELY(!cur2.rec
|
||||
|| !page_cur_move_to_next(&cur1))) {
|
||||
*err = DB_CORRUPTION;
|
||||
@@ -931,13 +932,14 @@ page_delete_rec_list_end(
|
||||
{
|
||||
page_cur_t cur;
|
||||
page_cur_position(rec, block, &cur);
|
||||
cur.index= index;
|
||||
offsets= rec_get_offsets(rec, index, offsets, n_core,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
rec= const_cast<rec_t*>(page_rec_get_next_low(rec, true));
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
ut_a(page_zip_validate(&block->page.zip, page, index));
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
page_cur_delete_rec(&cur, index, offsets, mtr);
|
||||
page_cur_delete_rec(&cur, offsets, mtr);
|
||||
}
|
||||
while (page_offset(rec) != PAGE_NEW_SUPREMUM);
|
||||
|
||||
@@ -1134,6 +1136,7 @@ page_delete_rec_list_start(
|
||||
return;
|
||||
}
|
||||
|
||||
cur1.index = index;
|
||||
page_cur_set_before_first(block, &cur1);
|
||||
if (UNIV_UNLIKELY(!page_cur_move_to_next(&cur1))) {
|
||||
ut_ad("corrupted page" == 0);
|
||||
@@ -1147,7 +1150,7 @@ page_delete_rec_list_start(
|
||||
offsets = rec_get_offsets(page_cur_get_rec(&cur1), index,
|
||||
offsets, n_core,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
page_cur_delete_rec(&cur1, index, offsets, mtr);
|
||||
page_cur_delete_rec(&cur1, offsets, mtr);
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
|
@@ -322,13 +322,9 @@ que_graph_free_recursive(
|
||||
case QUE_NODE_UPDATE:
|
||||
upd = static_cast<upd_node_t*>(node);
|
||||
|
||||
if (upd->in_mysql_interface) {
|
||||
|
||||
btr_pcur_free_for_mysql(upd->pcur);
|
||||
upd->in_mysql_interface = false;
|
||||
}
|
||||
|
||||
que_graph_free_recursive(upd->cascade_node);
|
||||
ut_free(upd->pcur->old_rec_buf);
|
||||
upd->pcur->old_rec_buf = NULL;
|
||||
|
||||
if (upd->cascade_heap) {
|
||||
mem_heap_free(upd->cascade_heap);
|
||||
|
@@ -611,7 +611,7 @@ rec_init_offsets(
|
||||
ulint i = 0;
|
||||
rec_offs offs;
|
||||
|
||||
/* This assertion was relaxed for the btr_cur_open_at_index_side()
|
||||
/* This assertion was relaxed for the btr_cur_t::open_leaf()
|
||||
call in btr_cur_instant_init_low(). We cannot invoke
|
||||
index->is_instant(), because the same assertion would fail there
|
||||
until btr_cur_instant_init_low() has invoked
|
||||
@@ -839,7 +839,7 @@ rec_get_offsets_func(
|
||||
bool alter_metadata = false;
|
||||
|
||||
ut_ad(index->n_core_fields >= n_core);
|
||||
/* This assertion was relaxed for the btr_cur_open_at_index_side()
|
||||
/* This assertion was relaxed for the btr_cur_t::open_leaf()
|
||||
call in btr_cur_instant_init_low(). We cannot invoke
|
||||
index->is_instant(), because the same assertion would fail there
|
||||
until btr_cur_instant_init_low() has invoked
|
||||
|
@@ -253,9 +253,10 @@ public:
|
||||
}
|
||||
|
||||
/** Position the cursor on the first user record. */
|
||||
rec_t* open(buf_block_t* block) noexcept
|
||||
rec_t* open(buf_block_t* block, const dict_index_t* index) noexcept
|
||||
MY_ATTRIBUTE((warn_unused_result))
|
||||
{
|
||||
m_cur.index = const_cast<dict_index_t*>(index);
|
||||
page_cur_set_before_first(block, &m_cur);
|
||||
return next();
|
||||
}
|
||||
@@ -285,10 +286,9 @@ public:
|
||||
|
||||
/** Remove the current record
|
||||
@return true on success */
|
||||
bool remove(
|
||||
const dict_index_t* index,
|
||||
rec_offs* offsets) UNIV_NOTHROW
|
||||
bool remove(rec_offs* offsets) UNIV_NOTHROW
|
||||
{
|
||||
const dict_index_t* const index = m_cur.index;
|
||||
ut_ad(page_is_leaf(m_cur.block->page.frame));
|
||||
/* We can't end up with an empty page unless it is root. */
|
||||
if (page_get_n_recs(m_cur.block->page.frame) <= 1) {
|
||||
@@ -311,7 +311,7 @@ public:
|
||||
page_zip, m_cur.block->page.frame, index));
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
|
||||
page_cur_delete_rec(&m_cur, index, offsets, &m_mtr);
|
||||
page_cur_delete_rec(&m_cur, offsets, &m_mtr);
|
||||
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
ut_a(!page_zip || page_zip_validate(
|
||||
@@ -1513,8 +1513,9 @@ inline bool IndexPurge::open() noexcept
|
||||
m_mtr.start();
|
||||
m_mtr.set_log_mode(MTR_LOG_NO_REDO);
|
||||
|
||||
if (btr_pcur_open_at_index_side(true, m_index, BTR_MODIFY_LEAF,
|
||||
&m_pcur, true, 0, &m_mtr) != DB_SUCCESS)
|
||||
btr_pcur_init(&m_pcur);
|
||||
|
||||
if (m_pcur.open_leaf(true, m_index, BTR_MODIFY_LEAF, &m_mtr) != DB_SUCCESS)
|
||||
return false;
|
||||
|
||||
rec_t *rec= page_rec_get_next(btr_pcur_get_rec(&m_pcur));
|
||||
@@ -1559,7 +1560,7 @@ dberr_t IndexPurge::next() noexcept
|
||||
return DB_CORRUPTION;
|
||||
}
|
||||
/* The following is based on btr_pcur_move_to_next_user_rec(). */
|
||||
m_pcur.old_stored = false;
|
||||
m_pcur.old_rec = nullptr;
|
||||
ut_ad(m_pcur.latch_mode == BTR_MODIFY_LEAF);
|
||||
do {
|
||||
if (btr_pcur_is_after_last_on_page(&m_pcur)) {
|
||||
@@ -1586,8 +1587,7 @@ tree structure may be changed during a pessimistic delete. */
|
||||
inline dberr_t IndexPurge::purge_pessimistic_delete() noexcept
|
||||
{
|
||||
dberr_t err;
|
||||
if (m_pcur.restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
|
||||
&m_mtr) != btr_pcur_t::CORRUPTED)
|
||||
if (m_pcur.restore_position(BTR_PURGE_TREE, &m_mtr) != btr_pcur_t::CORRUPTED)
|
||||
{
|
||||
ut_ad(rec_get_deleted_flag(btr_pcur_get_rec(&m_pcur),
|
||||
m_index->table->not_redundant()));
|
||||
@@ -1722,10 +1722,8 @@ re-organising the B+tree.
|
||||
@return true if purge succeeded */
|
||||
inline bool PageConverter::purge() UNIV_NOTHROW
|
||||
{
|
||||
const dict_index_t* index = m_index->m_srv_index;
|
||||
|
||||
/* We can't have a page that is empty and not root. */
|
||||
if (m_rec_iter.remove(index, m_offsets)) {
|
||||
if (m_rec_iter.remove(m_offsets)) {
|
||||
|
||||
++m_index->m_stats.m_n_purged;
|
||||
|
||||
@@ -1789,7 +1787,7 @@ PageConverter::update_records(
|
||||
|
||||
/* This will also position the cursor on the first user record. */
|
||||
|
||||
if (!m_rec_iter.open(block)) {
|
||||
if (!m_rec_iter.open(block, m_index->m_srv_index)) {
|
||||
return DB_CORRUPTION;
|
||||
}
|
||||
|
||||
@@ -2289,8 +2287,8 @@ row_import_set_sys_max_row_id(
|
||||
|
||||
mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
|
||||
|
||||
if (btr_pcur_open_at_index_side(false, index, BTR_SEARCH_LEAF,
|
||||
&pcur, true, 0, &mtr) == DB_SUCCESS) {
|
||||
if (pcur.open_leaf(false, index, BTR_SEARCH_LEAF, &mtr)
|
||||
== DB_SUCCESS) {
|
||||
rec = btr_pcur_move_to_prev_on_page(&pcur);
|
||||
|
||||
if (!rec) {
|
||||
|
@@ -174,7 +174,7 @@ dberr_t
|
||||
row_ins_sec_index_entry_by_modify(
|
||||
/*==============================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags */
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE,
|
||||
depending on whether mtr holds just a leaf
|
||||
latch or also a tree latch */
|
||||
btr_cur_t* cursor, /*!< in: B-tree cursor */
|
||||
@@ -194,8 +194,8 @@ row_ins_sec_index_entry_by_modify(
|
||||
|
||||
rec = btr_cur_get_rec(cursor);
|
||||
|
||||
ut_ad(!dict_index_is_clust(cursor->index));
|
||||
ut_ad(rec_offs_validate(rec, cursor->index, *offsets));
|
||||
ut_ad(!cursor->index()->is_clust());
|
||||
ut_ad(rec_offs_validate(rec, cursor->index(), *offsets));
|
||||
ut_ad(!entry->info_bits);
|
||||
|
||||
/* We know that in the alphabetical ordering, entry and rec are
|
||||
@@ -204,7 +204,7 @@ row_ins_sec_index_entry_by_modify(
|
||||
difference. */
|
||||
|
||||
update = row_upd_build_sec_rec_difference_binary(
|
||||
rec, cursor->index, *offsets, entry, heap);
|
||||
rec, cursor->index(), *offsets, entry, heap);
|
||||
|
||||
if (!rec_get_deleted_flag(rec, rec_offs_comp(*offsets))) {
|
||||
/* We should never insert in place of a record that
|
||||
@@ -218,8 +218,8 @@ row_ins_sec_index_entry_by_modify(
|
||||
returns. After that point, set_committed(true)
|
||||
would be invoked in commit_inplace_alter_table(). */
|
||||
ut_a(update->n_fields == 0);
|
||||
ut_a(!cursor->index->is_committed());
|
||||
ut_ad(!dict_index_is_online_ddl(cursor->index));
|
||||
ut_a(!cursor->index()->is_committed());
|
||||
ut_ad(!dict_index_is_online_ddl(cursor->index()));
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ row_ins_sec_index_entry_by_modify(
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ut_a(mode == BTR_MODIFY_TREE);
|
||||
ut_ad(mode == BTR_INSERT_TREE);
|
||||
if (buf_pool.running_out()) {
|
||||
|
||||
return(DB_LOCK_TABLE_FULL);
|
||||
@@ -288,15 +288,15 @@ row_ins_clust_index_entry_by_modify(
|
||||
dberr_t err = DB_SUCCESS;
|
||||
btr_cur_t* cursor = btr_pcur_get_btr_cur(pcur);
|
||||
TABLE* mysql_table = NULL;
|
||||
ut_ad(dict_index_is_clust(cursor->index));
|
||||
ut_ad(cursor->index()->is_clust());
|
||||
|
||||
rec = btr_cur_get_rec(cursor);
|
||||
|
||||
ut_ad(rec_get_deleted_flag(rec,
|
||||
dict_table_is_comp(cursor->index->table)));
|
||||
cursor->index()->table->not_redundant()));
|
||||
/* In delete-marked records, DB_TRX_ID must
|
||||
always refer to an existing undo log record. */
|
||||
ut_ad(rec_get_trx_id(rec, cursor->index));
|
||||
ut_ad(rec_get_trx_id(rec, cursor->index()));
|
||||
|
||||
/* Build an update vector containing all the fields to be modified;
|
||||
NOTE that this vector may NOT contain system columns trx_id or
|
||||
@@ -307,7 +307,7 @@ row_ins_clust_index_entry_by_modify(
|
||||
}
|
||||
|
||||
update = row_upd_build_difference_binary(
|
||||
cursor->index, entry, rec, NULL, true, true,
|
||||
cursor->index(), entry, rec, NULL, true, true,
|
||||
thr_get_trx(thr), heap, mysql_table, &err);
|
||||
if (err != DB_SUCCESS) {
|
||||
return(err);
|
||||
@@ -1115,7 +1115,7 @@ row_ins_foreign_check_on_constraint(
|
||||
goto nonstandard_exit_func;
|
||||
}
|
||||
|
||||
index = btr_pcur_get_btr_cur(pcur)->index;
|
||||
index = pcur->index();
|
||||
|
||||
ut_a(index == foreign->foreign_index);
|
||||
|
||||
@@ -1138,7 +1138,9 @@ row_ins_foreign_check_on_constraint(
|
||||
|
||||
ref = row_build_row_ref(ROW_COPY_POINTERS, index, rec,
|
||||
tmp_heap);
|
||||
err = btr_pcur_open_with_no_init(clust_index, ref,
|
||||
cascade->pcur->old_rec = nullptr;
|
||||
cascade->pcur->btr_cur.page_cur.index = clust_index;
|
||||
err = btr_pcur_open_with_no_init(ref,
|
||||
PAGE_CUR_LE, BTR_SEARCH_LEAF,
|
||||
cascade->pcur, mtr);
|
||||
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
|
||||
@@ -1622,9 +1624,9 @@ row_ins_check_foreign_constraint(
|
||||
n_fields_cmp = dtuple_get_n_fields_cmp(entry);
|
||||
|
||||
dtuple_set_n_fields_cmp(entry, foreign->n_fields);
|
||||
|
||||
err = btr_pcur_open(check_index, entry, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
pcur.btr_cur.page_cur.index = check_index;
|
||||
err = btr_pcur_open(entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, 0,
|
||||
&mtr);
|
||||
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
|
||||
goto end_scan;
|
||||
}
|
||||
@@ -2064,9 +2066,9 @@ row_ins_scan_sec_index_for_duplicate(
|
||||
|
||||
dtuple_set_n_fields_cmp(entry, n_unique);
|
||||
const auto allow_duplicates = thr_get_trx(thr)->duplicates;
|
||||
|
||||
dberr_t err = btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF,
|
||||
&pcur, mtr);
|
||||
pcur.btr_cur.page_cur.index = index;
|
||||
dberr_t err = btr_pcur_open(entry, PAGE_CUR_GE, BTR_SEARCH_LEAF,
|
||||
&pcur, 0, mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
goto end_scan;
|
||||
}
|
||||
@@ -2220,14 +2222,14 @@ row_ins_duplicate_error_in_clust_online(
|
||||
dberr_t err = DB_SUCCESS;
|
||||
const rec_t* rec = btr_cur_get_rec(cursor);
|
||||
|
||||
ut_ad(!cursor->index->is_instant());
|
||||
ut_ad(!cursor->index()->is_instant());
|
||||
|
||||
if (cursor->low_match >= n_uniq && !page_rec_is_infimum(rec)) {
|
||||
*offsets = rec_get_offsets(rec, cursor->index, *offsets,
|
||||
cursor->index->n_fields,
|
||||
*offsets = rec_get_offsets(rec, cursor->index(), *offsets,
|
||||
cursor->index()->n_fields,
|
||||
ULINT_UNDEFINED, heap);
|
||||
err = row_ins_duplicate_online(n_uniq, entry,
|
||||
rec, cursor->index, *offsets);
|
||||
rec, cursor->index(), *offsets);
|
||||
if (err != DB_SUCCESS) {
|
||||
return(err);
|
||||
}
|
||||
@@ -2238,11 +2240,11 @@ row_ins_duplicate_error_in_clust_online(
|
||||
}
|
||||
|
||||
if (cursor->up_match >= n_uniq && !page_rec_is_supremum(rec)) {
|
||||
*offsets = rec_get_offsets(rec, cursor->index, *offsets,
|
||||
cursor->index->n_fields,
|
||||
*offsets = rec_get_offsets(rec, cursor->index(), *offsets,
|
||||
cursor->index()->n_fields,
|
||||
ULINT_UNDEFINED, heap);
|
||||
err = row_ins_duplicate_online(n_uniq, entry,
|
||||
rec, cursor->index, *offsets);
|
||||
rec, cursor->index(), *offsets);
|
||||
}
|
||||
|
||||
return(err);
|
||||
@@ -2273,7 +2275,7 @@ row_ins_duplicate_error_in_clust(
|
||||
rec_offs* offsets = offsets_;
|
||||
rec_offs_init(offsets_);
|
||||
|
||||
ut_ad(dict_index_is_clust(cursor->index));
|
||||
ut_ad(cursor->index()->is_clust());
|
||||
|
||||
/* NOTE: For unique non-clustered indexes there may be any number
|
||||
of delete marked records with the same value for the non-clustered
|
||||
@@ -2288,15 +2290,17 @@ row_ins_duplicate_error_in_clust(
|
||||
user records on the leaf level. So, even if low_match would suggest
|
||||
that a duplicate key violation may occur, this may not be the case. */
|
||||
|
||||
n_unique = dict_index_get_n_unique(cursor->index);
|
||||
n_unique = dict_index_get_n_unique(cursor->index());
|
||||
|
||||
if (cursor->low_match >= n_unique) {
|
||||
|
||||
rec = btr_cur_get_rec(cursor);
|
||||
|
||||
if (!page_rec_is_infimum(rec)) {
|
||||
offsets = rec_get_offsets(rec, cursor->index, offsets,
|
||||
cursor->index->n_core_fields,
|
||||
offsets = rec_get_offsets(rec, cursor->index(),
|
||||
offsets,
|
||||
cursor->index()
|
||||
->n_core_fields,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
/* We set a lock on the possible duplicate: this
|
||||
@@ -2317,13 +2321,13 @@ row_ins_duplicate_error_in_clust(
|
||||
err = row_ins_set_exclusive_rec_lock(
|
||||
LOCK_REC_NOT_GAP,
|
||||
btr_cur_get_block(cursor),
|
||||
rec, cursor->index, offsets, thr);
|
||||
rec, cursor->index(), offsets, thr);
|
||||
} else {
|
||||
|
||||
err = row_ins_set_shared_rec_lock(
|
||||
LOCK_REC_NOT_GAP,
|
||||
btr_cur_get_block(cursor), rec,
|
||||
cursor->index, offsets, thr);
|
||||
cursor->index(), offsets, thr);
|
||||
}
|
||||
|
||||
switch (err) {
|
||||
@@ -2335,11 +2339,11 @@ row_ins_duplicate_error_in_clust(
|
||||
}
|
||||
|
||||
if (row_ins_dupl_error_with_rec(
|
||||
rec, entry, cursor->index, offsets)) {
|
||||
rec, entry, cursor->index(), offsets)) {
|
||||
duplicate:
|
||||
trx->error_info = cursor->index;
|
||||
trx->error_info = cursor->index();
|
||||
err = DB_DUPLICATE_KEY;
|
||||
if (cursor->index->table->versioned()
|
||||
if (cursor->index()->table->versioned()
|
||||
&& entry->vers_history_row())
|
||||
{
|
||||
ulint trx_id_len;
|
||||
@@ -2363,8 +2367,10 @@ duplicate:
|
||||
rec = page_rec_get_next(btr_cur_get_rec(cursor));
|
||||
|
||||
if (rec && !page_rec_is_supremum(rec)) {
|
||||
offsets = rec_get_offsets(rec, cursor->index, offsets,
|
||||
cursor->index->n_core_fields,
|
||||
offsets = rec_get_offsets(rec, cursor->index(),
|
||||
offsets,
|
||||
cursor->index()
|
||||
->n_core_fields,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
if (trx->duplicates) {
|
||||
@@ -2377,13 +2383,13 @@ duplicate:
|
||||
err = row_ins_set_exclusive_rec_lock(
|
||||
LOCK_REC_NOT_GAP,
|
||||
btr_cur_get_block(cursor),
|
||||
rec, cursor->index, offsets, thr);
|
||||
rec, cursor->index(), offsets, thr);
|
||||
} else {
|
||||
|
||||
err = row_ins_set_shared_rec_lock(
|
||||
LOCK_REC_NOT_GAP,
|
||||
btr_cur_get_block(cursor),
|
||||
rec, cursor->index, offsets, thr);
|
||||
rec, cursor->index(), offsets, thr);
|
||||
}
|
||||
|
||||
switch (err) {
|
||||
@@ -2394,7 +2400,7 @@ duplicate:
|
||||
/* fall through */
|
||||
case DB_SUCCESS:
|
||||
if (row_ins_dupl_error_with_rec(
|
||||
rec, entry, cursor->index,
|
||||
rec, entry, cursor->index(),
|
||||
offsets)) {
|
||||
goto duplicate;
|
||||
}
|
||||
@@ -2436,7 +2442,7 @@ row_ins_must_modify_rec(
|
||||
and a secondary index node pointer contains all index fields. */
|
||||
|
||||
return(cursor->low_match
|
||||
>= dict_index_get_n_unique_in_tree(cursor->index)
|
||||
>= dict_index_get_n_unique_in_tree(cursor->index())
|
||||
&& !page_rec_is_infimum(btr_cur_get_rec(cursor)));
|
||||
}
|
||||
|
||||
@@ -2465,6 +2471,7 @@ row_ins_index_entry_big_rec(
|
||||
btr_pcur_t pcur;
|
||||
rec_t* rec;
|
||||
|
||||
pcur.btr_cur.page_cur.index = index;
|
||||
ut_ad(index->is_primary());
|
||||
|
||||
DEBUG_SYNC_C_IF_THD(thd, "before_row_ins_extern_latch");
|
||||
@@ -2476,8 +2483,8 @@ row_ins_index_entry_big_rec(
|
||||
index->set_modified(mtr);
|
||||
}
|
||||
|
||||
dberr_t error = btr_pcur_open(index, entry, PAGE_CUR_LE,
|
||||
BTR_MODIFY_TREE, &pcur, &mtr);
|
||||
dberr_t error = btr_pcur_open(entry, PAGE_CUR_LE,
|
||||
BTR_MODIFY_TREE, &pcur, 0, &mtr);
|
||||
if (error != DB_SUCCESS) {
|
||||
return error;
|
||||
}
|
||||
@@ -2525,7 +2532,7 @@ dberr_t
|
||||
row_ins_clust_index_entry_low(
|
||||
/*==========================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags */
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
|
||||
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
|
||||
depending on whether we wish optimistic or
|
||||
pessimistic descent down the index tree */
|
||||
dict_index_t* index, /*!< in: clustered index */
|
||||
@@ -2578,7 +2585,7 @@ row_ins_clust_index_entry_low(
|
||||
} else {
|
||||
if (mode == BTR_MODIFY_LEAF
|
||||
&& dict_index_is_online_ddl(index)) {
|
||||
mode = BTR_MODIFY_LEAF_ALREADY_S_LATCHED;
|
||||
mode = BTR_MODIFY_LEAF_ALREADY_LATCHED;
|
||||
mtr_s_lock_index(index, &mtr);
|
||||
}
|
||||
|
||||
@@ -2603,8 +2610,8 @@ row_ins_clust_index_entry_low(
|
||||
/* Note that we use PAGE_CUR_LE as the search mode, because then
|
||||
the function will return in both low_match and up_match of the
|
||||
cursor sensible values */
|
||||
err = btr_pcur_open_low(index, 0, entry, PAGE_CUR_LE, mode, &pcur,
|
||||
auto_inc, &mtr);
|
||||
pcur.btr_cur.page_cur.index = index;
|
||||
err = btr_pcur_open(entry, PAGE_CUR_LE, mode, &pcur, auto_inc, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
index->table->file_unreadable = true;
|
||||
commit_exit:
|
||||
@@ -2732,7 +2739,7 @@ skip_bulk_insert:
|
||||
/* fall through */
|
||||
case DB_SUCCESS_LOCKED_REC:
|
||||
case DB_DUPLICATE_KEY:
|
||||
trx->error_info = cursor->index;
|
||||
trx->error_info = cursor->index();
|
||||
}
|
||||
} else {
|
||||
/* Note that the following may return also
|
||||
@@ -2769,8 +2776,8 @@ do_insert:
|
||||
rec_t* insert_rec;
|
||||
|
||||
if (mode != BTR_MODIFY_TREE) {
|
||||
ut_ad((mode & ulint(~BTR_ALREADY_S_LATCHED))
|
||||
== BTR_MODIFY_LEAF);
|
||||
ut_ad(mode == BTR_MODIFY_LEAF ||
|
||||
mode == BTR_MODIFY_LEAF_ALREADY_LATCHED);
|
||||
err = btr_cur_optimistic_insert(
|
||||
flags, cursor, &offsets, &offsets_heap,
|
||||
entry, &insert_rec, &big_rec,
|
||||
@@ -2846,13 +2853,13 @@ same fields is found, the other record is necessarily marked deleted.
|
||||
It is then unmarked. Otherwise, the entry is just inserted to the index.
|
||||
@retval DB_SUCCESS on success
|
||||
@retval DB_LOCK_WAIT on lock wait when !(flags & BTR_NO_LOCKING_FLAG)
|
||||
@retval DB_FAIL if retry with BTR_MODIFY_TREE is needed
|
||||
@retval DB_FAIL if retry with BTR_INSERT_TREE is needed
|
||||
@return error code */
|
||||
dberr_t
|
||||
row_ins_sec_index_entry_low(
|
||||
/*========================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags */
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
|
||||
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE,
|
||||
depending on whether we wish optimistic or
|
||||
pessimistic descent down the index tree */
|
||||
dict_index_t* index, /*!< in: secondary index */
|
||||
@@ -2867,7 +2874,7 @@ row_ins_sec_index_entry_low(
|
||||
DBUG_ENTER("row_ins_sec_index_entry_low");
|
||||
|
||||
btr_cur_t cursor;
|
||||
ulint search_mode = mode;
|
||||
btr_latch_mode search_mode = mode;
|
||||
dberr_t err;
|
||||
ulint n_unique;
|
||||
mtr_t mtr;
|
||||
@@ -2877,10 +2884,11 @@ row_ins_sec_index_entry_low(
|
||||
rtr_info_t rtr_info;
|
||||
|
||||
ut_ad(!dict_index_is_clust(index));
|
||||
ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_MODIFY_TREE);
|
||||
ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_INSERT_TREE);
|
||||
|
||||
cursor.thr = thr;
|
||||
cursor.rtr_info = NULL;
|
||||
cursor.page_cur.index = index;
|
||||
ut_ad(thr_get_trx(thr)->id != 0);
|
||||
|
||||
mtr.start();
|
||||
@@ -2892,24 +2900,19 @@ row_ins_sec_index_entry_low(
|
||||
mtr.set_log_mode(MTR_LOG_NO_REDO);
|
||||
} else {
|
||||
index->set_modified(mtr);
|
||||
if (!dict_index_is_spatial(index)) {
|
||||
search_mode |= BTR_INSERT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that we use PAGE_CUR_LE as the search mode, because then
|
||||
the function will return in both low_match and up_match of the
|
||||
cursor sensible values */
|
||||
|
||||
if (dict_index_is_spatial(index)) {
|
||||
cursor.index = index;
|
||||
if (index->is_spatial()) {
|
||||
rtr_init_rtr_info(&rtr_info, false, &cursor, index, false);
|
||||
rtr_info_update_btr(&cursor, &rtr_info);
|
||||
|
||||
err = btr_cur_search_to_nth_level(
|
||||
index, 0, entry, PAGE_CUR_RTREE_INSERT,
|
||||
search_mode,
|
||||
&cursor, &mtr);
|
||||
err = btr_cur_search_to_nth_level(0, entry,
|
||||
PAGE_CUR_RTREE_INSERT,
|
||||
search_mode, &cursor, &mtr);
|
||||
|
||||
if (err == DB_SUCCESS && search_mode == BTR_MODIFY_LEAF
|
||||
&& rtr_info.mbr_adj) {
|
||||
@@ -2926,9 +2929,8 @@ row_ins_sec_index_entry_low(
|
||||
index->set_modified(mtr);
|
||||
}
|
||||
err = btr_cur_search_to_nth_level(
|
||||
index, 0, entry, PAGE_CUR_RTREE_INSERT,
|
||||
search_mode,
|
||||
&cursor, &mtr);
|
||||
0, entry, PAGE_CUR_RTREE_INSERT,
|
||||
search_mode, &cursor, &mtr);
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF(
|
||||
@@ -2936,14 +2938,16 @@ row_ins_sec_index_entry_low(
|
||||
goto func_exit;});
|
||||
|
||||
} else {
|
||||
if (!thr_get_trx(thr)->check_unique_secondary) {
|
||||
search_mode |= BTR_IGNORE_SEC_UNIQUE;
|
||||
if (!index->table->is_temporary()) {
|
||||
search_mode = btr_latch_mode(
|
||||
search_mode
|
||||
| (thr_get_trx(thr)->check_unique_secondary
|
||||
? BTR_INSERT | BTR_IGNORE_SEC_UNIQUE
|
||||
: BTR_INSERT));
|
||||
}
|
||||
|
||||
err = btr_cur_search_to_nth_level(
|
||||
index, 0, entry, PAGE_CUR_LE,
|
||||
search_mode,
|
||||
&cursor, &mtr);
|
||||
err = btr_cur_search_to_nth_level(0, entry, PAGE_CUR_LE,
|
||||
search_mode, &cursor, &mtr);
|
||||
}
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
@@ -3018,11 +3022,12 @@ row_ins_sec_index_entry_low(
|
||||
locked with s-locks the necessary records to
|
||||
prevent any insertion of a duplicate by another
|
||||
transaction. Let us now reposition the cursor and
|
||||
continue the insertion. */
|
||||
continue the insertion (bypassing the change buffer). */
|
||||
err = btr_cur_search_to_nth_level(
|
||||
index, 0, entry, PAGE_CUR_LE,
|
||||
(search_mode
|
||||
& ~(BTR_INSERT | BTR_IGNORE_SEC_UNIQUE)),
|
||||
0, entry, PAGE_CUR_LE,
|
||||
btr_latch_mode(search_mode
|
||||
& ~(BTR_INSERT
|
||||
| BTR_IGNORE_SEC_UNIQUE)),
|
||||
&cursor, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
goto func_exit;
|
||||
@@ -3061,7 +3066,6 @@ row_ins_sec_index_entry_low(
|
||||
err = rtr_ins_enlarge_mbr(&cursor, &mtr);
|
||||
}
|
||||
} else {
|
||||
ut_ad(mode == BTR_MODIFY_TREE);
|
||||
if (buf_pool.running_out()) {
|
||||
err = DB_LOCK_TABLE_FULL;
|
||||
goto func_exit;
|
||||
@@ -3264,7 +3268,7 @@ row_ins_sec_index_entry(
|
||||
log_free_check();
|
||||
|
||||
err = row_ins_sec_index_entry_low(
|
||||
flags, BTR_MODIFY_TREE, index,
|
||||
flags, BTR_INSERT_TREE, index,
|
||||
offsets_heap, heap, entry, 0, thr);
|
||||
}
|
||||
|
||||
|
@@ -1583,7 +1583,7 @@ row_log_table_apply_insert_low(
|
||||
|
||||
entry = row_build_index_entry(row, NULL, index, heap);
|
||||
error = row_ins_sec_index_entry_low(
|
||||
flags, BTR_MODIFY_TREE,
|
||||
flags, BTR_INSERT_TREE,
|
||||
index, offsets_heap, heap, entry,
|
||||
thr_get_trx(thr)->id, thr);
|
||||
|
||||
@@ -1658,7 +1658,7 @@ row_log_table_apply_delete_low(
|
||||
dberr_t error;
|
||||
row_ext_t* ext;
|
||||
dtuple_t* row;
|
||||
dict_index_t* index = btr_pcur_get_btr_cur(pcur)->index;
|
||||
dict_index_t* index = pcur->index();
|
||||
|
||||
ut_ad(dict_index_is_clust(index));
|
||||
|
||||
@@ -1695,9 +1695,9 @@ err_exit:
|
||||
row, ext, index, heap);
|
||||
mtr->start();
|
||||
index->set_modified(*mtr);
|
||||
error = btr_pcur_open(index, entry, PAGE_CUR_LE,
|
||||
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
|
||||
pcur, mtr);
|
||||
pcur->btr_cur.page_cur.index = index;
|
||||
error = btr_pcur_open(entry, PAGE_CUR_LE,
|
||||
BTR_PURGE_TREE, pcur, 0, mtr);
|
||||
if (error) {
|
||||
goto err_exit;
|
||||
}
|
||||
@@ -1761,6 +1761,7 @@ row_log_table_apply_delete(
|
||||
btr_pcur_t pcur;
|
||||
rec_offs* offsets;
|
||||
|
||||
pcur.btr_cur.page_cur.index = index;
|
||||
ut_ad(rec_offs_n_fields(moffsets) == index->first_user_field());
|
||||
ut_ad(!rec_offs_any_extern(moffsets));
|
||||
|
||||
@@ -1779,9 +1780,8 @@ row_log_table_apply_delete(
|
||||
|
||||
mtr_start(&mtr);
|
||||
index->set_modified(mtr);
|
||||
dberr_t err = btr_pcur_open(index, old_pk, PAGE_CUR_LE,
|
||||
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
|
||||
&pcur, &mtr);
|
||||
dberr_t err = btr_pcur_open(old_pk, PAGE_CUR_LE,
|
||||
BTR_PURGE_TREE, &pcur, 0, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
goto all_done;
|
||||
}
|
||||
@@ -1893,6 +1893,8 @@ row_log_table_apply_update(
|
||||
dberr_t error;
|
||||
ulint n_index = 0;
|
||||
|
||||
pcur.btr_cur.page_cur.index = index;
|
||||
|
||||
ut_ad(dtuple_get_n_fields_cmp(old_pk)
|
||||
== dict_index_get_n_unique(index));
|
||||
ut_ad(dtuple_get_n_fields(old_pk) - (log->same_pk ? 0 : 2)
|
||||
@@ -1915,8 +1917,8 @@ row_log_table_apply_update(
|
||||
|
||||
mtr.start();
|
||||
index->set_modified(mtr);
|
||||
error = btr_pcur_open(index, old_pk, PAGE_CUR_LE,
|
||||
BTR_MODIFY_TREE, &pcur, &mtr);
|
||||
error = btr_pcur_open(old_pk, PAGE_CUR_LE,
|
||||
BTR_MODIFY_TREE, &pcur, 0, &mtr);
|
||||
if (error != DB_SUCCESS) {
|
||||
func_exit:
|
||||
mtr.commit();
|
||||
@@ -2061,7 +2063,7 @@ func_exit_committed:
|
||||
|
||||
for (n_index += index->type != DICT_CLUSTERED;
|
||||
(index = dict_table_get_next_index(index)); n_index++) {
|
||||
if (index->type & DICT_FTS) {
|
||||
if (!index->is_btree()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2089,9 +2091,10 @@ func_exit_committed:
|
||||
|
||||
mtr.start();
|
||||
index->set_modified(mtr);
|
||||
pcur.btr_cur.page_cur.index = index;
|
||||
|
||||
if (ROW_FOUND != row_search_index_entry(
|
||||
index, entry, BTR_MODIFY_TREE, &pcur, &mtr)) {
|
||||
entry, BTR_MODIFY_TREE, &pcur, &mtr)) {
|
||||
ut_ad(0);
|
||||
error = DB_CORRUPTION;
|
||||
break;
|
||||
@@ -2111,7 +2114,7 @@ func_exit_committed:
|
||||
error = row_ins_sec_index_entry_low(
|
||||
BTR_CREATE_FLAG | BTR_NO_LOCKING_FLAG
|
||||
| BTR_NO_UNDO_LOG_FLAG | BTR_KEEP_SYS_FLAG,
|
||||
BTR_MODIFY_TREE, index, offsets_heap, heap,
|
||||
BTR_INSERT_TREE, index, offsets_heap, heap,
|
||||
entry, thr_get_trx(thr)->id, thr);
|
||||
|
||||
/* Report correct index name for duplicate key error. */
|
||||
@@ -3071,13 +3074,14 @@ row_log_apply_op_low(
|
||||
|
||||
mtr_start(&mtr);
|
||||
index->set_modified(mtr);
|
||||
cursor.page_cur.index = index;
|
||||
|
||||
/* We perform the pessimistic variant of the operations if we
|
||||
already hold index->lock exclusively. First, search the
|
||||
record. The operation may already have been performed,
|
||||
depending on when the row in the clustered index was
|
||||
scanned. */
|
||||
*error = btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
|
||||
*error = btr_cur_search_to_nth_level(0, entry, PAGE_CUR_LE,
|
||||
has_index_lock
|
||||
? BTR_MODIFY_TREE
|
||||
: BTR_MODIFY_LEAF,
|
||||
@@ -3132,7 +3136,7 @@ row_log_apply_op_low(
|
||||
mtr_start(&mtr);
|
||||
index->set_modified(mtr);
|
||||
*error = btr_cur_search_to_nth_level(
|
||||
index, 0, entry, PAGE_CUR_LE,
|
||||
0, entry, PAGE_CUR_LE,
|
||||
BTR_MODIFY_TREE, &cursor, &mtr);
|
||||
if (UNIV_UNLIKELY(*error != DB_SUCCESS)) {
|
||||
goto func_exit;
|
||||
@@ -3236,7 +3240,7 @@ insert_the_rec:
|
||||
mtr_start(&mtr);
|
||||
index->set_modified(mtr);
|
||||
*error = btr_cur_search_to_nth_level(
|
||||
index, 0, entry, PAGE_CUR_LE,
|
||||
0, entry, PAGE_CUR_LE,
|
||||
BTR_MODIFY_TREE, &cursor, &mtr);
|
||||
if (*error != DB_SUCCESS) {
|
||||
break;
|
||||
@@ -3951,8 +3955,8 @@ void UndorecApplier::log_insert(const dtuple_t &tuple,
|
||||
}
|
||||
|
||||
bool success= true;
|
||||
dict_index_t *index= dict_table_get_next_index(clust_index);
|
||||
while (index)
|
||||
for (dict_index_t *index= clust_index;
|
||||
(index= dict_table_get_next_index(index)) != nullptr; )
|
||||
{
|
||||
index->lock.s_lock(SRW_LOCK_CALL);
|
||||
if (index->online_log &&
|
||||
@@ -3971,7 +3975,6 @@ void UndorecApplier::log_insert(const dtuple_t &tuple,
|
||||
row_log_mark_other_online_index_abort(index->table);
|
||||
return;
|
||||
}
|
||||
index= dict_table_get_next_index(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -145,13 +145,13 @@ public:
|
||||
mtr.start();
|
||||
index->set_modified(mtr);
|
||||
|
||||
ins_cur.index = index;
|
||||
ins_cur.page_cur.index = index;
|
||||
rtr_init_rtr_info(&rtr_info, false, &ins_cur, index,
|
||||
false);
|
||||
rtr_info_update_btr(&ins_cur, &rtr_info);
|
||||
|
||||
error = btr_cur_search_to_nth_level(
|
||||
index, 0, dtuple, PAGE_CUR_RTREE_INSERT,
|
||||
0, dtuple, PAGE_CUR_RTREE_INSERT,
|
||||
BTR_MODIFY_LEAF, &ins_cur, &mtr);
|
||||
|
||||
/* It need to update MBR in parent entry,
|
||||
@@ -165,7 +165,7 @@ public:
|
||||
mtr.start();
|
||||
index->set_modified(mtr);
|
||||
error = btr_cur_search_to_nth_level(
|
||||
index, 0, dtuple,
|
||||
0, dtuple,
|
||||
PAGE_CUR_RTREE_INSERT,
|
||||
BTR_MODIFY_TREE, &ins_cur, &mtr);
|
||||
}
|
||||
@@ -190,7 +190,7 @@ public:
|
||||
|
||||
rtr_info_update_btr(&ins_cur, &rtr_info);
|
||||
error = btr_cur_search_to_nth_level(
|
||||
index, 0, dtuple,
|
||||
0, dtuple,
|
||||
PAGE_CUR_RTREE_INSERT,
|
||||
BTR_MODIFY_TREE,
|
||||
&ins_cur, &mtr);
|
||||
@@ -1999,8 +1999,7 @@ row_merge_read_clustered_index(
|
||||
? col_map[old_trx_id_col] : old_trx_id_col;
|
||||
uint64_t n_rows = 0;
|
||||
|
||||
err = btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF,
|
||||
&pcur, true, 0, &mtr);
|
||||
err = pcur.open_leaf(true, clust_index, BTR_SEARCH_LEAF, &mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
err_exit:
|
||||
trx->error_key_num = 0;
|
||||
@@ -2232,13 +2231,15 @@ end_of_index:
|
||||
if (!block) {
|
||||
goto err_exit;
|
||||
}
|
||||
btr_leaf_page_release(page_cur_get_block(cur),
|
||||
BTR_SEARCH_LEAF, &mtr);
|
||||
|
||||
page_cur_set_before_first(block, cur);
|
||||
if (!page_cur_move_to_next(cur)
|
||||
|| page_cur_is_after_last(cur)) {
|
||||
goto corrupted_rec;
|
||||
}
|
||||
|
||||
const auto s = mtr.get_savepoint();
|
||||
mtr.rollback_to_savepoint(s - 2, s - 1);
|
||||
}
|
||||
} else {
|
||||
mem_heap_empty(row_heap);
|
||||
|
@@ -1456,11 +1456,8 @@ row_create_update_node_for_mysql(
|
||||
|
||||
node->in_mysql_interface = true;
|
||||
node->is_delete = NO_DELETE;
|
||||
node->searched_update = FALSE;
|
||||
node->select = NULL;
|
||||
node->pcur = btr_pcur_create_for_mysql();
|
||||
|
||||
DBUG_PRINT("info", ("node: %p, pcur: %p", node, node->pcur));
|
||||
node->pcur = new (mem_heap_alloc(heap, sizeof(btr_pcur_t)))
|
||||
btr_pcur_t();
|
||||
|
||||
node->table = table;
|
||||
|
||||
@@ -1472,10 +1469,6 @@ row_create_update_node_for_mysql(
|
||||
UT_LIST_INIT(node->columns, &sym_node_t::col_var_list);
|
||||
|
||||
node->has_clust_rec_x_lock = TRUE;
|
||||
node->cmpl_info = 0;
|
||||
|
||||
node->table_sym = NULL;
|
||||
node->col_assign_list = NULL;
|
||||
|
||||
DBUG_RETURN(node);
|
||||
}
|
||||
@@ -1650,8 +1643,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt)
|
||||
clust_index = dict_table_get_first_index(table);
|
||||
|
||||
btr_pcur_copy_stored_position(node->pcur,
|
||||
prebuilt->pcur->btr_cur.index
|
||||
== clust_index
|
||||
prebuilt->pcur->index() == clust_index
|
||||
? prebuilt->pcur
|
||||
: prebuilt->clust_pcur);
|
||||
|
||||
@@ -1804,7 +1796,7 @@ row_unlock_for_mysql(
|
||||
}
|
||||
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
index = btr_pcur_get_btr_cur(pcur)->index;
|
||||
index = pcur->index();
|
||||
|
||||
/* If the record has been modified by this
|
||||
transaction, do not unlock it. */
|
||||
|
@@ -67,7 +67,7 @@ static
|
||||
ibool
|
||||
row_purge_reposition_pcur(
|
||||
/*======================*/
|
||||
ulint mode, /*!< in: latching mode */
|
||||
btr_latch_mode mode, /*!< in: latching mode */
|
||||
purge_node_t* node, /*!< in: row purge node */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
@@ -104,7 +104,7 @@ bool
|
||||
row_purge_remove_clust_if_poss_low(
|
||||
/*===============================*/
|
||||
purge_node_t* node, /*!< in/out: row purge node */
|
||||
ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
|
||||
btr_latch_mode mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
|
||||
{
|
||||
dict_index_t* index = dict_table_get_first_index(node->table);
|
||||
table_id_t table_id = 0;
|
||||
@@ -216,7 +216,7 @@ close_and_exit:
|
||||
btr_pcur_get_btr_cur(&node->pcur), 0, &mtr);
|
||||
} else {
|
||||
dberr_t err;
|
||||
ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE));
|
||||
ut_ad(mode == BTR_PURGE_TREE);
|
||||
btr_cur_pessimistic_delete(
|
||||
&err, FALSE, btr_pcur_get_btr_cur(&node->pcur), 0,
|
||||
false, &mtr);
|
||||
@@ -257,8 +257,7 @@ row_purge_remove_clust_if_poss(
|
||||
for (ulint n_tries = 0;
|
||||
n_tries < BTR_CUR_RETRY_DELETE_N_TIMES;
|
||||
n_tries++) {
|
||||
if (row_purge_remove_clust_if_poss_low(
|
||||
node, BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE)) {
|
||||
if (row_purge_remove_clust_if_poss_low(node, BTR_PURGE_TREE)) {
|
||||
return(true);
|
||||
}
|
||||
|
||||
@@ -348,10 +347,9 @@ row_purge_remove_sec_if_poss_tree(
|
||||
log_free_check();
|
||||
mtr.start();
|
||||
index->set_modified(mtr);
|
||||
pcur.btr_cur.page_cur.index = index;
|
||||
|
||||
search_result = row_search_index_entry(
|
||||
index, entry,
|
||||
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
|
||||
search_result = row_search_index_entry(entry, BTR_PURGE_TREE,
|
||||
&pcur, &mtr);
|
||||
|
||||
switch (search_result) {
|
||||
@@ -455,6 +453,7 @@ row_purge_remove_sec_if_poss_leaf(
|
||||
virtual index. */
|
||||
mode = (index->type & (DICT_SPATIAL | DICT_VIRTUAL))
|
||||
? BTR_MODIFY_LEAF : BTR_PURGE_LEAF;
|
||||
pcur.btr_cur.page_cur.index = index;
|
||||
|
||||
/* Set the purge node for the call to row_purge_poss_sec(). */
|
||||
pcur.btr_cur.purge_node = node;
|
||||
@@ -462,7 +461,7 @@ row_purge_remove_sec_if_poss_leaf(
|
||||
pcur.btr_cur.thr = NULL;
|
||||
index->lock.u_lock(SRW_LOCK_CALL);
|
||||
search_result = row_search_index_entry(
|
||||
index, entry, mode, &pcur, &mtr);
|
||||
entry, mode, &pcur, &mtr);
|
||||
index->lock.u_unlock();
|
||||
} else {
|
||||
/* Set the query thread, so that ibuf_insert_low() will be
|
||||
@@ -470,7 +469,7 @@ row_purge_remove_sec_if_poss_leaf(
|
||||
pcur.btr_cur.thr = static_cast<que_thr_t*>(
|
||||
que_node_get_parent(node));
|
||||
search_result = row_search_index_entry(
|
||||
index, entry, mode, &pcur, &mtr);
|
||||
entry, mode, &pcur, &mtr);
|
||||
}
|
||||
|
||||
switch (search_result) {
|
||||
@@ -1343,11 +1342,11 @@ purge_node_t::validate_pcur()
|
||||
return(true);
|
||||
}
|
||||
|
||||
if (!pcur.old_stored) {
|
||||
if (!pcur.old_rec) {
|
||||
return(true);
|
||||
}
|
||||
|
||||
dict_index_t* clust_index = pcur.btr_cur.index;
|
||||
dict_index_t* clust_index = pcur.index();
|
||||
|
||||
rec_offs* offsets = rec_get_offsets(
|
||||
pcur.old_rec, clust_index, NULL, pcur.old_n_core_fields,
|
||||
|
@@ -1183,32 +1183,28 @@ row_build_row_ref_in_tuple(
|
||||
/***************************************************************//**
|
||||
Searches the clustered index record for a row, if we have the row reference.
|
||||
@return TRUE if found */
|
||||
ibool
|
||||
bool
|
||||
row_search_on_row_ref(
|
||||
/*==================*/
|
||||
btr_pcur_t* pcur, /*!< out: persistent cursor, which must
|
||||
be closed by the caller */
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
|
||||
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
|
||||
const dict_table_t* table, /*!< in: table */
|
||||
const dtuple_t* ref, /*!< in: row reference */
|
||||
mtr_t* mtr) /*!< in/out: mtr */
|
||||
{
|
||||
ulint low_match;
|
||||
rec_t* rec;
|
||||
dict_index_t* index;
|
||||
|
||||
ut_ad(dtuple_check_typed(ref));
|
||||
|
||||
index = dict_table_get_first_index(table);
|
||||
dict_index_t *index = dict_table_get_first_index(table);
|
||||
btr_pcur_init(pcur);
|
||||
pcur->btr_cur.page_cur.index = index;
|
||||
|
||||
if (UNIV_UNLIKELY(ref->info_bits != 0)) {
|
||||
ut_ad(ref->is_metadata());
|
||||
ut_ad(ref->n_fields <= index->n_uniq);
|
||||
if (btr_pcur_open_at_index_side(
|
||||
true, index, mode, pcur, true, 0, mtr)
|
||||
!= DB_SUCCESS
|
||||
if (pcur->open_leaf(true, index, mode, mtr) != DB_SUCCESS
|
||||
|| !btr_pcur_move_to_next_user_rec(pcur, mtr)) {
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
/* We do not necessarily have index->is_instant() here,
|
||||
because we could be executing a rollback of an
|
||||
@@ -1220,27 +1216,14 @@ row_search_on_row_ref(
|
||||
& REC_INFO_MIN_REC_FLAG;
|
||||
} else {
|
||||
ut_a(ref->n_fields == index->n_uniq);
|
||||
if (btr_pcur_open(index, ref, PAGE_CUR_LE, mode, pcur, mtr)
|
||||
if (btr_pcur_open(ref, PAGE_CUR_LE, mode, pcur, 0, mtr)
|
||||
!= DB_SUCCESS) {
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
low_match = btr_pcur_get_low_match(pcur);
|
||||
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
|
||||
if (page_rec_is_infimum(rec)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (low_match != dtuple_get_n_fields(ref)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
return !page_rec_is_infimum(btr_pcur_get_rec(pcur))
|
||||
&& btr_pcur_get_low_match(pcur) == dtuple_get_n_fields(ref);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
@@ -1250,7 +1233,7 @@ on the secondary index record are preserved.
|
||||
rec_t*
|
||||
row_get_clust_rec(
|
||||
/*==============*/
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
|
||||
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
|
||||
const rec_t* rec, /*!< in: record in a secondary index */
|
||||
dict_index_t* index, /*!< in: secondary index */
|
||||
dict_index_t** clust_index,/*!< out: clustered index */
|
||||
@@ -1283,9 +1266,8 @@ Searches an index record.
|
||||
enum row_search_result
|
||||
row_search_index_entry(
|
||||
/*===================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const dtuple_t* entry, /*!< in: index entry */
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
|
||||
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
|
||||
btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must
|
||||
be closed by the caller */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
@@ -1296,12 +1278,12 @@ row_search_index_entry(
|
||||
|
||||
ut_ad(dtuple_check_typed(entry));
|
||||
|
||||
if (index->is_spatial()) {
|
||||
if (rtr_pcur_open(index, entry, mode, pcur, mtr)) {
|
||||
if (pcur->index()->is_spatial()) {
|
||||
if (rtr_pcur_open(pcur->index(), entry, mode, pcur, mtr)) {
|
||||
return ROW_NOT_FOUND;
|
||||
}
|
||||
} else {
|
||||
if (btr_pcur_open(index, entry, PAGE_CUR_LE, mode, pcur, mtr)
|
||||
if (btr_pcur_open(entry, PAGE_CUR_LE, mode, pcur, 0, mtr)
|
||||
!= DB_SUCCESS) {
|
||||
return ROW_NOT_FOUND;
|
||||
}
|
||||
@@ -1310,7 +1292,7 @@ row_search_index_entry(
|
||||
switch (btr_pcur_get_btr_cur(pcur)->flag) {
|
||||
case BTR_CUR_DELETE_REF:
|
||||
ut_ad(!(~mode & BTR_DELETE));
|
||||
ut_ad(!index->is_spatial());
|
||||
ut_ad(!pcur->index()->is_spatial());
|
||||
return(ROW_NOT_DELETED_REF);
|
||||
|
||||
case BTR_CUR_DEL_MARK_IBUF:
|
||||
|
@@ -1008,17 +1008,16 @@ row_sel_get_clust_rec(
|
||||
|
||||
*out_rec = NULL;
|
||||
|
||||
offsets = rec_get_offsets(rec,
|
||||
btr_pcur_get_btr_cur(&plan->pcur)->index,
|
||||
offsets,
|
||||
btr_pcur_get_btr_cur(&plan->pcur)->index
|
||||
->n_core_fields, ULINT_UNDEFINED, &heap);
|
||||
offsets = rec_get_offsets(rec, plan->pcur.index(), offsets,
|
||||
plan->pcur.index()->n_core_fields,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec, offsets);
|
||||
|
||||
index = dict_table_get_first_index(plan->table);
|
||||
|
||||
dberr_t err = btr_pcur_open_with_no_init(index, plan->clust_ref,
|
||||
plan->clust_pcur.old_rec = nullptr;
|
||||
plan->clust_pcur.btr_cur.page_cur.index = index;
|
||||
dberr_t err = btr_pcur_open_with_no_init(plan->clust_ref,
|
||||
PAGE_CUR_LE, BTR_SEARCH_LEAF,
|
||||
&plan->clust_pcur, mtr);
|
||||
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
|
||||
@@ -1410,6 +1409,9 @@ row_sel_open_pcur(
|
||||
cond = UT_LIST_GET_NEXT(cond_list, cond);
|
||||
}
|
||||
|
||||
plan->pcur.old_rec = nullptr;
|
||||
plan->pcur.btr_cur.page_cur.index = index;
|
||||
|
||||
dberr_t err;
|
||||
|
||||
if (plan->tuple) {
|
||||
@@ -1429,13 +1431,12 @@ row_sel_open_pcur(
|
||||
que_node_get_val(exp));
|
||||
}
|
||||
|
||||
err = btr_pcur_open_with_no_init(index, plan->tuple,
|
||||
err = btr_pcur_open_with_no_init(plan->tuple,
|
||||
plan->mode, BTR_SEARCH_LEAF,
|
||||
&plan->pcur, mtr);
|
||||
} else {
|
||||
err = btr_pcur_open_at_index_side(plan->asc, index,
|
||||
BTR_SEARCH_LEAF, &plan->pcur,
|
||||
false, 0, mtr);
|
||||
err = plan->pcur.open_leaf(plan->asc, index, BTR_SEARCH_LEAF,
|
||||
mtr);
|
||||
}
|
||||
|
||||
plan->pcur_is_open = err == DB_SUCCESS;
|
||||
@@ -3370,6 +3371,7 @@ Row_sel_get_clust_rec_for_mysql::operator()(
|
||||
rec_t* old_vers;
|
||||
trx_t* trx;
|
||||
|
||||
prebuilt->clust_pcur->old_rec = nullptr;
|
||||
*out_rec = NULL;
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
@@ -3380,9 +3382,9 @@ Row_sel_get_clust_rec_for_mysql::operator()(
|
||||
sec_index, *offsets);
|
||||
|
||||
clust_index = dict_table_get_first_index(sec_index->table);
|
||||
prebuilt->clust_pcur->btr_cur.page_cur.index = clust_index;
|
||||
|
||||
dberr_t err = btr_pcur_open_with_no_init(clust_index,
|
||||
prebuilt->clust_ref,
|
||||
dberr_t err = btr_pcur_open_with_no_init(prebuilt->clust_ref,
|
||||
PAGE_CUR_LE, BTR_SEARCH_LEAF,
|
||||
prebuilt->clust_pcur, mtr);
|
||||
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
|
||||
@@ -3447,9 +3449,10 @@ Row_sel_get_clust_rec_for_mysql::operator()(
|
||||
rec, sec_index, true,
|
||||
sec_index->n_fields, heap);
|
||||
page_cur_t page_cursor;
|
||||
page_cursor.block = block;
|
||||
page_cursor.index = sec_index;
|
||||
ulint up_match = 0, low_match = 0;
|
||||
ut_ad(!page_cur_search_with_match(block, sec_index,
|
||||
tuple, PAGE_CUR_LE,
|
||||
ut_ad(!page_cur_search_with_match(tuple, PAGE_CUR_LE,
|
||||
&up_match,
|
||||
&low_match,
|
||||
&page_cursor,
|
||||
@@ -3639,7 +3642,8 @@ record with the same ordering prefix in in the B-tree index
|
||||
@return true if we may need to process the record the cursor is now
|
||||
positioned on (i.e. we should not go to the next record yet) */
|
||||
static bool sel_restore_position_for_mysql(bool *same_user_rec,
|
||||
ulint latch_mode, btr_pcur_t *pcur,
|
||||
btr_latch_mode latch_mode,
|
||||
btr_pcur_t *pcur,
|
||||
bool moves_up, mtr_t *mtr)
|
||||
{
|
||||
auto status = pcur->restore_position(latch_mode, mtr);
|
||||
@@ -3668,7 +3672,7 @@ static bool sel_restore_position_for_mysql(bool *same_user_rec,
|
||||
next:
|
||||
if (btr_pcur_move_to_next(pcur, mtr)
|
||||
&& rec_is_metadata(btr_pcur_get_rec(pcur),
|
||||
*pcur->btr_cur.index)) {
|
||||
*pcur->index())) {
|
||||
btr_pcur_move_to_next(pcur, mtr);
|
||||
}
|
||||
|
||||
@@ -3684,7 +3688,7 @@ next:
|
||||
prev:
|
||||
if (btr_pcur_is_on_user_rec(pcur) && !moves_up
|
||||
&& !rec_is_metadata(btr_pcur_get_rec(pcur),
|
||||
*pcur->btr_cur.index)) {
|
||||
*pcur->index())) {
|
||||
if (!btr_pcur_move_to_prev(pcur, mtr)) {
|
||||
return true;
|
||||
}
|
||||
@@ -3964,8 +3968,9 @@ row_sel_try_search_shortcut_for_mysql(
|
||||
ut_ad(!index->table->is_temporary());
|
||||
ut_ad(!prebuilt->templ_contains_blob);
|
||||
ut_ad(trx->read_view.is_open());
|
||||
pcur->old_rec = nullptr;
|
||||
|
||||
if (btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
|
||||
if (btr_pcur_open_with_no_init(search_tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, pcur, mtr)
|
||||
!= DB_SUCCESS) {
|
||||
return SEL_RETRY;
|
||||
@@ -4395,6 +4400,8 @@ row_search_mvcc(
|
||||
DBUG_RETURN(DB_CORRUPTION);
|
||||
}
|
||||
|
||||
pcur->btr_cur.page_cur.index = index;
|
||||
|
||||
/* We need to get the virtual column values stored in secondary
|
||||
index key, if this is covered index scan or virtual key read is
|
||||
requested. */
|
||||
@@ -4766,6 +4773,7 @@ wait_table_again:
|
||||
|
||||
} else if (dtuple_get_n_fields(search_tuple) > 0) {
|
||||
pcur->btr_cur.thr = thr;
|
||||
pcur->old_rec = nullptr;
|
||||
|
||||
if (dict_index_is_spatial(index)) {
|
||||
if (!prebuilt->rtr_info) {
|
||||
@@ -4785,7 +4793,7 @@ wait_table_again:
|
||||
}
|
||||
}
|
||||
|
||||
err = btr_pcur_open_with_no_init(index, search_tuple, mode,
|
||||
err = btr_pcur_open_with_no_init(search_tuple, mode,
|
||||
BTR_SEARCH_LEAF, pcur, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
@@ -4831,9 +4839,8 @@ page_corrupted:
|
||||
}
|
||||
}
|
||||
} else if (mode == PAGE_CUR_G || mode == PAGE_CUR_L) {
|
||||
err = btr_pcur_open_at_index_side(
|
||||
mode == PAGE_CUR_G, index, BTR_SEARCH_LEAF,
|
||||
pcur, false, 0, &mtr);
|
||||
err = pcur->open_leaf(mode == PAGE_CUR_G, index,
|
||||
BTR_SEARCH_LEAF, &mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (err == DB_DECRYPTION_FAILED) {
|
||||
@@ -5019,7 +5026,7 @@ wrong_offs:
|
||||
|
||||
page_cur_set_after_last(btr_pcur_get_block(pcur),
|
||||
btr_pcur_get_page_cur(pcur));
|
||||
pcur->old_stored = false;
|
||||
pcur->old_rec = nullptr;
|
||||
goto next_rec;
|
||||
}
|
||||
}
|
||||
@@ -5786,7 +5793,7 @@ next_rec_after_check:
|
||||
/* This is based on btr_pcur_move_to_next() */
|
||||
ut_ad(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(pcur->latch_mode != BTR_NO_LATCHES);
|
||||
pcur->old_stored = false;
|
||||
pcur->old_rec = nullptr;
|
||||
if (btr_pcur_is_after_last_on_page(pcur)) {
|
||||
if (btr_pcur_is_after_last_in_tree(pcur)) {
|
||||
goto not_moved;
|
||||
@@ -6198,8 +6205,6 @@ dberr_t row_check_index(row_prebuilt_t *prebuilt, ulint *n_rows)
|
||||
*n_rows= 0;
|
||||
dict_index_t *const index= prebuilt->index;
|
||||
|
||||
prebuilt->fetch_direction= ROW_SEL_NEXT;
|
||||
|
||||
if (!index->is_btree())
|
||||
return DB_CORRUPTION;
|
||||
|
||||
@@ -6210,9 +6215,8 @@ dberr_t row_check_index(row_prebuilt_t *prebuilt, ulint *n_rows)
|
||||
mtr.start();
|
||||
|
||||
dict_index_t *clust_index= dict_table_get_first_index(prebuilt->table);
|
||||
|
||||
dberr_t err= btr_pcur_open_at_index_side(true, index, BTR_SEARCH_LEAF,
|
||||
prebuilt->pcur, false, 0, &mtr);
|
||||
prebuilt->clust_pcur->btr_cur.page_cur.index = clust_index;
|
||||
dberr_t err= prebuilt->pcur->open_leaf(true, index, BTR_SEARCH_LEAF, &mtr);
|
||||
if (UNIV_UNLIKELY(err != DB_SUCCESS))
|
||||
{
|
||||
func_exit:
|
||||
@@ -6300,14 +6304,16 @@ rec_loop:
|
||||
goto next_rec;
|
||||
}
|
||||
|
||||
if (index->is_clust())
|
||||
if (prebuilt->table->is_temporary())
|
||||
{
|
||||
if (prebuilt->trx->isolation_level == TRX_ISO_READ_UNCOMMITTED)
|
||||
{
|
||||
if (!rec_deleted)
|
||||
goto count_row;
|
||||
count_or_not:
|
||||
if (rec_deleted)
|
||||
goto next_rec;
|
||||
}
|
||||
else if (index->is_clust())
|
||||
{
|
||||
if (prebuilt->trx->isolation_level == TRX_ISO_READ_UNCOMMITTED)
|
||||
goto count_or_not;
|
||||
|
||||
trx_id_t rec_trx_id= row_get_rec_trx_id(rec, index, offsets);
|
||||
|
||||
@@ -6371,10 +6377,7 @@ rec_loop:
|
||||
ER_NOT_KEYFILE, "InnoDB: %s", w.m_oss.str().c_str());
|
||||
}
|
||||
|
||||
if (!rec_deleted)
|
||||
goto count_row;
|
||||
|
||||
goto next_rec;
|
||||
goto count_or_not;
|
||||
}
|
||||
else if (const trx_id_t page_trx_id= page_get_max_trx_id(page_align(rec)))
|
||||
{
|
||||
@@ -6388,7 +6391,7 @@ rec_loop:
|
||||
const auto savepoint= mtr.get_savepoint();
|
||||
|
||||
row_build_row_ref_in_tuple(prebuilt->clust_ref, rec, index, offsets);
|
||||
err= btr_pcur_open_with_no_init(clust_index, prebuilt->clust_ref,
|
||||
err= btr_pcur_open_with_no_init(prebuilt->clust_ref,
|
||||
PAGE_CUR_LE, BTR_SEARCH_LEAF,
|
||||
prebuilt->clust_pcur, &mtr);
|
||||
if (err != DB_SUCCESS)
|
||||
@@ -6887,8 +6890,7 @@ row_search_get_max_rec(
|
||||
const rec_t* rec;
|
||||
const bool desc = index->fields[0].descending;
|
||||
|
||||
if (btr_pcur_open_at_index_side(desc, index, BTR_SEARCH_LEAF, &pcur,
|
||||
true, 0, mtr) != DB_SUCCESS) {
|
||||
if (pcur.open_leaf(desc, index, BTR_SEARCH_LEAF, mtr) != DB_SUCCESS) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@@ -68,7 +68,7 @@ row_undo_ins_remove_clust_rec(
|
||||
dberr_t err;
|
||||
ulint n_tries = 0;
|
||||
mtr_t mtr;
|
||||
dict_index_t* index = node->pcur.btr_cur.index;
|
||||
dict_index_t* index = node->pcur.index();
|
||||
table_id_t table_id = 0;
|
||||
const bool dict_locked = node->trx->dict_operation_lock_mode;
|
||||
restart:
|
||||
@@ -207,9 +207,8 @@ retry:
|
||||
} else {
|
||||
index->set_modified(mtr);
|
||||
}
|
||||
ut_a(
|
||||
node->pcur.restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
|
||||
&mtr) == btr_pcur_t::SAME_ALL);
|
||||
ut_a(node->pcur.restore_position(BTR_PURGE_TREE, &mtr)
|
||||
== btr_pcur_t::SAME_ALL);
|
||||
|
||||
btr_cur_pessimistic_delete(&err, FALSE, &node->pcur.btr_cur, 0, true,
|
||||
&mtr);
|
||||
@@ -254,7 +253,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
|
||||
dberr_t
|
||||
row_undo_ins_remove_sec_low(
|
||||
/*========================*/
|
||||
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
|
||||
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
|
||||
depending on whether we wish optimistic or
|
||||
pessimistic descent down the index tree */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
@@ -266,25 +265,27 @@ row_undo_ins_remove_sec_low(
|
||||
mtr_t mtr;
|
||||
const bool modify_leaf = mode == BTR_MODIFY_LEAF;
|
||||
|
||||
pcur.btr_cur.page_cur.index = index;
|
||||
row_mtr_start(&mtr, index, !modify_leaf);
|
||||
|
||||
if (modify_leaf) {
|
||||
mode = BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED;
|
||||
mode = BTR_MODIFY_LEAF_ALREADY_LATCHED;
|
||||
mtr_s_lock_index(index, &mtr);
|
||||
} else {
|
||||
ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE));
|
||||
ut_ad(mode == BTR_PURGE_TREE);
|
||||
mtr_sx_lock_index(index, &mtr);
|
||||
}
|
||||
|
||||
if (dict_index_is_spatial(index)) {
|
||||
if (modify_leaf) {
|
||||
mode |= BTR_RTREE_DELETE_MARK;
|
||||
}
|
||||
if (index->is_spatial()) {
|
||||
mode = modify_leaf
|
||||
? btr_latch_mode(BTR_MODIFY_LEAF_ALREADY_LATCHED
|
||||
| BTR_RTREE_DELETE_MARK
|
||||
| BTR_RTREE_UNDO_INS)
|
||||
: btr_latch_mode(BTR_PURGE_TREE | BTR_RTREE_UNDO_INS);
|
||||
btr_pcur_get_btr_cur(&pcur)->thr = thr;
|
||||
mode |= BTR_RTREE_UNDO_INS;
|
||||
}
|
||||
|
||||
switch (row_search_index_entry(index, entry, mode, &pcur, &mtr)) {
|
||||
switch (row_search_index_entry(entry, mode, &pcur, &mtr)) {
|
||||
case ROW_BUFFERED:
|
||||
case ROW_NOT_DELETED_REF:
|
||||
/* These are invalid outcomes, because the mode passed
|
||||
@@ -349,9 +350,7 @@ row_undo_ins_remove_sec(
|
||||
|
||||
/* Try then pessimistic descent to the B-tree */
|
||||
retry:
|
||||
err = row_undo_ins_remove_sec_low(
|
||||
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
|
||||
index, entry, thr);
|
||||
err = row_undo_ins_remove_sec_low(BTR_PURGE_TREE, index, entry, thr);
|
||||
|
||||
/* The delete operation may fail if we have little
|
||||
file space left: TODO: easiest to crash the database
|
||||
|
@@ -84,7 +84,7 @@ row_undo_mod_clust_low(
|
||||
que_thr_t* thr, /*!< in: query thread */
|
||||
mtr_t* mtr, /*!< in: mtr; must be committed before
|
||||
latching any further pages */
|
||||
ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
|
||||
btr_latch_mode mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
|
||||
{
|
||||
btr_pcur_t* pcur;
|
||||
btr_cur_t* btr_cur;
|
||||
@@ -106,8 +106,8 @@ row_undo_mod_clust_low(
|
||||
|| node->update->info_bits == REC_INFO_METADATA_ALTER);
|
||||
|
||||
if (mode != BTR_MODIFY_TREE) {
|
||||
ut_ad((mode & ulint(~BTR_ALREADY_S_LATCHED))
|
||||
== BTR_MODIFY_LEAF);
|
||||
ut_ad(mode == BTR_MODIFY_LEAF
|
||||
|| mode == BTR_MODIFY_LEAF_ALREADY_LATCHED);
|
||||
|
||||
err = btr_cur_optimistic_update(
|
||||
BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG
|
||||
@@ -224,14 +224,14 @@ static bool row_undo_mod_must_purge(const undo_node_t &node)
|
||||
ut_ad(!node.table->is_temporary());
|
||||
|
||||
const btr_cur_t &btr_cur= node.pcur.btr_cur;
|
||||
ut_ad(btr_cur.index->is_primary());
|
||||
ut_ad(btr_cur.index()->is_primary());
|
||||
DEBUG_SYNC_C("rollback_purge_clust");
|
||||
|
||||
if (!purge_sys.is_purgeable(node.new_trx_id))
|
||||
return false;
|
||||
|
||||
const rec_t *rec= btr_cur_get_rec(&btr_cur);
|
||||
return trx_read_trx_id(rec + row_trx_id_offset(rec, btr_cur.index)) ==
|
||||
return trx_read_trx_id(rec + row_trx_id_offset(rec, btr_cur.index())) ==
|
||||
node.new_trx_id;
|
||||
}
|
||||
|
||||
@@ -356,8 +356,7 @@ row_undo_mod_clust(
|
||||
}
|
||||
|
||||
mtr.start();
|
||||
if (pcur->restore_position(
|
||||
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, &mtr) !=
|
||||
if (pcur->restore_position(BTR_PURGE_TREE, &mtr) !=
|
||||
btr_pcur_t::SAME_ALL) {
|
||||
goto mtr_commit_exit;
|
||||
}
|
||||
@@ -483,7 +482,7 @@ row_undo_mod_del_mark_or_remove_sec_low(
|
||||
que_thr_t* thr, /*!< in: query thread */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
dtuple_t* entry, /*!< in: index entry */
|
||||
ulint mode) /*!< in: latch mode BTR_MODIFY_LEAF or
|
||||
btr_latch_mode mode) /*!< in: latch mode BTR_MODIFY_LEAF or
|
||||
BTR_MODIFY_TREE */
|
||||
{
|
||||
btr_pcur_t pcur;
|
||||
@@ -496,15 +495,25 @@ row_undo_mod_del_mark_or_remove_sec_low(
|
||||
|
||||
row_mtr_start(&mtr, index, !modify_leaf);
|
||||
|
||||
if (!index->is_committed()) {
|
||||
pcur.btr_cur.page_cur.index = index;
|
||||
btr_cur = btr_pcur_get_btr_cur(&pcur);
|
||||
|
||||
if (index->is_spatial()) {
|
||||
mode = modify_leaf
|
||||
? btr_latch_mode(BTR_MODIFY_LEAF
|
||||
| BTR_RTREE_DELETE_MARK
|
||||
| BTR_RTREE_UNDO_INS)
|
||||
: btr_latch_mode(BTR_PURGE_TREE | BTR_RTREE_UNDO_INS);
|
||||
btr_cur->thr = thr;
|
||||
} else if (!index->is_committed()) {
|
||||
/* The index->online_status may change if the index is
|
||||
or was being created online, but not committed yet. It
|
||||
is protected by index->lock. */
|
||||
if (modify_leaf) {
|
||||
mode = BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED;
|
||||
mode = BTR_MODIFY_LEAF_ALREADY_LATCHED;
|
||||
mtr_s_lock_index(index, &mtr);
|
||||
} else {
|
||||
ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE));
|
||||
ut_ad(mode == BTR_PURGE_TREE);
|
||||
mtr_sx_lock_index(index, &mtr);
|
||||
}
|
||||
} else {
|
||||
@@ -514,18 +523,7 @@ row_undo_mod_del_mark_or_remove_sec_low(
|
||||
ut_ad(!dict_index_is_online_ddl(index));
|
||||
}
|
||||
|
||||
btr_cur = btr_pcur_get_btr_cur(&pcur);
|
||||
|
||||
if (dict_index_is_spatial(index)) {
|
||||
if (modify_leaf) {
|
||||
btr_cur->thr = thr;
|
||||
mode |= BTR_RTREE_DELETE_MARK;
|
||||
}
|
||||
mode |= BTR_RTREE_UNDO_INS;
|
||||
}
|
||||
|
||||
search_result = row_search_index_entry(index, entry, mode,
|
||||
&pcur, &mtr);
|
||||
search_result = row_search_index_entry(entry, mode, &pcur, &mtr);
|
||||
|
||||
switch (UNIV_EXPECT(search_result, ROW_FOUND)) {
|
||||
case ROW_NOT_FOUND:
|
||||
@@ -634,7 +632,7 @@ row_undo_mod_del_mark_or_remove_sec(
|
||||
}
|
||||
|
||||
err = row_undo_mod_del_mark_or_remove_sec_low(node, thr, index,
|
||||
entry, BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE);
|
||||
entry, BTR_PURGE_TREE);
|
||||
return(err);
|
||||
}
|
||||
|
||||
@@ -652,7 +650,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
|
||||
dberr_t
|
||||
row_undo_mod_del_unmark_sec_and_undo_update(
|
||||
/*========================================*/
|
||||
ulint mode, /*!< in: search mode: BTR_MODIFY_LEAF or
|
||||
btr_latch_mode mode, /*!< in: search mode: BTR_MODIFY_LEAF or
|
||||
BTR_MODIFY_TREE */
|
||||
que_thr_t* thr, /*!< in: query thread */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
@@ -668,8 +666,9 @@ row_undo_mod_del_unmark_sec_and_undo_update(
|
||||
const ulint flags
|
||||
= BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG;
|
||||
row_search_result search_result;
|
||||
ulint orig_mode = mode;
|
||||
const auto orig_mode = mode;
|
||||
|
||||
pcur.btr_cur.page_cur.index = index;
|
||||
ut_ad(trx->id != 0);
|
||||
|
||||
if (dict_index_is_spatial(index)) {
|
||||
@@ -679,7 +678,7 @@ row_undo_mod_del_unmark_sec_and_undo_update(
|
||||
secondary index updates to avoid this. */
|
||||
static_assert(BTR_MODIFY_TREE == (8 | BTR_MODIFY_LEAF), "");
|
||||
ut_ad(!(mode & 8));
|
||||
mode |= BTR_RTREE_DELETE_MARK;
|
||||
mode = btr_latch_mode(mode | BTR_RTREE_DELETE_MARK);
|
||||
}
|
||||
|
||||
try_again:
|
||||
@@ -687,8 +686,7 @@ try_again:
|
||||
|
||||
btr_cur->thr = thr;
|
||||
|
||||
search_result = row_search_index_entry(index, entry, mode,
|
||||
&pcur, &mtr);
|
||||
search_result = row_search_index_entry(entry, mode, &pcur, &mtr);
|
||||
|
||||
switch (search_result) {
|
||||
mem_heap_t* heap;
|
||||
|
@@ -1840,7 +1840,7 @@ row_upd_sec_index_entry(
|
||||
btr_cur_t* btr_cur;
|
||||
dberr_t err = DB_SUCCESS;
|
||||
trx_t* trx = thr_get_trx(thr);
|
||||
ulint mode;
|
||||
btr_latch_mode mode;
|
||||
ulint flags;
|
||||
enum row_search_result search_result;
|
||||
|
||||
@@ -1870,14 +1870,16 @@ row_upd_sec_index_entry(
|
||||
"before_row_upd_sec_index_entry");
|
||||
|
||||
mtr.start();
|
||||
mode = BTR_MODIFY_LEAF;
|
||||
|
||||
switch (index->table->space_id) {
|
||||
case SRV_TMP_SPACE_ID:
|
||||
mtr.set_log_mode(MTR_LOG_NO_REDO);
|
||||
flags = BTR_NO_LOCKING_FLAG;
|
||||
mode = index->is_spatial()
|
||||
? ulint(BTR_MODIFY_LEAF | BTR_RTREE_DELETE_MARK)
|
||||
: ulint(BTR_MODIFY_LEAF);
|
||||
if (index->is_spatial()) {
|
||||
mode = btr_latch_mode(BTR_MODIFY_LEAF
|
||||
| BTR_RTREE_DELETE_MARK);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
index->set_modified(mtr);
|
||||
@@ -1887,18 +1889,19 @@ row_upd_sec_index_entry(
|
||||
/* We can only buffer delete-mark operations if there
|
||||
are no foreign key constraints referring to the index. */
|
||||
mode = index->is_spatial()
|
||||
? ulint(BTR_MODIFY_LEAF | BTR_RTREE_DELETE_MARK)
|
||||
? btr_latch_mode(BTR_MODIFY_LEAF
|
||||
| BTR_RTREE_DELETE_MARK)
|
||||
: referenced
|
||||
? ulint(BTR_MODIFY_LEAF) : ulint(BTR_DELETE_MARK_LEAF);
|
||||
? BTR_MODIFY_LEAF : BTR_DELETE_MARK_LEAF;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the query thread, so that ibuf_insert_low() will be
|
||||
able to invoke thd_get_trx(). */
|
||||
btr_pcur_get_btr_cur(&pcur)->thr = thr;
|
||||
pcur.btr_cur.page_cur.index = index;
|
||||
|
||||
search_result = row_search_index_entry(index, entry, mode,
|
||||
&pcur, &mtr);
|
||||
search_result = row_search_index_entry(entry, mode, &pcur, &mtr);
|
||||
|
||||
btr_cur = btr_pcur_get_btr_cur(&pcur);
|
||||
|
||||
@@ -2590,13 +2593,13 @@ row_upd_clust_step(
|
||||
|
||||
ut_a(pcur->rel_pos == BTR_PCUR_ON);
|
||||
|
||||
ulint mode;
|
||||
btr_latch_mode mode;
|
||||
|
||||
DEBUG_SYNC_C_IF_THD(trx->mysql_thd, "innodb_row_upd_clust_step_enter");
|
||||
|
||||
if (dict_index_is_online_ddl(index)) {
|
||||
ut_ad(node->table->id != DICT_INDEXES_ID);
|
||||
mode = BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED;
|
||||
mode = BTR_MODIFY_LEAF_ALREADY_LATCHED;
|
||||
mtr_s_lock_index(index, &mtr);
|
||||
} else {
|
||||
mode = BTR_MODIFY_LEAF;
|
||||
|
@@ -392,9 +392,6 @@ mysql_mutex_t srv_misc_tmpfile_mutex;
|
||||
/** Temporary file for miscellanous diagnostic output */
|
||||
FILE* srv_misc_tmpfile;
|
||||
|
||||
static ulint srv_main_thread_process_no;
|
||||
static ulint srv_main_thread_id;
|
||||
|
||||
/* The following counts are used by the srv_master_callback. */
|
||||
|
||||
/** Iterations of the loop bounded by 'srv_active' label. */
|
||||
@@ -887,12 +884,7 @@ srv_printf_innodb_monitor(
|
||||
n_reserved);
|
||||
}
|
||||
|
||||
fprintf(file,
|
||||
"Process ID=" ULINTPF
|
||||
", Main thread ID=" ULINTPF
|
||||
", state: %s\n",
|
||||
srv_main_thread_process_no,
|
||||
srv_main_thread_id,
|
||||
fprintf(file, "Process ID=0, Main thread ID=0, state: %s\n",
|
||||
srv_main_thread_op_info);
|
||||
fprintf(file,
|
||||
"Number of rows inserted " ULINTPF
|
||||
@@ -1456,30 +1448,28 @@ static void srv_sync_log_buffer_in_background()
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
This function prints progress message every 60 seconds during server
|
||||
shutdown, for any activities that master thread is pending on. */
|
||||
static
|
||||
void
|
||||
srv_shutdown_print_master_pending(
|
||||
/*==============================*/
|
||||
time_t* last_print_time, /*!< last time the function
|
||||
print the message */
|
||||
ulint n_bytes_merged) /*!< number of change buffer
|
||||
just merged */
|
||||
/** Report progress during shutdown.
|
||||
@param last time of last output
|
||||
@param n_read number of page reads initiated for change buffer merge */
|
||||
static void srv_shutdown_print(time_t &last, ulint n_read)
|
||||
{
|
||||
time_t current_time = time(NULL);
|
||||
time_t now= time(nullptr);
|
||||
if (now - last >= 15)
|
||||
{
|
||||
last= now;
|
||||
|
||||
if (difftime(current_time, *last_print_time) > 60) {
|
||||
*last_print_time = current_time;
|
||||
|
||||
/* Check change buffer merge, we only wait for change buffer
|
||||
merge if it is a slow shutdown */
|
||||
if (!srv_fast_shutdown && n_bytes_merged) {
|
||||
ib::info() << "Waiting for change buffer merge to"
|
||||
" complete number of bytes of change buffer"
|
||||
" just merged: " << n_bytes_merged;
|
||||
}
|
||||
const ulint ibuf_size= ibuf.size;
|
||||
sql_print_information("Completing change buffer merge;"
|
||||
" %zu page reads initiated;"
|
||||
" %zu change buffer pages remain",
|
||||
n_read, ibuf_size);
|
||||
#if defined HAVE_SYSTEMD && !defined EMBEDDED_LIBRARY
|
||||
service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL,
|
||||
"Completing change buffer merge;"
|
||||
" %zu page reads initiated;"
|
||||
" %zu change buffer pages remain",
|
||||
n_read, ibuf_size);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1525,7 +1515,7 @@ Complete the shutdown tasks such as background DROP TABLE,
|
||||
and optionally change buffer merge (on innodb_fast_shutdown=0). */
|
||||
void srv_shutdown(bool ibuf_merge)
|
||||
{
|
||||
ulint n_bytes_merged = 0;
|
||||
ulint n_read = 0;
|
||||
time_t now = time(NULL);
|
||||
|
||||
do {
|
||||
@@ -1534,21 +1524,12 @@ void srv_shutdown(bool ibuf_merge)
|
||||
++srv_main_shutdown_loops;
|
||||
|
||||
if (ibuf_merge) {
|
||||
srv_main_thread_op_info = "checking free log space";
|
||||
log_free_check();
|
||||
srv_main_thread_op_info = "doing insert buffer merge";
|
||||
n_bytes_merged = ibuf_merge_all();
|
||||
|
||||
/* Flush logs if needed */
|
||||
srv_sync_log_buffer_in_background();
|
||||
log_free_check();
|
||||
n_read = ibuf_contract();
|
||||
srv_shutdown_print(now, n_read);
|
||||
}
|
||||
|
||||
/* Print progress message every 60 seconds during shutdown */
|
||||
if (srv_print_verbose_log) {
|
||||
srv_shutdown_print_master_pending(&now,
|
||||
n_bytes_merged);
|
||||
}
|
||||
} while (n_bytes_merged);
|
||||
} while (n_read);
|
||||
}
|
||||
|
||||
/** The periodic master task controlling the server. */
|
||||
|
@@ -594,7 +594,7 @@ static dberr_t trx_resurrect_table_locks(trx_t *trx, const trx_undo_t &undo)
|
||||
|
||||
if (undo_block != block)
|
||||
{
|
||||
mtr.memo_release(undo_block, MTR_MEMO_PAGE_S_FIX);
|
||||
mtr.release(*undo_block);
|
||||
undo_block= block;
|
||||
}
|
||||
trx_undo_rec_get_pars(undo_rec, &type, &cmpl_info,
|
||||
|
Reference in New Issue
Block a user