Commit 4856b4ba authored by marko's avatar marko

branches/zip: Remove update-in-place-in-select from the internal SQL

interpreter.  It was only used for updating the InnoDB internal data
dictionary when renaming or dropping tables.  It could have caused
deadlocks after acquiring latches on insert buffer bitmap pages.
This and r3544 should fix Issue #135.

Furthermore, the update-in-place-in-select does not account for
compression failure.  That was not a problem yet, since the InnoDB SQL
interpreter has so far assumed ROW_FORMAT=REDUNDANT.

rb://63 approved by Heikki Tuuri
parent 3462b464
2008-12-17 The InnoDB Team
* include/row0upd.h, include/row0sel.h, pars/pars0pars.c,
row/row0upd.c, row/row0sel.c, row/row0mysql.c:
Remove update-in-place select from the internal SQL interpreter.
It was only used for updating the InnoDB internal data dictionary
when renaming or dropping tables. It could have caused deadlocks
when acquiring latches on insert buffer bitmap pages.
2008-12-17 The InnoDB Team 2008-12-17 The InnoDB Team
* include/univ.i, include/buf0buf.h, include/hash0hash.h, * include/univ.i, include/buf0buf.h, include/hash0hash.h,
......
...@@ -280,13 +280,6 @@ struct sel_node_struct{ ...@@ -280,13 +280,6 @@ struct sel_node_struct{
ibool set_x_locks; /* TRUE if the cursor is for update or ibool set_x_locks; /* TRUE if the cursor is for update or
delete, which means that a row x-lock delete, which means that a row x-lock
should be placed on the cursor row */ should be placed on the cursor row */
ibool select_will_do_update;
/* TRUE if the select is for a searched
update which can be performed in-place:
in this case the select will take care
of the update */
ulint latch_mode; /* BTR_SEARCH_LEAF, or BTR_MODIFY_LEAF
if select_will_do_update is TRUE */
ulint row_lock_mode; /* LOCK_X or LOCK_S */ ulint row_lock_mode; /* LOCK_X or LOCK_S */
ulint n_tables; /* number of tables */ ulint n_tables; /* number of tables */
ulint fetch_table; /* number of the next table to access ulint fetch_table; /* number of the next table to access
......
...@@ -292,16 +292,6 @@ row_upd_step( ...@@ -292,16 +292,6 @@ row_upd_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 */
/************************************************************************* /*************************************************************************
Performs an in-place update for the current clustered index record in
select. */
UNIV_INTERN
void
row_upd_in_place_in_select(
/*=======================*/
sel_node_t* sel_node, /* in: select node */
que_thr_t* thr, /* in: query thread */
mtr_t* mtr); /* in: mtr */
/*************************************************************************
Parses the log data of system field values. */ Parses the log data of system field values. */
UNIV_INTERN UNIV_INTERN
byte* byte*
...@@ -374,11 +364,6 @@ struct upd_node_struct{ ...@@ -374,11 +364,6 @@ struct upd_node_struct{
ibool searched_update; ibool searched_update;
/* TRUE if searched update, FALSE if /* TRUE if searched update, FALSE if
positioned */ positioned */
ibool select_will_do_update;
/* TRUE if a searched update where ordering
fields will not be updated, and the size of
the fields will not change: in this case the
select node will take care of the update */
ibool in_mysql_interface; ibool in_mysql_interface;
/* TRUE if the update node was created /* TRUE if the update node was created
for the MySQL interface */ for the MySQL interface */
......
...@@ -1032,19 +1032,6 @@ pars_update_statement( ...@@ -1032,19 +1032,6 @@ pars_update_statement(
node->pcur = &(plan->pcur); node->pcur = &(plan->pcur);
} }
if (!node->is_delete && node->searched_update
&& (node->cmpl_info & UPD_NODE_NO_SIZE_CHANGE)
&& (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
/* The select node can perform the update in-place */
ut_a(plan->asc);
node->select_will_do_update = TRUE;
sel_node->select_will_do_update = TRUE;
sel_node->latch_mode = BTR_MODIFY_LEAF;
}
return(node); return(node);
} }
......
...@@ -1200,7 +1200,6 @@ row_create_update_node_for_mysql( ...@@ -1200,7 +1200,6 @@ row_create_update_node_for_mysql(
node->in_mysql_interface = TRUE; node->in_mysql_interface = TRUE;
node->is_delete = FALSE; node->is_delete = FALSE;
node->searched_update = FALSE; node->searched_update = FALSE;
node->select_will_do_update = FALSE;
node->select = NULL; node->select = NULL;
node->pcur = btr_pcur_create_for_mysql(); node->pcur = btr_pcur_create_for_mysql();
node->table = table; node->table = table;
......
...@@ -230,9 +230,6 @@ sel_node_create( ...@@ -230,9 +230,6 @@ sel_node_create(
node->common.type = QUE_NODE_SELECT; node->common.type = QUE_NODE_SELECT;
node->state = SEL_NODE_OPEN; node->state = SEL_NODE_OPEN;
node->select_will_do_update = FALSE;
node->latch_mode = BTR_SEARCH_LEAF;
node->plans = NULL; node->plans = NULL;
return(node); return(node);
...@@ -793,7 +790,7 @@ row_sel_get_clust_rec( ...@@ -793,7 +790,7 @@ row_sel_get_clust_rec(
index = dict_table_get_first_index(plan->table); index = dict_table_get_first_index(plan->table);
btr_pcur_open_with_no_init(index, plan->clust_ref, PAGE_CUR_LE, btr_pcur_open_with_no_init(index, plan->clust_ref, PAGE_CUR_LE,
node->latch_mode, &(plan->clust_pcur), BTR_SEARCH_LEAF, &plan->clust_pcur,
0, mtr); 0, mtr);
clust_rec = btr_pcur_get_rec(&(plan->clust_pcur)); clust_rec = btr_pcur_get_rec(&(plan->clust_pcur));
...@@ -962,7 +959,6 @@ static ...@@ -962,7 +959,6 @@ static
void void
row_sel_open_pcur( row_sel_open_pcur(
/*==============*/ /*==============*/
sel_node_t* node, /* in: select node */
plan_t* plan, /* in: table plan */ plan_t* plan, /* in: table plan */
ibool search_latch_locked, ibool search_latch_locked,
/* in: TRUE if the thread currently /* in: TRUE if the thread currently
...@@ -1015,13 +1011,13 @@ row_sel_open_pcur( ...@@ -1015,13 +1011,13 @@ row_sel_open_pcur(
/* Open pcur to the index */ /* Open pcur to the index */
btr_pcur_open_with_no_init(index, plan->tuple, plan->mode, btr_pcur_open_with_no_init(index, plan->tuple, plan->mode,
node->latch_mode, &(plan->pcur), BTR_SEARCH_LEAF, &plan->pcur,
has_search_latch, mtr); has_search_latch, mtr);
} else { } else {
/* Open the cursor to the start or the end of the index /* Open the cursor to the start or the end of the index
(FALSE: no init) */ (FALSE: no init) */
btr_pcur_open_at_index_side(plan->asc, index, node->latch_mode, btr_pcur_open_at_index_side(plan->asc, index, BTR_SEARCH_LEAF,
&(plan->pcur), FALSE, mtr); &(plan->pcur), FALSE, mtr);
} }
...@@ -1043,7 +1039,6 @@ row_sel_restore_pcur_pos( ...@@ -1043,7 +1039,6 @@ row_sel_restore_pcur_pos(
function (moved to the previous, in the case function (moved to the previous, in the case
of a descending cursor) without processing of a descending cursor) without processing
again the current cursor record */ again the current cursor record */
sel_node_t* node, /* in: select node */
plan_t* plan, /* in: table plan */ plan_t* plan, /* in: table plan */
mtr_t* mtr) /* in: mtr */ mtr_t* mtr) /* in: mtr */
{ {
...@@ -1054,7 +1049,7 @@ row_sel_restore_pcur_pos( ...@@ -1054,7 +1049,7 @@ row_sel_restore_pcur_pos(
relative_position = btr_pcur_get_rel_pos(&(plan->pcur)); relative_position = btr_pcur_get_rel_pos(&(plan->pcur));
equal_position = btr_pcur_restore_position(node->latch_mode, equal_position = btr_pcur_restore_position(BTR_SEARCH_LEAF,
&(plan->pcur), mtr); &(plan->pcur), mtr);
/* If the cursor is traveling upwards, and relative_position is /* If the cursor is traveling upwards, and relative_position is
...@@ -1173,7 +1168,7 @@ row_sel_try_search_shortcut( ...@@ -1173,7 +1168,7 @@ row_sel_try_search_shortcut(
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
row_sel_open_pcur(node, plan, TRUE, mtr); row_sel_open_pcur(plan, TRUE, mtr);
rec = btr_pcur_get_rec(&(plan->pcur)); rec = btr_pcur_get_rec(&(plan->pcur));
...@@ -1274,13 +1269,6 @@ row_sel( ...@@ -1274,13 +1269,6 @@ row_sel(
ulint cost_counter = 0; ulint cost_counter = 0;
ibool cursor_just_opened; ibool cursor_just_opened;
ibool must_go_to_next; ibool must_go_to_next;
ibool leaf_contains_updates = FALSE;
/* TRUE if select_will_do_update is
TRUE and the current clustered index
leaf page has been updated during
the current mtr: mtr must be committed
at the same time as the leaf x-latch
is released */
ibool mtr_has_extra_clust_latch = FALSE; ibool mtr_has_extra_clust_latch = FALSE;
/* TRUE if the search was made using /* TRUE if the search was made using
a non-clustered index, and we had to a non-clustered index, and we had to
...@@ -1319,7 +1307,6 @@ row_sel( ...@@ -1319,7 +1307,6 @@ row_sel(
node->fetch_table changes, and after adding a row to aggregate totals node->fetch_table changes, and after adding a row to aggregate totals
and, of course, when this function is called. */ and, of course, when this function is called. */
ut_ad(leaf_contains_updates == FALSE);
ut_ad(mtr_has_extra_clust_latch == FALSE); ut_ad(mtr_has_extra_clust_latch == FALSE);
plan = sel_node_get_nth_plan(node, node->fetch_table); plan = sel_node_get_nth_plan(node, node->fetch_table);
...@@ -1394,7 +1381,7 @@ row_sel( ...@@ -1394,7 +1381,7 @@ row_sel(
/* Evaluate the expressions to build the search tuple and /* Evaluate the expressions to build the search tuple and
open the cursor */ open the cursor */
row_sel_open_pcur(node, plan, search_latch_locked, &mtr); row_sel_open_pcur(plan, search_latch_locked, &mtr);
cursor_just_opened = TRUE; cursor_just_opened = TRUE;
...@@ -1403,7 +1390,7 @@ row_sel( ...@@ -1403,7 +1390,7 @@ row_sel(
} else { } else {
/* Restore pcur position to the index */ /* Restore pcur position to the index */
must_go_to_next = row_sel_restore_pcur_pos(node, plan, &mtr); must_go_to_next = row_sel_restore_pcur_pos(plan, &mtr);
cursor_just_opened = FALSE; cursor_just_opened = FALSE;
...@@ -1744,28 +1731,6 @@ row_sel( ...@@ -1744,28 +1731,6 @@ row_sel(
ut_ad(plan->pcur.latch_mode == node->latch_mode); ut_ad(plan->pcur.latch_mode == node->latch_mode);
if (node->select_will_do_update) {
/* This is a searched update and we can do the update in-place,
saving CPU time */
row_upd_in_place_in_select(node, thr, &mtr);
leaf_contains_updates = TRUE;
/* When the database is in the online backup mode, the number
of log records for a single mtr should be small: increment the
cost counter to ensure it */
cost_counter += 1 + (SEL_COST_LIMIT / 8);
if (plan->unique_search) {
goto table_exhausted;
}
goto next_rec;
}
if ((plan->n_rows_fetched <= SEL_PREFETCH_LIMIT) if ((plan->n_rows_fetched <= SEL_PREFETCH_LIMIT)
|| plan->unique_search || plan->no_prefetch || plan->unique_search || plan->no_prefetch
|| plan->table->big_rows) { || plan->table->big_rows) {
...@@ -1799,19 +1764,6 @@ row_sel( ...@@ -1799,19 +1764,6 @@ row_sel(
goto commit_mtr_for_a_while; goto commit_mtr_for_a_while;
} }
if (leaf_contains_updates
&& btr_pcur_is_after_last_on_page(&plan->pcur)) {
/* We must commit &mtr if we are moving to a different page,
because we have done updates to the x-latched leaf page, and
the latch would be released in btr_pcur_move_to_next, without
&mtr getting committed there */
ut_ad(node->asc);
goto commit_mtr_for_a_while;
}
if (node->asc) { if (node->asc) {
moved = btr_pcur_move_to_next(&(plan->pcur), &mtr); moved = btr_pcur_move_to_next(&(plan->pcur), &mtr);
} else { } else {
...@@ -1848,7 +1800,6 @@ row_sel( ...@@ -1848,7 +1800,6 @@ row_sel(
mtr_commit(&mtr); mtr_commit(&mtr);
leaf_contains_updates = FALSE;
mtr_has_extra_clust_latch = FALSE; mtr_has_extra_clust_latch = FALSE;
next_table_no_mtr: next_table_no_mtr:
...@@ -1889,7 +1840,6 @@ row_sel( ...@@ -1889,7 +1840,6 @@ row_sel(
mtr_commit(&mtr); mtr_commit(&mtr);
leaf_contains_updates = FALSE;
mtr_has_extra_clust_latch = FALSE; mtr_has_extra_clust_latch = FALSE;
if (plan->n_rows_prefetched > 0) { if (plan->n_rows_prefetched > 0) {
...@@ -1958,7 +1908,6 @@ row_sel( ...@@ -1958,7 +1908,6 @@ row_sel(
mtr_commit(&mtr); mtr_commit(&mtr);
leaf_contains_updates = FALSE;
mtr_has_extra_clust_latch = FALSE; mtr_has_extra_clust_latch = FALSE;
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
......
...@@ -275,7 +275,6 @@ upd_node_create( ...@@ -275,7 +275,6 @@ upd_node_create(
node->common.type = QUE_NODE_UPDATE; node->common.type = QUE_NODE_UPDATE;
node->state = UPD_NODE_UPDATE_CLUSTERED; node->state = UPD_NODE_UPDATE_CLUSTERED;
node->select_will_do_update = FALSE;
node->in_mysql_interface = FALSE; node->in_mysql_interface = FALSE;
node->row = NULL; node->row = NULL;
...@@ -2151,66 +2150,3 @@ row_upd_step( ...@@ -2151,66 +2150,3 @@ row_upd_step(
return(thr); return(thr);
} }
/*************************************************************************
Performs an in-place update for the current clustered index record in
select. */
UNIV_INTERN
void
row_upd_in_place_in_select(
/*=======================*/
sel_node_t* sel_node, /* in: select node */
que_thr_t* thr, /* in: query thread */
mtr_t* mtr) /* in: mtr */
{
upd_node_t* node;
btr_pcur_t* pcur;
btr_cur_t* btr_cur;
ulint err;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
rec_offs_init(offsets_);
ut_ad(sel_node->select_will_do_update);
ut_ad(sel_node->latch_mode == BTR_MODIFY_LEAF);
ut_ad(sel_node->asc);
node = que_node_get_parent(sel_node);
ut_ad(que_node_get_type(node) == QUE_NODE_UPDATE);
pcur = node->pcur;
btr_cur = btr_pcur_get_btr_cur(pcur);
/* Copy the necessary columns from clust_rec and calculate the new
values to set */
row_upd_copy_columns(btr_pcur_get_rec(pcur),
rec_get_offsets(btr_pcur_get_rec(pcur),
btr_cur->index, offsets_,
ULINT_UNDEFINED, &heap),
UT_LIST_GET_FIRST(node->columns));
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
row_upd_eval_new_vals(node->update);
ut_ad(!rec_get_deleted_flag(
btr_pcur_get_rec(pcur),
dict_table_is_comp(btr_cur->index->table)));
ut_ad(node->cmpl_info & UPD_NODE_NO_SIZE_CHANGE);
ut_ad(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE);
ut_ad(node->select_will_do_update);
err = btr_cur_update_in_place(BTR_NO_LOCKING_FLAG, btr_cur,
node->update, node->cmpl_info,
thr, mtr);
/* TODO: the above can fail with DB_ZIP_OVERFLOW if page_zip != NULL.
However, this function row_upd_in_place_in_select() is only invoked
when executing UPDATE statements of the built-in InnoDB SQL parser.
The built-in SQL is only used for InnoDB system tables, which
always are in the old, uncompressed format (ROW_FORMAT=REDUNDANT,
comp == FALSE, page_zip == NULL). */
ut_ad(err == DB_SUCCESS);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment