Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
46305b00
Commit
46305b00
authored
Dec 13, 2017
by
Marko Mäkelä
Browse files
Options
Browse Files
Download
Plain Diff
Merge 10.0 into 10.1
parents
b93a87f1
b1977a39
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
345 additions
and
158 deletions
+345
-158
mysql-test/suite/innodb/r/recovery_shutdown.result
mysql-test/suite/innodb/r/recovery_shutdown.result
+56
-0
mysql-test/suite/innodb/t/recovery_shutdown.test
mysql-test/suite/innodb/t/recovery_shutdown.test
+57
-0
storage/innobase/include/trx0roll.h
storage/innobase/include/trx0roll.h
+8
-1
storage/innobase/row/row0undo.cc
storage/innobase/row/row0undo.cc
+8
-0
storage/innobase/trx/trx0roll.cc
storage/innobase/trx/trx0roll.cc
+88
-74
storage/innobase/trx/trx0undo.cc
storage/innobase/trx/trx0undo.cc
+12
-4
storage/xtradb/include/trx0roll.h
storage/xtradb/include/trx0roll.h
+8
-1
storage/xtradb/row/row0undo.cc
storage/xtradb/row/row0undo.cc
+8
-0
storage/xtradb/trx/trx0roll.cc
storage/xtradb/trx/trx0roll.cc
+88
-74
storage/xtradb/trx/trx0undo.cc
storage/xtradb/trx/trx0undo.cc
+12
-4
No files found.
mysql-test/suite/innodb/r/recovery_shutdown.result
0 → 100644
View file @
46305b00
#
# MDEV-13797 InnoDB may hang if shutdown is initiated soon after startup
# while rolling back recovered incomplete transactions
#
CREATE TABLE t (a INT) ENGINE=InnoDB;
BEGIN;
COMMIT;
CREATE TABLE t8 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
BEGIN;
INSERT INTO t8 (a) SELECT NULL FROM t;
UPDATE t8 SET a=a+100, b=a;
DELETE FROM t8;
CREATE TABLE t7 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
BEGIN;
INSERT INTO t7 (a) SELECT NULL FROM t;
UPDATE t7 SET a=a+100, b=a;
DELETE FROM t7;
CREATE TABLE t6 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
BEGIN;
INSERT INTO t6 (a) SELECT NULL FROM t;
UPDATE t6 SET a=a+100, b=a;
DELETE FROM t6;
CREATE TABLE t5 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
BEGIN;
INSERT INTO t5 (a) SELECT NULL FROM t;
UPDATE t5 SET a=a+100, b=a;
DELETE FROM t5;
CREATE TABLE t4 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
BEGIN;
INSERT INTO t4 (a) SELECT NULL FROM t;
UPDATE t4 SET a=a+100, b=a;
DELETE FROM t4;
CREATE TABLE t3 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
BEGIN;
INSERT INTO t3 (a) SELECT NULL FROM t;
UPDATE t3 SET a=a+100, b=a;
DELETE FROM t3;
CREATE TABLE t2 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
BEGIN;
INSERT INTO t2 (a) SELECT NULL FROM t;
UPDATE t2 SET a=a+100, b=a;
DELETE FROM t2;
CREATE TABLE t1 (a SERIAL, b INT UNIQUE, c INT UNIQUE) ENGINE=InnoDB;
BEGIN;
INSERT INTO t1 (a) SELECT NULL FROM t;
UPDATE t1 SET a=a+100, b=a;
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;
CREATE TABLE u(a SERIAL) ENGINE=INNODB;
# Kill and restart
DROP TABLE t,u;
mysql-test/suite/innodb/t/recovery_shutdown.test
0 → 100644
View file @
46305b00
--
source
include
/
have_innodb
.
inc
--
source
include
/
not_embedded
.
inc
--
echo
#
--
echo
# MDEV-13797 InnoDB may hang if shutdown is initiated soon after startup
--
echo
# while rolling back recovered incomplete transactions
--
echo
#
CREATE
TABLE
t
(
a
INT
)
ENGINE
=
InnoDB
;
let
$size
=
100
;
let
$trx
=
8
;
let
$c
=
$size
;
BEGIN
;
--
disable_query_log
while
(
$c
)
{
INSERT
INTO
t
VALUES
();
dec
$c
;
}
--
enable_query_log
COMMIT
;
let
$c
=
$trx
;
while
(
$c
)
{
connect
(
con
$c
,
localhost
,
root
,,);
eval
CREATE
TABLE
t
$c
(
a
SERIAL
,
b
INT
UNIQUE
,
c
INT
UNIQUE
)
ENGINE
=
InnoDB
;
BEGIN
;
eval
INSERT
INTO
t
$c
(
a
)
SELECT
NULL
FROM
t
;
eval
UPDATE
t
$c
SET
a
=
a
+
$size
,
b
=
a
;
eval
DELETE
FROM
t
$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
SET
GLOBAL
innodb_flush_log_at_trx_commit
=
1
;
CREATE
TABLE
u
(
a
SERIAL
)
ENGINE
=
INNODB
;
--
source
include
/
kill_and_restart_mysqld
.
inc
--
source
include
/
restart_mysqld
.
inc
--
disable_query_log
let
$c
=
$trx
;
while
(
$c
)
{
disconnect
con
$c
;
eval
DROP
TABLE
t
$c
;
dec
$c
;
}
--
enable_query_log
DROP
TABLE
t
,
u
;
storage/innobase/include/trx0roll.h
View file @
46305b00
/*****************************************************************************
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
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 "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
...
...
@@ -103,6 +105,11 @@ trx_undo_rec_release(
/*=================*/
trx_t
*
trx
,
/*!< in/out: transaction */
undo_no_t
undo_no
);
/*!< in: undo number */
/** Report progress when rolling back a row of a recovered transaction.
@return whether the rollback should be aborted due to pending shutdown */
UNIV_INTERN
bool
trx_roll_must_shutdown
();
/*******************************************************************//**
Rollback or clean up any incomplete transactions which were
encountered in crash recovery. If the transaction already was
...
...
storage/innobase/row/row0undo.cc
View file @
46305b00
/*****************************************************************************
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
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -348,6 +349,13 @@ row_undo_step(
ut_ad
(
que_node_get_type
(
node
)
==
QUE_NODE_UNDO
);
if
(
UNIV_UNLIKELY
(
trx
==
trx_roll_crash_recv_trx
)
&&
trx_roll_must_shutdown
())
{
/* Shutdown has been initiated. */
trx
->
error_state
=
DB_INTERRUPTED
;
return
(
NULL
);
}
err
=
row_undo
(
node
,
thr
);
trx
->
error_state
=
err
;
...
...
storage/innobase/trx/trx0roll.cc
View file @
46305b00
...
...
@@ -24,6 +24,9 @@ Transaction rollback
Created 3/26/1996 Heikki Tuuri
*******************************************************/
#include "my_config.h"
#include <my_systemd.h>
#include "trx0roll.h"
#ifdef UNIV_NONINL
...
...
@@ -55,14 +58,7 @@ rollback */
bool
trx_rollback_or_clean_is_active
;
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
static
const
trx_t
*
trx_roll_crash_recv_trx
=
NULL
;
/** 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. */
static
undo_no_t
trx_roll_max_undo_no
;
/** Auxiliary variable which tells the previous progress % we printed */
static
ulint
trx_roll_progress_printed_pct
;
const
trx_t
*
trx_roll_crash_recv_trx
;
/****************************************************************//**
Finishes a transaction rollback. */
...
...
@@ -552,8 +548,6 @@ trx_rollback_active(
que_thr_t
*
thr
;
roll_node_t
*
roll_node
;
dict_table_t
*
table
;
ib_int64_t
rows_to_undo
;
const
char
*
unit
=
""
;
ibool
dictionary_locked
=
FALSE
;
heap
=
mem_heap_create
(
512
);
...
...
@@ -572,30 +566,8 @@ trx_rollback_active(
ut_a
(
thr
==
que_fork_start_command
(
fork
));
mutex_enter
(
&
trx_sys
->
mutex
);
trx_roll_crash_recv_trx
=
trx
;
trx_roll_max_undo_no
=
trx
->
undo_no
;
trx_roll_progress_printed_pct
=
0
;
rows_to_undo
=
trx_roll_max_undo_no
;
mutex_exit
(
&
trx_sys
->
mutex
);
if
(
rows_to_undo
>
1000000000
)
{
rows_to_undo
=
rows_to_undo
/
1000000
;
unit
=
"M"
;
}
ut_print_timestamp
(
stderr
);
fprintf
(
stderr
,
" InnoDB: Rolling back trx with id "
TRX_ID_FMT
", %lu%s"
" rows to undo
\n
"
,
trx
->
id
,
(
ulong
)
rows_to_undo
,
unit
);
if
(
trx_get_dict_operation
(
trx
)
!=
TRX_DICT_OP_NONE
)
{
row_mysql_lock_data_dictionary
(
trx
);
dictionary_locked
=
TRUE
;
...
...
@@ -606,6 +578,14 @@ trx_rollback_active(
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
));
/* Free the memory reserved by the undo graph */
...
...
@@ -650,13 +630,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
)
{
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
);
trx_roll_crash_recv_trx
=
NULL
;
...
...
@@ -673,7 +654,7 @@ ibool
trx_rollback_resurrected
(
/*=====================*/
trx_t
*
trx
,
/*!< in: transaction to rollback or clean */
ibool
all
)
/*!< in
: FALSE=roll back dictionary transactions;
ibool
*
all
)
/*!< in/out
: FALSE=roll back dictionary transactions;
TRUE=roll back all non-PREPARED transactions */
{
ut_ad
(
mutex_own
(
&
trx_sys
->
mutex
));
...
...
@@ -684,16 +665,15 @@ trx_rollback_resurrected(
to accidentally clean up a non-recovered transaction here. */
trx_mutex_enter
(
trx
);
bool
is_recovered
=
trx
->
is_recovered
;
trx_state_t
state
=
trx
->
state
;
trx_mutex_exit
(
trx
);
if
(
!
is_recovered
)
{
if
(
!
trx
->
is_recovered
)
{
func_exit:
trx_mutex_exit
(
trx
);
return
(
FALSE
);
}
switch
(
state
)
{
switch
(
trx
->
state
)
{
case
TRX_STATE_COMMITTED_IN_MEMORY
:
trx_mutex_exit
(
trx
);
mutex_exit
(
&
trx_sys
->
mutex
);
fprintf
(
stderr
,
"InnoDB: Cleaning up trx with id "
TRX_ID_FMT
"
\n
"
,
...
...
@@ -702,21 +682,83 @@ trx_rollback_resurrected(
trx_free_for_background
(
trx
);
return
(
TRUE
);
case
TRX_STATE_ACTIVE
:
if
(
all
||
trx_get_dict_operation
(
trx
)
!=
TRX_DICT_OP_NONE
)
{
if
(
!
srv_undo_sources
&&
srv_fast_shutdown
)
{
fake_prepared:
trx
->
state
=
TRX_STATE_PREPARED
;
trx_sys
->
n_prepared_trx
++
;
trx_sys
->
n_prepared_recovered_trx
++
;
*
all
=
FALSE
;
goto
func_exit
;
}
trx_mutex_exit
(
trx
);
if
(
*
all
||
trx_get_dict_operation
(
trx
)
!=
TRX_DICT_OP_NONE
)
{
mutex_exit
(
&
trx_sys
->
mutex
);
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
);
return
(
TRUE
);
}
return
(
FALSE
);
case
TRX_STATE_PREPARED
:
return
(
FALSE
)
;
goto
func_exit
;
case
TRX_STATE_NOT_STARTED
:
break
;
}
ut_error
;
return
(
FALSE
);
goto
func_exit
;
}
/** Report progress when rolling back a row of a recovered transaction.
@return whether the rollback should be aborted due to pending shutdown */
UNIV_INTERN
bool
trx_roll_must_shutdown
()
{
const
trx_t
*
trx
=
trx_roll_crash_recv_trx
;
ut_ad
(
trx
);
ut_ad
(
trx_state_eq
(
trx
,
TRX_STATE_ACTIVE
));
if
(
trx_get_dict_operation
(
trx
)
==
TRX_DICT_OP_NONE
&&
!
srv_undo_sources
&&
srv_fast_shutdown
)
{
return
true
;
}
ib_time_t
time
=
ut_time
();
mutex_enter
(
&
trx_sys
->
mutex
);
mutex_enter
(
&
recv_sys
->
mutex
);
if
(
recv_sys
->
report
(
time
))
{
ulint
n_trx
=
0
,
n_rows
=
0
;
for
(
const
trx_t
*
t
=
UT_LIST_GET_FIRST
(
trx_sys
->
rw_trx_list
);
t
!=
NULL
;
t
=
UT_LIST_GET_NEXT
(
trx_list
,
t
))
{
assert_trx_in_rw_list
(
t
);
if
(
t
->
is_recovered
&&
trx_state_eq
(
t
,
TRX_STATE_ACTIVE
))
{
n_trx
++
;
n_rows
+=
t
->
undo_no
;
}
}
ib_logf
(
IB_LOG_LEVEL_INFO
,
"To roll back: "
ULINTPF
" transactions, "
ULINTPF
" rows"
,
n_trx
,
n_rows
);
sd_notifyf
(
0
,
"STATUS=To roll back: "
ULINTPF
" transactions, "
ULINTPF
" rows"
,
n_trx
,
n_rows
);
}
mutex_exit
(
&
recv_sys
->
mutex
);
mutex_exit
(
&
trx_sys
->
mutex
);
return
false
;
}
/*******************************************************************//**
...
...
@@ -763,17 +805,11 @@ trx_rollback_or_clean_recovered(
assert_trx_in_rw_list
(
trx
);
if
(
srv_shutdown_state
!=
SRV_SHUTDOWN_NONE
&&
srv_fast_shutdown
!=
0
)
{
all
=
FALSE
;
break
;
}
/* If this function does a cleanup or rollback
then it will release the trx_sys->mutex, therefore
we need to reacquire it before retrying the loop. */
if
(
trx_rollback_resurrected
(
trx
,
all
))
{
if
(
trx_rollback_resurrected
(
trx
,
&
all
))
{
mutex_enter
(
&
trx_sys
->
mutex
);
...
...
@@ -1100,7 +1136,6 @@ trx_roll_pop_top_rec_of_trx(
undo_no_t
undo_no
;
ibool
is_insert
;
trx_rseg_t
*
rseg
;
ulint
progress_pct
;
mtr_t
mtr
;
rseg
=
trx
->
rseg
;
...
...
@@ -1158,27 +1193,6 @@ trx_roll_pop_top_rec_of_trx(
ut_ad
(
undo_no
+
1
==
trx
->
undo_no
);
/* We print rollback progress info if we are in a crash recovery
and the transaction has at least 1000 row operations to undo. */
if
(
trx
==
trx_roll_crash_recv_trx
&&
trx_roll_max_undo_no
>
1000
)
{
progress_pct
=
100
-
(
ulint
)
((
undo_no
*
100
)
/
trx_roll_max_undo_no
);
if
(
progress_pct
!=
trx_roll_progress_printed_pct
)
{
if
(
trx_roll_progress_printed_pct
==
0
)
{
fprintf
(
stderr
,
"
\n
InnoDB: Progress in percents:"
" %lu"
,
(
ulong
)
progress_pct
);
}
else
{
fprintf
(
stderr
,
" %lu"
,
(
ulong
)
progress_pct
);
}
fflush
(
stderr
);
trx_roll_progress_printed_pct
=
progress_pct
;
}
}
trx
->
undo_no
=
undo_no
;
if
(
!
trx_undo_arr_store_info
(
trx
,
undo_no
))
{
...
...
storage/innobase/trx/trx0undo.cc
View file @
46305b00
...
...
@@ -2023,9 +2023,13 @@ trx_undo_free_prepared(
/* fall through */
case
TRX_UNDO_ACTIVE
:
/* lock_trx_release_locks() assigns
trx->is_recovered=false */
trx->is_recovered=false and
trx->state = TRX_STATE_COMMITTED_IN_MEMORY,
also for transactions that we faked
to TRX_STATE_PREPARED in trx_rollback_resurrected(). */
ut_a
(
srv_read_only_mode
||
srv_force_recovery
>=
SRV_FORCE_NO_TRX_UNDO
);
||
srv_force_recovery
>=
SRV_FORCE_NO_TRX_UNDO
||
srv_fast_shutdown
);
break
;
default:
ut_error
;
...
...
@@ -2047,9 +2051,13 @@ trx_undo_free_prepared(
/* fall through */
case
TRX_UNDO_ACTIVE
:
/* lock_trx_release_locks() assigns
trx->is_recovered=false */
trx->is_recovered=false and
trx->state = TRX_STATE_COMMITTED_IN_MEMORY,
also for transactions that we faked
to TRX_STATE_PREPARED in trx_rollback_resurrected(). */
ut_a
(
srv_read_only_mode
||
srv_force_recovery
>=
SRV_FORCE_NO_TRX_UNDO
);
||
srv_force_recovery
>=
SRV_FORCE_NO_TRX_UNDO
||
srv_fast_shutdown
);
break
;
default:
ut_error
;
...
...
storage/xtradb/include/trx0roll.h
View file @
46305b00
/*****************************************************************************
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
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 "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
...
...
@@ -104,6 +106,11 @@ trx_undo_rec_release(
/*=================*/
trx_t
*
trx
,
/*!< in/out: transaction */
undo_no_t
undo_no
);
/*!< in: undo number */
/** Report progress when rolling back a row of a recovered transaction.
@return whether the rollback should be aborted due to pending shutdown */
UNIV_INTERN
bool
trx_roll_must_shutdown
();
/*******************************************************************//**
Rollback or clean up any incomplete transactions which were
encountered in crash recovery. If the transaction already was
...
...
storage/xtradb/row/row0undo.cc
View file @
46305b00
/*****************************************************************************
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
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -348,6 +349,13 @@ row_undo_step(
ut_ad
(
que_node_get_type
(
node
)
==
QUE_NODE_UNDO
);
if
(
UNIV_UNLIKELY
(
trx
==
trx_roll_crash_recv_trx
)
&&
trx_roll_must_shutdown
())
{
/* Shutdown has been initiated. */
trx
->
error_state
=
DB_INTERRUPTED
;
return
(
NULL
);
}
err
=
row_undo
(
node
,
thr
);
trx
->
error_state
=
err
;
...
...
storage/xtradb/trx/trx0roll.cc
View file @
46305b00
...
...
@@ -24,6 +24,9 @@ Transaction rollback
Created 3/26/1996 Heikki Tuuri
*******************************************************/
#include "my_config.h"
#include <my_systemd.h>
#include "trx0roll.h"
#ifdef UNIV_NONINL
...
...
@@ -60,14 +63,7 @@ rollback */
bool
trx_rollback_or_clean_is_active
;
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
static
const
trx_t
*
trx_roll_crash_recv_trx
=
NULL
;
/** 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. */
static
undo_no_t
trx_roll_max_undo_no
;
/** Auxiliary variable which tells the previous progress % we printed */
static
ulint
trx_roll_progress_printed_pct
;
const
trx_t
*
trx_roll_crash_recv_trx
;
/****************************************************************//**
Finishes a transaction rollback. */
...
...
@@ -564,8 +560,6 @@ trx_rollback_active(
que_thr_t
*
thr
;
roll_node_t
*
roll_node
;
dict_table_t
*
table
;
ib_int64_t
rows_to_undo
;
const
char
*
unit
=
""
;
ibool
dictionary_locked
=
FALSE
;
heap
=
mem_heap_create
(
512
);
...
...
@@ -584,30 +578,8 @@ trx_rollback_active(
ut_a
(
thr
==
que_fork_start_command
(
fork
));
mutex_enter
(
&
trx_sys
->
mutex
);
trx_roll_crash_recv_trx
=
trx
;
trx_roll_max_undo_no
=
trx
->
undo_no
;
trx_roll_progress_printed_pct
=
0
;
rows_to_undo
=
trx_roll_max_undo_no
;
mutex_exit
(
&
trx_sys
->
mutex
);
if
(
rows_to_undo
>
1000000000
)
{
rows_to_undo
=
rows_to_undo
/
1000000
;
unit
=
"M"
;
}
ut_print_timestamp
(
stderr
);
fprintf
(
stderr
,
" InnoDB: Rolling back trx with id "
TRX_ID_FMT
", %lu%s"
" rows to undo
\n
"
,
trx
->
id
,
(
ulong
)
rows_to_undo
,
unit
);
if
(
trx_get_dict_operation
(
trx
)
!=
TRX_DICT_OP_NONE
)
{
row_mysql_lock_data_dictionary
(
trx
);
dictionary_locked
=
TRUE
;
...
...
@@ -618,6 +590,14 @@ trx_rollback_active(
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
));
/* Free the memory reserved by the undo graph */
...
...
@@ -662,13 +642,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
)
{
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
);
trx_roll_crash_recv_trx
=
NULL
;
...
...
@@ -685,7 +666,7 @@ ibool
trx_rollback_resurrected
(
/*=====================*/
trx_t
*
trx
,
/*!< in: transaction to rollback or clean */
ibool
all
)
/*!< in
: FALSE=roll back dictionary transactions;
ibool
*
all
)
/*!< in/out
: FALSE=roll back dictionary transactions;
TRUE=roll back all non-PREPARED transactions */
{
ut_ad
(
mutex_own
(
&
trx_sys
->
mutex
));
...
...
@@ -696,16 +677,15 @@ trx_rollback_resurrected(
to accidentally clean up a non-recovered transaction here. */
trx_mutex_enter
(
trx
);
bool
is_recovered
=
trx
->
is_recovered
;
trx_state_t
state
=
trx
->
state
;
trx_mutex_exit
(
trx
);
if
(
!
is_recovered
)
{
if
(
!
trx
->
is_recovered
)
{
func_exit:
trx_mutex_exit
(
trx
);
return
(
FALSE
);
}
switch
(
state
)
{
switch
(
trx
->
state
)
{
case
TRX_STATE_COMMITTED_IN_MEMORY
:
trx_mutex_exit
(
trx
);
mutex_exit
(
&
trx_sys
->
mutex
);
fprintf
(
stderr
,
"InnoDB: Cleaning up trx with id "
TRX_ID_FMT
"
\n
"
,
...
...
@@ -714,21 +694,83 @@ trx_rollback_resurrected(
trx_free_for_background
(
trx
);
return
(
TRUE
);
case
TRX_STATE_ACTIVE
:
if
(
all
||
trx_get_dict_operation
(
trx
)
!=
TRX_DICT_OP_NONE
)
{
if
(
!
srv_undo_sources
&&
srv_fast_shutdown
)
{
fake_prepared:
trx
->
state
=
TRX_STATE_PREPARED
;
trx_sys
->
n_prepared_trx
++
;
trx_sys
->
n_prepared_recovered_trx
++
;
*
all
=
FALSE
;
goto
func_exit
;
}
trx_mutex_exit
(
trx
);
if
(
*
all
||
trx_get_dict_operation
(
trx
)
!=
TRX_DICT_OP_NONE
)
{
mutex_exit
(
&
trx_sys
->
mutex
);
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
);
return
(
TRUE
);
}
return
(
FALSE
);
case
TRX_STATE_PREPARED
:
return
(
FALSE
)
;
goto
func_exit
;
case
TRX_STATE_NOT_STARTED
:
break
;
}
ut_error
;
return
(
FALSE
);
goto
func_exit
;
}
/** Report progress when rolling back a row of a recovered transaction.
@return whether the rollback should be aborted due to pending shutdown */
UNIV_INTERN
bool
trx_roll_must_shutdown
()
{
const
trx_t
*
trx
=
trx_roll_crash_recv_trx
;
ut_ad
(
trx
);
ut_ad
(
trx_state_eq
(
trx
,
TRX_STATE_ACTIVE
));
if
(
trx_get_dict_operation
(
trx
)
==
TRX_DICT_OP_NONE
&&
!
srv_undo_sources
&&
srv_fast_shutdown
)
{
return
true
;
}
ib_time_t
time
=
ut_time
();
mutex_enter
(
&
trx_sys
->
mutex
);
mutex_enter
(
&
recv_sys
->
mutex
);
if
(
recv_sys
->
report
(
time
))
{
ulint
n_trx
=
0
,
n_rows
=
0
;
for
(
const
trx_t
*
t
=
UT_LIST_GET_FIRST
(
trx_sys
->
rw_trx_list
);
t
!=
NULL
;
t
=
UT_LIST_GET_NEXT
(
trx_list
,
t
))
{
assert_trx_in_rw_list
(
t
);
if
(
t
->
is_recovered
&&
trx_state_eq
(
t
,
TRX_STATE_ACTIVE
))
{
n_trx
++
;
n_rows
+=
t
->
undo_no
;
}
}
ib_logf
(
IB_LOG_LEVEL_INFO
,
"To roll back: "
ULINTPF
" transactions, "
ULINTPF
" rows"
,
n_trx
,
n_rows
);
sd_notifyf
(
0
,
"STATUS=To roll back: "
ULINTPF
" transactions, "
ULINTPF
" rows"
,
n_trx
,
n_rows
);
}
mutex_exit
(
&
recv_sys
->
mutex
);
mutex_exit
(
&
trx_sys
->
mutex
);
return
false
;
}
/*******************************************************************//**
...
...
@@ -775,17 +817,11 @@ trx_rollback_or_clean_recovered(
assert_trx_in_rw_list
(
trx
);
if
(
srv_shutdown_state
!=
SRV_SHUTDOWN_NONE
&&
srv_fast_shutdown
!=
0
)
{
all
=
FALSE
;
break
;
}
/* If this function does a cleanup or rollback
then it will release the trx_sys->mutex, therefore
we need to reacquire it before retrying the loop. */
if
(
trx_rollback_resurrected
(
trx
,
all
))
{
if
(
trx_rollback_resurrected
(
trx
,
&
all
))
{
mutex_enter
(
&
trx_sys
->
mutex
);
...
...
@@ -1118,7 +1154,6 @@ trx_roll_pop_top_rec_of_trx(
undo_no_t
undo_no
;
ibool
is_insert
;
trx_rseg_t
*
rseg
;
ulint
progress_pct
;
mtr_t
mtr
;
rseg
=
trx
->
rseg
;
...
...
@@ -1176,27 +1211,6 @@ trx_roll_pop_top_rec_of_trx(
ut_ad
(
undo_no
+
1
==
trx
->
undo_no
);
/* We print rollback progress info if we are in a crash recovery
and the transaction has at least 1000 row operations to undo. */
if
(
trx
==
trx_roll_crash_recv_trx
&&
trx_roll_max_undo_no
>
1000
)
{
progress_pct
=
100
-
(
ulint
)
((
undo_no
*
100
)
/
trx_roll_max_undo_no
);
if
(
progress_pct
!=
trx_roll_progress_printed_pct
)
{
if
(
trx_roll_progress_printed_pct
==
0
)
{
fprintf
(
stderr
,
"
\n
InnoDB: Progress in percents:"
" %lu"
,
(
ulong
)
progress_pct
);
}
else
{
fprintf
(
stderr
,
" %lu"
,
(
ulong
)
progress_pct
);
}
fflush
(
stderr
);
trx_roll_progress_printed_pct
=
progress_pct
;
}
}
trx
->
undo_no
=
undo_no
;
if
(
!
trx_undo_arr_store_info
(
trx
,
undo_no
))
{
...
...
storage/xtradb/trx/trx0undo.cc
View file @
46305b00
...
...
@@ -2023,10 +2023,14 @@ trx_undo_free_prepared(
/* fall through */
case
TRX_UNDO_ACTIVE
:
/* lock_trx_release_locks() assigns
trx->is_recovered=false */
trx->is_recovered=false and
trx->state = TRX_STATE_COMMITTED_IN_MEMORY,
also for transactions that we faked
to TRX_STATE_PREPARED in trx_rollback_resurrected(). */
ut_a
(
srv_read_only_mode
||
srv_apply_log_only
||
srv_force_recovery
>=
SRV_FORCE_NO_TRX_UNDO
);
||
srv_force_recovery
>=
SRV_FORCE_NO_TRX_UNDO
||
srv_fast_shutdown
);
break
;
default:
ut_error
;
...
...
@@ -2048,10 +2052,14 @@ trx_undo_free_prepared(
/* fall through */
case
TRX_UNDO_ACTIVE
:
/* lock_trx_release_locks() assigns
trx->is_recovered=false */
trx->is_recovered=false and
trx->state = TRX_STATE_COMMITTED_IN_MEMORY,
also for transactions that we faked
to TRX_STATE_PREPARED in trx_rollback_resurrected(). */
ut_a
(
srv_read_only_mode
||
srv_apply_log_only
||
srv_force_recovery
>=
SRV_FORCE_NO_TRX_UNDO
);
||
srv_force_recovery
>=
SRV_FORCE_NO_TRX_UNDO
||
srv_fast_shutdown
);
break
;
default:
ut_error
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment