mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Merge with 4.0
BitKeeper/etc/gone: auto-union BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union BitKeeper/deleted/.del-.my_sys.h.swp~f6a4a7f8dae03f18: Auto merged BitKeeper/etc/config: Auto merged acconfig.h: Auto merged acinclude.m4: Auto merged Docs/manual.texi: Auto merged client/mysqlcheck.c: Auto merged client/mysqlshow.c: Auto merged include/myisam.h: Auto merged include/violite.h: Auto merged isam/pack_isam.c: Auto merged libmysql/libmysql.c: Auto merged libmysqld/lib_sql.cc: Auto merged myisam/Makefile.am: Auto merged myisam/ft_nlq_search.c: Auto merged myisam/mi_open.c: Auto merged myisam/mi_write.c: Auto merged myisam/sort.c: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/r/fulltext.result: Auto merged mysql-test/r/func_test.result: Auto merged mysql-test/r/isam.result: Auto merged mysql-test/r/rpl_replicate_do.result: Auto merged mysql-test/r/variables.result: Auto merged mysql-test/t/func_test.test: Auto merged mysql-test/t/myisam.test: Auto merged mysql-test/t/rpl_rotate_logs.test: Auto merged mysql-test/t/variables.test: Auto merged mysys/hash.c: Auto merged mysys/tree.c: Auto merged scripts/Makefile.am: Auto merged sql/Makefile.am: Auto merged sql/filesort.cc: Auto merged sql/gen_lex_hash.cc: Auto merged sql/ha_berkeley.cc: Auto merged sql/ha_innodb.cc: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/hash_filo.h: Auto merged sql/hostname.cc: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/item_timefunc.cc: Auto merged sql/lex.h: Auto merged sql/lock.cc: Auto merged sql/log.cc: Auto merged sql/log_event.h: Auto merged sql/mini_client.cc: Auto merged sql/opt_range.cc: Auto merged sql/opt_sum.cc: Auto merged sql/repl_failsafe.cc: Auto merged sql/set_var.h: Auto merged sql/slave.h: Auto merged sql/sql_acl.cc: Auto merged sql/sql_analyse.cc: Auto merged sql/sql_cache.cc: Auto merged sql/sql_insert.cc: Auto merged sql/sql_load.cc: Auto merged sql/sql_rename.cc: Auto merged sql/sql_repl.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_udf.cc: Auto merged sql/share/czech/errmsg.txt: Auto merged sql/share/danish/errmsg.txt: Auto merged sql/share/dutch/errmsg.txt: Auto merged sql/share/english/errmsg.txt: Auto merged sql/share/estonian/errmsg.txt: Auto merged sql/share/french/errmsg.txt: Auto merged sql/share/german/errmsg.txt: Auto merged sql/share/greek/errmsg.txt: Auto merged sql/share/hungarian/errmsg.txt: Auto merged sql/share/italian/errmsg.txt: Auto merged sql/share/japanese/errmsg.txt: Auto merged sql/share/korean/errmsg.txt: Auto merged sql/share/norwegian/errmsg.txt: Auto merged sql/table.h: Auto merged sql/unireg.cc: Auto merged sql-bench/server-cfg.sh: Auto merged sql/share/norwegian-ny/errmsg.txt: Auto merged sql/share/polish/errmsg.txt: Auto merged sql/share/portuguese/errmsg.txt: Auto merged sql/share/romanian/errmsg.txt: Auto merged sql/share/russian/errmsg.txt: Auto merged sql/share/slovak/errmsg.txt: Auto merged sql/share/spanish/errmsg.txt: Auto merged sql/share/swedish/errmsg.txt: Auto merged sql/share/ukrainian/errmsg.txt: Auto merged sql/ha_myisam.cc: Merge with 4.0 Removed some commented code sql/sql_db.cc: Merge with 4.0 Optimized the logging of the drop db call a bit sql/sql_update.cc: Added comment
This commit is contained in:
76
.bzrignore
76
.bzrignore
@ -31,8 +31,11 @@ BitKeeper/etc/gone
|
||||
BitKeeper/etc/level
|
||||
BitKeeper/etc/pushed
|
||||
BitKeeper/tmp/*
|
||||
BitKeeper/tmp/bkr3sAHD
|
||||
BitKeeper/tmp/gone
|
||||
COPYING
|
||||
COPYING.LIB
|
||||
Docs/#manual.texi#
|
||||
Docs/INSTALL-BINARY
|
||||
Docs/include.texi
|
||||
Docs/internals.info
|
||||
@ -73,6 +76,9 @@ PENDING/*
|
||||
TAGS
|
||||
aclocal.m4
|
||||
autom4te.cache/*
|
||||
autom4te.cache/output.0
|
||||
autom4te.cache/requests
|
||||
autom4te.cache/traces.0
|
||||
bdb/README
|
||||
bdb/btree/btree_auto.c
|
||||
bdb/build_unix/*
|
||||
@ -81,17 +87,21 @@ bdb/build_vxworks/db_int.h
|
||||
bdb/build_win32/db.h
|
||||
bdb/build_win32/db_archive.dsp
|
||||
bdb/build_win32/db_checkpoint.dsp
|
||||
bdb/build_win32/db_config.h
|
||||
bdb/build_win32/db_cxx.h
|
||||
bdb/build_win32/db_deadlock.dsp
|
||||
bdb/build_win32/db_dll.dsp
|
||||
bdb/build_win32/db_dump.dsp
|
||||
bdb/build_win32/db_int.h
|
||||
bdb/build_win32/db_java.dsp
|
||||
bdb/build_win32/db_load.dsp
|
||||
bdb/build_win32/db_perf.dsp
|
||||
bdb/build_win32/db_printlog.dsp
|
||||
bdb/build_win32/db_recover.dsp
|
||||
bdb/build_win32/db_stat.dsp
|
||||
bdb/build_win32/db_static.dsp
|
||||
bdb/build_win32/db_tcl.dsp
|
||||
bdb/build_win32/db_test.dsp
|
||||
bdb/build_win32/db_upgrade.dsp
|
||||
bdb/build_win32/db_verify.dsp
|
||||
bdb/build_win32/ex_access.dsp
|
||||
@ -107,9 +117,16 @@ bdb/build_win32/excxx_lock.dsp
|
||||
bdb/build_win32/excxx_mpool.dsp
|
||||
bdb/build_win32/excxx_tpcb.dsp
|
||||
bdb/build_win32/include.tcl
|
||||
bdb/build_win32/libdb.def
|
||||
bdb/build_win32/libdb.rc
|
||||
bdb/db/crdel_auto.c
|
||||
bdb/db/db_auto.c
|
||||
bdb/dbinc_auto/*.*
|
||||
bdb/dbreg/dbreg_auto.c
|
||||
bdb/dist/autom4te.cache/*
|
||||
bdb/dist/autom4te.cache/output.0
|
||||
bdb/dist/autom4te.cache/requests
|
||||
bdb/dist/autom4te.cache/traces.0
|
||||
bdb/dist/config.hin
|
||||
bdb/dist/configure
|
||||
bdb/dist/tags
|
||||
@ -118,11 +135,17 @@ bdb/dist/template/gen_client_ret
|
||||
bdb/dist/template/rec_btree
|
||||
bdb/dist/template/rec_crdel
|
||||
bdb/dist/template/rec_db
|
||||
bdb/dist/template/rec_dbreg
|
||||
bdb/dist/template/rec_fileops
|
||||
bdb/dist/template/rec_hash
|
||||
bdb/dist/template/rec_log
|
||||
bdb/dist/template/rec_qam
|
||||
bdb/dist/template/rec_txn
|
||||
bdb/examples_c/ex_apprec/ex_apprec_auto.c
|
||||
bdb/examples_c/ex_apprec/ex_apprec_auto.h
|
||||
bdb/examples_c/ex_apprec/ex_apprec_template
|
||||
bdb/examples_java
|
||||
bdb/fileops/fileops_auto.c
|
||||
bdb/hash/hash_auto.c
|
||||
bdb/include/btree_auto.h
|
||||
bdb/include/btree_ext.h
|
||||
@ -151,16 +174,33 @@ bdb/include/tcl_ext.h
|
||||
bdb/include/txn_auto.h
|
||||
bdb/include/txn_ext.h
|
||||
bdb/include/xa_ext.h
|
||||
bdb/java/src/com/sleepycat/db/Db.java
|
||||
bdb/java/src/com/sleepycat/db/DbBtreeStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbConstants.java
|
||||
bdb/java/src/com/sleepycat/db/DbHashStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbLockStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbLogStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbMpoolFStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbQueueStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbRepStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbTxnStat.java
|
||||
bdb/libdb_java/java_stat_auto.c
|
||||
bdb/libdb_java/java_stat_auto.h
|
||||
bdb/log/log_auto.c
|
||||
bdb/qam/qam_auto.c
|
||||
bdb/rpc_client/db_server_clnt.c
|
||||
bdb/rpc_client/gen_client.c
|
||||
bdb/rpc_server/c/db_server_proc.c
|
||||
bdb/rpc_server/c/db_server_proc.sed
|
||||
bdb/rpc_server/c/db_server_svc.c
|
||||
bdb/rpc_server/c/db_server_xdr.c
|
||||
bdb/rpc_server/c/gen_db_server.c
|
||||
bdb/rpc_server/db_server.x
|
||||
bdb/rpc_server/db_server_proc.sed
|
||||
bdb/rpc_server/db_server_svc.c
|
||||
bdb/rpc_server/db_server_xdr.c
|
||||
bdb/rpc_server/gen_db_server.c
|
||||
bdb/test/TESTS
|
||||
bdb/test/include.tcl
|
||||
bdb/test/logtrack.list
|
||||
bdb/txn/txn_auto.c
|
||||
@ -194,6 +234,7 @@ configure.lineno
|
||||
core
|
||||
db-*.*.*
|
||||
dbug/user.t
|
||||
depcomp
|
||||
extra/comp_err
|
||||
extra/my_print_defaults
|
||||
extra/mysql_install
|
||||
@ -209,6 +250,9 @@ include/my_global.h
|
||||
include/mysql_version.h
|
||||
include/widec.h
|
||||
innobase/autom4te.cache/*
|
||||
innobase/autom4te.cache/output.0
|
||||
innobase/autom4te.cache/requests
|
||||
innobase/autom4te.cache/traces.0
|
||||
innobase/configure.lineno
|
||||
innobase/conftest.s1
|
||||
innobase/conftest.subs
|
||||
@ -392,9 +436,11 @@ mysql.kdevprj
|
||||
mysql.proj
|
||||
mysqld.S
|
||||
mysqld.sym
|
||||
mysys/#mf_iocache.c#
|
||||
mysys/charset2html
|
||||
mysys/getopt.c
|
||||
mysys/getopt1.c
|
||||
mysys/ste5KbMa
|
||||
mysys/test_charset
|
||||
mysys/test_dir
|
||||
mysys/test_io_cache
|
||||
@ -511,33 +557,3 @@ vio/test-ssl
|
||||
vio/test-sslclient
|
||||
vio/test-sslserver
|
||||
vio/viotest-ssl
|
||||
bdb/build_win32/db_config.h
|
||||
bdb/build_win32/db_cxx.h
|
||||
bdb/build_win32/db_perf.dsp
|
||||
bdb/build_win32/db_test.dsp
|
||||
bdb/build_win32/libdb.def
|
||||
bdb/dbinc_auto/*.*
|
||||
bdb/dbreg/dbreg_auto.c
|
||||
bdb/dist/template/rec_dbreg
|
||||
bdb/dist/template/rec_fileops
|
||||
bdb/examples_c/ex_apprec/ex_apprec_auto.c
|
||||
bdb/examples_c/ex_apprec/ex_apprec_auto.h
|
||||
bdb/examples_c/ex_apprec/ex_apprec_template
|
||||
bdb/fileops/fileops_auto.c
|
||||
bdb/java/src/com/sleepycat/db/Db.java
|
||||
bdb/java/src/com/sleepycat/db/DbBtreeStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbHashStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbLockStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbLogStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbMpoolFStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbQueueStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbRepStat.java
|
||||
bdb/java/src/com/sleepycat/db/DbTxnStat.java
|
||||
bdb/libdb_java/java_stat_auto.c
|
||||
bdb/libdb_java/java_stat_auto.h
|
||||
bdb/rpc_server/c/db_server_proc.c
|
||||
bdb/rpc_server/c/db_server_proc.sed
|
||||
bdb/rpc_server/c/db_server_svc.c
|
||||
bdb/rpc_server/c/db_server_xdr.c
|
||||
bdb/rpc_server/c/gen_db_server.c
|
||||
bdb/test/TESTS
|
||||
|
@ -37,7 +37,7 @@ EXTRA_DIST = FINISH.sh \
|
||||
compile-pentium-pgcc \
|
||||
compile-solaris-sparc \
|
||||
compile-solaris-sparc-debug \
|
||||
compile-solaris-sparc-fortre \
|
||||
compile-solaris-sparc-forte \
|
||||
compile-solaris-sparc-purify
|
||||
|
||||
# Don't update the files from bitkeeper
|
||||
|
13
BUILD/compile-pentium-valgrind-max
Executable file
13
BUILD/compile-pentium-valgrind-max
Executable file
@ -0,0 +1,13 @@
|
||||
#! /bin/sh
|
||||
|
||||
path=`dirname $0`
|
||||
. "$path/SETUP.sh"
|
||||
|
||||
extra_flags="$pentium_cflags $debug_cflags -DHAVE_purify"
|
||||
c_warnings="$c_warnings $debug_extra_warnings"
|
||||
cxx_warnings="$cxx_warnings $debug_extra_warnings"
|
||||
extra_configs="$pentium_configs $debug_configs"
|
||||
|
||||
extra_configs="$extra_configs --with-berkeley-db --with-innodb --with-embedded-server --with-openssl"
|
||||
|
||||
. "$path/FINISH.sh"
|
39
BUILD/compile-solaris-sparc-forte
Executable file
39
BUILD/compile-solaris-sparc-forte
Executable file
@ -0,0 +1,39 @@
|
||||
#! /bin/sh
|
||||
|
||||
gmake -k clean || true
|
||||
/bin/rm -f */.deps/*.P config.cache
|
||||
|
||||
aclocal && autoheader && aclocal && automake && autoconf
|
||||
(cd bdb/dist && sh s_all)
|
||||
(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
|
||||
if [ -d gemini ]
|
||||
then
|
||||
(cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
|
||||
fi
|
||||
|
||||
|
||||
# Assume Forte is installed in /opt/SUNWSpro
|
||||
|
||||
PATH=/opt/SUNWspro/bin/:$PATH
|
||||
|
||||
# For "optimal" code for this computer add -fast to EXTRA
|
||||
# To compile 64 bit, add -xarch=v9 to EXTRA_64_BIT
|
||||
|
||||
EXTRA_64_BIT="-xarch=v9" # Remove comment to get 64 bit binaries
|
||||
EXTRA="-fast" # Remove comment to target current machine
|
||||
|
||||
#
|
||||
# The following should not need to be touched
|
||||
#
|
||||
|
||||
STD="-mt -D_FORTEC_ $EXTRA $EXTRA_64_BIT"
|
||||
ASFLAGS="$EXTRA_64_BIT" \
|
||||
CC=cc-5.0 CFLAGS="-Xa -xstrconst $STD" \
|
||||
CXX=CC CXXFLAGS="-noex $STD" \
|
||||
./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
|
||||
|
||||
gmake -j 4
|
||||
if [ $? = 0 ]
|
||||
then
|
||||
make test
|
||||
fi
|
@ -1,19 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
gmake -k clean || true
|
||||
/bin/rm -f */.deps/*.P config.cache
|
||||
|
||||
aclocal && autoheader && aclocal && automake && autoconf
|
||||
(cd bdb/dist && sh s_all)
|
||||
(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
|
||||
if [ -d gemini ]
|
||||
then
|
||||
(cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
|
||||
fi
|
||||
|
||||
PATH=/opt/SUNWspro/bin/:$PATH
|
||||
CC=cc CFLAGS="-Xa -fast -xO4 -native -xstrconst -mt -D_FORTREC_" \
|
||||
CXX=CC CXXFLAGS="-noex -xO4 -mt" \
|
||||
./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
|
||||
|
||||
gmake -j 4
|
@ -42,7 +42,7 @@ single_host:
|
||||
# discovers a problem which requires local intervention. Please make the
|
||||
# contact information accurate so we can support you.
|
||||
#
|
||||
contact: Sasha Pachev <sasha@mysql.com>
|
||||
contact: sys@mysql.com
|
||||
#
|
||||
# It is very important that this email address is filled out and accurate.
|
||||
# If someone converts your repository to open logging (which you may not
|
||||
@ -51,7 +51,7 @@ contact: Sasha Pachev <sasha@mysql.com>
|
||||
# response from anyone else at your location after 90 days, then open logging
|
||||
# will be implicitly approved.
|
||||
#
|
||||
email: sasha@mysql.com
|
||||
email: sys@mysql.com
|
||||
#
|
||||
# Add your street address if you like, it is optional.
|
||||
#
|
||||
|
@ -199,7 +199,9 @@ BK|sql-bench/Results/ATIS-mysql-3.21-Linux_2.2.1_i686|19700101030959|02022|660fb
|
||||
BK|sql-bench/Results/ATIS-mysql-Linux_2.2.10_i686|19700101030959|02025|3fa4d167cceff7e8
|
||||
BK|sql-bench/Results/ATIS-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02312|84ca3b85ff306133
|
||||
BK|sql-bench/Results/ATIS-mysql-Linux_2.2.14_i686_xeon|19700101030959|02044|3e820c28bf4af63a
|
||||
BK|sql-bench/Results/ATIS-mysql-SunOS_5.5.1_sun4u|19700101030959|02031|dfb4c5f6b6db3b49
|
||||
BK|sql-bench/Results/ATIS-mysql-SunOS_5.6_sun4m|19700101030959|02032|62028e0375b3b8b
|
||||
BK|sql-bench/Results/ATIS-mysql-SunOS_5.7_sun4u|19700101030959|02034|be0d9789776c5ed7
|
||||
BK|sql-bench/Results/ATIS-mysql_3.21-Linux_2.0.35_i686|19700101030959|02036|c25425e045ca8dfc
|
||||
BK|sql-bench/Results/ATIS-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02304|cbe120d860296d2f
|
||||
BK|sql-bench/Results/ATIS-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02027|a74e7b82d3908fa9
|
||||
@ -263,7 +265,9 @@ BK|sql-bench/Results/RUN-mysql-3.21-Linux_2.2.1_i686|19700101030959|02050|f6fdd6
|
||||
BK|sql-bench/Results/RUN-mysql-Linux_2.2.10_i686|19700101030959|02041|712f52be5d195406
|
||||
BK|sql-bench/Results/RUN-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02038|8ee87b26b91c86fe
|
||||
BK|sql-bench/Results/RUN-mysql-Linux_2.2.14_i686_xeon|19700101030959|02055|17854e751e1d9d1d
|
||||
BK|sql-bench/Results/RUN-mysql-SunOS_5.5.1_sun4u|19700101030959|02058|afbba182428e20df
|
||||
BK|sql-bench/Results/RUN-mysql-SunOS_5.6_sun4m|19700101030959|02059|eafc8188345e262b
|
||||
BK|sql-bench/Results/RUN-mysql-SunOS_5.7_sun4u|19700101030959|02061|86e1dc0e25a8b8f
|
||||
BK|sql-bench/Results/RUN-mysql_3.21-Linux_2.0.35_i686|19700101030959|02064|ea8672d8473435
|
||||
BK|sql-bench/Results/RUN-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02310|a902e1a967d79c42
|
||||
BK|sql-bench/Results/RUN-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02030|413ab3b8a99e61e9
|
||||
@ -273,7 +277,9 @@ BK|sql-bench/Results/alter-table-mysql-3.21-Linux_2.2.1_i686|19700101030959|0207
|
||||
BK|sql-bench/Results/alter-table-mysql-Linux_2.2.10_i686|19700101030959|02081|93b78a85b720a186
|
||||
BK|sql-bench/Results/alter-table-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02314|4ae4b989301df98b
|
||||
BK|sql-bench/Results/alter-table-mysql-Linux_2.2.14_i686_xeon|19700101030959|02057|64cc4b874cd6fabf
|
||||
BK|sql-bench/Results/alter-table-mysql-SunOS_5.5.1_sun4u|19700101030959|02087|9d7e75667fcb29ec
|
||||
BK|sql-bench/Results/alter-table-mysql-SunOS_5.6_sun4m|19700101030959|02088|8a1bd6589a189890
|
||||
BK|sql-bench/Results/alter-table-mysql-SunOS_5.7_sun4u|19700101030959|02090|ce74c2f623d3bb3
|
||||
BK|sql-bench/Results/alter-table-mysql_3.21-Linux_2.0.35_i686|19700101030959|02092|762639f2560976bd
|
||||
BK|sql-bench/Results/alter-table-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02316|1390155aad5b6e86
|
||||
BK|sql-bench/Results/alter-table-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02317|9090bebb62ef164b
|
||||
@ -283,7 +289,9 @@ BK|sql-bench/Results/big-tables-mysql-3.21-Linux_2.2.1_i686|19700101030959|02106
|
||||
BK|sql-bench/Results/big-tables-mysql-Linux_2.2.10_i686|19700101030959|02109|99daa1c5370d077d
|
||||
BK|sql-bench/Results/big-tables-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02315|2804ec3c95be436a
|
||||
BK|sql-bench/Results/big-tables-mysql-Linux_2.2.14_i686_xeon|19700101030959|02074|290c2c3de9d8e6b
|
||||
BK|sql-bench/Results/big-tables-mysql-SunOS_5.5.1_sun4u|19700101030959|02115|7d7b6c0bf58b9b79
|
||||
BK|sql-bench/Results/big-tables-mysql-SunOS_5.6_sun4m|19700101030959|02116|f351a7f3e1e2257e
|
||||
BK|sql-bench/Results/big-tables-mysql-SunOS_5.7_sun4u|19700101030959|02118|ebc379b231312bbe
|
||||
BK|sql-bench/Results/big-tables-mysql_3.21-Linux_2.0.35_i686|19700101030959|02120|190e827e569c99a4
|
||||
BK|sql-bench/Results/big-tables-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02318|c5eabcb89ceac698
|
||||
BK|sql-bench/Results/big-tables-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02319|856d503725373684
|
||||
@ -293,7 +301,9 @@ BK|sql-bench/Results/connect-mysql-3.21-Linux_2.2.1_i686|19700101030959|02134|c0
|
||||
BK|sql-bench/Results/connect-mysql-Linux_2.2.10_i686|19700101030959|02137|c92505d77e19d5ec
|
||||
BK|sql-bench/Results/connect-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02084|e7e2959b7387251f
|
||||
BK|sql-bench/Results/connect-mysql-Linux_2.2.14_i686_xeon|19700101030959|02071|ea19dc3ec55b3618
|
||||
BK|sql-bench/Results/connect-mysql-SunOS_5.5.1_sun4u|19700101030959|02142|a9493110fe62e0b1
|
||||
BK|sql-bench/Results/connect-mysql-SunOS_5.6_sun4m|19700101030959|02143|a10e3ddfa26a3e7f
|
||||
BK|sql-bench/Results/connect-mysql-SunOS_5.7_sun4u|19700101030959|02145|c67beb9e9d2cf32e
|
||||
BK|sql-bench/Results/connect-mysql_3.21-Linux_2.0.35_i686|19700101030959|02146|650abd213e6828c6
|
||||
BK|sql-bench/Results/connect-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02320|ce69cc65bc827b5c
|
||||
BK|sql-bench/Results/connect-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02066|f801e08429a4f7c6
|
||||
@ -303,7 +313,9 @@ BK|sql-bench/Results/create-mysql-3.21-Linux_2.2.1_i686|19700101030959|02158|515
|
||||
BK|sql-bench/Results/create-mysql-Linux_2.2.10_i686|19700101030959|02161|9e7822f66df6aa76
|
||||
BK|sql-bench/Results/create-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02102|34ded91c5fc25de9
|
||||
BK|sql-bench/Results/create-mysql-Linux_2.2.14_i686_xeon|19700101030959|02139|50d15991293030ef
|
||||
BK|sql-bench/Results/create-mysql-SunOS_5.5.1_sun4u|19700101030959|02166|bbb5de66fc56de7b
|
||||
BK|sql-bench/Results/create-mysql-SunOS_5.6_sun4m|19700101030959|02221|9233114ae6f8c5f
|
||||
BK|sql-bench/Results/create-mysql-SunOS_5.7_sun4u|19700101030959|02223|7ee13bfcafeab498
|
||||
BK|sql-bench/Results/create-mysql_3.21-Linux_2.0.35_i686|19700101030959|02225|df1b037d17b33587
|
||||
BK|sql-bench/Results/create-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02321|e985e71d552ff09e
|
||||
BK|sql-bench/Results/create-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02099|483dcf223d5abf81
|
||||
@ -313,7 +325,9 @@ BK|sql-bench/Results/insert-mysql-3.21-Linux_2.2.1_i686|19700101030959|02239|fd0
|
||||
BK|sql-bench/Results/insert-mysql-Linux_2.2.10_i686|19700101030959|02242|763edf9aec633f51
|
||||
BK|sql-bench/Results/insert-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02130|5be3d6f299738a31
|
||||
BK|sql-bench/Results/insert-mysql-Linux_2.2.14_i686_xeon|19700101030959|02141|c683ee4b9d214298
|
||||
BK|sql-bench/Results/insert-mysql-SunOS_5.5.1_sun4u|19700101030959|02247|8a9ae41f9a79f79
|
||||
BK|sql-bench/Results/insert-mysql-SunOS_5.6_sun4m|19700101030959|02248|3402d060ae20e19
|
||||
BK|sql-bench/Results/insert-mysql-SunOS_5.7_sun4u|19700101030959|02250|78efa132c6e252b9
|
||||
BK|sql-bench/Results/insert-mysql_3.21-Linux_2.0.35_i686|19700101030959|02252|60c0965dff31db07
|
||||
BK|sql-bench/Results/insert-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02322|ed252140ff399961
|
||||
BK|sql-bench/Results/insert-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02114|29a3b8a1ca8aa9d
|
||||
@ -323,7 +337,9 @@ BK|sql-bench/Results/select-mysql-3.21-Linux_2.2.1_i686|19700101030959|02265|ed3
|
||||
BK|sql-bench/Results/select-mysql-Linux_2.2.10_i686|19700101030959|02268|a2e264d777b787d
|
||||
BK|sql-bench/Results/select-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02227|308117295c3bc096
|
||||
BK|sql-bench/Results/select-mysql-Linux_2.2.14_i686_xeon|19700101030959|02152|ead3f11b46ac626f
|
||||
BK|sql-bench/Results/select-mysql-SunOS_5.5.1_sun4u|19700101030959|02273|c9a1a498a052e268
|
||||
BK|sql-bench/Results/select-mysql-SunOS_5.6_sun4m|19700101030959|02274|4da215905bce988d
|
||||
BK|sql-bench/Results/select-mysql-SunOS_5.7_sun4u|19700101030959|02276|632c92971c61e34a
|
||||
BK|sql-bench/Results/select-mysql_3.21-Linux_2.0.35_i686|19700101030959|02278|5fadbac5f98696a
|
||||
BK|sql-bench/Results/select-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02323|e8c0871a668a610d
|
||||
BK|sql-bench/Results/select-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02127|963a98ed526e2be4
|
||||
@ -333,7 +349,9 @@ BK|sql-bench/Results/wisconsin-mysql-3.21-Linux_2.2.1_i686|19700101030959|02290|
|
||||
BK|sql-bench/Results/wisconsin-mysql-Linux_2.2.10_i686|19700101030959|02288|301a82b12a84922b
|
||||
BK|sql-bench/Results/wisconsin-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02280|d01900af34fb33b8
|
||||
BK|sql-bench/Results/wisconsin-mysql-Linux_2.2.14_i686_xeon|19700101030959|02154|7525b23938631801
|
||||
BK|sql-bench/Results/wisconsin-mysql-SunOS_5.5.1_sun4u|19700101030959|02297|379705afa2e12378
|
||||
BK|sql-bench/Results/wisconsin-mysql-SunOS_5.6_sun4m|19700101030959|02298|ec61b14072715dc8
|
||||
BK|sql-bench/Results/wisconsin-mysql-SunOS_5.7_sun4u|19700101030959|02300|f27927f8c64ea8ad
|
||||
BK|sql-bench/Results/wisconsin-mysql_3.21-Linux_2.0.35_i686|19700101030959|02302|31703d40ea6b4f66
|
||||
BK|sql-bench/Results/wisconsin-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02324|ec075a89dbdbbe6a
|
||||
BK|sql-bench/Results/wisconsin-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02325|233d5aa529979990
|
||||
@ -727,6 +745,8 @@ mwagner@evoq.home.mwagner.org|mysql-test/xml/tests/sel000029.xml|20001017133713|
|
||||
mwagner@evoq.home.mwagner.org|mysql-test/xml/tests/sel000030.xml|20001017133600|63205|c2b25781eefaee9
|
||||
mwagner@evoq.home.mwagner.org|mysql-test/xml/xsl/README|20001013051514|26509|cd4bb681e5a0cd10
|
||||
mwagner@evoq.home.mwagner.org|mysql-test/xml/xsl/mysqltest.xsl|20001013051514|27425|1b8f6ec4f1b5f634
|
||||
mwagner@work.mysql.com|mysql-test/r/3.23/sel000001.result|20001010091454|28284|383913ae4505ec86
|
||||
mwagner@work.mysql.com|mysql-test/r/3.23/sel000002.result|20001010091454|29230|d1787e6fd5dbc1cc
|
||||
nick@nick.leippe.com|mysql-test/r/rpl_empty_master_crash.result|20020531235552|47718|615f521be2132141
|
||||
nick@nick.leippe.com|mysql-test/t/rpl_empty_master_crash.test|20020531235552|52328|99464e737639ccc6
|
||||
sasha@mysql.sashanet.com|BitKeeper/etc/logging_ok|20000801000905|12967|5b7d847a2158554
|
||||
@ -734,19 +754,36 @@ sasha@mysql.sashanet.com|build-tags|20011125054855|05181|7afb7e785b80f97
|
||||
sasha@mysql.sashanet.com|build-tags|20011201050944|25384|b6f6fff142121618
|
||||
sasha@mysql.sashanet.com|libmysql_r/acconfig.h|20001128060846|51084|65f1202b3b5c345f
|
||||
sasha@mysql.sashanet.com|mysql-test/README.gcov|20001012045950|28177|5a6da067a30780ce
|
||||
sasha@mysql.sashanet.com|mysql-test/README.gcov|20001214012355|41825|2de7575ca81155e5
|
||||
sasha@mysql.sashanet.com|mysql-test/README|20001010001022|12739|108667adaeabe3f5
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/alt000001.result|20001122072330|24729|393103dbf15f35c9
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/ins000001.result|20001018175743|49824|f45c599efdf8352b
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000001.a.result|20001118063528|39426|2987b17db06808c3
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000001.b.result|20001118063528|44057|62e1fa91167cacc3
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000002.result|20001118063528|46039|109f5ceed1e0d64
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000003.result|20001118063528|48148|68d6ee00beaa011
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000004.a.result|20001118063528|50132|3415f066cb91c460
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000004.b.result|20001118063528|52094|352b35351551485
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000005.result|20001118063528|54071|a50962bc2340ab9a
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000006.result|20001118063528|56081|5653051e8ce6b4aa
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000007.result|20001121063807|21606|e0c3b6134e0884da
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000008.result|20001121063807|23636|c5cfee19ca5a7da9
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000009.result|20001121063807|25633|ed8042446ab97926
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000010.result|20001122072330|29430|3228109b8965b0f8
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000011.result|20001125024912|48851|c29dce30aa97f265
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000012.result|20001126062901|05938|35d6596da7b90fc5
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000012.status.result|20001126062901|09395|bbbd650b5beea32f
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000013.result|20001202171150|03876|ac5024e6cf6daac6
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000013.status.result|20001202171150|06069|6bee190c298cc9fd
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/sel000003.result|20001011230020|64653|d7b657b1e3a286a7
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/sel000100.res|20001205131218|23520|84ed46856cb3a69f
|
||||
sasha@mysql.sashanet.com|mysql-test/r/3.23/shw000001.result|20001121234128|16652|8b20b03d8319b9a5
|
||||
sasha@mysql.sashanet.com|mysql-test/r/binlog-backup-restore.result|20010424233926|16010|605de78abda64d27
|
||||
sasha@mysql.sashanet.com|mysql-test/r/df_crash.result|20010406010433|59989|4a3dbee64843953d
|
||||
sasha@mysql.sashanet.com|mysql-test/r/identity.result|20010910233028|16331|e41453a364242503
|
||||
sasha@mysql.sashanet.com|mysql-test/r/mrg000002.result|20001212152450|11492|745be0854aaaaf5e
|
||||
sasha@mysql.sashanet.com|mysql-test/r/slave-running.result|20001208141122|24303|f73e49462cf59e1f
|
||||
sasha@mysql.sashanet.com|mysql-test/r/slave-stopped.result|20001208141122|28916|25c134b1a4f1993a
|
||||
sasha@mysql.sashanet.com|mysql-test/std_data/m.MRG|20001212152450|17736|3f5632c37af00f18
|
||||
sasha@mysql.sashanet.com|mysql-test/std_data/m.frm|20001212152450|13897|e351dfe0b6824c0c
|
||||
sasha@mysql.sashanet.com|mysql-test/std_data/select-key.master|20001009234916|07315|e6b83af25df0ce5
|
||||
|
@ -16,6 +16,7 @@ bar@gw.udmsearch.izhnet.ru
|
||||
bell@sanja.is.com.ua
|
||||
bk@admin.bk
|
||||
davida@isil.mysql.com
|
||||
gluh@gluh.(none)
|
||||
heikki@donna.mysql.fi
|
||||
heikki@hundin.mysql.fi
|
||||
heikki@rescue.
|
||||
@ -41,6 +42,7 @@ miguel@hegel.local
|
||||
miguel@light.
|
||||
miguel@light.local
|
||||
monty@bitch.mysql.fi
|
||||
monty@butch.
|
||||
monty@donna.mysql.fi
|
||||
monty@hundin.mysql.fi
|
||||
monty@mashka.mysql.fi
|
||||
|
@ -8,13 +8,13 @@ use Getopt::Long;
|
||||
$opt_distribution=$opt_user=$opt_config_env="";
|
||||
$opt_dbd_options=$opt_perl_options=$opt_config_options=$opt_make_options=$opt_suffix="";
|
||||
$opt_tmp=$opt_version_suffix="";
|
||||
$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=0;
|
||||
$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=$opt_with_debug=0;
|
||||
$opt_innodb=$opt_bdb=$opt_raid=$opt_libwrap=0;
|
||||
|
||||
GetOptions(
|
||||
"bdb",
|
||||
"build-thread=i",
|
||||
"config-env=s",
|
||||
"config-env=s" => \@config_env,
|
||||
"config-options=s" => \@config_options,
|
||||
"dbd-options=s",
|
||||
"debug",
|
||||
@ -45,6 +45,7 @@ GetOptions(
|
||||
"use-old-distribution",
|
||||
"user=s",
|
||||
"version-suffix=s",
|
||||
"with-debug",
|
||||
"with-low-memory",
|
||||
"with-other-libc=s",
|
||||
"with-small-disk",
|
||||
@ -53,11 +54,6 @@ GetOptions(
|
||||
usage() if ($opt_help);
|
||||
usage() if (!$opt_distribution);
|
||||
|
||||
if ($opt_bdb && $opt_version_suffix eq "")
|
||||
{
|
||||
$opt_version_suffix="-max";
|
||||
}
|
||||
|
||||
if (@make_options > 0)
|
||||
{
|
||||
chomp(@make_options);
|
||||
@ -70,6 +66,12 @@ if (@config_options > 0)
|
||||
$opt_config_options= join(" ", @config_options);
|
||||
}
|
||||
|
||||
if (@config_env > 0)
|
||||
{
|
||||
chomp(@config_env);
|
||||
$opt_config_env= join(" ", @config_env);
|
||||
}
|
||||
|
||||
chomp($host=`hostname`);
|
||||
$full_host_name=$host;
|
||||
$connect_option= ($opt_tcpip ? "--host=$host" : "");
|
||||
@ -208,6 +210,7 @@ if ($opt_stage <= 1)
|
||||
$opt_config_options.= " --disable-shared" if (!$opt_enable_shared); # Default for binary versions
|
||||
$opt_config_options.= " --with-berkeley-db" if ($opt_bdb);
|
||||
$opt_config_options.= " --with-client-ldflags=-all-static" if ($opt_static_client);
|
||||
$opt_config_options.= " --with-debug" if ($opt_with_debug);
|
||||
$opt_config_options.= " --with-libwrap" if ($opt_libwrap);
|
||||
$opt_config_options.= " --with-low-memory" if ($opt_with_low_memory);
|
||||
$opt_config_options.= " --with-mysqld-ldflags=-all-static" if ($opt_static_server);
|
||||
@ -258,7 +261,7 @@ if ($opt_stage <= 3)
|
||||
log_system("rm -fr mysql-3* mysql-4* $pwd/$host/*.tar.gz");
|
||||
log_system("nm -n sql/mysqld | gzip -9 -v 2>&1 > sql/mysqld.sym.gz | cat");
|
||||
|
||||
$flags.= "--no-strip" if ($opt_no_strip);
|
||||
$flags.= "--no-strip" if ($opt_no_strip || $opt_with_debug);
|
||||
check_system("scripts/make_binary_distribution --tmp=$opt_tmp --suffix=$opt_suffix $flags",".tar.gz created");
|
||||
safe_system("mv mysql*.tar.gz $pwd/$host");
|
||||
if (-f "client/.libs/mysqladmin")
|
||||
@ -381,13 +384,15 @@ if ($opt_stage <= 9 && !$opt_no_test)
|
||||
log_system("rm -f output/*");
|
||||
$tmp= $opt_fast_benchmark ? "--fast --user root --small-test" : "";
|
||||
check_system("perl ./run-all-tests --log --die-on-errors $connect_option $tmp","RUN-mysql");
|
||||
# Run additional fast test with dynamic-row tables
|
||||
check_system("perl ./run-all-tests --log --suffix=\"_dynamic_rows\" --die-on-errors $connect_option --fast --user=root --small-test --create-options=\"row_format=dynamic\"","RUN-mysql");
|
||||
if ($opt_innodb)
|
||||
{
|
||||
check_system("perl ./run-all-tests --log --suffix=\"_innodb\" --die-on-errors $connect_option $tmp --create-option=\"type=innodb\"","RUN-mysql");
|
||||
check_system("perl ./run-all-tests --log --suffix=\"_innodb\" --die-on-errors $connect_option $tmp --create-options=\"type=innodb\"","RUN-mysql");
|
||||
}
|
||||
if ($opt_bdb)
|
||||
{
|
||||
check_system("perl ./run-all-tests --log --suffix=\"_bdb\" --die-on-errors $connect_option $tmp --create-option=\"type=bdb\"","RUN-mysql");
|
||||
check_system("perl ./run-all-tests --log --suffix=\"_bdb\" --die-on-errors $connect_option $tmp --create-options=\"type=bdb\"","RUN-mysql");
|
||||
}
|
||||
}
|
||||
|
||||
@ -498,6 +503,9 @@ If user is empty then no mail is sent.
|
||||
--version-suffix suffix
|
||||
Set name suffix (e.g. 'com' or '-max') for a distribution
|
||||
|
||||
--with-debug
|
||||
Build binaries with debug information (implies "--no-strip")
|
||||
|
||||
--with-low-memory
|
||||
Use less memory when compiling.
|
||||
|
||||
@ -528,7 +536,7 @@ sub abort
|
||||
print TMP "To: $email\n";
|
||||
print TMP "Subject: $ver$opt_version_suffix compilation failed\n\n";
|
||||
close TMP;
|
||||
system("tail -40 $log > $log.mail");
|
||||
system("tail -n 40 $log > $log.mail");
|
||||
system("cat $mail_header_file $log.mail | $sendmail -t -f $email");
|
||||
unlink($mail_header_file);
|
||||
unlink("$log.mail");
|
||||
@ -604,7 +612,7 @@ sub which
|
||||
my(@progs)=@_;
|
||||
foreach $prog (@progs)
|
||||
{
|
||||
chomp($found=`which $prog | head -1`);
|
||||
chomp($found=`which $prog | head -n 1`);
|
||||
if ($? == 0 && $found ne "" && index($found," ") == -1)
|
||||
{
|
||||
$found =~ s|/+|/|g; # Make nicer output
|
||||
|
1069
Docs/internals.texi
1069
Docs/internals.texi
File diff suppressed because it is too large
Load Diff
140
Docs/manual.texi
140
Docs/manual.texi
@ -8202,6 +8202,10 @@ The following startup variables/options have been renamed:
|
||||
The startup options @code{record_buffer}, @code{sort_buffer} and
|
||||
@code{warnings} will still work in MySQL 4.0 but are deprecated.
|
||||
@item
|
||||
The mysqld option @code{--safe_show_database} doesn't work anymore. One
|
||||
should instead give the @code{SHOW DATABASES} privileges to everyone that
|
||||
need to see all databases.
|
||||
@item
|
||||
The following SQL variables have changed name.
|
||||
@c arjen note: New table, not yet measured for O'Reilly/DocBook.
|
||||
@multitable @columnfractions .50 .50
|
||||
@ -19879,7 +19883,6 @@ differ somewhat:
|
||||
| query_cache_limit | 1048576 |
|
||||
| query_cache_size | 0 |
|
||||
| query_cache_type | ON |
|
||||
| safe_show_database | OFF |
|
||||
| server_id | 0 |
|
||||
| slave_net_timeout | 3600 |
|
||||
| skip_external_locking | ON |
|
||||
@ -20314,7 +20317,8 @@ This may be set (only numeric) to
|
||||
Don't show databases for which the user doesn't have any database or
|
||||
table privileges. This can improve security if you're concerned about
|
||||
people being able to see what databases other users have. See also
|
||||
@code{skip_show_database}.
|
||||
@code{skip_show_database}. This option is deprecated as one should instead
|
||||
use the @code{SHOW DATABASES} privilege instead.
|
||||
|
||||
@item @code{server_id}
|
||||
The value of the @code{--server-id} option.
|
||||
@ -20327,7 +20331,7 @@ Is ON if we only allow local (socket) connections.
|
||||
|
||||
@item @code{skip_show_database}
|
||||
This prevents people from doing @code{SHOW DATABASES} if they don't have
|
||||
the @code{PROCESS} privilege. This can improve security if you're
|
||||
the @code{SHOW DATABASE} privilege. This can improve security if you're
|
||||
concerned about people being able to see what databases other users
|
||||
have. See also @code{safe_show_database}.
|
||||
|
||||
@ -23506,17 +23510,21 @@ will be logged in the execution order.
|
||||
Updates to non-transactional tables are stored in the binary log
|
||||
immediately after execution. For transactional tables such as @code{BDB}
|
||||
or @code{InnoDB} tables, all updates (@code{UPDATE}, @code{DELETE}
|
||||
or @code{INSERT}) that change tables are cached until a @code{COMMIT}.
|
||||
or @code{INSERT}) that change tables are cached until a @code{COMMIT} command
|
||||
is sent to the server. At this point mysqld writes the whole transaction to
|
||||
the binary log before the @code{COMMIT} is executed.
|
||||
Every thread will, on start, allocate a buffer of @code{binlog_cache_size}
|
||||
to buffer queries. If a query is bigger than this, the thread will open
|
||||
a temporary file to handle the bigger cache. The temporary file will
|
||||
a temporary file to store the transcation. The temporary file will
|
||||
be deleted when the thread ends.
|
||||
|
||||
The @code{max_binlog_cache_size} can be used to restrict the total size used
|
||||
to cache a multi-query transaction.
|
||||
The @code{max_binlog_cache_size} (default 4G) can be used to restrict
|
||||
the total size used to cache a multi-query transaction. If a transaction is
|
||||
bigger than this it will fail and roll back.
|
||||
|
||||
If you are using the update or binary log, concurrent inserts will
|
||||
not work together with @code{CREATE ... SELECT} and @code{INSERT ... SELECT}.
|
||||
be converted to normal inserts when using @code{CREATE ... SELECT} and
|
||||
@code{INSERT ... SELECT}.
|
||||
This is to ensure that you can recreate an exact copy of your tables by
|
||||
applying the log on a backup.
|
||||
|
||||
@ -23683,7 +23691,7 @@ started}, your slaves may fail.
|
||||
|
||||
Please see the following table for an indication of master-slave
|
||||
compatibility between different versions. With regard to version 4.0,
|
||||
we recommend using same version on both sides.
|
||||
we recommend using at least 4.0.4 on both sides.
|
||||
|
||||
@c FIX arjen 2002-07-17 new table, not yet measured for XML/DocBook.
|
||||
@multitable @columnfractions .10 .15 .15 .10 .10 .10
|
||||
@ -24350,7 +24358,7 @@ may be used with @code{IO_THREAD} and @code{SQL_THREAD} options. (Slave)
|
||||
@tab Re-enables update logging if the user has the @code{SUPER} privilege.
|
||||
Ignored otherwise. (Master)
|
||||
|
||||
@item @code{GLOBAL SET SQL_SLAVE_SKIP_COUNTER=n}
|
||||
@item @code{SET GLOBAL SQL_SLAVE_SKIP_COUNTER=n}
|
||||
@tab Skip the next @code{n} events from the master. Only valid when
|
||||
the slave thread is not running, otherwise, gives an error. Useful for
|
||||
recovering from replication glitches.
|
||||
@ -25510,7 +25518,7 @@ temporary table to hold the result. This typically happens if you do an
|
||||
@code{ORDER BY} on a different column set than you did a @code{GROUP
|
||||
BY} on.
|
||||
|
||||
@item Where used
|
||||
@item Using where (was @code{where used})
|
||||
A @code{WHERE} clause will be used to restrict which rows will be
|
||||
matched against the next table or sent to the client. If you don't have
|
||||
this information and the table is of type @code{ALL} or @code{index},
|
||||
@ -25670,7 +25678,7 @@ Executing the @code{EXPLAIN} statement again produces this result:
|
||||
|
||||
@example
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used
|
||||
tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 Using where
|
||||
do ALL PRIMARY NULL NULL NULL 2135
|
||||
range checked for each record (key map: 1)
|
||||
et_1 ALL PRIMARY NULL NULL NULL 74
|
||||
@ -25696,7 +25704,7 @@ Now @code{EXPLAIN} produces the output shown here:
|
||||
@example
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
et ALL PRIMARY NULL NULL NULL 74
|
||||
tt ref AssignedPC, ActualPC 15 et.EMPLOYID 52 where used
|
||||
tt ref AssignedPC, ActualPC 15 et.EMPLOYID 52 Using where
|
||||
ClientID,
|
||||
ActualPC
|
||||
et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1
|
||||
@ -25719,7 +25727,7 @@ Now the join is perfect, and @code{EXPLAIN} produces this result:
|
||||
|
||||
@example
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
tt ALL AssignedPC NULL NULL NULL 3872 where used
|
||||
tt ALL AssignedPC NULL NULL NULL 3872 Using where
|
||||
ClientID,
|
||||
ActualPC
|
||||
et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
|
||||
@ -28868,7 +28876,6 @@ and if you can use @code{GLOBAL} or @code{SESSION} with them.
|
||||
@item read_buffer_size @tab num @tab GLOBAL | SESSION
|
||||
@item read_rnd_buffer_size @tab num @tab GLOBAL | SESSION
|
||||
@item rpl_recovery_rank @tab num @tab GLOBAL
|
||||
@item safe_show_database @tab bool @tab GLOBAL
|
||||
@item server_id @tab num @tab GLOBAL
|
||||
@item slave_compressed_protocol @tab bool @tab GLOBAL
|
||||
@item slave_net_timeout @tab num @tab GLOBAL
|
||||
@ -38698,8 +38705,8 @@ SUM_OVER_ALL_KEYS(max_length_of_key + sizeof(char*) * 2)
|
||||
* Table and index:: Table and Index Structures
|
||||
* File space management:: File Space Management and Disk I/O
|
||||
* Error handling:: Error Handling
|
||||
* InnoDB change history:: InnoDB Change History
|
||||
* InnoDB restrictions:: Restrictions on InnoDB Tables
|
||||
* InnoDB change history:: InnoDB Change History
|
||||
* InnoDB contact information:: InnoDB Contact Information.
|
||||
@end menu
|
||||
|
||||
@ -50735,6 +50742,7 @@ this means that the version has not yet been released!
|
||||
@c Please don't add a new version here without also updating ../configure.in!
|
||||
|
||||
@menu
|
||||
* News-4.1.x::
|
||||
* News-4.0.x:: Changes in release 4.0.x (Beta)
|
||||
* News-3.23.x:: Changes in release 3.23.x (Stable)
|
||||
* News-3.22.x:: Changes in release 3.22.x (Older; Still supported)
|
||||
@ -50744,7 +50752,77 @@ this means that the version has not yet been released!
|
||||
@end menu
|
||||
|
||||
|
||||
@node News-4.0.x, News-3.23.x, News, News
|
||||
@node News-4.1.x, News-4.0.x, News, News
|
||||
@appendixsec Changes in release 4.1.x (Alpha)
|
||||
|
||||
@cindex changes, version 4.1
|
||||
|
||||
Version 4.1 of the MySQL server includes many enhancements and new features:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Sub selects: @code{SELECT * from t1 where t1.a=(SELECT t2.b FROM t2)}.
|
||||
@item
|
||||
Character sets to be defined per column, table and database.
|
||||
@item
|
||||
Unicode (UTF8) support.
|
||||
@item
|
||||
Derived tables: @code{SELECT a from t1, (select * from t2) WHERE t1.a=t2.a}
|
||||
@item
|
||||
@code{BTREE} index on @code{HEAP} tables.
|
||||
@item
|
||||
Support for GIS (Geometrical data).
|
||||
@item
|
||||
@code{SHOW WARNINGS}; Shows warnings for the last command.
|
||||
@end itemize
|
||||
|
||||
For a full list of changes, please refer to the changelog sections for
|
||||
each individual 4.1.x release.
|
||||
|
||||
@menu
|
||||
* News-4.1.0::
|
||||
@end menu
|
||||
|
||||
@node News-4.1.0, , News-4.1.x, News-4.1.x
|
||||
@appendixsubsec Changes in release 4.1.0
|
||||
@itemize
|
||||
@item
|
||||
One can specify many temporary directories to be used in a round-robin
|
||||
fasion with: @code{--tmpdir=dirname1:dirname2:dirname3}.
|
||||
@item
|
||||
Sub selects: @code{SELECT * from t1 where t1.a=(SELECT t2.b FROM t2)}.
|
||||
@item
|
||||
Character sets to be defined per column, table and database.
|
||||
@item
|
||||
Unicode (UTF8) support.
|
||||
@item
|
||||
Derived tables: @code{SELECT a from t1, (select * from t2) WHERE t1.a=t2.a}
|
||||
@item
|
||||
@code{BTREE} index on @code{HEAP} tables.
|
||||
@item
|
||||
Faster embedded server.
|
||||
@item
|
||||
One can add a comment per column in @code{CREATE TABLE}.
|
||||
@item
|
||||
@code{SHOW FULL COLUMNS FROM table_name} shows column comments.
|
||||
@item
|
||||
@code{ALTER DATABASE}.
|
||||
@item
|
||||
Support for GIS (Geometrical data).
|
||||
@item
|
||||
@code{SHOW WARNINGS}; Shows warnings from the last command.
|
||||
@item
|
||||
One can specify a column type for a colum in @code{CREATE TABLE
|
||||
... SELECT} by defining the column in the @code{CREATE} part
|
||||
|
||||
@example
|
||||
CREATE TABLE foo (a tinyint not null) SELECT b+1 AS 'a' FROM bar;
|
||||
@end example
|
||||
|
||||
@end itemize
|
||||
|
||||
|
||||
@node News-4.0.x, News-3.23.x, News-4.1.x, News
|
||||
@appendixsec Changes in release 4.0.x (Beta)
|
||||
|
||||
@cindex changes, version 4.0
|
||||
@ -50815,6 +50893,19 @@ each individual 4.0.x release.
|
||||
@appendixsubsec Changes in release 4.0.5
|
||||
@itemize
|
||||
@item
|
||||
When one uses the @code{--open-files-limit=#} option to @code{mysqld_safe}
|
||||
it's now passed on to @code{mysqld}
|
||||
@item
|
||||
Fixed that @code{GROUP BY} on columns that may have a @code{NULL} value
|
||||
doesn't always use disk based temporary tables.
|
||||
@item
|
||||
Changed output from @code{EXPLAIN} from @code{'where used'} to
|
||||
@code{'Using where'} to make it more in line with other output.
|
||||
@item
|
||||
Removed variable @code{safe_show_database} as it was not used anymore.
|
||||
@item
|
||||
Read @code{--des-key-file} relative to database directory.
|
||||
@item
|
||||
Small code improvement in multi-table updates
|
||||
@item
|
||||
Fixed a newly introduced bug that caused @code{ORDER BY ... LIMIT #}
|
||||
@ -51680,6 +51771,11 @@ not yet 100% confident in this code.
|
||||
@appendixsubsec Changes in release 3.23.54
|
||||
@itemize
|
||||
@item
|
||||
Allow one to start multiple MySQL servers on windows (code backported
|
||||
from 4.0.2).
|
||||
@item
|
||||
Fixed that @code{--core-file} works on Linux (at least on kernel 2.4.18).
|
||||
@item
|
||||
Fixed a problem with BDB and @code{ALTER TABLE}.
|
||||
@item
|
||||
Fixed reference to freed memory when doing complicated @code{GROUP BY
|
||||
@ -51765,6 +51861,11 @@ Changed initialisation of @code{RND()} to make it less predicatable.
|
||||
Fixed problem with @code{GROUP BY} on result with expression that created a
|
||||
@code{BLOB} field.
|
||||
@item
|
||||
Fixed problem with @code{GROUP BY} on columns that have NULL values. To
|
||||
solve this we now create an MyISAM temporary table when doing a group by
|
||||
on a possible NULL item. In MySQL 4.0.5 we can again use in memory HEAP
|
||||
tables for this case.
|
||||
@item
|
||||
Fixed problem with privilege tables when downgrading from 4.0.2 to 3.23.
|
||||
@item
|
||||
Fixed thread bug in @code{SLAVE START}, @code{SLAVE STOP} and automatic repair
|
||||
@ -52506,8 +52607,9 @@ long as @code{server-id} is set and valid @file{master.info} is present.
|
||||
Partial updates (terminated with kill) are now logged with a special error
|
||||
code to the binary log. Slave will refuse to execute them if the error code
|
||||
indicates the update was terminated abnormally, and will have to be recovered
|
||||
with @code{SET SQL_SLAVE_SKIP_COUNTER=1; SLAVE START} after a manual sanity
|
||||
check/correction of data integrity.
|
||||
with @code{SET SQL_SLAVE_SKIP_COUNTER=1; SLAVE START} after a manual
|
||||
sanity check/correction of data integrity. Update: In 4.0.3 and above
|
||||
you have to use @code{SET GLOBAL}.
|
||||
@item
|
||||
Fixed bug that erroneously logged a drop of internal temporary table
|
||||
on thread termination to the binary log -- this bug affected replication.
|
||||
|
@ -274,7 +274,7 @@
|
||||
#undef SPRINTF_RETURNS_INT
|
||||
#undef SPRINTF_RETURNS_GARBAGE
|
||||
|
||||
/* Needed to get large file supportat HPUX 10.20 */
|
||||
/* Needed to get large file support on HPUX 10.20 */
|
||||
#undef __STDC_EXT__
|
||||
|
||||
#undef STACK_DIRECTION
|
||||
|
137
acinclude.m4
137
acinclude.m4
@ -1190,5 +1190,142 @@ dnl ---------------------------------------------------------------------------
|
||||
dnl END OF MYSQL_CHECK_INNODB SECTION
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
dnl By default, many hosts won't let programs access large files;
|
||||
dnl one must use special compiler options to get large-file access to work.
|
||||
dnl For more details about this brain damage please see:
|
||||
dnl http://www.sas.com/standards/large.file/x_open.20Mar96.html
|
||||
|
||||
dnl Written by Paul Eggert <eggert@twinsun.com>.
|
||||
|
||||
dnl Internal subroutine of AC_SYS_LARGEFILE.
|
||||
dnl AC_SYS_LARGEFILE_FLAGS(FLAGSNAME)
|
||||
AC_DEFUN(AC_SYS_LARGEFILE_FLAGS,
|
||||
[AC_CACHE_CHECK([for $1 value to request large file support],
|
||||
ac_cv_sys_largefile_$1,
|
||||
[if ($GETCONF LFS_$1) >conftest.1 2>conftest.2 && test ! -s conftest.2
|
||||
then
|
||||
ac_cv_sys_largefile_$1=`cat conftest.1`
|
||||
else
|
||||
ac_cv_sys_largefile_$1=no
|
||||
ifelse($1, CFLAGS,
|
||||
[case "$host_os" in
|
||||
# HP-UX 10.20 requires -D__STDC_EXT__ with gcc 2.95.1.
|
||||
changequote(, )dnl
|
||||
hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
|
||||
changequote([, ])dnl
|
||||
if test "$GCC" = yes; then
|
||||
ac_cv_sys_largefile_CFLAGS=-D__STDC_EXT__
|
||||
fi
|
||||
;;
|
||||
# IRIX 6.2 and later require cc -n32.
|
||||
changequote(, )dnl
|
||||
irix6.[2-9]* | irix6.1[0-9]* | irix[7-9].* | irix[1-9][0-9]*)
|
||||
changequote([, ])dnl
|
||||
if test "$GCC" != yes; then
|
||||
ac_cv_sys_largefile_CFLAGS=-n32
|
||||
fi
|
||||
esac
|
||||
if test "$ac_cv_sys_largefile_CFLAGS" != no; then
|
||||
ac_save_CC="$CC"
|
||||
CC="$CC $ac_cv_sys_largefile_CFLAGS"
|
||||
AC_TRY_LINK(, , , ac_cv_sys_largefile_CFLAGS=no)
|
||||
CC="$ac_save_CC"
|
||||
fi])
|
||||
fi
|
||||
rm -f conftest*])])
|
||||
|
||||
dnl Internal subroutine of AC_SYS_LARGEFILE.
|
||||
dnl AC_SYS_LARGEFILE_SPACE_APPEND(VAR, VAL)
|
||||
AC_DEFUN(AC_SYS_LARGEFILE_SPACE_APPEND,
|
||||
[case $2 in
|
||||
no) ;;
|
||||
?*)
|
||||
case "[$]$1" in
|
||||
'') $1=$2 ;;
|
||||
*) $1=[$]$1' '$2 ;;
|
||||
esac ;;
|
||||
esac])
|
||||
|
||||
dnl Internal subroutine of AC_SYS_LARGEFILE.
|
||||
dnl AC_SYS_LARGEFILE_MACRO_VALUE(C-MACRO, CACHE-VAR, COMMENT, CODE-TO-SET-DEFAULT)
|
||||
AC_DEFUN(AC_SYS_LARGEFILE_MACRO_VALUE,
|
||||
[AC_CACHE_CHECK([for $1], $2,
|
||||
[$2=no
|
||||
changequote(, )dnl
|
||||
for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
|
||||
case "$ac_flag" in
|
||||
-D$1)
|
||||
$2=1 ;;
|
||||
-D$1=*)
|
||||
$2=`expr " $ac_flag" : '[^=]*=\(.*\)'` ;;
|
||||
esac
|
||||
done
|
||||
$4
|
||||
changequote([, ])dnl
|
||||
])
|
||||
if test "[$]$2" != no; then
|
||||
AC_DEFINE_UNQUOTED([$1], [$]$2, [$3])
|
||||
fi])
|
||||
|
||||
AC_DEFUN(MYSQL_SYS_LARGEFILE,
|
||||
[AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_ARG_ENABLE(largefile,
|
||||
[ --disable-largefile Omit support for large files])
|
||||
if test "$enable_largefile" != no; then
|
||||
AC_CHECK_TOOL(GETCONF, getconf)
|
||||
AC_SYS_LARGEFILE_FLAGS(CFLAGS)
|
||||
AC_SYS_LARGEFILE_FLAGS(LDFLAGS)
|
||||
AC_SYS_LARGEFILE_FLAGS(LIBS)
|
||||
|
||||
for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
|
||||
case "$ac_flag" in
|
||||
no) ;;
|
||||
-D_FILE_OFFSET_BITS=*) ;;
|
||||
-D_LARGEFILE_SOURCE | -D_LARGEFILE_SOURCE=*) ;;
|
||||
-D_LARGE_FILES | -D_LARGE_FILES=*) ;;
|
||||
-D?* | -I?*)
|
||||
AC_SYS_LARGEFILE_SPACE_APPEND(CPPFLAGS, "$ac_flag") ;;
|
||||
*)
|
||||
AC_SYS_LARGEFILE_SPACE_APPEND(CFLAGS, "$ac_flag") ;;
|
||||
esac
|
||||
done
|
||||
AC_SYS_LARGEFILE_SPACE_APPEND(LDFLAGS, "$ac_cv_sys_largefile_LDFLAGS")
|
||||
AC_SYS_LARGEFILE_SPACE_APPEND(LIBS, "$ac_cv_sys_largefile_LIBS")
|
||||
|
||||
AC_SYS_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS,
|
||||
ac_cv_sys_file_offset_bits,
|
||||
[Number of bits in a file offset, on hosts where this is settable.],
|
||||
[case "$host_os" in
|
||||
# HP-UX 10.20 and later
|
||||
hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
|
||||
ac_cv_sys_file_offset_bits=64 ;;
|
||||
# We can't declare _FILE_OFFSET_BITS here as this will cause
|
||||
# compile errors as AC_PROG_CC adds include files in confdefs.h
|
||||
# We solve this (until autoconf is fixed) by instead declaring it
|
||||
# as define instead
|
||||
solaris2.[8,9])
|
||||
CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64"
|
||||
CXXFLAGS="$CXXFLAGS -D_FILE_OFFSET_BITS=64"
|
||||
ac_cv_sys_file_offset_bits=no ;;
|
||||
esac])
|
||||
AC_SYS_LARGEFILE_MACRO_VALUE(_LARGEFILE_SOURCE,
|
||||
ac_cv_sys_largefile_source,
|
||||
[Define to make fseeko etc. visible, on some hosts.],
|
||||
[case "$host_os" in
|
||||
# HP-UX 10.20 and later
|
||||
hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
|
||||
ac_cv_sys_largefile_source=1 ;;
|
||||
esac])
|
||||
AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES,
|
||||
ac_cv_sys_large_files,
|
||||
[Define for large files, on AIX-style hosts.],
|
||||
[case "$host_os" in
|
||||
# AIX 4.2 and later
|
||||
aix4.[2-9]* | aix4.1[0-9]* | aix[5-9].* | aix[1-9][0-9]*)
|
||||
ac_cv_sys_large_files=1 ;;
|
||||
esac])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
|
@ -38,4 +38,4 @@ enum options { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET,
|
||||
OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH,
|
||||
OPT_SSL_CIPHER, OPT_SHUTDOWN_TIMEOUT, OPT_LOCAL_INFILE,
|
||||
OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL,
|
||||
OPT_SHARED_MEMORY_BASE_NAME };
|
||||
OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM };
|
||||
|
@ -176,7 +176,7 @@ static void dump_remote_file(NET* net, const char* fname)
|
||||
}
|
||||
|
||||
|
||||
static my_bool
|
||||
extern "C" my_bool
|
||||
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||
char *argument)
|
||||
{
|
||||
@ -210,7 +210,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||
print_version();
|
||||
exit(0);
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0,
|
||||
opt_compress = 0, opt_databases = 0, opt_fast = 0,
|
||||
opt_medium_check = 0, opt_quick = 0, opt_all_in_1 = 0,
|
||||
opt_silent = 0, opt_auto_repair = 0, ignore_errors = 0,
|
||||
tty_password = 0;
|
||||
tty_password = 0, opt_frm = 0;
|
||||
static uint verbose = 0, opt_mysql_port=0;
|
||||
static my_string opt_mysql_unix_port = 0;
|
||||
static char *opt_password = 0, *current_user = 0, *default_charset = 0,
|
||||
@ -139,6 +139,10 @@ static struct my_option my_long_options[] =
|
||||
{"user", 'u', "User for login if not current user.", (gptr*) ¤t_user,
|
||||
(gptr*) ¤t_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
#endif
|
||||
{"use-frm", OPT_FRM,
|
||||
"When used with REPAIR, get table structure from .frm file, so the table can be repaired even if .MYI header is corrupted.",
|
||||
(gptr*) &opt_frm, (gptr*) &opt_frm, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
|
||||
0},
|
||||
{"verbose", 'v', "Print info about the various stages.", 0, 0, 0, GET_NO_ARG,
|
||||
NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
|
||||
@ -368,21 +372,25 @@ static int process_selected_tables(char *db, char **table_names, int tables)
|
||||
return 1;
|
||||
if (opt_all_in_1)
|
||||
{
|
||||
/*
|
||||
We need table list in form `a`, `b`, `c`
|
||||
that's why we need 4 more chars added to to each table name
|
||||
space is for more readable output in logs and in case of error
|
||||
*/
|
||||
char *table_names_comma_sep, *end;
|
||||
int i, tot_length = 0;
|
||||
|
||||
for (i = 0; i < tables; i++)
|
||||
tot_length += strlen(*(table_names + i)) + 1;
|
||||
tot_length += strlen(*(table_names + i)) + 4;
|
||||
|
||||
if (!(table_names_comma_sep = (char *)
|
||||
my_malloc((sizeof(char) * tot_length) + 1, MYF(MY_WME))))
|
||||
my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME))))
|
||||
return 1;
|
||||
|
||||
for (end = table_names_comma_sep + 1; tables > 0;
|
||||
tables--, table_names++)
|
||||
{
|
||||
end = strmov(end, *table_names);
|
||||
*end++= ',';
|
||||
end = strxmov(end, " `", *table_names, "`,", NullS);
|
||||
}
|
||||
*--end = 0;
|
||||
handle_request_for_tables(table_names_comma_sep + 1, tot_length - 1);
|
||||
@ -409,22 +417,27 @@ static int process_all_tables_in_db(char *database)
|
||||
|
||||
if (opt_all_in_1)
|
||||
{
|
||||
/*
|
||||
We need table list in form `a`, `b`, `c`
|
||||
that's why we need 4 more chars added to to each table name
|
||||
space is for more readable output in logs and in case of error
|
||||
*/
|
||||
|
||||
char *tables, *end;
|
||||
uint tot_length = 0;
|
||||
|
||||
while ((row = mysql_fetch_row(res)))
|
||||
tot_length += strlen(row[0]) + 1;
|
||||
tot_length += strlen(row[0]) + 4;
|
||||
mysql_data_seek(res, 0);
|
||||
|
||||
if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+1, MYF(MY_WME))))
|
||||
if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME))))
|
||||
{
|
||||
mysql_free_result(res);
|
||||
return 1;
|
||||
}
|
||||
for (end = tables + 1; (row = mysql_fetch_row(res)) ;)
|
||||
{
|
||||
end = strmov(end, row[0]);
|
||||
*end++= ',';
|
||||
end = strxmov(end, " `", row[0], "`,", NullS);
|
||||
}
|
||||
*--end = 0;
|
||||
if (tot_length)
|
||||
@ -472,6 +485,7 @@ static int handle_request_for_tables(char *tables, uint length)
|
||||
op = "REPAIR";
|
||||
if (opt_quick) end = strmov(end, " QUICK");
|
||||
if (opt_extended) end = strmov(end, " EXTENDED");
|
||||
if (opt_frm) end = strmov(end, " USE_FRM");
|
||||
break;
|
||||
case DO_ANALYZE:
|
||||
op = "ANALYZE";
|
||||
@ -483,10 +497,14 @@ static int handle_request_for_tables(char *tables, uint length)
|
||||
|
||||
if (!(query =(char *) my_malloc((sizeof(char)*(length+110)), MYF(MY_WME))))
|
||||
return 1;
|
||||
if (opt_all_in_1)
|
||||
/* No backticks here as we added them before */
|
||||
sprintf(query, "%s TABLE %s %s", op, tables, options);
|
||||
else
|
||||
sprintf(query, "%s TABLE `%s` %s", op, tables, options);
|
||||
if (mysql_query(sock, query))
|
||||
{
|
||||
sprintf(message, "when executing '%s TABLE `%s` %s", op, tables,options);
|
||||
sprintf(message, "when executing '%s TABLE ... %s'", op, options);
|
||||
DBerror(sock, message);
|
||||
return 1;
|
||||
}
|
||||
|
@ -305,7 +305,10 @@ static void short_usage(void)
|
||||
static void write_header(FILE *sql_file, char *db_name)
|
||||
{
|
||||
if (opt_xml)
|
||||
{
|
||||
fprintf(sql_file,"<?xml version=\"1.0\"?>\n");
|
||||
fprintf(sql_file,"<mysqldump>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION);
|
||||
@ -319,6 +322,12 @@ static void write_header(FILE *sql_file, char *db_name)
|
||||
return;
|
||||
} /* write_header */
|
||||
|
||||
static void write_footer(FILE *sql_file)
|
||||
{
|
||||
if (opt_xml)
|
||||
fprintf(sql_file,"</mysqldump>");
|
||||
fputs("\n", sql_file);
|
||||
} /* write_footer */
|
||||
|
||||
static my_bool
|
||||
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||
@ -1004,7 +1013,7 @@ static void dumpTable(uint numFields, char *table)
|
||||
rownr=0;
|
||||
init_length=(uint) strlen(insert_pat)+4;
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "\t<%s>\n", table);
|
||||
fprintf(md_result_file, "\t<table name=\"%s\">\n", table);
|
||||
|
||||
if (opt_autocommit)
|
||||
fprintf(md_result_file, "set autocommit=0;\n");
|
||||
@ -1094,9 +1103,9 @@ static void dumpTable(uint numFields, char *table)
|
||||
/* change any strings ("inf","nan",..) into NULL */
|
||||
char *ptr = row[i];
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "\t\t<%s>%s</%s>\n",
|
||||
fprintf(md_result_file, "\t\t<field name=\"%s\">%s</field>\n",
|
||||
field->name,
|
||||
!my_isalpha(system_charset_info,*ptr) ?ptr: "NULL",field->name);
|
||||
!my_isalpha(system_charset_info, *ptr) ? ptr: "NULL");
|
||||
else
|
||||
fputs((!my_isalpha(system_charset_info,*ptr)) ?
|
||||
ptr : "NULL", md_result_file);
|
||||
@ -1105,8 +1114,8 @@ static void dumpTable(uint numFields, char *table)
|
||||
else
|
||||
{
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "\t\t<%s>%s</%s>\n",
|
||||
field->name, "NULL", field->name);
|
||||
fprintf(md_result_file, "\t\t<field name=\"%s\">%s</field>\n",
|
||||
field->name, "NULL");
|
||||
else
|
||||
fputs("NULL", md_result_file);
|
||||
}
|
||||
@ -1147,7 +1156,7 @@ static void dumpTable(uint numFields, char *table)
|
||||
|
||||
/* XML - close table tag and supress regular output */
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "\t</%s>\n", table);
|
||||
fprintf(md_result_file, "\t</table>\n");
|
||||
else if (extended_insert && row_break)
|
||||
fputs(";\n", md_result_file); /* If not empty table */
|
||||
fflush(md_result_file);
|
||||
@ -1179,7 +1188,7 @@ static void print_quoted_xml(FILE *output, char *fname, char *str, uint len)
|
||||
{
|
||||
const char *end;
|
||||
|
||||
fprintf(output, "\t\t<%s>", fname);
|
||||
fprintf(output, "\t\t<field name=\"%s\">", fname);
|
||||
for (end = str + len; str != end; str++)
|
||||
{
|
||||
if (*str == '<')
|
||||
@ -1193,7 +1202,7 @@ static void print_quoted_xml(FILE *output, char *fname, char *str, uint len)
|
||||
else
|
||||
fputc(*str, output);
|
||||
}
|
||||
fprintf(output, "</%s>\n", fname);
|
||||
fprintf(output, "</field>\n");
|
||||
}
|
||||
|
||||
static char *getTableName(int reset)
|
||||
@ -1248,13 +1257,8 @@ static int dump_databases(char **db_names)
|
||||
int result=0;
|
||||
for ( ; *db_names ; db_names++)
|
||||
{
|
||||
/* XML edit - add database element */
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "<%s>\n", *db_names);
|
||||
if (dump_all_tables_in_db(*db_names))
|
||||
result=1;
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "</%s>\n", *db_names);
|
||||
}
|
||||
return result;
|
||||
} /* dump_databases */
|
||||
@ -1267,7 +1271,7 @@ static int init_dumping(char *database)
|
||||
DBerror(sock, "when selecting the database");
|
||||
return 1; /* If --force */
|
||||
}
|
||||
if (!path)
|
||||
if (!path && !opt_xml)
|
||||
{
|
||||
if (opt_databases || opt_alldbs)
|
||||
{
|
||||
@ -1313,6 +1317,8 @@ static int dump_all_tables_in_db(char *database)
|
||||
|
||||
if (init_dumping(database))
|
||||
return 1;
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "<database name=\"%s\">\n", database);
|
||||
if (lock_tables)
|
||||
{
|
||||
DYNAMIC_STRING query;
|
||||
@ -1339,6 +1345,8 @@ static int dump_all_tables_in_db(char *database)
|
||||
if (!dFlag && numrows > 0)
|
||||
dumpTable(numrows,table);
|
||||
}
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "</database>\n");
|
||||
if (lock_tables)
|
||||
mysql_query(sock,"UNLOCK_TABLES");
|
||||
return 0;
|
||||
@ -1375,12 +1383,16 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
|
||||
DBerror(sock, "when doing refresh");
|
||||
/* We shall countinue here, if --force was given */
|
||||
}
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "<database name=\"%s\">\n", db);
|
||||
for (; tables > 0 ; tables-- , table_names++)
|
||||
{
|
||||
numrows = getTableStructure(*table_names, db);
|
||||
if (!dFlag && numrows > 0)
|
||||
dumpTable(numrows, *table_names);
|
||||
}
|
||||
if (opt_xml)
|
||||
fprintf(md_result_file, "</database>\n");
|
||||
if (lock_tables)
|
||||
mysql_query(sock,"UNLOCK_TABLES");
|
||||
return 0;
|
||||
@ -1514,7 +1526,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
dbDisconnect(current_host);
|
||||
fputs("\n", md_result_file);
|
||||
write_footer(md_result_file);
|
||||
if (md_result_file != stdout)
|
||||
my_fclose(md_result_file, MYF(0));
|
||||
my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
|
||||
|
@ -56,6 +56,7 @@ static my_string opt_mysql_unix_port=0;
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int error;
|
||||
my_bool first_argument_uses_wildcards=0;
|
||||
char *wild;
|
||||
MYSQL mysql;
|
||||
MY_INIT(argv[0]);
|
||||
@ -63,21 +64,37 @@ int main(int argc, char **argv)
|
||||
get_options(&argc,&argv);
|
||||
|
||||
wild=0;
|
||||
if (argc && strcont(argv[argc-1],"*?%_"))
|
||||
if (argc)
|
||||
{
|
||||
char *pos;
|
||||
|
||||
wild=argv[--argc];
|
||||
for (pos=wild ; *pos ; pos++)
|
||||
{ /* Unix wildcards to sql */
|
||||
if (*pos == '*')
|
||||
*pos='%';
|
||||
else if (*pos == '?')
|
||||
*pos='_';
|
||||
char *pos= argv[argc-1], *to;
|
||||
for (to= pos ; *pos ; pos++, to++)
|
||||
{
|
||||
switch (*pos)
|
||||
{
|
||||
case '*':
|
||||
*pos= '%';
|
||||
first_argument_uses_wildcards= 1;
|
||||
break;
|
||||
case '?':
|
||||
*pos= '_';
|
||||
first_argument_uses_wildcards= 1;
|
||||
break;
|
||||
case '%':
|
||||
case '_':
|
||||
first_argument_uses_wildcards= 1;
|
||||
break;
|
||||
case '\\':
|
||||
pos++;
|
||||
default: break;
|
||||
}
|
||||
*to= *pos;
|
||||
}
|
||||
*to= *pos; // just to copy a '\0' if '\\' was used
|
||||
}
|
||||
if (first_argument_uses_wildcards)
|
||||
wild= argv[--argc];
|
||||
else if (argc == 3) /* We only want one field */
|
||||
wild=argv[--argc];
|
||||
wild= argv[--argc];
|
||||
|
||||
if (argc > 2)
|
||||
{
|
||||
@ -99,7 +116,7 @@ int main(int argc, char **argv)
|
||||
mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
|
||||
#endif
|
||||
if (!(mysql_real_connect(&mysql,host,user,opt_password,
|
||||
argv[0],opt_mysql_port,opt_mysql_unix_port,
|
||||
(first_argument_uses_wildcards) ? "" : argv[0],opt_mysql_port,opt_mysql_unix_port,
|
||||
0)))
|
||||
{
|
||||
fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
|
||||
|
@ -91,7 +91,7 @@
|
||||
|
||||
|
||||
enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
|
||||
OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT};
|
||||
OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC};
|
||||
|
||||
static int record = 0, opt_sleep=0;
|
||||
static char *db = 0, *pass=0;
|
||||
@ -1850,6 +1850,9 @@ static struct my_option my_long_options[] =
|
||||
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"silent", 's', "Suppress all normal output. Synonym for --quiet.",
|
||||
(gptr*) &silent, (gptr*) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"skip-safemalloc", OPT_SKIP_SAFEMALLOC,
|
||||
"Don't use the memory allocation checking", 0, 0, 0, GET_NO_ARG, NO_ARG,
|
||||
0, 0, 0, 0, 0, 0},
|
||||
{"sleep", 'T', "Sleep always this many seconds on sleep commands",
|
||||
(gptr*) &opt_sleep, (gptr*) &opt_sleep, 0, GET_INT, REQUIRED_ARG, 0, 0, 0,
|
||||
0, 0, 0},
|
||||
@ -1949,6 +1952,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||
if (read_server_arguments(argument))
|
||||
die(NullS);
|
||||
break;
|
||||
case OPT_SKIP_SAFEMALLOC:
|
||||
#ifdef SAFEMALLOC
|
||||
sf_malloc_quick=1;
|
||||
#endif
|
||||
break;
|
||||
case 'V':
|
||||
print_version();
|
||||
exit(0);
|
||||
@ -2323,6 +2331,7 @@ static void var_from_env(const char* name, const char* def_val)
|
||||
static void init_var_hash()
|
||||
{
|
||||
VAR* v;
|
||||
DBUG_ENTER("init_var_hash");
|
||||
if (hash_init(&var_hash, system_charset_info,
|
||||
1024, 0, 0, get_var_key, var_free, MYF(0)))
|
||||
die("Variable hash initialization failed");
|
||||
@ -2332,6 +2341,7 @@ static void init_var_hash()
|
||||
var_from_env("BIG_TEST", opt_big_test ? "1" : "0");
|
||||
v=var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "63",0);
|
||||
hash_insert(&var_hash, (byte*)v);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
|
26
configure.in
26
configure.in
@ -72,12 +72,14 @@ case $MACHINE_TYPE in
|
||||
esac
|
||||
|
||||
# Save some variables and the command line options for mysqlbug
|
||||
SAVE_ASFLAGS="$ASFLAGS"
|
||||
SAVE_CFLAGS="$CFLAGS"
|
||||
SAVE_CXXFLAGS="$CXXFLAGS"
|
||||
SAVE_LDFLAGS="$LDFLAGS"
|
||||
SAVE_CXXLDFLAGS="$CXXLDFLAGS"
|
||||
CONF_COMMAND="$0 $ac_configure_args"
|
||||
AC_SUBST(CONF_COMMAND)
|
||||
AC_SUBST(SAVE_ASFLAGS)
|
||||
AC_SUBST(SAVE_CFLAGS)
|
||||
AC_SUBST(SAVE_CXXFLAGS)
|
||||
AC_SUBST(SAVE_LDFLAGS)
|
||||
@ -602,8 +604,9 @@ AC_ARG_ENABLE(assembler,
|
||||
AC_MSG_CHECKING(if we should use assembler functions)
|
||||
# For now we only support assembler on i386 and sparc systems
|
||||
AM_CONDITIONAL(ASSEMBLER_x86, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "i386")
|
||||
AM_CONDITIONAL(ASSEMBLER_sparc, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparc")
|
||||
AM_CONDITIONAL(ASSEMBLER, test "$ASSEMBLER_x86_TRUE" = "" -o "$ASSEMBLER_sparc_TRUE" = "")
|
||||
AM_CONDITIONAL(ASSEMBLER_sparc32, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparc")
|
||||
AM_CONDITIONAL(ASSEMBLER_sparc64, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparcv9")
|
||||
AM_CONDITIONAL(ASSEMBLER, test "$ASSEMBLER_x86_TRUE" = "" -o "$ASSEMBLER_sparc32_TRUE" = "")
|
||||
|
||||
if test "$ASSEMBLER_TRUE" = ""
|
||||
then
|
||||
@ -674,7 +677,7 @@ else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
MYSQL_SYS_LARGEFILE
|
||||
|
||||
# Types that must be checked AFTER large file support is checked
|
||||
AC_TYPE_SIZE_T
|
||||
@ -917,8 +920,8 @@ case $SYSTEM_TYPE in
|
||||
;;
|
||||
*hpux10.20*)
|
||||
echo "Enabling workarounds for hpux 10.20"
|
||||
CFLAGS="$CFLAGS -DHAVE_BROKEN_SNPRINTF -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
|
||||
CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_SNPRINTF -D_INCLUDE_LONGLONG -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
|
||||
CFLAGS="$CFLAGS -DHAVE_BROKEN_SNPRINTF -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX10 -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
|
||||
CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_SNPRINTF -D_INCLUDE_LONGLONG -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX10 -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
|
||||
if test "$with_named_thread" = "no"
|
||||
then
|
||||
echo "Using --with-named-thread=-lpthread"
|
||||
@ -927,13 +930,19 @@ case $SYSTEM_TYPE in
|
||||
;;
|
||||
*hpux11.*)
|
||||
echo "Enabling workarounds for hpux 11"
|
||||
CFLAGS="$CFLAGS -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
|
||||
CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
|
||||
CFLAGS="$CFLAGS -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
|
||||
CXXFLAGS="$CXXFLAGS -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
|
||||
if test "$with_named_thread" = "no"
|
||||
then
|
||||
echo "Using --with-named-thread=-lpthread"
|
||||
with_named_thread="-lpthread"
|
||||
fi
|
||||
# Fixes for HPUX 11.0 compiler
|
||||
if test "$ac_cv_prog_gcc" = "no"
|
||||
then
|
||||
CFLAGS="$CFLAGS +DD64 -DHAVE_BROKEN_INLINE"
|
||||
CXXFLAGS="$CXXFLAGS +DD64 +O2"
|
||||
fi
|
||||
;;
|
||||
*rhapsody*)
|
||||
if test "$ac_cv_prog_gcc" = "yes"
|
||||
@ -966,7 +975,8 @@ case $SYSTEM_TYPE in
|
||||
;;
|
||||
*freebsd*)
|
||||
echo "Adding fix for interrupted reads"
|
||||
CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000"
|
||||
CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH"
|
||||
CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH"
|
||||
;;
|
||||
*netbsd*)
|
||||
echo "Adding flag -Dunix"
|
||||
|
73
dbug/dbug_add_tags.pl
Executable file
73
dbug/dbug_add_tags.pl
Executable file
@ -0,0 +1,73 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
die "No files specified\n" unless $ARGV[0];
|
||||
|
||||
$ctags="exctags -x -f - --c-types=f -u";
|
||||
|
||||
sub get_tag {
|
||||
local $.; local $_=<TAGS>;
|
||||
($symbol, $line)= /^(.*\S)\s+function\s+(\d+)/;
|
||||
$symbol=$1 if /\s(\S+)\s*\(/;
|
||||
$line=1e50 unless $line;
|
||||
}
|
||||
|
||||
while($src=shift)
|
||||
{
|
||||
warn "==> $src\n";
|
||||
|
||||
$dst=$src.$$;
|
||||
open(TAGS, "$ctags $src|") || die "Cannot exec('$ctags $src'): $!";
|
||||
open(SRC, "<$src") || die "Cannot open $src: $!";
|
||||
open(DST, ">$dst") || die "Cannot create $dst: $!";
|
||||
select DST;
|
||||
|
||||
&get_tag;
|
||||
$in_func=0;
|
||||
while(<SRC>)
|
||||
{
|
||||
my $orig=$_;
|
||||
if ($in_func)
|
||||
{
|
||||
if (/\breturn\b/ && !/\/\*.*\breturn\b.*\*\// && !/;/ )
|
||||
{
|
||||
$_.=<SRC> until /;/;
|
||||
}
|
||||
s/(?<=\s)return\s*;/DBUG_VOID_RETURN;/;
|
||||
s/(?<=\s)return\s*(.+)\s*;/DBUG_RETURN(\1);/s;
|
||||
$ret_line=$. if /DBUG_(VOID_)?RETURN/; #{{
|
||||
print "$tab DBUG_VOID_RETURN;\n" if /^$tab}/ && $ret_line < $.-1;
|
||||
$in_func=0 if /^$tab}/;
|
||||
warn "$src:".($.-1)."\t$orig" if /\breturn\b/;
|
||||
}
|
||||
print;
|
||||
next if $. < $line;
|
||||
die "Something wrong: \$.=$., \$line=$line, \$symbol=$symbol\n" if $. > $line;
|
||||
&get_tag && next if /^\s*inline /;
|
||||
print $_=<SRC> until /{/; $tab=$`;
|
||||
&get_tag && next if /}/; # skip one-liners
|
||||
$semicolon=1;
|
||||
while(<SRC>)
|
||||
{
|
||||
$skip=!$semicolon;
|
||||
$semicolon= /;\s*$/;
|
||||
print && next if $skip ||
|
||||
(/^\s+\w+((::\w+)?|<\w+>)\s+\**\w+/ && !/^\s*return/);
|
||||
last if /DBUG_ENTER/;
|
||||
print "$tab DBUG_ENTER(\"$symbol\");\n";
|
||||
print "\n" unless $_ eq "\n";
|
||||
last;
|
||||
}
|
||||
$in_func=1;
|
||||
&get_tag;
|
||||
redo;
|
||||
}
|
||||
close SRC;
|
||||
close DST;
|
||||
close TAGS;
|
||||
unlink("$src.orig");
|
||||
rename($src, "$src.orig") || die "Cannot rename $src to $src.orig: $!";
|
||||
rename($dst, $src) || die "Cannot rename $dst to $src: $!";
|
||||
}
|
||||
|
||||
warn "All done!\n";
|
||||
|
@ -18,7 +18,7 @@ INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include -I..
|
||||
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
|
||||
../dbug/libdbug.a ../strings/libmystrings.a
|
||||
bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \
|
||||
resolve_stack_dump mysql_install
|
||||
resolve_stack_dump mysql_install
|
||||
|
||||
# Don't update the files from bitkeeper
|
||||
%::SCCS/s.%
|
||||
|
@ -61,26 +61,27 @@ extern const char *client_errors[]; /* Error messages */
|
||||
#define CR_PROBE_SLAVE_HOSTS 2023
|
||||
#define CR_PROBE_SLAVE_CONNECT 2024
|
||||
#define CR_PROBE_MASTER_CONNECT 2025
|
||||
#define CR_SSL_CONNECTION_ERROR 2026
|
||||
|
||||
/* new 4.1 error codes */
|
||||
#define CR_INVALID_CONN_HANDLE 2026
|
||||
#define CR_NULL_POINTER 2027
|
||||
#define CR_NO_PREPARE_STMT 2028
|
||||
#define CR_NOT_ALL_PARAMS_BOUND 2029
|
||||
#define CR_DATA_TRUNCATED 2030
|
||||
#define CR_NO_PARAMETERS_EXISTS 2031
|
||||
#define CR_INVALID_PARAMETER_NO 2032
|
||||
#define CR_INVALID_BUFFER_USE 2033
|
||||
#define CR_UNSUPPORTED_PARAM_TYPE 2034
|
||||
#define CR_INVALID_CONN_HANDLE 2027
|
||||
#define CR_NULL_POINTER 2028
|
||||
#define CR_NO_PREPARE_STMT 2029
|
||||
#define CR_NOT_ALL_PARAMS_BOUND 2030
|
||||
#define CR_DATA_TRUNCATED 2031
|
||||
#define CR_NO_PARAMETERS_EXISTS 2032
|
||||
#define CR_INVALID_PARAMETER_NO 2033
|
||||
#define CR_INVALID_BUFFER_USE 2034
|
||||
#define CR_UNSUPPORTED_PARAM_TYPE 2035
|
||||
|
||||
#define CR_SHARED_MEMORY_CONNECTION 2035
|
||||
#define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2036
|
||||
#define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2037
|
||||
#define CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2038
|
||||
#define CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2039
|
||||
#define CR_SHARED_MEMORY_FILE_MAP_ERROR 2040
|
||||
#define CR_SHARED_MEMORY_MAP_ERROR 2041
|
||||
#define CR_SHARED_MEMORY_EVENT_ERROR 2042
|
||||
#define CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR 2043
|
||||
#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2046
|
||||
#define CR_CONN_UNKNOW_PROTOCOL 2048
|
||||
#define CR_SHARED_MEMORY_CONNECTION 2036
|
||||
#define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2037
|
||||
#define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2038
|
||||
#define CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2039
|
||||
#define CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2040
|
||||
#define CR_SHARED_MEMORY_FILE_MAP_ERROR 2041
|
||||
#define CR_SHARED_MEMORY_MAP_ERROR 2042
|
||||
#define CR_SHARED_MEMORY_EVENT_ERROR 2043
|
||||
#define CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR 2044
|
||||
#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2045
|
||||
#define CR_CONN_UNKNOW_PROTOCOL 2046
|
||||
|
@ -21,7 +21,8 @@
|
||||
#ifndef _my_alloc_h
|
||||
#define _my_alloc_h
|
||||
|
||||
#define MAX_BLOCK_USAGE_BEFORE_DROP 10
|
||||
#define ALLOC_MAX_BLOCK_TO_DROP 4096
|
||||
#define ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP 10
|
||||
|
||||
typedef struct st_used_mem
|
||||
{ /* struct for once_alloc (block) */
|
||||
|
@ -301,8 +301,10 @@ enum data_file_type {
|
||||
|
||||
/* For number of records */
|
||||
#ifdef BIG_TABLES
|
||||
#define rows2double(A) ulonglong2double(A)
|
||||
typedef my_off_t ha_rows;
|
||||
#else
|
||||
#define rows2double(A) (double) (A)
|
||||
typedef ulong ha_rows;
|
||||
#endif
|
||||
|
||||
|
@ -38,6 +38,14 @@
|
||||
#define HAVE_ERRNO_AS_DEFINE
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
/* Macros to make switching between C and C++ mode easier */
|
||||
#ifdef __cplusplus
|
||||
#define C_MODE_START extern "C" {
|
||||
#define C_MODE_END }
|
||||
#else
|
||||
#define C_MODE_START
|
||||
#define C_MODE_END
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
|
||||
#include <config-win.h>
|
||||
@ -119,7 +127,12 @@
|
||||
#define _H_STRINGS
|
||||
#define _SYS_STREAM_H
|
||||
/* #define _AIX32_CURSES */ /* XXX: this breaks AIX 4.3.3 (others?). */
|
||||
#endif
|
||||
#define ulonglong2double(A) my_ulonglong2double(A)
|
||||
#define my_off_t2double(A) my_ulonglong2double(A)
|
||||
C_MODE_START
|
||||
double my_ulonglong2double(unsigned long long A);
|
||||
C_MODE_END
|
||||
#endif /* _AIX */
|
||||
|
||||
#ifdef HAVE_BROKEN_SNPRINTF /* HPUX 10.20 don't have this defined */
|
||||
#undef HAVE_SNPRINTF
|
||||
@ -128,6 +141,10 @@
|
||||
#undef HAVE_PREAD
|
||||
#undef HAVE_PWRITE
|
||||
#endif
|
||||
#if defined(HAVE_BROKEN_INLINE) && !defined(__cplusplus)
|
||||
#undef inline
|
||||
#define inline
|
||||
#endif
|
||||
|
||||
#ifdef UNDEF_HAVE_GETHOSTBYNAME_R /* For OSF4.x */
|
||||
#undef HAVE_GETHOSTBYNAME_R
|
||||
@ -240,7 +257,7 @@
|
||||
#ifdef DONT_USE_FINITE /* HPUX 11.x has is_finite() */
|
||||
#undef HAVE_FINITE
|
||||
#endif
|
||||
#if defined(HPUX) && defined(_LARGEFILE64_SOURCE) && defined(THREAD)
|
||||
#if defined(HPUX10) && defined(_LARGEFILE64_SOURCE) && defined(THREAD)
|
||||
/* Fix bug in setrlimit */
|
||||
#undef setrlimit
|
||||
#define setrlimit cma_setrlimit64
|
||||
@ -376,7 +393,9 @@ typedef int my_socket; /* File descriptor for sockets */
|
||||
#endif
|
||||
/* Type for fuctions that handles signals */
|
||||
#define sig_handler RETSIGTYPE
|
||||
C_MODE_START
|
||||
typedef void (*sig_return)();/* Returns type from signal */
|
||||
C_MODE_END
|
||||
#if defined(__GNUC__) && !defined(_lint)
|
||||
typedef char pchar; /* Mixed prototypes can take char */
|
||||
typedef char puchar; /* Mixed prototypes can take char */
|
||||
@ -390,8 +409,10 @@ typedef int pbool; /* Mixed prototypes can't take char */
|
||||
typedef int pshort; /* Mixed prototypes can't take short int */
|
||||
typedef double pfloat; /* Mixed prototypes can't take float */
|
||||
#endif
|
||||
C_MODE_START
|
||||
typedef int (*qsort_cmp)(const void *,const void *);
|
||||
typedef int (*qsort_cmp2)(void*, const void *,const void *);
|
||||
C_MODE_END
|
||||
#ifdef HAVE_mit_thread
|
||||
#define qsort_t void
|
||||
#undef QSORT_TYPE_IS_VOID
|
||||
@ -1029,13 +1050,4 @@ typedef union {
|
||||
#define statistic_add(V,C,L) (V)+=(C)
|
||||
#endif
|
||||
|
||||
/* Macros to make switching between C and C++ mode easier */
|
||||
#ifdef __cplusplus
|
||||
#define C_MODE_START extern "C" {
|
||||
#define C_MODE_END }
|
||||
#else
|
||||
#define C_MODE_START
|
||||
#define C_MODE_END
|
||||
#endif
|
||||
|
||||
#endif /* _global_h */
|
||||
#endif /* my_global_h */
|
||||
|
@ -71,7 +71,7 @@ void my_inet_ntoa(struct in_addr in, char *buf);
|
||||
Handling of gethostbyname_r()
|
||||
*/
|
||||
|
||||
#if !defined(HPUX)
|
||||
#if !defined(HPUX10)
|
||||
struct hostent;
|
||||
#endif /* HPUX */
|
||||
#if !defined(HAVE_GETHOSTBYNAME_R)
|
||||
@ -84,7 +84,7 @@ struct hostent *my_gethostbyname_r(const char *name,
|
||||
struct hostent *result, char *buffer,
|
||||
int buflen, int *h_errnop);
|
||||
#define my_gethostbyname_r_free()
|
||||
#if !defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) && !defined(HPUX)
|
||||
#if !defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) && !defined(HPUX10)
|
||||
#define GETHOSTBYNAME_BUFF_SIZE sizeof(struct hostent_data)
|
||||
#endif /* !defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) */
|
||||
|
||||
|
@ -428,7 +428,7 @@ struct tm *localtime_r(const time_t *clock, struct tm *res);
|
||||
|
||||
#endif /* defined(__WIN__) */
|
||||
|
||||
#if defined(HPUX) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
|
||||
#if defined(HPUX10) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
|
||||
#undef pthread_cond_timedwait
|
||||
#define pthread_cond_timedwait(a,b,c) my_pthread_cond_timedwait((a),(b),(c))
|
||||
int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
|
@ -83,7 +83,6 @@ void *tree_search(TREE *tree, void *key, void *custom_arg);
|
||||
int tree_walk(TREE *tree,tree_walk_action action,
|
||||
void *argument, TREE_WALK visit);
|
||||
int tree_delete(TREE *tree, void *key, void *custom_arg);
|
||||
|
||||
void *tree_search_key(TREE *tree, const void *key,
|
||||
TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos,
|
||||
enum ha_rkey_function flag, void *custom_arg);
|
||||
@ -93,6 +92,9 @@ void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs,
|
||||
int r_offs);
|
||||
ha_rows tree_record_pos(TREE *tree, const void *key,
|
||||
enum ha_rkey_function search_flag, void *custom_arg);
|
||||
|
||||
#define TREE_ELEMENT_EXTRA_SIZE (sizeof(TREE_ELEMENT) + sizeof(void*))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -285,7 +285,7 @@ extern uint mi_get_pointer_length(ulonglong file_length, uint def);
|
||||
#define T_VERBOSE (1L << 28)
|
||||
#define T_VERY_SILENT (1L << 29)
|
||||
#define T_WAIT_FOREVER (1L << 30)
|
||||
#define T_WRITE_LOOP (1L << 31)
|
||||
#define T_WRITE_LOOP ((ulong) 1L << 31)
|
||||
|
||||
#define T_REP_ANY (T_REP | T_REP_BY_SORT | T_REP_PARALLEL)
|
||||
|
||||
|
@ -41,12 +41,13 @@ typedef struct st_queue {
|
||||
#define queue_element(queue,index) ((queue)->root[index+1])
|
||||
#define queue_end(queue) ((queue)->root[(queue)->elements])
|
||||
#define queue_replaced(queue) _downheap(queue,1)
|
||||
typedef int (*queue_compare)(void *,byte *, byte *);
|
||||
|
||||
int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
|
||||
pbool max_at_top, int (*compare)(void *,byte *, byte *),
|
||||
pbool max_at_top, queue_compare compare,
|
||||
void *first_cmp_arg);
|
||||
int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
|
||||
pbool max_at_top, int (*compare)(void *,byte *, byte *),
|
||||
pbool max_at_top, queue_compare compare,
|
||||
void *first_cmp_arg);
|
||||
void delete_queue(QUEUE *queue);
|
||||
void queue_insert(QUEUE *queue,byte *element);
|
||||
|
@ -188,7 +188,7 @@ struct st_VioSSLConnectorFd
|
||||
SSL_METHOD* ssl_method_;
|
||||
};
|
||||
|
||||
void sslaccept(struct st_VioSSLAcceptorFd*, Vio*, long timeout);
|
||||
int sslaccept(struct st_VioSSLAcceptorFd*, Vio*, long timeout);
|
||||
int sslconnect(struct st_VioSSLConnectorFd*, Vio*, long timeout);
|
||||
|
||||
struct st_VioSSLConnectorFd
|
||||
@ -245,7 +245,6 @@ struct st_vio
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
SSL* ssl_;
|
||||
my_bool open_;
|
||||
#endif /* HAVE_OPENSSL */
|
||||
#ifdef HAVE_SMEM
|
||||
HANDLE handle_file_map;
|
||||
|
@ -274,6 +274,7 @@ btr_page_create(
|
||||
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
|
||||
MTR_MEMO_PAGE_X_FIX));
|
||||
page_create(page, mtr);
|
||||
buf_block_align(page)->check_index_page_at_flush = TRUE;
|
||||
|
||||
btr_page_set_index_id(page, tree->id, mtr);
|
||||
}
|
||||
@ -713,6 +714,7 @@ btr_create(
|
||||
|
||||
/* Create a new index page on the the allocated segment page */
|
||||
page = page_create(frame, mtr);
|
||||
buf_block_align(page)->check_index_page_at_flush = TRUE;
|
||||
|
||||
/* Set the index id of the page */
|
||||
btr_page_set_index_id(page, index_id, mtr);
|
||||
@ -847,6 +849,7 @@ btr_page_reorganize_low(
|
||||
segment headers, next page-field, etc.) is preserved intact */
|
||||
|
||||
page_create(page, mtr);
|
||||
buf_block_align(page)->check_index_page_at_flush = TRUE;
|
||||
|
||||
/* Copy the records from the temporary space to the recreated page;
|
||||
do not copy the lock bits yet */
|
||||
@ -919,6 +922,7 @@ btr_page_empty(
|
||||
segment headers, next page-field, etc.) is preserved intact */
|
||||
|
||||
page_create(page, mtr);
|
||||
buf_block_align(page)->check_index_page_at_flush = TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
@ -2291,29 +2295,54 @@ btr_check_node_ptr(
|
||||
/****************************************************************
|
||||
Checks the size and number of fields in a record based on the definition of
|
||||
the index. */
|
||||
static
|
||||
|
||||
ibool
|
||||
btr_index_rec_validate(
|
||||
/*====================*/
|
||||
/* out: TRUE if ok */
|
||||
rec_t* rec, /* in: index record */
|
||||
dict_index_t* index) /* in: index */
|
||||
dict_index_t* index, /* in: index */
|
||||
ibool dump_on_error) /* in: TRUE if the function
|
||||
should print hex dump of record
|
||||
and page on error */
|
||||
{
|
||||
dtype_t* type;
|
||||
byte* data;
|
||||
ulint len;
|
||||
ulint n;
|
||||
ulint i;
|
||||
page_t* page;
|
||||
char err_buf[1000];
|
||||
|
||||
page = buf_frame_align(rec);
|
||||
|
||||
if (index->type & DICT_UNIVERSAL) {
|
||||
/* The insert buffer index tree can contain records from any
|
||||
other index: we cannot check the number of fields or
|
||||
their length */
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
n = dict_index_get_n_fields(index);
|
||||
|
||||
if (rec_get_n_fields(rec) != n) {
|
||||
fprintf(stderr, "Record has %lu fields, should have %lu\n",
|
||||
fprintf(stderr,
|
||||
"InnoDB: Record in index %s in table %s, page %lu, at offset %lu\n"
|
||||
"InnoDB: has %lu fields, should have %lu\n",
|
||||
index->name, index->table_name,
|
||||
buf_frame_get_page_no(page), (ulint)(rec - page),
|
||||
rec_get_n_fields(rec), n);
|
||||
|
||||
if (!dump_on_error) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
buf_page_print(page);
|
||||
|
||||
rec_sprintf(err_buf, 900, rec);
|
||||
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
||||
fprintf(stderr, "InnoDB: corrupt record %s\n", err_buf);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
@ -2326,11 +2355,23 @@ btr_index_rec_validate(
|
||||
if (len != UNIV_SQL_NULL && dtype_is_fixed_size(type)
|
||||
&& len != dtype_get_fixed_size(type)) {
|
||||
fprintf(stderr,
|
||||
"Record field %lu len is %lu, should be %lu\n",
|
||||
"InnoDB: Record in index %s in table %s, page %lu, at offset %lu\n"
|
||||
"InnoDB: field %lu len is %lu, should be %lu\n",
|
||||
index->name, index->table_name,
|
||||
buf_frame_get_page_no(page),
|
||||
(ulint)(rec - page),
|
||||
i, len, dtype_get_fixed_size(type));
|
||||
|
||||
if (!dump_on_error) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
buf_page_print(page);
|
||||
|
||||
rec_sprintf(err_buf, 900, rec);
|
||||
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
||||
fprintf(stderr,
|
||||
"InnoDB: corrupt record %s\n", err_buf);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
@ -2361,12 +2402,13 @@ btr_index_page_validate(
|
||||
rec = (&cur)->rec;
|
||||
|
||||
if (page_cur_is_after_last(&cur)) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!btr_index_rec_validate(rec, index)) {
|
||||
if (!btr_index_rec_validate(rec, index, TRUE)) {
|
||||
|
||||
ret = FALSE;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
page_cur_move_to_next(&cur);
|
||||
@ -2423,25 +2465,26 @@ btr_validate_level(
|
||||
|
||||
index = UT_LIST_GET_FIRST(tree->tree_indexes);
|
||||
|
||||
/* Now we are on the desired level */
|
||||
/* Now we are on the desired level. Loop through the pages on that
|
||||
level. */
|
||||
loop:
|
||||
mtr_x_lock(dict_tree_get_lock(tree), &mtr);
|
||||
|
||||
/* Check ordering etc. of records */
|
||||
|
||||
if (!page_validate(page, index)) {
|
||||
fprintf(stderr, "Error in page %lu in index %s\n",
|
||||
buf_frame_get_page_no(page), index->name);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error in page %lu in index %s table %s, index tree level %lu\n",
|
||||
buf_frame_get_page_no(page), index->name,
|
||||
index->table_name, level);
|
||||
|
||||
ret = FALSE;
|
||||
}
|
||||
} else if (level == 0) {
|
||||
/* We are on level 0. Check that the records have the right
|
||||
number of fields, and field lengths are right. */
|
||||
|
||||
if (level == 0) {
|
||||
if (!btr_index_page_validate(page, index)) {
|
||||
fprintf(stderr,
|
||||
"Error in page %lu in index %s, level %lu\n",
|
||||
buf_frame_get_page_no(page), index->name,
|
||||
level);
|
||||
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
@ -2464,14 +2507,17 @@ loop:
|
||||
UT_LIST_GET_FIRST(tree->tree_indexes)) >= 0) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error on pages %lu and %lu in index %s\n",
|
||||
"InnoDB: Error on pages %lu and %lu in index %s table %s\n",
|
||||
buf_frame_get_page_no(page),
|
||||
right_page_no,
|
||||
index->name);
|
||||
index->name, index->table_name);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: records in wrong order on adjacent pages\n");
|
||||
|
||||
buf_page_print(page);
|
||||
buf_page_print(right_page);
|
||||
|
||||
rec_sprintf(err_buf, 900,
|
||||
page_rec_get_prev(page_get_supremum_rec(page)));
|
||||
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
||||
@ -2494,6 +2540,7 @@ loop:
|
||||
/* Check father node pointers */
|
||||
|
||||
node_ptr = btr_page_get_father_node_ptr(tree, page, &mtr);
|
||||
father_page = buf_frame_align(node_ptr);
|
||||
|
||||
if (btr_node_ptr_get_child_page_no(node_ptr) !=
|
||||
buf_frame_get_page_no(page)
|
||||
@ -2501,13 +2548,16 @@ loop:
|
||||
page_rec_get_prev(page_get_supremum_rec(page)),
|
||||
&mtr)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error on page %lu in index %s\n",
|
||||
"InnoDB: Error on page %lu in index %s table %s\n",
|
||||
buf_frame_get_page_no(page),
|
||||
index->name);
|
||||
index->name, index->table_name);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: node pointer to the page is wrong\n");
|
||||
|
||||
buf_page_print(father_page);
|
||||
buf_page_print(page);
|
||||
|
||||
rec_sprintf(err_buf, 900, node_ptr);
|
||||
|
||||
fprintf(stderr, "InnoDB: node ptr %s\n", err_buf);
|
||||
@ -2528,8 +2578,6 @@ loop:
|
||||
goto node_ptr_fails;
|
||||
}
|
||||
|
||||
father_page = buf_frame_align(node_ptr);
|
||||
|
||||
if (btr_page_get_level(page, &mtr) > 0) {
|
||||
heap = mem_heap_create(256);
|
||||
|
||||
@ -2543,9 +2591,12 @@ loop:
|
||||
if (cmp_dtuple_rec(node_ptr_tuple, node_ptr) != 0) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error on page %lu in index %s\n",
|
||||
"InnoDB: Error on page %lu in index %s table %s\n",
|
||||
buf_frame_get_page_no(page),
|
||||
index->name);
|
||||
index->name, index->table_name);
|
||||
|
||||
buf_page_print(father_page);
|
||||
buf_page_print(page);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: node ptrs differ on levels > 0\n");
|
||||
@ -2595,9 +2646,13 @@ loop:
|
||||
"InnoDB: node pointer to the right page is wrong\n");
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error on page %lu in index %s\n",
|
||||
"InnoDB: Error on page %lu in index %s table %s\n",
|
||||
buf_frame_get_page_no(page),
|
||||
index->name);
|
||||
index->name, index->table_name);
|
||||
|
||||
buf_page_print(father_page);
|
||||
buf_page_print(page);
|
||||
buf_page_print(right_page);
|
||||
}
|
||||
} else {
|
||||
right_father_page = buf_frame_align(
|
||||
@ -2611,9 +2666,14 @@ loop:
|
||||
"InnoDB: node pointer 2 to the right page is wrong\n");
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error on page %lu in index %s\n",
|
||||
"InnoDB: Error on page %lu in index %s table %s\n",
|
||||
buf_frame_get_page_no(page),
|
||||
index->name);
|
||||
index->name, index->table_name);
|
||||
|
||||
buf_page_print(father_page);
|
||||
buf_page_print(right_father_page);
|
||||
buf_page_print(page);
|
||||
buf_page_print(right_page);
|
||||
}
|
||||
|
||||
if (buf_frame_get_page_no(right_father_page)
|
||||
@ -2624,9 +2684,14 @@ loop:
|
||||
"InnoDB: node pointer 3 to the right page is wrong\n");
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error on page %lu in index %s\n",
|
||||
"InnoDB: Error on page %lu in index %s table %s\n",
|
||||
buf_frame_get_page_no(page),
|
||||
index->name);
|
||||
index->name, index->table_name);
|
||||
|
||||
buf_page_print(father_page);
|
||||
buf_page_print(right_father_page);
|
||||
buf_page_print(page);
|
||||
buf_page_print(right_page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,16 +121,19 @@ btr_cur_latch_leaves(
|
||||
{
|
||||
ulint left_page_no;
|
||||
ulint right_page_no;
|
||||
page_t* get_page;
|
||||
|
||||
ut_ad(tree && page && mtr);
|
||||
|
||||
if (latch_mode == BTR_SEARCH_LEAF) {
|
||||
|
||||
btr_page_get(space, page_no, RW_S_LATCH, mtr);
|
||||
get_page = btr_page_get(space, page_no, RW_S_LATCH, mtr);
|
||||
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
|
||||
|
||||
} else if (latch_mode == BTR_MODIFY_LEAF) {
|
||||
|
||||
btr_page_get(space, page_no, RW_X_LATCH, mtr);
|
||||
get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
|
||||
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
|
||||
|
||||
} else if (latch_mode == BTR_MODIFY_TREE) {
|
||||
|
||||
@ -138,15 +141,22 @@ btr_cur_latch_leaves(
|
||||
left_page_no = btr_page_get_prev(page, mtr);
|
||||
|
||||
if (left_page_no != FIL_NULL) {
|
||||
btr_page_get(space, left_page_no, RW_X_LATCH, mtr);
|
||||
get_page = btr_page_get(space, left_page_no,
|
||||
RW_X_LATCH, mtr);
|
||||
buf_block_align(get_page)->check_index_page_at_flush =
|
||||
TRUE;
|
||||
}
|
||||
|
||||
btr_page_get(space, page_no, RW_X_LATCH, mtr);
|
||||
get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
|
||||
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
|
||||
|
||||
right_page_no = btr_page_get_next(page, mtr);
|
||||
|
||||
if (right_page_no != FIL_NULL) {
|
||||
btr_page_get(space, right_page_no, RW_X_LATCH, mtr);
|
||||
get_page = btr_page_get(space, right_page_no,
|
||||
RW_X_LATCH, mtr);
|
||||
buf_block_align(get_page)->check_index_page_at_flush =
|
||||
TRUE;
|
||||
}
|
||||
|
||||
} else if (latch_mode == BTR_SEARCH_PREV) {
|
||||
@ -157,9 +167,12 @@ btr_cur_latch_leaves(
|
||||
if (left_page_no != FIL_NULL) {
|
||||
cursor->left_page = btr_page_get(space, left_page_no,
|
||||
RW_S_LATCH, mtr);
|
||||
buf_block_align(
|
||||
cursor->left_page)->check_index_page_at_flush = TRUE;
|
||||
}
|
||||
|
||||
btr_page_get(space, page_no, RW_S_LATCH, mtr);
|
||||
get_page = btr_page_get(space, page_no, RW_S_LATCH, mtr);
|
||||
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
|
||||
|
||||
} else if (latch_mode == BTR_MODIFY_PREV) {
|
||||
|
||||
@ -169,9 +182,12 @@ btr_cur_latch_leaves(
|
||||
if (left_page_no != FIL_NULL) {
|
||||
cursor->left_page = btr_page_get(space, left_page_no,
|
||||
RW_X_LATCH, mtr);
|
||||
buf_block_align(
|
||||
cursor->left_page)->check_index_page_at_flush = TRUE;
|
||||
}
|
||||
|
||||
btr_page_get(space, page_no, RW_X_LATCH, mtr);
|
||||
get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
|
||||
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
|
||||
} else {
|
||||
ut_error;
|
||||
}
|
||||
@ -274,6 +290,7 @@ btr_cur_search_to_nth_level(
|
||||
if (btr_search_latch.writer == RW_LOCK_NOT_LOCKED
|
||||
&& latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ
|
||||
&& !estimate
|
||||
&& mode != PAGE_CUR_LE_OR_EXTENDS
|
||||
&& btr_search_guess_on_hash(index, info, tuple, mode,
|
||||
latch_mode, cursor,
|
||||
has_search_latch, mtr)) {
|
||||
@ -334,12 +351,18 @@ btr_cur_search_to_nth_level(
|
||||
rw_latch = RW_NO_LATCH;
|
||||
buf_mode = BUF_GET;
|
||||
|
||||
/* We use these modified search modes on non-leaf levels of the
|
||||
B-tree. These let us end up in the right B-tree leaf. In that leaf
|
||||
we use the original search mode. */
|
||||
|
||||
if (mode == PAGE_CUR_GE) {
|
||||
page_mode = PAGE_CUR_L;
|
||||
} else if (mode == PAGE_CUR_G) {
|
||||
page_mode = PAGE_CUR_LE;
|
||||
} else if (mode == PAGE_CUR_LE) {
|
||||
page_mode = PAGE_CUR_LE;
|
||||
} else if (mode == PAGE_CUR_LE_OR_EXTENDS) {
|
||||
page_mode = PAGE_CUR_LE_OR_EXTENDS;
|
||||
} else {
|
||||
ut_ad(mode == PAGE_CUR_L);
|
||||
page_mode = PAGE_CUR_L;
|
||||
@ -391,6 +414,8 @@ retry_page_get:
|
||||
goto retry_page_get;
|
||||
}
|
||||
|
||||
buf_block_align(page)->check_index_page_at_flush = TRUE;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
if (rw_latch != RW_NO_LATCH) {
|
||||
buf_page_dbg_add_level(page, SYNC_TREE_NODE);
|
||||
@ -543,6 +568,8 @@ btr_cur_open_at_index_side(
|
||||
ut_ad(0 == ut_dulint_cmp(tree->id,
|
||||
btr_page_get_index_id(page)));
|
||||
|
||||
buf_block_align(page)->check_index_page_at_flush = TRUE;
|
||||
|
||||
if (height == ULINT_UNDEFINED) {
|
||||
/* We are in the root node */
|
||||
|
||||
|
@ -354,6 +354,7 @@ btr_pcur_move_to_next_page(
|
||||
ut_ad(next_page_no != FIL_NULL);
|
||||
|
||||
next_page = btr_page_get(space, next_page_no, cursor->latch_mode, mtr);
|
||||
buf_block_align(next_page)->check_index_page_at_flush = TRUE;
|
||||
|
||||
btr_leaf_page_release(page, cursor->latch_mode, mtr);
|
||||
|
||||
|
@ -331,6 +331,11 @@ buf_page_print(
|
||||
index->table_name,
|
||||
index->name);
|
||||
}
|
||||
} else if (fil_page_get_type(read_buf) == FIL_PAGE_INODE) {
|
||||
fprintf(stderr, "InnoDB: Page may be an 'inode' page\n");
|
||||
} else if (fil_page_get_type(read_buf) == FIL_PAGE_IBUF_FREE_LIST) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Page may be an insert buffer free list page\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,6 +356,8 @@ buf_block_init(
|
||||
|
||||
block->file_page_was_freed = FALSE;
|
||||
|
||||
block->check_index_page_at_flush = FALSE;
|
||||
|
||||
rw_lock_create(&(block->lock));
|
||||
ut_ad(rw_lock_validate(&(block->lock)));
|
||||
|
||||
@ -616,6 +623,29 @@ buf_page_peek_block(
|
||||
return(block);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Resets the check_index_page_at_flush field of a page if found in the buffer
|
||||
pool. */
|
||||
|
||||
void
|
||||
buf_reset_check_index_page_at_flush(
|
||||
/*================================*/
|
||||
ulint space, /* in: space id */
|
||||
ulint offset) /* in: page number */
|
||||
{
|
||||
buf_block_t* block;
|
||||
|
||||
mutex_enter_fast(&(buf_pool->mutex));
|
||||
|
||||
block = buf_page_hash_get(space, offset);
|
||||
|
||||
if (block) {
|
||||
block->check_index_page_at_flush = FALSE;
|
||||
}
|
||||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Returns the current state of is_hashed of a page. FALSE if the page is
|
||||
not in the pool. NOTE that this operation does not fix the page in the
|
||||
@ -1185,6 +1215,8 @@ buf_page_init(
|
||||
block->space = space;
|
||||
block->offset = offset;
|
||||
|
||||
block->check_index_page_at_flush = FALSE;
|
||||
|
||||
block->lock_hash_val = lock_rec_hash(space, offset);
|
||||
block->lock_mutex = NULL;
|
||||
|
||||
@ -1326,11 +1358,6 @@ buf_page_create(
|
||||
|
||||
free_block = buf_LRU_get_free_block();
|
||||
|
||||
/* Delete possible entries for the page from the insert buffer:
|
||||
such can exist if the page belonged to an index which was dropped */
|
||||
|
||||
ibuf_merge_or_delete_for_page(NULL, space, offset);
|
||||
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
block = buf_page_hash_get(space, offset);
|
||||
@ -1378,6 +1405,11 @@ buf_page_create(
|
||||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
|
||||
/* Delete possible entries for the page from the insert buffer:
|
||||
such can exist if the page belonged to an index which was dropped */
|
||||
|
||||
ibuf_merge_or_delete_for_page(NULL, space, offset);
|
||||
|
||||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin();
|
||||
|
||||
|
@ -15,6 +15,7 @@ Created 11/11/1995 Heikki Tuuri
|
||||
|
||||
#include "ut0byte.h"
|
||||
#include "ut0lst.h"
|
||||
#include "page0page.h"
|
||||
#include "fil0fil.h"
|
||||
#include "buf0buf.h"
|
||||
#include "buf0lru.h"
|
||||
@ -225,6 +226,24 @@ buf_flush_buffered_writes(void)
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < trx_doublewrite->first_free; i++) {
|
||||
block = trx_doublewrite->buf_block_arr[i];
|
||||
|
||||
if (block->check_index_page_at_flush
|
||||
&& !page_simple_validate(block->frame)) {
|
||||
|
||||
buf_page_print(block->frame);
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Apparent corruption of an index page\n"
|
||||
"InnoDB: to be written to data file. We intentionally crash server\n"
|
||||
"InnoDB: to prevent corrupt data from ending up in data\n"
|
||||
"InnoDB: files.\n");
|
||||
ut_a(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (trx_doublewrite->first_free > TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
|
||||
len = TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE;
|
||||
} else {
|
||||
|
@ -86,6 +86,8 @@ else
|
||||
fi
|
||||
|
||||
case "$target_os" in
|
||||
lin*)
|
||||
CFLAGS="$CFLAGS -DUNIV_LINUX";;
|
||||
hpux10*)
|
||||
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX -DUNIV_HPUX10";;
|
||||
hp*)
|
||||
|
@ -1060,20 +1060,24 @@ dict_create_or_check_foreign_constraint_tables(void)
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
|
||||
trx = trx_allocate_for_mysql();
|
||||
|
||||
trx->op_info = (char *) "creating foreign key sys tables";
|
||||
|
||||
row_mysql_lock_data_dictionary(trx);
|
||||
|
||||
if (table1) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: dropping incompletely created SYS_FOREIGN table\n");
|
||||
row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
|
||||
row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx);
|
||||
}
|
||||
|
||||
if (table2) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: dropping incompletely created SYS_FOREIGN_COLS table\n");
|
||||
row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
|
||||
row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx);
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
@ -1122,8 +1126,8 @@ dict_create_or_check_foreign_constraint_tables(void)
|
||||
fprintf(stderr,
|
||||
"InnoDB: dropping incompletely created SYS_FOREIGN tables\n");
|
||||
|
||||
row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
|
||||
row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
|
||||
row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx);
|
||||
row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx);
|
||||
|
||||
error = DB_MUST_GET_MORE_FILE_SPACE;
|
||||
}
|
||||
@ -1132,6 +1136,8 @@ dict_create_or_check_foreign_constraint_tables(void)
|
||||
|
||||
trx->op_info = (char *) "";
|
||||
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
||||
trx_free_for_mysql(trx);
|
||||
|
||||
if (error == DB_SUCCESS) {
|
||||
@ -1139,8 +1145,6 @@ dict_create_or_check_foreign_constraint_tables(void)
|
||||
"InnoDB: Foreign key constraint system tables created\n");
|
||||
}
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,17 @@ Created 1/8/1996 Heikki Tuuri
|
||||
|
||||
dict_sys_t* dict_sys = NULL; /* the dictionary system */
|
||||
|
||||
rw_lock_t dict_foreign_key_check_lock;
|
||||
rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
|
||||
this in X-mode; implicit or backround
|
||||
operations purge, rollback, foreign
|
||||
key checks reserve this in S-mode; we
|
||||
cannot trust that MySQL protects
|
||||
implicit or background operations
|
||||
a table drop since MySQL does not
|
||||
know of them; therefore we need this;
|
||||
NOTE: a transaction which reserves
|
||||
this must keep book on the mode in
|
||||
trx->dict_operation_lock_mode */
|
||||
|
||||
#define DICT_HEAP_SIZE 100 /* initial memory heap size when
|
||||
creating a table or index object */
|
||||
@ -175,6 +185,58 @@ dict_foreign_free(
|
||||
/*==============*/
|
||||
dict_foreign_t* foreign); /* in, own: foreign key struct */
|
||||
|
||||
/************************************************************************
|
||||
Checks if the database name in two table names is the same. */
|
||||
static
|
||||
ibool
|
||||
dict_tables_have_same_db(
|
||||
/*=====================*/
|
||||
/* out: TRUE if same db name */
|
||||
char* name1, /* in: table name in the form dbname '/' tablename */
|
||||
char* name2) /* in: table name in the form dbname '/' tablename */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < 100000; i++) {
|
||||
if (name1[i] == '/' && name2[i] == '/') {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
if (name1[i] != name2[i]) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
ut_a(0);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Return the end of table name where we have removed dbname and '/'. */
|
||||
static
|
||||
char*
|
||||
dict_remove_db_name(
|
||||
/*================*/
|
||||
/* out: table name */
|
||||
char* name) /* in: table name in the form dbname '/' tablename */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < 100000 ; i++) {
|
||||
if (name[i] == '/') {
|
||||
|
||||
return(name + i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
ut_a(0);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Reserves the dictionary system mutex for MySQL. */
|
||||
|
||||
@ -509,9 +571,8 @@ dict_init(void)
|
||||
|
||||
UT_LIST_INIT(dict_sys->table_LRU);
|
||||
|
||||
rw_lock_create(&dict_foreign_key_check_lock);
|
||||
rw_lock_set_level(&dict_foreign_key_check_lock,
|
||||
SYNC_FOREIGN_KEY_CHECK);
|
||||
rw_lock_create(&dict_operation_lock);
|
||||
rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
@ -1851,14 +1912,14 @@ loop:
|
||||
|
||||
/*************************************************************************
|
||||
Accepts a specified string. Comparisons are case-insensitive. */
|
||||
static
|
||||
|
||||
char*
|
||||
dict_accept(
|
||||
/*========*/
|
||||
/* out: if string was accepted, the pointer
|
||||
is moved after that, else ptr is returned */
|
||||
char* ptr, /* in: scan from this */
|
||||
const char* string, /* in: accept only this string as the next
|
||||
const char* string,/* in: accept only this string as the next
|
||||
non-whitespace string */
|
||||
ibool* success)/* out: TRUE if accepted */
|
||||
{
|
||||
@ -1920,7 +1981,8 @@ dict_scan_col(
|
||||
|
||||
old_ptr = ptr;
|
||||
|
||||
while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`') {
|
||||
while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`'
|
||||
&& *ptr != '\0') {
|
||||
|
||||
ptr++;
|
||||
}
|
||||
@ -1994,7 +2056,7 @@ dict_scan_table_name(
|
||||
|
||||
old_ptr = ptr;
|
||||
|
||||
while (!isspace(*ptr) && *ptr != '(' && *ptr != '`') {
|
||||
while (!isspace(*ptr) && *ptr != '(' && *ptr != '`' && *ptr != '\0') {
|
||||
if (*ptr == '.') {
|
||||
dot_ptr = ptr;
|
||||
}
|
||||
@ -2019,7 +2081,13 @@ dict_scan_table_name(
|
||||
ut_cpy_in_lower_case(second_table_name + i, old_ptr,
|
||||
ptr - old_ptr);
|
||||
#else
|
||||
ut_memcpy(second_table_name + i, old_ptr, ptr - old_ptr);
|
||||
if (srv_lower_case_table_names) {
|
||||
ut_cpy_in_lower_case(second_table_name + i, old_ptr,
|
||||
ptr - old_ptr);
|
||||
} else {
|
||||
ut_memcpy(second_table_name + i, old_ptr,
|
||||
ptr - old_ptr);
|
||||
}
|
||||
#endif
|
||||
second_table_name[i + (ptr - old_ptr)] = '\0';
|
||||
} else {
|
||||
@ -2027,7 +2095,12 @@ dict_scan_table_name(
|
||||
ut_cpy_in_lower_case(second_table_name, old_ptr,
|
||||
ptr - old_ptr);
|
||||
#else
|
||||
if (srv_lower_case_table_names) {
|
||||
ut_cpy_in_lower_case(second_table_name, old_ptr,
|
||||
ptr - old_ptr);
|
||||
} else {
|
||||
ut_memcpy(second_table_name, old_ptr, ptr - old_ptr);
|
||||
}
|
||||
#endif
|
||||
second_table_name[dot_ptr - old_ptr] = '/';
|
||||
second_table_name[ptr - old_ptr] = '\0';
|
||||
@ -2044,6 +2117,44 @@ dict_scan_table_name(
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Skips one 'word', like an id. For the lexical definition of 'word', see the
|
||||
code below. */
|
||||
static
|
||||
char*
|
||||
dict_skip_word(
|
||||
/*===========*/
|
||||
/* out: scanned to */
|
||||
char* ptr, /* in: scanned to */
|
||||
ibool* success)/* out: TRUE if success, FALSE if just spaces left in
|
||||
string */
|
||||
{
|
||||
*success = FALSE;
|
||||
|
||||
while (isspace(*ptr)) {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (*ptr == '\0') {
|
||||
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
if (*ptr == '`') {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != '`'
|
||||
&& *ptr != '\0') {
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
*success = TRUE;
|
||||
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Returns the number of opening brackets '(' subtracted by the number
|
||||
of closing brackets ')' between string and ptr. */
|
||||
@ -2113,7 +2224,6 @@ dict_create_foreign_constraints(
|
||||
if (table == NULL) {
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
loop:
|
||||
ptr = dict_scan_to(ptr, (char *) "FOREIGN");
|
||||
|
||||
@ -2142,7 +2252,19 @@ loop:
|
||||
ptr = dict_accept(ptr, (char *) "(", &success);
|
||||
|
||||
if (!success) {
|
||||
goto loop;
|
||||
/* MySQL allows also an index id before the '('; we
|
||||
skip it */
|
||||
ptr = dict_skip_word(ptr, &success);
|
||||
|
||||
if (!success) {
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, (char *) "(", &success);
|
||||
|
||||
if (!success) {
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
@ -2217,6 +2339,7 @@ col_loop1:
|
||||
|
||||
if (!success) {
|
||||
dict_foreign_free(foreign);
|
||||
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
|
||||
@ -2230,6 +2353,7 @@ col_loop2:
|
||||
|
||||
if (!success) {
|
||||
dict_foreign_free(foreign);
|
||||
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
|
||||
@ -2257,14 +2381,20 @@ col_loop2:
|
||||
ptr = dict_accept(ptr, "DELETE", &success);
|
||||
|
||||
if (!success) {
|
||||
dict_foreign_free(foreign);
|
||||
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "RESTRICT", &success);
|
||||
|
||||
if (success) {
|
||||
goto try_find_index;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "CASCADE", &success);
|
||||
|
||||
if (success) {
|
||||
|
||||
foreign->type = DICT_FOREIGN_ON_DELETE_CASCADE;
|
||||
|
||||
goto try_find_index;
|
||||
@ -2273,13 +2403,19 @@ col_loop2:
|
||||
ptr = dict_accept(ptr, "SET", &success);
|
||||
|
||||
if (!success) {
|
||||
dict_foreign_free(foreign);
|
||||
|
||||
goto try_find_index;
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "NULL", &success);
|
||||
|
||||
if (success) {
|
||||
if (!success) {
|
||||
dict_foreign_free(foreign);
|
||||
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
|
||||
for (j = 0; j < foreign->n_fields; j++) {
|
||||
if ((dict_index_get_nth_type(
|
||||
foreign->foreign_index, j)->prtype)
|
||||
@ -2289,16 +2425,25 @@ col_loop2:
|
||||
if the column is not allowed to be NULL! */
|
||||
|
||||
dict_foreign_free(foreign);
|
||||
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
}
|
||||
|
||||
foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL;
|
||||
|
||||
goto try_find_index;
|
||||
try_find_index:
|
||||
/* We check that there are no superfluous words like 'ON UPDATE ...'
|
||||
which we do not support yet. */
|
||||
|
||||
ptr = dict_accept(ptr, (char *) "ON", &success);
|
||||
|
||||
if (success) {
|
||||
dict_foreign_free(foreign);
|
||||
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
|
||||
try_find_index:
|
||||
/* Try to find an index which contains the columns as the first fields
|
||||
and in the right order, and the types are the same as in
|
||||
foreign->foreign_index */
|
||||
@ -2345,6 +2490,7 @@ try_find_index:
|
||||
referenced_table->referenced_list,
|
||||
foreign);
|
||||
}
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
@ -2843,6 +2989,14 @@ dict_update_statistics_low(
|
||||
ulint size;
|
||||
ulint sum_of_index_sizes = 0;
|
||||
|
||||
/* If we have set a high innodb_force_recovery level, do not calculate
|
||||
statistics, as a badly corrupted index can cause a crash in it. */
|
||||
|
||||
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find out the sizes of the indexes and how many different values
|
||||
for the key they approximately have */
|
||||
|
||||
@ -3146,6 +3300,14 @@ dict_print_info_on_foreign_keys_in_create_format(
|
||||
}
|
||||
}
|
||||
|
||||
if (dict_tables_have_same_db(table->name,
|
||||
foreign->referenced_table_name)) {
|
||||
/* Do not print the database name of the referenced
|
||||
table */
|
||||
buf2 += sprintf(buf2, ") REFERENCES `%s` (",
|
||||
dict_remove_db_name(
|
||||
foreign->referenced_table_name));
|
||||
} else {
|
||||
buf2 += sprintf(buf2, ") REFERENCES `%s` (",
|
||||
foreign->referenced_table_name);
|
||||
/* Change the '/' in the table name to '.' */
|
||||
@ -3158,6 +3320,7 @@ dict_print_info_on_foreign_keys_in_create_format(
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < foreign->n_fields; i++) {
|
||||
if ((ulint)(buf2 - buf) >= len) {
|
||||
|
@ -335,7 +335,7 @@ dict_load_fields(
|
||||
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
|
||||
if (rec_get_deleted_flag(rec)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: data dictionary entry for table %s is corrupt!\n",
|
||||
"InnoDB: Error: data dictionary entry for table %s is corrupt!\n"
|
||||
"InnoDB: An index field is delete marked.\n",
|
||||
table->name);
|
||||
}
|
||||
|
@ -967,6 +967,7 @@ fil_extend_last_data_file(
|
||||
fil_node_t* node;
|
||||
fil_space_t* space;
|
||||
fil_system_t* system = fil_system;
|
||||
byte* buf2;
|
||||
byte* buf;
|
||||
ibool success;
|
||||
ulint i;
|
||||
@ -981,19 +982,23 @@ fil_extend_last_data_file(
|
||||
|
||||
fil_node_prepare_for_io(node, system, space);
|
||||
|
||||
buf = mem_alloc(1024 * 1024);
|
||||
buf2 = mem_alloc(1024 * 1024 + UNIV_PAGE_SIZE);
|
||||
buf = ut_align(buf2, UNIV_PAGE_SIZE);
|
||||
|
||||
memset(buf, '\0', 1024 * 1024);
|
||||
|
||||
for (i = 0; i < size_increase / ((1024 * 1024) / UNIV_PAGE_SIZE); i++) {
|
||||
|
||||
success = os_file_write(node->name, node->handle, buf,
|
||||
/* If we use native Windows aio, then also this write is
|
||||
done using it */
|
||||
|
||||
success = os_aio(OS_FILE_WRITE, OS_AIO_SYNC,
|
||||
node->name, node->handle, buf,
|
||||
(node->size << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFF,
|
||||
node->size >> (32 - UNIV_PAGE_SIZE_SHIFT),
|
||||
1024 * 1024);
|
||||
1024 * 1024, NULL, NULL);
|
||||
|
||||
if (!success) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1003,7 +1008,7 @@ fil_extend_last_data_file(
|
||||
os_has_said_disk_full = FALSE;
|
||||
}
|
||||
|
||||
mem_free(buf);
|
||||
mem_free(buf2);
|
||||
|
||||
fil_node_complete_io(node, system, OS_FILE_WRITE);
|
||||
|
||||
@ -1528,7 +1533,6 @@ fil_page_set_type(
|
||||
ulint type) /* in: type */
|
||||
{
|
||||
ut_ad(page);
|
||||
ut_ad((type == FIL_PAGE_INDEX) || (type == FIL_PAGE_UNDO_LOG));
|
||||
|
||||
mach_write_to_2(page + FIL_PAGE_TYPE, type);
|
||||
}
|
||||
|
@ -769,6 +769,8 @@ fsp_init_file_page_low(
|
||||
#endif
|
||||
page = buf_frame_align(ptr);
|
||||
|
||||
buf_block_align(page)->check_index_page_at_flush = FALSE;
|
||||
|
||||
#ifdef UNIV_BASIC_LOG_DEBUG
|
||||
/* printf("In log debug version: Erase the contents of the file page\n");
|
||||
*/
|
||||
@ -1097,7 +1099,7 @@ fsp_fill_free_list(
|
||||
|
||||
/* Initialize the ibuf page in a separate
|
||||
mini-transaction because it is low in the latching
|
||||
order, and we must be able to release the its latch
|
||||
order, and we must be able to release its latch
|
||||
before returning from the fsp routine */
|
||||
|
||||
mtr_start(&ibuf_mtr);
|
||||
@ -1264,7 +1266,12 @@ fsp_alloc_free_page(
|
||||
|
||||
free = xdes_find_bit(descr, XDES_FREE_BIT, TRUE,
|
||||
hint % FSP_EXTENT_SIZE, mtr);
|
||||
ut_a(free != ULINT_UNDEFINED);
|
||||
if (free == ULINT_UNDEFINED) {
|
||||
|
||||
ut_print_buf(((byte*)descr) - 500, 1000);
|
||||
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr);
|
||||
|
||||
@ -1412,7 +1419,12 @@ fsp_free_extent(
|
||||
|
||||
descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr);
|
||||
|
||||
ut_a(xdes_get_state(descr, mtr) != XDES_FREE);
|
||||
if (xdes_get_state(descr, mtr) == XDES_FREE) {
|
||||
|
||||
ut_print_buf(((byte*)descr) - 500, 1000);
|
||||
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
xdes_init(descr, mtr);
|
||||
|
||||
@ -1523,6 +1535,10 @@ fsp_alloc_seg_inode_page(
|
||||
|
||||
page = buf_page_get(space, page_no, RW_X_LATCH, mtr);
|
||||
|
||||
buf_block_align(page)->check_index_page_at_flush = FALSE;
|
||||
|
||||
fil_page_set_type(page, FIL_PAGE_INODE);
|
||||
|
||||
buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
|
||||
|
||||
for (i = 0; i < FSP_SEG_INODES_PER_PAGE; i++) {
|
||||
@ -2298,6 +2314,8 @@ fseg_alloc_free_page_low(
|
||||
fseg_mark_page_used(seg_inode, space, ret_page, mtr);
|
||||
}
|
||||
|
||||
buf_reset_check_index_page_at_flush(space, ret_page);
|
||||
|
||||
return(ret_page);
|
||||
}
|
||||
|
||||
|
@ -1295,6 +1295,8 @@ ibuf_add_free_page(
|
||||
flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
|
||||
page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
|
||||
|
||||
fil_page_set_type(page, FIL_PAGE_IBUF_FREE_LIST);
|
||||
|
||||
ibuf_data->seg_size++;
|
||||
ibuf_data->free_list_len++;
|
||||
|
||||
@ -1305,6 +1307,7 @@ ibuf_add_free_page(
|
||||
|
||||
ibuf_bitmap_page_set_bits(bitmap_page, page_no, IBUF_BITMAP_IBUF,
|
||||
TRUE, &mtr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
@ -399,6 +399,19 @@ btr_print_tree(
|
||||
dict_tree_t* tree, /* in: tree */
|
||||
ulint width); /* in: print this many entries from start
|
||||
and end */
|
||||
/****************************************************************
|
||||
Checks the size and number of fields in a record based on the definition of
|
||||
the index. */
|
||||
|
||||
ibool
|
||||
btr_index_rec_validate(
|
||||
/*====================*/
|
||||
/* out: TRUE if ok */
|
||||
rec_t* rec, /* in: index record */
|
||||
dict_index_t* index, /* in: index */
|
||||
ibool dump_on_error); /* in: TRUE if the function
|
||||
should print hex dump of record
|
||||
and page on error */
|
||||
/******************************************************************
|
||||
Checks the consistency of an index tree. */
|
||||
|
||||
|
@ -298,6 +298,14 @@ btr_pcur_move_to_prev(
|
||||
function may release the page latch */
|
||||
mtr_t* mtr); /* in: mtr */
|
||||
/*************************************************************
|
||||
Moves the persistent cursor to the last record on the same page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_move_to_last_on_page(
|
||||
/*==========================*/
|
||||
btr_pcur_t* cursor, /* in: persistent cursor */
|
||||
mtr_t* mtr); /* in: mtr */
|
||||
/*************************************************************
|
||||
Moves the persistent cursor to the next user record in the tree. If no user
|
||||
records are left, the cursor ends up 'after last in tree'. */
|
||||
UNIV_INLINE
|
||||
|
@ -284,6 +284,24 @@ btr_pcur_move_to_prev_on_page(
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Moves the persistent cursor to the last record on the same page. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_pcur_move_to_last_on_page(
|
||||
/*==========================*/
|
||||
btr_pcur_t* cursor, /* in: persistent cursor */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
UT_NOT_USED(mtr);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
page_cur_set_after_last(buf_frame_align(btr_pcur_get_rec(cursor)),
|
||||
btr_pcur_get_page_cur(cursor));
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Moves the persistent cursor to the next user record in the tree. If no user
|
||||
records are left, the cursor ends up 'after last in tree'. */
|
||||
|
@ -274,6 +274,15 @@ buf_page_peek_block(
|
||||
ulint space, /* in: space id */
|
||||
ulint offset);/* in: page number */
|
||||
/************************************************************************
|
||||
Resets the check_index_page_at_flush field of a page if found in the buffer
|
||||
pool. */
|
||||
|
||||
void
|
||||
buf_reset_check_index_page_at_flush(
|
||||
/*================================*/
|
||||
ulint space, /* in: space id */
|
||||
ulint offset);/* in: page number */
|
||||
/************************************************************************
|
||||
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
|
||||
This function should be called when we free a file page and want the
|
||||
debug version to check that it is not accessed any more unless
|
||||
@ -648,6 +657,14 @@ struct buf_block_struct{
|
||||
then it can wait for this rw-lock */
|
||||
buf_block_t* hash; /* node used in chaining to the page
|
||||
hash table */
|
||||
ibool check_index_page_at_flush;
|
||||
/* TRUE if we know that this is
|
||||
an index page, and want the database
|
||||
to check its consistency before flush;
|
||||
note that there may be pages in the
|
||||
buffer pool which are index pages,
|
||||
but this flag is not set because
|
||||
we do not keep track of all pages */
|
||||
/* 2. Page flushing fields */
|
||||
|
||||
UT_LIST_NODE_T(buf_block_t) flush_list;
|
||||
|
@ -41,6 +41,7 @@ Created 5/24/1996 Heikki Tuuri
|
||||
which is referenced */
|
||||
#define DB_CANNOT_ADD_CONSTRAINT 38 /* adding a foreign key constraint
|
||||
to a table failed */
|
||||
#define DB_CORRUPTION 39 /* data structure corruption noticed */
|
||||
|
||||
/* The following are partial failure codes */
|
||||
#define DB_FAIL 1000
|
||||
|
@ -26,6 +26,18 @@ Created 1/8/1996 Heikki Tuuri
|
||||
#include "ut0byte.h"
|
||||
#include "trx0types.h"
|
||||
|
||||
/*************************************************************************
|
||||
Accepts a specified string. Comparisons are case-insensitive. */
|
||||
|
||||
char*
|
||||
dict_accept(
|
||||
/*========*/
|
||||
/* out: if string was accepted, the pointer
|
||||
is moved after that, else ptr is returned */
|
||||
char* ptr, /* in: scan from this */
|
||||
const char* string,/* in: accept only this string as the next
|
||||
non-whitespace string */
|
||||
ibool* success);/* out: TRUE if accepted */
|
||||
/************************************************************************
|
||||
Decrements the count of open MySQL handles to a table. */
|
||||
|
||||
@ -798,7 +810,7 @@ dict_mutex_exit_for_mysql(void);
|
||||
|
||||
|
||||
extern dict_sys_t* dict_sys; /* the dictionary system */
|
||||
extern rw_lock_t dict_foreign_key_check_lock;
|
||||
extern rw_lock_t dict_operation_lock;
|
||||
|
||||
/* Dictionary system struct */
|
||||
struct dict_sys_struct{
|
||||
|
@ -73,6 +73,8 @@ extern fil_addr_t fil_addr_null;
|
||||
/* File page types */
|
||||
#define FIL_PAGE_INDEX 17855
|
||||
#define FIL_PAGE_UNDO_LOG 2
|
||||
#define FIL_PAGE_INODE 3
|
||||
#define FIL_PAGE_IBUF_FREE_LIST 4
|
||||
|
||||
/* Space types */
|
||||
#define FIL_TABLESPACE 501
|
||||
|
@ -292,6 +292,27 @@ lock_sec_rec_modify_check_and_lock(
|
||||
dict_index_t* index, /* in: secondary index */
|
||||
que_thr_t* thr); /* in: query thread */
|
||||
/*************************************************************************
|
||||
Like the counterpart for a clustered index below, but now we read a
|
||||
secondary index record. */
|
||||
|
||||
ulint
|
||||
lock_sec_rec_read_check_and_lock(
|
||||
/*=============================*/
|
||||
/* out: DB_SUCCESS, DB_LOCK_WAIT,
|
||||
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
|
||||
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
|
||||
does nothing */
|
||||
rec_t* rec, /* in: user record or page supremum record
|
||||
which should be read or passed over by a read
|
||||
cursor */
|
||||
dict_index_t* index, /* in: secondary index */
|
||||
ulint mode, /* in: mode of the lock which the read cursor
|
||||
should set on records: LOCK_S or LOCK_X; the
|
||||
latter is possible in SELECT FOR UPDATE */
|
||||
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
|
||||
LOCK_REC_NOT_GAP */
|
||||
que_thr_t* thr); /* in: query thread */
|
||||
/*************************************************************************
|
||||
Checks if locks of other transactions prevent an immediate read, or passing
|
||||
over by a read cursor, of a clustered index record. If they do, first tests
|
||||
if the query thread should anyway be suspended for some reason; if not, then
|
||||
@ -313,25 +334,8 @@ lock_clust_rec_read_check_and_lock(
|
||||
ulint mode, /* in: mode of the lock which the read cursor
|
||||
should set on records: LOCK_S or LOCK_X; the
|
||||
latter is possible in SELECT FOR UPDATE */
|
||||
que_thr_t* thr); /* in: query thread */
|
||||
/*************************************************************************
|
||||
Like the counterpart for a clustered index above, but now we read a
|
||||
secondary index record. */
|
||||
|
||||
ulint
|
||||
lock_sec_rec_read_check_and_lock(
|
||||
/*=============================*/
|
||||
/* out: DB_SUCCESS, DB_LOCK_WAIT,
|
||||
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
|
||||
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
|
||||
does nothing */
|
||||
rec_t* rec, /* in: user record or page supremum record
|
||||
which should be read or passed over by a read
|
||||
cursor */
|
||||
dict_index_t* index, /* in: secondary index */
|
||||
ulint mode, /* in: mode of the lock which the read cursor
|
||||
should set on records: LOCK_S or LOCK_X; the
|
||||
latter is possible in SELECT FOR UPDATE */
|
||||
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
|
||||
LOCK_REC_NOT_GAP */
|
||||
que_thr_t* thr); /* in: query thread */
|
||||
/*************************************************************************
|
||||
Checks that a record is seen in a consistent read. */
|
||||
@ -509,6 +513,7 @@ lock_validate(void);
|
||||
extern lock_sys_t* lock_sys;
|
||||
|
||||
/* Lock modes and types */
|
||||
/* Basic modes */
|
||||
#define LOCK_NONE 0 /* this flag is used elsewhere to note
|
||||
consistent read */
|
||||
#define LOCK_IS 2 /* intention shared */
|
||||
@ -519,15 +524,20 @@ extern lock_sys_t* lock_sys;
|
||||
in an exclusive mode */
|
||||
#define LOCK_MODE_MASK 0xF /* mask used to extract mode from the
|
||||
type_mode field in a lock */
|
||||
/* Lock types */
|
||||
#define LOCK_TABLE 16 /* these type values should be so high that */
|
||||
#define LOCK_REC 32 /* they can be ORed to the lock mode */
|
||||
#define LOCK_TYPE_MASK 0xF0 /* mask used to extract lock type from the
|
||||
type_mode field in a lock */
|
||||
/* Waiting lock flag */
|
||||
#define LOCK_WAIT 256 /* this wait bit should be so high that
|
||||
it can be ORed to the lock mode and type;
|
||||
when this bit is set, it means that the
|
||||
lock has not yet been granted, it is just
|
||||
waiting for its turn in the wait queue */
|
||||
/* Precise modes */
|
||||
#define LOCK_ORDINARY 0 /* this flag denotes an ordinary next-key lock
|
||||
in contrast to LOCK_GAP or LOCK_REC_NOT_GAP */
|
||||
#define LOCK_GAP 512 /* this gap bit should be so high that
|
||||
it can be ORed to the other flags;
|
||||
when this bit is set, it means that the
|
||||
@ -537,7 +547,15 @@ extern lock_sys_t* lock_sys;
|
||||
the bit is set; locks of this type are created
|
||||
when records are removed from the index chain
|
||||
of records */
|
||||
#define LOCK_INSERT_INTENTION 1024 /* this bit is set when we place a waiting
|
||||
#define LOCK_REC_NOT_GAP 1024 /* this bit means that the lock is only on
|
||||
the index record and does NOT block inserts
|
||||
to the gap before the index record; this is
|
||||
used in the case when we retrieve a record
|
||||
with a unique key, and is also used in
|
||||
locking plain SELECTs (not part of UPDATE
|
||||
or DELETE) when the user has set the READ
|
||||
COMMITTED isolation level */
|
||||
#define LOCK_INSERT_INTENTION 2048 /* this bit is set when we place a waiting
|
||||
gap type record lock request in order to let
|
||||
an insert of an index record to wait until
|
||||
there are no conflicting locks by other
|
||||
|
@ -334,6 +334,7 @@ extern ibool recv_no_ibuf_operations;
|
||||
extern ibool recv_needed_recovery;
|
||||
|
||||
extern ibool recv_is_making_a_backup;
|
||||
extern ulint recv_max_parsed_page_no;
|
||||
|
||||
/* Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
|
||||
times! */
|
||||
|
@ -111,6 +111,7 @@ log. */
|
||||
#define OS_WIN31 1
|
||||
#define OS_WIN95 2
|
||||
#define OS_WINNT 3
|
||||
#define OS_WIN2000 4
|
||||
|
||||
extern ulint os_n_file_reads;
|
||||
extern ulint os_n_file_writes;
|
||||
@ -122,7 +123,7 @@ Gets the operating system version. Currently works only on Windows. */
|
||||
ulint
|
||||
os_get_os_version(void);
|
||||
/*===================*/
|
||||
/* out: OS_WIN95, OS_WIN31, OS_WINNT (2000 == NT) */
|
||||
/* out: OS_WIN95, OS_WIN31, OS_WINNT, or OS_WIN2000 */
|
||||
/********************************************************************
|
||||
Creates the seek mutexes used in positioned reads and writes. */
|
||||
|
||||
|
@ -15,6 +15,15 @@ Created 9/30/1995 Heikki Tuuri
|
||||
typedef void* os_process_t;
|
||||
typedef unsigned long int os_process_id_t;
|
||||
|
||||
/********************************************************************
|
||||
Converts the current process id to a number. It is not guaranteed that the
|
||||
number is unique. In Linux returns the 'process number' of the current
|
||||
thread. That number is the same as one sees in 'top', for example. In Linux
|
||||
the thread id is not the same as one sees in 'top'. */
|
||||
|
||||
ulint
|
||||
os_proc_get_number(void);
|
||||
/*====================*/
|
||||
/********************************************************************
|
||||
Allocates non-cacheable memory. */
|
||||
|
||||
|
@ -16,11 +16,8 @@ Created 9/8/1995 Heikki Tuuri
|
||||
this is also the size of the wait slot array for MySQL threads which
|
||||
can wait inside InnoDB */
|
||||
#ifdef __WIN__
|
||||
/* Windows 95/98/ME seemed to have difficulties creating the all
|
||||
the event semaphores for the wait array slots. If the computer had
|
||||
<= 64 MB memory, InnoDB startup could take minutes or even crash.
|
||||
That is why we set this to only 1000 in Windows. */
|
||||
|
||||
/* Create less event semaphores because Win 98/ME had difficult creating
|
||||
40000 event semaphores */
|
||||
#define OS_THREAD_MAX_N 1000
|
||||
#else
|
||||
#define OS_THREAD_MAX_N 10000
|
||||
|
@ -26,7 +26,12 @@ Created 10/4/1994 Heikki Tuuri
|
||||
#define PAGE_CUR_GE 2
|
||||
#define PAGE_CUR_L 3
|
||||
#define PAGE_CUR_LE 4
|
||||
#define PAGE_CUR_DBG 5
|
||||
#define PAGE_CUR_LE_OR_EXTENDS 5 /* This is a search mode used in
|
||||
"column LIKE 'abc%' ORDER BY column DESC";
|
||||
we have to find strings which are <= 'abc' or
|
||||
which extend it */
|
||||
#define PAGE_CUR_DBG 6
|
||||
|
||||
|
||||
extern ulint page_cur_short_succ;
|
||||
|
||||
|
@ -666,6 +666,16 @@ page_rec_validate(
|
||||
/* out: TRUE if ok */
|
||||
rec_t* rec); /* in: record on the page */
|
||||
/*******************************************************************
|
||||
This function checks the consistency of an index page when we do not
|
||||
know the index. This is also resilient so that this should never crash
|
||||
even if the page is total garbage. */
|
||||
|
||||
ibool
|
||||
page_simple_validate(
|
||||
/*=================*/
|
||||
/* out: TRUE if ok */
|
||||
page_t* page); /* in: index page */
|
||||
/*******************************************************************
|
||||
This function checks the consistency of an index page. */
|
||||
|
||||
ibool
|
||||
|
@ -117,6 +117,7 @@ que_thr_stop(
|
||||
/**************************************************************************
|
||||
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
|
||||
the n_active_thrs counters of the query graph and transaction. */
|
||||
|
||||
void
|
||||
que_thr_move_to_run_state_for_mysql(
|
||||
/*================================*/
|
||||
@ -125,14 +126,17 @@ que_thr_move_to_run_state_for_mysql(
|
||||
/**************************************************************************
|
||||
A patch for MySQL used to 'stop' a dummy query thread used in MySQL
|
||||
select, when there is no error or lock wait. */
|
||||
|
||||
void
|
||||
que_thr_stop_for_mysql_no_error(
|
||||
/*============================*/
|
||||
que_thr_t* thr, /* in: query thread */
|
||||
trx_t* trx); /* in: transaction */
|
||||
/**************************************************************************
|
||||
A patch for MySQL used to 'stop' a dummy query thread used in MySQL
|
||||
select. */
|
||||
A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The
|
||||
query thread is stopped and made inactive, except in the case where
|
||||
it was put to the lock wait state in lock0lock.c, but the lock has already
|
||||
been granted or the transaction chosen as a victim in deadlock resolution. */
|
||||
|
||||
void
|
||||
que_thr_stop_for_mysql(
|
||||
|
@ -45,6 +45,14 @@ read_view_close(
|
||||
/*============*/
|
||||
read_view_t* view); /* in: read view */
|
||||
/*************************************************************************
|
||||
Closes a consistent read view for MySQL. This function is called at an SQL
|
||||
statement end if the trx isolation level is <= TRX_ISO_READ_COMMITTED. */
|
||||
|
||||
void
|
||||
read_view_close_for_mysql(
|
||||
/*======================*/
|
||||
trx_t* trx); /* in: trx which has a read view */
|
||||
/*************************************************************************
|
||||
Checks if a read view sees the specified transaction. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
|
@ -148,12 +148,22 @@ data field in the record. */
|
||||
byte*
|
||||
rec_get_nth_field(
|
||||
/*==============*/
|
||||
/* out: pointer to the field, NULL if SQL null */
|
||||
/* out: pointer to the field */
|
||||
rec_t* rec, /* in: record */
|
||||
ulint n, /* in: index of the field */
|
||||
ulint* len); /* out: length of the field; UNIV_SQL_NULL
|
||||
if SQL null */
|
||||
/****************************************************************
|
||||
Return field length or UNIV_SQL_NULL. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
rec_get_nth_field_len(
|
||||
/*==================*/
|
||||
/* out: length of the field; UNIV_SQL_NULL if SQL
|
||||
null */
|
||||
rec_t* rec, /* in: record */
|
||||
ulint n); /* in: index of the field */
|
||||
/****************************************************************
|
||||
Gets the physical size of a field. Also an SQL null may have a field of
|
||||
size > 0, if the data type is of a fixed size. */
|
||||
UNIV_INLINE
|
||||
|
@ -65,6 +65,24 @@ a field stored to another page: */
|
||||
|
||||
#define REC_2BYTE_EXTERN_MASK 0x4000
|
||||
|
||||
/****************************************************************
|
||||
Return field length or UNIV_SQL_NULL. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
rec_get_nth_field_len(
|
||||
/*==================*/
|
||||
/* out: length of the field; UNIV_SQL_NULL if SQL
|
||||
null */
|
||||
rec_t* rec, /* in: record */
|
||||
ulint n) /* in: index of the field */
|
||||
{
|
||||
ulint len;
|
||||
|
||||
rec_get_nth_field(rec, n, &len);
|
||||
|
||||
return(len);
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
Sets the value of the ith field SQL null bit. */
|
||||
|
||||
|
@ -230,18 +230,35 @@ row_update_cascade_for_mysql(
|
||||
or set null operation */
|
||||
dict_table_t* table); /* in: table where we do the operation */
|
||||
/*************************************************************************
|
||||
Locks the data dictionary exclusively for performing a table create
|
||||
operation. */
|
||||
Locks the data dictionary exclusively for performing a table create or other
|
||||
data dictionary modification operation. */
|
||||
|
||||
void
|
||||
row_mysql_lock_data_dictionary(void);
|
||||
/*================================*/
|
||||
row_mysql_lock_data_dictionary(
|
||||
/*===========================*/
|
||||
trx_t* trx); /* in: transaction */
|
||||
/*************************************************************************
|
||||
Unlocks the data dictionary exclusively lock. */
|
||||
Unlocks the data dictionary exclusive lock. */
|
||||
|
||||
void
|
||||
row_mysql_unlock_data_dictionary(void);
|
||||
/*==================================*/
|
||||
row_mysql_unlock_data_dictionary(
|
||||
/*=============================*/
|
||||
trx_t* trx); /* in: transaction */
|
||||
/*************************************************************************
|
||||
Locks the data dictionary in shared mode from modifications, for performing
|
||||
foreign key check, rollback, or other operation invisible to MySQL. */
|
||||
|
||||
void
|
||||
row_mysql_freeze_data_dictionary(
|
||||
/*=============================*/
|
||||
trx_t* trx); /* in: transaction */
|
||||
/*************************************************************************
|
||||
Unlocks the data dictionary shared lock. */
|
||||
|
||||
void
|
||||
row_mysql_unfreeze_data_dictionary(
|
||||
/*===============================*/
|
||||
trx_t* trx); /* in: transaction */
|
||||
/*************************************************************************
|
||||
Does a table creation operation for MySQL. If the name of the created
|
||||
table ends to characters INNODB_MONITOR, then this also starts
|
||||
@ -312,9 +329,7 @@ row_drop_table_for_mysql(
|
||||
/*=====================*/
|
||||
/* out: error code or DB_SUCCESS */
|
||||
char* name, /* in: table name */
|
||||
trx_t* trx, /* in: transaction handle */
|
||||
ibool has_dict_mutex);/* in: TRUE if the caller already owns the
|
||||
dictionary system mutex */
|
||||
trx_t* trx); /* in: transaction handle */
|
||||
/*************************************************************************
|
||||
Drops a database for MySQL. */
|
||||
|
||||
@ -393,6 +408,10 @@ struct row_prebuilt_struct {
|
||||
an SQL statement: we may have to set
|
||||
an intention lock on the table,
|
||||
create a consistent read view etc. */
|
||||
ibool mysql_has_locked; /* this is set TRUE when MySQL
|
||||
calls external_lock on this handle
|
||||
with a lock flag, and set FALSE when
|
||||
with the F_UNLOCK flag */
|
||||
ibool clust_index_was_generated;
|
||||
/* if the user did not define a
|
||||
primary key in MySQL, then Innobase
|
||||
|
@ -28,6 +28,9 @@ extern os_event_t srv_lock_timeout_thread_event;
|
||||
at a time */
|
||||
#define SRV_AUTO_EXTEND_INCREMENT (8 * ((1024 * 1024) / UNIV_PAGE_SIZE))
|
||||
|
||||
/* This is set to TRUE if the MySQL user has set it in MySQL */
|
||||
extern ibool srv_lower_case_table_names;
|
||||
|
||||
/* Server parameters which are read from the initfile */
|
||||
|
||||
extern char* srv_data_home;
|
||||
@ -57,8 +60,6 @@ extern ulint srv_flush_log_at_trx_commit;
|
||||
|
||||
extern byte srv_latin1_ordering[256];/* The sort order table of the latin1
|
||||
character set */
|
||||
extern ibool srv_use_native_aio;
|
||||
|
||||
extern ulint srv_pool_size;
|
||||
extern ulint srv_mem_pool_size;
|
||||
extern ulint srv_lock_table_size;
|
||||
@ -70,8 +71,9 @@ extern dulint srv_archive_recovery_limit_lsn;
|
||||
|
||||
extern ulint srv_lock_wait_timeout;
|
||||
|
||||
extern char* srv_unix_file_flush_method_str;
|
||||
extern char* srv_file_flush_method_str;
|
||||
extern ulint srv_unix_file_flush_method;
|
||||
extern ulint srv_win_file_flush_method;
|
||||
extern ulint srv_force_recovery;
|
||||
extern ulint srv_thread_concurrency;
|
||||
|
||||
@ -154,13 +156,19 @@ typedef struct srv_sys_struct srv_sys_t;
|
||||
/* The server system */
|
||||
extern srv_sys_t* srv_sys;
|
||||
|
||||
/* Alternatives for the field flush option in Unix; see the InnoDB manual about
|
||||
/* Alternatives for the file flush option in Unix; see the InnoDB manual about
|
||||
what these mean */
|
||||
#define SRV_UNIX_FDATASYNC 1
|
||||
#define SRV_UNIX_FDATASYNC 1 /* This is the default; it is currently mapped
|
||||
to a call of fsync() because fdatasync()
|
||||
seemed to corrupt files in Linux and Solaris */
|
||||
#define SRV_UNIX_O_DSYNC 2
|
||||
#define SRV_UNIX_LITTLESYNC 3
|
||||
#define SRV_UNIX_NOSYNC 4
|
||||
|
||||
/* Alternatives for file i/o in Windows */
|
||||
#define SRV_WIN_IO_NORMAL 1
|
||||
#define SRV_WIN_IO_UNBUFFERED 2 /* This is the default */
|
||||
|
||||
/* Alternatives for srv_force_recovery. Non-zero values are intended
|
||||
to help the user get a damaged database up so that he can dump intact
|
||||
tables and rows with SELECT INTO OUTFILE. The database must not otherwise
|
||||
@ -311,15 +319,17 @@ srv_conc_exit_innodb(
|
||||
trx_t* trx); /* in: transaction object associated with the
|
||||
thread */
|
||||
/*******************************************************************
|
||||
Puts a MySQL OS thread to wait for a lock to be released. */
|
||||
Puts a MySQL OS thread to wait for a lock to be released. If an error
|
||||
occurs during the wait trx->error_state associated with thr is
|
||||
!= DB_SUCCESS when we return. DB_LOCK_WAIT_TIMEOUT and DB_DEADLOCK
|
||||
are possible errors. DB_DEADLOCK is returned if selective deadlock
|
||||
resolution chose this transaction as a victim. */
|
||||
|
||||
ibool
|
||||
void
|
||||
srv_suspend_mysql_thread(
|
||||
/*=====================*/
|
||||
/* out: TRUE if the lock wait timeout was
|
||||
exceeded */
|
||||
que_thr_t* thr); /* in: query thread associated with
|
||||
the MySQL OS thread */
|
||||
que_thr_t* thr); /* in: query thread associated with the MySQL
|
||||
OS thread */
|
||||
/************************************************************************
|
||||
Releases a MySQL OS thread waiting for a lock to be released, if the
|
||||
thread is already suspended. */
|
||||
@ -407,3 +417,4 @@ struct srv_sys_struct{
|
||||
extern ulint srv_n_threads_active[];
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -79,6 +79,8 @@ innobase_shutdown_for_mysql(void);
|
||||
/*=============================*/
|
||||
/* out: DB_SUCCESS or error code */
|
||||
|
||||
extern ulint srv_sizeof_trx_t_in_ha_innodb_cc;
|
||||
|
||||
extern ibool srv_startup_is_before_trx_rollback_phase;
|
||||
extern ibool srv_is_being_shut_down;
|
||||
|
||||
|
@ -335,7 +335,8 @@ ibool
|
||||
rw_lock_own(
|
||||
/*========*/
|
||||
rw_lock_t* lock, /* in: rw-lock */
|
||||
ulint lock_type); /* in: lock type */
|
||||
ulint lock_type); /* in: lock type: RW_LOCK_SHARED,
|
||||
RW_LOCK_EX */
|
||||
/**********************************************************************
|
||||
Checks if somebody has locked the rw-lock in the specified mode. */
|
||||
|
||||
|
@ -371,10 +371,12 @@ or row lock! */
|
||||
#define SYNC_NO_ORDER_CHECK 3000 /* this can be used to suppress
|
||||
latching order checking */
|
||||
#define SYNC_LEVEL_NONE 2000 /* default: level not defined */
|
||||
#define SYNC_FOREIGN_KEY_CHECK 1001
|
||||
#define SYNC_DICT_OPERATION 1001 /* table create, drop, etc. reserve
|
||||
this in X-mode, implicit or backround
|
||||
operations purge, rollback, foreign
|
||||
key checks reserve this in S-mode */
|
||||
#define SYNC_DICT 1000
|
||||
#define SYNC_DICT_AUTOINC_MUTEX 999
|
||||
#define SYNC_PURGE_IS_RUNNING 997
|
||||
#define SYNC_DICT_HEADER 995
|
||||
#define SYNC_IBUF_HEADER 914
|
||||
#define SYNC_IBUF_PESS_INSERT_MUTEX 912
|
||||
|
@ -111,9 +111,6 @@ struct trx_purge_struct{
|
||||
of the trx system and it never ends */
|
||||
que_t* query; /* The query graph which will do the
|
||||
parallelized purge operation */
|
||||
rw_lock_t purge_is_running;/* Purge operation set an x-latch here
|
||||
while it is accessing a table: this
|
||||
prevents dropping of the table */
|
||||
rw_lock_t latch; /* The latch protecting the purge view.
|
||||
A purge operation must acquire an
|
||||
x-latch here for the instant at which
|
||||
|
@ -327,6 +327,7 @@ struct trx_struct{
|
||||
time_t start_time; /* time the trx object was created
|
||||
or the state last time became
|
||||
TRX_ACTIVE */
|
||||
ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */
|
||||
ibool check_foreigns; /* normally TRUE, but if the user
|
||||
wants to suppress foreign key checks,
|
||||
(in table imports, for example) we
|
||||
@ -350,6 +351,9 @@ struct trx_struct{
|
||||
/*------------------------------*/
|
||||
void* mysql_thd; /* MySQL thread handle corresponding
|
||||
to this trx, or NULL */
|
||||
char** mysql_query_str;/* pointer to the field in mysqld_thd
|
||||
which contains the pointer to the
|
||||
current SQL query string */
|
||||
char* mysql_log_file_name;
|
||||
/* if MySQL binlog is used, this field
|
||||
contains a pointer to the latest file
|
||||
@ -371,6 +375,9 @@ struct trx_struct{
|
||||
replication has processed */
|
||||
os_thread_id_t mysql_thread_id;/* id of the MySQL thread associated
|
||||
with this transaction object */
|
||||
ulint mysql_process_no;/* since in Linux, 'top' reports
|
||||
process id's and not thread id's, we
|
||||
store the process number too */
|
||||
/*------------------------------*/
|
||||
ulint n_mysql_tables_in_use; /* number of Innobase tables
|
||||
used in the processing of the current
|
||||
@ -379,9 +386,10 @@ struct trx_struct{
|
||||
/* how many tables the current SQL
|
||||
statement uses, except those
|
||||
in consistent read */
|
||||
ibool has_dict_foreign_key_check_lock;
|
||||
/* TRUE if the trx currently holds
|
||||
an s-lock on dict_foreign_... */
|
||||
ibool dict_operation_lock_mode;
|
||||
/* 0, RW_S_LATCH, or RW_X_LATCH:
|
||||
the latch mode trx currently holds
|
||||
on dict_operation_lock */
|
||||
ibool has_search_latch;
|
||||
/* TRUE if this trx has latched the
|
||||
search system latch in S-mode */
|
||||
@ -420,36 +428,11 @@ struct trx_struct{
|
||||
mysql_trx_list; /* list of transactions created for
|
||||
MySQL */
|
||||
/*------------------------------*/
|
||||
mutex_t undo_mutex; /* mutex protecting the fields in this
|
||||
section (down to undo_no_arr), EXCEPT
|
||||
last_sql_stat_start, which can be
|
||||
accessed only when we know that there
|
||||
cannot be any activity in the undo
|
||||
logs! */
|
||||
dulint undo_no; /* next undo log record number to
|
||||
assign */
|
||||
trx_savept_t last_sql_stat_start;
|
||||
/* undo_no when the last sql statement
|
||||
was started: in case of an error, trx
|
||||
is rolled back down to this undo
|
||||
number; see note at undo_mutex! */
|
||||
trx_rseg_t* rseg; /* rollback segment assigned to the
|
||||
transaction, or NULL if not assigned
|
||||
yet */
|
||||
trx_undo_t* insert_undo; /* pointer to the insert undo log, or
|
||||
NULL if no inserts performed yet */
|
||||
trx_undo_t* update_undo; /* pointer to the update undo log, or
|
||||
NULL if no update performed yet */
|
||||
dulint roll_limit; /* least undo number to undo during
|
||||
a rollback */
|
||||
ulint pages_undone; /* number of undo log pages undone
|
||||
since the last undo log truncation */
|
||||
trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
|
||||
records which are currently processed
|
||||
by a rollback operation */
|
||||
/*------------------------------*/
|
||||
ulint error_state; /* 0 if no error, otherwise error
|
||||
number */
|
||||
number; NOTE That ONLY the thread
|
||||
doing the transaction is allowed to
|
||||
set this field: this is NOT protected
|
||||
by the kernel mutex */
|
||||
void* error_info; /* if the error number indicates a
|
||||
duplicate key error, a pointer to
|
||||
the problematic index is stored here */
|
||||
@ -486,6 +469,12 @@ struct trx_struct{
|
||||
TRX_QUE_LOCK_WAIT, this points to
|
||||
the lock request, otherwise this is
|
||||
NULL */
|
||||
ibool was_chosen_as_deadlock_victim;
|
||||
/* when the transaction decides to wait
|
||||
for a lock, this it sets this to FALSE;
|
||||
if another transaction chooses this
|
||||
transaction as a victim in deadlock
|
||||
resolution, it sets this to TRUE */
|
||||
time_t wait_started; /* lock wait started at this time */
|
||||
UT_LIST_BASE_NODE_T(que_thr_t)
|
||||
wait_thrs; /* query threads belonging to this
|
||||
@ -501,6 +490,34 @@ struct trx_struct{
|
||||
/*------------------------------*/
|
||||
mem_heap_t* read_view_heap; /* memory heap for the read view */
|
||||
read_view_t* read_view; /* consistent read view or NULL */
|
||||
/*------------------------------*/
|
||||
mutex_t undo_mutex; /* mutex protecting the fields in this
|
||||
section (down to undo_no_arr), EXCEPT
|
||||
last_sql_stat_start, which can be
|
||||
accessed only when we know that there
|
||||
cannot be any activity in the undo
|
||||
logs! */
|
||||
dulint undo_no; /* next undo log record number to
|
||||
assign */
|
||||
trx_savept_t last_sql_stat_start;
|
||||
/* undo_no when the last sql statement
|
||||
was started: in case of an error, trx
|
||||
is rolled back down to this undo
|
||||
number; see note at undo_mutex! */
|
||||
trx_rseg_t* rseg; /* rollback segment assigned to the
|
||||
transaction, or NULL if not assigned
|
||||
yet */
|
||||
trx_undo_t* insert_undo; /* pointer to the insert undo log, or
|
||||
NULL if no inserts performed yet */
|
||||
trx_undo_t* update_undo; /* pointer to the update undo log, or
|
||||
NULL if no update performed yet */
|
||||
dulint roll_limit; /* least undo number to undo during
|
||||
a rollback */
|
||||
ulint pages_undone; /* number of undo log pages undone
|
||||
since the last undo log truncation */
|
||||
trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
|
||||
records which are currently processed
|
||||
by a rollback operation */
|
||||
};
|
||||
|
||||
#define TRX_MAX_N_THREADS 32 /* maximum number of concurrent
|
||||
@ -523,6 +540,41 @@ struct trx_struct{
|
||||
#define TRX_QUE_ROLLING_BACK 3 /* transaction is rolling back */
|
||||
#define TRX_QUE_COMMITTING 4 /* transaction is committing */
|
||||
|
||||
/* Transaction isolation levels */
|
||||
#define TRX_ISO_READ_UNCOMMITTED 1 /* dirty read: non-locking
|
||||
SELECTs are performed so that
|
||||
we do not look at a possible
|
||||
earlier version of a record;
|
||||
thus they are not 'consistent'
|
||||
reads under this isolation
|
||||
level; otherwise like level
|
||||
2 */
|
||||
|
||||
#define TRX_ISO_READ_COMMITTED 2 /* somewhat Oracle-like
|
||||
isolation, except that in
|
||||
range UPDATE and DELETE we
|
||||
must block phantom rows
|
||||
with next-key locks;
|
||||
SELECT ... FOR UPDATE and ...
|
||||
LOCK IN SHARE MODE only lock
|
||||
the index records, NOT the
|
||||
gaps before them, and thus
|
||||
allow free inserting;
|
||||
each consistent read reads its
|
||||
own snapshot */
|
||||
|
||||
#define TRX_ISO_REPEATABLE_READ 3 /* this is the default;
|
||||
all consistent reads in the
|
||||
same trx read the same
|
||||
snapshot;
|
||||
full next-key locking used
|
||||
in locking reads to block
|
||||
insertions into gaps */
|
||||
|
||||
#define TRX_ISO_SERIALIZABLE 4 /* all plain SELECTs are
|
||||
converted to LOCK IN SHARE
|
||||
MODE reads */
|
||||
|
||||
/* Types of a trx signal */
|
||||
#define TRX_SIG_NO_SIGNAL 100
|
||||
#define TRX_SIG_TOTAL_ROLLBACK 1
|
||||
|
@ -70,6 +70,11 @@ A waiting record lock can also be of the gap type. A waiting lock request
|
||||
can be granted when there is no conflicting mode lock request by another
|
||||
transaction ahead of it in the explicit lock queue.
|
||||
|
||||
In version 4.0.5 we added yet another explicit lock type: LOCK_REC_NOT_GAP.
|
||||
It only locks the record it is placed on, not the gap before the record.
|
||||
This lock type is necessary to emulate an Oracle-like READ COMMITTED isolation
|
||||
level.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
RULE 1: If there is an implicit x-lock on a record, and there are non-gap
|
||||
-------
|
||||
@ -294,7 +299,9 @@ struct lock_struct{
|
||||
UT_LIST_NODE_T(lock_t)
|
||||
trx_locks; /* list of the locks of the
|
||||
transaction */
|
||||
ulint type_mode; /* lock type, mode, gap flag, and
|
||||
ulint type_mode; /* lock type, mode, LOCK_GAP or
|
||||
LOCK_REC_NOT_GAP,
|
||||
LOCK_INSERT_INTENTION,
|
||||
wait flag, ORed */
|
||||
hash_node_t hash; /* hash chain node for a record lock */
|
||||
dict_index_t* index; /* index for a record lock */
|
||||
@ -309,6 +316,10 @@ Monitor will then fetch it and print */
|
||||
ibool lock_deadlock_found = FALSE;
|
||||
char* lock_latest_err_buf; /* We allocate 5000 bytes for this */
|
||||
|
||||
/* Flags for recursive deadlock search */
|
||||
#define LOCK_VICTIM_IS_START 1
|
||||
#define LOCK_VICTIM_IS_OTHER 2
|
||||
|
||||
/************************************************************************
|
||||
Checks if a lock request results in a deadlock. */
|
||||
static
|
||||
@ -700,23 +711,23 @@ lock_rec_get_gap(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Sets the gap flag of a record lock. */
|
||||
Gets the LOCK_REC_NOT_GAP flag of a record lock. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
lock_rec_set_gap(
|
||||
/*=============*/
|
||||
lock_t* lock, /* in: record lock */
|
||||
ibool val) /* in: value to set: TRUE or FALSE */
|
||||
ibool
|
||||
lock_rec_get_rec_not_gap(
|
||||
/*=====================*/
|
||||
/* out: TRUE if LOCK_REC_NOT_GAP flag set */
|
||||
lock_t* lock) /* in: record lock */
|
||||
{
|
||||
ut_ad(lock);
|
||||
ut_ad((val == TRUE) || (val == FALSE));
|
||||
ut_ad(lock_get_type(lock) == LOCK_REC);
|
||||
|
||||
if (val) {
|
||||
lock->type_mode = lock->type_mode | LOCK_GAP;
|
||||
} else {
|
||||
lock->type_mode = lock->type_mode & ~LOCK_GAP;
|
||||
if (lock->type_mode & LOCK_REC_NOT_GAP) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
@ -739,26 +750,6 @@ lock_rec_get_insert_intention(
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Sets the waiting insert flag of a record lock. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
lock_rec_set_insert_intention(
|
||||
/*==========================*/
|
||||
lock_t* lock, /* in: record lock */
|
||||
ibool val) /* in: value to set: TRUE or FALSE */
|
||||
{
|
||||
ut_ad(lock);
|
||||
ut_ad((val == TRUE) || (val == FALSE));
|
||||
ut_ad(lock_get_type(lock) == LOCK_REC);
|
||||
|
||||
if (val) {
|
||||
lock->type_mode = lock->type_mode | LOCK_INSERT_INTENTION;
|
||||
} else {
|
||||
lock->type_mode = lock->type_mode & ~LOCK_INSERT_INTENTION;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Calculates if lock mode 1 is stronger or equal to lock mode 2. */
|
||||
UNIV_INLINE
|
||||
@ -848,47 +839,52 @@ lock_rec_has_to_wait(
|
||||
/* out: TRUE if new lock has to wait for lock2 to be
|
||||
removed */
|
||||
trx_t* trx, /* in: trx of new lock */
|
||||
ulint mode, /* in: LOCK_S or LOCK_X */
|
||||
ulint gap, /* in: LOCK_GAP or 0 */
|
||||
ulint insert_intention,
|
||||
/* in: LOCK_INSERT_INTENTION or 0 */
|
||||
ulint type_mode,/* in: precise mode of the new lock to set:
|
||||
LOCK_S or LOCK_X, possibly ORed to
|
||||
LOCK_GAP or LOCK_REC_NOT_GAP, LOCK_INSERT_INTENTION */
|
||||
lock_t* lock2) /* in: another record lock; NOTE that it is assumed
|
||||
that this has a lock bit set on the same record as
|
||||
in lock1 */
|
||||
in the new lock we are setting */
|
||||
{
|
||||
ut_ad(trx && lock2);
|
||||
ut_ad(lock_get_type(lock2) == LOCK_REC);
|
||||
ut_ad(mode == LOCK_S || mode == LOCK_X);
|
||||
ut_ad(gap == LOCK_GAP || gap == 0);
|
||||
ut_ad(insert_intention == LOCK_INSERT_INTENTION
|
||||
|| insert_intention == 0);
|
||||
|
||||
if (trx != lock2->trx && !lock_mode_compatible(mode,
|
||||
if (trx != lock2->trx
|
||||
&& !lock_mode_compatible(LOCK_MODE_MASK & type_mode,
|
||||
lock_get_mode(lock2))) {
|
||||
|
||||
/* We have somewhat complex rules when gap type
|
||||
record locks cause waits */
|
||||
/* We have somewhat complex rules when gap type record locks
|
||||
cause waits */
|
||||
|
||||
if (!gap && lock_rec_get_insert_intention(lock2)) {
|
||||
|
||||
/* Request of a full next-key record does not
|
||||
need to wait for an insert intention lock to be
|
||||
removed. This is ok since our rules allow conflicting
|
||||
locks on gaps. This eliminates a spurious deadlock
|
||||
caused by a next-key lock waiting for an insert
|
||||
intention lock; when the insert intention lock was
|
||||
granted, the insert deadlocked on the waiting
|
||||
next-key lock. */
|
||||
if ((type_mode & LOCK_REC_NOT_GAP)
|
||||
&& lock_rec_get_gap(lock2)) {
|
||||
/* Lock on just the record does not need to wait for
|
||||
a gap type lock */
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (insert_intention && lock_rec_get_insert_intention(lock2)) {
|
||||
if ((type_mode & LOCK_GAP)
|
||||
&& lock_rec_get_rec_not_gap(lock2)) {
|
||||
|
||||
/* An insert intention is not disturbed by another
|
||||
insert intention; this removes a spurious deadlock
|
||||
caused by inserts which had to wait for a next-key
|
||||
lock to be removed */
|
||||
/* Lock on gap does not need to wait for
|
||||
a LOCK_REC_NOT_GAP type lock */
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (lock_rec_get_insert_intention(lock2)) {
|
||||
|
||||
/* No lock request needs to wait for an insert
|
||||
intention lock to be removed. This is ok since our
|
||||
rules allow conflicting locks on gaps. This eliminates
|
||||
a spurious deadlock caused by a next-key lock waiting
|
||||
for an insert intention lock; when the insert
|
||||
intention lock was granted, the insert deadlocked on
|
||||
the waiting next-key lock.
|
||||
|
||||
Also, insert intention locks do not disturb each
|
||||
other. */
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
@ -921,10 +917,7 @@ lock_has_to_wait(
|
||||
ut_ad(lock_get_type(lock2) == LOCK_REC);
|
||||
|
||||
return(lock_rec_has_to_wait(lock1->trx,
|
||||
lock_get_mode(lock1),
|
||||
lock_rec_get_gap(lock1),
|
||||
lock_rec_get_insert_intention(lock1),
|
||||
lock2));
|
||||
lock1->type_mode, lock2));
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
@ -1386,32 +1379,41 @@ lock_table_has(
|
||||
/*============= FUNCTIONS FOR ANALYZING RECORD LOCK QUEUE ================*/
|
||||
|
||||
/*************************************************************************
|
||||
Checks if a transaction has a GRANTED explicit lock on rec, where the gap
|
||||
flag or the insert intention flag is not set, stronger or equal to mode.
|
||||
Note that locks on the supremum of a page are a special case here, since
|
||||
they are always gap type locks, even if the gap flag is not set in them. */
|
||||
Checks if a transaction has a GRANTED explicit lock on rec stronger or equal
|
||||
to precise_mode. */
|
||||
UNIV_INLINE
|
||||
lock_t*
|
||||
lock_rec_has_expl(
|
||||
/*==============*/
|
||||
/* out: lock or NULL */
|
||||
ulint mode, /* in: lock mode */
|
||||
ulint precise_mode,/* in: LOCK_S or LOCK_X possibly ORed to
|
||||
LOCK_GAP or LOCK_REC_NOT_GAP,
|
||||
for a supremum record we regard this always a gap
|
||||
type request */
|
||||
rec_t* rec, /* in: record */
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
lock_t* lock;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_ad((mode == LOCK_X) || (mode == LOCK_S));
|
||||
ut_ad((precise_mode & LOCK_MODE_MASK) == LOCK_S
|
||||
|| (precise_mode & LOCK_MODE_MASK) == LOCK_X);
|
||||
ut_ad(!(precise_mode & LOCK_INSERT_INTENTION));
|
||||
|
||||
lock = lock_rec_get_first(rec);
|
||||
|
||||
while (lock) {
|
||||
if (lock->trx == trx
|
||||
&& lock_mode_stronger_or_eq(lock_get_mode(lock), mode)
|
||||
&& lock_mode_stronger_or_eq(lock_get_mode(lock),
|
||||
precise_mode & LOCK_MODE_MASK)
|
||||
&& !lock_get_wait(lock)
|
||||
&& !lock_rec_get_insert_intention(lock)
|
||||
&& !lock_rec_get_gap(lock)) {
|
||||
&& (!lock_rec_get_rec_not_gap(lock)
|
||||
|| (precise_mode & LOCK_REC_NOT_GAP)
|
||||
|| page_rec_is_supremum(rec))
|
||||
&& (!lock_rec_get_gap(lock)
|
||||
|| (precise_mode & LOCK_GAP)
|
||||
|| page_rec_is_supremum(rec))
|
||||
&& (!lock_rec_get_insert_intention(lock))) {
|
||||
|
||||
return(lock);
|
||||
}
|
||||
@ -1429,7 +1431,7 @@ lock_t*
|
||||
lock_rec_other_has_expl_req(
|
||||
/*========================*/
|
||||
/* out: lock or NULL */
|
||||
ulint mode, /* in: lock mode */
|
||||
ulint mode, /* in: LOCK_S or LOCK_X */
|
||||
ulint gap, /* in: LOCK_GAP if also gap locks are taken
|
||||
into account, or 0 if not */
|
||||
ulint wait, /* in: LOCK_WAIT if also waiting locks are
|
||||
@ -1471,27 +1473,21 @@ lock_t*
|
||||
lock_rec_other_has_conflicting(
|
||||
/*===========================*/
|
||||
/* out: lock or NULL */
|
||||
ulint mode, /* in: lock mode of the lock we are going to reserve */
|
||||
ulint gap, /* in: LOCK_GAP if we are going to reserve a gap type
|
||||
lock, else 0 */
|
||||
ulint insert_intention,
|
||||
/* in: LOCK_INSERT_INTENTION if we are going to
|
||||
reserve an insert intention lock */
|
||||
ulint mode, /* in: LOCK_S or LOCK_X,
|
||||
possibly ORed to LOCK_GAP or LOC_REC_NOT_GAP,
|
||||
LOCK_INSERT_INTENTION */
|
||||
rec_t* rec, /* in: record to look at */
|
||||
trx_t* trx) /* in: our transaction */
|
||||
{
|
||||
lock_t* lock;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_ad(mode == LOCK_X || mode == LOCK_S);
|
||||
ut_ad(gap == 0 || gap == LOCK_GAP);
|
||||
ut_ad(insert_intention == LOCK_INSERT_INTENTION
|
||||
|| insert_intention == 0);
|
||||
|
||||
lock = lock_rec_get_first(rec);
|
||||
|
||||
while (lock) {
|
||||
if (lock_rec_has_to_wait(trx, mode, gap, insert_intention,
|
||||
lock)) {
|
||||
if (lock_rec_has_to_wait(trx, mode, lock)) {
|
||||
|
||||
return(lock);
|
||||
}
|
||||
|
||||
@ -1607,14 +1603,14 @@ lock_rec_create(
|
||||
page_no = buf_frame_get_page_no(page);
|
||||
heap_no = rec_get_heap_no(rec);
|
||||
|
||||
/* If rec is the supremum record, then we reset the gap bit, as
|
||||
all locks on the supremum are automatically of the gap type, and
|
||||
we try to avoid unnecessary memory consumption of a new record lock
|
||||
struct for a gap type lock */
|
||||
/* If rec is the supremum record, then we reset the gap and
|
||||
LOCK_REC_NOT_GAP bits, as all locks on the supremum are
|
||||
automatically of the gap type */
|
||||
|
||||
if (rec == page_get_supremum_rec(page)) {
|
||||
ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
|
||||
|
||||
type_mode = type_mode & ~LOCK_GAP;
|
||||
type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
|
||||
}
|
||||
|
||||
/* Make lock bitmap bigger by a safety margin */
|
||||
@ -1666,10 +1662,14 @@ ulint
|
||||
lock_rec_enqueue_waiting(
|
||||
/*=====================*/
|
||||
/* out: DB_LOCK_WAIT, DB_DEADLOCK, or
|
||||
DB_QUE_THR_SUSPENDED */
|
||||
DB_QUE_THR_SUSPENDED, or DB_SUCCESS;
|
||||
DB_SUCCESS means that there was a deadlock,
|
||||
but another transaction was chosen as a
|
||||
victim, and we got the lock immediately:
|
||||
no need to wait then */
|
||||
ulint type_mode,/* in: lock mode this transaction is
|
||||
requesting: LOCK_S or LOCK_X, ORed with
|
||||
LOCK_GAP if a gap lock is requested, ORed
|
||||
requesting: LOCK_S or LOCK_X, possibly ORed
|
||||
with LOCK_GAP or LOCK_REC_NOT_GAP, ORed
|
||||
with LOCK_INSERT_INTENTION if this waiting
|
||||
lock request is set when performing an
|
||||
insert of an index record */
|
||||
@ -1718,7 +1718,16 @@ index->table_name);
|
||||
return(DB_DEADLOCK);
|
||||
}
|
||||
|
||||
/* If there was a deadlock but we chose another transaction as a
|
||||
victim, it is possible that we already have the lock now granted! */
|
||||
|
||||
if (trx->wait_lock == NULL) {
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
trx->que_state = TRX_QUE_LOCK_WAIT;
|
||||
trx->was_chosen_as_deadlock_victim = FALSE;
|
||||
trx->wait_started = time(NULL);
|
||||
|
||||
ut_a(que_thr_stop(thr));
|
||||
@ -1744,8 +1753,8 @@ lock_rec_add_to_queue(
|
||||
/*==================*/
|
||||
/* out: lock where the bit was set, NULL if out
|
||||
of memory */
|
||||
ulint type_mode,/* in: lock mode, wait, and gap flags; type
|
||||
is ignored and replaced by LOCK_REC */
|
||||
ulint type_mode,/* in: lock mode, wait, gap etc. flags;
|
||||
type is ignored and replaced by LOCK_REC */
|
||||
rec_t* rec, /* in: record on page */
|
||||
dict_index_t* index, /* in: index of record */
|
||||
trx_t* trx) /* in: transaction */
|
||||
@ -1759,12 +1768,11 @@ lock_rec_add_to_queue(
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|
||||
|| ((type_mode & LOCK_MODE_MASK) != LOCK_S)
|
||||
|| !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT,
|
||||
rec, trx));
|
||||
|| !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT, rec, trx));
|
||||
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|
||||
|| ((type_mode & LOCK_MODE_MASK) != LOCK_X)
|
||||
|| !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
|
||||
rec, trx));
|
||||
|| !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT, rec, trx));
|
||||
|
||||
type_mode = type_mode | LOCK_REC;
|
||||
|
||||
page = buf_frame_align(rec);
|
||||
@ -1775,12 +1783,15 @@ lock_rec_add_to_queue(
|
||||
struct for a gap type lock */
|
||||
|
||||
if (rec == page_get_supremum_rec(page)) {
|
||||
ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
|
||||
|
||||
type_mode = type_mode & ~LOCK_GAP;
|
||||
/* There should never be LOCK_REC_NOT_GAP on a supremum
|
||||
record, but let us play safe */
|
||||
|
||||
type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
|
||||
}
|
||||
|
||||
/* Look for a waiting lock request on the same record, or for a
|
||||
similar record lock on the same page */
|
||||
/* Look for a waiting lock request on the same record or on a gap */
|
||||
|
||||
heap_no = rec_get_heap_no(rec);
|
||||
lock = lock_rec_get_first_on_page(rec);
|
||||
@ -1795,6 +1806,9 @@ lock_rec_add_to_queue(
|
||||
lock = lock_rec_get_next_on_page(lock);
|
||||
}
|
||||
|
||||
/* Look for a similar record lock on the same page: if one is found
|
||||
and there are no waiting lock requests, we can just set the bit */
|
||||
|
||||
similar_lock = lock_rec_find_similar_on_page(type_mode, rec, trx);
|
||||
|
||||
if (similar_lock && !somebody_waits && !(type_mode & LOCK_WAIT)) {
|
||||
@ -1822,7 +1836,8 @@ lock_rec_lock_fast(
|
||||
ibool impl, /* in: if TRUE, no lock is set if no wait
|
||||
is necessary: we assume that the caller will
|
||||
set an implicit lock */
|
||||
ulint mode, /* in: lock mode */
|
||||
ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly
|
||||
ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
|
||||
rec_t* rec, /* in: record */
|
||||
dict_index_t* index, /* in: index of record */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
@ -1831,7 +1846,15 @@ lock_rec_lock_fast(
|
||||
ulint heap_no;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_ad((mode == LOCK_X) || (mode == LOCK_S));
|
||||
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
|
||||
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
|
||||
ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
|
||||
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
|
||||
ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
|
||||
|| (LOCK_MODE_MASK & mode) == LOCK_X);
|
||||
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|
||||
|| mode - (LOCK_MODE_MASK & mode) == 0
|
||||
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
|
||||
|
||||
heap_no = rec_get_heap_no(rec);
|
||||
|
||||
@ -1877,7 +1900,8 @@ lock_rec_lock_slow(
|
||||
ibool impl, /* in: if TRUE, no lock is set if no wait is
|
||||
necessary: we assume that the caller will set
|
||||
an implicit lock */
|
||||
ulint mode, /* in: lock mode */
|
||||
ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly
|
||||
ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
|
||||
rec_t* rec, /* in: record */
|
||||
dict_index_t* index, /* in: index of record */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
@ -1886,20 +1910,24 @@ lock_rec_lock_slow(
|
||||
ulint err;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_ad((mode == LOCK_X) || (mode == LOCK_S));
|
||||
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
|
||||
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
|
||||
ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
|
||||
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
|
||||
ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
|
||||
|| (LOCK_MODE_MASK & mode) == LOCK_X);
|
||||
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|
||||
|| mode - (LOCK_MODE_MASK & mode) == 0
|
||||
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
|
||||
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
ut_ad((mode != LOCK_S) || lock_table_has(trx, index->table,
|
||||
LOCK_IS));
|
||||
ut_ad((mode != LOCK_X) || lock_table_has(trx, index->table,
|
||||
LOCK_IX));
|
||||
if (lock_rec_has_expl(mode, rec, trx)) {
|
||||
/* The trx already has a strong enough lock on rec: do
|
||||
nothing */
|
||||
|
||||
err = DB_SUCCESS;
|
||||
} else if (lock_rec_other_has_conflicting(mode, 0, 0, rec, trx)) {
|
||||
} else if (lock_rec_other_has_conflicting(mode, rec, trx)) {
|
||||
|
||||
/* If another transaction has a non-gap conflicting request in
|
||||
the queue, as this transaction does not have a lock strong
|
||||
@ -1935,7 +1963,8 @@ lock_rec_lock(
|
||||
ibool impl, /* in: if TRUE, no lock is set if no wait is
|
||||
necessary: we assume that the caller will set
|
||||
an implicit lock */
|
||||
ulint mode, /* in: lock mode */
|
||||
ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly
|
||||
ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
|
||||
rec_t* rec, /* in: record */
|
||||
dict_index_t* index, /* in: index of record */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
@ -1943,10 +1972,15 @@ lock_rec_lock(
|
||||
ulint err;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_ad((mode != LOCK_S) || lock_table_has(thr_get_trx(thr),
|
||||
index->table, LOCK_IS));
|
||||
ut_ad((mode != LOCK_X) || lock_table_has(thr_get_trx(thr),
|
||||
index->table, LOCK_IX));
|
||||
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
|
||||
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
|
||||
ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
|
||||
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
|
||||
ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
|
||||
|| (LOCK_MODE_MASK & mode) == LOCK_X);
|
||||
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|
||||
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
|
||||
|| mode - (LOCK_MODE_MASK & mode) == 0);
|
||||
|
||||
if (lock_rec_lock_fast(impl, mode, rec, index, thr)) {
|
||||
|
||||
@ -2030,7 +2064,14 @@ lock_grant(
|
||||
ut_dulint_get_low(lock->trx->id));
|
||||
}
|
||||
|
||||
/* If we are resolving a deadlock by choosing another transaction
|
||||
as a victim, then our original transaction may not be in the
|
||||
TRX_QUE_LOCK_WAIT state, and there is no need to end the lock wait
|
||||
for it */
|
||||
|
||||
if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) {
|
||||
trx_end_lock_wait(lock->trx);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
@ -2199,9 +2240,10 @@ lock_rec_reset_and_release_wait(
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Makes a record to inherit the locks of another record as gap type locks, but
|
||||
does not reset the lock bits of the other record. Also waiting lock requests
|
||||
on rec are inherited as GRANTED gap locks. */
|
||||
Makes a record to inherit the locks (except LOCK_INSERT_INTENTION type)
|
||||
of another record as gap type locks, but does not reset the lock bits of
|
||||
the other record. Also waiting lock requests on rec are inherited as
|
||||
GRANTED gap locks. */
|
||||
|
||||
void
|
||||
lock_rec_inherit_to_gap(
|
||||
@ -2217,9 +2259,45 @@ lock_rec_inherit_to_gap(
|
||||
lock = lock_rec_get_first(rec);
|
||||
|
||||
while (lock != NULL) {
|
||||
lock_rec_add_to_queue(((lock->type_mode | LOCK_GAP)
|
||||
& ~LOCK_WAIT),
|
||||
if (!lock_rec_get_insert_intention(lock)) {
|
||||
|
||||
lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock)
|
||||
| LOCK_GAP,
|
||||
heir, lock->index, lock->trx);
|
||||
}
|
||||
|
||||
lock = lock_rec_get_next(rec, lock);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Makes a record to inherit the gap locks (except LOCK_INSERT_INTENTION type)
|
||||
of another record as gap type locks, but does not reset the lock bits of the
|
||||
other record. Also waiting lock requests are inherited as GRANTED gap locks. */
|
||||
|
||||
void
|
||||
lock_rec_inherit_to_gap_if_gap_lock(
|
||||
/*================================*/
|
||||
rec_t* heir, /* in: record which inherits */
|
||||
rec_t* rec) /* in: record from which inherited; does NOT reset
|
||||
the locks on this record */
|
||||
{
|
||||
lock_t* lock;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
lock = lock_rec_get_first(rec);
|
||||
|
||||
while (lock != NULL) {
|
||||
if (!lock_rec_get_insert_intention(lock)
|
||||
&& (page_rec_is_supremum(rec)
|
||||
|| !lock_rec_get_rec_not_gap(lock))) {
|
||||
|
||||
lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock)
|
||||
| LOCK_GAP,
|
||||
heir, lock->index, lock->trx);
|
||||
}
|
||||
|
||||
lock = lock_rec_get_next(rec, lock);
|
||||
}
|
||||
}
|
||||
@ -2778,9 +2856,10 @@ lock_update_insert(
|
||||
{
|
||||
lock_mutex_enter_kernel();
|
||||
|
||||
/* Inherit the locks for rec, in gap mode, from the next record */
|
||||
/* Inherit the gap-locking locks for rec, in gap mode, from the next
|
||||
record */
|
||||
|
||||
lock_rec_inherit_to_gap(rec, page_rec_get_next(rec));
|
||||
lock_rec_inherit_to_gap_if_gap_lock(rec, page_rec_get_next(rec));
|
||||
|
||||
lock_mutex_exit_kernel();
|
||||
}
|
||||
@ -2859,20 +2938,23 @@ static
|
||||
ibool
|
||||
lock_deadlock_occurs(
|
||||
/*=================*/
|
||||
/* out: TRUE if a deadlock was detected */
|
||||
/* out: TRUE if a deadlock was detected and we
|
||||
chose trx as a victim; FALSE if no deadlock, or
|
||||
there was a deadlock, but we chose other
|
||||
transaction(s) as victim(s) */
|
||||
lock_t* lock, /* in: lock the transaction is requesting */
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
dict_table_t* table;
|
||||
dict_index_t* index;
|
||||
trx_t* mark_trx;
|
||||
ibool ret;
|
||||
ulint ret;
|
||||
ulint cost = 0;
|
||||
char* err_buf;
|
||||
|
||||
ut_ad(trx && lock);
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
retry:
|
||||
/* We check that adding this trx to the waits-for graph
|
||||
does not produce a cycle. First mark all active transactions
|
||||
with 0: */
|
||||
@ -2886,7 +2968,14 @@ lock_deadlock_occurs(
|
||||
|
||||
ret = lock_deadlock_recursive(trx, trx, lock, &cost);
|
||||
|
||||
if (ret) {
|
||||
if (ret == LOCK_VICTIM_IS_OTHER) {
|
||||
/* We chose some other trx as a victim: retry if there still
|
||||
is a deadlock */
|
||||
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (ret == LOCK_VICTIM_IS_START) {
|
||||
if (lock_get_type(lock) == LOCK_TABLE) {
|
||||
table = lock->un_member.tab_lock.table;
|
||||
index = NULL;
|
||||
@ -2899,19 +2988,6 @@ lock_deadlock_occurs(
|
||||
|
||||
err_buf = lock_latest_err_buf + strlen(lock_latest_err_buf);
|
||||
|
||||
err_buf += sprintf(err_buf,
|
||||
"*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n");
|
||||
|
||||
ut_a(err_buf <= lock_latest_err_buf + 4000);
|
||||
|
||||
if (lock_get_type(lock) == LOCK_REC) {
|
||||
lock_rec_print(err_buf, lock);
|
||||
err_buf += strlen(err_buf);
|
||||
} else {
|
||||
lock_table_print(err_buf, lock);
|
||||
err_buf += strlen(err_buf);
|
||||
}
|
||||
|
||||
ut_a(err_buf <= lock_latest_err_buf + 4000);
|
||||
|
||||
err_buf += sprintf(err_buf,
|
||||
@ -2923,30 +2999,39 @@ lock_deadlock_occurs(
|
||||
sess_raise_error_low(trx, DB_DEADLOCK, lock->type_mode, table,
|
||||
index, NULL, NULL, NULL);
|
||||
*/
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Looks recursively for a deadlock. */
|
||||
static
|
||||
ibool
|
||||
ulint
|
||||
lock_deadlock_recursive(
|
||||
/*====================*/
|
||||
/* out: TRUE if a deadlock was detected
|
||||
or the calculation took too long */
|
||||
/* out: 0 if no deadlock found,
|
||||
LOCK_VICTIM_IS_START if there was a deadlock
|
||||
and we chose 'start' as the victim,
|
||||
LOCK_VICTIM_IS_OTHER if a deadlock
|
||||
was found and we chose some other trx as a
|
||||
victim: we must do the search again in this
|
||||
last case because there may be another
|
||||
deadlock! */
|
||||
trx_t* start, /* in: recursion starting point */
|
||||
trx_t* trx, /* in: a transaction waiting for a lock */
|
||||
lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
|
||||
ulint* cost) /* in/out: number of calculation steps thus
|
||||
far: if this exceeds LOCK_MAX_N_STEPS_...
|
||||
we return TRUE */
|
||||
we return LOCK_VICTIM_IS_START */
|
||||
{
|
||||
lock_t* lock;
|
||||
ulint bit_no;
|
||||
trx_t* lock_trx;
|
||||
char* err_buf;
|
||||
ulint ret;
|
||||
|
||||
ut_a(trx && start && wait_lock);
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
@ -2955,14 +3040,14 @@ lock_deadlock_recursive(
|
||||
/* We have already exhaustively searched the subtree starting
|
||||
from this trx */
|
||||
|
||||
return(FALSE);
|
||||
return(0);
|
||||
}
|
||||
|
||||
*cost = *cost + 1;
|
||||
|
||||
if (*cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK) {
|
||||
|
||||
return(TRUE);
|
||||
return(LOCK_VICTIM_IS_START);
|
||||
}
|
||||
|
||||
lock = wait_lock;
|
||||
@ -2998,6 +3083,9 @@ lock_deadlock_recursive(
|
||||
lock_trx = lock->trx;
|
||||
|
||||
if (lock_trx == start) {
|
||||
/* We came back to the recursion starting
|
||||
point: a deadlock detected */
|
||||
|
||||
err_buf = lock_latest_err_buf;
|
||||
|
||||
ut_sprintf_timestamp(err_buf);
|
||||
@ -3045,11 +3133,60 @@ lock_deadlock_recursive(
|
||||
|
||||
ut_a(err_buf <= lock_latest_err_buf + 4000);
|
||||
|
||||
err_buf += sprintf(err_buf,
|
||||
"*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n");
|
||||
|
||||
ut_a(err_buf <= lock_latest_err_buf + 4000);
|
||||
|
||||
if (lock_get_type(start->wait_lock)
|
||||
== LOCK_REC) {
|
||||
lock_rec_print(err_buf,
|
||||
start->wait_lock);
|
||||
err_buf += strlen(err_buf);
|
||||
} else {
|
||||
lock_table_print(err_buf,
|
||||
start->wait_lock);
|
||||
err_buf += strlen(err_buf);
|
||||
}
|
||||
|
||||
if (lock_print_waits) {
|
||||
printf("Deadlock detected\n");
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
if (ut_dulint_cmp(wait_lock->trx->undo_no,
|
||||
start->undo_no) >= 0) {
|
||||
/* Our recursion starting point
|
||||
transaction is 'smaller', let us
|
||||
choose 'start' as the victim and roll
|
||||
back it */
|
||||
|
||||
return(LOCK_VICTIM_IS_START);
|
||||
}
|
||||
|
||||
lock_deadlock_found = TRUE;
|
||||
|
||||
ut_a(err_buf <= lock_latest_err_buf + 4000);
|
||||
|
||||
/* Let us choose the transaction of wait_lock
|
||||
as a victim to try to avoid deadlocking our
|
||||
recursion starting point transaction */
|
||||
|
||||
err_buf += sprintf(err_buf,
|
||||
"*** WE ROLL BACK TRANSACTION (1)\n");
|
||||
|
||||
wait_lock->trx->was_chosen_as_deadlock_victim
|
||||
= TRUE;
|
||||
|
||||
lock_cancel_waiting_and_release(wait_lock);
|
||||
|
||||
/* Since trx and wait_lock are no longer
|
||||
in the waits-for graph, we can return FALSE;
|
||||
note that our selective algorithm can choose
|
||||
several transactions as victims, but still
|
||||
we may end up rolling back also the recursion
|
||||
starting point transaction! */
|
||||
|
||||
return(LOCK_VICTIM_IS_OTHER);
|
||||
}
|
||||
|
||||
if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) {
|
||||
@ -3058,10 +3195,11 @@ lock_deadlock_recursive(
|
||||
incompatible mode, and is itself waiting for
|
||||
a lock */
|
||||
|
||||
if (lock_deadlock_recursive(start, lock_trx,
|
||||
lock_trx->wait_lock, cost)) {
|
||||
ret = lock_deadlock_recursive(start, lock_trx,
|
||||
lock_trx->wait_lock, cost);
|
||||
if (ret != 0) {
|
||||
|
||||
return(TRUE);
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3153,12 +3291,16 @@ lock_table_remove_low(
|
||||
/*************************************************************************
|
||||
Enqueues a waiting request for a table lock which cannot be granted
|
||||
immediately. Checks for deadlocks. */
|
||||
|
||||
static
|
||||
ulint
|
||||
lock_table_enqueue_waiting(
|
||||
/*=======================*/
|
||||
/* out: DB_LOCK_WAIT, DB_DEADLOCK, or
|
||||
DB_QUE_THR_SUSPENDED */
|
||||
DB_QUE_THR_SUSPENDED, or DB_SUCCESS;
|
||||
DB_SUCCESS means that there was a deadlock,
|
||||
but another transaction was chosen as a
|
||||
victim, and we got the lock immediately:
|
||||
no need to wait then */
|
||||
ulint mode, /* in: lock mode this transaction is
|
||||
requesting */
|
||||
dict_table_t* table, /* in: table */
|
||||
@ -3205,7 +3347,15 @@ table->name);
|
||||
return(DB_DEADLOCK);
|
||||
}
|
||||
|
||||
if (trx->wait_lock == NULL) {
|
||||
/* Deadlock resolution chose another transaction as a victim,
|
||||
and we accidentally got our lock granted! */
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
trx->que_state = TRX_QUE_LOCK_WAIT;
|
||||
trx->was_chosen_as_deadlock_victim = FALSE;
|
||||
trx->wait_started = time(NULL);
|
||||
|
||||
ut_a(que_thr_stop(thr));
|
||||
@ -3292,7 +3442,7 @@ lock_table(
|
||||
if (lock_table_other_has_incompatible(trx, LOCK_WAIT, table, mode)) {
|
||||
|
||||
/* Another trx has a request on the table in an incompatible
|
||||
mode: this trx must wait */
|
||||
mode: this trx may have to wait */
|
||||
|
||||
err = lock_table_enqueue_waiting(mode, table, thr);
|
||||
|
||||
@ -3659,7 +3809,11 @@ lock_rec_print(
|
||||
}
|
||||
|
||||
if (lock_rec_get_gap(lock)) {
|
||||
buf += sprintf(buf, " gap type lock");
|
||||
buf += sprintf(buf, " locks gap before rec");
|
||||
}
|
||||
|
||||
if (lock_rec_get_rec_not_gap(lock)) {
|
||||
buf += sprintf(buf, " locks rec but not gap");
|
||||
}
|
||||
|
||||
if (lock_rec_get_insert_intention(lock)) {
|
||||
@ -4080,7 +4234,8 @@ lock_rec_queue_validate(
|
||||
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
|
||||
LOCK_WAIT, rec, impl_trx)) {
|
||||
|
||||
ut_a(lock_rec_has_expl(LOCK_X, rec, impl_trx));
|
||||
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
|
||||
impl_trx));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4095,7 +4250,8 @@ lock_rec_queue_validate(
|
||||
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
|
||||
LOCK_WAIT, rec, impl_trx)) {
|
||||
|
||||
ut_a(lock_rec_has_expl(LOCK_X, rec, impl_trx));
|
||||
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
|
||||
impl_trx));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4359,8 +4515,8 @@ lock_rec_insert_check_and_lock(
|
||||
|
||||
*inherit = TRUE;
|
||||
|
||||
/* If another transaction has an explicit lock request, gap or not,
|
||||
waiting or granted, on the successor, the insert has to wait.
|
||||
/* If another transaction has an explicit lock request which locks
|
||||
the gap, waiting or granted, on the successor, the insert has to wait.
|
||||
|
||||
An exception is the case where the lock by the another transaction
|
||||
is a gap type lock which it placed to wait for its turn to insert. We
|
||||
@ -4369,8 +4525,10 @@ lock_rec_insert_check_and_lock(
|
||||
had to wait for their insert. Both had waiting gap type lock requests
|
||||
on the successor, which produced an unnecessary deadlock. */
|
||||
|
||||
if (lock_rec_other_has_conflicting(LOCK_X, LOCK_GAP,
|
||||
LOCK_INSERT_INTENTION, next_rec, trx)) {
|
||||
if (lock_rec_other_has_conflicting(LOCK_X | LOCK_GAP
|
||||
| LOCK_INSERT_INTENTION, next_rec, trx)) {
|
||||
|
||||
/* Note that we may get DB_SUCCESS also here! */
|
||||
err = lock_rec_enqueue_waiting(LOCK_X | LOCK_GAP
|
||||
| LOCK_INSERT_INTENTION,
|
||||
next_rec, index, thr);
|
||||
@ -4418,9 +4576,11 @@ lock_rec_convert_impl_to_expl(
|
||||
/* If the transaction has no explicit x-lock set on the
|
||||
record, set one for it */
|
||||
|
||||
if (!lock_rec_has_expl(LOCK_X, rec, impl_trx)) {
|
||||
if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
|
||||
impl_trx)) {
|
||||
|
||||
lock_rec_add_to_queue(LOCK_REC | LOCK_X, rec, index,
|
||||
lock_rec_add_to_queue(LOCK_REC | LOCK_X
|
||||
| LOCK_REC_NOT_GAP, rec, index,
|
||||
impl_trx);
|
||||
}
|
||||
}
|
||||
@ -4466,7 +4626,7 @@ lock_clust_rec_modify_check_and_lock(
|
||||
|
||||
lock_rec_convert_impl_to_expl(rec, index);
|
||||
|
||||
err = lock_rec_lock(TRUE, LOCK_X, rec, index, thr);
|
||||
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr);
|
||||
|
||||
lock_mutex_exit_kernel();
|
||||
|
||||
@ -4511,7 +4671,7 @@ lock_sec_rec_modify_check_and_lock(
|
||||
|
||||
ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
|
||||
|
||||
err = lock_rec_lock(TRUE, LOCK_X, rec, index, thr);
|
||||
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr);
|
||||
|
||||
lock_mutex_exit_kernel();
|
||||
|
||||
@ -4545,6 +4705,8 @@ lock_sec_rec_read_check_and_lock(
|
||||
ulint mode, /* in: mode of the lock which the read cursor
|
||||
should set on records: LOCK_S or LOCK_X; the
|
||||
latter is possible in SELECT FOR UPDATE */
|
||||
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
|
||||
LOCK_REC_NOT_GAP */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
{
|
||||
ulint err;
|
||||
@ -4576,7 +4738,7 @@ lock_sec_rec_read_check_and_lock(
|
||||
lock_rec_convert_impl_to_expl(rec, index);
|
||||
}
|
||||
|
||||
err = lock_rec_lock(FALSE, mode, rec, index, thr);
|
||||
err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
|
||||
|
||||
lock_mutex_exit_kernel();
|
||||
|
||||
@ -4607,13 +4769,16 @@ lock_clust_rec_read_check_and_lock(
|
||||
ulint mode, /* in: mode of the lock which the read cursor
|
||||
should set on records: LOCK_S or LOCK_X; the
|
||||
latter is possible in SELECT FOR UPDATE */
|
||||
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
|
||||
LOCK_REC_NOT_GAP */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
{
|
||||
ulint err;
|
||||
|
||||
ut_ad(index->type & DICT_CLUSTERED);
|
||||
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
|
||||
|
||||
ut_ad(gap_mode == LOCK_ORDINARY || gap_mode == LOCK_GAP
|
||||
|| gap_mode == LOCK_REC_NOT_GAP);
|
||||
if (flags & BTR_NO_LOCKING_FLAG) {
|
||||
|
||||
return(DB_SUCCESS);
|
||||
@ -4631,7 +4796,7 @@ lock_clust_rec_read_check_and_lock(
|
||||
lock_rec_convert_impl_to_expl(rec, index);
|
||||
}
|
||||
|
||||
err = lock_rec_lock(FALSE, mode, rec, index, thr);
|
||||
err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
|
||||
|
||||
lock_mutex_exit_kernel();
|
||||
|
||||
|
@ -1654,8 +1654,8 @@ log_reset_first_header_and_checkpoint(
|
||||
lsn = ut_dulint_add(start, LOG_BLOCK_HDR_SIZE);
|
||||
|
||||
/* Write the label of ibbackup --restore */
|
||||
sprintf(hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, "ibbackup ");
|
||||
ut_sprintf_timestamp(hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
|
||||
sprintf((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, "ibbackup ");
|
||||
ut_sprintf_timestamp((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
|
||||
+ strlen("ibbackup "));
|
||||
buf = hdr_buf + LOG_CHECKPOINT_1;
|
||||
|
||||
|
@ -69,6 +69,8 @@ ulint recv_previous_parsed_rec_type = 999999;
|
||||
ulint recv_previous_parsed_rec_offset = 0;
|
||||
ulint recv_previous_parsed_rec_is_multi = 0;
|
||||
|
||||
ulint recv_max_parsed_page_no = 0;
|
||||
|
||||
/************************************************************
|
||||
Creates the recovery system. */
|
||||
|
||||
@ -141,7 +143,13 @@ recv_sys_empty_hash(void)
|
||||
/*=====================*/
|
||||
{
|
||||
ut_ad(mutex_own(&(recv_sys->mutex)));
|
||||
ut_a(recv_sys->n_addrs == 0);
|
||||
if (recv_sys->n_addrs != 0) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: %lu pages with log records were left unprocessed!\n"
|
||||
"InnoDB: Maximum page number with log records on it %lu\n",
|
||||
recv_sys->n_addrs, recv_max_parsed_page_no);
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
hash_table_free(recv_sys->addr_hash);
|
||||
mem_heap_empty(recv_sys->heap);
|
||||
@ -1361,6 +1369,14 @@ recv_apply_log_recs_for_backup(
|
||||
n_pages_total += file_sizes[i];
|
||||
}
|
||||
|
||||
if (recv_max_parsed_page_no >= n_pages_total) {
|
||||
printf(
|
||||
"InnoDB: Error: tablespace size %lu pages, but a log record on page %lu!\n"
|
||||
"InnoDB: Are you sure you have specified all the ibdata files right in\n"
|
||||
"InnoDB: the my.cnf file you gave as the argument to ibbackup --restore?\n",
|
||||
n_pages_total, recv_max_parsed_page_no);
|
||||
}
|
||||
|
||||
printf(
|
||||
"InnoDB: Starting an apply batch of log records to the database...\n"
|
||||
"InnoDB: Progress in percents: ");
|
||||
@ -1381,7 +1397,7 @@ recv_apply_log_recs_for_backup(
|
||||
&success);
|
||||
if (!success) {
|
||||
printf(
|
||||
"InnoDB: Error: cannot open %lu'th data file %s\n", nth_file);
|
||||
"InnoDB: Error: cannot open %lu'th data file\n", nth_file);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
@ -1397,7 +1413,7 @@ recv_apply_log_recs_for_backup(
|
||||
UNIV_PAGE_SIZE);
|
||||
if (!success) {
|
||||
printf(
|
||||
"InnoDB: Error: cannot read page no %lu from %lu'th data file %s\n",
|
||||
"InnoDB: Error: cannot read page no %lu from %lu'th data file\n",
|
||||
nth_page_in_file, nth_file);
|
||||
|
||||
exit(1);
|
||||
@ -1425,7 +1441,7 @@ recv_apply_log_recs_for_backup(
|
||||
UNIV_PAGE_SIZE);
|
||||
if (!success) {
|
||||
printf(
|
||||
"InnoDB: Error: cannot write page no %lu to %lu'th data file %s\n",
|
||||
"InnoDB: Error: cannot write page no %lu to %lu'th data file\n",
|
||||
nth_page_in_file, nth_file);
|
||||
|
||||
exit(1);
|
||||
@ -1701,6 +1717,10 @@ recv_parse_log_rec(
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (*page_no > recv_max_parsed_page_no) {
|
||||
recv_max_parsed_page_no = *page_no;
|
||||
}
|
||||
|
||||
return(new_ptr - ptr);
|
||||
}
|
||||
|
||||
@ -1779,7 +1799,7 @@ recv_report_corrupt_log(
|
||||
"InnoDB: Recv offset %lu, prev %lu\n",
|
||||
recv_previous_parsed_rec_type,
|
||||
recv_previous_parsed_rec_is_multi,
|
||||
ptr - recv_sys->buf,
|
||||
(ulint)(ptr - recv_sys->buf),
|
||||
recv_previous_parsed_rec_offset);
|
||||
|
||||
if ((ulint)(ptr - recv_sys->buf + 100)
|
||||
|
@ -350,6 +350,16 @@ mem_hash_remove(
|
||||
node->nth_heap);
|
||||
printf("in %s line %lu and tried to free in %s line %lu.\n",
|
||||
node->file_name, node->line, file_name, line);
|
||||
|
||||
printf(
|
||||
"Hex dump of 400 bytes around memory heap first block start:\n");
|
||||
|
||||
ut_print_buf((byte*)(node->heap) - 200, 400);
|
||||
|
||||
printf("\nDump of the mem heap:\n");
|
||||
|
||||
mem_heap_validate_or_print(node->heap, NULL, TRUE, &error, &size,
|
||||
NULL, NULL);
|
||||
ut_error;
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,7 @@ Gets the operating system version. Currently works only on Windows. */
|
||||
ulint
|
||||
os_get_os_version(void)
|
||||
/*===================*/
|
||||
/* out: OS_WIN95, OS_WIN31, OS_WINNT (2000 == NT) */
|
||||
/* out: OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000 */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
OSVERSIONINFO os_info;
|
||||
@ -162,7 +162,11 @@ os_get_os_version(void)
|
||||
} else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
|
||||
return(OS_WIN95);
|
||||
} else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
||||
if (os_info.dwMajorVersion <= 4) {
|
||||
return(OS_WINNT);
|
||||
} else {
|
||||
return(OS_WIN2000);
|
||||
}
|
||||
} else {
|
||||
ut_error;
|
||||
return(0);
|
||||
@ -268,9 +272,7 @@ os_file_get_last_error(void)
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Does error handling when a file operation fails. If we have run out
|
||||
of disk space, then the user can clean the disk. If we do not find
|
||||
a specified file, then the user can copy it to disk. */
|
||||
Does error handling when a file operation fails. */
|
||||
static
|
||||
ibool
|
||||
os_file_handle_error(
|
||||
@ -503,7 +505,11 @@ try_again:
|
||||
value 2 denotes that we do not flush the log at every
|
||||
commit, but only once per second */
|
||||
} else {
|
||||
attributes = attributes | FILE_FLAG_NO_BUFFERING;
|
||||
if (srv_win_file_flush_method ==
|
||||
SRV_WIN_IO_UNBUFFERED) {
|
||||
attributes = attributes
|
||||
| FILE_FLAG_NO_BUFFERING;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if (purpose == OS_FILE_NORMAL) {
|
||||
@ -514,7 +520,11 @@ try_again:
|
||||
value 2 denotes that we do not flush the log at every
|
||||
commit, but only once per second */
|
||||
} else {
|
||||
attributes = attributes | FILE_FLAG_NO_BUFFERING;
|
||||
if (srv_win_file_flush_method ==
|
||||
SRV_WIN_IO_UNBUFFERED) {
|
||||
attributes = attributes
|
||||
| FILE_FLAG_NO_BUFFERING;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
@ -1752,6 +1762,7 @@ os_aio(
|
||||
os_aio_array_t* array;
|
||||
os_aio_slot_t* slot;
|
||||
#ifdef WIN_ASYNC_IO
|
||||
ibool retval;
|
||||
BOOL ret = TRUE;
|
||||
DWORD len = n;
|
||||
void* dummy_mess1;
|
||||
@ -1824,6 +1835,8 @@ try_again:
|
||||
if (os_aio_use_native_aio) {
|
||||
#ifdef WIN_ASYNC_IO
|
||||
os_n_file_reads++;
|
||||
os_bytes_read_since_printout += len;
|
||||
|
||||
ret = ReadFile(file, buf, (DWORD)n, &len,
|
||||
&(slot->control));
|
||||
#elif defined(POSIX_ASYNC_IO)
|
||||
@ -1870,10 +1883,12 @@ try_again:
|
||||
where we also use async i/o: in Windows we must
|
||||
use the same wait mechanism as for async i/o */
|
||||
|
||||
return(os_aio_windows_handle(ULINT_UNDEFINED,
|
||||
retval = os_aio_windows_handle(ULINT_UNDEFINED,
|
||||
slot->pos,
|
||||
&dummy_mess1, &dummy_mess2,
|
||||
&dummy_type));
|
||||
&dummy_type);
|
||||
|
||||
return(retval);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
@ -1897,8 +1912,6 @@ try_again:
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
ut_error;
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
@ -1958,14 +1971,14 @@ os_aio_windows_handle(
|
||||
n = array->n_slots / array->n_segments;
|
||||
|
||||
if (array == os_aio_sync_array) {
|
||||
srv_io_thread_op_info[orig_seg] = "wait windows aio for 1 page";
|
||||
srv_io_thread_op_info[orig_seg] = "wait Windows aio for 1 page";
|
||||
|
||||
ut_ad(pos < array->n_slots);
|
||||
os_event_wait(array->events[pos]);
|
||||
i = pos;
|
||||
} else {
|
||||
srv_io_thread_op_info[orig_seg] =
|
||||
"wait windows aio for n pages";
|
||||
"wait Windows aio";
|
||||
i = os_event_wait_multiple(n, (array->events) + segment * n);
|
||||
}
|
||||
|
||||
@ -1991,9 +2004,7 @@ os_aio_windows_handle(
|
||||
ut_a(TRUE == os_file_flush(slot->file));
|
||||
}
|
||||
} else {
|
||||
os_file_get_last_error();
|
||||
|
||||
ut_error;
|
||||
os_file_handle_error(slot->file, slot->name);
|
||||
|
||||
ret_val = FALSE;
|
||||
}
|
||||
|
@ -18,6 +18,23 @@ Created 9/30/1995 Heikki Tuuri
|
||||
|
||||
#include "ut0mem.h"
|
||||
|
||||
/********************************************************************
|
||||
Converts the current process id to a number. It is not guaranteed that the
|
||||
number is unique. In Linux returns the 'process number' of the current
|
||||
thread. That number is the same as one sees in 'top', for example. In Linux
|
||||
the thread id is not the same as one sees in 'top'. */
|
||||
|
||||
ulint
|
||||
os_proc_get_number(void)
|
||||
/*====================*/
|
||||
{
|
||||
#ifdef __WIN__
|
||||
return((ulint)GetCurrentProcessId());
|
||||
#else
|
||||
return((ulint)getpid());
|
||||
#endif
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Allocates non-cacheable memory. */
|
||||
|
||||
|
@ -66,8 +66,12 @@ os_event_create(
|
||||
event = ut_malloc(sizeof(struct os_event_struct));
|
||||
|
||||
os_fast_mutex_init(&(event->os_mutex));
|
||||
pthread_cond_init(&(event->cond_var), NULL);
|
||||
|
||||
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
|
||||
pthread_cond_init(&(event->cond_var), pthread_condattr_default);
|
||||
#else
|
||||
pthread_cond_init(&(event->cond_var), NULL);
|
||||
#endif
|
||||
event->is_set = FALSE;
|
||||
|
||||
return(event);
|
||||
@ -440,9 +444,13 @@ os_fast_mutex_init(
|
||||
ut_a(fast_mutex);
|
||||
|
||||
InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
|
||||
#else
|
||||
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
|
||||
pthread_mutex_init(fast_mutex, pthread_mutexattr_default);
|
||||
#else
|
||||
pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
|
@ -126,7 +126,9 @@ os_thread_create(
|
||||
os_thread_t pthread;
|
||||
pthread_attr_t attr;
|
||||
|
||||
#if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
|
||||
pthread_attr_init(&attr);
|
||||
#endif
|
||||
|
||||
#ifdef UNIV_AIX
|
||||
/* We must make sure a thread stack is at least 32 kB, otherwise
|
||||
@ -142,16 +144,21 @@ os_thread_create(
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
ret = pthread_create(&pthread, &attr, start_f, arg);
|
||||
|
||||
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
|
||||
ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
|
||||
#else
|
||||
ret = pthread_create(&pthread, &attr, start_f, arg);
|
||||
#endif
|
||||
if (ret) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: pthread_create returned %d\n", ret);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
#endif
|
||||
if (srv_set_thread_priorities) {
|
||||
|
||||
my_pthread_setprio(pthread, srv_query_thread_priority);
|
||||
|
@ -169,7 +169,7 @@ page_cur_search_with_match(
|
||||
ut_ad(dtuple_check_typed(tuple));
|
||||
ut_ad((mode == PAGE_CUR_L) || (mode == PAGE_CUR_LE)
|
||||
|| (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)
|
||||
|| (mode == PAGE_CUR_DBG));
|
||||
|| (mode == PAGE_CUR_LE_OR_EXTENDS) || (mode == PAGE_CUR_DBG));
|
||||
|
||||
#ifdef PAGE_CUR_ADAPT
|
||||
if ((page_header_get_field(page, PAGE_LEVEL) == 0)
|
||||
@ -232,9 +232,26 @@ page_cur_search_with_match(
|
||||
low_matched_bytes = cur_matched_bytes;
|
||||
|
||||
} else if (cmp == -1) {
|
||||
|
||||
if (mode == PAGE_CUR_LE_OR_EXTENDS
|
||||
&& dfield_get_len(dtuple_get_nth_field(tuple,
|
||||
cur_matched_fields))
|
||||
== cur_matched_bytes
|
||||
&& rec_get_nth_field_len(mid_rec,
|
||||
cur_matched_fields)
|
||||
!= UNIV_SQL_NULL) {
|
||||
|
||||
/* This means current dfield is not SQL
|
||||
NULL, and the current rec field extends it */
|
||||
|
||||
low = mid;
|
||||
low_matched_fields = cur_matched_fields;
|
||||
low_matched_bytes = cur_matched_bytes;
|
||||
} else {
|
||||
up = mid;
|
||||
up_matched_fields = cur_matched_fields;
|
||||
up_matched_bytes = cur_matched_bytes;
|
||||
}
|
||||
|
||||
} else if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_LE)) {
|
||||
low = mid;
|
||||
@ -252,8 +269,8 @@ page_cur_search_with_match(
|
||||
slot = page_dir_get_nth_slot(page, up);
|
||||
up_rec = page_dir_slot_get_rec(slot);
|
||||
|
||||
/* Perform linear search until the upper and lower records
|
||||
come to distance 1 of each other. */
|
||||
/* Perform linear search until the upper and lower records come to
|
||||
distance 1 of each other. */
|
||||
|
||||
while (page_rec_get_next(low_rec) != up_rec) {
|
||||
|
||||
@ -272,10 +289,25 @@ page_cur_search_with_match(
|
||||
low_matched_bytes = cur_matched_bytes;
|
||||
|
||||
} else if (cmp == -1) {
|
||||
if (mode == PAGE_CUR_LE_OR_EXTENDS
|
||||
&& dfield_get_len(dtuple_get_nth_field(tuple,
|
||||
cur_matched_fields))
|
||||
== cur_matched_bytes
|
||||
&& rec_get_nth_field_len(mid_rec,
|
||||
cur_matched_fields)
|
||||
!= UNIV_SQL_NULL) {
|
||||
|
||||
/* This means current dfield is not SQL
|
||||
NULL, and the current rec field extends it */
|
||||
|
||||
low = mid;
|
||||
low_matched_fields = cur_matched_fields;
|
||||
low_matched_bytes = cur_matched_bytes;
|
||||
} else {
|
||||
up_rec = mid_rec;
|
||||
up_matched_fields = cur_matched_fields;
|
||||
up_matched_bytes = cur_matched_bytes;
|
||||
|
||||
}
|
||||
} else if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_LE)) {
|
||||
low_rec = mid_rec;
|
||||
low_matched_fields = cur_matched_fields;
|
||||
|
@ -1299,12 +1299,16 @@ page_rec_validate(
|
||||
heap_no = rec_get_heap_no(rec);
|
||||
|
||||
if (!(n_owned <= PAGE_DIR_SLOT_MAX_N_OWNED)) {
|
||||
fprintf(stderr, "Dir slot n owned too big %lu\n", n_owned);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Dir slot of rec %lu, n owned too big %lu\n",
|
||||
(ulint)(rec - page), n_owned);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (!(heap_no < page_header_get_field(page, PAGE_N_HEAP))) {
|
||||
fprintf(stderr, "Heap no too big %lu %lu\n", heap_no,
|
||||
fprintf(stderr,
|
||||
"InnoDB: Heap no of rec %lu too big %lu %lu\n",
|
||||
(ulint)(rec - page), heap_no,
|
||||
page_header_get_field(page, PAGE_N_HEAP));
|
||||
return(FALSE);
|
||||
}
|
||||
@ -1312,6 +1316,194 @@ page_rec_validate(
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
This function checks the consistency of an index page when we do not
|
||||
know the index. This is also resilient so that this should never crash
|
||||
even if the page is total garbage. */
|
||||
|
||||
ibool
|
||||
page_simple_validate(
|
||||
/*=================*/
|
||||
/* out: TRUE if ok */
|
||||
page_t* page) /* in: index page */
|
||||
{
|
||||
page_cur_t cur;
|
||||
page_dir_slot_t* slot;
|
||||
ulint slot_no;
|
||||
ulint n_slots;
|
||||
rec_t* rec;
|
||||
byte* rec_heap_top;
|
||||
ulint count;
|
||||
ulint own_count;
|
||||
ibool ret = FALSE;
|
||||
|
||||
/* Check first that the record heap and the directory do not
|
||||
overlap. */
|
||||
|
||||
n_slots = page_dir_get_n_slots(page);
|
||||
|
||||
if (n_slots > UNIV_PAGE_SIZE / 4) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Nonsensical number %lu of page dir slots\n", n_slots);
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
rec_heap_top = page_header_get_ptr(page, PAGE_HEAP_TOP);
|
||||
|
||||
if (rec_heap_top > page_dir_get_nth_slot(page, n_slots - 1)) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Record heap and dir overlap on a page, heap top %lu, dir %lu\n",
|
||||
(ulint)(page_header_get_ptr(page, PAGE_HEAP_TOP) - page),
|
||||
(ulint)(page_dir_get_nth_slot(page, n_slots - 1) - page));
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
/* Validate the record list in a loop checking also that it is
|
||||
consistent with the page record directory. */
|
||||
|
||||
count = 0;
|
||||
own_count = 1;
|
||||
slot_no = 0;
|
||||
slot = page_dir_get_nth_slot(page, slot_no);
|
||||
|
||||
page_cur_set_before_first(page, &cur);
|
||||
|
||||
for (;;) {
|
||||
rec = (&cur)->rec;
|
||||
|
||||
if (rec > rec_heap_top) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Record %lu is above rec heap top %lu\n",
|
||||
(ulint)(rec - page), (ulint)(rec_heap_top - page));
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (rec_get_n_owned(rec) != 0) {
|
||||
/* This is a record pointed to by a dir slot */
|
||||
if (rec_get_n_owned(rec) != own_count) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Wrong owned count %lu, %lu, rec %lu\n",
|
||||
rec_get_n_owned(rec), own_count,
|
||||
(ulint)(rec - page));
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (page_dir_slot_get_rec(slot) != rec) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Dir slot does not point to right rec %lu\n",
|
||||
(ulint)(rec - page));
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
own_count = 0;
|
||||
|
||||
if (!page_cur_is_after_last(&cur)) {
|
||||
slot_no++;
|
||||
slot = page_dir_get_nth_slot(page, slot_no);
|
||||
}
|
||||
}
|
||||
|
||||
if (page_cur_is_after_last(&cur)) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (rec_get_next_offs(rec) < FIL_PAGE_DATA
|
||||
|| rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Next record offset nonsensical %lu for rec %lu\n",
|
||||
rec_get_next_offs(rec),
|
||||
(ulint)(rec - page));
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
if (count > UNIV_PAGE_SIZE) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Page record list appears to be circular %lu\n",
|
||||
count);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
page_cur_move_to_next(&cur);
|
||||
own_count++;
|
||||
}
|
||||
|
||||
if (rec_get_n_owned(rec) == 0) {
|
||||
fprintf(stderr, "InnoDB: n owned is zero in a supremum rec\n");
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (slot_no != n_slots - 1) {
|
||||
fprintf(stderr, "InnoDB: n slots wrong %lu, %lu\n",
|
||||
slot_no, n_slots - 1);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) {
|
||||
fprintf(stderr, "InnoDB: n recs wrong %lu %lu\n",
|
||||
page_header_get_field(page, PAGE_N_RECS) + 2, count + 1);
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
/* Check then the free list */
|
||||
rec = page_header_get_ptr(page, PAGE_FREE);
|
||||
|
||||
while (rec != NULL) {
|
||||
if (rec < page + FIL_PAGE_DATA
|
||||
|| rec >= page + UNIV_PAGE_SIZE) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Free list record has a nonsensical offset %lu\n",
|
||||
(ulint)(rec - page));
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (rec > rec_heap_top) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Free list record %lu is above rec heap top %lu\n",
|
||||
(ulint)(rec - page), (ulint)(rec_heap_top - page));
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
if (count > UNIV_PAGE_SIZE) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Page free list appears to be circular %lu\n",
|
||||
count);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
rec = page_rec_get_next(rec);
|
||||
}
|
||||
|
||||
if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) {
|
||||
|
||||
fprintf(stderr, "InnoDB: N heap is wrong %lu, %lu\n",
|
||||
page_header_get_field(page, PAGE_N_HEAP), count + 1);
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
func_exit:
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
This function checks the consistency of an index page. */
|
||||
|
||||
@ -1339,6 +1531,17 @@ page_validate(
|
||||
ulint i;
|
||||
char err_buf[1000];
|
||||
|
||||
if (!page_simple_validate(page)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Apparent corruption in page %lu in index %s in table %s\n",
|
||||
buf_frame_get_page_no(page), index->name,
|
||||
index->table_name);
|
||||
|
||||
buf_page_print(page);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
heap = mem_heap_create(UNIV_PAGE_SIZE);
|
||||
|
||||
/* The following buffer is used to check that the
|
||||
@ -1357,7 +1560,7 @@ page_validate(
|
||||
if (!(page_header_get_ptr(page, PAGE_HEAP_TOP) <=
|
||||
page_dir_get_nth_slot(page, n_slots - 1))) {
|
||||
fprintf(stderr,
|
||||
"Record heap and dir overlap on a page in index %s, %lu, %lu\n",
|
||||
"InnoDB: Record heap and dir overlap on a page in index %s, %lu, %lu\n",
|
||||
index->name, (ulint)page_header_get_ptr(page, PAGE_HEAP_TOP),
|
||||
(ulint)page_dir_get_nth_slot(page, n_slots - 1));
|
||||
|
||||
@ -1385,10 +1588,14 @@ page_validate(
|
||||
if ((count >= 2) && (!page_cur_is_after_last(&cur))) {
|
||||
if (!(1 == cmp_rec_rec(rec, old_rec, index))) {
|
||||
fprintf(stderr,
|
||||
"Records in wrong order in index %s\n",
|
||||
index->name);
|
||||
"InnoDB: Records in wrong order on page %lu index %s table %s\n",
|
||||
buf_frame_get_page_no(page),
|
||||
index->name,
|
||||
index->table_name);
|
||||
|
||||
rec_sprintf(err_buf, 900, old_rec);
|
||||
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
||||
fprintf(stderr,
|
||||
"InnoDB: previous record %s\n", err_buf);
|
||||
|
||||
rec_sprintf(err_buf, 900, rec);
|
||||
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
||||
@ -1410,7 +1617,7 @@ page_validate(
|
||||
/* No other record may overlap this */
|
||||
|
||||
fprintf(stderr,
|
||||
"Record overlaps another in index %s \n",
|
||||
"InnoDB: Record overlaps another in index %s \n",
|
||||
index->name);
|
||||
|
||||
goto func_exit;
|
||||
@ -1423,7 +1630,7 @@ page_validate(
|
||||
/* This is a record pointed to by a dir slot */
|
||||
if (rec_get_n_owned(rec) != own_count) {
|
||||
fprintf(stderr,
|
||||
"Wrong owned count %lu, %lu, in index %s\n",
|
||||
"InnoDB: Wrong owned count %lu, %lu, in index %s\n",
|
||||
rec_get_n_owned(rec), own_count,
|
||||
index->name);
|
||||
|
||||
@ -1432,7 +1639,7 @@ page_validate(
|
||||
|
||||
if (page_dir_slot_get_rec(slot) != rec) {
|
||||
fprintf(stderr,
|
||||
"Dir slot does not point to right rec in %s\n",
|
||||
"InnoDB: Dir slot does not point to right rec in %s\n",
|
||||
index->name);
|
||||
|
||||
goto func_exit;
|
||||
@ -1454,7 +1661,7 @@ page_validate(
|
||||
if (rec_get_next_offs(rec) < FIL_PAGE_DATA
|
||||
|| rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) {
|
||||
fprintf(stderr,
|
||||
"Next record offset wrong %lu in index %s\n",
|
||||
"InnoDB: Next record offset wrong %lu in index %s\n",
|
||||
rec_get_next_offs(rec), index->name);
|
||||
|
||||
goto func_exit;
|
||||
@ -1467,19 +1674,20 @@ page_validate(
|
||||
}
|
||||
|
||||
if (rec_get_n_owned(rec) == 0) {
|
||||
fprintf(stderr, "n owned is zero in index %s\n", index->name);
|
||||
fprintf(stderr,
|
||||
"InnoDB: n owned is zero in index %s\n", index->name);
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (slot_no != n_slots - 1) {
|
||||
fprintf(stderr, "n slots wrong %lu %lu in index %s\n",
|
||||
fprintf(stderr, "InnoDB: n slots wrong %lu %lu in index %s\n",
|
||||
slot_no, n_slots - 1, index->name);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) {
|
||||
fprintf(stderr, "n recs wrong %lu %lu in index %s\n",
|
||||
fprintf(stderr, "InnoDB: n recs wrong %lu %lu in index %s\n",
|
||||
page_header_get_field(page, PAGE_N_RECS) + 2, count + 1,
|
||||
index->name);
|
||||
|
||||
@ -1487,7 +1695,8 @@ page_validate(
|
||||
}
|
||||
|
||||
if (data_size != page_get_data_size(page)) {
|
||||
fprintf(stderr, "Summed data size %lu, returned by func %lu\n",
|
||||
fprintf(stderr,
|
||||
"InnoDB: Summed data size %lu, returned by func %lu\n",
|
||||
data_size, page_get_data_size(page));
|
||||
goto func_exit;
|
||||
}
|
||||
@ -1508,7 +1717,7 @@ page_validate(
|
||||
|
||||
if (buf[offs + i] != 0) {
|
||||
fprintf(stderr,
|
||||
"Record overlaps another in free list, index %s \n",
|
||||
"InnoDB: Record overlaps another in free list, index %s \n",
|
||||
index->name);
|
||||
|
||||
goto func_exit;
|
||||
@ -1522,9 +1731,11 @@ page_validate(
|
||||
|
||||
if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) {
|
||||
|
||||
fprintf(stderr, "N heap is wrong %lu %lu in index %s\n",
|
||||
fprintf(stderr,
|
||||
"InnoDB: N heap is wrong %lu %lu in index %s\n",
|
||||
page_header_get_field(page, PAGE_N_HEAP), count + 1,
|
||||
index->name);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
@ -1532,6 +1743,15 @@ page_validate(
|
||||
func_exit:
|
||||
mem_heap_free(heap);
|
||||
|
||||
if (ret == FALSE) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Apparent corruption in page %lu in index %s in table %s\n",
|
||||
buf_frame_get_page_no(page), index->name,
|
||||
index->table_name);
|
||||
|
||||
buf_page_print(page);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,6 @@
|
||||
* $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
|
||||
*/
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#define FLEX_SCANNER
|
||||
#define YY_FLEX_MAJOR_VERSION 2
|
||||
#define YY_FLEX_MINOR_VERSION 5
|
||||
@ -609,11 +607,8 @@ How to make the InnoDB parser and lexer C files:
|
||||
|
||||
6. Remove the #include of unistd.h from about line 2500 of lexyy.c
|
||||
|
||||
7. Move #include <math.h> in pars0grm.c after #include "univ.i" to remove
|
||||
a large file compilation error on AIX.
|
||||
|
||||
8. Move #include "univ.i" in lexyy.c to the file start to remove a large
|
||||
file compilation error on AIX.
|
||||
7. Add '#include "univ.i"' before #include <stdio.h> in lexyy.c
|
||||
(Needed for AIX)
|
||||
|
||||
These instructions seem to work at least with bison-1.28 and flex-2.5.4 on
|
||||
Linux.
|
||||
@ -621,6 +616,7 @@ Linux.
|
||||
#line 36 "pars0lex.l"
|
||||
#define YYSTYPE que_node_t*
|
||||
|
||||
#include "univ.i"
|
||||
#include "pars0pars.h"
|
||||
#include "pars0grm.h"
|
||||
#include "pars0sym.h"
|
||||
|
@ -102,8 +102,6 @@ que_node_t */
|
||||
#include "que0que.h"
|
||||
#include "row0sel.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define YYSTYPE que_node_t*
|
||||
|
||||
/* #define __STDC__ */
|
||||
|
@ -1046,14 +1046,16 @@ que_thr_stop(
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
A patch for MySQL used to 'stop' a dummy query thread used in MySQL. */
|
||||
A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The
|
||||
query thread is stopped and made inactive, except in the case where
|
||||
it was put to the lock wait state in lock0lock.c, but the lock has already
|
||||
been granted or the transaction chosen as a victim in deadlock resolution. */
|
||||
|
||||
void
|
||||
que_thr_stop_for_mysql(
|
||||
/*===================*/
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
{
|
||||
ibool stopped = FALSE;
|
||||
trx_t* trx;
|
||||
|
||||
trx = thr_get_trx(thr);
|
||||
@ -1067,13 +1069,10 @@ que_thr_stop_for_mysql(
|
||||
|
||||
/* Error handling built for the MySQL interface */
|
||||
thr->state = QUE_THR_COMPLETED;
|
||||
|
||||
stopped = TRUE;
|
||||
}
|
||||
|
||||
if (!stopped) {
|
||||
/* It must have been a lock wait but the
|
||||
lock was already released */
|
||||
} else {
|
||||
/* It must have been a lock wait but the lock was
|
||||
already released, or this transaction was chosen
|
||||
as a victim in selective deadlock resolution */
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
@ -1081,6 +1080,10 @@ que_thr_stop_for_mysql(
|
||||
}
|
||||
}
|
||||
|
||||
ut_ad(thr->is_active == TRUE);
|
||||
ut_ad(trx->n_active_thrs == 1);
|
||||
ut_ad(thr->graph->n_active_thrs == 1);
|
||||
|
||||
thr->is_active = FALSE;
|
||||
(thr->graph)->n_active_thrs--;
|
||||
|
||||
@ -1132,6 +1135,9 @@ que_thr_stop_for_mysql_no_error(
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
ut_ad(thr->state == QUE_THR_RUNNING);
|
||||
ut_ad(thr->is_active == TRUE);
|
||||
ut_ad(trx->n_active_thrs == 1);
|
||||
ut_ad(thr->graph->n_active_thrs == 1);
|
||||
|
||||
if (thr->magic_n != QUE_THR_MAGIC_N) {
|
||||
fprintf(stderr,
|
||||
|
@ -200,6 +200,28 @@ read_view_close(
|
||||
UT_LIST_REMOVE(view_list, trx_sys->view_list, view);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Closes a consistent read view for MySQL. This function is called at an SQL
|
||||
statement end if the trx isolation level is <= TRX_ISO_READ_COMMITTED. */
|
||||
|
||||
void
|
||||
read_view_close_for_mysql(
|
||||
/*======================*/
|
||||
trx_t* trx) /* in: trx which has a read view */
|
||||
{
|
||||
ut_a(trx->read_view);
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
read_view_close(trx->read_view);
|
||||
|
||||
mem_heap_empty(trx->read_view_heap);
|
||||
|
||||
trx->read_view = NULL;
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Prints a read view to stderr. */
|
||||
|
||||
|
@ -353,7 +353,7 @@ cmp_data_data_slow(
|
||||
data2++;
|
||||
}
|
||||
|
||||
return(0);
|
||||
return(0); /* Not reached */
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
|
@ -321,59 +321,6 @@ row_ins_clust_index_entry_by_modify(
|
||||
return(err);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Checks if a unique key violation to rec would occur at the index entry
|
||||
insert. */
|
||||
static
|
||||
ibool
|
||||
row_ins_dupl_error_with_rec(
|
||||
/*========================*/
|
||||
/* out: TRUE if error */
|
||||
rec_t* rec, /* in: user record; NOTE that we assume
|
||||
that the caller already has a record lock on
|
||||
the record! */
|
||||
dtuple_t* entry, /* in: entry to insert */
|
||||
dict_index_t* index) /* in: index */
|
||||
{
|
||||
ulint matched_fields;
|
||||
ulint matched_bytes;
|
||||
ulint n_unique;
|
||||
ulint i;
|
||||
|
||||
n_unique = dict_index_get_n_unique(index);
|
||||
|
||||
matched_fields = 0;
|
||||
matched_bytes = 0;
|
||||
|
||||
cmp_dtuple_rec_with_match(entry, rec, &matched_fields, &matched_bytes);
|
||||
|
||||
if (matched_fields < n_unique) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* In a unique secondary index we allow equal key values if they
|
||||
contain SQL NULLs */
|
||||
|
||||
if (!(index->type & DICT_CLUSTERED)) {
|
||||
|
||||
for (i = 0; i < n_unique; i++) {
|
||||
if (UNIV_SQL_NULL == dfield_get_len(
|
||||
dtuple_get_nth_field(entry, i))) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rec_get_deleted_flag(rec)) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Either deletes or sets the referencing columns SQL NULL in a child row.
|
||||
Used in ON DELETE ... clause for foreign keys when a parent row is
|
||||
@ -533,8 +480,12 @@ row_ins_foreign_delete_or_set_null(
|
||||
err = lock_table(0, table, LOCK_IX, thr);
|
||||
|
||||
if (err == DB_SUCCESS) {
|
||||
/* Here it suffices to use a LOCK_REC_NOT_GAP type lock;
|
||||
we already have a normal shared lock on the appropriate
|
||||
gap if the search criterion was not unique */
|
||||
|
||||
err = lock_clust_rec_read_check_and_lock(0, clust_rec,
|
||||
clust_index, LOCK_X, thr);
|
||||
clust_index, LOCK_X, LOCK_REC_NOT_GAP, thr);
|
||||
}
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
@ -630,12 +581,14 @@ nonstandard_exit_func:
|
||||
|
||||
/*************************************************************************
|
||||
Sets a shared lock on a record. Used in locking possible duplicate key
|
||||
records. */
|
||||
records and also in checking foreign key constraints. */
|
||||
static
|
||||
ulint
|
||||
row_ins_set_shared_rec_lock(
|
||||
/*========================*/
|
||||
/* out: DB_SUCCESS or error code */
|
||||
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
|
||||
LOCK_REC_NOT_GAP type lock */
|
||||
rec_t* rec, /* in: record */
|
||||
dict_index_t* index, /* in: index */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
@ -644,10 +597,10 @@ row_ins_set_shared_rec_lock(
|
||||
|
||||
if (index->type & DICT_CLUSTERED) {
|
||||
err = lock_clust_rec_read_check_and_lock(0, rec, index, LOCK_S,
|
||||
thr);
|
||||
type, thr);
|
||||
} else {
|
||||
err = lock_sec_rec_read_check_and_lock(0, rec, index, LOCK_S,
|
||||
thr);
|
||||
type, thr);
|
||||
}
|
||||
|
||||
return(err);
|
||||
@ -656,7 +609,7 @@ row_ins_set_shared_rec_lock(
|
||||
/*******************************************************************
|
||||
Checks if foreign key constraint fails for an index entry. Sets shared locks
|
||||
which lock either the success or the failure of the constraint. NOTE that
|
||||
the caller must have a shared latch on dict_foreign_key_check_lock. */
|
||||
the caller must have a shared latch on dict_operation_lock. */
|
||||
|
||||
ulint
|
||||
row_ins_check_foreign_constraint(
|
||||
@ -679,7 +632,7 @@ row_ins_check_foreign_constraint(
|
||||
dict_table_t* check_table;
|
||||
dict_index_t* check_index;
|
||||
ulint n_fields_cmp;
|
||||
ibool timeout_expired;
|
||||
ibool unique_search;
|
||||
rec_t* rec;
|
||||
btr_pcur_t pcur;
|
||||
ibool moved;
|
||||
@ -689,7 +642,9 @@ row_ins_check_foreign_constraint(
|
||||
mtr_t mtr;
|
||||
|
||||
run_again:
|
||||
ut_ad(rw_lock_own(&dict_foreign_key_check_lock, RW_LOCK_SHARED));
|
||||
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_SHARED));
|
||||
|
||||
err = DB_SUCCESS;
|
||||
|
||||
if (thr_get_trx(thr)->check_foreigns == FALSE) {
|
||||
/* The user has suppressed foreign key checks currently for
|
||||
@ -748,6 +703,14 @@ run_again:
|
||||
|
||||
dtuple_set_n_fields_cmp(entry, foreign->n_fields);
|
||||
|
||||
if (dict_index_get_n_unique(check_index) <= foreign->n_fields) {
|
||||
/* We can just set a LOCK_REC_NOT_GAP type lock */
|
||||
|
||||
unique_search = TRUE;
|
||||
} else {
|
||||
unique_search = FALSE;
|
||||
}
|
||||
|
||||
btr_pcur_open(check_index, entry, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
|
||||
@ -761,26 +724,46 @@ run_again:
|
||||
goto next_rec;
|
||||
}
|
||||
|
||||
/* Try to place a lock on the index record */
|
||||
|
||||
err = row_ins_set_shared_rec_lock(rec, check_index, thr);
|
||||
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
|
||||
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec,
|
||||
check_index, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
|
||||
goto next_rec;
|
||||
}
|
||||
|
||||
cmp = cmp_dtuple_rec(entry, rec);
|
||||
|
||||
if (cmp == 0) {
|
||||
if (!rec_get_deleted_flag(rec)) {
|
||||
if (rec_get_deleted_flag(rec)) {
|
||||
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY,
|
||||
rec, check_index, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Found a matching record */
|
||||
|
||||
if (unique_search) {
|
||||
err = row_ins_set_shared_rec_lock(
|
||||
LOCK_REC_NOT_GAP,
|
||||
rec, check_index, thr);
|
||||
} else {
|
||||
err = row_ins_set_shared_rec_lock(
|
||||
LOCK_ORDINARY,
|
||||
rec, check_index, thr);
|
||||
}
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* printf(
|
||||
"FOREIGN: Found matching record from %s %s\n",
|
||||
check_index->table_name, check_index->name);
|
||||
@ -807,6 +790,13 @@ run_again:
|
||||
}
|
||||
|
||||
if (cmp < 0) {
|
||||
err = row_ins_set_shared_rec_lock(LOCK_GAP,
|
||||
rec, check_index, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (check_ref) {
|
||||
err = DB_NO_REFERENCED_ROW;
|
||||
} else {
|
||||
@ -844,14 +834,14 @@ do_possible_lock_wait:
|
||||
|
||||
que_thr_stop_for_mysql(thr);
|
||||
|
||||
timeout_expired = srv_suspend_mysql_thread(thr);
|
||||
srv_suspend_mysql_thread(thr);
|
||||
|
||||
if (!timeout_expired) {
|
||||
if (thr_get_trx(thr)->error_state == DB_SUCCESS) {
|
||||
|
||||
goto run_again;
|
||||
}
|
||||
|
||||
err = DB_LOCK_WAIT_TIMEOUT;
|
||||
err = thr_get_trx(thr)->error_state;
|
||||
}
|
||||
|
||||
return(err);
|
||||
@ -890,21 +880,16 @@ row_ins_check_foreign_constraints(
|
||||
trx);
|
||||
}
|
||||
|
||||
if (!trx->has_dict_foreign_key_check_lock) {
|
||||
if (0 == trx->dict_operation_lock_mode) {
|
||||
got_s_lock = TRUE;
|
||||
|
||||
rw_lock_s_lock(&dict_foreign_key_check_lock);
|
||||
|
||||
trx->has_dict_foreign_key_check_lock = TRUE;
|
||||
row_mysql_freeze_data_dictionary(trx);
|
||||
}
|
||||
|
||||
err = row_ins_check_foreign_constraint(TRUE, foreign,
|
||||
table, index, entry, thr);
|
||||
if (got_s_lock) {
|
||||
|
||||
rw_lock_s_unlock(&dict_foreign_key_check_lock);
|
||||
|
||||
trx->has_dict_foreign_key_check_lock = FALSE;
|
||||
row_mysql_unfreeze_data_dictionary(trx);
|
||||
}
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
@ -918,6 +903,59 @@ row_ins_check_foreign_constraints(
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Checks if a unique key violation to rec would occur at the index entry
|
||||
insert. */
|
||||
static
|
||||
ibool
|
||||
row_ins_dupl_error_with_rec(
|
||||
/*========================*/
|
||||
/* out: TRUE if error */
|
||||
rec_t* rec, /* in: user record; NOTE that we assume
|
||||
that the caller already has a record lock on
|
||||
the record! */
|
||||
dtuple_t* entry, /* in: entry to insert */
|
||||
dict_index_t* index) /* in: index */
|
||||
{
|
||||
ulint matched_fields;
|
||||
ulint matched_bytes;
|
||||
ulint n_unique;
|
||||
ulint i;
|
||||
|
||||
n_unique = dict_index_get_n_unique(index);
|
||||
|
||||
matched_fields = 0;
|
||||
matched_bytes = 0;
|
||||
|
||||
cmp_dtuple_rec_with_match(entry, rec, &matched_fields, &matched_bytes);
|
||||
|
||||
if (matched_fields < n_unique) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* In a unique secondary index we allow equal key values if they
|
||||
contain SQL NULLs */
|
||||
|
||||
if (!(index->type & DICT_CLUSTERED)) {
|
||||
|
||||
for (i = 0; i < n_unique; i++) {
|
||||
if (UNIV_SQL_NULL == dfield_get_len(
|
||||
dtuple_get_nth_field(entry, i))) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rec_get_deleted_flag(rec)) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Scans a unique non-clustered index at a given index entry to determine
|
||||
whether a uniqueness violation has occurred for the key value of the entry.
|
||||
@ -978,7 +1016,8 @@ row_ins_scan_sec_index_for_duplicate(
|
||||
|
||||
/* Try to place a lock on the index record */
|
||||
|
||||
err = row_ins_set_shared_rec_lock(rec, index, thr);
|
||||
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec, index,
|
||||
thr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
@ -1082,8 +1121,8 @@ row_ins_duplicate_error_in_clust(
|
||||
sure that in roll-forward we get the same duplicate
|
||||
errors as in original execution */
|
||||
|
||||
err = row_ins_set_shared_rec_lock(rec, cursor->index,
|
||||
thr);
|
||||
err = row_ins_set_shared_rec_lock(LOCK_REC_NOT_GAP,
|
||||
rec, cursor->index, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
return(err);
|
||||
@ -1105,8 +1144,8 @@ row_ins_duplicate_error_in_clust(
|
||||
|
||||
if (rec != page_get_supremum_rec(page)) {
|
||||
|
||||
err = row_ins_set_shared_rec_lock(rec, cursor->index,
|
||||
thr);
|
||||
err = row_ins_set_shared_rec_lock(LOCK_REC_NOT_GAP,
|
||||
rec, cursor->index, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
return(err);
|
||||
|
@ -27,6 +27,7 @@ Created 9/17/2000 Heikki Tuuri
|
||||
#include "lock0lock.h"
|
||||
#include "rem0cmp.h"
|
||||
#include "log0log.h"
|
||||
#include "btr0sea.h"
|
||||
|
||||
/* A dummy variable used to fool the compiler */
|
||||
ibool row_mysql_identically_false = FALSE;
|
||||
@ -197,13 +198,13 @@ row_mysql_handle_errors(
|
||||
/* out: TRUE if it was a lock wait and
|
||||
we should continue running the query thread */
|
||||
ulint* new_err,/* out: possible new error encountered in
|
||||
rollback, or the old error which was
|
||||
during the function entry */
|
||||
lock wait, or if no new error, the value
|
||||
of trx->error_state at the entry of this
|
||||
function */
|
||||
trx_t* trx, /* in: transaction */
|
||||
que_thr_t* thr, /* in: query thread */
|
||||
trx_savept_t* savept) /* in: savepoint or NULL */
|
||||
{
|
||||
ibool timeout_expired;
|
||||
ulint err;
|
||||
|
||||
handle_new_error:
|
||||
@ -240,11 +241,9 @@ handle_new_error:
|
||||
/* MySQL will roll back the latest SQL statement */
|
||||
} else if (err == DB_LOCK_WAIT) {
|
||||
|
||||
timeout_expired = srv_suspend_mysql_thread(thr);
|
||||
|
||||
if (timeout_expired) {
|
||||
trx->error_state = DB_LOCK_WAIT_TIMEOUT;
|
||||
srv_suspend_mysql_thread(thr);
|
||||
|
||||
if (trx->error_state != DB_SUCCESS) {
|
||||
que_thr_stop_for_mysql(thr);
|
||||
|
||||
goto handle_new_error;
|
||||
@ -321,6 +320,8 @@ row_create_prebuilt(
|
||||
|
||||
prebuilt->sql_stat_start = TRUE;
|
||||
|
||||
prebuilt->mysql_has_locked = FALSE;
|
||||
|
||||
prebuilt->index = NULL;
|
||||
prebuilt->n_template = 0;
|
||||
prebuilt->mysql_template = NULL;
|
||||
@ -1012,10 +1013,27 @@ run_again:
|
||||
|
||||
err = trx->error_state;
|
||||
|
||||
/* Note that the cascade node is a subnode of another InnoDB
|
||||
query graph node. We do a normal lock wait in this node, but
|
||||
all errors are handled by the parent node. */
|
||||
|
||||
if (err == DB_LOCK_WAIT) {
|
||||
/* Handle lock wait here */
|
||||
|
||||
que_thr_stop_for_mysql(thr);
|
||||
|
||||
row_mysql_handle_errors(&err, trx, thr, NULL);
|
||||
srv_suspend_mysql_thread(thr);
|
||||
|
||||
/* Note that a lock wait may also end in a lock wait timeout,
|
||||
or this transaction is picked as a victim in selective
|
||||
deadlock resolution */
|
||||
|
||||
if (trx->error_state != DB_SUCCESS) {
|
||||
|
||||
return(trx->error_state);
|
||||
}
|
||||
|
||||
/* Retry operation after a normal lock wait */
|
||||
|
||||
goto run_again;
|
||||
}
|
||||
@ -1136,32 +1154,73 @@ row_mysql_recover_tmp_table(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Locks the data dictionary exclusively for performing a table create
|
||||
operation. */
|
||||
Locks the data dictionary in shared mode from modifications, for performing
|
||||
foreign key check, rollback, or other operation invisible to MySQL. */
|
||||
|
||||
void
|
||||
row_mysql_lock_data_dictionary(void)
|
||||
/*================================*/
|
||||
row_mysql_freeze_data_dictionary(
|
||||
/*=============================*/
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
ut_a(trx->dict_operation_lock_mode == 0);
|
||||
|
||||
rw_lock_s_lock(&dict_operation_lock);
|
||||
|
||||
trx->dict_operation_lock_mode = RW_S_LATCH;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Unlocks the data dictionary shared lock. */
|
||||
|
||||
void
|
||||
row_mysql_unfreeze_data_dictionary(
|
||||
/*===============================*/
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
ut_a(trx->dict_operation_lock_mode == RW_S_LATCH);
|
||||
|
||||
rw_lock_s_unlock(&dict_operation_lock);
|
||||
|
||||
trx->dict_operation_lock_mode = 0;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Locks the data dictionary exclusively for performing a table create or other
|
||||
data dictionary modification operation. */
|
||||
|
||||
void
|
||||
row_mysql_lock_data_dictionary(
|
||||
/*===========================*/
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
ut_a(trx->dict_operation_lock_mode == 0);
|
||||
|
||||
/* Serialize data dictionary operations with dictionary mutex:
|
||||
no deadlocks or lock waits can occur then in these operations */
|
||||
|
||||
rw_lock_x_lock(&(dict_foreign_key_check_lock));
|
||||
rw_lock_x_lock(&dict_operation_lock);
|
||||
trx->dict_operation_lock_mode = RW_X_LATCH;
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Unlocks the data dictionary exclusively lock. */
|
||||
Unlocks the data dictionary exclusive lock. */
|
||||
|
||||
void
|
||||
row_mysql_unlock_data_dictionary(void)
|
||||
/*==================================*/
|
||||
row_mysql_unlock_data_dictionary(
|
||||
/*=============================*/
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
|
||||
|
||||
/* Serialize data dictionary operations with dictionary mutex:
|
||||
no deadlocks can occur then in these operations */
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
rw_lock_x_unlock(&(dict_foreign_key_check_lock));
|
||||
rw_lock_x_unlock(&dict_operation_lock);
|
||||
|
||||
trx->dict_operation_lock_mode = 0;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
@ -1184,6 +1243,8 @@ row_create_table_for_mysql(
|
||||
ulint err;
|
||||
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
|
||||
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
|
||||
if (srv_created_new_raw) {
|
||||
@ -1332,7 +1393,7 @@ row_create_table_for_mysql(
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: cannot create table %s because tablespace full\n",
|
||||
table->name);
|
||||
row_drop_table_for_mysql(table->name, trx, TRUE);
|
||||
row_drop_table_for_mysql(table->name, trx);
|
||||
} else {
|
||||
ut_a(err == DB_DUPLICATE_KEY);
|
||||
|
||||
@ -1384,6 +1445,7 @@ row_create_index_for_mysql(
|
||||
ulint keywordlen;
|
||||
ulint err;
|
||||
|
||||
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
|
||||
@ -1425,7 +1487,7 @@ row_create_index_for_mysql(
|
||||
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
|
||||
row_drop_table_for_mysql(index->table_name, trx, TRUE);
|
||||
row_drop_table_for_mysql(index->table_name, trx);
|
||||
|
||||
trx->error_state = DB_SUCCESS;
|
||||
}
|
||||
@ -1464,6 +1526,7 @@ row_table_add_foreign_constraints(
|
||||
ulint err;
|
||||
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
|
||||
ut_a(sql_string);
|
||||
|
||||
trx->op_info = (char *) "adding foreign keys";
|
||||
@ -1498,7 +1561,7 @@ row_table_add_foreign_constraints(
|
||||
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
|
||||
row_drop_table_for_mysql(name, trx, TRUE);
|
||||
row_drop_table_for_mysql(name, trx);
|
||||
|
||||
trx->error_state = DB_SUCCESS;
|
||||
}
|
||||
@ -1529,7 +1592,7 @@ row_drop_table_for_mysql_in_background(
|
||||
name); */
|
||||
/* Drop the table in InnoDB */
|
||||
|
||||
error = row_drop_table_for_mysql(name, trx, FALSE);
|
||||
error = row_drop_table_for_mysql(name, trx);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
fprintf(stderr,
|
||||
@ -1688,9 +1751,7 @@ row_drop_table_for_mysql(
|
||||
/*=====================*/
|
||||
/* out: error code or DB_SUCCESS */
|
||||
char* name, /* in: table name */
|
||||
trx_t* trx, /* in: transaction handle */
|
||||
ibool has_dict_mutex) /* in: TRUE if the caller already owns the
|
||||
dictionary system mutex */
|
||||
trx_t* trx) /* in: transaction handle */
|
||||
{
|
||||
dict_table_t* table;
|
||||
que_thr_t* thr;
|
||||
@ -1702,6 +1763,7 @@ row_drop_table_for_mysql(
|
||||
ulint namelen;
|
||||
ulint keywordlen;
|
||||
ulint rounds = 0;
|
||||
ibool locked_dictionary = FALSE;
|
||||
char buf[10000];
|
||||
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
@ -1845,13 +1907,18 @@ row_drop_table_for_mysql(
|
||||
/* Serialize data dictionary operations with dictionary mutex:
|
||||
no deadlocks can occur then in these operations */
|
||||
|
||||
if (!has_dict_mutex) {
|
||||
/* Prevent foreign key checks while we are dropping the table */
|
||||
rw_lock_x_lock(&(dict_foreign_key_check_lock));
|
||||
if (trx->dict_operation_lock_mode != RW_X_LATCH) {
|
||||
/* Prevent foreign key checks etc. while we are dropping the
|
||||
table */
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
row_mysql_lock_data_dictionary(trx);
|
||||
|
||||
locked_dictionary = TRUE;
|
||||
}
|
||||
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
|
||||
|
||||
graph = pars_sql(buf);
|
||||
|
||||
ut_a(graph);
|
||||
@ -1861,9 +1928,6 @@ row_drop_table_for_mysql(
|
||||
|
||||
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
|
||||
|
||||
/* Prevent purge from running while we are dropping the table */
|
||||
rw_lock_s_lock(&(purge_sys->purge_is_running));
|
||||
|
||||
table = dict_table_get_low(name);
|
||||
|
||||
if (!table) {
|
||||
@ -1945,11 +2009,9 @@ row_drop_table_for_mysql(
|
||||
}
|
||||
}
|
||||
funct_exit:
|
||||
rw_lock_s_unlock(&(purge_sys->purge_is_running));
|
||||
|
||||
if (!has_dict_mutex) {
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
rw_lock_x_unlock(&(dict_foreign_key_check_lock));
|
||||
if (locked_dictionary) {
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
}
|
||||
|
||||
que_graph_free(graph);
|
||||
@ -1985,8 +2047,7 @@ row_drop_database_for_mysql(
|
||||
|
||||
trx_start_if_not_started(trx);
|
||||
loop:
|
||||
rw_lock_x_lock(&(dict_foreign_key_check_lock));
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
row_mysql_lock_data_dictionary(trx);
|
||||
|
||||
while ((table_name = dict_get_first_table_name_in_db(name))) {
|
||||
ut_a(memcmp(table_name, name, strlen(name)) == 0);
|
||||
@ -1999,8 +2060,7 @@ loop:
|
||||
the table */
|
||||
|
||||
if (table->n_mysql_handles_opened > 0) {
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
rw_lock_x_unlock(&(dict_foreign_key_check_lock));
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
@ -2015,7 +2075,7 @@ loop:
|
||||
goto loop;
|
||||
}
|
||||
|
||||
err = row_drop_table_for_mysql(table_name, trx, TRUE);
|
||||
err = row_drop_table_for_mysql(table_name, trx);
|
||||
|
||||
mem_free(table_name);
|
||||
|
||||
@ -2027,8 +2087,7 @@ loop:
|
||||
}
|
||||
}
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
rw_lock_x_unlock(&(dict_foreign_key_check_lock));
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
@ -2165,8 +2224,7 @@ row_rename_table_for_mysql(
|
||||
/* Serialize data dictionary operations with dictionary mutex:
|
||||
no deadlocks can occur then in these operations */
|
||||
|
||||
rw_lock_x_lock(&(dict_foreign_key_check_lock));
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
row_mysql_lock_data_dictionary(trx);
|
||||
|
||||
table = dict_table_get_low(old_name);
|
||||
|
||||
@ -2248,8 +2306,7 @@ row_rename_table_for_mysql(
|
||||
}
|
||||
}
|
||||
funct_exit:
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
rw_lock_x_unlock(&(dict_foreign_key_check_lock));
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
||||
que_graph_free(graph);
|
||||
|
||||
@ -2399,9 +2456,19 @@ row_check_table_for_mysql(
|
||||
ulint n_rows;
|
||||
ulint n_rows_in_table = ULINT_UNDEFINED;
|
||||
ulint ret = DB_SUCCESS;
|
||||
ulint old_isolation_level;
|
||||
|
||||
prebuilt->trx->op_info = (char *) "checking table";
|
||||
|
||||
old_isolation_level = prebuilt->trx->isolation_level;
|
||||
|
||||
/* We must run the index record counts at an isolation level
|
||||
>= READ COMMITTED, because a dirty read can see a wrong number
|
||||
of records in some index; to play safe, we use always
|
||||
REPEATABLE READ here */
|
||||
|
||||
prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
|
||||
|
||||
index = dict_table_get_first_index(table);
|
||||
|
||||
while (index != NULL) {
|
||||
@ -2433,6 +2500,9 @@ row_check_table_for_mysql(
|
||||
index = dict_table_get_next_index(index);
|
||||
}
|
||||
|
||||
/* Restore the original isolation level */
|
||||
prebuilt->trx->isolation_level = old_isolation_level;
|
||||
|
||||
/* We validate also the whole adaptive hash index for all tables
|
||||
at every CHECK TABLE */
|
||||
|
||||
|
@ -24,6 +24,7 @@ Created 3/14/1997 Heikki Tuuri
|
||||
#include "row0row.h"
|
||||
#include "row0upd.h"
|
||||
#include "row0vers.h"
|
||||
#include "row0mysql.h"
|
||||
#include "log0log.h"
|
||||
|
||||
/************************************************************************
|
||||
@ -453,7 +454,9 @@ static
|
||||
ibool
|
||||
row_purge_parse_undo_rec(
|
||||
/*=====================*/
|
||||
/* out: TRUE if purge operation required */
|
||||
/* out: TRUE if purge operation required:
|
||||
NOTE that then the CALLER must unfreeze
|
||||
data dictionary! */
|
||||
purge_node_t* node, /* in: row undo node */
|
||||
ibool* updated_extern,
|
||||
/* out: TRUE if an externally stored field
|
||||
@ -462,6 +465,7 @@ row_purge_parse_undo_rec(
|
||||
{
|
||||
dict_index_t* clust_index;
|
||||
byte* ptr;
|
||||
trx_t* trx;
|
||||
dulint undo_no;
|
||||
dulint table_id;
|
||||
dulint trx_id;
|
||||
@ -472,6 +476,8 @@ row_purge_parse_undo_rec(
|
||||
|
||||
ut_ad(node && thr);
|
||||
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
|
||||
updated_extern, &undo_no, &table_id);
|
||||
node->rec_type = type;
|
||||
@ -493,18 +499,21 @@ row_purge_parse_undo_rec(
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* Prevent DROP TABLE etc. from running when we are doing the purge
|
||||
for this row */
|
||||
|
||||
row_mysql_freeze_data_dictionary(trx);
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
|
||||
node->table = dict_table_get_on_id_low(table_id, thr_get_trx(thr));
|
||||
|
||||
rw_lock_x_lock(&(purge_sys->purge_is_running));
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
|
||||
if (node->table == NULL) {
|
||||
/* The table has been dropped: no need to do purge */
|
||||
|
||||
rw_lock_x_unlock(&(purge_sys->purge_is_running));
|
||||
row_mysql_unfreeze_data_dictionary(trx);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
@ -514,7 +523,7 @@ row_purge_parse_undo_rec(
|
||||
if (clust_index == NULL) {
|
||||
/* The table was corrupt in the data dictionary */
|
||||
|
||||
rw_lock_x_unlock(&(purge_sys->purge_is_running));
|
||||
row_mysql_unfreeze_data_dictionary(trx);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
@ -552,9 +561,12 @@ row_purge(
|
||||
dulint roll_ptr;
|
||||
ibool purge_needed;
|
||||
ibool updated_extern;
|
||||
trx_t* trx;
|
||||
|
||||
ut_ad(node && thr);
|
||||
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr,
|
||||
&(node->reservation),
|
||||
node->heap);
|
||||
@ -573,6 +585,8 @@ row_purge(
|
||||
} else {
|
||||
purge_needed = row_purge_parse_undo_rec(node, &updated_extern,
|
||||
thr);
|
||||
/* If purge_needed == TRUE, we must also remember to unfreeze
|
||||
data dictionary! */
|
||||
}
|
||||
|
||||
if (purge_needed) {
|
||||
@ -594,7 +608,7 @@ row_purge(
|
||||
btr_pcur_close(&(node->pcur));
|
||||
}
|
||||
|
||||
rw_lock_x_unlock(&(purge_sys->purge_is_running));
|
||||
row_mysql_unfreeze_data_dictionary(trx);
|
||||
}
|
||||
|
||||
/* Do some cleanup */
|
||||
|
@ -606,7 +606,7 @@ row_sel_get_clust_rec(
|
||||
/* Try to place a lock on the index record */
|
||||
|
||||
err = lock_clust_rec_read_check_and_lock(0, clust_rec, index,
|
||||
node->row_lock_mode, thr);
|
||||
node->row_lock_mode, LOCK_ORDINARY, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
return(err);
|
||||
@ -678,16 +678,17 @@ sel_set_rec_lock(
|
||||
rec_t* rec, /* in: record */
|
||||
dict_index_t* index, /* in: index */
|
||||
ulint mode, /* in: lock mode */
|
||||
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
{
|
||||
ulint err;
|
||||
|
||||
if (index->type & DICT_CLUSTERED) {
|
||||
err = lock_clust_rec_read_check_and_lock(0, rec, index, mode,
|
||||
thr);
|
||||
type, thr);
|
||||
} else {
|
||||
err = lock_sec_rec_read_check_and_lock(0, rec, index, mode,
|
||||
thr);
|
||||
type, thr);
|
||||
}
|
||||
|
||||
return(err);
|
||||
@ -1154,7 +1155,7 @@ rec_loop:
|
||||
|
||||
if (!consistent_read) {
|
||||
err = sel_set_rec_lock(page_rec_get_next(rec), index,
|
||||
node->row_lock_mode, thr);
|
||||
node->row_lock_mode, LOCK_ORDINARY, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
/* Note that in this case we will store in pcur
|
||||
the PREDECESSOR of the record we are waiting
|
||||
@ -1180,8 +1181,8 @@ rec_loop:
|
||||
if (!consistent_read) {
|
||||
/* Try to place a lock on the index record */
|
||||
|
||||
err = sel_set_rec_lock(rec, index, node->row_lock_mode, thr);
|
||||
|
||||
err = sel_set_rec_lock(rec, index, node->row_lock_mode,
|
||||
LOCK_ORDINARY, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto lock_wait_or_error;
|
||||
@ -2200,6 +2201,7 @@ row_sel_get_clust_rec_for_mysql(
|
||||
rec_t* old_vers;
|
||||
ulint err;
|
||||
trx_t* trx;
|
||||
char err_buf[1000];
|
||||
|
||||
*out_rec = NULL;
|
||||
|
||||
@ -2213,14 +2215,41 @@ row_sel_get_clust_rec_for_mysql(
|
||||
|
||||
clust_rec = btr_pcur_get_rec(prebuilt->clust_pcur);
|
||||
|
||||
ut_ad(page_rec_is_user_rec(clust_rec));
|
||||
if (!page_rec_is_user_rec(clust_rec)) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: error clustered record for sec rec not found\n"
|
||||
"InnoDB: index %s table %s\n", sec_index->name,
|
||||
sec_index->table->name);
|
||||
|
||||
rec_sprintf(err_buf, 900, rec);
|
||||
fprintf(stderr, "InnoDB: sec index record %s\n", err_buf);
|
||||
|
||||
rec_sprintf(err_buf, 900, clust_rec);
|
||||
fprintf(stderr, "InnoDB: clust index record %s\n", err_buf);
|
||||
|
||||
trx = thr_get_trx(thr);
|
||||
trx_print(err_buf, trx);
|
||||
|
||||
fprintf(stderr,
|
||||
"%s\nInnoDB: Make a detailed bug report and send it\n",
|
||||
err_buf);
|
||||
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
|
||||
|
||||
clust_rec = NULL;
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE) {
|
||||
/* Try to place a lock on the index record */
|
||||
/* Try to place a lock on the index record; we are searching
|
||||
the clust rec with a unique condition, hence
|
||||
we set a LOCK_REC_NOT_GAP type lock */
|
||||
|
||||
err = lock_clust_rec_read_check_and_lock(0, clust_rec,
|
||||
clust_index,
|
||||
prebuilt->select_lock_type, thr);
|
||||
prebuilt->select_lock_type,
|
||||
LOCK_REC_NOT_GAP, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
return(err);
|
||||
@ -2233,7 +2262,11 @@ row_sel_get_clust_rec_for_mysql(
|
||||
|
||||
old_vers = NULL;
|
||||
|
||||
if (!lock_clust_rec_cons_read_sees(clust_rec, clust_index,
|
||||
/* If the isolation level allows reading of uncommitted data,
|
||||
then we never look for an earlier version */
|
||||
|
||||
if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED
|
||||
&& !lock_clust_rec_cons_read_sees(clust_rec, clust_index,
|
||||
trx->read_view)) {
|
||||
|
||||
err = row_sel_build_prev_vers_for_mysql(
|
||||
@ -2275,6 +2308,7 @@ row_sel_get_clust_rec_for_mysql(
|
||||
}
|
||||
}
|
||||
|
||||
func_exit:
|
||||
*out_rec = clust_rec;
|
||||
|
||||
if (prebuilt->select_lock_type == LOCK_X) {
|
||||
@ -2407,7 +2441,7 @@ row_sel_push_cache_row_for_mysql(
|
||||
/*************************************************************************
|
||||
Tries to do a shortcut to fetch a clustered index record with a unique key,
|
||||
using the hash index if possible (not always). We assume that the search
|
||||
mode is PAGE_CUR_GE, it is a consistent read, trx has already a read view,
|
||||
mode is PAGE_CUR_GE, it is a consistent read, there is a read view in trx,
|
||||
btr search latch has been locked in S-mode. */
|
||||
static
|
||||
ulint
|
||||
@ -2516,17 +2550,23 @@ row_search_for_mysql(
|
||||
ibool was_lock_wait;
|
||||
ulint ret;
|
||||
ulint shortcut;
|
||||
ibool unique_search = FALSE;
|
||||
ibool unique_search_from_clust_index = FALSE;
|
||||
ibool mtr_has_extra_clust_latch = FALSE;
|
||||
ibool moves_up = FALSE;
|
||||
ibool set_also_gap_locks = TRUE;
|
||||
/* if the query is a plain
|
||||
locking SELECT, and the isolation
|
||||
level is <= TRX_ISO_READ_COMMITTED,
|
||||
then this is set to FALSE */
|
||||
ibool success;
|
||||
ulint cnt = 0;
|
||||
ulint next_offs;
|
||||
mtr_t mtr;
|
||||
|
||||
ut_ad(index && pcur && search_tuple);
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
|
||||
ut_ad(sync_thread_levels_empty_gen(FALSE));
|
||||
|
||||
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to free a corrupt\n"
|
||||
@ -2543,6 +2583,9 @@ row_search_for_mysql(
|
||||
|
||||
printf("N tables locked %lu\n", trx->mysql_n_tables_locked);
|
||||
*/
|
||||
/*-------------------------------------------------------------*/
|
||||
/* PHASE 1: Try to pop the row from the prefetch cache */
|
||||
|
||||
if (direction == 0) {
|
||||
trx->op_info = (char *) "starting index read";
|
||||
|
||||
@ -2608,18 +2651,35 @@ row_search_for_mysql(
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
/* Since we must release the search system latch when we retrieve an
|
||||
externally stored field, we cannot use the adaptive hash index in a
|
||||
search in the case the row may be long and there may be externally
|
||||
stored fields */
|
||||
/* In a search where at most one record in the index may match, we
|
||||
can use a LOCK_REC_NOT_GAP type record lock when locking a non-delete
|
||||
marked matching record.
|
||||
|
||||
Note that in a unique secondary index there may be different delete
|
||||
marked versions of a record where only the primary key values differ:
|
||||
thus in a secondary index we must use next-key locks when locking
|
||||
delete marked records. */
|
||||
|
||||
if (match_mode == ROW_SEL_EXACT
|
||||
&& index->type & DICT_UNIQUE
|
||||
&& index->type & DICT_CLUSTERED
|
||||
&& !prebuilt->templ_contains_blob
|
||||
&& (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)
|
||||
&& dtuple_get_n_fields(search_tuple)
|
||||
== dict_index_get_n_unique(index)) {
|
||||
unique_search = TRUE;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/* PHASE 2: Try fast adaptive hash index search if possible */
|
||||
|
||||
/* Next test if this is the special case where we can use the fast
|
||||
adaptive hash index to try the search. Since we must release the
|
||||
search system latch when we retrieve an externally stored field, we
|
||||
cannot use the adaptive hash index in a search in the case the row
|
||||
may be long and there may be externally stored fields */
|
||||
|
||||
if (unique_search
|
||||
&& index->type & DICT_CLUSTERED
|
||||
&& !prebuilt->templ_contains_blob
|
||||
&& (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
|
||||
|
||||
if (direction == ROW_SEL_NEXT) {
|
||||
/* MySQL sometimes seems to do fetch next even
|
||||
@ -2642,8 +2702,9 @@ row_search_for_mysql(
|
||||
|
||||
unique_search_from_clust_index = TRUE;
|
||||
|
||||
if (trx->mysql_n_tables_locked == 0
|
||||
&& !prebuilt->sql_stat_start) {
|
||||
if (prebuilt->select_lock_type == LOCK_NONE
|
||||
&& trx->isolation_level > TRX_ISO_READ_UNCOMMITTED
|
||||
&& trx->read_view) {
|
||||
|
||||
/* This is a SELECT query done as a consistent read,
|
||||
and the read view has already been allocated:
|
||||
@ -2722,7 +2783,11 @@ row_search_for_mysql(
|
||||
mtr_start(&mtr);
|
||||
}
|
||||
}
|
||||
|
||||
no_shortcut:
|
||||
/*-------------------------------------------------------------*/
|
||||
/* PHASE 3: Open or restore index cursor position */
|
||||
|
||||
if (trx->has_search_latch) {
|
||||
rw_lock_s_unlock(&btr_search_latch);
|
||||
trx->has_search_latch = FALSE;
|
||||
@ -2730,6 +2795,23 @@ no_shortcut:
|
||||
|
||||
trx_start_if_not_started(trx);
|
||||
|
||||
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
|
||||
&& prebuilt->select_lock_type != LOCK_NONE
|
||||
&& trx->mysql_query_str) {
|
||||
|
||||
/* Scan the MySQL query string; check if SELECT is the first
|
||||
word there */
|
||||
|
||||
dict_accept(*trx->mysql_query_str, "SELECT", &success);
|
||||
|
||||
if (success) {
|
||||
/* It is a plain locking SELECT and the isolation
|
||||
level is low: do not lock gaps */
|
||||
|
||||
set_also_gap_locks = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that if the search mode was GE or G, then the cursor
|
||||
naturally moves upward (in fetch next) in alphabetical order,
|
||||
otherwise downward */
|
||||
@ -2793,8 +2875,10 @@ no_shortcut:
|
||||
prebuilt->sql_stat_start = FALSE;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
rec_loop:
|
||||
/*-------------------------------------------------------------*/
|
||||
/* PHASE 4: Look for matching records in a loop */
|
||||
|
||||
cons_read_requires_clust_rec = FALSE;
|
||||
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
@ -2813,36 +2897,87 @@ rec_loop:
|
||||
goto next_rec;
|
||||
}
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE) {
|
||||
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE
|
||||
&& set_also_gap_locks) {
|
||||
|
||||
/* Try to place a lock on the index record */
|
||||
|
||||
err = sel_set_rec_lock(rec, index, prebuilt->select_lock_type,
|
||||
thr);
|
||||
err = sel_set_rec_lock(rec, index,
|
||||
prebuilt->select_lock_type,
|
||||
LOCK_ORDINARY, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
|
||||
/* A page supremum record cannot be in the result set: skip
|
||||
it now when we have placed a possible lock on it */
|
||||
it now that we have placed a possible lock on it */
|
||||
|
||||
goto next_rec;
|
||||
}
|
||||
|
||||
ut_ad(page_rec_is_user_rec(rec));
|
||||
/*-------------------------------------------------------------*/
|
||||
/* Do sanity checks in case our cursor has bumped into page
|
||||
corruption */
|
||||
|
||||
if (unique_search_from_clust_index && btr_pcur_get_up_match(pcur)
|
||||
== dtuple_get_n_fields(search_tuple)) {
|
||||
/* The record matches enough */
|
||||
next_offs = rec_get_next_offs(rec);
|
||||
|
||||
ut_ad(mode == PAGE_CUR_GE);
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
ut_a(0 == cmp_dtuple_rec(search_tuple, rec));
|
||||
#endif
|
||||
} else if (match_mode == ROW_SEL_EXACT) {
|
||||
if (next_offs >= UNIV_PAGE_SIZE || next_offs < PAGE_SUPREMUM) {
|
||||
|
||||
if (srv_force_recovery == 0 || moves_up == FALSE) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
|
||||
"InnoDB: index %s, table %s. Run CHECK TABLE to table. You may need to\n"
|
||||
"InnoDB: restore from a backup, or dump + drop + reimport the table.\n",
|
||||
(ulint)(rec - buf_frame_align(rec)), next_offs,
|
||||
buf_frame_get_page_no(rec), index->name,
|
||||
index->table_name);
|
||||
|
||||
err = DB_CORRUPTION;
|
||||
|
||||
goto lock_wait_or_error;
|
||||
} else {
|
||||
/* The user may be dumping a corrupt table. Jump
|
||||
over the corruption to recover as much as possible. */
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
|
||||
"InnoDB: index %s, table %s. We try to skip the rest of the page.\n",
|
||||
(ulint)(rec - buf_frame_align(rec)), next_offs,
|
||||
buf_frame_get_page_no(rec), index->name,
|
||||
index->table_name);
|
||||
|
||||
btr_pcur_move_to_last_on_page(pcur, &mtr);
|
||||
|
||||
goto next_rec;
|
||||
}
|
||||
}
|
||||
|
||||
if (srv_force_recovery > 0) {
|
||||
if (!rec_validate(rec) || !btr_index_rec_validate(rec, index,
|
||||
FALSE)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Index record corruption: rec offs %lu next offs %lu, page no %lu,\n"
|
||||
"InnoDB: index %s, table %s. We try to skip the record.\n",
|
||||
(ulint)(rec - buf_frame_align(rec)), next_offs,
|
||||
buf_frame_get_page_no(rec), index->name,
|
||||
index->table_name);
|
||||
|
||||
goto next_rec;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* Note that we cannot trust the up_match value in the cursor at this
|
||||
place because we can arrive here after moving the cursor! Thus
|
||||
we have to recompare rec and search_tuple to determine if they
|
||||
match enough. */
|
||||
|
||||
if (match_mode == ROW_SEL_EXACT) {
|
||||
/* Test if the index record matches completely to search_tuple
|
||||
in prebuilt: if not, then we return with DB_RECORD_NOT_FOUND */
|
||||
|
||||
@ -2850,6 +2985,19 @@ rec_loop:
|
||||
|
||||
if (0 != cmp_dtuple_rec(search_tuple, rec)) {
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE
|
||||
&& set_also_gap_locks) {
|
||||
/* Try to place a lock on the index record */
|
||||
|
||||
err = sel_set_rec_lock(rec, index,
|
||||
prebuilt->select_lock_type,
|
||||
LOCK_GAP, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
}
|
||||
|
||||
btr_pcur_store_position(pcur, &mtr);
|
||||
|
||||
ret = DB_RECORD_NOT_FOUND;
|
||||
@ -2862,6 +3010,19 @@ rec_loop:
|
||||
|
||||
if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec)) {
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE
|
||||
&& set_also_gap_locks) {
|
||||
/* Try to place a lock on the index record */
|
||||
|
||||
err = sel_set_rec_lock(rec, index,
|
||||
prebuilt->select_lock_type,
|
||||
LOCK_GAP, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
}
|
||||
|
||||
btr_pcur_store_position(pcur, &mtr);
|
||||
|
||||
ret = DB_RECORD_NOT_FOUND;
|
||||
@ -2874,16 +3035,39 @@ rec_loop:
|
||||
/* We are ready to look at a possible new index entry in the result
|
||||
set: the cursor is now placed on a user record */
|
||||
|
||||
/* Get the right version of the row in a consistent read */
|
||||
if (prebuilt->select_lock_type != LOCK_NONE) {
|
||||
/* Try to place a lock on the index record; note that delete
|
||||
marked records are a special case in a unique search. If there
|
||||
is a non-delete marked record, then it is enough to lock its
|
||||
existence with LOCK_REC_NOT_GAP. */
|
||||
|
||||
if (prebuilt->select_lock_type == LOCK_NONE) {
|
||||
if (!set_also_gap_locks
|
||||
|| (unique_search && !rec_get_deleted_flag(rec))) {
|
||||
err = sel_set_rec_lock(rec, index,
|
||||
prebuilt->select_lock_type,
|
||||
LOCK_REC_NOT_GAP, thr);
|
||||
} else {
|
||||
err = sel_set_rec_lock(rec, index,
|
||||
prebuilt->select_lock_type,
|
||||
LOCK_ORDINARY, thr);
|
||||
}
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
} else {
|
||||
/* This is a non-locking consistent read: if necessary, fetch
|
||||
a previous version of the record */
|
||||
|
||||
cons_read_requires_clust_rec = FALSE;
|
||||
|
||||
if (index == clust_index) {
|
||||
if (trx->isolation_level == TRX_ISO_READ_UNCOMMITTED) {
|
||||
|
||||
/* Do nothing: we let a non-locking SELECT read the
|
||||
latest version of the record */
|
||||
|
||||
} else if (index == clust_index) {
|
||||
|
||||
if (!lock_clust_rec_cons_read_sees(rec, index,
|
||||
trx->read_view)) {
|
||||
@ -3020,8 +3204,11 @@ got_row:
|
||||
ret = DB_SUCCESS;
|
||||
|
||||
goto normal_return;
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
next_rec:
|
||||
/*-------------------------------------------------------------*/
|
||||
/* PHASE 5: Move the cursor to the next index record */
|
||||
|
||||
if (mtr_has_extra_clust_latch) {
|
||||
/* We must commit mtr if we are moving to the next
|
||||
non-clustered index record, because we could break the
|
||||
@ -3064,8 +3251,10 @@ next_rec:
|
||||
cnt++;
|
||||
|
||||
goto rec_loop;
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
lock_wait_or_error:
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
btr_pcur_store_position(pcur, &mtr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
@ -3096,6 +3285,7 @@ lock_wait_or_error:
|
||||
return(err);
|
||||
|
||||
normal_return:
|
||||
/*-------------------------------------------------------------*/
|
||||
que_thr_stop_for_mysql_no_error(thr, trx);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
@ -3156,10 +3346,12 @@ row_search_check_if_query_cache_permitted(
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
/* Assign a read view for the transaction if it does not yet
|
||||
have one */
|
||||
/* If the isolation level is high, assign a read view for the
|
||||
transaction if it does not yet have one */
|
||||
|
||||
if (trx->isolation_level >= TRX_ISO_REPEATABLE_READ
|
||||
&& !trx->read_view) {
|
||||
|
||||
if (!trx->read_view) {
|
||||
trx->read_view = read_view_open_now(trx,
|
||||
trx->read_view_heap);
|
||||
}
|
||||
|
@ -254,6 +254,7 @@ row_undo_ins_parse_undo_rec(
|
||||
node->table = dict_table_get_on_id(table_id, node->trx);
|
||||
|
||||
if (node->table == NULL) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -292,6 +293,7 @@ row_undo_ins(
|
||||
|
||||
if (!found) {
|
||||
trx_undo_rec_release(node->trx, node->undo_no);
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ Created 1/8/1997 Heikki Tuuri
|
||||
#include "row0row.h"
|
||||
#include "row0uins.h"
|
||||
#include "row0umod.h"
|
||||
#include "row0mysql.h"
|
||||
#include "srv0srv.h"
|
||||
|
||||
/* How to undo row operations?
|
||||
@ -204,6 +205,7 @@ row_undo(
|
||||
ulint err;
|
||||
trx_t* trx;
|
||||
dulint roll_ptr;
|
||||
ibool froze_data_dict = FALSE;
|
||||
|
||||
ut_ad(node && thr);
|
||||
|
||||
@ -211,7 +213,6 @@ row_undo(
|
||||
|
||||
if (node->state == UNDO_NODE_FETCH_NEXT) {
|
||||
|
||||
/* The call below also starts &mtr */
|
||||
node->undo_rec = trx_roll_pop_top_rec_of_trx(trx,
|
||||
trx->roll_limit,
|
||||
&roll_ptr,
|
||||
@ -254,6 +255,18 @@ row_undo(
|
||||
}
|
||||
}
|
||||
|
||||
/* Prevent DROP TABLE etc. while we are rolling back this row.
|
||||
If we are doing a TABLE CREATE or some other dictionary operation,
|
||||
then we already have dict_operation_lock locked in x-mode. Do not
|
||||
try to lock again in s-mode, because that would cause a hang. */
|
||||
|
||||
if (trx->dict_operation_lock_mode == 0) {
|
||||
|
||||
row_mysql_freeze_data_dictionary(trx);
|
||||
|
||||
froze_data_dict = TRUE;
|
||||
}
|
||||
|
||||
if (node->state == UNDO_NODE_INSERT) {
|
||||
|
||||
err = row_undo_ins(node, thr);
|
||||
@ -264,6 +277,11 @@ row_undo(
|
||||
err = row_undo_mod(node, thr);
|
||||
}
|
||||
|
||||
if (froze_data_dict) {
|
||||
|
||||
row_mysql_unfreeze_data_dictionary(trx);
|
||||
}
|
||||
|
||||
/* Do some cleanup */
|
||||
btr_pcur_close(&(node->pcur));
|
||||
|
||||
|
@ -79,7 +79,7 @@ ibool
|
||||
row_upd_index_is_referenced(
|
||||
/*========================*/
|
||||
/* out: TRUE if referenced; NOTE that since
|
||||
we do not hold dict_foreign_key_check_lock
|
||||
we do not hold dict_operation_lock
|
||||
when leaving the function, it may be that
|
||||
the referencing table has been dropped when
|
||||
we leave this function: this function is only
|
||||
@ -89,14 +89,16 @@ row_upd_index_is_referenced(
|
||||
{
|
||||
dict_table_t* table = index->table;
|
||||
dict_foreign_t* foreign;
|
||||
ibool froze_data_dict = FALSE;
|
||||
|
||||
if (!UT_LIST_GET_FIRST(table->referenced_list)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (!trx->has_dict_foreign_key_check_lock) {
|
||||
rw_lock_s_lock(&dict_foreign_key_check_lock);
|
||||
if (trx->dict_operation_lock_mode == 0) {
|
||||
row_mysql_freeze_data_dictionary(trx);
|
||||
froze_data_dict = TRUE;
|
||||
}
|
||||
|
||||
foreign = UT_LIST_GET_FIRST(table->referenced_list);
|
||||
@ -104,8 +106,8 @@ row_upd_index_is_referenced(
|
||||
while (foreign) {
|
||||
if (foreign->referenced_index == index) {
|
||||
|
||||
if (!trx->has_dict_foreign_key_check_lock) {
|
||||
rw_lock_s_unlock(&dict_foreign_key_check_lock);
|
||||
if (froze_data_dict) {
|
||||
row_mysql_unfreeze_data_dictionary(trx);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
@ -114,8 +116,8 @@ row_upd_index_is_referenced(
|
||||
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
|
||||
}
|
||||
|
||||
if (!trx->has_dict_foreign_key_check_lock) {
|
||||
rw_lock_s_unlock(&dict_foreign_key_check_lock);
|
||||
if (froze_data_dict) {
|
||||
row_mysql_unfreeze_data_dictionary(trx);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
@ -162,12 +164,10 @@ row_upd_check_references_constraints(
|
||||
|
||||
mtr_start(mtr);
|
||||
|
||||
if (!trx->has_dict_foreign_key_check_lock) {
|
||||
if (trx->dict_operation_lock_mode == 0) {
|
||||
got_s_lock = TRUE;
|
||||
|
||||
rw_lock_s_lock(&dict_foreign_key_check_lock);
|
||||
|
||||
trx->has_dict_foreign_key_check_lock = TRUE;
|
||||
row_mysql_freeze_data_dictionary(trx);
|
||||
}
|
||||
|
||||
foreign = UT_LIST_GET_FIRST(table->referenced_list);
|
||||
@ -189,7 +189,7 @@ row_upd_check_references_constraints(
|
||||
}
|
||||
|
||||
/* NOTE that if the thread ends up waiting for a lock
|
||||
we will release dict_foreign_key_check_lock
|
||||
we will release dict_operation_lock
|
||||
temporarily! But the counter on the table
|
||||
protects 'foreign' from being dropped while the check
|
||||
is running. */
|
||||
@ -211,10 +211,7 @@ row_upd_check_references_constraints(
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (got_s_lock) {
|
||||
rw_lock_s_unlock(
|
||||
&dict_foreign_key_check_lock);
|
||||
trx->has_dict_foreign_key_check_lock
|
||||
= FALSE;
|
||||
row_mysql_unfreeze_data_dictionary(trx);
|
||||
}
|
||||
|
||||
mem_heap_free(heap);
|
||||
@ -227,8 +224,7 @@ row_upd_check_references_constraints(
|
||||
}
|
||||
|
||||
if (got_s_lock) {
|
||||
rw_lock_s_unlock(&dict_foreign_key_check_lock);
|
||||
trx->has_dict_foreign_key_check_lock = FALSE;
|
||||
row_mysql_unfreeze_data_dictionary(trx);
|
||||
}
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
@ -51,6 +51,10 @@ Created 10/8/1995 Heikki Tuuri
|
||||
#include "srv0start.h"
|
||||
#include "row0mysql.h"
|
||||
|
||||
/* This is set to TRUE if the MySQL user has set it in MySQL; currently
|
||||
affects only FOREIGN KEY definition parsing */
|
||||
ibool srv_lower_case_table_names = FALSE;
|
||||
|
||||
/* Buffer which can be used in printing fatal error messages */
|
||||
char srv_fatal_errbuf[5000];
|
||||
|
||||
@ -136,8 +140,6 @@ byte srv_latin1_ordering[256] /* The sort order table of the latin1
|
||||
, 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xFF
|
||||
};
|
||||
|
||||
ibool srv_use_native_aio = FALSE;
|
||||
|
||||
ulint srv_pool_size = ULINT_MAX; /* size in database pages;
|
||||
MySQL originally sets this
|
||||
value in megabytes */
|
||||
@ -151,8 +153,9 @@ dulint srv_archive_recovery_limit_lsn;
|
||||
|
||||
ulint srv_lock_wait_timeout = 1024 * 1024 * 1024;
|
||||
|
||||
char* srv_unix_file_flush_method_str = NULL;
|
||||
ulint srv_unix_file_flush_method = 0;
|
||||
char* srv_file_flush_method_str = NULL;
|
||||
ulint srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
|
||||
ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
|
||||
|
||||
/* If the following is != 0 we do not allow inserts etc. This protects
|
||||
the user from forgetting the innodb_force_recovery keyword to my.cnf */
|
||||
@ -281,6 +284,9 @@ time_t srv_last_monitor_time;
|
||||
|
||||
mutex_t srv_innodb_monitor_mutex;
|
||||
|
||||
ulint srv_main_thread_process_no = 0;
|
||||
ulint srv_main_thread_id = 0;
|
||||
|
||||
/*
|
||||
IMPLEMENTATION OF THE SERVER MAIN PROGRAM
|
||||
=========================================
|
||||
@ -2046,13 +2052,15 @@ srv_table_reserve_slot_for_mysql(void)
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Puts a MySQL OS thread to wait for a lock to be released. */
|
||||
Puts a MySQL OS thread to wait for a lock to be released. If an error
|
||||
occurs during the wait trx->error_state associated with thr is
|
||||
!= DB_SUCCESS when we return. DB_LOCK_WAIT_TIMEOUT and DB_DEADLOCK
|
||||
are possible errors. DB_DEADLOCK is returned if selective deadlock
|
||||
resolution chose this transaction as a victim. */
|
||||
|
||||
ibool
|
||||
void
|
||||
srv_suspend_mysql_thread(
|
||||
/*=====================*/
|
||||
/* out: TRUE if the lock wait timeout was
|
||||
exceeded */
|
||||
que_thr_t* thr) /* in: query thread associated with the MySQL
|
||||
OS thread */
|
||||
{
|
||||
@ -2060,6 +2068,7 @@ srv_suspend_mysql_thread(
|
||||
os_event_t event;
|
||||
double wait_time;
|
||||
trx_t* trx;
|
||||
ibool had_dict_lock = FALSE;
|
||||
|
||||
ut_ad(!mutex_own(&kernel_mutex));
|
||||
|
||||
@ -2069,15 +2078,28 @@ srv_suspend_mysql_thread(
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
trx->error_state = DB_SUCCESS;
|
||||
|
||||
if (thr->state == QUE_THR_RUNNING) {
|
||||
|
||||
/* The lock has already been released: no need to suspend */
|
||||
ut_ad(thr->is_active == TRUE);
|
||||
|
||||
/* The lock has already been released or this transaction
|
||||
was chosen as a deadlock victim: no need to suspend */
|
||||
|
||||
if (trx->was_chosen_as_deadlock_victim) {
|
||||
|
||||
trx->error_state = DB_DEADLOCK;
|
||||
trx->was_chosen_as_deadlock_victim = FALSE;
|
||||
}
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
return(FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
ut_ad(thr->is_active == FALSE);
|
||||
|
||||
slot = srv_table_reserve_slot_for_mysql();
|
||||
|
||||
event = slot->event;
|
||||
@ -2101,18 +2123,22 @@ srv_suspend_mysql_thread(
|
||||
srv_conc_force_exit_innodb(thr_get_trx(thr));
|
||||
|
||||
/* Release possible foreign key check latch */
|
||||
if (trx->has_dict_foreign_key_check_lock) {
|
||||
if (trx->dict_operation_lock_mode == RW_S_LATCH) {
|
||||
|
||||
rw_lock_s_unlock(&dict_foreign_key_check_lock);
|
||||
had_dict_lock = TRUE;
|
||||
|
||||
row_mysql_unfreeze_data_dictionary(trx);
|
||||
}
|
||||
|
||||
ut_a(trx->dict_operation_lock_mode == 0);
|
||||
|
||||
/* Wait for the release */
|
||||
|
||||
os_event_wait(event);
|
||||
|
||||
if (trx->has_dict_foreign_key_check_lock) {
|
||||
if (had_dict_lock) {
|
||||
|
||||
rw_lock_s_lock(&dict_foreign_key_check_lock);
|
||||
row_mysql_freeze_data_dictionary(trx);
|
||||
}
|
||||
|
||||
/* Return back inside InnoDB */
|
||||
@ -2127,14 +2153,19 @@ srv_suspend_mysql_thread(
|
||||
|
||||
wait_time = ut_difftime(ut_time(), slot->suspend_time);
|
||||
|
||||
if (trx->was_chosen_as_deadlock_victim) {
|
||||
|
||||
trx->error_state = DB_DEADLOCK;
|
||||
trx->was_chosen_as_deadlock_victim = FALSE;
|
||||
}
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
if (srv_lock_wait_timeout < 100000000 &&
|
||||
wait_time > (double)srv_lock_wait_timeout) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
trx->error_state = DB_LOCK_WAIT_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@ -2300,9 +2331,19 @@ srv_sprintf_innodb_monitor(
|
||||
"ROW OPERATIONS\n"
|
||||
"--------------\n");
|
||||
buf += sprintf(buf,
|
||||
"%ld queries inside InnoDB, %ld queries in queue; main thread: %s\n",
|
||||
srv_conc_n_threads, srv_conc_n_waiting_threads,
|
||||
"%ld queries inside InnoDB, %ld queries in queue\n",
|
||||
srv_conc_n_threads, srv_conc_n_waiting_threads);
|
||||
#ifdef UNIV_LINUX
|
||||
buf += sprintf(buf,
|
||||
"Main thread process no %lu, state: %s\n",
|
||||
srv_main_thread_process_no,
|
||||
srv_main_thread_op_info);
|
||||
#else
|
||||
buf += sprintf(buf,
|
||||
"Main thread id %lu, state: %s\n",
|
||||
srv_main_thread_id,
|
||||
srv_main_thread_op_info);
|
||||
#endif
|
||||
buf += sprintf(buf,
|
||||
"Number of rows inserted %lu, updated %lu, deleted %lu, read %lu\n",
|
||||
srv_n_rows_inserted,
|
||||
@ -2636,6 +2677,9 @@ srv_master_thread(
|
||||
|
||||
UT_NOT_USED(arg);
|
||||
|
||||
srv_main_thread_process_no = os_proc_get_number();
|
||||
srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
|
||||
|
||||
srv_table_reserve_slot(SRV_MASTER);
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
@ -56,6 +56,10 @@ Created 2/16/1996 Heikki Tuuri
|
||||
#include "srv0start.h"
|
||||
#include "que0que.h"
|
||||
|
||||
ibool srv_start_has_been_called = FALSE;
|
||||
|
||||
ulint srv_sizeof_trx_t_in_ha_innodb_cc;
|
||||
|
||||
ibool srv_startup_is_before_trx_rollback_phase = FALSE;
|
||||
ibool srv_is_being_started = FALSE;
|
||||
ibool srv_was_started = FALSE;
|
||||
@ -515,7 +519,7 @@ srv_calc_high32(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Creates or opens the log files. */
|
||||
Creates or opens the log files and closes them. */
|
||||
static
|
||||
ulint
|
||||
open_or_create_log_file(
|
||||
@ -640,7 +644,7 @@ open_or_create_log_file(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Creates or opens database data files. */
|
||||
Creates or opens database data files and closes them. */
|
||||
static
|
||||
ulint
|
||||
open_or_create_data_files(
|
||||
@ -960,36 +964,91 @@ innobase_start_or_create_for_mysql(void)
|
||||
"InnoDB: !!!!!!!!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!!!!!!!\n");
|
||||
#endif
|
||||
|
||||
if (srv_sizeof_trx_t_in_ha_innodb_cc != (ulint)sizeof(trx_t)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trx_t size is %lu in ha_innodb.cc but %lu in srv0start.c\n"
|
||||
"InnoDB: Check that pthread_mutex_t is defined in the same way in these\n"
|
||||
"InnoDB: compilation modules. Cannot continue.\n",
|
||||
srv_sizeof_trx_t_in_ha_innodb_cc, (ulint)sizeof(trx_t));
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
/* Since InnoDB does not currently clean up all its internal data
|
||||
structures in MySQL Embedded Server Library server_end(), we
|
||||
print an error message if someone tries to start up InnoDB a
|
||||
second time during the process lifetime. */
|
||||
|
||||
if (srv_start_has_been_called) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error:startup called second time during the process lifetime.\n"
|
||||
"InnoDB: In the MySQL Embedded Server Library you cannot call server_init()\n"
|
||||
"InnoDB: more than once during the process lifetime.\n");
|
||||
}
|
||||
|
||||
srv_start_has_been_called = TRUE;
|
||||
|
||||
log_do_write = TRUE;
|
||||
/* yydebug = TRUE; */
|
||||
|
||||
srv_is_being_started = TRUE;
|
||||
srv_startup_is_before_trx_rollback_phase = TRUE;
|
||||
os_aio_use_native_aio = FALSE;
|
||||
|
||||
#ifdef __WIN__
|
||||
if (os_get_os_version() == OS_WIN95
|
||||
|| os_get_os_version() == OS_WIN31
|
||||
|| os_get_os_version() == OS_WINNT) {
|
||||
|
||||
/* On Win 95, 98, ME, Win32 subsystem for Windows 3.1,
|
||||
and NT use simulated aio. In NT Windows provides async i/o,
|
||||
but when run in conjunction with InnoDB Hot Backup, it seemed
|
||||
to corrupt the data files. */
|
||||
|
||||
os_aio_use_native_aio = FALSE;
|
||||
} else {
|
||||
/* On Win 2000 and XP use async i/o */
|
||||
os_aio_use_native_aio = TRUE;
|
||||
}
|
||||
#endif
|
||||
if (srv_file_flush_method_str == NULL) {
|
||||
/* These are the default options */
|
||||
|
||||
if (0 == ut_strcmp(srv_unix_file_flush_method_str, "fdatasync")) {
|
||||
srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
|
||||
|
||||
} else if (0 == ut_strcmp(srv_unix_file_flush_method_str, "O_DSYNC")) {
|
||||
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
|
||||
#ifndef __WIN__
|
||||
} else if (0 == ut_strcmp(srv_file_flush_method_str, "fdatasync")) {
|
||||
srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
|
||||
|
||||
} else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
|
||||
srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
|
||||
|
||||
} else if (0 == ut_strcmp(srv_unix_file_flush_method_str,
|
||||
} else if (0 == ut_strcmp(srv_file_flush_method_str,
|
||||
"littlesync")) {
|
||||
srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
|
||||
|
||||
} else if (0 == ut_strcmp(srv_unix_file_flush_method_str, "nosync")) {
|
||||
} else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
|
||||
srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
|
||||
#else
|
||||
} else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
|
||||
srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
|
||||
os_aio_use_native_aio = FALSE;
|
||||
|
||||
} else if (0 == ut_strcmp(srv_file_flush_method_str, "unbuffered")) {
|
||||
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
|
||||
os_aio_use_native_aio = FALSE;
|
||||
|
||||
} else if (0 == ut_strcmp(srv_file_flush_method_str,
|
||||
"async_unbuffered")) {
|
||||
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
|
||||
#endif
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Unrecognized value %s for innodb_flush_method\n",
|
||||
srv_unix_file_flush_method_str);
|
||||
srv_file_flush_method_str);
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
printf("srv_unix set to %lu\n", srv_unix_file_flush_method);
|
||||
*/
|
||||
os_aio_use_native_aio = srv_use_native_aio;
|
||||
|
||||
err = srv_boot();
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
@ -999,34 +1058,15 @@ innobase_start_or_create_for_mysql(void)
|
||||
|
||||
/* Restrict the maximum number of file i/o threads */
|
||||
if (srv_n_file_io_threads > SRV_MAX_N_IO_THREADS) {
|
||||
|
||||
srv_n_file_io_threads = SRV_MAX_N_IO_THREADS;
|
||||
}
|
||||
|
||||
#if !(defined(WIN_ASYNC_IO) || defined(POSIX_ASYNC_IO))
|
||||
if (!os_aio_use_native_aio) {
|
||||
/* In simulated aio we currently have use only for 4 threads */
|
||||
|
||||
os_aio_use_native_aio = FALSE;
|
||||
|
||||
srv_n_file_io_threads = 4;
|
||||
#endif
|
||||
|
||||
#ifdef __WIN__
|
||||
if (os_get_os_version() == OS_WIN95
|
||||
|| os_get_os_version() == OS_WIN31) {
|
||||
|
||||
/* On Win 95, 98, ME, and Win32 subsystem for Windows 3.1 use
|
||||
simulated aio */
|
||||
|
||||
os_aio_use_native_aio = FALSE;
|
||||
srv_n_file_io_threads = 4;
|
||||
} else {
|
||||
/* On NT and Win 2000 always use aio */
|
||||
os_aio_use_native_aio = TRUE;
|
||||
}
|
||||
#endif
|
||||
os_aio_use_native_aio = FALSE;
|
||||
|
||||
if (!os_aio_use_native_aio) {
|
||||
os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
|
||||
* srv_n_file_io_threads,
|
||||
srv_n_file_io_threads,
|
||||
@ -1047,15 +1087,6 @@ innobase_start_or_create_for_mysql(void)
|
||||
|
||||
lock_sys_create(srv_lock_table_size);
|
||||
|
||||
#ifdef POSIX_ASYNC_IO
|
||||
if (os_aio_use_native_aio) {
|
||||
/* There is only one thread per async io array:
|
||||
one for ibuf i/o, one for log i/o, one for ordinary reads,
|
||||
one for ordinary writes; we need only 4 i/o threads */
|
||||
|
||||
srv_n_file_io_threads = 4;
|
||||
}
|
||||
#endif
|
||||
/* Create i/o-handler threads: */
|
||||
|
||||
for (i = 0; i < srv_n_file_io_threads; i++) {
|
||||
@ -1365,7 +1396,7 @@ innobase_start_or_create_for_mysql(void)
|
||||
if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: pthread_mutex_trylock returns an unexpected value on\n"
|
||||
"InnoDB: success! Cannot continue.\n");
|
||||
"InnoDB: success! Cannot continue.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -1375,11 +1406,17 @@ innobase_start_or_create_for_mysql(void)
|
||||
|
||||
os_fast_mutex_unlock(&srv_os_test_mutex);
|
||||
|
||||
if (srv_print_verbose_log)
|
||||
{
|
||||
if (srv_print_verbose_log) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: Started\n");
|
||||
}
|
||||
|
||||
if (srv_force_recovery > 0) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: !!! innodb_force_recovery is set to %lu !!!\n",
|
||||
srv_force_recovery);
|
||||
}
|
||||
|
||||
return((int) DB_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
timestamp
|
@ -663,7 +663,8 @@ rw_lock_own(
|
||||
/*========*/
|
||||
/* out: TRUE if locked */
|
||||
rw_lock_t* lock, /* in: rw-lock */
|
||||
ulint lock_type) /* in: lock type */
|
||||
ulint lock_type) /* in: lock type: RW_LOCK_SHARED,
|
||||
RW_LOCK_EX */
|
||||
{
|
||||
rw_lock_debug_t* info;
|
||||
|
||||
|
@ -901,8 +901,7 @@ sync_thread_levels_empty_gen(
|
||||
|
||||
if (slot->latch != NULL && (!dict_mutex_allowed ||
|
||||
(slot->level != SYNC_DICT
|
||||
&& slot->level != SYNC_FOREIGN_KEY_CHECK
|
||||
&& slot->level != SYNC_PURGE_IS_RUNNING))) {
|
||||
&& slot->level != SYNC_DICT_OPERATION))) {
|
||||
|
||||
lock = slot->latch;
|
||||
mutex = slot->latch;
|
||||
@ -1087,12 +1086,10 @@ sync_thread_add_level(
|
||||
SYNC_IBUF_PESS_INSERT_MUTEX));
|
||||
} else if (level == SYNC_DICT_AUTOINC_MUTEX) {
|
||||
ut_a(sync_thread_levels_g(array, SYNC_DICT_AUTOINC_MUTEX));
|
||||
} else if (level == SYNC_FOREIGN_KEY_CHECK) {
|
||||
ut_a(sync_thread_levels_g(array, SYNC_FOREIGN_KEY_CHECK));
|
||||
} else if (level == SYNC_DICT_OPERATION) {
|
||||
ut_a(sync_thread_levels_g(array, SYNC_DICT_OPERATION));
|
||||
} else if (level == SYNC_DICT_HEADER) {
|
||||
ut_a(sync_thread_levels_g(array, SYNC_DICT_HEADER));
|
||||
} else if (level == SYNC_PURGE_IS_RUNNING) {
|
||||
ut_a(sync_thread_levels_g(array, SYNC_PURGE_IS_RUNNING));
|
||||
} else if (level == SYNC_DICT) {
|
||||
ut_a(buf_debug_prints
|
||||
|| sync_thread_levels_g(array, SYNC_DICT));
|
||||
|
@ -209,9 +209,6 @@ trx_purge_sys_create(void)
|
||||
purge_sys->purge_undo_no = ut_dulint_zero;
|
||||
purge_sys->next_stored = FALSE;
|
||||
|
||||
rw_lock_create(&(purge_sys->purge_is_running));
|
||||
rw_lock_set_level(&(purge_sys->purge_is_running),
|
||||
SYNC_PURGE_IS_RUNNING);
|
||||
rw_lock_create(&(purge_sys->latch));
|
||||
rw_lock_set_level(&(purge_sys->latch), SYNC_PURGE_LATCH);
|
||||
|
||||
|
@ -254,7 +254,7 @@ loop:
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
if (trx->dict_operation) {
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
row_mysql_lock_data_dictionary(trx);
|
||||
}
|
||||
|
||||
que_run_threads(thr);
|
||||
@ -290,14 +290,14 @@ loop:
|
||||
fprintf(stderr,
|
||||
"InnoDB: Table found: dropping table %s in recovery\n", table->name);
|
||||
|
||||
err = row_drop_table_for_mysql(table->name, trx,
|
||||
TRUE);
|
||||
err = row_drop_table_for_mysql(table->name, trx);
|
||||
|
||||
ut_a(err == (int) DB_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
if (trx->dict_operation) {
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
}
|
||||
|
||||
fprintf(stderr, "InnoDB: Rolling back of trx id %lu %lu completed\n",
|
||||
|
@ -23,7 +23,7 @@ Created 3/26/1996 Heikki Tuuri
|
||||
#include "srv0srv.h"
|
||||
#include "thr0loc.h"
|
||||
#include "btr0sea.h"
|
||||
|
||||
#include "os0proc.h"
|
||||
|
||||
/* Copy of the prototype for innobase_mysql_print_thd: this
|
||||
copy MUST be equal to the one in mysql/sql/ha_innobase.cc ! */
|
||||
@ -85,12 +85,14 @@ trx_create(
|
||||
trx->conc_state = TRX_NOT_STARTED;
|
||||
trx->start_time = time(NULL);
|
||||
|
||||
trx->isolation_level = TRX_ISO_REPEATABLE_READ;
|
||||
trx->check_foreigns = TRUE;
|
||||
trx->check_unique_secondary = TRUE;
|
||||
|
||||
trx->dict_operation = FALSE;
|
||||
|
||||
trx->mysql_thd = NULL;
|
||||
trx->mysql_query_str = NULL;
|
||||
|
||||
trx->n_mysql_tables_in_use = 0;
|
||||
trx->mysql_n_tables_locked = 0;
|
||||
@ -127,12 +129,13 @@ trx_create(
|
||||
trx->graph = NULL;
|
||||
|
||||
trx->wait_lock = NULL;
|
||||
trx->was_chosen_as_deadlock_victim = FALSE;
|
||||
UT_LIST_INIT(trx->wait_thrs);
|
||||
|
||||
trx->lock_heap = mem_heap_create_in_buffer(256);
|
||||
UT_LIST_INIT(trx->trx_locks);
|
||||
|
||||
trx->has_dict_foreign_key_check_lock = FALSE;
|
||||
trx->dict_operation_lock_mode = 0;
|
||||
trx->has_search_latch = FALSE;
|
||||
trx->search_latch_timeout = BTR_SEA_TIMEOUT;
|
||||
|
||||
@ -176,6 +179,8 @@ trx_allocate_for_mysql(void)
|
||||
|
||||
trx->mysql_thread_id = os_thread_get_curr_id();
|
||||
|
||||
trx->mysql_process_no = os_proc_get_number();
|
||||
|
||||
return(trx);
|
||||
}
|
||||
|
||||
@ -257,6 +262,8 @@ trx_free(
|
||||
ut_a(!trx->has_search_latch);
|
||||
ut_a(!trx->auto_inc_lock);
|
||||
|
||||
ut_a(trx->dict_operation_lock_mode == 0);
|
||||
|
||||
if (trx->lock_heap) {
|
||||
mem_heap_free(trx->lock_heap);
|
||||
}
|
||||
@ -1497,9 +1504,12 @@ trx_print(
|
||||
default: buf += sprintf(buf, " state %lu", trx->conc_state);
|
||||
}
|
||||
|
||||
#ifdef UNIV_LINUX
|
||||
buf += sprintf(buf, ", process no %lu", trx->mysql_process_no);
|
||||
#else
|
||||
buf += sprintf(buf, ", OS thread id %lu",
|
||||
os_thread_pf(trx->mysql_thread_id));
|
||||
|
||||
#endif
|
||||
if (ut_strlen(trx->op_info) > 0) {
|
||||
buf += sprintf(buf, " %s", trx->op_info);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ struct st_file_buffer {
|
||||
char *buffer,*pos,*end;
|
||||
my_off_t pos_in_file;
|
||||
int bits;
|
||||
uint byte;
|
||||
uint bytes;
|
||||
};
|
||||
|
||||
struct st_huff_tree;
|
||||
@ -1835,7 +1835,7 @@ static void init_file_buffer(File file, pbool read_buffer)
|
||||
file_buffer.pos=file_buffer.buffer;
|
||||
file_buffer.bits=BITS_SAVED;
|
||||
}
|
||||
file_buffer.byte=0;
|
||||
file_buffer.bytes=0;
|
||||
}
|
||||
|
||||
|
||||
@ -1866,13 +1866,13 @@ static void write_bits (register ulong value, register uint bits)
|
||||
{
|
||||
if ((file_buffer.bits-=(int) bits) >= 0)
|
||||
{
|
||||
file_buffer.byte|=value << file_buffer.bits;
|
||||
file_buffer.bytes|=value << file_buffer.bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
reg3 uint byte_buff;
|
||||
bits= (uint) -file_buffer.bits;
|
||||
byte_buff=file_buffer.byte | (uint) (value >> bits);
|
||||
byte_buff=file_buffer.bytes | (uint) (value >> bits);
|
||||
#if BITS_SAVED == 32
|
||||
*file_buffer.pos++= (byte) (byte_buff >> 24) ;
|
||||
*file_buffer.pos++= (byte) (byte_buff >> 16) ;
|
||||
@ -1898,7 +1898,7 @@ static void write_bits (register ulong value, register uint bits)
|
||||
if (file_buffer.pos >= file_buffer.end)
|
||||
VOID(flush_buffer((uint) ~0));
|
||||
file_buffer.bits=(int) (BITS_SAVED - bits);
|
||||
file_buffer.byte=(uint) (value << (BITS_SAVED - bits));
|
||||
file_buffer.bytes=(uint) (value << (BITS_SAVED - bits));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1910,7 +1910,7 @@ static void flush_bits (void)
|
||||
uint bits,byte_buff;
|
||||
|
||||
bits=(file_buffer.bits) & ~7;
|
||||
byte_buff = file_buffer.byte >> bits;
|
||||
byte_buff = file_buffer.bytes >> bits;
|
||||
bits=BITS_SAVED - bits;
|
||||
while (bits > 0)
|
||||
{
|
||||
@ -1918,7 +1918,7 @@ static void flush_bits (void)
|
||||
*file_buffer.pos++= (byte) (uchar) (byte_buff >> bits) ;
|
||||
}
|
||||
file_buffer.bits=BITS_SAVED;
|
||||
file_buffer.byte=0;
|
||||
file_buffer.bytes=0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user