1
0
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:
unknown
2002-11-21 15:56:48 +02:00
300 changed files with 7665 additions and 2426 deletions

View File

@ -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

View File

@ -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

View 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"

View 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

View File

@ -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

View File

@ -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.
#

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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.

View File

@ -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

View File

@ -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 ---------------------------------------------------------------------------

View File

@ -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 };

View File

@ -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);
}

View File

@ -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*) &current_user,
(gptr*) &current_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;
}

View File

@ -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));

View File

@ -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));

View File

@ -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;
}

View File

@ -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
View 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";

View File

@ -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.%

View File

@ -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

View File

@ -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) */

View File

@ -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

View File

@ -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 */

View File

@ -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) */

View File

@ -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,

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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 */

View File

@ -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);

View File

@ -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();

View File

@ -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 {

View File

@ -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*)

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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. */

View File

@ -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

View File

@ -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'. */

View File

@ -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;

View File

@ -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

View File

@ -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{

View File

@ -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

View File

@ -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

View File

@ -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! */

View File

@ -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. */

View File

@ -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. */

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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(

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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. */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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. */

View File

@ -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
}
/**************************************************************

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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"

View File

@ -102,8 +102,6 @@ que_node_t */
#include "que0que.h"
#include "row0sel.h"
#include <math.h>
#define YYSTYPE que_node_t*
/* #define __STDC__ */

View File

@ -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,

View File

@ -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. */

View File

@ -353,7 +353,7 @@ cmp_data_data_slow(
data2++;
}
return(0);
return(0); /* Not reached */
}
/*****************************************************************

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -1 +0,0 @@
timestamp

View File

@ -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;

View File

@ -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));

View File

@ -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);

View File

@ -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",

View File

@ -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);
}

View File

@ -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