1
/*****************************************************************************
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
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
17
*****************************************************************************/
19
/**************************************************//**
1
/******************************************************
21
2
Transaction rollback
23
6
Created 3/26/1996 Heikki Tuuri
24
7
*******************************************************/
44
27
#include "lock0lock.h"
45
28
#include "pars0pars.h"
47
/** This many pages must be undone before a truncate is tried within
30
/* This many pages must be undone before a truncate is tried within rollback */
49
31
#define TRX_ROLL_TRUNC_THRESHOLD 1
51
/** In crash recovery, the current trx to be rolled back */
33
/* In crash recovery, the current trx to be rolled back */
52
34
static trx_t* trx_roll_crash_recv_trx = NULL;
54
/** In crash recovery we set this to the undo n:o of the current trx to be
36
/* In crash recovery we set this to the undo n:o of the current trx to be
55
37
rolled back. Then we can print how many % the rollback has progressed. */
56
38
static ib_int64_t trx_roll_max_undo_no;
58
/** Auxiliary variable which tells the previous progress % we printed */
40
/* Auxiliary variable which tells the previous progress % we printed */
59
41
static ulint trx_roll_progress_printed_pct;
61
/*******************************************************************//**
62
Rollback a transaction used in MySQL.
63
@return error code or DB_SUCCESS */
43
/***********************************************************************
44
Rollback a transaction used in MySQL. */
66
47
trx_general_rollback_for_mysql(
67
48
/*===========================*/
68
trx_t* trx, /*!< in: transaction handle */
69
ibool partial,/*!< in: TRUE if partial rollback requested */
70
trx_savept_t* savept) /*!< in: pointer to savepoint undo number, if
49
/* out: error code or DB_SUCCESS */
50
trx_t* trx, /* in: transaction handle */
51
ibool partial,/* in: TRUE if partial rollback requested */
52
trx_savept_t* savept) /* in: pointer to savepoint undo number, if
71
53
partial rollback requested */
55
#ifndef UNIV_HOTBACKUP
75
58
roll_node_t* roll_node;
121
104
srv_active_wake_master_thread();
123
106
return((int) trx->error_state);
107
#else /* UNIV_HOTBACKUP */
108
/* This function depends on MySQL code that is not included in
109
InnoDB Hot Backup builds. Besides, this function should never
110
be called in InnoDB Hot Backup. */
113
#endif /* UNIV_HOTBACKUP */
126
/*******************************************************************//**
127
Rollback a transaction used in MySQL.
128
@return error code or DB_SUCCESS */
116
/***********************************************************************
117
Rollback a transaction used in MySQL. */
131
120
trx_rollback_for_mysql(
132
121
/*===================*/
133
trx_t* trx) /*!< in: transaction handle */
122
/* out: error code or DB_SUCCESS */
123
trx_t* trx) /* in: transaction handle */
155
/*******************************************************************//**
156
Rollback the latest SQL statement for MySQL.
157
@return error code or DB_SUCCESS */
145
/***********************************************************************
146
Rollback the latest SQL statement for MySQL. */
160
149
trx_rollback_last_sql_stat_for_mysql(
161
150
/*=================================*/
162
trx_t* trx) /*!< in: transaction handle */
151
/* out: error code or DB_SUCCESS */
152
trx_t* trx) /* in: transaction handle */
183
/*******************************************************************//**
184
Frees a single savepoint struct. */
187
trx_roll_savepoint_free(
188
/*=====================*/
189
trx_t* trx, /*!< in: transaction handle */
190
trx_named_savept_t* savep) /*!< in: savepoint to free */
193
ut_a(UT_LIST_GET_LEN(trx->trx_savepoints) > 0);
195
UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep);
196
mem_free(savep->name);
200
/*******************************************************************//**
201
Frees savepoint structs starting from savep, if savep == NULL then
202
free all savepoints. */
173
/***********************************************************************
174
Frees savepoint structs. */
205
177
trx_roll_savepoints_free(
206
178
/*=====================*/
207
trx_t* trx, /*!< in: transaction handle */
208
trx_named_savept_t* savep) /*!< in: free all savepoints > this one;
179
trx_t* trx, /* in: transaction handle */
180
trx_named_savept_t* savep) /* in: free all savepoints > this one;
209
181
if this is NULL, free all savepoints
220
192
while (savep != NULL) {
221
193
next_savep = UT_LIST_GET_NEXT(trx_savepoints, savep);
223
trx_roll_savepoint_free(trx, savep);
195
UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep);
196
mem_free(savep->name);
225
199
savep = next_savep;
229
/*******************************************************************//**
203
/***********************************************************************
230
204
Rolls back a transaction back to a named savepoint. Modifications after the
231
205
savepoint are undone but InnoDB does NOT release the corresponding locks
232
206
which are stored in memory. If a lock is 'implicit', that is, a new inserted
233
207
row holds a lock where the lock information is carried by the trx id stored in
234
208
the row, these locks are naturally released in the rollback. Savepoints which
235
were set after this savepoint are deleted.
236
@return if no savepoint of the name found then DB_NO_SAVEPOINT,
237
otherwise DB_SUCCESS */
209
were set after this savepoint are deleted. */
240
212
trx_rollback_to_savepoint_for_mysql(
241
213
/*================================*/
242
trx_t* trx, /*!< in: transaction handle */
243
const char* savepoint_name, /*!< in: savepoint name */
244
ib_int64_t* mysql_binlog_cache_pos) /*!< out: the MySQL binlog cache
214
/* out: if no savepoint
215
of the name found then
217
otherwise DB_SUCCESS */
218
trx_t* trx, /* in: transaction handle */
219
const char* savepoint_name, /* in: savepoint name */
220
ib_int64_t* mysql_binlog_cache_pos) /* out: the MySQL binlog cache
245
221
position corresponding to this
246
222
savepoint; MySQL needs this
247
223
information to remove the
297
/*******************************************************************//**
273
/***********************************************************************
298
274
Creates a named savepoint. If the transaction is not yet started, starts it.
299
275
If there is already a savepoint of the same name, this call erases that old
300
276
savepoint and replaces it with a new. Savepoints are deleted in a transaction
302
@return always DB_SUCCESS */
277
commit or rollback. */
305
280
trx_savepoint_for_mysql(
306
281
/*====================*/
307
trx_t* trx, /*!< in: transaction handle */
308
const char* savepoint_name, /*!< in: savepoint name */
309
ib_int64_t binlog_cache_pos) /*!< in: MySQL binlog cache
282
/* out: always DB_SUCCESS */
283
trx_t* trx, /* in: transaction handle */
284
const char* savepoint_name, /* in: savepoint name */
285
ib_int64_t binlog_cache_pos) /* in: MySQL binlog cache
310
286
position corresponding to this
311
287
connection at the time of the
352
328
return(DB_SUCCESS);
355
/*******************************************************************//**
356
Releases only the named savepoint. Savepoints which were set after this
357
savepoint are left as is.
358
@return if no savepoint of the name found then DB_NO_SAVEPOINT,
359
otherwise DB_SUCCESS */
331
/***********************************************************************
332
Releases a named savepoint. Savepoints which
333
were set after this savepoint are deleted. */
362
336
trx_release_savepoint_for_mysql(
363
337
/*============================*/
364
trx_t* trx, /*!< in: transaction handle */
365
const char* savepoint_name) /*!< in: savepoint name */
338
/* out: if no savepoint
339
of the name found then
341
otherwise DB_SUCCESS */
342
trx_t* trx, /* in: transaction handle */
343
const char* savepoint_name) /* in: savepoint name */
367
345
trx_named_savept_t* savep;
369
347
savep = UT_LIST_GET_FIRST(trx->trx_savepoints);
371
/* Search for the savepoint by name and free if found. */
372
349
while (savep != NULL) {
373
350
if (0 == ut_strcmp(savep->name, savepoint_name)) {
374
trx_roll_savepoint_free(trx, savep);
377
354
savep = UT_LIST_GET_NEXT(trx_savepoints, savep);
380
return(DB_NO_SAVEPOINT);
359
return(DB_NO_SAVEPOINT);
362
/* We can now free all savepoints strictly later than this one */
364
trx_roll_savepoints_free(trx, savep);
366
/* Now we can free this savepoint too */
368
UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep);
370
mem_free(savep->name);
383
/*******************************************************************//**
376
/***********************************************************************
384
377
Determines if this transaction is rolling back an incomplete transaction
386
@return TRUE if trx is an incomplete transaction that is being rolled
387
back in crash recovery */
378
in crash recovery. */
392
const trx_t* trx) /*!< in: transaction */
383
/* out: TRUE if trx is an incomplete
384
transaction that is being rolled back
386
const trx_t* trx) /* in: transaction */
394
388
return(trx == trx_roll_crash_recv_trx);
397
/*******************************************************************//**
398
Returns a transaction savepoint taken at this point in time.
391
/***********************************************************************
392
Returns a transaction savepoint taken at this point in time. */
404
trx_t* trx) /*!< in: transaction */
398
trx_t* trx) /* in: transaction */
406
400
trx_savept_t savept;
530
524
trx_roll_crash_recv_trx = NULL;
533
/*******************************************************************//**
527
/***********************************************************************
534
528
Rollback or clean up any incomplete transactions which were
535
529
encountered in crash recovery. If the transaction already was
536
530
committed, then we clean up a possible insert undo log. If the
537
531
transaction was not yet committed, then we roll it back.
538
Note: this is done in a background thread.
539
@return a dummy parameter */
532
Note: this is done in a background thread. */
542
535
trx_rollback_or_clean_all_recovered(
543
536
/*================================*/
537
/* out: a dummy parameter */
544
538
void* arg __attribute__((unused)))
545
/*!< in: a dummy parameter required by
539
/* in: a dummy parameter required by
546
540
os_thread_create */
605
599
OS_THREAD_DUMMY_RETURN;
608
/*******************************************************************//**
609
Creates an undo number array.
610
@return own: undo number array */
602
/***********************************************************************
603
Creates an undo number array. */
613
606
trx_undo_arr_create(void)
639
/*******************************************************************//**
632
/***********************************************************************
640
633
Frees an undo number array. */
643
636
trx_undo_arr_free(
644
637
/*==============*/
645
trx_undo_arr_t* arr) /*!< in: undo number array */
638
trx_undo_arr_t* arr) /* in: undo number array */
647
640
ut_ad(arr->n_used == 0);
649
642
mem_heap_free(arr->heap);
652
/*******************************************************************//**
653
Stores info of an undo log record to the array if it is not stored yet.
654
@return FALSE if the record already existed in the array */
645
/***********************************************************************
646
Stores info of an undo log record to the array if it is not stored yet. */
657
649
trx_undo_arr_store_info(
658
650
/*====================*/
659
trx_t* trx, /*!< in: transaction */
660
undo_no_t undo_no)/*!< in: undo number */
651
/* out: FALSE if the record already existed in the
653
trx_t* trx, /* in: transaction */
654
dulint undo_no)/* in: undo number */
662
656
trx_undo_inf_t* cell;
663
657
trx_undo_inf_t* stored_here;
713
/*******************************************************************//**
707
/***********************************************************************
714
708
Removes an undo number from the array. */
717
711
trx_undo_arr_remove_info(
718
712
/*=====================*/
719
trx_undo_arr_t* arr, /*!< in: undo number array */
720
undo_no_t undo_no)/*!< in: undo number */
713
trx_undo_arr_t* arr, /* in: undo number array */
714
dulint undo_no)/* in: undo number */
722
716
trx_undo_inf_t* cell;
747
/*******************************************************************//**
748
Gets the biggest undo number in an array.
749
@return biggest value, ut_dulint_zero if the array is empty */
741
/***********************************************************************
742
Gets the biggest undo number in an array. */
752
745
trx_undo_arr_get_biggest(
753
746
/*=====================*/
754
trx_undo_arr_t* arr) /*!< in: undo number array */
747
/* out: biggest value, ut_dulint_zero if
748
the array is empty */
749
trx_undo_arr_t* arr) /* in: undo number array */
756
751
trx_undo_inf_t* cell;
783
/***********************************************************************//**
778
/***************************************************************************
784
779
Tries truncate the undo logs. */
787
782
trx_roll_try_truncate(
788
783
/*==================*/
789
trx_t* trx) /*!< in/out: transaction */
784
trx_t* trx) /* in: transaction */
791
786
trx_undo_arr_t* arr;
795
790
ut_ad(mutex_own(&(trx->undo_mutex)));
796
791
ut_ad(mutex_own(&((trx->rseg)->mutex)));
822
/***********************************************************************//**
817
/***************************************************************************
823
818
Pops the topmost undo log record in a single undo log and updates the info
824
about the topmost record in the undo log memory struct.
825
@return undo log record, the page s-latched */
819
about the topmost record in the undo log memory struct. */
828
822
trx_roll_pop_top_rec(
829
823
/*=================*/
830
trx_t* trx, /*!< in: transaction */
831
trx_undo_t* undo, /*!< in: undo log */
832
mtr_t* mtr) /*!< in: mtr */
824
/* out: undo log record, the page s-latched */
825
trx_t* trx, /* in: transaction */
826
trx_undo_t* undo, /* in: undo log */
827
mtr_t* mtr) /* in: mtr */
834
829
page_t* undo_page;
868
863
return(undo_page + offset);
871
/********************************************************************//**
866
/************************************************************************
872
867
Pops the topmost record when the two undo logs of a transaction are seen
873
868
as a single stack of records ordered by their undo numbers. Inserts the
874
869
undo number of the popped undo record to the array of currently processed
875
870
undo numbers in the transaction. When the query thread finishes processing
876
of this undo record, it must be released with trx_undo_rec_release.
877
@return undo log record copied to heap, NULL if none left, or if the
878
undo number of the top record would be less than the limit */
871
of this undo record, it must be released with trx_undo_rec_release. */
881
874
trx_roll_pop_top_rec_of_trx(
882
875
/*========================*/
883
trx_t* trx, /*!< in: transaction */
884
undo_no_t limit, /*!< in: least undo number we need */
885
roll_ptr_t* roll_ptr,/*!< out: roll pointer to undo record */
886
mem_heap_t* heap) /*!< in: memory heap where copied */
876
/* out: undo log record copied to heap, NULL
877
if none left, or if the undo number of the
878
top record would be less than the limit */
879
trx_t* trx, /* in: transaction */
880
dulint limit, /* in: least undo number we need */
881
dulint* roll_ptr,/* out: roll pointer to undo record */
882
mem_heap_t* heap) /* in: memory heap where copied */
888
884
trx_undo_t* undo;
889
885
trx_undo_t* ins_undo;
890
886
trx_undo_t* upd_undo;
891
887
trx_undo_rec_t* undo_rec;
892
888
trx_undo_rec_t* undo_rec_copy;
895
891
trx_rseg_t* rseg;
896
892
ulint progress_pct;
1000
996
return(undo_rec_copy);
1003
/********************************************************************//**
999
/************************************************************************
1004
1000
Reserves an undo log record for a query thread to undo. This should be
1005
1001
called if the query thread gets the undo log record not using the pop
1007
@return TRUE if succeeded */
1010
1005
trx_undo_rec_reserve(
1011
1006
/*=================*/
1012
trx_t* trx, /*!< in/out: transaction */
1013
undo_no_t undo_no)/*!< in: undo number of the record */
1007
/* out: TRUE if succeeded */
1008
trx_t* trx, /* in: transaction */
1009
dulint undo_no)/* in: undo number of the record */
1026
/*******************************************************************//**
1022
/***********************************************************************
1027
1023
Releases a reserved undo record. */
1030
1026
trx_undo_rec_release(
1031
1027
/*=================*/
1032
trx_t* trx, /*!< in/out: transaction */
1033
undo_no_t undo_no)/*!< in: undo number */
1028
trx_t* trx, /* in: transaction */
1029
dulint undo_no)/* in: undo number */
1035
1031
trx_undo_arr_t* arr;
1043
1039
mutex_exit(&(trx->undo_mutex));
1046
/*********************************************************************//**
1042
/*************************************************************************
1047
1043
Starts a rollback operation. */
1052
trx_t* trx, /*!< in: transaction */
1053
trx_sig_t* sig, /*!< in: signal starting the rollback */
1054
que_thr_t** next_thr)/*!< in/out: next query thread to run;
1048
trx_t* trx, /* in: transaction */
1049
trx_sig_t* sig, /* in: signal starting the rollback */
1050
que_thr_t** next_thr)/* in/out: next query thread to run;
1055
1051
if the value which is passed in is
1056
1052
a pointer to a NULL pointer, then the
1057
1053
calling function can start running
1117
/****************************************************************//**
1113
/********************************************************************
1118
1114
Builds an undo 'query' graph for a transaction. The actual rollback is
1119
1115
performed by executing this query graph like a query subprocedure call.
1120
1116
The reply about the completion of the rollback will be sent by this
1122
@return own: the query graph */
1125
1120
trx_roll_graph_build(
1126
1121
/*=================*/
1127
trx_t* trx) /*!< in: trx handle */
1122
/* out, own: the query graph */
1123
trx_t* trx) /* in: trx handle */
1129
1125
mem_heap_t* heap;
1130
1126
que_fork_t* fork;
1149
/*********************************************************************//**
1145
/*************************************************************************
1150
1146
Finishes error processing after the necessary partial rollback has been
1154
1150
trx_finish_error_processing(
1155
1151
/*========================*/
1156
trx_t* trx) /*!< in: transaction */
1152
trx_t* trx) /* in: transaction */
1158
1154
trx_sig_t* sig;
1159
1155
trx_sig_t* next_sig;
1176
1172
trx->que_state = TRX_QUE_RUNNING;
1179
/*********************************************************************//**
1175
/*************************************************************************
1180
1176
Finishes a partial rollback operation. */
1183
1179
trx_finish_partial_rollback_off_kernel(
1184
1180
/*===================================*/
1185
trx_t* trx, /*!< in: transaction */
1186
que_thr_t** next_thr)/*!< in/out: next query thread to run;
1181
trx_t* trx, /* in: transaction */
1182
que_thr_t** next_thr)/* in/out: next query thread to run;
1187
1183
if the value which is passed in is a pointer
1188
1184
to a NULL pointer, then the calling function
1189
1185
can start running a new query thread; if this
1204
1200
trx->que_state = TRX_QUE_RUNNING;
1207
/****************************************************************//**
1203
/********************************************************************
1208
1204
Finishes a transaction rollback. */
1211
1207
trx_finish_rollback_off_kernel(
1212
1208
/*===========================*/
1213
que_t* graph, /*!< in: undo graph which can now be freed */
1214
trx_t* trx, /*!< in: transaction */
1215
que_thr_t** next_thr)/*!< in/out: next query thread to run;
1209
que_t* graph, /* in: undo graph which can now be freed */
1210
trx_t* trx, /* in: transaction */
1211
que_thr_t** next_thr)/* in/out: next query thread to run;
1216
1212
if the value which is passed in is
1217
1213
a pointer to a NULL pointer, then the
1218
1214
calling function can start running
1275
/*********************************************************************//**
1276
Creates a rollback command node struct.
1277
@return own: rollback node struct */
1271
/*************************************************************************
1272
Creates a rollback command node struct. */
1280
1275
roll_node_create(
1281
1276
/*=============*/
1282
mem_heap_t* heap) /*!< in: mem heap where created */
1277
/* out, own: rollback node struct */
1278
mem_heap_t* heap) /* in: mem heap where created */
1284
1280
roll_node_t* node;
1295
/***********************************************************//**
1296
Performs an execution step for a rollback command node in a query graph.
1297
@return query thread to run next, or NULL */
1291
/***************************************************************
1292
Performs an execution step for a rollback command node in a query graph. */
1300
1295
trx_rollback_step(
1301
1296
/*==============*/
1302
que_thr_t* thr) /*!< in: query thread */
1297
/* out: query thread to run next, or NULL */
1298
que_thr_t* thr) /* in: query thread */
1304
1300
roll_node_t* node;