mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
trx0roll.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
trx0sys.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints trx0trx.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints row0mysql.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints row0purge.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints row0sel.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints row0uins.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints row0umod.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints row0upd.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints srv0srv.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints srv0start.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints sync0arr.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints fil0fil.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints ibuf0ibuf.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints lock0lock.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints os0file.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints btr0btr.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints btr0cur.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints btr0sea.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints buf0buf.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints data0data.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints srv0srv.h Fix the primary key update + BLOB bug, improve InnoDB Monitor prints trx0sys.h Fix the primary key update + BLOB bug, improve InnoDB Monitor prints trx0trx.h Fix the primary key update + BLOB bug, improve InnoDB Monitor prints btr0cur.h Fix the primary key update + BLOB bug, improve InnoDB Monitor prints buf0buf.h Fix the primary key update + BLOB bug, improve InnoDB Monitor prints data0data.h Fix the primary key update + BLOB bug, improve InnoDB Monitor prints ha_innobase.cc Fix the auto-inc+REPLACE+replication bug, improve InnoDB Monitor prints sql/ha_innobase.cc: Fix the auto-inc+REPLACE+replication bug, improve InnoDB Monitor prints innobase/include/btr0cur.h: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/include/buf0buf.h: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/include/data0data.h: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/include/srv0srv.h: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/include/trx0sys.h: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/include/trx0trx.h: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/btr/btr0btr.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/btr/btr0cur.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/btr/btr0sea.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/buf/buf0buf.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/data/data0data.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/fil/fil0fil.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/ibuf/ibuf0ibuf.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/lock/lock0lock.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/os/os0file.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/row/row0mysql.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/row/row0purge.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/row/row0sel.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/row/row0uins.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/row/row0umod.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/row/row0upd.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/srv/srv0srv.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/srv/srv0start.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/sync/sync0arr.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/trx/trx0roll.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/trx/trx0sys.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints innobase/trx/trx0trx.c: Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
This commit is contained in:
@ -1738,8 +1738,8 @@ btr_node_ptr_delete(
|
|||||||
|
|
||||||
btr_cur_position(UT_LIST_GET_FIRST(tree->tree_indexes), node_ptr,
|
btr_cur_position(UT_LIST_GET_FIRST(tree->tree_indexes), node_ptr,
|
||||||
&cursor);
|
&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);
|
ut_a(err == DB_SUCCESS);
|
||||||
|
|
||||||
if (!compressed) {
|
if (!compressed) {
|
||||||
|
@ -80,6 +80,9 @@ btr_rec_free_updated_extern_fields(
|
|||||||
X-latched */
|
X-latched */
|
||||||
rec_t* rec, /* in: record */
|
rec_t* rec, /* in: record */
|
||||||
upd_t* update, /* in: update vector */
|
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
|
mtr_t* mtr); /* in: mini-transaction handle which contains
|
||||||
an X-latch to record page and to the tree */
|
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
|
/* The record is so big that we have to store some fields
|
||||||
externally on separate database pages */
|
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) {
|
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
|
/* The record is so big that we have to store some fields
|
||||||
externally on separate database pages */
|
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) {
|
if (big_rec_vec == NULL) {
|
||||||
|
|
||||||
@ -1242,6 +1245,7 @@ btr_cur_update_in_place(
|
|||||||
rec_t* rec;
|
rec_t* rec;
|
||||||
dulint roll_ptr;
|
dulint roll_ptr;
|
||||||
trx_t* trx;
|
trx_t* trx;
|
||||||
|
ibool was_delete_marked;
|
||||||
|
|
||||||
/* Only clustered index records are updated using this function */
|
/* Only clustered index records are updated using this function */
|
||||||
ut_ad((cursor->index)->type & DICT_CLUSTERED);
|
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
|
/* FIXME: in a mixed tree, all records may not have enough ordering
|
||||||
fields for btr search: */
|
fields for btr search: */
|
||||||
|
|
||||||
|
was_delete_marked = rec_get_deleted_flag(rec);
|
||||||
|
|
||||||
row_upd_rec_in_place(rec, update);
|
row_upd_rec_in_place(rec, update);
|
||||||
|
|
||||||
if (block->is_hashed) {
|
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,
|
btr_cur_update_in_place_log(flags, rec, index, update, trx, roll_ptr,
|
||||||
mtr);
|
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);
|
return(DB_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1434,6 +1447,13 @@ btr_cur_optimistic_update(
|
|||||||
|
|
||||||
ut_a(rec); /* <- We calculated above the insert would fit */
|
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 */
|
/* Restore the old explicit lock state on the record */
|
||||||
|
|
||||||
lock_rec_restore_from_page_infimum(rec, page);
|
lock_rec_restore_from_page_infimum(rec, page);
|
||||||
@ -1655,11 +1675,15 @@ btr_cur_pessimistic_update(
|
|||||||
if (flags & BTR_NO_UNDO_LOG_FLAG) {
|
if (flags & BTR_NO_UNDO_LOG_FLAG) {
|
||||||
/* We are in a transaction rollback undoing a row
|
/* We are in a transaction rollback undoing a row
|
||||||
update: we must free possible externally stored fields
|
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);
|
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
|
/* 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)
|
page_get_free_space_of_empty() / 2)
|
||||||
|| (rec_get_converted_size(new_entry) >= REC_MAX_DATA_SIZE)) {
|
|| (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) {
|
if (big_rec_vec == NULL) {
|
||||||
|
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
@ -1694,6 +1718,13 @@ btr_cur_pessimistic_update(
|
|||||||
lock_rec_restore_from_page_infimum(rec, page);
|
lock_rec_restore_from_page_infimum(rec, page);
|
||||||
rec_set_field_extern_bits(rec, ext_vect, n_ext_vect, mtr);
|
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);
|
btr_cur_compress_if_useful(cursor, mtr);
|
||||||
|
|
||||||
err = DB_SUCCESS;
|
err = DB_SUCCESS;
|
||||||
@ -1725,6 +1756,13 @@ btr_cur_pessimistic_update(
|
|||||||
|
|
||||||
rec_set_field_extern_bits(rec, ext_vect, n_ext_vect, mtr);
|
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);
|
lock_rec_restore_from_page_infimum(rec, page);
|
||||||
|
|
||||||
/* If necessary, restore also the correct lock state for a new,
|
/* 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
|
if compression does not occur, the cursor
|
||||||
stays valid: it points to successor of
|
stays valid: it points to successor of
|
||||||
deleted record on function exit */
|
deleted record on function exit */
|
||||||
|
ibool in_rollback,/* in: TRUE if called in rollback */
|
||||||
mtr_t* mtr) /* in: mtr */
|
mtr_t* mtr) /* in: mtr */
|
||||||
{
|
{
|
||||||
page_t* page;
|
page_t* page;
|
||||||
@ -2218,7 +2257,8 @@ btr_cur_pessimistic_delete(
|
|||||||
}
|
}
|
||||||
|
|
||||||
btr_rec_free_externally_stored_fields(cursor->index,
|
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)
|
if ((page_get_n_recs(page) < 2)
|
||||||
&& (dict_tree_get_page(btr_cur_get_tree(cursor))
|
&& (dict_tree_get_page(btr_cur_get_tree(cursor))
|
||||||
!= buf_frame_get_page_no(page))) {
|
!= buf_frame_get_page_no(page))) {
|
||||||
@ -2516,6 +2556,199 @@ btr_estimate_number_of_different_key_vals(
|
|||||||
|
|
||||||
/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/
|
/*================== 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
|
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
|
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
|
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
|
void
|
||||||
btr_free_externally_stored_field(
|
btr_free_externally_stored_field(
|
||||||
@ -2777,6 +3012,9 @@ btr_free_externally_stored_field(
|
|||||||
+ reference to the externally
|
+ reference to the externally
|
||||||
stored part */
|
stored part */
|
||||||
ulint local_len, /* in: length of data */
|
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
|
mtr_t* local_mtr) /* in: mtr containing the latch to
|
||||||
data an an X-latch to the index
|
data an an X-latch to the index
|
||||||
tree */
|
tree */
|
||||||
@ -2828,6 +3066,26 @@ btr_free_externally_stored_field(
|
|||||||
return;
|
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);
|
page = buf_page_get(space_id, page_no, RW_X_LATCH, &mtr);
|
||||||
|
|
||||||
buf_page_dbg_add_level(page, SYNC_EXTERN_STORAGE);
|
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
|
dict_index_t* index, /* in: index of the data, the index
|
||||||
tree MUST be X-latched */
|
tree MUST be X-latched */
|
||||||
rec_t* rec, /* in: record */
|
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
|
mtr_t* mtr) /* in: mini-transaction handle which contains
|
||||||
an X-latch to record page and to the index
|
an X-latch to record page and to the index
|
||||||
tree */
|
tree */
|
||||||
@ -2896,7 +3157,8 @@ btr_rec_free_externally_stored_fields(
|
|||||||
if (rec_get_nth_field_extern_bit(rec, i)) {
|
if (rec_get_nth_field_extern_bit(rec, i)) {
|
||||||
|
|
||||||
data = rec_get_nth_field(rec, i, &len);
|
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 */
|
X-latched */
|
||||||
rec_t* rec, /* in: record */
|
rec_t* rec, /* in: record */
|
||||||
upd_t* update, /* in: update vector */
|
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
|
mtr_t* mtr) /* in: mini-transaction handle which contains
|
||||||
an X-latch to record page and to the tree */
|
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)) {
|
if (rec_get_nth_field_extern_bit(rec, ufield->field_no)) {
|
||||||
|
|
||||||
data = rec_get_nth_field(rec, ufield->field_no, &len);
|
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);
|
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);
|
return(TRUE);
|
||||||
|
|
||||||
/*-------------------------------------------*/
|
/*-------------------------------------------*/
|
||||||
|
@ -349,6 +349,10 @@ buf_pool_create(
|
|||||||
buf_pool->n_pages_written = 0;
|
buf_pool->n_pages_written = 0;
|
||||||
buf_pool->n_pages_created = 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
|
/* 2. Initialize flushing fields
|
||||||
---------------------------- */
|
---------------------------- */
|
||||||
UT_LIST_INIT(buf_pool->flush_list);
|
UT_LIST_INIT(buf_pool->flush_list);
|
||||||
@ -667,6 +671,7 @@ buf_page_get_gen(
|
|||||||
#ifndef UNIV_LOG_DEBUG
|
#ifndef UNIV_LOG_DEBUG
|
||||||
ut_ad(!ibuf_inside() || ibuf_page(space, offset));
|
ut_ad(!ibuf_inside() || ibuf_page(space, offset));
|
||||||
#endif
|
#endif
|
||||||
|
buf_pool->n_page_gets++;
|
||||||
loop:
|
loop:
|
||||||
mutex_enter_fast(&(buf_pool->mutex));
|
mutex_enter_fast(&(buf_pool->mutex));
|
||||||
|
|
||||||
@ -846,6 +851,8 @@ buf_page_optimistic_get_func(
|
|||||||
ut_ad(mtr && guess);
|
ut_ad(mtr && guess);
|
||||||
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
|
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
|
||||||
|
|
||||||
|
buf_pool->n_page_gets++;
|
||||||
|
|
||||||
block = buf_block_align(guess);
|
block = buf_block_align(guess);
|
||||||
|
|
||||||
mutex_enter(&(buf_pool->mutex));
|
mutex_enter(&(buf_pool->mutex));
|
||||||
@ -976,6 +983,8 @@ buf_page_get_known_nowait(
|
|||||||
ut_ad(mtr);
|
ut_ad(mtr);
|
||||||
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
|
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
|
||||||
|
|
||||||
|
buf_pool->n_page_gets++;
|
||||||
|
|
||||||
block = buf_block_align(guess);
|
block = buf_block_align(guess);
|
||||||
|
|
||||||
mutex_enter(&(buf_pool->mutex));
|
mutex_enter(&(buf_pool->mutex));
|
||||||
@ -1643,6 +1652,18 @@ buf_print_io(void)
|
|||||||
printf("Pages read %lu, created %lu, written %lu\n",
|
printf("Pages read %lu, created %lu, written %lu\n",
|
||||||
buf_pool->n_pages_read, buf_pool->n_pages_created,
|
buf_pool->n_pages_read, buf_pool->n_pages_created,
|
||||||
buf_pool->n_pages_written);
|
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));
|
mutex_exit(&(buf_pool->mutex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +395,12 @@ dtuple_convert_big_rec(
|
|||||||
the entry enough, i.e., if there are
|
the entry enough, i.e., if there are
|
||||||
too many short fields in entry */
|
too many short fields in entry */
|
||||||
dict_index_t* index, /* in: index */
|
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;
|
mem_heap_t* heap;
|
||||||
big_rec_t* vector;
|
big_rec_t* vector;
|
||||||
@ -404,7 +409,9 @@ dtuple_convert_big_rec(
|
|||||||
ulint n_fields;
|
ulint n_fields;
|
||||||
ulint longest;
|
ulint longest;
|
||||||
ulint longest_i;
|
ulint longest_i;
|
||||||
|
ibool is_externally_stored;
|
||||||
ulint i;
|
ulint i;
|
||||||
|
ulint j;
|
||||||
|
|
||||||
size = rec_get_converted_size(entry);
|
size = rec_get_converted_size(entry);
|
||||||
|
|
||||||
@ -431,9 +438,23 @@ dtuple_convert_big_rec(
|
|||||||
for (i = dict_index_get_n_unique_in_tree(index);
|
for (i = dict_index_get_n_unique_in_tree(index);
|
||||||
i < dtuple_get_n_fields(entry); i++) {
|
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 */
|
/* 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))
|
dict_index_get_nth_field(index, i))
|
||||||
->ord_part == 0) {
|
->ord_part == 0) {
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ Created 10/25/1995 Heikki Tuuri
|
|||||||
#include "log0log.h"
|
#include "log0log.h"
|
||||||
#include "log0recv.h"
|
#include "log0recv.h"
|
||||||
#include "fsp0fsp.h"
|
#include "fsp0fsp.h"
|
||||||
|
#include "srv0srv.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
IMPLEMENTATION OF THE LOW-LEVEL FILE SYSTEM
|
IMPLEMENTATION OF THE LOW-LEVEL FILE SYSTEM
|
||||||
@ -1152,6 +1153,7 @@ fil_aio_wait(
|
|||||||
ut_ad(fil_validate());
|
ut_ad(fil_validate());
|
||||||
|
|
||||||
if (os_aio_use_native_aio) {
|
if (os_aio_use_native_aio) {
|
||||||
|
srv_io_thread_op_info[segment] = "native aio handle";
|
||||||
#ifdef WIN_ASYNC_IO
|
#ifdef WIN_ASYNC_IO
|
||||||
ret = os_aio_windows_handle(segment, 0, &fil_node, &message,
|
ret = os_aio_windows_handle(segment, 0, &fil_node, &message,
|
||||||
&type);
|
&type);
|
||||||
@ -1161,12 +1163,16 @@ fil_aio_wait(
|
|||||||
ut_a(0);
|
ut_a(0);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
srv_io_thread_op_info[segment] = "simulated aio handle";
|
||||||
|
|
||||||
ret = os_aio_simulated_handle(segment, (void**) &fil_node,
|
ret = os_aio_simulated_handle(segment, (void**) &fil_node,
|
||||||
&message, &type);
|
&message, &type);
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_a(ret);
|
ut_a(ret);
|
||||||
|
|
||||||
|
srv_io_thread_op_info[segment] = "complete io for fil node";
|
||||||
|
|
||||||
mutex_enter(&(system->mutex));
|
mutex_enter(&(system->mutex));
|
||||||
|
|
||||||
fil_node_complete_io(fil_node, fil_system, type);
|
fil_node_complete_io(fil_node, fil_system, type);
|
||||||
@ -1178,9 +1184,10 @@ fil_aio_wait(
|
|||||||
/* Do the i/o handling */
|
/* Do the i/o handling */
|
||||||
|
|
||||||
if (buf_pool_is_block(message)) {
|
if (buf_pool_is_block(message)) {
|
||||||
|
srv_io_thread_op_info[segment] = "complete io for buf page";
|
||||||
buf_page_io_complete(message);
|
buf_page_io_complete(message);
|
||||||
} else {
|
} else {
|
||||||
|
srv_io_thread_op_info[segment] = "complete io for log";
|
||||||
log_io_complete(message);
|
log_io_complete(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2341,7 +2341,7 @@ ibuf_delete_rec(
|
|||||||
root = ibuf_tree_root_get(ibuf_data, space, mtr);
|
root = ibuf_tree_root_get(ibuf_data, space, mtr);
|
||||||
|
|
||||||
btr_cur_pessimistic_delete(&err, TRUE, btr_pcur_get_btr_cur(pcur),
|
btr_cur_pessimistic_delete(&err, TRUE, btr_pcur_get_btr_cur(pcur),
|
||||||
mtr);
|
FALSE, mtr);
|
||||||
ut_a(err == DB_SUCCESS);
|
ut_a(err == DB_SUCCESS);
|
||||||
|
|
||||||
#ifdef UNIV_IBUF_DEBUG
|
#ifdef UNIV_IBUF_DEBUG
|
||||||
|
@ -353,6 +353,7 @@ btr_cur_pessimistic_delete(
|
|||||||
if compression does not occur, the cursor
|
if compression does not occur, the cursor
|
||||||
stays valid: it points to successor of
|
stays valid: it points to successor of
|
||||||
deleted record on function exit */
|
deleted record on function exit */
|
||||||
|
ibool in_rollback,/* in: TRUE if called in rollback */
|
||||||
mtr_t* mtr); /* in: mtr */
|
mtr_t* mtr); /* in: mtr */
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
Parses a redo log record of updating a record in-place. */
|
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 */
|
/* out: estimated number of key values */
|
||||||
dict_index_t* index); /* in: index */
|
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
|
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
|
them in rec. The fields are stored on pages allocated from leaf node
|
||||||
file segment of the index tree. */
|
file segment of the index tree. */
|
||||||
@ -435,7 +482,9 @@ btr_store_big_rec_extern_fields(
|
|||||||
rec and to the tree */
|
rec and to the tree */
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
Frees the space in an externally stored field to the file space
|
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
|
void
|
||||||
btr_free_externally_stored_field(
|
btr_free_externally_stored_field(
|
||||||
@ -446,6 +495,9 @@ btr_free_externally_stored_field(
|
|||||||
+ reference to the externally
|
+ reference to the externally
|
||||||
stored part */
|
stored part */
|
||||||
ulint local_len, /* in: length of data */
|
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
|
mtr_t* local_mtr); /* in: mtr containing the latch to
|
||||||
data an an X-latch to the index
|
data an an X-latch to the index
|
||||||
tree */
|
tree */
|
||||||
@ -458,6 +510,9 @@ btr_rec_free_externally_stored_fields(
|
|||||||
dict_index_t* index, /* in: index of the data, the index
|
dict_index_t* index, /* in: index of the data, the index
|
||||||
tree MUST be X-latched */
|
tree MUST be X-latched */
|
||||||
rec_t* rec, /* in: record */
|
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
|
mtr_t* mtr); /* in: mini-transaction handle which contains
|
||||||
an X-latch to record page and to the index
|
an X-latch to record page and to the index
|
||||||
tree */
|
tree */
|
||||||
@ -620,10 +675,21 @@ and sleep this many microseconds in between */
|
|||||||
on that page */
|
on that page */
|
||||||
#define BTR_EXTERN_LEN 12 /* 8 bytes containing the
|
#define BTR_EXTERN_LEN 12 /* 8 bytes containing the
|
||||||
length of the externally
|
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
|
#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;
|
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_written;/* number write operations */
|
||||||
ulint n_pages_created;/* number of pages created in the pool
|
ulint n_pages_created;/* number of pages created in the pool
|
||||||
with no read */
|
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 */
|
/* 2. Page flushing algorithm fields */
|
||||||
|
|
||||||
UT_LIST_BASE_NODE_T(buf_block_t) flush_list;
|
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
|
the entry enough, i.e., if there are
|
||||||
too many short fields in entry */
|
too many short fields in entry */
|
||||||
dict_index_t* index, /* in: index */
|
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
|
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
|
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_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_n_spin_wait_rounds;
|
||||||
extern ulint srv_spin_wait_delay;
|
extern ulint srv_spin_wait_delay;
|
||||||
extern ibool srv_priority_boost;
|
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 */
|
same DRAM page as other hotspot semaphores */
|
||||||
#define kernel_mutex (*kernel_mutex_temp)
|
#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;
|
typedef struct srv_sys_struct srv_sys_t;
|
||||||
|
|
||||||
/* The server system */
|
/* The server system */
|
||||||
extern srv_sys_t* srv_sys;
|
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 */
|
what these mean */
|
||||||
#define SRV_UNIX_FDATASYNC 1
|
#define SRV_UNIX_FDATASYNC 1
|
||||||
#define SRV_UNIX_O_DSYNC 2
|
#define SRV_UNIX_O_DSYNC 2
|
||||||
|
@ -315,6 +315,9 @@ struct trx_sys_struct{
|
|||||||
/* List of active and committed in
|
/* List of active and committed in
|
||||||
memory transactions, sorted on trx id,
|
memory transactions, sorted on trx id,
|
||||||
biggest first */
|
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;
|
UT_LIST_BASE_NODE_T(trx_rseg_t) rseg_list;
|
||||||
/* List of rollback segment objects */
|
/* List of rollback segment objects */
|
||||||
trx_rseg_t* latest_rseg; /* Latest rollback segment in the
|
trx_rseg_t* latest_rseg; /* Latest rollback segment in the
|
||||||
|
@ -130,6 +130,14 @@ void
|
|||||||
trx_mark_sql_stat_end(
|
trx_mark_sql_stat_end(
|
||||||
/*==================*/
|
/*==================*/
|
||||||
trx_t* trx); /* in: trx handle */
|
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
|
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
|
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 */
|
/* out: query thread to run next, or NULL */
|
||||||
que_thr_t* thr); /* in: query thread */
|
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 */
|
/* Signal to a transaction */
|
||||||
@ -270,6 +286,9 @@ rolling back after a database recovery */
|
|||||||
struct trx_struct{
|
struct trx_struct{
|
||||||
/* All the next fields are protected by the kernel mutex, except the
|
/* All the next fields are protected by the kernel mutex, except the
|
||||||
undo logs which are protected by undo_mutex */
|
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 type; /* TRX_USER, TRX_PURGE */
|
||||||
ulint conc_state; /* state of the trx from the point
|
ulint conc_state; /* state of the trx from the point
|
||||||
of view of concurrency control:
|
of view of concurrency control:
|
||||||
@ -284,6 +303,8 @@ struct trx_struct{
|
|||||||
table */
|
table */
|
||||||
dulint table_id; /* table id if the preceding field is
|
dulint table_id; /* table id if the preceding field is
|
||||||
TRUE */
|
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
|
os_thread_id_t mysql_thread_id;/* id of the MySQL thread associated
|
||||||
with this transaction object */
|
with this transaction object */
|
||||||
ulint n_mysql_tables_in_use; /* number of Innobase tables
|
ulint n_mysql_tables_in_use; /* number of Innobase tables
|
||||||
@ -302,6 +323,9 @@ struct trx_struct{
|
|||||||
of a duplicate key error */
|
of a duplicate key error */
|
||||||
UT_LIST_NODE_T(trx_t)
|
UT_LIST_NODE_T(trx_t)
|
||||||
trx_list; /* list of transactions */
|
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
|
mutex_t undo_mutex; /* mutex protecting the fields in this
|
||||||
section (down to undo_no_arr), EXCEPT
|
section (down to undo_no_arr), EXCEPT
|
||||||
|
@ -13,6 +13,7 @@ Created 5/7/1996 Heikki Tuuri
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "usr0sess.h"
|
#include "usr0sess.h"
|
||||||
|
#include "trx0purge.h"
|
||||||
|
|
||||||
/* When releasing transaction locks, this specifies how often we release
|
/* When releasing transaction locks, this specifies how often we release
|
||||||
the kernel mutex for a moment to give also others access to it */
|
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_ad(mutex_own(&kernel_mutex));
|
||||||
ut_a(lock_get_type(lock) == LOCK_TABLE);
|
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->un_member.tab_lock.table->name,
|
||||||
(lock->trx)->id.high, (lock->trx)->id.low);
|
(lock->trx)->id.high, (lock->trx)->id.low);
|
||||||
|
|
||||||
@ -3220,6 +3221,8 @@ lock_rec_print(
|
|||||||
ulint page_no;
|
ulint page_no;
|
||||||
ulint i;
|
ulint i;
|
||||||
ulint count = 0;
|
ulint count = 0;
|
||||||
|
ulint len;
|
||||||
|
char buf[200];
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
|
|
||||||
ut_ad(mutex_own(&kernel_mutex));
|
ut_ad(mutex_own(&kernel_mutex));
|
||||||
@ -3228,7 +3231,7 @@ lock_rec_print(
|
|||||||
space = lock->un_member.rec_lock.space;
|
space = lock->un_member.rec_lock.space;
|
||||||
page_no = lock->un_member.rec_lock.page_no;
|
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));
|
space, page_no, lock_rec_get_n_bits(lock));
|
||||||
|
|
||||||
printf(" table %s index %s trx id %lu %lu",
|
printf(" table %s index %s trx id %lu %lu",
|
||||||
@ -3251,10 +3254,10 @@ lock_rec_print(
|
|||||||
printf(" waiting");
|
printf(" waiting");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
mtr_start(&mtr);
|
mtr_start(&mtr);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
/* If the page is not in the buffer pool, we cannot load it
|
/* If the page is not in the buffer pool, we cannot load it
|
||||||
because we have the kernel mutex and ibuf operations would
|
because we have the kernel mutex and ibuf operations would
|
||||||
break the latching order */
|
break the latching order */
|
||||||
@ -3280,12 +3283,14 @@ lock_rec_print(
|
|||||||
printf("Record lock, heap no %lu ", i);
|
printf("Record lock, heap no %lu ", i);
|
||||||
|
|
||||||
if (page) {
|
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");
|
printf("\n");
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count >= 3) {
|
if (count >= 3) {
|
||||||
@ -3343,11 +3348,31 @@ lock_print_info(void)
|
|||||||
ulint i;
|
ulint i;
|
||||||
mtr_t mtr;
|
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();
|
lock_mutex_enter_kernel();
|
||||||
|
|
||||||
printf("LOCK INFO:\n");
|
printf("Total number of lock structs in row lock hash table %lu\n",
|
||||||
printf("Number of locks in the record hash table %lu\n",
|
|
||||||
lock_get_n_rec_locks());
|
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:
|
loop:
|
||||||
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
||||||
|
|
||||||
@ -3367,11 +3392,21 @@ loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nth_lock == 0) {
|
if (nth_lock == 0) {
|
||||||
printf("\nLOCKS FOR TRANSACTION ID %lu %lu\n", trx->id.high,
|
printf("---");
|
||||||
trx->id.low);
|
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) {
|
if (trx->que_state == TRX_QUE_LOCK_WAIT) {
|
||||||
printf(
|
printf(
|
||||||
"################# TRX IS WAITING FOR THE LOCK: ###\n");
|
"------------------TRX IS WAITING FOR THE LOCK:\n");
|
||||||
|
|
||||||
if (lock_get_type(trx->wait_lock) == LOCK_REC) {
|
if (lock_get_type(trx->wait_lock) == LOCK_REC) {
|
||||||
lock_rec_print(trx->wait_lock);
|
lock_rec_print(trx->wait_lock);
|
||||||
@ -3380,10 +3415,15 @@ loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf(
|
printf(
|
||||||
"##################################################\n");
|
"------------------\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!srv_print_innodb_lock_monitor) {
|
||||||
|
nth_trx++;
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
lock = UT_LIST_GET_FIRST(trx->trx_locks);
|
lock = UT_LIST_GET_FIRST(trx->trx_locks);
|
||||||
@ -3431,9 +3471,9 @@ loop:
|
|||||||
|
|
||||||
nth_lock++;
|
nth_lock++;
|
||||||
|
|
||||||
if (nth_lock >= 25) {
|
if (nth_lock >= 10) {
|
||||||
printf(
|
printf(
|
||||||
"25 LOCKS PRINTED FOR THIS TRX: SUPPRESSING FURTHER PRINTS\n");
|
"10 LOCKS PRINTED FOR THIS TRX: SUPPRESSING FURTHER PRINTS\n");
|
||||||
|
|
||||||
nth_trx++;
|
nth_trx++;
|
||||||
nth_lock = 0;
|
nth_lock = 0;
|
||||||
|
@ -1577,6 +1577,7 @@ os_aio_windows_handle(
|
|||||||
void** message2,
|
void** message2,
|
||||||
ulint* type) /* out: OS_FILE_WRITE or ..._READ */
|
ulint* type) /* out: OS_FILE_WRITE or ..._READ */
|
||||||
{
|
{
|
||||||
|
ulint orig_seg = segment;
|
||||||
os_aio_array_t* array;
|
os_aio_array_t* array;
|
||||||
os_aio_slot_t* slot;
|
os_aio_slot_t* slot;
|
||||||
ulint n;
|
ulint n;
|
||||||
@ -1602,10 +1603,14 @@ os_aio_windows_handle(
|
|||||||
n = array->n_slots / array->n_segments;
|
n = array->n_slots / array->n_segments;
|
||||||
|
|
||||||
if (array == os_aio_sync_array) {
|
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);
|
ut_ad(pos < array->n_slots);
|
||||||
os_event_wait(array->events[pos]);
|
os_event_wait(array->events[pos]);
|
||||||
i = pos;
|
i = pos;
|
||||||
} else {
|
} else {
|
||||||
|
srv_io_thread_op_info[orig_seg] =
|
||||||
|
"wait windows aio for n pages";
|
||||||
i = os_event_wait_multiple(n, (array->events) + segment * n);
|
i = os_event_wait_multiple(n, (array->events) + segment * n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1615,6 +1620,7 @@ os_aio_windows_handle(
|
|||||||
|
|
||||||
ut_a(slot->reserved);
|
ut_a(slot->reserved);
|
||||||
|
|
||||||
|
srv_io_thread_op_info[orig_seg] = "get windows aio return value";
|
||||||
ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE);
|
ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE);
|
||||||
|
|
||||||
*message1 = slot->message1;
|
*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: */
|
/* Do the i/o with ordinary, synchronous i/o functions: */
|
||||||
if (slot->type == OS_FILE_WRITE) {
|
if (slot->type == OS_FILE_WRITE) {
|
||||||
ret = os_file_write(slot->name, slot->file, combined_buf,
|
ret = os_file_write(slot->name, slot->file, combined_buf,
|
||||||
@ -1897,6 +1905,7 @@ consecutive_loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
ut_a(ret);
|
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",
|
/* printf("aio: %lu consecutive %lu:th segment, first offs %lu blocks\n",
|
||||||
n_consecutive, global_segment, slot->offset
|
n_consecutive, global_segment, slot->offset
|
||||||
@ -1953,6 +1962,8 @@ wait_for_io:
|
|||||||
|
|
||||||
os_mutex_exit(array->mutex);
|
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]);
|
os_event_wait(os_aio_segment_wait_events[global_segment]);
|
||||||
|
|
||||||
goto restart;
|
goto restart;
|
||||||
@ -2023,7 +2034,12 @@ os_aio_print(void)
|
|||||||
ulint n_reserved;
|
ulint n_reserved;
|
||||||
ulint i;
|
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;
|
array = os_aio_read_array;
|
||||||
loop:
|
loop:
|
||||||
@ -2041,21 +2057,21 @@ loop:
|
|||||||
|
|
||||||
if (slot->reserved) {
|
if (slot->reserved) {
|
||||||
n_reserved++;
|
n_reserved++;
|
||||||
printf("Reserved slot, messages %lx %lx\n",
|
/* printf("Reserved slot, messages %lx %lx\n",
|
||||||
(ulint)slot->message1,
|
(ulint)slot->message1,
|
||||||
(ulint)slot->message2);
|
(ulint)slot->message2);
|
||||||
ut_a(slot->len > 0);
|
*/ ut_a(slot->len > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_a(array->n_reserved == n_reserved);
|
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);
|
os_mutex_exit(array->mutex);
|
||||||
|
|
||||||
if (array == os_aio_read_array) {
|
if (array == os_aio_read_array) {
|
||||||
printf("Pending aio writes:\n");
|
printf("Pending aio writes: ");
|
||||||
|
|
||||||
array = os_aio_write_array;
|
array = os_aio_write_array;
|
||||||
|
|
||||||
@ -2063,21 +2079,21 @@ loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (array == os_aio_write_array) {
|
if (array == os_aio_write_array) {
|
||||||
printf("Pending insert buffer aio reads:\n");
|
printf("Pending insert buffer aio reads: ");
|
||||||
array = os_aio_ibuf_array;
|
array = os_aio_ibuf_array;
|
||||||
|
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array == os_aio_ibuf_array) {
|
if (array == os_aio_ibuf_array) {
|
||||||
printf("Pending log writes or reads:\n");
|
printf("Pending log writes or reads: ");
|
||||||
array = os_aio_log_array;
|
array = os_aio_log_array;
|
||||||
|
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array == os_aio_log_array) {
|
if (array == os_aio_log_array) {
|
||||||
printf("Pending synchronous reads or writes:\n");
|
printf("Pending synchronous reads or writes: ");
|
||||||
array = os_aio_sync_array;
|
array = os_aio_sync_array;
|
||||||
|
|
||||||
goto loop;
|
goto loop;
|
||||||
|
@ -462,6 +462,8 @@ row_insert_for_mysql(
|
|||||||
ut_ad(trx);
|
ut_ad(trx);
|
||||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||||
|
|
||||||
|
trx->op_info = "inserting";
|
||||||
|
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
row_get_prebuilt_insert_row(prebuilt);
|
row_get_prebuilt_insert_row(prebuilt);
|
||||||
node = prebuilt->ins_node;
|
node = prebuilt->ins_node;
|
||||||
@ -499,6 +501,8 @@ run_again:
|
|||||||
goto run_again;
|
goto run_again;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,12 +510,15 @@ run_again:
|
|||||||
|
|
||||||
prebuilt->table->stat_n_rows++;
|
prebuilt->table->stat_n_rows++;
|
||||||
|
|
||||||
|
srv_n_rows_inserted++;
|
||||||
|
|
||||||
if (prebuilt->table->stat_n_rows == 0) {
|
if (prebuilt->table->stat_n_rows == 0) {
|
||||||
/* Avoid wrap-over */
|
/* Avoid wrap-over */
|
||||||
prebuilt->table->stat_n_rows--;
|
prebuilt->table->stat_n_rows--;
|
||||||
}
|
}
|
||||||
|
|
||||||
row_update_statistics_if_needed(prebuilt);
|
row_update_statistics_if_needed(prebuilt);
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return((int) err);
|
return((int) err);
|
||||||
}
|
}
|
||||||
@ -627,6 +634,8 @@ row_update_for_mysql(
|
|||||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||||
UT_NOT_USED(mysql_rec);
|
UT_NOT_USED(mysql_rec);
|
||||||
|
|
||||||
|
trx->op_info = "updating or deleting";
|
||||||
|
|
||||||
node = prebuilt->upd_node;
|
node = prebuilt->upd_node;
|
||||||
|
|
||||||
clust_index = dict_table_get_first_index(table);
|
clust_index = dict_table_get_first_index(table);
|
||||||
@ -700,6 +709,7 @@ run_again:
|
|||||||
|
|
||||||
if (err == DB_RECORD_NOT_FOUND) {
|
if (err == DB_RECORD_NOT_FOUND) {
|
||||||
trx->error_state = DB_SUCCESS;
|
trx->error_state = DB_SUCCESS;
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return((int) err);
|
return((int) err);
|
||||||
}
|
}
|
||||||
@ -710,6 +720,8 @@ run_again:
|
|||||||
goto run_again;
|
goto run_again;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -719,10 +731,16 @@ run_again:
|
|||||||
if (prebuilt->table->stat_n_rows > 0) {
|
if (prebuilt->table->stat_n_rows > 0) {
|
||||||
prebuilt->table->stat_n_rows--;
|
prebuilt->table->stat_n_rows--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srv_n_rows_deleted++;
|
||||||
|
} else {
|
||||||
|
srv_n_rows_updated++;
|
||||||
}
|
}
|
||||||
|
|
||||||
row_update_statistics_if_needed(prebuilt);
|
row_update_statistics_if_needed(prebuilt);
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return((int) err);
|
return((int) err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -798,6 +816,8 @@ row_create_table_for_mysql(
|
|||||||
|
|
||||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||||
|
|
||||||
|
trx->op_info = "creating table";
|
||||||
|
|
||||||
/* Serialize data dictionary operations with dictionary mutex:
|
/* Serialize data dictionary operations with dictionary mutex:
|
||||||
no deadlocks can occur then in these operations */
|
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);
|
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||||
|
|
||||||
if (err == DB_OUT_OF_FILE_SPACE) {
|
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 {
|
} else {
|
||||||
assert(err == DB_DUPLICATE_KEY);
|
assert(err == DB_DUPLICATE_KEY);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Error: table %s already exists in InnoDB internal\n"
|
"InnoDB: Error: table %s already exists in InnoDB internal\n"
|
||||||
"InnoDB: data dictionary. Have you deleted the .frm file\n"
|
"InnoDB: data dictionary. Have you deleted the .frm file\n"
|
||||||
"InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\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",
|
"InnoDB: See the Restrictions section of the InnoDB manual.\n",
|
||||||
table->name);
|
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;
|
trx->error_state = DB_SUCCESS;
|
||||||
@ -852,11 +878,32 @@ row_create_table_for_mysql(
|
|||||||
|
|
||||||
srv_print_innodb_monitor = TRUE;
|
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));
|
mutex_exit(&(dict_sys->mutex));
|
||||||
que_graph_free((que_t*) que_node_get_parent(thr));
|
que_graph_free((que_t*) que_node_get_parent(thr));
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return((int) err);
|
return((int) err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -879,6 +926,8 @@ row_create_index_for_mysql(
|
|||||||
|
|
||||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||||
|
|
||||||
|
trx->op_info = "creating index";
|
||||||
|
|
||||||
/* Serialize data dictionary operations with dictionary mutex:
|
/* Serialize data dictionary operations with dictionary mutex:
|
||||||
no deadlocks can occur then in these operations */
|
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));
|
que_graph_free((que_t*) que_node_get_parent(thr));
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return((int) err);
|
return((int) err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -946,6 +997,8 @@ row_drop_table_for_mysql(
|
|||||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||||
ut_a(name != NULL);
|
ut_a(name != NULL);
|
||||||
|
|
||||||
|
trx->op_info = "dropping table";
|
||||||
|
|
||||||
namelen = ut_strlen(name);
|
namelen = ut_strlen(name);
|
||||||
keywordlen = ut_strlen("innodb_monitor");
|
keywordlen = ut_strlen("innodb_monitor");
|
||||||
|
|
||||||
@ -957,6 +1010,26 @@ row_drop_table_for_mysql(
|
|||||||
stop monitor prints */
|
stop monitor prints */
|
||||||
|
|
||||||
srv_print_innodb_monitor = FALSE;
|
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
|
/* We use the private SQL parser of Innobase to generate the
|
||||||
@ -1071,6 +1144,8 @@ funct_exit:
|
|||||||
|
|
||||||
que_graph_free(graph);
|
que_graph_free(graph);
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return((int) err);
|
return((int) err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1099,6 +1174,8 @@ row_rename_table_for_mysql(
|
|||||||
ut_a(old_name != NULL);
|
ut_a(old_name != NULL);
|
||||||
ut_a(new_name != NULL);
|
ut_a(new_name != NULL);
|
||||||
|
|
||||||
|
trx->op_info = "renaming table";
|
||||||
|
|
||||||
str1 =
|
str1 =
|
||||||
"PROCEDURE RENAME_TABLE_PROC () IS\n"
|
"PROCEDURE RENAME_TABLE_PROC () IS\n"
|
||||||
"BEGIN\n"
|
"BEGIN\n"
|
||||||
@ -1168,6 +1245,8 @@ funct_exit:
|
|||||||
|
|
||||||
que_graph_free(graph);
|
que_graph_free(graph);
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return((int) err);
|
return((int) err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1280,6 +1359,8 @@ row_check_table_for_mysql(
|
|||||||
ulint n_rows_in_table;
|
ulint n_rows_in_table;
|
||||||
ulint ret = DB_SUCCESS;
|
ulint ret = DB_SUCCESS;
|
||||||
|
|
||||||
|
prebuilt->trx->op_info = "checking table";
|
||||||
|
|
||||||
index = dict_table_get_first_index(table);
|
index = dict_table_get_first_index(table);
|
||||||
|
|
||||||
while (index != NULL) {
|
while (index != NULL) {
|
||||||
@ -1311,5 +1392,7 @@ row_check_table_for_mysql(
|
|||||||
index = dict_table_get_next_index(index);
|
index = dict_table_get_next_index(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prebuilt->trx->op_info = "";
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ row_purge_remove_clust_if_poss_low(
|
|||||||
success = btr_cur_optimistic_delete(btr_cur, &mtr);
|
success = btr_cur_optimistic_delete(btr_cur, &mtr);
|
||||||
} else {
|
} else {
|
||||||
ut_ad(mode == BTR_MODIFY_TREE);
|
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) {
|
if (err == DB_SUCCESS) {
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
@ -254,8 +254,8 @@ row_purge_remove_sec_if_poss_low(
|
|||||||
success = btr_cur_optimistic_delete(btr_cur, &mtr);
|
success = btr_cur_optimistic_delete(btr_cur, &mtr);
|
||||||
} else {
|
} else {
|
||||||
ut_ad(mode == BTR_MODIFY_TREE);
|
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) {
|
if (err == DB_SUCCESS) {
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
} else if (err == DB_OUT_OF_FILE_SPACE) {
|
} else if (err == DB_OUT_OF_FILE_SPACE) {
|
||||||
@ -437,7 +437,7 @@ skip_secondaries:
|
|||||||
data_field_len = ufield->new_val.len;
|
data_field_len = ufield->new_val.len;
|
||||||
|
|
||||||
btr_free_externally_stored_field(index, data_field,
|
btr_free_externally_stored_field(index, data_field,
|
||||||
data_field_len, &mtr);
|
data_field_len, FALSE, &mtr);
|
||||||
mtr_commit(&mtr);
|
mtr_commit(&mtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2488,6 +2488,8 @@ row_search_for_mysql(
|
|||||||
printf("N tables locked %lu\n", trx->mysql_n_tables_locked);
|
printf("N tables locked %lu\n", trx->mysql_n_tables_locked);
|
||||||
*/
|
*/
|
||||||
if (direction == 0) {
|
if (direction == 0) {
|
||||||
|
trx->op_info = "starting index read";
|
||||||
|
|
||||||
prebuilt->n_rows_fetched = 0;
|
prebuilt->n_rows_fetched = 0;
|
||||||
prebuilt->n_fetch_cached = 0;
|
prebuilt->n_fetch_cached = 0;
|
||||||
prebuilt->fetch_cache_first = 0;
|
prebuilt->fetch_cache_first = 0;
|
||||||
@ -2497,6 +2499,8 @@ row_search_for_mysql(
|
|||||||
row_prebuild_sel_graph(prebuilt);
|
row_prebuild_sel_graph(prebuilt);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
trx->op_info = "fetching rows";
|
||||||
|
|
||||||
if (prebuilt->n_rows_fetched == 0) {
|
if (prebuilt->n_rows_fetched == 0) {
|
||||||
prebuilt->fetch_direction = direction;
|
prebuilt->fetch_direction = direction;
|
||||||
}
|
}
|
||||||
@ -2519,6 +2523,9 @@ row_search_for_mysql(
|
|||||||
|
|
||||||
prebuilt->n_rows_fetched++;
|
prebuilt->n_rows_fetched++;
|
||||||
|
|
||||||
|
srv_n_rows_read++;
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return(DB_SUCCESS);
|
return(DB_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2529,6 +2536,7 @@ row_search_for_mysql(
|
|||||||
cache, but the cache was not full at the time of the
|
cache, but the cache was not full at the time of the
|
||||||
popping: no more rows can exist in the result set */
|
popping: no more rows can exist in the result set */
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
return(DB_RECORD_NOT_FOUND);
|
return(DB_RECORD_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2560,6 +2568,7 @@ row_search_for_mysql(
|
|||||||
|
|
||||||
/* printf("%s record not found 1\n", index->name); */
|
/* printf("%s record not found 1\n", index->name); */
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
return(DB_RECORD_NOT_FOUND);
|
return(DB_RECORD_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2599,6 +2608,9 @@ row_search_for_mysql(
|
|||||||
|
|
||||||
/* printf("%s shortcut\n", index->name); */
|
/* printf("%s shortcut\n", index->name); */
|
||||||
|
|
||||||
|
srv_n_rows_read++;
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
return(DB_SUCCESS);
|
return(DB_SUCCESS);
|
||||||
|
|
||||||
} else if (shortcut == SEL_EXHAUSTED) {
|
} else if (shortcut == SEL_EXHAUSTED) {
|
||||||
@ -2607,6 +2619,7 @@ row_search_for_mysql(
|
|||||||
|
|
||||||
/* printf("%s record not found 2\n",
|
/* printf("%s record not found 2\n",
|
||||||
index->name); */
|
index->name); */
|
||||||
|
trx->op_info = "";
|
||||||
return(DB_RECORD_NOT_FOUND);
|
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,
|
/* printf("Using index %s cnt %lu ret value %lu err\n", index->name,
|
||||||
cnt, err); */
|
cnt, err); */
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
|
|
||||||
normal_return:
|
normal_return:
|
||||||
@ -2995,5 +3010,11 @@ normal_return:
|
|||||||
|
|
||||||
/* printf("Using index %s cnt %lu ret value %lu\n", index->name,
|
/* printf("Using index %s cnt %lu ret value %lu\n", index->name,
|
||||||
cnt, err); */
|
cnt, err); */
|
||||||
|
if (ret == DB_SUCCESS) {
|
||||||
|
srv_n_rows_read++;
|
||||||
|
}
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ retry:
|
|||||||
&(node->pcur), &mtr);
|
&(node->pcur), &mtr);
|
||||||
ut_a(success);
|
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
|
/* The delete operation may fail if we have little
|
||||||
file space left: TODO: easiest to crash the database
|
file space left: TODO: easiest to crash the database
|
||||||
@ -174,7 +174,7 @@ row_undo_ins_remove_sec_low(
|
|||||||
} else {
|
} else {
|
||||||
ut_ad(mode == BTR_MODIFY_TREE);
|
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);
|
btr_pcur_close(&pcur);
|
||||||
|
@ -179,7 +179,11 @@ row_undo_mod_remove_clust_low(
|
|||||||
} else {
|
} else {
|
||||||
ut_ad(mode == BTR_MODIFY_TREE);
|
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
|
/* The delete operation may fail if we have little
|
||||||
file space left: TODO: easiest to crash the database
|
file space left: TODO: easiest to crash the database
|
||||||
@ -356,7 +360,8 @@ row_undo_mod_del_mark_or_remove_sec_low(
|
|||||||
} else {
|
} else {
|
||||||
ut_ad(mode == BTR_MODIFY_TREE);
|
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
|
/* The delete operation may fail if we have little
|
||||||
file space left: TODO: easiest to crash the database
|
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,
|
found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
|
||||||
&mtr);
|
&mtr);
|
||||||
if (!found) {
|
if (!found) {
|
||||||
err_buf = mem_alloc(1000);
|
err_buf = mem_alloc(1000);
|
||||||
dtuple_sprintf(err_buf, 900, entry);
|
dtuple_sprintf(err_buf, 900, entry);
|
||||||
|
|
||||||
fprintf(stderr, "InnoDB: error in sec index entry del undo in\n"
|
fprintf(stderr, "InnoDB: error in sec index entry del undo in\n"
|
||||||
"InnoDB: index %s table %s\n", index->name,
|
"InnoDB: index %s table %s\n", index->name,
|
||||||
index->table->name);
|
index->table->name);
|
||||||
fprintf(stderr, "InnoDB: tuple %s\n", err_buf);
|
fprintf(stderr, "InnoDB: tuple %s\n", err_buf);
|
||||||
|
|
||||||
rec_sprintf(err_buf, 900, btr_pcur_get_rec(&pcur));
|
rec_sprintf(err_buf, 900, btr_pcur_get_rec(&pcur));
|
||||||
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
||||||
|
|
||||||
fprintf(stderr, "InnoDB: Make a detailed bug report and send it\n");
|
fprintf(stderr,
|
||||||
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
|
"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 {
|
} else {
|
||||||
btr_cur = btr_pcur_get_btr_cur(&pcur);
|
btr_cur = btr_pcur_get_btr_cur(&pcur);
|
||||||
|
|
||||||
|
@ -840,32 +840,31 @@ row_upd_sec_index_entry(
|
|||||||
rec = btr_cur_get_rec(btr_cur);
|
rec = btr_cur_get_rec(btr_cur);
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
|
err_buf = mem_alloc(1000);
|
||||||
|
dtuple_sprintf(err_buf, 900, entry);
|
||||||
|
|
||||||
err_buf = mem_alloc(1000);
|
fprintf(stderr, "InnoDB: error in sec index entry update in\n"
|
||||||
dtuple_sprintf(err_buf, 900, entry);
|
"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"
|
rec_sprintf(err_buf, 900, rec);
|
||||||
"InnoDB: index %s table %s\n", index->name,
|
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
||||||
index->table->name);
|
|
||||||
fprintf(stderr, "InnoDB: tuple %s\n", err_buf);
|
|
||||||
|
|
||||||
rec_sprintf(err_buf, 900, rec);
|
fprintf(stderr,
|
||||||
fprintf(stderr, "InnoDB: record %s\n", err_buf);
|
"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");
|
mem_free(err_buf);
|
||||||
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
|
|
||||||
|
|
||||||
mem_free(err_buf);
|
|
||||||
} else {
|
} 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
|
if (!rec_get_deleted_flag(rec)) {
|
||||||
delete marked if we return after a lock wait in
|
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
|
||||||
row_ins_index_entry below */
|
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);
|
btr_pcur_close(&pcur);
|
||||||
@ -907,7 +906,7 @@ row_upd_sec_step(
|
|||||||
|| (node->state == UPD_NODE_UPDATE_SOME_SEC));
|
|| (node->state == UPD_NODE_UPDATE_SOME_SEC));
|
||||||
ut_ad(!(node->index->type & DICT_CLUSTERED));
|
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,
|
|| row_upd_changes_ord_field(node->row, node->index,
|
||||||
node->update)) {
|
node->update)) {
|
||||||
err = row_upd_sec_index_entry(node, thr);
|
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 */
|
que_thr_t* thr, /* in: query thread */
|
||||||
mtr_t* mtr) /* in: mtr; gets committed here */
|
mtr_t* mtr) /* in: mtr; gets committed here */
|
||||||
{
|
{
|
||||||
|
mem_heap_t* heap;
|
||||||
btr_pcur_t* pcur;
|
btr_pcur_t* pcur;
|
||||||
btr_cur_t* btr_cur;
|
btr_cur_t* btr_cur;
|
||||||
trx_t* trx;
|
trx_t* trx;
|
||||||
dict_table_t* table;
|
dict_table_t* table;
|
||||||
mem_heap_t* heap;
|
|
||||||
dtuple_t* entry;
|
dtuple_t* entry;
|
||||||
ulint* ext_vec;
|
|
||||||
ulint n_ext_vec;
|
|
||||||
ulint err;
|
ulint err;
|
||||||
|
|
||||||
ut_ad(node);
|
ut_ad(node);
|
||||||
@ -961,17 +958,20 @@ row_upd_clust_rec_by_insert(
|
|||||||
|
|
||||||
return(err);
|
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);
|
mtr_commit(mtr);
|
||||||
|
|
||||||
node->state = UPD_NODE_INSERT_CLUSTERED;
|
node->state = UPD_NODE_INSERT_CLUSTERED;
|
||||||
|
|
||||||
heap = mem_heap_create(1024);
|
heap = mem_heap_create(500);
|
||||||
|
|
||||||
ext_vec = mem_heap_alloc(heap,
|
|
||||||
sizeof(ulint) * dtuple_get_n_fields(node->row));
|
|
||||||
n_ext_vec = 0;
|
|
||||||
|
|
||||||
entry = row_build_index_entry(node->row, index, heap);
|
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);
|
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,
|
err = row_ins_index_entry(index, entry, node->ext_vec,
|
||||||
node->n_ext_vec, thr);
|
node->n_ext_vec, thr);
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
@ -111,7 +111,14 @@ ibool srv_print_buf_io = FALSE;
|
|||||||
ibool srv_print_log_io = FALSE;
|
ibool srv_print_log_io = FALSE;
|
||||||
ibool srv_print_latch_waits = 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_monitor = FALSE;
|
||||||
|
ibool srv_print_innodb_lock_monitor = FALSE;
|
||||||
|
ibool srv_print_innodb_tablespace_monitor = FALSE;
|
||||||
|
|
||||||
/* The parameters below are obsolete: */
|
/* 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_array_size = ULINT_MAX;
|
||||||
ulint srv_test_n_mutexes = 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
|
IMPLEMENTATION OF THE SERVER MAIN PROGRAM
|
||||||
=========================================
|
=========================================
|
||||||
@ -1926,23 +1938,25 @@ loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
background_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 */
|
is quiet */
|
||||||
|
|
||||||
current_time = time(NULL);
|
current_time = time(NULL);
|
||||||
|
|
||||||
if (srv_print_innodb_monitor
|
if (difftime(current_time, last_monitor_time) > 15) {
|
||||||
&& difftime(current_time, last_monitor_time) > 8) {
|
|
||||||
|
|
||||||
printf("================================\n");
|
last_monitor_time = time(NULL);
|
||||||
last_monitor_time = time(NULL);
|
|
||||||
|
if (srv_print_innodb_monitor) {
|
||||||
|
|
||||||
|
printf("=====================================\n");
|
||||||
ut_print_timestamp(stdout);
|
ut_print_timestamp(stdout);
|
||||||
|
|
||||||
printf(" INNODB MONITOR OUTPUT\n"
|
printf(" INNODB MONITOR OUTPUT\n"
|
||||||
"================================\n");
|
"=====================================\n");
|
||||||
printf("--------------------------\n"
|
printf("------------\n"
|
||||||
"LOCKS HELD BY TRANSACTIONS\n"
|
"TRANSACTIONS\n"
|
||||||
"--------------------------\n");
|
"------------\n");
|
||||||
lock_print_info();
|
lock_print_info();
|
||||||
printf("-----------------------------------------------\n"
|
printf("-----------------------------------------------\n"
|
||||||
"CURRENT SEMAPHORES RESERVED AND SEMAPHORE WAITS\n"
|
"CURRENT SEMAPHORES RESERVED AND SEMAPHORE WAITS\n"
|
||||||
@ -1955,9 +1969,38 @@ background_loop:
|
|||||||
"BUFFER POOL\n"
|
"BUFFER POOL\n"
|
||||||
"-----------\n");
|
"-----------\n");
|
||||||
buf_print_io();
|
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"
|
printf("----------------------------\n"
|
||||||
"END OF INNODB MONITOR OUTPUT\n"
|
"END OF INNODB MONITOR OUTPUT\n"
|
||||||
"============================\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);
|
mutex_enter(&kernel_mutex);
|
||||||
@ -2009,8 +2052,18 @@ background_loop:
|
|||||||
}
|
}
|
||||||
mutex_exit(&kernel_mutex);
|
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);
|
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);
|
mutex_enter(&kernel_mutex);
|
||||||
if (srv_activity_count != old_activity_count) {
|
if (srv_activity_count != old_activity_count) {
|
||||||
mutex_exit(&kernel_mutex);
|
mutex_exit(&kernel_mutex);
|
||||||
@ -2038,12 +2091,7 @@ background_loop:
|
|||||||
|
|
||||||
/* mem_print_new_info();
|
/* 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
|
#ifdef UNIV_SEARCH_PERF_STAT
|
||||||
/* btr_search_print_info(); */
|
/* btr_search_print_info(); */
|
||||||
#endif
|
#endif
|
||||||
|
@ -67,8 +67,6 @@ os_file_t files[1000];
|
|||||||
mutex_t ios_mutex;
|
mutex_t ios_mutex;
|
||||||
ulint ios;
|
ulint ios;
|
||||||
|
|
||||||
#define SRV_MAX_N_IO_THREADS 1000
|
|
||||||
|
|
||||||
ulint n[SRV_MAX_N_IO_THREADS + 5];
|
ulint n[SRV_MAX_N_IO_THREADS + 5];
|
||||||
os_thread_id_t thread_ids[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);
|
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))
|
#if !(defined(WIN_ASYNC_IO) || defined(POSIX_ASYNC_IO))
|
||||||
/* In simulated aio we currently have use only for 4 threads */
|
/* 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 */
|
sync_cell_t* cell) /* in: sync cell */
|
||||||
{
|
{
|
||||||
char* str = NULL;
|
mutex_t* mutex;
|
||||||
ulint type;
|
rw_lock_t* rwlock;
|
||||||
|
char* str = NULL;
|
||||||
|
ulint type;
|
||||||
|
|
||||||
type = cell->request_type;
|
type = cell->request_type;
|
||||||
|
|
||||||
if (type == SYNC_MUTEX) {
|
if (type == SYNC_MUTEX) {
|
||||||
str = "MUTEX ENTER";
|
str = "MUTEX ENTER";
|
||||||
} else if (type == RW_LOCK_EX) {
|
mutex = (mutex_t*)cell->wait_object;
|
||||||
str = "X-LOCK";
|
|
||||||
} else if (type == RW_LOCK_SHARED) {
|
printf("Mutex created in file %s line %lu",
|
||||||
str = "S-LOCK";
|
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 {
|
} else {
|
||||||
ut_error;
|
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->wait_object,
|
||||||
(ulint)cell->thread,
|
(ulint)cell->thread,
|
||||||
str, cell->file, cell->line);
|
str, cell->file, cell->line);
|
||||||
|
@ -99,6 +99,8 @@ trx_rollback_for_mysql(
|
|||||||
return(DB_SUCCESS);
|
return(DB_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trx->op_info = "rollback";
|
||||||
|
|
||||||
/* Tell Innobase server that there might be work for
|
/* Tell Innobase server that there might be work for
|
||||||
utility threads: */
|
utility threads: */
|
||||||
|
|
||||||
@ -111,6 +113,8 @@ trx_rollback_for_mysql(
|
|||||||
|
|
||||||
srv_active_wake_master_thread();
|
srv_active_wake_master_thread();
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +134,8 @@ trx_rollback_last_sql_stat_for_mysql(
|
|||||||
return(DB_SUCCESS);
|
return(DB_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trx->op_info = "rollback of SQL statement";
|
||||||
|
|
||||||
/* Tell Innobase server that there might be work for
|
/* Tell Innobase server that there might be work for
|
||||||
utility threads: */
|
utility threads: */
|
||||||
|
|
||||||
@ -144,6 +150,8 @@ trx_rollback_last_sql_stat_for_mysql(
|
|||||||
|
|
||||||
srv_active_wake_master_thread();
|
srv_active_wake_master_thread();
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,6 +511,7 @@ trx_sys_init_at_db_start(void)
|
|||||||
TRX_SYS_TRX_ID_WRITE_MARGIN),
|
TRX_SYS_TRX_ID_WRITE_MARGIN),
|
||||||
2 * 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();
|
trx_lists_init_at_db_start();
|
||||||
|
|
||||||
if (UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
|
if (UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
|
||||||
|
@ -24,6 +24,12 @@ Created 3/26/1996 Heikki Tuuri
|
|||||||
#include "thr0loc.h"
|
#include "thr0loc.h"
|
||||||
#include "btr0sea.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 */
|
/* Dummy session used currently in MySQL interface */
|
||||||
sess_t* trx_dummy_sess = NULL;
|
sess_t* trx_dummy_sess = NULL;
|
||||||
|
|
||||||
@ -58,11 +64,15 @@ trx_create(
|
|||||||
|
|
||||||
trx = mem_alloc(sizeof(trx_t));
|
trx = mem_alloc(sizeof(trx_t));
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
trx->type = TRX_USER;
|
trx->type = TRX_USER;
|
||||||
trx->conc_state = TRX_NOT_STARTED;
|
trx->conc_state = TRX_NOT_STARTED;
|
||||||
|
|
||||||
trx->dict_operation = FALSE;
|
trx->dict_operation = FALSE;
|
||||||
|
|
||||||
|
trx->mysql_thd = NULL;
|
||||||
|
|
||||||
trx->n_mysql_tables_in_use = 0;
|
trx->n_mysql_tables_in_use = 0;
|
||||||
trx->mysql_n_tables_locked = 0;
|
trx->mysql_n_tables_locked = 0;
|
||||||
|
|
||||||
@ -129,6 +139,8 @@ trx_allocate_for_mysql(void)
|
|||||||
|
|
||||||
trx_n_mysql_transactions++;
|
trx_n_mysql_transactions++;
|
||||||
|
|
||||||
|
UT_LIST_ADD_FIRST(mysql_trx_list, trx_sys->mysql_trx_list, trx);
|
||||||
|
|
||||||
mutex_exit(&kernel_mutex);
|
mutex_exit(&kernel_mutex);
|
||||||
|
|
||||||
trx->mysql_thread_id = os_thread_get_curr_id();
|
trx->mysql_thread_id = os_thread_get_curr_id();
|
||||||
@ -144,11 +156,11 @@ trx_search_latch_release_if_reserved(
|
|||||||
/*=================================*/
|
/*=================================*/
|
||||||
trx_t* trx) /* in: transaction */
|
trx_t* trx) /* in: transaction */
|
||||||
{
|
{
|
||||||
if (trx->has_search_latch) {
|
if (trx->has_search_latch) {
|
||||||
rw_lock_s_unlock(&btr_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);
|
mutex_enter(&kernel_mutex);
|
||||||
|
|
||||||
|
UT_LIST_REMOVE(mysql_trx_list, trx_sys->mysql_trx_list, trx);
|
||||||
|
|
||||||
trx_free(trx);
|
trx_free(trx);
|
||||||
|
|
||||||
ut_a(trx_n_mysql_transactions > 0);
|
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
|
sig to the transaction, we must here make sure that trx has been
|
||||||
started. */
|
started. */
|
||||||
|
|
||||||
|
trx->op_info = "committing";
|
||||||
|
|
||||||
trx_start_if_not_started(trx);
|
trx_start_if_not_started(trx);
|
||||||
|
|
||||||
mutex_enter(&kernel_mutex);
|
mutex_enter(&kernel_mutex);
|
||||||
@ -1276,6 +1292,8 @@ trx_commit_for_mysql(
|
|||||||
|
|
||||||
mutex_exit(&kernel_mutex);
|
mutex_exit(&kernel_mutex);
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1295,3 +1313,78 @@ trx_mark_sql_stat_end(
|
|||||||
|
|
||||||
mutex_exit(&kernel_mutex);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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
|
Gets the InnoDB transaction handle for a MySQL handler object, creates
|
||||||
an InnoDB transaction struct if the corresponding MySQL thread struct still
|
an InnoDB transaction struct if the corresponding MySQL thread struct still
|
||||||
@ -199,6 +240,8 @@ check_trx_exists(
|
|||||||
dbug_assert(thd != NULL);
|
dbug_assert(thd != NULL);
|
||||||
trx = trx_allocate_for_mysql();
|
trx = trx_allocate_for_mysql();
|
||||||
|
|
||||||
|
trx->mysql_thd = thd;
|
||||||
|
|
||||||
thd->transaction.all.innobase_tid = trx;
|
thd->transaction.all.innobase_tid = trx;
|
||||||
|
|
||||||
/* The execution of a single SQL statement is denoted by
|
/* 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) {
|
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
|
||||||
trx_commit_for_mysql(trx);
|
trx_commit_for_mysql(trx);
|
||||||
trx_mark_sql_stat_end(trx);
|
trx_mark_sql_stat_end_do_not_start_new(trx);
|
||||||
} else {
|
} else {
|
||||||
trx_mark_sql_stat_end(trx);
|
trx_mark_sql_stat_end(trx);
|
||||||
}
|
}
|
||||||
@ -672,6 +715,7 @@ innobase_rollback(
|
|||||||
|
|
||||||
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
|
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
|
||||||
error = trx_rollback_for_mysql(trx);
|
error = trx_rollback_for_mysql(trx);
|
||||||
|
trx_mark_sql_stat_end_do_not_start_new(trx);
|
||||||
} else {
|
} else {
|
||||||
error = trx_rollback_last_sql_stat_for_mysql(trx);
|
error = trx_rollback_last_sql_stat_for_mysql(trx);
|
||||||
trx_mark_sql_stat_end(trx);
|
trx_mark_sql_stat_end(trx);
|
||||||
@ -1334,8 +1378,15 @@ ha_innobase::write_row(
|
|||||||
autoincrement field */
|
autoincrement field */
|
||||||
|
|
||||||
auto_inc = table->next_number_field->val_int();
|
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) {
|
if (auto_inc != 0) {
|
||||||
/* This call will calculate the max of the
|
/* This call will calculate the max of the
|
||||||
@ -2221,29 +2272,29 @@ ha_innobase::external_lock(
|
|||||||
if (trx->n_mysql_tables_in_use == 0) {
|
if (trx->n_mysql_tables_in_use == 0) {
|
||||||
trx_mark_sql_stat_end(trx);
|
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++;
|
trx->n_mysql_tables_in_use++;
|
||||||
|
|
||||||
if (prebuilt->select_lock_type != LOCK_NONE) {
|
if (prebuilt->select_lock_type != LOCK_NONE) {
|
||||||
|
|
||||||
trx->mysql_n_tables_locked++;
|
trx->mysql_n_tables_locked++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trx->n_mysql_tables_in_use--;
|
trx->n_mysql_tables_in_use--;
|
||||||
|
|
||||||
if (trx->n_mysql_tables_in_use == 0) {
|
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
|
if (!(thd->options
|
||||||
& (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))) {
|
& (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))) {
|
||||||
innobase_commit(thd, trx);
|
innobase_commit(thd, trx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2639,6 +2690,10 @@ ha_innobase::records_in_range(
|
|||||||
|
|
||||||
DBUG_ENTER("records_in_range");
|
DBUG_ENTER("records_in_range");
|
||||||
|
|
||||||
|
if (prebuilt->trx) {
|
||||||
|
prebuilt->trx->op_info = "estimating range size";
|
||||||
|
}
|
||||||
|
|
||||||
active_index = keynr;
|
active_index = keynr;
|
||||||
|
|
||||||
key = table->key_info + active_index;
|
key = table->key_info + active_index;
|
||||||
@ -2671,6 +2726,10 @@ ha_innobase::records_in_range(
|
|||||||
|
|
||||||
my_free((char*) key_val_buff2, MYF(0));
|
my_free((char*) key_val_buff2, MYF(0));
|
||||||
|
|
||||||
|
if (prebuilt->trx) {
|
||||||
|
prebuilt->trx->op_info = "";
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_RETURN((ha_rows) n_rows);
|
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;
|
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||||
dict_table_t* ib_table;
|
dict_table_t* ib_table;
|
||||||
|
|
||||||
|
if (prebuilt->trx) {
|
||||||
|
prebuilt->trx->op_info =
|
||||||
|
"estimating upper bound of table size";
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_ENTER("info");
|
DBUG_ENTER("info");
|
||||||
|
|
||||||
ib_table = prebuilt->table;
|
ib_table = prebuilt->table;
|
||||||
@ -2702,6 +2766,10 @@ ha_innobase::estimate_number_of_rows(void)
|
|||||||
|
|
||||||
/* The minimum clustered index record size is 20 bytes */
|
/* The minimum clustered index record size is 20 bytes */
|
||||||
|
|
||||||
|
if (prebuilt->trx) {
|
||||||
|
prebuilt->trx->op_info = "";
|
||||||
|
}
|
||||||
|
|
||||||
return((ha_rows) (1000 + data_file_length / 20));
|
return((ha_rows) (1000 + data_file_length / 20));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2740,6 +2808,10 @@ ha_innobase::info(
|
|||||||
|
|
||||||
DBUG_ENTER("info");
|
DBUG_ENTER("info");
|
||||||
|
|
||||||
|
if (prebuilt->trx) {
|
||||||
|
prebuilt->trx->op_info = "calculating table stats";
|
||||||
|
}
|
||||||
|
|
||||||
ib_table = prebuilt->table;
|
ib_table = prebuilt->table;
|
||||||
|
|
||||||
if (flag & HA_STATUS_TIME) {
|
if (flag & HA_STATUS_TIME) {
|
||||||
@ -2802,6 +2874,10 @@ ha_innobase::info(
|
|||||||
trx_get_error_info(prebuilt->trx));
|
trx_get_error_info(prebuilt->trx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prebuilt->trx) {
|
||||||
|
prebuilt->trx->op_info = "";
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user