mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 04:53:01 +01:00
Merge work.mysql.com:/home/bk/mysql into white.box:/home/tim/my/3
This commit is contained in:
commit
9ddc25b471
68 changed files with 1217 additions and 266 deletions
187
Docs/manual.texi
187
Docs/manual.texi
|
@ -4502,6 +4502,13 @@ Minimum respective maximum possible @code{double} value.
|
|||
|
||||
@item
|
||||
@code{LIMIT} on negative numbers are treated as big positive numbers.
|
||||
@item
|
||||
If you use @code{ALTER TABLE} to first add an @code{UNIQUE} index to a
|
||||
table used in a @code{MERGE} table and then use @code{ALTER TABLE} to
|
||||
add a normal index on the @code{MERGE} table, the key order will be
|
||||
different for the tables if there was an old not-unique key in the
|
||||
table. This is because @code{ALTER TABLE} puts @code{UNIQUE} keys before
|
||||
normal keys to be able to detect duplicate keys as early as possible.
|
||||
@end itemize
|
||||
|
||||
The following are known bugs in earlier versions of MySQL:
|
||||
|
@ -11688,9 +11695,9 @@ work:
|
|||
|
||||
@example
|
||||
CC="cc -pthread"
|
||||
CFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all -arch host"
|
||||
CFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all -arch host"
|
||||
CXX="cxx -pthread"
|
||||
CXXFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all -arch host"
|
||||
CXXFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all -arch host"
|
||||
export CC CFLAGS CXX CXXFLAGS
|
||||
./configure \
|
||||
--prefix=/usr/local/mysql \
|
||||
|
@ -13163,75 +13170,89 @@ MySQL provides several functions that you can use to perform
|
|||
calculations on dates, for example, to calculate ages or extract
|
||||
parts of dates.
|
||||
|
||||
To determine how many years old each of your pets is, compute age as the
|
||||
difference between the birth date and the current date. Do this by
|
||||
converting the two dates to days, take the difference, and divide by 365 (the
|
||||
number of days in a year):
|
||||
To determine how many years old each of your pets is, compute the
|
||||
difference in the year part of the current date and the birth date, then
|
||||
subtract one if the current date occurs earlier in the calendar year than
|
||||
the birth date. The following query shows, for each pet, the birth date,
|
||||
the current date, and the age in years.
|
||||
|
||||
@example
|
||||
mysql> SELECT name, (TO_DAYS(NOW())-TO_DAYS(birth))/365 FROM pet;
|
||||
+----------+-------------------------------------+
|
||||
| name | (TO_DAYS(NOW())-TO_DAYS(birth))/365 |
|
||||
+----------+-------------------------------------+
|
||||
| Fluffy | 6.15 |
|
||||
| Claws | 5.04 |
|
||||
| Buffy | 9.88 |
|
||||
| Fang | 8.59 |
|
||||
| Bowser | 9.58 |
|
||||
| Chirpy | 0.55 |
|
||||
| Whistler | 1.30 |
|
||||
| Slim | 2.92 |
|
||||
| Puffball | 0.00 |
|
||||
+----------+-------------------------------------+
|
||||
mysql> SELECT name, birth, CURRENT_DATE,
|
||||
-> (YEAR(CURRENT_DATE)-YEAR(birth))
|
||||
-> - (RIGHT(CURRENT_DATE,5)<RIGHT(birth,5))
|
||||
-> AS age
|
||||
-> FROM pet;
|
||||
+----------+------------+--------------+------+
|
||||
| name | birth | CURRENT_DATE | age |
|
||||
+----------+------------+--------------+------+
|
||||
| Fluffy | 1993-02-04 | 2001-08-29 | 8 |
|
||||
| Claws | 1994-03-17 | 2001-08-29 | 7 |
|
||||
| Buffy | 1989-05-13 | 2001-08-29 | 12 |
|
||||
| Fang | 1990-08-27 | 2001-08-29 | 11 |
|
||||
| Bowser | 1989-08-31 | 2001-08-29 | 11 |
|
||||
| Chirpy | 1998-09-11 | 2001-08-29 | 2 |
|
||||
| Whistler | 1997-12-09 | 2001-08-29 | 3 |
|
||||
| Slim | 1996-04-29 | 2001-08-29 | 5 |
|
||||
| Puffball | 1999-03-30 | 2001-08-29 | 2 |
|
||||
+----------+------------+--------------+------+
|
||||
@end example
|
||||
|
||||
Although the query works, there are some things about it that could be
|
||||
improved. First, the result could be scanned more easily if the rows were
|
||||
presented in some order. Second, the heading for the age column isn't very
|
||||
Here, @code{YEAR()} pulls out the year part of a date and @code{RIGHT()}
|
||||
pulls off the rightmost five characters that represent the @code{MM-DD}
|
||||
(calendar year) part of the date. The part of the expression that
|
||||
compares the @code{MM-DD} values evaluates to 1 or 0, which adjusts the
|
||||
year difference down a year if @code{CURRENT_DATE} occurs earlier in
|
||||
the year than @code{birth}. The full expression is somewhat ungainly,
|
||||
so an alias (@code{age}) is used to make the output column label more
|
||||
meaningful.
|
||||
|
||||
The first problem can be handled by adding an @code{ORDER BY name} clause to
|
||||
sort the output by name. To deal with the column heading, provide a name for
|
||||
the column so that a different label appears in the output (this is called a
|
||||
column alias):
|
||||
The query works, but the result could be scanned more easily if the rows
|
||||
were presented in some order. This can be done by adding an @code{ORDER
|
||||
BY name} clause to sort the output by name:
|
||||
|
||||
@example
|
||||
mysql> SELECT name, (TO_DAYS(NOW())-TO_DAYS(birth))/365 AS age
|
||||
mysql> SELECT name, birth, CURRENT_DATE,
|
||||
-> (YEAR(CURRENT_DATE)-YEAR(birth))
|
||||
-> - (RIGHT(CURRENT_DATE,5)<RIGHT(birth,5))
|
||||
-> AS age
|
||||
-> FROM pet ORDER BY name;
|
||||
+----------+------+
|
||||
| name | age |
|
||||
+----------+------+
|
||||
| Bowser | 9.58 |
|
||||
| Buffy | 9.88 |
|
||||
| Chirpy | 0.55 |
|
||||
| Claws | 5.04 |
|
||||
| Fang | 8.59 |
|
||||
| Fluffy | 6.15 |
|
||||
| Puffball | 0.00 |
|
||||
| Slim | 2.92 |
|
||||
| Whistler | 1.30 |
|
||||
+----------+------+
|
||||
+----------+------------+--------------+------+
|
||||
| name | birth | CURRENT_DATE | age |
|
||||
+----------+------------+--------------+------+
|
||||
| Bowser | 1989-08-31 | 2001-08-29 | 11 |
|
||||
| Buffy | 1989-05-13 | 2001-08-29 | 12 |
|
||||
| Chirpy | 1998-09-11 | 2001-08-29 | 2 |
|
||||
| Claws | 1994-03-17 | 2001-08-29 | 7 |
|
||||
| Fang | 1990-08-27 | 2001-08-29 | 11 |
|
||||
| Fluffy | 1993-02-04 | 2001-08-29 | 8 |
|
||||
| Puffball | 1999-03-30 | 2001-08-29 | 2 |
|
||||
| Slim | 1996-04-29 | 2001-08-29 | 5 |
|
||||
| Whistler | 1997-12-09 | 2001-08-29 | 3 |
|
||||
+----------+------------+--------------+------+
|
||||
@end example
|
||||
|
||||
To sort the output by @code{age} rather than @code{name}, just use a
|
||||
different @code{ORDER BY} clause:
|
||||
|
||||
@example
|
||||
mysql> SELECT name, (TO_DAYS(NOW())-TO_DAYS(birth))/365 AS age
|
||||
-> FROM pet ORDER BY age;
|
||||
+----------+------+
|
||||
| name | age |
|
||||
+----------+------+
|
||||
| Puffball | 0.00 |
|
||||
| Chirpy | 0.55 |
|
||||
| Whistler | 1.30 |
|
||||
| Slim | 2.92 |
|
||||
| Claws | 5.04 |
|
||||
| Fluffy | 6.15 |
|
||||
| Fang | 8.59 |
|
||||
| Bowser | 9.58 |
|
||||
| Buffy | 9.88 |
|
||||
+----------+------+
|
||||
mysql> SELECT name, birth, CURRENT_DATE,
|
||||
-> (YEAR(CURRENT_DATE)-YEAR(birth))
|
||||
-> - (RIGHT(CURRENT_DATE,5)<RIGHT(birth,5))
|
||||
-> AS age
|
||||
-> FROM pet ORDER BY age;
|
||||
+----------+------------+--------------+------+
|
||||
| name | birth | CURRENT_DATE | age |
|
||||
+----------+------------+--------------+------+
|
||||
| Chirpy | 1998-09-11 | 2001-08-29 | 2 |
|
||||
| Puffball | 1999-03-30 | 2001-08-29 | 2 |
|
||||
| Whistler | 1997-12-09 | 2001-08-29 | 3 |
|
||||
| Slim | 1996-04-29 | 2001-08-29 | 5 |
|
||||
| Claws | 1994-03-17 | 2001-08-29 | 7 |
|
||||
| Fluffy | 1993-02-04 | 2001-08-29 | 8 |
|
||||
| Fang | 1990-08-27 | 2001-08-29 | 11 |
|
||||
| Bowser | 1989-08-31 | 2001-08-29 | 11 |
|
||||
| Buffy | 1989-05-13 | 2001-08-29 | 12 |
|
||||
+----------+------------+--------------+------+
|
||||
@end example
|
||||
|
||||
A similar query can be used to determine age at death for animals that have
|
||||
|
@ -13241,12 +13262,14 @@ values, compute the difference between the @code{death} and @code{birth}
|
|||
values:
|
||||
|
||||
@example
|
||||
mysql> SELECT name, birth, death, (TO_DAYS(death)-TO_DAYS(birth))/365 AS age
|
||||
-> FROM pet WHERE death IS NOT NULL ORDER BY age;
|
||||
mysql> SELECT name, birth, death,
|
||||
-> (YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5))
|
||||
-> AS age
|
||||
-> FROM pet WHERE death IS NOT NULL ORDER BY age;
|
||||
+--------+------------+------------+------+
|
||||
| name | birth | death | age |
|
||||
+--------+------------+------------+------+
|
||||
| Bowser | 1989-08-31 | 1995-07-29 | 5.91 |
|
||||
| Bowser | 1989-08-31 | 1995-07-29 | 5 |
|
||||
+--------+------------+------------+------+
|
||||
@end example
|
||||
|
||||
|
@ -13321,7 +13344,7 @@ mysql> SELECT name, birth FROM pet
|
|||
|
||||
Note that @code{MONTH} returns a number between 1 and 12. And
|
||||
@code{MOD(something,12)} returns a number between 0 and 11. So the
|
||||
addition has to be after the @code{MOD()} otherwise we would go from
|
||||
addition has to be after the @code{MOD()}, otherwise we would go from
|
||||
November (11) to January (1).
|
||||
|
||||
|
||||
|
@ -34149,6 +34172,12 @@ index exists, it drops the first @code{UNIQUE} index in the table.
|
|||
(MySQL marks the first @code{UNIQUE} key as the @code{PRIMARY KEY}
|
||||
if no @code{PRIMARY KEY} was specified explicitly.)
|
||||
|
||||
@findex UNIQUE
|
||||
@findex PRIMARY KEY
|
||||
If you add a @code{UNIQUE INDEX} or @code{PRIMARY KEY} to a table, this
|
||||
is stored before any not @code{UNIQUE} index so that MySQL can detect
|
||||
duplicate keys as early as possible.
|
||||
|
||||
@findex ORDER BY
|
||||
@item
|
||||
@code{ORDER BY} allows you to create the new table with the rows in a
|
||||
|
@ -35558,14 +35587,15 @@ mapped tables. (We plan to fix this in 4.0).
|
|||
|
||||
With identical tables we mean that all tables are created with identical
|
||||
column and key information. You can't put a MERGE over tables where the
|
||||
columns are packed differently or doesn't have exactly the same columns.
|
||||
Some of the tables can however be compressed with @code{myisampack}.
|
||||
@xref{myisampack}.
|
||||
columns are packed differently, doesn't have exactly the same columns or
|
||||
have the keys in different order. Some of the tables can however be
|
||||
compressed with @code{myisampack}. @xref{myisampack}.
|
||||
|
||||
When you create a @code{MERGE} table, you will get a @code{.frm} table
|
||||
definition file and a @code{.MRG} table list file. The @code{.MRG} just
|
||||
contains a list of the index files (@code{.MYI} files) that should
|
||||
be used as one.
|
||||
be used as one. All used tables must be in the same database as the
|
||||
@code{MERGE} table itself.
|
||||
|
||||
For the moment you need to have @code{SELECT}, @code{UPDATE}, and
|
||||
@code{DELETE} privileges on the tables you map to a @code{MERGE} table.
|
||||
|
@ -35691,7 +35721,6 @@ Change the @code{.MRG} file and issue a @code{FLUSH TABLE} on the
|
|||
read the new definition file.
|
||||
@end itemize
|
||||
|
||||
|
||||
@node ISAM, HEAP, MERGE, Table types
|
||||
@section ISAM Tables
|
||||
|
||||
|
@ -46683,22 +46712,38 @@ not yet 100% confident in this code.
|
|||
@appendixsubsec Changes in release 3.23.42
|
||||
@itemize @bullet
|
||||
@item
|
||||
Fixes problem when one edited @code{.MRG} tables by hand.
|
||||
(Patch from Benjamin Pflugmann).
|
||||
@item
|
||||
Enforce that all tables in a @code{MERGE} table come from the same
|
||||
database.
|
||||
@item
|
||||
Fixed bug with @code{LOAD DATA INFILE} and transactional tables.
|
||||
@item
|
||||
Fix bug when using @code{INSERT DELAYED} with wrong column definition.
|
||||
@item
|
||||
Fixed coredump during @code{REPAIR} of some particularly broken tables.
|
||||
@item
|
||||
Fixed bug in @code{InnoDB} and @code{AUTO_INCREMENT} columns.
|
||||
@item
|
||||
Fixed critical bug in @code{InnoDB} and @code{BLOB} columns. If one has
|
||||
used @code{BLOB} columns larger than 8K in an @code{InnoDB} table, one must
|
||||
dump the table with @code{mysqldump}, drop it and restore it from the dump.
|
||||
@item
|
||||
Applied large patch for OS/2 from Yuri Dario.
|
||||
@item
|
||||
Fixed problem with InnoDB when one could get the error @code{Can't
|
||||
Fixed problem with @code{InnoDB} when one could get the error @code{Can't
|
||||
execute the given command...} even when one didn't have an active
|
||||
transaction.
|
||||
@item
|
||||
Applied some fixes for Gemini.
|
||||
Applied some minor fixes that concern Gemini.
|
||||
@item
|
||||
Use real arithmetic operations even in integer context if not
|
||||
all arguments are integers. (Fixes uncommon bug in some integer
|
||||
context).
|
||||
contexts).
|
||||
@item
|
||||
Don't force everything to lower cases on windows. (To fix problem
|
||||
with windows and @code{ALTER TABLE}). Now @code{--lower_case_names}
|
||||
Don't force everything to lower cases on Windows. (To fix problem
|
||||
with Windows and @code{ALTER TABLE}). Now @code{--lower_case_names}
|
||||
also works on Unix.
|
||||
@item
|
||||
Fixed that automatic rollback that is done when thread end doesn't lock
|
||||
|
@ -46714,7 +46759,7 @@ Added option @code{--sql-mode=option[,option[,option]]}.
|
|||
@xref{Command-line options}.
|
||||
@item
|
||||
Fixed possible problem with @code{shutdown} on Solaris where the
|
||||
@code{.pid} file wasn't deleted.
|
||||
@file{.pid} file wasn't deleted.
|
||||
@item
|
||||
InnoDB now supports < 4 GB rows. The former limit was 8000 bytes.
|
||||
@item
|
||||
|
|
|
@ -40,20 +40,15 @@ mysqltest_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
|
|||
mysqlbinlog_SOURCES = mysqlbinlog.cc
|
||||
mysqlbinlog_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
|
||||
sql_src=log_event.h log_event.cc
|
||||
mysys_src=mysys_priv.h
|
||||
|
||||
# Fix for mit-threads
|
||||
DEFS = -DUNDEF_THREADS_HACK
|
||||
|
||||
link_sources:
|
||||
for f in $(sql_src) ; do \
|
||||
rm -f $$f; \
|
||||
@LN_CP_F@ ../sql/$$f $$f; \
|
||||
done; \
|
||||
for f in $(mysys_src); do \
|
||||
rm -f $$f; \
|
||||
@LN_CP_F@ ../mysys/$$f $$f; \
|
||||
done;
|
||||
rm -f $(srcdir)/$$f; \
|
||||
@LN_CP_F@ $(top_srcdir)/sql/$$f $(srcdir)/$$f; \
|
||||
done;
|
||||
|
||||
thread_test.o: thread_test.c
|
||||
$(COMPILE) -c @MT_INCLUDES@ $(INCLUDES) $<
|
||||
|
|
|
@ -1365,7 +1365,7 @@ uint _line_)
|
|||
#ifdef THREAD
|
||||
(void) fprintf (_db_fp_, "%-7s: ", my_thread_name());
|
||||
#else
|
||||
(void) fprintf (_db_fp_, "%5d: ", getpid ());
|
||||
(void) fprintf (_db_fp_, "%5d: ", (int) getpid ());
|
||||
#endif
|
||||
}
|
||||
if (stack -> flags & NUMBER_ON) {
|
||||
|
|
|
@ -29,8 +29,11 @@ extern const char *client_errors[]; /* Error messages */
|
|||
|
||||
#define CR_MIN_ERROR 2000 /* For easier client code */
|
||||
#define CR_MAX_ERROR 2999
|
||||
#undef ER
|
||||
#if defined(OS2) && defined( MYSQL_SERVER)
|
||||
#define CER(X) client_errors[(X)-CR_MIN_ERROR]
|
||||
#else
|
||||
#define ER(X) client_errors[(X)-CR_MIN_ERROR]
|
||||
#endif
|
||||
#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
|
||||
|
||||
#define CR_UNKNOWN_ERROR 2000
|
||||
|
|
|
@ -112,13 +112,13 @@ typedef struct st_heap_share
|
|||
LIST open_list;
|
||||
} HP_SHARE;
|
||||
|
||||
struct st_hash_info;
|
||||
struct st_hp_hash_info;
|
||||
|
||||
typedef struct st_heap_info
|
||||
{
|
||||
HP_SHARE *s;
|
||||
byte *current_ptr;
|
||||
struct st_hash_info *current_hash_ptr;
|
||||
struct st_hp_hash_info *current_hash_ptr;
|
||||
ulong current_record,next_block;
|
||||
int lastinx,errkey;
|
||||
int mode; /* Mode of file (READONLY..) */
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
# define bmove_allign(A,B,C) memcpy((A),(B),(C))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus) && !defined(OS2)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
@ -238,7 +238,7 @@ extern ulonglong strtoull(const char *str, char **ptr, int base);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus) && !defined(OS2)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -212,4 +212,5 @@
|
|||
#define ER_CREATE_DB_WITH_READ_LOCK 1209
|
||||
#define ER_WRONG_ARGUMENTS 1210
|
||||
#define ER_NO_PERMISSON_TO_CREATE_USER 1211
|
||||
#define ER_ERROR_MESSAGES 212
|
||||
#define ER_UNION_TABLES_IN_DIFFERENT_DIR 1212
|
||||
#define ER_ERROR_MESSAGES 213
|
||||
|
|
|
@ -1738,8 +1738,8 @@ btr_node_ptr_delete(
|
|||
|
||||
btr_cur_position(UT_LIST_GET_FIRST(tree->tree_indexes), node_ptr,
|
||||
&cursor);
|
||||
compressed = btr_cur_pessimistic_delete(&err, TRUE, &cursor, mtr);
|
||||
|
||||
compressed = btr_cur_pessimistic_delete(&err, TRUE, &cursor, FALSE,
|
||||
mtr);
|
||||
ut_a(err == DB_SUCCESS);
|
||||
|
||||
if (!compressed) {
|
||||
|
|
|
@ -80,6 +80,9 @@ btr_rec_free_updated_extern_fields(
|
|||
X-latched */
|
||||
rec_t* rec, /* in: record */
|
||||
upd_t* update, /* in: update vector */
|
||||
ibool do_not_free_inherited,/* in: TRUE if called in a
|
||||
rollback and we do not want to free
|
||||
inherited fields */
|
||||
mtr_t* mtr); /* in: mini-transaction handle which contains
|
||||
an X-latch to record page and to the tree */
|
||||
|
||||
|
@ -813,7 +816,7 @@ calculate_sizes_again:
|
|||
/* The record is so big that we have to store some fields
|
||||
externally on separate database pages */
|
||||
|
||||
big_rec_vec = dtuple_convert_big_rec(index, entry);
|
||||
big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0);
|
||||
|
||||
if (big_rec_vec == NULL) {
|
||||
|
||||
|
@ -1021,7 +1024,7 @@ btr_cur_pessimistic_insert(
|
|||
/* The record is so big that we have to store some fields
|
||||
externally on separate database pages */
|
||||
|
||||
big_rec_vec = dtuple_convert_big_rec(index, entry);
|
||||
big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0);
|
||||
|
||||
if (big_rec_vec == NULL) {
|
||||
|
||||
|
@ -1242,6 +1245,7 @@ btr_cur_update_in_place(
|
|||
rec_t* rec;
|
||||
dulint roll_ptr;
|
||||
trx_t* trx;
|
||||
ibool was_delete_marked;
|
||||
|
||||
/* Only clustered index records are updated using this function */
|
||||
ut_ad((cursor->index)->type & DICT_CLUSTERED);
|
||||
|
@ -1270,6 +1274,8 @@ btr_cur_update_in_place(
|
|||
|
||||
/* FIXME: in a mixed tree, all records may not have enough ordering
|
||||
fields for btr search: */
|
||||
|
||||
was_delete_marked = rec_get_deleted_flag(rec);
|
||||
|
||||
row_upd_rec_in_place(rec, update);
|
||||
|
||||
|
@ -1279,6 +1285,13 @@ btr_cur_update_in_place(
|
|||
|
||||
btr_cur_update_in_place_log(flags, rec, index, update, trx, roll_ptr,
|
||||
mtr);
|
||||
if (was_delete_marked && !rec_get_deleted_flag(rec)) {
|
||||
/* The new updated record owns its possible externally
|
||||
stored fields */
|
||||
|
||||
btr_cur_unmark_extern_fields(rec, mtr);
|
||||
}
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -1434,6 +1447,13 @@ btr_cur_optimistic_update(
|
|||
|
||||
ut_a(rec); /* <- We calculated above the insert would fit */
|
||||
|
||||
if (!rec_get_deleted_flag(rec)) {
|
||||
/* The new inserted record owns its possible externally
|
||||
stored fields */
|
||||
|
||||
btr_cur_unmark_extern_fields(rec, mtr);
|
||||
}
|
||||
|
||||
/* Restore the old explicit lock state on the record */
|
||||
|
||||
lock_rec_restore_from_page_infimum(rec, page);
|
||||
|
@ -1655,11 +1675,15 @@ btr_cur_pessimistic_update(
|
|||
if (flags & BTR_NO_UNDO_LOG_FLAG) {
|
||||
/* We are in a transaction rollback undoing a row
|
||||
update: we must free possible externally stored fields
|
||||
which got new values in the update */
|
||||
which got new values in the update, if they are not
|
||||
inherited values. They can be inherited if we have
|
||||
updated the primary key to another value, and then
|
||||
update it back again. */
|
||||
|
||||
ut_a(big_rec_vec == NULL);
|
||||
|
||||
btr_rec_free_updated_extern_fields(index, rec, update, mtr);
|
||||
btr_rec_free_updated_extern_fields(index, rec, update,
|
||||
TRUE, mtr);
|
||||
}
|
||||
|
||||
/* We have to set appropriate extern storage bits in the new
|
||||
|
@ -1676,8 +1700,8 @@ btr_cur_pessimistic_update(
|
|||
page_get_free_space_of_empty() / 2)
|
||||
|| (rec_get_converted_size(new_entry) >= REC_MAX_DATA_SIZE)) {
|
||||
|
||||
big_rec_vec = dtuple_convert_big_rec(index, new_entry);
|
||||
|
||||
big_rec_vec = dtuple_convert_big_rec(index, new_entry,
|
||||
ext_vect, n_ext_vect);
|
||||
if (big_rec_vec == NULL) {
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
@ -1694,6 +1718,13 @@ btr_cur_pessimistic_update(
|
|||
lock_rec_restore_from_page_infimum(rec, page);
|
||||
rec_set_field_extern_bits(rec, ext_vect, n_ext_vect, mtr);
|
||||
|
||||
if (!rec_get_deleted_flag(rec)) {
|
||||
/* The new inserted record owns its possible externally
|
||||
stored fields */
|
||||
|
||||
btr_cur_unmark_extern_fields(rec, mtr);
|
||||
}
|
||||
|
||||
btr_cur_compress_if_useful(cursor, mtr);
|
||||
|
||||
err = DB_SUCCESS;
|
||||
|
@ -1725,6 +1756,13 @@ btr_cur_pessimistic_update(
|
|||
|
||||
rec_set_field_extern_bits(rec, ext_vect, n_ext_vect, mtr);
|
||||
|
||||
if (!rec_get_deleted_flag(rec)) {
|
||||
/* The new inserted record owns its possible externally
|
||||
stored fields */
|
||||
|
||||
btr_cur_unmark_extern_fields(rec, mtr);
|
||||
}
|
||||
|
||||
lock_rec_restore_from_page_infimum(rec, page);
|
||||
|
||||
/* If necessary, restore also the correct lock state for a new,
|
||||
|
@ -2183,6 +2221,7 @@ btr_cur_pessimistic_delete(
|
|||
if compression does not occur, the cursor
|
||||
stays valid: it points to successor of
|
||||
deleted record on function exit */
|
||||
ibool in_rollback,/* in: TRUE if called in rollback */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
page_t* page;
|
||||
|
@ -2218,7 +2257,8 @@ btr_cur_pessimistic_delete(
|
|||
}
|
||||
|
||||
btr_rec_free_externally_stored_fields(cursor->index,
|
||||
btr_cur_get_rec(cursor), mtr);
|
||||
btr_cur_get_rec(cursor), in_rollback, mtr);
|
||||
|
||||
if ((page_get_n_recs(page) < 2)
|
||||
&& (dict_tree_get_page(btr_cur_get_tree(cursor))
|
||||
!= buf_frame_get_page_no(page))) {
|
||||
|
@ -2516,6 +2556,199 @@ btr_estimate_number_of_different_key_vals(
|
|||
|
||||
/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/
|
||||
|
||||
/***********************************************************************
|
||||
Sets the ownership bit of an externally stored field in a record. */
|
||||
static
|
||||
void
|
||||
btr_cur_set_ownership_of_extern_field(
|
||||
/*==================================*/
|
||||
rec_t* rec, /* in: clustered index record */
|
||||
ulint i, /* in: field number */
|
||||
ibool val, /* in: value to set */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
byte* data;
|
||||
ulint local_len;
|
||||
ulint byte_val;
|
||||
|
||||
data = rec_get_nth_field(rec, i, &local_len);
|
||||
|
||||
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||
|
||||
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
|
||||
|
||||
byte_val = mach_read_from_1(data + local_len + BTR_EXTERN_LEN);
|
||||
|
||||
if (val) {
|
||||
byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG);
|
||||
} else {
|
||||
byte_val = byte_val | BTR_EXTERN_OWNER_FLAG;
|
||||
}
|
||||
|
||||
mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, byte_val,
|
||||
MLOG_1BYTE, mtr);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Marks not updated extern fields as not-owned by this record. The ownership
|
||||
is transferred to the updated record which is inserted elsewhere in the
|
||||
index tree. In purge only the owner of externally stored field is allowed
|
||||
to free the field. */
|
||||
|
||||
void
|
||||
btr_cur_mark_extern_inherited_fields(
|
||||
/*=================================*/
|
||||
rec_t* rec, /* in: record in a clustered index */
|
||||
upd_t* update, /* in: update vector */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
ibool is_updated;
|
||||
ulint n;
|
||||
ulint j;
|
||||
ulint i;
|
||||
|
||||
n = rec_get_n_fields(rec);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (rec_get_nth_field_extern_bit(rec, i)) {
|
||||
|
||||
/* Check it is not in updated fields */
|
||||
is_updated = FALSE;
|
||||
|
||||
if (update) {
|
||||
for (j = 0; j < upd_get_n_fields(update);
|
||||
j++) {
|
||||
if (upd_get_nth_field(update, j)
|
||||
->field_no == i) {
|
||||
is_updated = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_updated) {
|
||||
btr_cur_set_ownership_of_extern_field(rec, i,
|
||||
FALSE, mtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
The complement of the previous function: in an update entry may inherit
|
||||
some externally stored fields from a record. We must mark them as inherited
|
||||
in entry, so that they are not freed in a rollback. */
|
||||
|
||||
void
|
||||
btr_cur_mark_dtuple_inherited_extern(
|
||||
/*=================================*/
|
||||
dtuple_t* entry, /* in: updated entry to be inserted to
|
||||
clustered index */
|
||||
ulint* ext_vec, /* in: array of extern fields in the
|
||||
original record */
|
||||
ulint n_ext_vec, /* in: number of elements in ext_vec */
|
||||
upd_t* update) /* in: update vector */
|
||||
{
|
||||
dfield_t* dfield;
|
||||
ulint byte_val;
|
||||
byte* data;
|
||||
ulint len;
|
||||
ibool is_updated;
|
||||
ulint j;
|
||||
ulint i;
|
||||
|
||||
if (ext_vec == NULL) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_ext_vec; i++) {
|
||||
|
||||
/* Check ext_vec[i] is in updated fields */
|
||||
is_updated = FALSE;
|
||||
|
||||
for (j = 0; j < upd_get_n_fields(update); j++) {
|
||||
if (upd_get_nth_field(update, j)->field_no
|
||||
== ext_vec[i]) {
|
||||
is_updated = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_updated) {
|
||||
dfield = dtuple_get_nth_field(entry, ext_vec[i]);
|
||||
|
||||
data = dfield_get_data(dfield);
|
||||
len = dfield_get_len(dfield);
|
||||
|
||||
len -= BTR_EXTERN_FIELD_REF_SIZE;
|
||||
|
||||
byte_val = mach_read_from_1(data + len
|
||||
+ BTR_EXTERN_LEN);
|
||||
|
||||
byte_val = byte_val | BTR_EXTERN_INHERITED_FLAG;
|
||||
|
||||
mach_write_to_1(data + len + BTR_EXTERN_LEN, byte_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Marks all extern fields in a record as owned by the record. This function
|
||||
should be called if the delete mark of a record is removed: a not delete
|
||||
marked record always owns all its extern fields. */
|
||||
|
||||
void
|
||||
btr_cur_unmark_extern_fields(
|
||||
/*=========================*/
|
||||
rec_t* rec, /* in: record in a clustered index */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
ulint n;
|
||||
ulint i;
|
||||
|
||||
n = rec_get_n_fields(rec);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (rec_get_nth_field_extern_bit(rec, i)) {
|
||||
|
||||
btr_cur_set_ownership_of_extern_field(rec, i,
|
||||
TRUE, mtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Marks all extern fields in a dtuple as owned by the record. */
|
||||
|
||||
void
|
||||
btr_cur_unmark_dtuple_extern_fields(
|
||||
/*================================*/
|
||||
dtuple_t* entry, /* in: clustered index entry */
|
||||
ulint* ext_vec, /* in: array of numbers of fields
|
||||
which have been stored externally */
|
||||
ulint n_ext_vec) /* in: number of elements in ext_vec */
|
||||
{
|
||||
dfield_t* dfield;
|
||||
ulint byte_val;
|
||||
byte* data;
|
||||
ulint len;
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < n_ext_vec; i++) {
|
||||
dfield = dtuple_get_nth_field(entry, ext_vec[i]);
|
||||
|
||||
data = dfield_get_data(dfield);
|
||||
len = dfield_get_len(dfield);
|
||||
|
||||
len -= BTR_EXTERN_FIELD_REF_SIZE;
|
||||
|
||||
byte_val = mach_read_from_1(data + len + BTR_EXTERN_LEN);
|
||||
|
||||
byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG);
|
||||
|
||||
mach_write_to_1(data + len + BTR_EXTERN_LEN, byte_val);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Stores the positions of the fields marked as extern storage in the update
|
||||
vector, and also those fields who are marked as extern storage in rec
|
||||
|
@ -2766,7 +2999,9 @@ btr_store_big_rec_extern_fields(
|
|||
|
||||
/***********************************************************************
|
||||
Frees the space in an externally stored field to the file space
|
||||
management. */
|
||||
management if the field in data is owned the externally stored field,
|
||||
in a rollback we may have the additional condition that the field must
|
||||
not be inherited. */
|
||||
|
||||
void
|
||||
btr_free_externally_stored_field(
|
||||
|
@ -2777,6 +3012,9 @@ btr_free_externally_stored_field(
|
|||
+ reference to the externally
|
||||
stored part */
|
||||
ulint local_len, /* in: length of data */
|
||||
ibool do_not_free_inherited,/* in: TRUE if called in a
|
||||
rollback and we do not want to free
|
||||
inherited fields */
|
||||
mtr_t* local_mtr) /* in: mtr containing the latch to
|
||||
data an an X-latch to the index
|
||||
tree */
|
||||
|
@ -2828,6 +3066,26 @@ btr_free_externally_stored_field(
|
|||
return;
|
||||
}
|
||||
|
||||
if (mach_read_from_1(data + local_len + BTR_EXTERN_LEN)
|
||||
& BTR_EXTERN_OWNER_FLAG) {
|
||||
/* This field does not own the externally
|
||||
stored field: do not free! */
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (do_not_free_inherited
|
||||
&& mach_read_from_1(data + local_len + BTR_EXTERN_LEN)
|
||||
& BTR_EXTERN_INHERITED_FLAG) {
|
||||
/* Rollback and inherited field: do not free! */
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
page = buf_page_get(space_id, page_no, RW_X_LATCH, &mtr);
|
||||
|
||||
buf_page_dbg_add_level(page, SYNC_EXTERN_STORAGE);
|
||||
|
@ -2872,6 +3130,9 @@ btr_rec_free_externally_stored_fields(
|
|||
dict_index_t* index, /* in: index of the data, the index
|
||||
tree MUST be X-latched */
|
||||
rec_t* rec, /* in: record */
|
||||
ibool do_not_free_inherited,/* in: TRUE if called in a
|
||||
rollback and we do not want to free
|
||||
inherited fields */
|
||||
mtr_t* mtr) /* in: mini-transaction handle which contains
|
||||
an X-latch to record page and to the index
|
||||
tree */
|
||||
|
@ -2896,7 +3157,8 @@ btr_rec_free_externally_stored_fields(
|
|||
if (rec_get_nth_field_extern_bit(rec, i)) {
|
||||
|
||||
data = rec_get_nth_field(rec, i, &len);
|
||||
btr_free_externally_stored_field(index, data, len, mtr);
|
||||
btr_free_externally_stored_field(index, data, len,
|
||||
do_not_free_inherited, mtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2912,6 +3174,9 @@ btr_rec_free_updated_extern_fields(
|
|||
X-latched */
|
||||
rec_t* rec, /* in: record */
|
||||
upd_t* update, /* in: update vector */
|
||||
ibool do_not_free_inherited,/* in: TRUE if called in a
|
||||
rollback and we do not want to free
|
||||
inherited fields */
|
||||
mtr_t* mtr) /* in: mini-transaction handle which contains
|
||||
an X-latch to record page and to the tree */
|
||||
{
|
||||
|
@ -2938,7 +3203,8 @@ btr_rec_free_updated_extern_fields(
|
|||
if (rec_get_nth_field_extern_bit(rec, ufield->field_no)) {
|
||||
|
||||
data = rec_get_nth_field(rec, ufield->field_no, &len);
|
||||
btr_free_externally_stored_field(index, data, len, mtr);
|
||||
btr_free_externally_stored_field(index, data, len,
|
||||
do_not_free_inherited, mtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -769,6 +769,11 @@ btr_search_guess_on_hash(
|
|||
buf_page_make_young(page);
|
||||
}
|
||||
|
||||
/* Increment the page get statistics though we did not really
|
||||
fix the page: for user info only */
|
||||
|
||||
buf_pool->n_page_gets++;
|
||||
|
||||
return(TRUE);
|
||||
|
||||
/*-------------------------------------------*/
|
||||
|
|
|
@ -349,6 +349,10 @@ buf_pool_create(
|
|||
buf_pool->n_pages_written = 0;
|
||||
buf_pool->n_pages_created = 0;
|
||||
|
||||
buf_pool->n_page_gets = 0;
|
||||
buf_pool->n_page_gets_old = 0;
|
||||
buf_pool->n_pages_read_old = 0;
|
||||
|
||||
/* 2. Initialize flushing fields
|
||||
---------------------------- */
|
||||
UT_LIST_INIT(buf_pool->flush_list);
|
||||
|
@ -667,6 +671,7 @@ buf_page_get_gen(
|
|||
#ifndef UNIV_LOG_DEBUG
|
||||
ut_ad(!ibuf_inside() || ibuf_page(space, offset));
|
||||
#endif
|
||||
buf_pool->n_page_gets++;
|
||||
loop:
|
||||
mutex_enter_fast(&(buf_pool->mutex));
|
||||
|
||||
|
@ -846,6 +851,8 @@ buf_page_optimistic_get_func(
|
|||
ut_ad(mtr && guess);
|
||||
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
|
||||
|
||||
buf_pool->n_page_gets++;
|
||||
|
||||
block = buf_block_align(guess);
|
||||
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
@ -976,6 +983,8 @@ buf_page_get_known_nowait(
|
|||
ut_ad(mtr);
|
||||
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
|
||||
|
||||
buf_pool->n_page_gets++;
|
||||
|
||||
block = buf_block_align(guess);
|
||||
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
@ -1643,6 +1652,18 @@ buf_print_io(void)
|
|||
printf("Pages read %lu, created %lu, written %lu\n",
|
||||
buf_pool->n_pages_read, buf_pool->n_pages_created,
|
||||
buf_pool->n_pages_written);
|
||||
|
||||
if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) {
|
||||
printf("Buffer pool hit rate %lu / 1000\n",
|
||||
1000
|
||||
- ((1000 *
|
||||
(buf_pool->n_pages_read - buf_pool->n_pages_read_old))
|
||||
/ (buf_pool->n_page_gets - buf_pool->n_page_gets_old)));
|
||||
}
|
||||
|
||||
buf_pool->n_page_gets_old = buf_pool->n_page_gets;
|
||||
buf_pool->n_pages_read_old = buf_pool->n_pages_read;
|
||||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ Created 11/11/1995 Heikki Tuuri
|
|||
flushed along with the original page. */
|
||||
|
||||
#define BUF_FLUSH_AREA ut_min(BUF_READ_AHEAD_AREA,\
|
||||
buf_pool->curr_size / 16)
|
||||
buf_pool->curr_size / 16)
|
||||
|
||||
/**********************************************************************
|
||||
Validates the flush list. */
|
||||
|
|
|
@ -395,7 +395,12 @@ dtuple_convert_big_rec(
|
|||
the entry enough, i.e., if there are
|
||||
too many short fields in entry */
|
||||
dict_index_t* index, /* in: index */
|
||||
dtuple_t* entry) /* in: index entry */
|
||||
dtuple_t* entry, /* in: index entry */
|
||||
ulint* ext_vec,/* in: array of externally stored fields,
|
||||
or NULL: if a field already is externally
|
||||
stored, then we cannot move it to the vector
|
||||
this function returns */
|
||||
ulint n_ext_vec)/* in: number of elements is ext_vec */
|
||||
{
|
||||
mem_heap_t* heap;
|
||||
big_rec_t* vector;
|
||||
|
@ -404,7 +409,9 @@ dtuple_convert_big_rec(
|
|||
ulint n_fields;
|
||||
ulint longest;
|
||||
ulint longest_i;
|
||||
ibool is_externally_stored;
|
||||
ulint i;
|
||||
ulint j;
|
||||
|
||||
size = rec_get_converted_size(entry);
|
||||
|
||||
|
@ -431,9 +438,23 @@ dtuple_convert_big_rec(
|
|||
for (i = dict_index_get_n_unique_in_tree(index);
|
||||
i < dtuple_get_n_fields(entry); i++) {
|
||||
|
||||
/* Skip over fields which already are externally
|
||||
stored */
|
||||
|
||||
is_externally_stored = FALSE;
|
||||
|
||||
if (ext_vec) {
|
||||
for (j = 0; j < n_ext_vec; j++) {
|
||||
if (ext_vec[j] == i) {
|
||||
is_externally_stored = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip over fields which are ordering in some index */
|
||||
|
||||
if (dict_field_get_col(
|
||||
if (!is_externally_stored &&
|
||||
dict_field_get_col(
|
||||
dict_index_get_nth_field(index, i))
|
||||
->ord_part == 0) {
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ Created 10/25/1995 Heikki Tuuri
|
|||
#include "log0log.h"
|
||||
#include "log0recv.h"
|
||||
#include "fsp0fsp.h"
|
||||
#include "srv0srv.h"
|
||||
|
||||
/*
|
||||
IMPLEMENTATION OF THE LOW-LEVEL FILE SYSTEM
|
||||
|
@ -1152,6 +1153,7 @@ fil_aio_wait(
|
|||
ut_ad(fil_validate());
|
||||
|
||||
if (os_aio_use_native_aio) {
|
||||
srv_io_thread_op_info[segment] = "native aio handle";
|
||||
#ifdef WIN_ASYNC_IO
|
||||
ret = os_aio_windows_handle(segment, 0, &fil_node, &message,
|
||||
&type);
|
||||
|
@ -1161,12 +1163,16 @@ fil_aio_wait(
|
|||
ut_a(0);
|
||||
#endif
|
||||
} else {
|
||||
srv_io_thread_op_info[segment] = "simulated aio handle";
|
||||
|
||||
ret = os_aio_simulated_handle(segment, (void**) &fil_node,
|
||||
&message, &type);
|
||||
}
|
||||
|
||||
ut_a(ret);
|
||||
|
||||
|
||||
srv_io_thread_op_info[segment] = "complete io for fil node";
|
||||
|
||||
mutex_enter(&(system->mutex));
|
||||
|
||||
fil_node_complete_io(fil_node, fil_system, type);
|
||||
|
@ -1178,9 +1184,10 @@ fil_aio_wait(
|
|||
/* Do the i/o handling */
|
||||
|
||||
if (buf_pool_is_block(message)) {
|
||||
|
||||
srv_io_thread_op_info[segment] = "complete io for buf page";
|
||||
buf_page_io_complete(message);
|
||||
} else {
|
||||
srv_io_thread_op_info[segment] = "complete io for log";
|
||||
log_io_complete(message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2341,7 +2341,7 @@ ibuf_delete_rec(
|
|||
root = ibuf_tree_root_get(ibuf_data, space, mtr);
|
||||
|
||||
btr_cur_pessimistic_delete(&err, TRUE, btr_pcur_get_btr_cur(pcur),
|
||||
mtr);
|
||||
FALSE, mtr);
|
||||
ut_a(err == DB_SUCCESS);
|
||||
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
|
|
|
@ -353,6 +353,7 @@ btr_cur_pessimistic_delete(
|
|||
if compression does not occur, the cursor
|
||||
stays valid: it points to successor of
|
||||
deleted record on function exit */
|
||||
ibool in_rollback,/* in: TRUE if called in rollback */
|
||||
mtr_t* mtr); /* in: mtr */
|
||||
/***************************************************************
|
||||
Parses a redo log record of updating a record in-place. */
|
||||
|
@ -418,6 +419,52 @@ btr_estimate_number_of_different_key_vals(
|
|||
/* out: estimated number of key values */
|
||||
dict_index_t* index); /* in: index */
|
||||
/***********************************************************************
|
||||
Marks not updated extern fields as not-owned by this record. The ownership
|
||||
is transferred to the updated record which is inserted elsewhere in the
|
||||
index tree. In purge only the owner of externally stored field is allowed
|
||||
to free the field. */
|
||||
|
||||
void
|
||||
btr_cur_mark_extern_inherited_fields(
|
||||
/*=================================*/
|
||||
rec_t* rec, /* in: record in a clustered index */
|
||||
upd_t* update, /* in: update vector */
|
||||
mtr_t* mtr); /* in: mtr */
|
||||
/***********************************************************************
|
||||
The complement of the previous function: in an update entry may inherit
|
||||
some externally stored fields from a record. We must mark them as inherited
|
||||
in entry, so that they are not freed in a rollback. */
|
||||
|
||||
void
|
||||
btr_cur_mark_dtuple_inherited_extern(
|
||||
/*=================================*/
|
||||
dtuple_t* entry, /* in: updated entry to be inserted to
|
||||
clustered index */
|
||||
ulint* ext_vec, /* in: array of extern fields in the
|
||||
original record */
|
||||
ulint n_ext_vec, /* in: number of elements in ext_vec */
|
||||
upd_t* update); /* in: update vector */
|
||||
/***********************************************************************
|
||||
Marks all extern fields in a record as owned by the record. This function
|
||||
should be called if the delete mark of a record is removed: a not delete
|
||||
marked record always owns all its extern fields. */
|
||||
|
||||
void
|
||||
btr_cur_unmark_extern_fields(
|
||||
/*=========================*/
|
||||
rec_t* rec, /* in: record in a clustered index */
|
||||
mtr_t* mtr); /* in: mtr */
|
||||
/***********************************************************************
|
||||
Marks all extern fields in a dtuple as owned by the record. */
|
||||
|
||||
void
|
||||
btr_cur_unmark_dtuple_extern_fields(
|
||||
/*================================*/
|
||||
dtuple_t* entry, /* in: clustered index entry */
|
||||
ulint* ext_vec, /* in: array of numbers of fields
|
||||
which have been stored externally */
|
||||
ulint n_ext_vec); /* in: number of elements in ext_vec */
|
||||
/***********************************************************************
|
||||
Stores the fields in big_rec_vec to the tablespace and puts pointers to
|
||||
them in rec. The fields are stored on pages allocated from leaf node
|
||||
file segment of the index tree. */
|
||||
|
@ -435,7 +482,9 @@ btr_store_big_rec_extern_fields(
|
|||
rec and to the tree */
|
||||
/***********************************************************************
|
||||
Frees the space in an externally stored field to the file space
|
||||
management. */
|
||||
management if the field in data is owned the externally stored field,
|
||||
in a rollback we may have the additional condition that the field must
|
||||
not be inherited. */
|
||||
|
||||
void
|
||||
btr_free_externally_stored_field(
|
||||
|
@ -446,6 +495,9 @@ btr_free_externally_stored_field(
|
|||
+ reference to the externally
|
||||
stored part */
|
||||
ulint local_len, /* in: length of data */
|
||||
ibool do_not_free_inherited,/* in: TRUE if called in a
|
||||
rollback and we do not want to free
|
||||
inherited fields */
|
||||
mtr_t* local_mtr); /* in: mtr containing the latch to
|
||||
data an an X-latch to the index
|
||||
tree */
|
||||
|
@ -458,6 +510,9 @@ btr_rec_free_externally_stored_fields(
|
|||
dict_index_t* index, /* in: index of the data, the index
|
||||
tree MUST be X-latched */
|
||||
rec_t* rec, /* in: record */
|
||||
ibool do_not_free_inherited,/* in: TRUE if called in a
|
||||
rollback and we do not want to free
|
||||
inherited fields */
|
||||
mtr_t* mtr); /* in: mini-transaction handle which contains
|
||||
an X-latch to record page and to the index
|
||||
tree */
|
||||
|
@ -620,10 +675,21 @@ and sleep this many microseconds in between */
|
|||
on that page */
|
||||
#define BTR_EXTERN_LEN 12 /* 8 bytes containing the
|
||||
length of the externally
|
||||
stored part of the BLOB */
|
||||
stored part of the BLOB.
|
||||
The 2 highest bits are
|
||||
reserved to the flags below. */
|
||||
/*--------------------------------------*/
|
||||
#define BTR_EXTERN_FIELD_REF_SIZE 20
|
||||
|
||||
/* The highest bit of BTR_EXTERN_LEN (i.e., the highest bit of the byte
|
||||
at lowest address) is set to 1 if this field does not 'own' the externally
|
||||
stored field; only the owner field is allowed to free the field in purge!
|
||||
If the 2nd highest bit is 1 then it means that the externally stored field
|
||||
was inherited from an earlier version of the row. In rollback we are not
|
||||
allowed to free an inherited external field. */
|
||||
|
||||
#define BTR_EXTERN_OWNER_FLAG 128
|
||||
#define BTR_EXTERN_INHERITED_FLAG 64
|
||||
|
||||
extern ulint btr_cur_n_non_sea;
|
||||
|
||||
|
|
|
@ -771,6 +771,17 @@ struct buf_pool_struct{
|
|||
ulint n_pages_written;/* number write operations */
|
||||
ulint n_pages_created;/* number of pages created in the pool
|
||||
with no read */
|
||||
ulint n_page_gets; /* number of page gets performed;
|
||||
also successful seraches through
|
||||
the adaptive hash index are
|
||||
counted as page gets; this field
|
||||
is NOT protected by the buffer
|
||||
pool mutex */
|
||||
ulint n_page_gets_old;/* n_page_gets when buf_print was
|
||||
last time called: used to calculate
|
||||
hit rate */
|
||||
ulint n_pages_read_old;/* n_pages_read when buf_print was
|
||||
last time called */
|
||||
/* 2. Page flushing algorithm fields */
|
||||
|
||||
UT_LIST_BASE_NODE_T(buf_block_t) flush_list;
|
||||
|
|
|
@ -329,7 +329,12 @@ dtuple_convert_big_rec(
|
|||
the entry enough, i.e., if there are
|
||||
too many short fields in entry */
|
||||
dict_index_t* index, /* in: index */
|
||||
dtuple_t* entry); /* in: index entry */
|
||||
dtuple_t* entry, /* in: index entry */
|
||||
ulint* ext_vec,/* in: array of externally stored fields,
|
||||
or NULL: if a field already is externally
|
||||
stored, then we cannot move it to the vector
|
||||
this function returns */
|
||||
ulint n_ext_vec);/* in: number of elements is ext_vec */
|
||||
/******************************************************************
|
||||
Puts back to entry the data stored in vector. Note that to ensure the
|
||||
fields in entry can accommodate the data, vector must have been created
|
||||
|
|
|
@ -62,7 +62,15 @@ extern int srv_query_thread_priority;
|
|||
|
||||
/*-------------------------------------------*/
|
||||
|
||||
extern ulint srv_n_rows_inserted;
|
||||
extern ulint srv_n_rows_updated;
|
||||
extern ulint srv_n_rows_deleted;
|
||||
extern ulint srv_n_rows_read;
|
||||
|
||||
extern ibool srv_print_innodb_monitor;
|
||||
extern ibool srv_print_innodb_lock_monitor;
|
||||
extern ibool srv_print_innodb_tablespace_monitor;
|
||||
|
||||
extern ulint srv_n_spin_wait_rounds;
|
||||
extern ulint srv_spin_wait_delay;
|
||||
extern ibool srv_priority_boost;
|
||||
|
@ -105,13 +113,19 @@ extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
|
|||
it from dynamic memory to get it to the
|
||||
same DRAM page as other hotspot semaphores */
|
||||
#define kernel_mutex (*kernel_mutex_temp)
|
||||
|
||||
#define SRV_MAX_N_IO_THREADS 100
|
||||
|
||||
/* Array of English strings describing the current state of an
|
||||
i/o handler thread */
|
||||
extern char* srv_io_thread_op_info[];
|
||||
|
||||
typedef struct srv_sys_struct srv_sys_t;
|
||||
|
||||
/* The server system */
|
||||
extern srv_sys_t* srv_sys;
|
||||
|
||||
/* Alternatives for fiel flush option in Unix; see the InnoDB manual about
|
||||
/* Alternatives for the field flush option in Unix; see the InnoDB manual about
|
||||
what these mean */
|
||||
#define SRV_UNIX_FDATASYNC 1
|
||||
#define SRV_UNIX_O_DSYNC 2
|
||||
|
|
|
@ -315,6 +315,9 @@ struct trx_sys_struct{
|
|||
/* List of active and committed in
|
||||
memory transactions, sorted on trx id,
|
||||
biggest first */
|
||||
UT_LIST_BASE_NODE_T(trx_t) mysql_trx_list;
|
||||
/* List of transactions created
|
||||
for MySQL */
|
||||
UT_LIST_BASE_NODE_T(trx_rseg_t) rseg_list;
|
||||
/* List of rollback segment objects */
|
||||
trx_rseg_t* latest_rseg; /* Latest rollback segment in the
|
||||
|
|
|
@ -130,6 +130,14 @@ void
|
|||
trx_mark_sql_stat_end(
|
||||
/*==================*/
|
||||
trx_t* trx); /* in: trx handle */
|
||||
/**************************************************************************
|
||||
Marks the latest SQL statement ended but does not start a new transaction
|
||||
if the trx is not started. */
|
||||
|
||||
void
|
||||
trx_mark_sql_stat_end_do_not_start_new(
|
||||
/*===================================*/
|
||||
trx_t* trx); /* in: trx handle */
|
||||
/************************************************************************
|
||||
Assigns a read view for a consistent read query. All the consistent reads
|
||||
within the same transaction will get the same read view, which is created
|
||||
|
@ -236,6 +244,14 @@ trx_commit_step(
|
|||
/*============*/
|
||||
/* out: query thread to run next, or NULL */
|
||||
que_thr_t* thr); /* in: query thread */
|
||||
/**************************************************************************
|
||||
Prints info about a transaction to the standard output. The caller must
|
||||
own the kernel mutex. */
|
||||
|
||||
void
|
||||
trx_print(
|
||||
/*======*/
|
||||
trx_t* trx); /* in: transaction */
|
||||
|
||||
|
||||
/* Signal to a transaction */
|
||||
|
@ -270,6 +286,9 @@ rolling back after a database recovery */
|
|||
struct trx_struct{
|
||||
/* All the next fields are protected by the kernel mutex, except the
|
||||
undo logs which are protected by undo_mutex */
|
||||
char* op_info; /* English text describing the
|
||||
current operation, or an empty
|
||||
string */
|
||||
ulint type; /* TRX_USER, TRX_PURGE */
|
||||
ulint conc_state; /* state of the trx from the point
|
||||
of view of concurrency control:
|
||||
|
@ -284,6 +303,8 @@ struct trx_struct{
|
|||
table */
|
||||
dulint table_id; /* table id if the preceding field is
|
||||
TRUE */
|
||||
void* mysql_thd; /* MySQL thread handle corresponding
|
||||
to this trx, or NULL */
|
||||
os_thread_id_t mysql_thread_id;/* id of the MySQL thread associated
|
||||
with this transaction object */
|
||||
ulint n_mysql_tables_in_use; /* number of Innobase tables
|
||||
|
@ -302,6 +323,9 @@ struct trx_struct{
|
|||
of a duplicate key error */
|
||||
UT_LIST_NODE_T(trx_t)
|
||||
trx_list; /* list of transactions */
|
||||
UT_LIST_NODE_T(trx_t)
|
||||
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
|
||||
|
|
|
@ -13,6 +13,7 @@ Created 5/7/1996 Heikki Tuuri
|
|||
#endif
|
||||
|
||||
#include "usr0sess.h"
|
||||
#include "trx0purge.h"
|
||||
|
||||
/* When releasing transaction locks, this specifies how often we release
|
||||
the kernel mutex for a moment to give also others access to it */
|
||||
|
@ -3184,7 +3185,7 @@ lock_table_print(
|
|||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_a(lock_get_type(lock) == LOCK_TABLE);
|
||||
|
||||
printf("\nTABLE LOCK table %s trx id %lu %lu",
|
||||
printf("TABLE LOCK table %s trx id %lu %lu",
|
||||
lock->un_member.tab_lock.table->name,
|
||||
(lock->trx)->id.high, (lock->trx)->id.low);
|
||||
|
||||
|
@ -3220,6 +3221,8 @@ lock_rec_print(
|
|||
ulint page_no;
|
||||
ulint i;
|
||||
ulint count = 0;
|
||||
ulint len;
|
||||
char buf[200];
|
||||
mtr_t mtr;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
@ -3228,7 +3231,7 @@ lock_rec_print(
|
|||
space = lock->un_member.rec_lock.space;
|
||||
page_no = lock->un_member.rec_lock.page_no;
|
||||
|
||||
printf("\nRECORD LOCKS space id %lu page no %lu n bits %lu",
|
||||
printf("RECORD LOCKS space id %lu page no %lu n bits %lu",
|
||||
space, page_no, lock_rec_get_n_bits(lock));
|
||||
|
||||
printf(" table %s index %s trx id %lu %lu",
|
||||
|
@ -3251,10 +3254,10 @@ lock_rec_print(
|
|||
printf(" waiting");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
printf("\n");
|
||||
|
||||
/* If the page is not in the buffer pool, we cannot load it
|
||||
because we have the kernel mutex and ibuf operations would
|
||||
break the latching order */
|
||||
|
@ -3280,12 +3283,14 @@ lock_rec_print(
|
|||
printf("Record lock, heap no %lu ", i);
|
||||
|
||||
if (page) {
|
||||
rec_print(page_find_rec_with_heap_no(page, i));
|
||||
len = rec_sprintf(buf, 190,
|
||||
page_find_rec_with_heap_no(page, i));
|
||||
buf[len] = '\0';
|
||||
printf("%s", buf);
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
printf("\n");
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count >= 3) {
|
||||
|
@ -3342,12 +3347,32 @@ lock_print_info(void)
|
|||
ulint nth_lock = 0;
|
||||
ulint i;
|
||||
mtr_t mtr;
|
||||
|
||||
lock_mutex_enter_kernel();
|
||||
|
||||
printf("LOCK INFO:\n");
|
||||
printf("Number of locks in the record hash table %lu\n",
|
||||
printf(
|
||||
"Purge done for all trx's with n:o < %lu %lu, undo n:o < %lu %lu\n",
|
||||
ut_dulint_get_high(purge_sys->purge_trx_no),
|
||||
ut_dulint_get_low(purge_sys->purge_trx_no),
|
||||
ut_dulint_get_high(purge_sys->purge_undo_no),
|
||||
ut_dulint_get_low(purge_sys->purge_undo_no));
|
||||
|
||||
lock_mutex_enter_kernel();
|
||||
|
||||
printf("Total number of lock structs in row lock hash table %lu\n",
|
||||
lock_get_n_rec_locks());
|
||||
|
||||
/* First print info on non-active transactions */
|
||||
|
||||
trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
|
||||
|
||||
while (trx) {
|
||||
if (trx->conc_state == TRX_NOT_STARTED) {
|
||||
printf("---");
|
||||
trx_print(trx);
|
||||
}
|
||||
|
||||
trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
|
||||
}
|
||||
|
||||
loop:
|
||||
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
||||
|
||||
|
@ -3367,11 +3392,21 @@ loop:
|
|||
}
|
||||
|
||||
if (nth_lock == 0) {
|
||||
printf("\nLOCKS FOR TRANSACTION ID %lu %lu\n", trx->id.high,
|
||||
trx->id.low);
|
||||
printf("---");
|
||||
trx_print(trx);
|
||||
|
||||
if (trx->read_view) {
|
||||
printf(
|
||||
"Trx read view will not see trx with id >= %lu %lu, sees < %lu %lu\n",
|
||||
ut_dulint_get_high(trx->read_view->low_limit_id),
|
||||
ut_dulint_get_low(trx->read_view->low_limit_id),
|
||||
ut_dulint_get_high(trx->read_view->up_limit_id),
|
||||
ut_dulint_get_low(trx->read_view->up_limit_id));
|
||||
}
|
||||
|
||||
if (trx->que_state == TRX_QUE_LOCK_WAIT) {
|
||||
printf(
|
||||
"################# TRX IS WAITING FOR THE LOCK: ###\n");
|
||||
"------------------TRX IS WAITING FOR THE LOCK:\n");
|
||||
|
||||
if (lock_get_type(trx->wait_lock) == LOCK_REC) {
|
||||
lock_rec_print(trx->wait_lock);
|
||||
|
@ -3380,10 +3415,15 @@ loop:
|
|||
}
|
||||
|
||||
printf(
|
||||
"##################################################\n");
|
||||
"------------------\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!srv_print_innodb_lock_monitor) {
|
||||
nth_trx++;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
lock = UT_LIST_GET_FIRST(trx->trx_locks);
|
||||
|
@ -3431,9 +3471,9 @@ loop:
|
|||
|
||||
nth_lock++;
|
||||
|
||||
if (nth_lock >= 25) {
|
||||
if (nth_lock >= 10) {
|
||||
printf(
|
||||
"25 LOCKS PRINTED FOR THIS TRX: SUPPRESSING FURTHER PRINTS\n");
|
||||
"10 LOCKS PRINTED FOR THIS TRX: SUPPRESSING FURTHER PRINTS\n");
|
||||
|
||||
nth_trx++;
|
||||
nth_lock = 0;
|
||||
|
|
|
@ -1577,6 +1577,7 @@ os_aio_windows_handle(
|
|||
void** message2,
|
||||
ulint* type) /* out: OS_FILE_WRITE or ..._READ */
|
||||
{
|
||||
ulint orig_seg = segment;
|
||||
os_aio_array_t* array;
|
||||
os_aio_slot_t* slot;
|
||||
ulint n;
|
||||
|
@ -1602,10 +1603,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";
|
||||
|
||||
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";
|
||||
i = os_event_wait_multiple(n, (array->events) + segment * n);
|
||||
}
|
||||
|
||||
|
@ -1615,6 +1620,7 @@ os_aio_windows_handle(
|
|||
|
||||
ut_a(slot->reserved);
|
||||
|
||||
srv_io_thread_op_info[orig_seg] = "get windows aio return value";
|
||||
ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE);
|
||||
|
||||
*message1 = slot->message1;
|
||||
|
@ -1887,6 +1893,8 @@ consecutive_loop:
|
|||
}
|
||||
}
|
||||
|
||||
srv_io_thread_op_info[global_segment] = "doing file i/o";
|
||||
|
||||
/* Do the i/o with ordinary, synchronous i/o functions: */
|
||||
if (slot->type == OS_FILE_WRITE) {
|
||||
ret = os_file_write(slot->name, slot->file, combined_buf,
|
||||
|
@ -1897,7 +1905,8 @@ consecutive_loop:
|
|||
}
|
||||
|
||||
ut_a(ret);
|
||||
|
||||
srv_io_thread_op_info[global_segment] = "file i/o done";
|
||||
|
||||
/* printf("aio: %lu consecutive %lu:th segment, first offs %lu blocks\n",
|
||||
n_consecutive, global_segment, slot->offset
|
||||
/ UNIV_PAGE_SIZE); */
|
||||
|
@ -1953,6 +1962,8 @@ wait_for_io:
|
|||
|
||||
os_mutex_exit(array->mutex);
|
||||
|
||||
srv_io_thread_op_info[global_segment] = "waiting for i/o request";
|
||||
|
||||
os_event_wait(os_aio_segment_wait_events[global_segment]);
|
||||
|
||||
goto restart;
|
||||
|
@ -2023,7 +2034,12 @@ os_aio_print(void)
|
|||
ulint n_reserved;
|
||||
ulint i;
|
||||
|
||||
printf("Pending normal aio reads:\n");
|
||||
for (i = 0; i < srv_n_file_io_threads; i++) {
|
||||
printf("I/O thread %lu state: %s\n", i,
|
||||
srv_io_thread_op_info[i]);
|
||||
}
|
||||
|
||||
printf("Pending normal aio reads: ");
|
||||
|
||||
array = os_aio_read_array;
|
||||
loop:
|
||||
|
@ -2041,21 +2057,21 @@ loop:
|
|||
|
||||
if (slot->reserved) {
|
||||
n_reserved++;
|
||||
printf("Reserved slot, messages %lx %lx\n",
|
||||
/* printf("Reserved slot, messages %lx %lx\n",
|
||||
(ulint)slot->message1,
|
||||
(ulint)slot->message2);
|
||||
ut_a(slot->len > 0);
|
||||
*/ ut_a(slot->len > 0);
|
||||
}
|
||||
}
|
||||
|
||||
ut_a(array->n_reserved == n_reserved);
|
||||
|
||||
printf("Total of %lu reserved aio slots\n", n_reserved);
|
||||
printf("%lu\n", n_reserved);
|
||||
|
||||
os_mutex_exit(array->mutex);
|
||||
|
||||
if (array == os_aio_read_array) {
|
||||
printf("Pending aio writes:\n");
|
||||
printf("Pending aio writes: ");
|
||||
|
||||
array = os_aio_write_array;
|
||||
|
||||
|
@ -2063,21 +2079,21 @@ loop:
|
|||
}
|
||||
|
||||
if (array == os_aio_write_array) {
|
||||
printf("Pending insert buffer aio reads:\n");
|
||||
printf("Pending insert buffer aio reads: ");
|
||||
array = os_aio_ibuf_array;
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
if (array == os_aio_ibuf_array) {
|
||||
printf("Pending log writes or reads:\n");
|
||||
printf("Pending log writes or reads: ");
|
||||
array = os_aio_log_array;
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
if (array == os_aio_log_array) {
|
||||
printf("Pending synchronous reads or writes:\n");
|
||||
printf("Pending synchronous reads or writes: ");
|
||||
array = os_aio_sync_array;
|
||||
|
||||
goto loop;
|
||||
|
|
|
@ -462,6 +462,8 @@ row_insert_for_mysql(
|
|||
ut_ad(trx);
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
|
||||
trx->op_info = "inserting";
|
||||
|
||||
if (node == NULL) {
|
||||
row_get_prebuilt_insert_row(prebuilt);
|
||||
node = prebuilt->ins_node;
|
||||
|
@ -499,6 +501,8 @@ run_again:
|
|||
goto run_again;
|
||||
}
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
@ -506,12 +510,15 @@ run_again:
|
|||
|
||||
prebuilt->table->stat_n_rows++;
|
||||
|
||||
srv_n_rows_inserted++;
|
||||
|
||||
if (prebuilt->table->stat_n_rows == 0) {
|
||||
/* Avoid wrap-over */
|
||||
prebuilt->table->stat_n_rows--;
|
||||
}
|
||||
|
||||
row_update_statistics_if_needed(prebuilt);
|
||||
trx->op_info = "";
|
||||
|
||||
return((int) err);
|
||||
}
|
||||
|
@ -627,6 +634,8 @@ row_update_for_mysql(
|
|||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
UT_NOT_USED(mysql_rec);
|
||||
|
||||
trx->op_info = "updating or deleting";
|
||||
|
||||
node = prebuilt->upd_node;
|
||||
|
||||
clust_index = dict_table_get_first_index(table);
|
||||
|
@ -700,6 +709,7 @@ run_again:
|
|||
|
||||
if (err == DB_RECORD_NOT_FOUND) {
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx->op_info = "";
|
||||
|
||||
return((int) err);
|
||||
}
|
||||
|
@ -710,6 +720,8 @@ run_again:
|
|||
goto run_again;
|
||||
}
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
@ -719,10 +731,16 @@ run_again:
|
|||
if (prebuilt->table->stat_n_rows > 0) {
|
||||
prebuilt->table->stat_n_rows--;
|
||||
}
|
||||
}
|
||||
|
||||
srv_n_rows_deleted++;
|
||||
} else {
|
||||
srv_n_rows_updated++;
|
||||
}
|
||||
|
||||
row_update_statistics_if_needed(prebuilt);
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return((int) err);
|
||||
}
|
||||
|
||||
|
@ -798,6 +816,8 @@ row_create_table_for_mysql(
|
|||
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
|
||||
trx->op_info = "creating table";
|
||||
|
||||
/* Serialize data dictionary operations with dictionary mutex:
|
||||
no deadlocks can occur then in these operations */
|
||||
|
||||
|
@ -825,16 +845,22 @@ row_create_table_for_mysql(
|
|||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
|
||||
if (err == DB_OUT_OF_FILE_SPACE) {
|
||||
row_drop_table_for_mysql(table->name, trx, TRUE);
|
||||
row_drop_table_for_mysql(table->name, trx, TRUE);
|
||||
} else {
|
||||
assert(err == DB_DUPLICATE_KEY);
|
||||
fprintf(stderr,
|
||||
assert(err == DB_DUPLICATE_KEY);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: table %s already exists in InnoDB internal\n"
|
||||
"InnoDB: data dictionary. Have you deleted the .frm file\n"
|
||||
"InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n"
|
||||
"InnoDB: for InnoDB tables in MySQL version <= 3.23.39?\n"
|
||||
"InnoDB: for InnoDB tables in MySQL version <= 3.23.42?\n"
|
||||
"InnoDB: See the Restrictions section of the InnoDB manual.\n",
|
||||
table->name);
|
||||
fprintf(stderr,
|
||||
"InnoDB: You can drop the orphaned table inside InnoDB by\n"
|
||||
"InnoDB: creating an InnoDB table with the same name in another\n"
|
||||
"InnoDB: database and moving the .frm file to the current database.\n"
|
||||
"InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n"
|
||||
"InnoDB: succeed.\n");
|
||||
}
|
||||
|
||||
trx->error_state = DB_SUCCESS;
|
||||
|
@ -852,11 +878,32 @@ row_create_table_for_mysql(
|
|||
|
||||
srv_print_innodb_monitor = TRUE;
|
||||
}
|
||||
|
||||
keywordlen = ut_strlen("innodb_lock_monitor");
|
||||
|
||||
if (namelen >= keywordlen
|
||||
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
|
||||
"innodb_lock_monitor", keywordlen)) {
|
||||
|
||||
srv_print_innodb_monitor = TRUE;
|
||||
srv_print_innodb_lock_monitor = TRUE;
|
||||
}
|
||||
|
||||
keywordlen = ut_strlen("innodb_tablespace_monitor");
|
||||
|
||||
if (namelen >= keywordlen
|
||||
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
|
||||
"innodb_tablespace_monitor", keywordlen)) {
|
||||
|
||||
srv_print_innodb_tablespace_monitor = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
que_graph_free((que_t*) que_node_get_parent(thr));
|
||||
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return((int) err);
|
||||
}
|
||||
|
||||
|
@ -879,6 +926,8 @@ row_create_index_for_mysql(
|
|||
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
|
||||
trx->op_info = "creating index";
|
||||
|
||||
/* Serialize data dictionary operations with dictionary mutex:
|
||||
no deadlocks can occur then in these operations */
|
||||
|
||||
|
@ -915,6 +964,8 @@ row_create_index_for_mysql(
|
|||
|
||||
que_graph_free((que_t*) que_node_get_parent(thr));
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return((int) err);
|
||||
}
|
||||
|
||||
|
@ -945,7 +996,9 @@ row_drop_table_for_mysql(
|
|||
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
ut_a(name != NULL);
|
||||
|
||||
|
||||
trx->op_info = "dropping table";
|
||||
|
||||
namelen = ut_strlen(name);
|
||||
keywordlen = ut_strlen("innodb_monitor");
|
||||
|
||||
|
@ -957,6 +1010,26 @@ row_drop_table_for_mysql(
|
|||
stop monitor prints */
|
||||
|
||||
srv_print_innodb_monitor = FALSE;
|
||||
srv_print_innodb_lock_monitor = FALSE;
|
||||
}
|
||||
|
||||
keywordlen = ut_strlen("innodb_lock_monitor");
|
||||
|
||||
if (namelen >= keywordlen
|
||||
&& 0 == ut_memcmp(name + namelen - keywordlen,
|
||||
"innodb_lock_monitor", keywordlen)) {
|
||||
|
||||
srv_print_innodb_monitor = FALSE;
|
||||
srv_print_innodb_lock_monitor = FALSE;
|
||||
}
|
||||
|
||||
keywordlen = ut_strlen("innodb_tablespace_monitor");
|
||||
|
||||
if (namelen >= keywordlen
|
||||
&& 0 == ut_memcmp(name + namelen - keywordlen,
|
||||
"innodb_tablespace_monitor", keywordlen)) {
|
||||
|
||||
srv_print_innodb_tablespace_monitor = FALSE;
|
||||
}
|
||||
|
||||
/* We use the private SQL parser of Innobase to generate the
|
||||
|
@ -1071,6 +1144,8 @@ funct_exit:
|
|||
|
||||
que_graph_free(graph);
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return((int) err);
|
||||
}
|
||||
|
||||
|
@ -1099,6 +1174,8 @@ row_rename_table_for_mysql(
|
|||
ut_a(old_name != NULL);
|
||||
ut_a(new_name != NULL);
|
||||
|
||||
trx->op_info = "renaming table";
|
||||
|
||||
str1 =
|
||||
"PROCEDURE RENAME_TABLE_PROC () IS\n"
|
||||
"BEGIN\n"
|
||||
|
@ -1168,6 +1245,8 @@ funct_exit:
|
|||
|
||||
que_graph_free(graph);
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return((int) err);
|
||||
}
|
||||
|
||||
|
@ -1279,6 +1358,8 @@ row_check_table_for_mysql(
|
|||
ulint n_rows;
|
||||
ulint n_rows_in_table;
|
||||
ulint ret = DB_SUCCESS;
|
||||
|
||||
prebuilt->trx->op_info = "checking table";
|
||||
|
||||
index = dict_table_get_first_index(table);
|
||||
|
||||
|
@ -1311,5 +1392,7 @@ row_check_table_for_mysql(
|
|||
index = dict_table_get_next_index(index);
|
||||
}
|
||||
|
||||
prebuilt->trx->op_info = "";
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ row_purge_remove_clust_if_poss_low(
|
|||
success = btr_cur_optimistic_delete(btr_cur, &mtr);
|
||||
} else {
|
||||
ut_ad(mode == BTR_MODIFY_TREE);
|
||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, &mtr);
|
||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, FALSE, &mtr);
|
||||
|
||||
if (err == DB_SUCCESS) {
|
||||
success = TRUE;
|
||||
|
@ -254,8 +254,8 @@ row_purge_remove_sec_if_poss_low(
|
|||
success = btr_cur_optimistic_delete(btr_cur, &mtr);
|
||||
} else {
|
||||
ut_ad(mode == BTR_MODIFY_TREE);
|
||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, &mtr);
|
||||
|
||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
|
||||
FALSE, &mtr);
|
||||
if (err == DB_SUCCESS) {
|
||||
success = TRUE;
|
||||
} else if (err == DB_OUT_OF_FILE_SPACE) {
|
||||
|
@ -437,7 +437,7 @@ skip_secondaries:
|
|||
data_field_len = ufield->new_val.len;
|
||||
|
||||
btr_free_externally_stored_field(index, data_field,
|
||||
data_field_len, &mtr);
|
||||
data_field_len, FALSE, &mtr);
|
||||
mtr_commit(&mtr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2488,6 +2488,8 @@ row_search_for_mysql(
|
|||
printf("N tables locked %lu\n", trx->mysql_n_tables_locked);
|
||||
*/
|
||||
if (direction == 0) {
|
||||
trx->op_info = "starting index read";
|
||||
|
||||
prebuilt->n_rows_fetched = 0;
|
||||
prebuilt->n_fetch_cached = 0;
|
||||
prebuilt->fetch_cache_first = 0;
|
||||
|
@ -2497,6 +2499,8 @@ row_search_for_mysql(
|
|||
row_prebuild_sel_graph(prebuilt);
|
||||
}
|
||||
} else {
|
||||
trx->op_info = "fetching rows";
|
||||
|
||||
if (prebuilt->n_rows_fetched == 0) {
|
||||
prebuilt->fetch_direction = direction;
|
||||
}
|
||||
|
@ -2519,6 +2523,9 @@ row_search_for_mysql(
|
|||
|
||||
prebuilt->n_rows_fetched++;
|
||||
|
||||
srv_n_rows_read++;
|
||||
trx->op_info = "";
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -2529,6 +2536,7 @@ row_search_for_mysql(
|
|||
cache, but the cache was not full at the time of the
|
||||
popping: no more rows can exist in the result set */
|
||||
|
||||
trx->op_info = "";
|
||||
return(DB_RECORD_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
@ -2560,6 +2568,7 @@ row_search_for_mysql(
|
|||
|
||||
/* printf("%s record not found 1\n", index->name); */
|
||||
|
||||
trx->op_info = "";
|
||||
return(DB_RECORD_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
@ -2599,6 +2608,9 @@ row_search_for_mysql(
|
|||
|
||||
/* printf("%s shortcut\n", index->name); */
|
||||
|
||||
srv_n_rows_read++;
|
||||
|
||||
trx->op_info = "";
|
||||
return(DB_SUCCESS);
|
||||
|
||||
} else if (shortcut == SEL_EXHAUSTED) {
|
||||
|
@ -2607,6 +2619,7 @@ row_search_for_mysql(
|
|||
|
||||
/* printf("%s record not found 2\n",
|
||||
index->name); */
|
||||
trx->op_info = "";
|
||||
return(DB_RECORD_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
@ -2980,6 +2993,8 @@ lock_wait_or_error:
|
|||
|
||||
/* printf("Using index %s cnt %lu ret value %lu err\n", index->name,
|
||||
cnt, err); */
|
||||
trx->op_info = "";
|
||||
|
||||
return(err);
|
||||
|
||||
normal_return:
|
||||
|
@ -2995,5 +3010,11 @@ normal_return:
|
|||
|
||||
/* printf("Using index %s cnt %lu ret value %lu\n", index->name,
|
||||
cnt, err); */
|
||||
if (ret == DB_SUCCESS) {
|
||||
srv_n_rows_read++;
|
||||
}
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ retry:
|
|||
&(node->pcur), &mtr);
|
||||
ut_a(success);
|
||||
|
||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, &mtr);
|
||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, TRUE, &mtr);
|
||||
|
||||
/* The delete operation may fail if we have little
|
||||
file space left: TODO: easiest to crash the database
|
||||
|
@ -174,7 +174,7 @@ row_undo_ins_remove_sec_low(
|
|||
} else {
|
||||
ut_ad(mode == BTR_MODIFY_TREE);
|
||||
|
||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, &mtr);
|
||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, TRUE, &mtr);
|
||||
}
|
||||
|
||||
btr_pcur_close(&pcur);
|
||||
|
|
|
@ -179,7 +179,11 @@ row_undo_mod_remove_clust_low(
|
|||
} else {
|
||||
ut_ad(mode == BTR_MODIFY_TREE);
|
||||
|
||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, mtr);
|
||||
/* Note that since this operation is analogous to purge,
|
||||
we can free also inherited externally stored fields:
|
||||
hence the last FALSE in the call below */
|
||||
|
||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, FALSE, mtr);
|
||||
|
||||
/* The delete operation may fail if we have little
|
||||
file space left: TODO: easiest to crash the database
|
||||
|
@ -356,7 +360,8 @@ row_undo_mod_del_mark_or_remove_sec_low(
|
|||
} else {
|
||||
ut_ad(mode == BTR_MODIFY_TREE);
|
||||
|
||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, &mtr);
|
||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
|
||||
TRUE, &mtr);
|
||||
|
||||
/* The delete operation may fail if we have little
|
||||
file space left: TODO: easiest to crash the database
|
||||
|
@ -423,22 +428,22 @@ row_undo_mod_del_unmark_sec(
|
|||
found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
|
||||
&mtr);
|
||||
if (!found) {
|
||||
err_buf = mem_alloc(1000);
|
||||
dtuple_sprintf(err_buf, 900, entry);
|
||||
err_buf = mem_alloc(1000);
|
||||
dtuple_sprintf(err_buf, 900, entry);
|
||||
|
||||
fprintf(stderr, "InnoDB: error in sec index entry del undo in\n"
|
||||
"InnoDB: index %s table %s\n", index->name,
|
||||
index->table->name);
|
||||
fprintf(stderr, "InnoDB: tuple %s\n", err_buf);
|
||||
fprintf(stderr, "InnoDB: error in sec index entry del undo in\n"
|
||||
"InnoDB: index %s table %s\n", index->name,
|
||||
index->table->name);
|
||||
fprintf(stderr, "InnoDB: tuple %s\n", err_buf);
|
||||
|
||||
rec_sprintf(err_buf, 900, btr_pcur_get_rec(&pcur));
|
||||
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
||||
rec_sprintf(err_buf, 900, btr_pcur_get_rec(&pcur));
|
||||
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
||||
|
||||
fprintf(stderr, "InnoDB: Make a detailed bug report and send it\n");
|
||||
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
|
||||
|
||||
mem_free(err_buf);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Make a detailed bug report and send it\n");
|
||||
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
|
||||
|
||||
mem_free(err_buf);
|
||||
} else {
|
||||
btr_cur = btr_pcur_get_btr_cur(&pcur);
|
||||
|
||||
|
|
|
@ -840,32 +840,31 @@ row_upd_sec_index_entry(
|
|||
rec = btr_cur_get_rec(btr_cur);
|
||||
|
||||
if (!found) {
|
||||
err_buf = mem_alloc(1000);
|
||||
dtuple_sprintf(err_buf, 900, entry);
|
||||
|
||||
err_buf = mem_alloc(1000);
|
||||
dtuple_sprintf(err_buf, 900, entry);
|
||||
fprintf(stderr, "InnoDB: error in sec index entry update in\n"
|
||||
"InnoDB: index %s table %s\n", index->name,
|
||||
index->table->name);
|
||||
fprintf(stderr, "InnoDB: tuple %s\n", err_buf);
|
||||
|
||||
fprintf(stderr, "InnoDB: error in sec index entry update in\n"
|
||||
"InnoDB: index %s table %s\n", index->name,
|
||||
index->table->name);
|
||||
fprintf(stderr, "InnoDB: tuple %s\n", err_buf);
|
||||
rec_sprintf(err_buf, 900, rec);
|
||||
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
||||
|
||||
rec_sprintf(err_buf, 900, rec);
|
||||
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Make a detailed bug report and send it\n");
|
||||
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
|
||||
|
||||
fprintf(stderr, "InnoDB: Make a detailed bug report and send it\n");
|
||||
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
|
||||
|
||||
mem_free(err_buf);
|
||||
mem_free(err_buf);
|
||||
} else {
|
||||
/* Delete mark the old index record; it can already be
|
||||
delete marked if we return after a lock wait in
|
||||
row_ins_index_entry below */
|
||||
|
||||
/* Delete mark the old index record; it can already be
|
||||
delete marked if we return after a lock wait in
|
||||
row_ins_index_entry below */
|
||||
|
||||
if (!rec_get_deleted_flag(rec)) {
|
||||
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE, thr,
|
||||
&mtr);
|
||||
}
|
||||
if (!rec_get_deleted_flag(rec)) {
|
||||
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
|
||||
thr, &mtr);
|
||||
}
|
||||
}
|
||||
|
||||
btr_pcur_close(&pcur);
|
||||
|
@ -907,7 +906,7 @@ row_upd_sec_step(
|
|||
|| (node->state == UPD_NODE_UPDATE_SOME_SEC));
|
||||
ut_ad(!(node->index->type & DICT_CLUSTERED));
|
||||
|
||||
if ((node->state == UPD_NODE_UPDATE_ALL_SEC)
|
||||
if (node->state == UPD_NODE_UPDATE_ALL_SEC
|
||||
|| row_upd_changes_ord_field(node->row, node->index,
|
||||
node->update)) {
|
||||
err = row_upd_sec_index_entry(node, thr);
|
||||
|
@ -933,15 +932,13 @@ row_upd_clust_rec_by_insert(
|
|||
dict_index_t* index, /* in: clustered index of the record */
|
||||
que_thr_t* thr, /* in: query thread */
|
||||
mtr_t* mtr) /* in: mtr; gets committed here */
|
||||
{
|
||||
{
|
||||
mem_heap_t* heap;
|
||||
btr_pcur_t* pcur;
|
||||
btr_cur_t* btr_cur;
|
||||
trx_t* trx;
|
||||
dict_table_t* table;
|
||||
mem_heap_t* heap;
|
||||
dtuple_t* entry;
|
||||
ulint* ext_vec;
|
||||
ulint n_ext_vec;
|
||||
ulint err;
|
||||
|
||||
ut_ad(node);
|
||||
|
@ -961,17 +958,20 @@ row_upd_clust_rec_by_insert(
|
|||
|
||||
return(err);
|
||||
}
|
||||
/* Mark as not-owned the externally stored fields which the new
|
||||
row inherits from the delete marked record: purge should not
|
||||
free those externally stored fields even if the delete marked
|
||||
record is removed from the index tree, or updated. */
|
||||
|
||||
btr_cur_mark_extern_inherited_fields(btr_cur_get_rec(btr_cur),
|
||||
node->update, mtr);
|
||||
}
|
||||
|
||||
mtr_commit(mtr);
|
||||
|
||||
node->state = UPD_NODE_INSERT_CLUSTERED;
|
||||
|
||||
heap = mem_heap_create(1024);
|
||||
|
||||
ext_vec = mem_heap_alloc(heap,
|
||||
sizeof(ulint) * dtuple_get_n_fields(node->row));
|
||||
n_ext_vec = 0;
|
||||
heap = mem_heap_create(500);
|
||||
|
||||
entry = row_build_index_entry(node->row, index, heap);
|
||||
|
||||
|
@ -979,10 +979,23 @@ row_upd_clust_rec_by_insert(
|
|||
|
||||
row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
|
||||
|
||||
/* If we return from a lock wait, for example, we may have
|
||||
extern fields marked as not-owned in entry (marked if the
|
||||
if-branch above). We must unmark them. */
|
||||
|
||||
btr_cur_unmark_dtuple_extern_fields(entry, node->ext_vec,
|
||||
node->n_ext_vec);
|
||||
/* We must mark non-updated extern fields in entry as inherited,
|
||||
so that a possible rollback will not free them */
|
||||
|
||||
btr_cur_mark_dtuple_inherited_extern(entry, node->ext_vec,
|
||||
node->n_ext_vec,
|
||||
node->update);
|
||||
|
||||
err = row_ins_index_entry(index, entry, node->ext_vec,
|
||||
node->n_ext_vec, thr);
|
||||
mem_heap_free(heap);
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,14 @@ ibool srv_print_buf_io = FALSE;
|
|||
ibool srv_print_log_io = FALSE;
|
||||
ibool srv_print_latch_waits = FALSE;
|
||||
|
||||
ulint srv_n_rows_inserted = 0;
|
||||
ulint srv_n_rows_updated = 0;
|
||||
ulint srv_n_rows_deleted = 0;
|
||||
ulint srv_n_rows_read = 0;
|
||||
|
||||
ibool srv_print_innodb_monitor = FALSE;
|
||||
ibool srv_print_innodb_lock_monitor = FALSE;
|
||||
ibool srv_print_innodb_tablespace_monitor = FALSE;
|
||||
|
||||
/* The parameters below are obsolete: */
|
||||
|
||||
|
@ -137,6 +144,11 @@ ulint srv_test_n_reserved_rnds = ULINT_MAX;
|
|||
ulint srv_test_array_size = ULINT_MAX;
|
||||
ulint srv_test_n_mutexes = ULINT_MAX;
|
||||
|
||||
/* Array of English strings describing the current state of an
|
||||
i/o handler thread */
|
||||
|
||||
char* srv_io_thread_op_info[SRV_MAX_N_IO_THREADS];
|
||||
|
||||
/*
|
||||
IMPLEMENTATION OF THE SERVER MAIN PROGRAM
|
||||
=========================================
|
||||
|
@ -1926,23 +1938,25 @@ loop:
|
|||
}
|
||||
|
||||
background_loop:
|
||||
/* In this loop we run background operations while the server
|
||||
/* In this loop we run background operations when the server
|
||||
is quiet */
|
||||
|
||||
current_time = time(NULL);
|
||||
|
||||
if (srv_print_innodb_monitor
|
||||
&& difftime(current_time, last_monitor_time) > 8) {
|
||||
if (difftime(current_time, last_monitor_time) > 15) {
|
||||
|
||||
last_monitor_time = time(NULL);
|
||||
|
||||
if (srv_print_innodb_monitor) {
|
||||
|
||||
printf("================================\n");
|
||||
last_monitor_time = time(NULL);
|
||||
printf("=====================================\n");
|
||||
ut_print_timestamp(stdout);
|
||||
|
||||
printf(" INNODB MONITOR OUTPUT\n"
|
||||
"================================\n");
|
||||
printf("--------------------------\n"
|
||||
"LOCKS HELD BY TRANSACTIONS\n"
|
||||
"--------------------------\n");
|
||||
"=====================================\n");
|
||||
printf("------------\n"
|
||||
"TRANSACTIONS\n"
|
||||
"------------\n");
|
||||
lock_print_info();
|
||||
printf("-----------------------------------------------\n"
|
||||
"CURRENT SEMAPHORES RESERVED AND SEMAPHORE WAITS\n"
|
||||
|
@ -1955,11 +1969,40 @@ background_loop:
|
|||
"BUFFER POOL\n"
|
||||
"-----------\n");
|
||||
buf_print_io();
|
||||
printf("--------------\n"
|
||||
"ROW OPERATIONS\n"
|
||||
"--------------\n");
|
||||
printf(
|
||||
"Number of rows inserted %lu, updated %lu, deleted %lu, read %lu\n",
|
||||
srv_n_rows_inserted,
|
||||
srv_n_rows_updated,
|
||||
srv_n_rows_deleted,
|
||||
srv_n_rows_read);
|
||||
printf("Server activity counter %lu\n", srv_activity_count);
|
||||
printf("----------------------------\n"
|
||||
"END OF INNODB MONITOR OUTPUT\n"
|
||||
"============================\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (srv_print_innodb_tablespace_monitor) {
|
||||
|
||||
printf("================================================\n");
|
||||
|
||||
ut_print_timestamp(stdout);
|
||||
|
||||
printf(" INNODB TABLESPACE MONITOR OUTPUT\n"
|
||||
"================================================\n");
|
||||
|
||||
fsp_print(0);
|
||||
fprintf(stderr, "Validating tablespace\n");
|
||||
fsp_validate(0);
|
||||
fprintf(stderr, "Validation ok\n");
|
||||
printf("---------------------------------------\n"
|
||||
"END OF INNODB TABLESPACE MONITOR OUTPUT\n"
|
||||
"=======================================\n");
|
||||
}
|
||||
}
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
if (srv_activity_count != old_activity_count) {
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
@ -2009,8 +2052,18 @@ background_loop:
|
|||
}
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
if (srv_print_innodb_monitor) {
|
||||
ut_print_timestamp(stdout);
|
||||
printf(" InnoDB (main thread) starts buffer pool flush\n");
|
||||
}
|
||||
|
||||
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
|
||||
|
||||
if (srv_print_innodb_monitor) {
|
||||
ut_print_timestamp(stdout);
|
||||
printf(" InnoDB flushed %lu pages\n", n_pages_flushed);
|
||||
}
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
if (srv_activity_count != old_activity_count) {
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
@ -2038,12 +2091,7 @@ background_loop:
|
|||
|
||||
/* mem_print_new_info();
|
||||
*/
|
||||
/*
|
||||
fsp_print(0);
|
||||
fprintf(stderr, "Validating tablespace\n");
|
||||
fsp_validate(0);
|
||||
fprintf(stderr, "Validation ok\n");
|
||||
*/
|
||||
|
||||
#ifdef UNIV_SEARCH_PERF_STAT
|
||||
/* btr_search_print_info(); */
|
||||
#endif
|
||||
|
|
|
@ -67,8 +67,6 @@ os_file_t files[1000];
|
|||
mutex_t ios_mutex;
|
||||
ulint ios;
|
||||
|
||||
#define SRV_MAX_N_IO_THREADS 1000
|
||||
|
||||
ulint n[SRV_MAX_N_IO_THREADS + 5];
|
||||
os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 5];
|
||||
|
||||
|
@ -591,6 +589,11 @@ innobase_start_or_create_for_mysql(void)
|
|||
return((int) err);
|
||||
}
|
||||
|
||||
/* 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))
|
||||
/* In simulated aio we currently have use only for 4 threads */
|
||||
|
||||
|
|
|
@ -438,22 +438,48 @@ sync_array_cell_print(
|
|||
/*==================*/
|
||||
sync_cell_t* cell) /* in: sync cell */
|
||||
{
|
||||
char* str = NULL;
|
||||
ulint type;
|
||||
mutex_t* mutex;
|
||||
rw_lock_t* rwlock;
|
||||
char* str = NULL;
|
||||
ulint type;
|
||||
|
||||
type = cell->request_type;
|
||||
|
||||
if (type == SYNC_MUTEX) {
|
||||
str = "MUTEX ENTER";
|
||||
} else if (type == RW_LOCK_EX) {
|
||||
str = "X-LOCK";
|
||||
} else if (type == RW_LOCK_SHARED) {
|
||||
str = "S-LOCK";
|
||||
mutex = (mutex_t*)cell->wait_object;
|
||||
|
||||
printf("Mutex created in file %s line %lu",
|
||||
mutex->cfile_name, mutex->cline);
|
||||
} else if (type == RW_LOCK_EX || type == RW_LOCK_SHARED) {
|
||||
|
||||
if (type == RW_LOCK_EX) {
|
||||
str = "X-LOCK";
|
||||
} else {
|
||||
str = "S_LOCK";
|
||||
}
|
||||
|
||||
rwlock = (rw_lock_t*)cell->wait_object;
|
||||
|
||||
printf("Rw-latch created in file %s line %lu",
|
||||
rwlock->cfile_name, rwlock->cline);
|
||||
if (rwlock->writer != RW_LOCK_NOT_LOCKED) {
|
||||
printf(" writer reserved with %lu", rwlock->writer);
|
||||
}
|
||||
|
||||
if (rwlock->writer == RW_LOCK_EX) {
|
||||
printf(" reserv. thread id %lu",
|
||||
(ulint)rwlock->writer_thread);
|
||||
}
|
||||
|
||||
if (rwlock->reader_count > 0) {
|
||||
printf(" readers %lu", rwlock->reader_count);
|
||||
}
|
||||
} else {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
printf("%lx waited for by thread %lu op. %s file %s line %lu ",
|
||||
printf(" at addr %lx waited for by thread %lu op. %s file %s line %lu ",
|
||||
(ulint)cell->wait_object,
|
||||
(ulint)cell->thread,
|
||||
str, cell->file, cell->line);
|
||||
|
|
|
@ -98,6 +98,8 @@ trx_rollback_for_mysql(
|
|||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
trx->op_info = "rollback";
|
||||
|
||||
/* Tell Innobase server that there might be work for
|
||||
utility threads: */
|
||||
|
@ -111,6 +113,8 @@ trx_rollback_for_mysql(
|
|||
|
||||
srv_active_wake_master_thread();
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
@ -129,6 +133,8 @@ trx_rollback_last_sql_stat_for_mysql(
|
|||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
trx->op_info = "rollback of SQL statement";
|
||||
|
||||
/* Tell Innobase server that there might be work for
|
||||
utility threads: */
|
||||
|
@ -144,6 +150,8 @@ trx_rollback_last_sql_stat_for_mysql(
|
|||
|
||||
srv_active_wake_master_thread();
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
|
|
@ -510,7 +510,8 @@ trx_sys_init_at_db_start(void)
|
|||
MLOG_8BYTES, &mtr),
|
||||
TRX_SYS_TRX_ID_WRITE_MARGIN),
|
||||
2 * TRX_SYS_TRX_ID_WRITE_MARGIN);
|
||||
|
||||
|
||||
UT_LIST_INIT(trx_sys->mysql_trx_list);
|
||||
trx_lists_init_at_db_start();
|
||||
|
||||
if (UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
|
||||
|
|
|
@ -24,6 +24,12 @@ Created 3/26/1996 Heikki Tuuri
|
|||
#include "thr0loc.h"
|
||||
#include "btr0sea.h"
|
||||
|
||||
|
||||
/* Copy of the prototype for innobase_mysql_print_thd: this
|
||||
copy must be equal to the one in mysql/sql/ha_innobase.cc ! */
|
||||
void innobase_mysql_print_thd(void* thd);
|
||||
|
||||
|
||||
/* Dummy session used currently in MySQL interface */
|
||||
sess_t* trx_dummy_sess = NULL;
|
||||
|
||||
|
@ -58,11 +64,15 @@ trx_create(
|
|||
|
||||
trx = mem_alloc(sizeof(trx_t));
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
trx->type = TRX_USER;
|
||||
trx->conc_state = TRX_NOT_STARTED;
|
||||
|
||||
trx->dict_operation = FALSE;
|
||||
|
||||
trx->mysql_thd = NULL;
|
||||
|
||||
trx->n_mysql_tables_in_use = 0;
|
||||
trx->mysql_n_tables_locked = 0;
|
||||
|
||||
|
@ -129,6 +139,8 @@ trx_allocate_for_mysql(void)
|
|||
|
||||
trx_n_mysql_transactions++;
|
||||
|
||||
UT_LIST_ADD_FIRST(mysql_trx_list, trx_sys->mysql_trx_list, trx);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
trx->mysql_thread_id = os_thread_get_curr_id();
|
||||
|
@ -144,11 +156,11 @@ trx_search_latch_release_if_reserved(
|
|||
/*=================================*/
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
if (trx->has_search_latch) {
|
||||
rw_lock_s_unlock(&btr_search_latch);
|
||||
if (trx->has_search_latch) {
|
||||
rw_lock_s_unlock(&btr_search_latch);
|
||||
|
||||
trx->has_search_latch = FALSE;
|
||||
}
|
||||
trx->has_search_latch = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
@ -209,6 +221,8 @@ trx_free_for_mysql(
|
|||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
UT_LIST_REMOVE(mysql_trx_list, trx_sys->mysql_trx_list, trx);
|
||||
|
||||
trx_free(trx);
|
||||
|
||||
ut_a(trx_n_mysql_transactions > 0);
|
||||
|
@ -641,7 +655,7 @@ shortcut:
|
|||
ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
|
||||
ut_ad(UT_LIST_GET_LEN(trx->trx_locks) == 0);
|
||||
|
||||
UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx);
|
||||
UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
@ -1268,6 +1282,8 @@ trx_commit_for_mysql(
|
|||
sig to the transaction, we must here make sure that trx has been
|
||||
started. */
|
||||
|
||||
trx->op_info = "committing";
|
||||
|
||||
trx_start_if_not_started(trx);
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
@ -1276,6 +1292,8 @@ trx_commit_for_mysql(
|
|||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -1295,3 +1313,78 @@ trx_mark_sql_stat_end(
|
|||
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Marks the latest SQL statement ended but does not start a new transaction
|
||||
if the trx is not started. */
|
||||
|
||||
void
|
||||
trx_mark_sql_stat_end_do_not_start_new(
|
||||
/*===================================*/
|
||||
trx_t* trx) /* in: trx handle */
|
||||
{
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
trx->last_sql_stat_start.least_undo_no = trx->undo_no;
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Prints info about a transaction to the standard output. The caller must
|
||||
own the kernel mutex. */
|
||||
|
||||
void
|
||||
trx_print(
|
||||
/*======*/
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
printf("TRANSACTION %lu %lu, OS thread id %lu",
|
||||
ut_dulint_get_high(trx->id),
|
||||
ut_dulint_get_low(trx->id),
|
||||
(ulint)trx->mysql_thread_id);
|
||||
|
||||
if (ut_strlen(trx->op_info) > 0) {
|
||||
printf(" %s", trx->op_info);
|
||||
}
|
||||
|
||||
if (trx->type != TRX_USER) {
|
||||
printf(" purge trx");
|
||||
}
|
||||
|
||||
switch (trx->conc_state) {
|
||||
case TRX_NOT_STARTED: printf(", not started"); break;
|
||||
case TRX_ACTIVE: printf(", active"); break;
|
||||
case TRX_COMMITTED_IN_MEMORY: printf(", committed in memory");
|
||||
break;
|
||||
default: printf(" state %lu", trx->conc_state);
|
||||
}
|
||||
|
||||
switch (trx->que_state) {
|
||||
case TRX_QUE_RUNNING: printf(", runs or sleeps"); break;
|
||||
case TRX_QUE_LOCK_WAIT: printf(", lock wait"); break;
|
||||
case TRX_QUE_ROLLING_BACK: printf(", rolling back"); break;
|
||||
case TRX_QUE_COMMITTING: printf(", committing"); break;
|
||||
default: printf(" que state %lu", trx->que_state);
|
||||
}
|
||||
|
||||
if (0 < UT_LIST_GET_LEN(trx->trx_locks)) {
|
||||
printf(", has %lu lock struct(s)",
|
||||
UT_LIST_GET_LEN(trx->trx_locks));
|
||||
}
|
||||
|
||||
if (trx->has_search_latch) {
|
||||
printf(", holds adaptive hash latch");
|
||||
}
|
||||
|
||||
if (ut_dulint_cmp(trx->undo_no, ut_dulint_zero) != 0) {
|
||||
printf(", undo log entries %lu",
|
||||
ut_dulint_get_low(trx->undo_no));
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (trx->mysql_thd != NULL) {
|
||||
innobase_mysql_print_thd(trx->mysql_thd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1111,6 +1111,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
|
|||
SORT_INFO *sort_info= ¶m->sort_info;
|
||||
DBUG_ENTER("mi_repair");
|
||||
|
||||
sort_info->buff=sort_info->record=0;
|
||||
start_records=info->state->records;
|
||||
new_header_length=(param->testflag & T_UNPACK) ? 0L :
|
||||
share->pack.header_length;
|
||||
|
@ -1329,9 +1330,7 @@ err:
|
|||
}
|
||||
mi_mark_crashed_on_repair(info);
|
||||
}
|
||||
if (sort_info->record)
|
||||
my_free(sort_info->record,MYF(0));
|
||||
|
||||
my_free(sort_info->record,MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free(sort_info->buff,MYF(MY_ALLOW_ZERO_PTR));
|
||||
VOID(end_io_cache(¶m->read_cache));
|
||||
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
|
||||
|
|
|
@ -200,7 +200,7 @@ static struct option long_options[] =
|
|||
|
||||
static void print_version(void)
|
||||
{
|
||||
printf("%s Ver 1.50 for %s at %s\n",my_progname,SYSTEM_TYPE,
|
||||
printf("%s Ver 1.51 for %s at %s\n",my_progname,SYSTEM_TYPE,
|
||||
MACHINE_TYPE);
|
||||
}
|
||||
|
||||
|
@ -608,7 +608,8 @@ static int myisamchk(MI_CHECK *param, my_string filename)
|
|||
info->s->state.header.file_version[3] != myisam_file_magic[3] ||
|
||||
(set_charset && set_charset->number != share->state.header.language)))
|
||||
{
|
||||
check_param.language=set_charset->number;
|
||||
if (set_charset)
|
||||
check_param.language=set_charset->number;
|
||||
if (recreate_table(&check_param, &info,filename))
|
||||
{
|
||||
VOID(fprintf(stderr,
|
||||
|
|
|
@ -251,7 +251,7 @@ static struct option long_options[] =
|
|||
|
||||
static void print_version(void)
|
||||
{
|
||||
printf("%s Ver 1.9 for %s on %s\n",my_progname,SYSTEM_TYPE,MACHINE_TYPE);
|
||||
printf("%s Ver 1.10 for %s on %s\n",my_progname,SYSTEM_TYPE,MACHINE_TYPE);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
|
@ -1670,7 +1670,7 @@ static int compress_isam_file(MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
|
|||
max_calc_length+=huff_counts[i].tree->height;
|
||||
else if (huff_counts[i].field_type == FIELD_BLOB ||
|
||||
huff_counts[i].field_type == FIELD_VARCHAR)
|
||||
max_calc_length=huff_counts[i].tree->height*huff_counts[i].max_length + huff_counts[i].length_bits +1;
|
||||
max_calc_length+=huff_counts[i].tree->height*huff_counts[i].max_length + huff_counts[i].length_bits +1;
|
||||
else
|
||||
max_calc_length+=
|
||||
(huff_counts[i].field_length - huff_counts[i].max_zero_fill)*
|
||||
|
|
|
@ -65,7 +65,6 @@ int handle_locking)
|
|||
end[-1]='\0';
|
||||
if (buff[0] && buff[0] != '#') /* Skipp empty lines and comments */
|
||||
{
|
||||
last_isam=isam;
|
||||
if (!test_if_hard_path(buff))
|
||||
{
|
||||
VOID(strmake(name_buff+dir_length,buff,
|
||||
|
@ -75,14 +74,14 @@ int handle_locking)
|
|||
if (!(isam=mi_open(buff,mode,test(handle_locking))))
|
||||
goto err;
|
||||
files++;
|
||||
last_isam=isam;
|
||||
if (info.reclength && info.reclength != isam->s->base.reclength)
|
||||
{
|
||||
my_errno=HA_ERR_WRONG_IN_RECORD;
|
||||
goto err;
|
||||
}
|
||||
info.reclength=isam->s->base.reclength;
|
||||
}
|
||||
last_isam=isam;
|
||||
if (info.reclength && info.reclength != isam->s->base.reclength)
|
||||
{
|
||||
my_errno=HA_ERR_WRONG_IN_RECORD;
|
||||
goto err;
|
||||
}
|
||||
info.reclength=isam->s->base.reclength;
|
||||
}
|
||||
if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO)+
|
||||
files*sizeof(MYRG_TABLE),
|
||||
|
|
|
@ -35,9 +35,13 @@ show create table t3;
|
|||
|
||||
# The following should give errors
|
||||
create table t4 (a int not null, b char(10), key(a)) type=MERGE UNION=(t1,t2);
|
||||
--error 1016
|
||||
select * from t4;
|
||||
--error 1212
|
||||
create table t5 (a int not null, b char(10), key(a)) type=MERGE UNION=(test.t1,test_2.t2);
|
||||
|
||||
# Because of windows, it's important that we drop the merge tables first!
|
||||
drop table if exists t4,t3,t1,t2;
|
||||
drop table if exists t5,t4,t3,t1,t2;
|
||||
|
||||
create table t1 (c char(10)) type=myisam;
|
||||
create table t2 (c char(10)) type=myisam;
|
||||
|
|
|
@ -81,7 +81,7 @@ option ProjectOptions = MySQLOptions
|
|||
|
||||
// target source files
|
||||
source "rint.obj"
|
||||
source zlib, ufc, regex
|
||||
source zlib, ufc, regex, 'strings\bmove_upp.c'
|
||||
if debug_build {
|
||||
source type('cpp') dbug
|
||||
}
|
||||
|
|
|
@ -472,7 +472,7 @@ int main(int argc,char **argv)
|
|||
int error;
|
||||
|
||||
MY_INIT(argv[0]);
|
||||
start_value=4597269L; best_t1=6001982L; best_t2=5063828L; best_type=4; /* mode=4513 add=8 type: 0 */
|
||||
start_value=6130115L; best_t1=3632784L; best_t2=86437L; best_type=3; /* mode=4229 add=2 type: 0 */
|
||||
if (get_options(argc,(char **) argv))
|
||||
exit(1);
|
||||
|
||||
|
|
|
@ -180,6 +180,47 @@ convert_error_code_to_mysql(
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
/*****************************************************************
|
||||
Prints info of a THD object (== user session thread) to the
|
||||
standatd output. NOTE that mysql/innobase/trx/trx0trx.c must contain
|
||||
the prototype for this function! */
|
||||
|
||||
void
|
||||
innobase_mysql_print_thd(
|
||||
/*=====================*/
|
||||
void* input_thd)/* in: pointer to a MySQL THD object */
|
||||
{
|
||||
THD* thd;
|
||||
|
||||
thd = (THD*) input_thd;
|
||||
|
||||
printf("MySQL thread id %lu, query id %lu",
|
||||
thd->thread_id, thd->query_id);
|
||||
if (thd->host) {
|
||||
printf(" %s", thd->host);
|
||||
}
|
||||
|
||||
if (thd->ip) {
|
||||
printf(" %s", thd->ip);
|
||||
}
|
||||
|
||||
if (thd->user) {
|
||||
printf(" %s", thd->user);
|
||||
}
|
||||
|
||||
if (thd->proc_info) {
|
||||
printf(" %s", thd->proc_info);
|
||||
}
|
||||
|
||||
if (thd->query) {
|
||||
printf(" %0.100s", thd->query);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Gets the InnoDB transaction handle for a MySQL handler object, creates
|
||||
an InnoDB transaction struct if the corresponding MySQL thread struct still
|
||||
|
@ -199,6 +240,8 @@ check_trx_exists(
|
|||
dbug_assert(thd != NULL);
|
||||
trx = trx_allocate_for_mysql();
|
||||
|
||||
trx->mysql_thd = thd;
|
||||
|
||||
thd->transaction.all.innobase_tid = trx;
|
||||
|
||||
/* The execution of a single SQL statement is denoted by
|
||||
|
@ -633,7 +676,7 @@ innobase_commit(
|
|||
|
||||
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
|
||||
trx_commit_for_mysql(trx);
|
||||
trx_mark_sql_stat_end(trx);
|
||||
trx_mark_sql_stat_end_do_not_start_new(trx);
|
||||
} else {
|
||||
trx_mark_sql_stat_end(trx);
|
||||
}
|
||||
|
@ -672,6 +715,7 @@ innobase_rollback(
|
|||
|
||||
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
|
||||
error = trx_rollback_for_mysql(trx);
|
||||
trx_mark_sql_stat_end_do_not_start_new(trx);
|
||||
} else {
|
||||
error = trx_rollback_last_sql_stat_for_mysql(trx);
|
||||
trx_mark_sql_stat_end(trx);
|
||||
|
@ -1334,8 +1378,15 @@ ha_innobase::write_row(
|
|||
autoincrement field */
|
||||
|
||||
auto_inc = table->next_number_field->val_int();
|
||||
if (auto_inc == 0)
|
||||
auto_inc= user_thd->next_insert_id;
|
||||
|
||||
/* In replication and also otherwise the auto-inc column
|
||||
can be set with SET INSERT_ID. Then we must look at
|
||||
user_thd->next_insert_id. If it is nonzero and the user
|
||||
has not supplied a value, we must use it. */
|
||||
|
||||
if (auto_inc == 0 && user_thd->next_insert_id != 0) {
|
||||
auto_inc = user_thd->next_insert_id;
|
||||
}
|
||||
|
||||
if (auto_inc != 0) {
|
||||
/* This call will calculate the max of the
|
||||
|
@ -2221,29 +2272,29 @@ ha_innobase::external_lock(
|
|||
if (trx->n_mysql_tables_in_use == 0) {
|
||||
trx_mark_sql_stat_end(trx);
|
||||
}
|
||||
thd->transaction.all.innodb_active_trans=1;
|
||||
thd->transaction.all.innodb_active_trans = 1;
|
||||
trx->n_mysql_tables_in_use++;
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
trx->mysql_n_tables_locked++;
|
||||
trx->mysql_n_tables_locked++;
|
||||
}
|
||||
} else {
|
||||
trx->n_mysql_tables_in_use--;
|
||||
|
||||
if (trx->n_mysql_tables_in_use == 0) {
|
||||
|
||||
trx->mysql_n_tables_locked = 0;
|
||||
trx->mysql_n_tables_locked = 0;
|
||||
|
||||
if (trx->has_search_latch) {
|
||||
if (trx->has_search_latch) {
|
||||
|
||||
trx_search_latch_release_if_reserved(trx);
|
||||
}
|
||||
trx_search_latch_release_if_reserved(trx);
|
||||
}
|
||||
|
||||
if (!(thd->options
|
||||
& (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))) {
|
||||
innobase_commit(thd, trx);
|
||||
}
|
||||
if (!(thd->options
|
||||
& (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))) {
|
||||
innobase_commit(thd, trx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2639,6 +2690,10 @@ ha_innobase::records_in_range(
|
|||
|
||||
DBUG_ENTER("records_in_range");
|
||||
|
||||
if (prebuilt->trx) {
|
||||
prebuilt->trx->op_info = "estimating range size";
|
||||
}
|
||||
|
||||
active_index = keynr;
|
||||
|
||||
key = table->key_info + active_index;
|
||||
|
@ -2671,6 +2726,10 @@ ha_innobase::records_in_range(
|
|||
|
||||
my_free((char*) key_val_buff2, MYF(0));
|
||||
|
||||
if (prebuilt->trx) {
|
||||
prebuilt->trx->op_info = "";
|
||||
}
|
||||
|
||||
DBUG_RETURN((ha_rows) n_rows);
|
||||
}
|
||||
|
||||
|
@ -2690,10 +2749,15 @@ ha_innobase::estimate_number_of_rows(void)
|
|||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
dict_table_t* ib_table;
|
||||
|
||||
if (prebuilt->trx) {
|
||||
prebuilt->trx->op_info =
|
||||
"estimating upper bound of table size";
|
||||
}
|
||||
|
||||
DBUG_ENTER("info");
|
||||
|
||||
ib_table = prebuilt->table;
|
||||
|
||||
|
||||
dict_update_statistics(ib_table);
|
||||
|
||||
data_file_length = ((ulonglong)
|
||||
|
@ -2702,6 +2766,10 @@ ha_innobase::estimate_number_of_rows(void)
|
|||
|
||||
/* The minimum clustered index record size is 20 bytes */
|
||||
|
||||
if (prebuilt->trx) {
|
||||
prebuilt->trx->op_info = "";
|
||||
}
|
||||
|
||||
return((ha_rows) (1000 + data_file_length / 20));
|
||||
}
|
||||
|
||||
|
@ -2740,6 +2808,10 @@ ha_innobase::info(
|
|||
|
||||
DBUG_ENTER("info");
|
||||
|
||||
if (prebuilt->trx) {
|
||||
prebuilt->trx->op_info = "calculating table stats";
|
||||
}
|
||||
|
||||
ib_table = prebuilt->table;
|
||||
|
||||
if (flag & HA_STATUS_TIME) {
|
||||
|
@ -2802,6 +2874,10 @@ ha_innobase::info(
|
|||
trx_get_error_info(prebuilt->trx));
|
||||
}
|
||||
|
||||
if (prebuilt->trx) {
|
||||
prebuilt->trx->op_info = "";
|
||||
}
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,6 @@ int ha_myisammrg::delete_row(const byte * buf)
|
|||
int ha_myisammrg::index_read(byte * buf, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
{
|
||||
// return (my_errno=HA_ERR_WRONG_COMMAND);
|
||||
statistic_increment(ha_read_key_count,&LOCK_status);
|
||||
int error=myrg_rkey(file,buf,active_index, key, key_len, find_flag);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
|
@ -96,7 +95,6 @@ int ha_myisammrg::index_read(byte * buf, const byte * key,
|
|||
int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
{
|
||||
// return (my_errno=HA_ERR_WRONG_COMMAND);
|
||||
statistic_increment(ha_read_key_count,&LOCK_status);
|
||||
int error=myrg_rkey(file,buf,index, key, key_len, find_flag);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
|
@ -105,7 +103,6 @@ int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
|
|||
|
||||
int ha_myisammrg::index_next(byte * buf)
|
||||
{
|
||||
// return (my_errno=HA_ERR_WRONG_COMMAND);
|
||||
statistic_increment(ha_read_next_count,&LOCK_status);
|
||||
int error=myrg_rnext(file,buf,active_index);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
|
@ -114,7 +111,6 @@ int ha_myisammrg::index_next(byte * buf)
|
|||
|
||||
int ha_myisammrg::index_prev(byte * buf)
|
||||
{
|
||||
// return (my_errno=HA_ERR_WRONG_COMMAND);
|
||||
statistic_increment(ha_read_prev_count,&LOCK_status);
|
||||
int error=myrg_rprev(file,buf, active_index);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
|
@ -123,7 +119,6 @@ int ha_myisammrg::index_prev(byte * buf)
|
|||
|
||||
int ha_myisammrg::index_first(byte * buf)
|
||||
{
|
||||
// return (my_errno=HA_ERR_WRONG_COMMAND);
|
||||
statistic_increment(ha_read_first_count,&LOCK_status);
|
||||
int error=myrg_rfirst(file, buf, active_index);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
|
@ -132,7 +127,6 @@ int ha_myisammrg::index_first(byte * buf)
|
|||
|
||||
int ha_myisammrg::index_last(byte * buf)
|
||||
{
|
||||
// return (my_errno=HA_ERR_WRONG_COMMAND);
|
||||
statistic_increment(ha_read_last_count,&LOCK_status);
|
||||
int error=myrg_rlast(file, buf, active_index);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
|
|
|
@ -52,6 +52,11 @@ inline int local_thr_alarm(my_bool *A,int B __attribute__((unused)),ALARM *C __a
|
|||
#include "errmsg.h"
|
||||
#include <violite.h>
|
||||
|
||||
#if defined( OS2) && defined( MYSQL_SERVER)
|
||||
#undef ER
|
||||
#define ER CER
|
||||
#endif
|
||||
|
||||
extern ulong net_read_timeout;
|
||||
|
||||
extern "C" { // Because of SCO 3.2V4.2
|
||||
|
|
|
@ -222,3 +222,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -216,3 +216,4 @@
|
|||
"CREATE DATABASE er ikke tilladt mens en tråd holder på globalt read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -217,3 +217,4 @@
|
|||
"CREATE DATABASE niet toegestaan terwijl thread een globale 'read lock' bezit",
|
||||
"Foutieve parameters voor %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -213,3 +213,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -217,3 +217,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -213,3 +213,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -216,3 +216,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -213,3 +213,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -215,3 +215,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -213,3 +213,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -215,3 +215,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -213,3 +213,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -215,3 +215,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -215,3 +215,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -217,3 +217,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -213,3 +213,4 @@
|
|||
"CREATE DATABASE não permitido enquanto uma 'thread' está mantendo um travamento global de leitura",
|
||||
"Argumentos errados para %s",
|
||||
"Não é permitido a %-.32s@%-.64s criar novos usuários",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -217,3 +217,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -216,3 +216,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -221,3 +221,4 @@
|
|||
"CREATE DATABASE not allowed while thread is holding global read lock",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -214,3 +214,4 @@
|
|||
"CREATE DATABASE no permitido mientras un thread está ejerciendo un bloqueo de lectura global",
|
||||
"Wrong arguments to %s",
|
||||
"%-.32s@%-.64s is not allowed to create new users",
|
||||
"Incorrect table definition; All MERGE tables must be in the same database",
|
||||
|
|
|
@ -213,3 +213,4 @@
|
|||
"CREATE DATABASE är inte tillåtet när man har ett globalt läs-lås",
|
||||
"Felaktiga argument till %s",
|
||||
"%-.32s@%-.64s har inte rättigheter att skapa nya användare",
|
||||
"Felaktig tabell definition: Alla tabeller i en MERGE tabell måste vara i samma databas",
|
||||
|
|
|
@ -2178,10 +2178,18 @@ static bool check_merge_table_access(THD *thd, char *db,
|
|||
int error=0;
|
||||
if (table_list)
|
||||
{
|
||||
/* Force all tables to use the current database */
|
||||
/* Check that all tables use the current database */
|
||||
TABLE_LIST *tmp;
|
||||
for (tmp=table_list; tmp ; tmp=tmp->next)
|
||||
tmp->db=db;
|
||||
{
|
||||
if (!tmp->db || !tmp->db[0])
|
||||
tmp->db=db;
|
||||
else if (!strcmp(tmp->db,db))
|
||||
{
|
||||
send_error(&thd->net,ER_UNION_TABLES_IN_DIFFERENT_DIR);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
error=check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
|
||||
table_list);
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ print_array(FILE *f, const char *set, const char *name, int n)
|
|||
endptr = p;
|
||||
for (;;)
|
||||
{
|
||||
while (isspace(*endptr))
|
||||
while (isspace((* (unsigned char*) endptr)))
|
||||
++endptr;
|
||||
if (*endptr && *endptr != '#') /* not comment */
|
||||
break;
|
||||
|
@ -90,7 +90,7 @@ print_array(FILE *f, const char *set, const char *name, int n)
|
|||
}
|
||||
|
||||
p = val;
|
||||
while (!isspace(*endptr))
|
||||
while (!isspace((* (unsigned char*) endptr)))
|
||||
*p++ = *endptr++;
|
||||
*p = '\0';
|
||||
p = endptr;
|
||||
|
|
Loading…
Reference in a new issue