Merge work.mysql.com:/home/bk/mysql into white.box:/home/tim/my/3

This commit is contained in:
tim@white.box 2001-08-30 13:18:06 -04:00
commit 9ddc25b471
68 changed files with 1217 additions and 266 deletions

View file

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

View file

@ -40,19 +40,14 @@ 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; \
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(top_srcdir)/sql/$$f $(srcdir)/$$f; \
done;
thread_test.o: thread_test.c

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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);
@ -1271,6 +1275,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);
if (block->is_hashed) {
@ -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);
}
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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;
@ -106,12 +114,18 @@ extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
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

View file

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

View file

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

View file

@ -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) {
@ -3343,11 +3348,31 @@ lock_print_info(void)
ulint i;
mtr_t mtr;
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("LOCK INFO:\n");
printf("Number of locks in the record hash table %lu\n",
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;

View file

@ -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,6 +1905,7 @@ 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
@ -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;

View file

@ -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 */
@ -832,9 +852,15 @@ row_create_table_for_mysql(
"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);
}
@ -946,6 +997,8 @@ 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);
}
@ -1280,6 +1359,8 @@ row_check_table_for_mysql(
ulint n_rows_in_table;
ulint ret = DB_SUCCESS;
prebuilt->trx->op_info = "checking table";
index = dict_table_get_first_index(table);
while (index != NULL) {
@ -1311,5 +1392,7 @@ row_check_table_for_mysql(
index = dict_table_get_next_index(index);
}
prebuilt->trx->op_info = "";
return(ret);
}

View file

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

View file

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

View file

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

View file

@ -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
@ -434,11 +439,11 @@ row_undo_mod_del_unmark_sec(
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: 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);

View file

@ -840,7 +840,6 @@ 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);
@ -852,19 +851,19 @@ row_upd_sec_index_entry(
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: Make a detailed bug report and send it\n");
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
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 */
if (!rec_get_deleted_flag(rec)) {
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE, thr,
&mtr);
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
thr, &mtr);
}
}
@ -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);
@ -934,14 +933,12 @@ row_upd_clust_rec_by_insert(
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,6 +979,19 @@ 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);

View file

@ -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) {
printf("================================\n");
last_monitor_time = time(NULL);
if (srv_print_innodb_monitor) {
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

View file

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

View file

@ -438,6 +438,8 @@ sync_array_cell_print(
/*==================*/
sync_cell_t* cell) /* in: sync cell */
{
mutex_t* mutex;
rw_lock_t* rwlock;
char* str = NULL;
ulint type;
@ -445,15 +447,39 @@ sync_array_cell_print(
if (type == SYNC_MUTEX) {
str = "MUTEX ENTER";
} else if (type == RW_LOCK_EX) {
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 if (type == RW_LOCK_SHARED) {
str = "S-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);

View file

@ -99,6 +99,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);
}
@ -130,6 +134,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);
}

View file

@ -511,6 +511,7 @@ trx_sys_init_at_db_start(void)
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) {

View file

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

View file

@ -1111,6 +1111,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
SORT_INFO *sort_info= &param->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(&param->read_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);

View file

@ -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,6 +608,7 @@ 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)))
{
if (set_charset)
check_param.language=set_charset->number;
if (recreate_table(&check_param, &info,filename))
{

View file

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

View file

@ -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,7 +74,6 @@ 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)
{
@ -84,6 +82,7 @@ int handle_locking)
}
info.reclength=isam->s->base.reclength;
}
}
if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO)+
files*sizeof(MYRG_TABLE),
MYF(MY_WME))))

View file

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

View file

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

View file

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

View file

@ -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,7 +2272,7 @@ 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) {
@ -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,6 +2749,11 @@ 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;
@ -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;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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