1
1
/*****************************************************************************
3
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
3
Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
14
this program; if not, write to the Free Software Foundation, Inc.,
15
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17
17
*****************************************************************************/
44
44
#include "row0mysql.h"
45
45
#include "log0log.h"
47
/*************************************************************************
48
IMPORTANT NOTE: Any operation that generates redo MUST check that there
49
is enough space in the redo log before for that operation. This is
50
done by calling log_free_check(). The reason for checking the
51
availability of the redo log space before the start of the operation is
52
that we MUST not hold any synchonization objects when performing the
54
If you make a change in this module make sure that no codepath is
55
introduced where a call to log_free_check() is bypassed. */
47
57
/********************************************************************//**
48
58
Creates a purge node to a query graph.
49
59
@return own: purge node */
376
387
marked record if that record contained an externally stored field. */
379
row_purge_upd_exist_or_extern(
380
/*==========================*/
390
row_purge_upd_exist_or_extern_func(
391
/*===============================*/
393
const que_thr_t*thr, /*!< in: query thread */
394
#endif /* UNIV_DEBUG */
381
395
purge_node_t* node) /*!< in: row purge node */
383
397
mem_heap_t* heap;
402
417
while (node->index != NULL) {
403
418
index = node->index;
405
if (row_upd_changes_ord_field_binary(NULL, node->index,
420
if (row_upd_changes_ord_field_binary(node->index, node->update,
407
422
/* Build the older version of the index entry */
408
423
entry = row_build_index_entry(node->row, NULL,
504
# define row_purge_upd_exist_or_extern(thr,node) \
505
row_purge_upd_exist_or_extern_func(thr,node)
506
#else /* UNIV_DEBUG */
507
# define row_purge_upd_exist_or_extern(thr,node) \
508
row_purge_upd_exist_or_extern_func(node)
509
#endif /* UNIV_DEBUG */
488
511
/***********************************************************//**
489
512
Parses the row reference and other info in a modify undo log record.
490
513
@return TRUE if purge operation required: NOTE that then the CALLER
508
531
roll_ptr_t roll_ptr;
513
535
ut_ad(node && thr);
515
537
trx = thr_get_trx(thr);
517
ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
518
updated_extern, &undo_no, &table_id);
539
ptr = trx_undo_rec_get_pars(
540
node->undo_rec, &type, &node->cmpl_info,
541
updated_extern, &undo_no, &table_id);
519
542
node->rec_type = type;
521
544
if (type == TRX_UNDO_UPD_DEL_REC && !(*updated_extern)) {
579
603
/* Read to the partial row the fields that occur in indexes */
581
if (!(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
605
if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
582
606
ptr = trx_undo_rec_get_partial_row(
583
607
ptr, clust_index, &node->row,
584
608
type == TRX_UNDO_UPD_DEL_REC,
591
615
/***********************************************************//**
592
616
Fetches an undo log record and does the purge for the recorded operation.
593
617
If none left, or the current purge completed, returns the control to the
594
parent node, which is always a query thread node.
595
@return DB_SUCCESS if operation successfully completed, else error code */
618
parent node, which is always a query thread node. */
619
static __attribute__((nonnull))
600
623
purge_node_t* node, /*!< in: row purge node */
601
624
que_thr_t* thr) /*!< in: query thread */
605
626
ibool updated_extern;
610
trx = thr_get_trx(thr);
612
node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr,
613
&(node->reservation),
631
node->undo_rec = trx_purge_fetch_next_rec(&node->roll_ptr,
615
634
if (!node->undo_rec) {
616
635
/* Purge completed for this query thread */
618
637
thr->run_node = que_node_get_parent(node);
623
node->roll_ptr = roll_ptr;
625
if (node->undo_rec == &trx_purge_dummy_rec) {
626
purge_needed = FALSE;
628
purge_needed = row_purge_parse_undo_rec(node, &updated_extern,
630
/* If purge_needed == TRUE, we must also remember to unfreeze
642
if (node->undo_rec != &trx_purge_dummy_rec
643
&& row_purge_parse_undo_rec(node, &updated_extern, thr)) {
635
644
node->found_clust = FALSE;
637
646
node->index = dict_table_get_next_index(
643
652
} else if (updated_extern
644
653
|| node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
646
row_purge_upd_exist_or_extern(node);
655
row_purge_upd_exist_or_extern(thr, node);
649
658
if (node->found_clust) {
650
659
btr_pcur_close(&(node->pcur));
653
row_mysql_unfreeze_data_dictionary(trx);
662
row_mysql_unfreeze_data_dictionary(thr_get_trx(thr));
656
665
/* Do some cleanup */