mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-12352 InnoDB shutdown should not be blocked by a large transaction rollback
row_undo_step(), trx_rollback_active(): Abort the rollback of a recovered ordinary transaction if fast shutdown has been initiated. trx_rollback_resurrected(): Convert an aborted-rollback transaction into a fake XA PREPARE transaction, so that fast shutdown can proceed.
This commit is contained in:
@ -45,6 +45,11 @@ BEGIN;
|
|||||||
INSERT INTO t1 (a) SELECT NULL FROM t;
|
INSERT INTO t1 (a) SELECT NULL FROM t;
|
||||||
UPDATE t1 SET a=a+100, b=a;
|
UPDATE t1 SET a=a+100, b=a;
|
||||||
DELETE FROM t1;
|
DELETE FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
SET GLOBAL innodb_flush_log_at_trx_commit=1;
|
SET GLOBAL innodb_flush_log_at_trx_commit=1;
|
||||||
CREATE TABLE u(a SERIAL) ENGINE=INNODB;
|
CREATE TABLE u(a SERIAL) ENGINE=INNODB;
|
||||||
# Kill and restart
|
# Kill and restart
|
||||||
|
@ -31,6 +31,12 @@ eval DELETE FROM t$c;
|
|||||||
dec $c;
|
dec $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
INSERT INTO t1(a) SELECT NULL FROM t1;
|
||||||
|
|
||||||
--connection default
|
--connection default
|
||||||
SET GLOBAL innodb_flush_log_at_trx_commit=1;
|
SET GLOBAL innodb_flush_log_at_trx_commit=1;
|
||||||
CREATE TABLE u(a SERIAL) ENGINE=INNODB;
|
CREATE TABLE u(a SERIAL) ENGINE=INNODB;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2017, MariaDB Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -32,7 +33,8 @@ Created 3/26/1996 Heikki Tuuri
|
|||||||
#include "mtr0mtr.h"
|
#include "mtr0mtr.h"
|
||||||
#include "trx0sys.h"
|
#include "trx0sys.h"
|
||||||
|
|
||||||
extern bool trx_rollback_or_clean_is_active;
|
extern bool trx_rollback_or_clean_is_active;
|
||||||
|
extern const trx_t* trx_roll_crash_recv_trx;
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Determines if this transaction is rolling back an incomplete transaction
|
Determines if this transaction is rolling back an incomplete transaction
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2017, MariaDB Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -44,6 +45,7 @@ Created 1/8/1997 Heikki Tuuri
|
|||||||
#include "row0upd.h"
|
#include "row0upd.h"
|
||||||
#include "row0mysql.h"
|
#include "row0mysql.h"
|
||||||
#include "srv0srv.h"
|
#include "srv0srv.h"
|
||||||
|
#include "srv0start.h"
|
||||||
|
|
||||||
/* How to undo row operations?
|
/* How to undo row operations?
|
||||||
(1) For an insert, we have stored a prefix of the clustered index record
|
(1) For an insert, we have stored a prefix of the clustered index record
|
||||||
@ -348,6 +350,14 @@ row_undo_step(
|
|||||||
|
|
||||||
ut_ad(que_node_get_type(node) == QUE_NODE_UNDO);
|
ut_ad(que_node_get_type(node) == QUE_NODE_UNDO);
|
||||||
|
|
||||||
|
if (UNIV_UNLIKELY(trx == trx_roll_crash_recv_trx)
|
||||||
|
&& trx_get_dict_operation(trx) == TRX_DICT_OP_NONE
|
||||||
|
&& !srv_undo_sources && srv_fast_shutdown) {
|
||||||
|
/* Shutdown has been initiated. */
|
||||||
|
trx->error_state = DB_INTERRUPTED;
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
err = row_undo(node, thr);
|
err = row_undo(node, thr);
|
||||||
|
|
||||||
trx->error_state = err;
|
trx->error_state = err;
|
||||||
|
@ -55,7 +55,7 @@ rollback */
|
|||||||
bool trx_rollback_or_clean_is_active;
|
bool trx_rollback_or_clean_is_active;
|
||||||
|
|
||||||
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
|
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
|
||||||
static const trx_t* trx_roll_crash_recv_trx = NULL;
|
const trx_t* trx_roll_crash_recv_trx;
|
||||||
|
|
||||||
/** In crash recovery we set this to the undo n:o of the current trx to be
|
/** In crash recovery we set this to the undo n:o of the current trx to be
|
||||||
rolled back. Then we can print how many % the rollback has progressed. */
|
rolled back. Then we can print how many % the rollback has progressed. */
|
||||||
@ -605,6 +605,14 @@ trx_rollback_active(
|
|||||||
|
|
||||||
que_run_threads(roll_node->undo_thr);
|
que_run_threads(roll_node->undo_thr);
|
||||||
|
|
||||||
|
if (trx->error_state != DB_SUCCESS) {
|
||||||
|
ut_ad(trx->error_state == DB_INTERRUPTED);
|
||||||
|
ut_ad(!srv_undo_sources);
|
||||||
|
ut_ad(srv_fast_shutdown);
|
||||||
|
ut_ad(!dictionary_locked);
|
||||||
|
goto func_exit;
|
||||||
|
}
|
||||||
|
|
||||||
trx_rollback_finish(thr_get_trx(roll_node->undo_thr));
|
trx_rollback_finish(thr_get_trx(roll_node->undo_thr));
|
||||||
|
|
||||||
/* Free the memory reserved by the undo graph */
|
/* Free the memory reserved by the undo graph */
|
||||||
@ -649,13 +657,14 @@ trx_rollback_active(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ib_logf(IB_LOG_LEVEL_INFO,
|
||||||
|
"Rollback of trx with id " TRX_ID_FMT " completed", trx->id);
|
||||||
|
|
||||||
|
func_exit:
|
||||||
if (dictionary_locked) {
|
if (dictionary_locked) {
|
||||||
row_mysql_unlock_data_dictionary(trx);
|
row_mysql_unlock_data_dictionary(trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ib_logf(IB_LOG_LEVEL_INFO,
|
|
||||||
"Rollback of trx with id " TRX_ID_FMT " completed", trx->id);
|
|
||||||
|
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
||||||
trx_roll_crash_recv_trx = NULL;
|
trx_roll_crash_recv_trx = NULL;
|
||||||
@ -700,8 +709,8 @@ func_exit:
|
|||||||
trx_free_for_background(trx);
|
trx_free_for_background(trx);
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
case TRX_STATE_ACTIVE:
|
case TRX_STATE_ACTIVE:
|
||||||
if (srv_shutdown_state != SRV_SHUTDOWN_NONE
|
if (!srv_undo_sources && srv_fast_shutdown) {
|
||||||
&& srv_fast_shutdown) {
|
fake_prepared:
|
||||||
trx->state = TRX_STATE_PREPARED;
|
trx->state = TRX_STATE_PREPARED;
|
||||||
trx_sys->n_prepared_trx++;
|
trx_sys->n_prepared_trx++;
|
||||||
trx_sys->n_prepared_recovered_trx++;
|
trx_sys->n_prepared_recovered_trx++;
|
||||||
@ -713,6 +722,14 @@ func_exit:
|
|||||||
if (*all || trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
|
if (*all || trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
|
||||||
mutex_exit(&trx_sys->mutex);
|
mutex_exit(&trx_sys->mutex);
|
||||||
trx_rollback_active(trx);
|
trx_rollback_active(trx);
|
||||||
|
if (trx->error_state != DB_SUCCESS) {
|
||||||
|
ut_ad(trx->error_state == DB_INTERRUPTED);
|
||||||
|
ut_ad(!srv_undo_sources);
|
||||||
|
ut_ad(srv_fast_shutdown);
|
||||||
|
mutex_enter(&trx_sys->mutex);
|
||||||
|
trx_mutex_enter(trx);
|
||||||
|
goto fake_prepared;
|
||||||
|
}
|
||||||
trx_free_for_background(trx);
|
trx_free_for_background(trx);
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2017, MariaDB Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -33,7 +34,8 @@ Created 3/26/1996 Heikki Tuuri
|
|||||||
#include "mtr0mtr.h"
|
#include "mtr0mtr.h"
|
||||||
#include "trx0sys.h"
|
#include "trx0sys.h"
|
||||||
|
|
||||||
extern bool trx_rollback_or_clean_is_active;
|
extern bool trx_rollback_or_clean_is_active;
|
||||||
|
extern const trx_t* trx_roll_crash_recv_trx;
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Determines if this transaction is rolling back an incomplete transaction
|
Determines if this transaction is rolling back an incomplete transaction
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2017, MariaDB Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -44,6 +45,7 @@ Created 1/8/1997 Heikki Tuuri
|
|||||||
#include "row0upd.h"
|
#include "row0upd.h"
|
||||||
#include "row0mysql.h"
|
#include "row0mysql.h"
|
||||||
#include "srv0srv.h"
|
#include "srv0srv.h"
|
||||||
|
#include "srv0start.h"
|
||||||
|
|
||||||
/* How to undo row operations?
|
/* How to undo row operations?
|
||||||
(1) For an insert, we have stored a prefix of the clustered index record
|
(1) For an insert, we have stored a prefix of the clustered index record
|
||||||
@ -348,6 +350,14 @@ row_undo_step(
|
|||||||
|
|
||||||
ut_ad(que_node_get_type(node) == QUE_NODE_UNDO);
|
ut_ad(que_node_get_type(node) == QUE_NODE_UNDO);
|
||||||
|
|
||||||
|
if (UNIV_UNLIKELY(trx == trx_roll_crash_recv_trx)
|
||||||
|
&& trx_get_dict_operation(trx) == TRX_DICT_OP_NONE
|
||||||
|
&& !srv_undo_sources && srv_fast_shutdown) {
|
||||||
|
/* Shutdown has been initiated. */
|
||||||
|
trx->error_state = DB_INTERRUPTED;
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
err = row_undo(node, thr);
|
err = row_undo(node, thr);
|
||||||
|
|
||||||
trx->error_state = err;
|
trx->error_state = err;
|
||||||
|
@ -55,7 +55,7 @@ rollback */
|
|||||||
bool trx_rollback_or_clean_is_active;
|
bool trx_rollback_or_clean_is_active;
|
||||||
|
|
||||||
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
|
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
|
||||||
static const trx_t* trx_roll_crash_recv_trx = NULL;
|
const trx_t* trx_roll_crash_recv_trx;
|
||||||
|
|
||||||
/** In crash recovery we set this to the undo n:o of the current trx to be
|
/** In crash recovery we set this to the undo n:o of the current trx to be
|
||||||
rolled back. Then we can print how many % the rollback has progressed. */
|
rolled back. Then we can print how many % the rollback has progressed. */
|
||||||
@ -605,6 +605,14 @@ trx_rollback_active(
|
|||||||
|
|
||||||
que_run_threads(roll_node->undo_thr);
|
que_run_threads(roll_node->undo_thr);
|
||||||
|
|
||||||
|
if (trx->error_state != DB_SUCCESS) {
|
||||||
|
ut_ad(trx->error_state == DB_INTERRUPTED);
|
||||||
|
ut_ad(!srv_undo_sources);
|
||||||
|
ut_ad(srv_fast_shutdown);
|
||||||
|
ut_ad(!dictionary_locked);
|
||||||
|
goto func_exit;
|
||||||
|
}
|
||||||
|
|
||||||
trx_rollback_finish(thr_get_trx(roll_node->undo_thr));
|
trx_rollback_finish(thr_get_trx(roll_node->undo_thr));
|
||||||
|
|
||||||
/* Free the memory reserved by the undo graph */
|
/* Free the memory reserved by the undo graph */
|
||||||
@ -649,13 +657,14 @@ trx_rollback_active(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ib_logf(IB_LOG_LEVEL_INFO,
|
||||||
|
"Rollback of trx with id " TRX_ID_FMT " completed", trx->id);
|
||||||
|
|
||||||
|
func_exit:
|
||||||
if (dictionary_locked) {
|
if (dictionary_locked) {
|
||||||
row_mysql_unlock_data_dictionary(trx);
|
row_mysql_unlock_data_dictionary(trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ib_logf(IB_LOG_LEVEL_INFO,
|
|
||||||
"Rollback of trx with id " TRX_ID_FMT " completed", trx->id);
|
|
||||||
|
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
||||||
trx_roll_crash_recv_trx = NULL;
|
trx_roll_crash_recv_trx = NULL;
|
||||||
@ -700,8 +709,8 @@ func_exit:
|
|||||||
trx_free_for_background(trx);
|
trx_free_for_background(trx);
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
case TRX_STATE_ACTIVE:
|
case TRX_STATE_ACTIVE:
|
||||||
if (srv_shutdown_state != SRV_SHUTDOWN_NONE
|
if (!srv_undo_sources && srv_fast_shutdown) {
|
||||||
&& srv_fast_shutdown) {
|
fake_prepared:
|
||||||
trx->state = TRX_STATE_PREPARED;
|
trx->state = TRX_STATE_PREPARED;
|
||||||
trx_sys->n_prepared_trx++;
|
trx_sys->n_prepared_trx++;
|
||||||
trx_sys->n_prepared_recovered_trx++;
|
trx_sys->n_prepared_recovered_trx++;
|
||||||
@ -713,6 +722,14 @@ func_exit:
|
|||||||
if (*all || trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
|
if (*all || trx_get_dict_operation(trx) != TRX_DICT_OP_NONE) {
|
||||||
mutex_exit(&trx_sys->mutex);
|
mutex_exit(&trx_sys->mutex);
|
||||||
trx_rollback_active(trx);
|
trx_rollback_active(trx);
|
||||||
|
if (trx->error_state != DB_SUCCESS) {
|
||||||
|
ut_ad(trx->error_state == DB_INTERRUPTED);
|
||||||
|
ut_ad(!srv_undo_sources);
|
||||||
|
ut_ad(srv_fast_shutdown);
|
||||||
|
mutex_enter(&trx_sys->mutex);
|
||||||
|
trx_mutex_enter(trx);
|
||||||
|
goto fake_prepared;
|
||||||
|
}
|
||||||
trx_free_for_background(trx);
|
trx_free_for_background(trx);
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user