mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-15772 Potential list overrun during XA recovery
InnoDB could return the same list again and again if the buffer passed to trx_recover_for_mysql() is smaller than the number of transactions that InnoDB recovered in XA PREPARE state. We introduce the transaction state TRX_PREPARED_RECOVERED, which is like TRX_PREPARED, but will be set during trx_recover_for_mysql() so that each transaction will only be returned once. Because init_server_components() is invoking ha_recover() twice, we must reset the state of the transactions back to TRX_PREPARED after returning the complete list, so that repeated traversals will see the complete list again, instead of seeing an empty list. Without this tweak, the test main.tc_heuristic_recover would hang in MariaDB 10.1.
This commit is contained in:
committed by
Marko Mäkelä
parent
cb8d888c42
commit
d5da8ae04d
310
mysql-test/suite/innodb/r/xa_debug.result
Normal file
310
mysql-test/suite/innodb/r/xa_debug.result
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
call mtr.add_suppression("Found 50 prepared XA transactions");
|
||||||
|
create table t1 (a int) engine=innodb;
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa start 'test50';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test50';
|
||||||
|
xa prepare 'test50';
|
||||||
|
xa start 'test49';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test49';
|
||||||
|
xa prepare 'test49';
|
||||||
|
xa start 'test48';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test48';
|
||||||
|
xa prepare 'test48';
|
||||||
|
xa start 'test47';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test47';
|
||||||
|
xa prepare 'test47';
|
||||||
|
xa start 'test46';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test46';
|
||||||
|
xa prepare 'test46';
|
||||||
|
xa start 'test45';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test45';
|
||||||
|
xa prepare 'test45';
|
||||||
|
xa start 'test44';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test44';
|
||||||
|
xa prepare 'test44';
|
||||||
|
xa start 'test43';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test43';
|
||||||
|
xa prepare 'test43';
|
||||||
|
xa start 'test42';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test42';
|
||||||
|
xa prepare 'test42';
|
||||||
|
xa start 'test41';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test41';
|
||||||
|
xa prepare 'test41';
|
||||||
|
xa start 'test40';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test40';
|
||||||
|
xa prepare 'test40';
|
||||||
|
xa start 'test39';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test39';
|
||||||
|
xa prepare 'test39';
|
||||||
|
xa start 'test38';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test38';
|
||||||
|
xa prepare 'test38';
|
||||||
|
xa start 'test37';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test37';
|
||||||
|
xa prepare 'test37';
|
||||||
|
xa start 'test36';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test36';
|
||||||
|
xa prepare 'test36';
|
||||||
|
xa start 'test35';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test35';
|
||||||
|
xa prepare 'test35';
|
||||||
|
xa start 'test34';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test34';
|
||||||
|
xa prepare 'test34';
|
||||||
|
xa start 'test33';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test33';
|
||||||
|
xa prepare 'test33';
|
||||||
|
xa start 'test32';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test32';
|
||||||
|
xa prepare 'test32';
|
||||||
|
xa start 'test31';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test31';
|
||||||
|
xa prepare 'test31';
|
||||||
|
xa start 'test30';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test30';
|
||||||
|
xa prepare 'test30';
|
||||||
|
xa start 'test29';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test29';
|
||||||
|
xa prepare 'test29';
|
||||||
|
xa start 'test28';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test28';
|
||||||
|
xa prepare 'test28';
|
||||||
|
xa start 'test27';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test27';
|
||||||
|
xa prepare 'test27';
|
||||||
|
xa start 'test26';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test26';
|
||||||
|
xa prepare 'test26';
|
||||||
|
xa start 'test25';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test25';
|
||||||
|
xa prepare 'test25';
|
||||||
|
xa start 'test24';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test24';
|
||||||
|
xa prepare 'test24';
|
||||||
|
xa start 'test23';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test23';
|
||||||
|
xa prepare 'test23';
|
||||||
|
xa start 'test22';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test22';
|
||||||
|
xa prepare 'test22';
|
||||||
|
xa start 'test21';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test21';
|
||||||
|
xa prepare 'test21';
|
||||||
|
xa start 'test20';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test20';
|
||||||
|
xa prepare 'test20';
|
||||||
|
xa start 'test19';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test19';
|
||||||
|
xa prepare 'test19';
|
||||||
|
xa start 'test18';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test18';
|
||||||
|
xa prepare 'test18';
|
||||||
|
xa start 'test17';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test17';
|
||||||
|
xa prepare 'test17';
|
||||||
|
xa start 'test16';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test16';
|
||||||
|
xa prepare 'test16';
|
||||||
|
xa start 'test15';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test15';
|
||||||
|
xa prepare 'test15';
|
||||||
|
xa start 'test14';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test14';
|
||||||
|
xa prepare 'test14';
|
||||||
|
xa start 'test13';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test13';
|
||||||
|
xa prepare 'test13';
|
||||||
|
xa start 'test12';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test12';
|
||||||
|
xa prepare 'test12';
|
||||||
|
xa start 'test11';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test11';
|
||||||
|
xa prepare 'test11';
|
||||||
|
xa start 'test10';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test10';
|
||||||
|
xa prepare 'test10';
|
||||||
|
xa start 'test9';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test9';
|
||||||
|
xa prepare 'test9';
|
||||||
|
xa start 'test8';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test8';
|
||||||
|
xa prepare 'test8';
|
||||||
|
xa start 'test7';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test7';
|
||||||
|
xa prepare 'test7';
|
||||||
|
xa start 'test6';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test6';
|
||||||
|
xa prepare 'test6';
|
||||||
|
xa start 'test5';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test5';
|
||||||
|
xa prepare 'test5';
|
||||||
|
xa start 'test4';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test4';
|
||||||
|
xa prepare 'test4';
|
||||||
|
xa start 'test3';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test3';
|
||||||
|
xa prepare 'test3';
|
||||||
|
xa start 'test2';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test2';
|
||||||
|
xa prepare 'test2';
|
||||||
|
xa start 'test1';
|
||||||
|
insert into t1 values(1);
|
||||||
|
xa end 'test1';
|
||||||
|
xa prepare 'test1';
|
||||||
|
xa recover;
|
||||||
|
formatID gtrid_length bqual_length data
|
||||||
|
1 5 0 test1
|
||||||
|
1 5 0 test2
|
||||||
|
1 5 0 test3
|
||||||
|
1 5 0 test4
|
||||||
|
1 5 0 test5
|
||||||
|
1 5 0 test6
|
||||||
|
1 5 0 test7
|
||||||
|
1 5 0 test8
|
||||||
|
1 5 0 test9
|
||||||
|
1 6 0 test10
|
||||||
|
1 6 0 test11
|
||||||
|
1 6 0 test12
|
||||||
|
1 6 0 test13
|
||||||
|
1 6 0 test14
|
||||||
|
1 6 0 test15
|
||||||
|
1 6 0 test16
|
||||||
|
1 6 0 test17
|
||||||
|
1 6 0 test18
|
||||||
|
1 6 0 test19
|
||||||
|
1 6 0 test20
|
||||||
|
1 6 0 test21
|
||||||
|
1 6 0 test22
|
||||||
|
1 6 0 test23
|
||||||
|
1 6 0 test24
|
||||||
|
1 6 0 test25
|
||||||
|
1 6 0 test26
|
||||||
|
1 6 0 test27
|
||||||
|
1 6 0 test28
|
||||||
|
1 6 0 test29
|
||||||
|
1 6 0 test30
|
||||||
|
1 6 0 test31
|
||||||
|
1 6 0 test32
|
||||||
|
1 6 0 test33
|
||||||
|
1 6 0 test34
|
||||||
|
1 6 0 test35
|
||||||
|
1 6 0 test36
|
||||||
|
1 6 0 test37
|
||||||
|
1 6 0 test38
|
||||||
|
1 6 0 test39
|
||||||
|
1 6 0 test40
|
||||||
|
1 6 0 test41
|
||||||
|
1 6 0 test42
|
||||||
|
1 6 0 test43
|
||||||
|
1 6 0 test44
|
||||||
|
1 6 0 test45
|
||||||
|
1 6 0 test46
|
||||||
|
1 6 0 test47
|
||||||
|
1 6 0 test48
|
||||||
|
1 6 0 test49
|
||||||
|
1 6 0 test50
|
||||||
|
xa recover;
|
||||||
|
formatID gtrid_length bqual_length data
|
||||||
|
1 5 0 test1
|
||||||
|
1 5 0 test2
|
||||||
|
1 5 0 test3
|
||||||
|
1 5 0 test4
|
||||||
|
1 5 0 test5
|
||||||
|
1 5 0 test6
|
||||||
|
1 5 0 test7
|
||||||
|
1 5 0 test8
|
||||||
|
1 5 0 test9
|
||||||
|
1 6 0 test10
|
||||||
|
1 6 0 test11
|
||||||
|
1 6 0 test12
|
||||||
|
1 6 0 test13
|
||||||
|
1 6 0 test14
|
||||||
|
1 6 0 test15
|
||||||
|
1 6 0 test16
|
||||||
|
1 6 0 test17
|
||||||
|
1 6 0 test18
|
||||||
|
1 6 0 test19
|
||||||
|
1 6 0 test20
|
||||||
|
1 6 0 test21
|
||||||
|
1 6 0 test22
|
||||||
|
1 6 0 test23
|
||||||
|
1 6 0 test24
|
||||||
|
1 6 0 test25
|
||||||
|
1 6 0 test26
|
||||||
|
1 6 0 test27
|
||||||
|
1 6 0 test28
|
||||||
|
1 6 0 test29
|
||||||
|
1 6 0 test30
|
||||||
|
1 6 0 test31
|
||||||
|
1 6 0 test32
|
||||||
|
1 6 0 test33
|
||||||
|
1 6 0 test34
|
||||||
|
1 6 0 test35
|
||||||
|
1 6 0 test36
|
||||||
|
1 6 0 test37
|
||||||
|
1 6 0 test38
|
||||||
|
1 6 0 test39
|
||||||
|
1 6 0 test40
|
||||||
|
1 6 0 test41
|
||||||
|
1 6 0 test42
|
||||||
|
1 6 0 test43
|
||||||
|
1 6 0 test44
|
||||||
|
1 6 0 test45
|
||||||
|
1 6 0 test46
|
||||||
|
1 6 0 test47
|
||||||
|
1 6 0 test48
|
||||||
|
1 6 0 test49
|
||||||
|
1 6 0 test50
|
||||||
|
xa recover;
|
||||||
|
formatID gtrid_length bqual_length data
|
||||||
|
drop table t1;
|
45
mysql-test/suite/innodb/t/xa_debug.test
Normal file
45
mysql-test/suite/innodb/t/xa_debug.test
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
-- source include/have_innodb.inc
|
||||||
|
-- source include/have_debug.inc
|
||||||
|
-- source include/not_embedded.inc
|
||||||
|
|
||||||
|
call mtr.add_suppression("Found 50 prepared XA transactions");
|
||||||
|
create table t1 (a int) engine=innodb;
|
||||||
|
insert into t1 values(1);
|
||||||
|
|
||||||
|
let $trial = 50;
|
||||||
|
while ($trial)
|
||||||
|
{
|
||||||
|
--connect (con$trial, localhost, root,,)
|
||||||
|
let $st_pre = `select concat('test', $trial)`;
|
||||||
|
eval xa start '$st_pre';
|
||||||
|
insert into t1 values(1);
|
||||||
|
eval xa end '$st_pre';
|
||||||
|
eval xa prepare '$st_pre';
|
||||||
|
dec $trial;
|
||||||
|
}
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
# Kill and restart the server.
|
||||||
|
-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
|
-- shutdown_server 0
|
||||||
|
-- source include/wait_until_disconnected.inc
|
||||||
|
|
||||||
|
-- exec echo "restart:--debug_dbug=+d,min_xa_len" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
|
-- enable_reconnect
|
||||||
|
-- source include/wait_until_connected_again.inc
|
||||||
|
-- disable_reconnect
|
||||||
|
--sorted_result
|
||||||
|
xa recover;
|
||||||
|
--sorted_result
|
||||||
|
xa recover;
|
||||||
|
--disable_query_log
|
||||||
|
let $trial = 50;
|
||||||
|
while ($trial)
|
||||||
|
{
|
||||||
|
let $st_pre = `select concat('test', $trial)`;
|
||||||
|
eval xa commit '$st_pre';
|
||||||
|
dec $trial;
|
||||||
|
}
|
||||||
|
--enable_query_log
|
||||||
|
xa recover;
|
||||||
|
drop table t1;
|
@ -1740,6 +1740,7 @@ int ha_recover(HASH *commit_list)
|
|||||||
for (info.len= MAX_XID_LIST_SIZE ;
|
for (info.len= MAX_XID_LIST_SIZE ;
|
||||||
info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
|
info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
|
||||||
{
|
{
|
||||||
|
DBUG_EXECUTE_IF("min_xa_len", info.len = 16;);
|
||||||
info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
|
info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
|
||||||
}
|
}
|
||||||
if (!info.list)
|
if (!info.list)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2019, 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
|
||||||
@ -353,10 +354,13 @@ trx_is_active(
|
|||||||
}
|
}
|
||||||
|
|
||||||
trx = trx_get_on_id(trx_id);
|
trx = trx_get_on_id(trx_id);
|
||||||
if (trx && (trx->conc_state == TRX_ACTIVE
|
if (trx) {
|
||||||
|| trx->conc_state == TRX_PREPARED)) {
|
switch (trx->conc_state) {
|
||||||
|
case TRX_ACTIVE:
|
||||||
return(TRUE);
|
case TRX_PREPARED:
|
||||||
|
case TRX_PREPARED_RECOVERED:
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
|
||||||
|
Copyright (c) 2019, 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
|
||||||
@ -741,6 +742,8 @@ struct trx_struct{
|
|||||||
#define TRX_ACTIVE 1
|
#define TRX_ACTIVE 1
|
||||||
#define TRX_COMMITTED_IN_MEMORY 2
|
#define TRX_COMMITTED_IN_MEMORY 2
|
||||||
#define TRX_PREPARED 3 /* Support for 2PC/XA */
|
#define TRX_PREPARED 3 /* Support for 2PC/XA */
|
||||||
|
#define TRX_PREPARED_RECOVERED 4 /* XA PREPARE transaction that
|
||||||
|
was returned to ha_recover() */
|
||||||
|
|
||||||
/* Transaction execution states when trx->conc_state == TRX_ACTIVE */
|
/* Transaction execution states when trx->conc_state == TRX_ACTIVE */
|
||||||
#define TRX_QUE_RUNNING 0 /* transaction is running */
|
#define TRX_QUE_RUNNING 0 /* transaction is running */
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2019, 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
|
||||||
@ -4782,6 +4783,22 @@ print_rec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
|
/** Validate the state of a transaction that holds locks */
|
||||||
|
static void lock_trx_state_validate(const trx_t* trx)
|
||||||
|
{
|
||||||
|
switch (trx->conc_state) {
|
||||||
|
case TRX_NOT_STARTED:
|
||||||
|
break;
|
||||||
|
case TRX_ACTIVE:
|
||||||
|
case TRX_PREPARED:
|
||||||
|
case TRX_PREPARED_RECOVERED:
|
||||||
|
case TRX_COMMITTED_IN_MEMORY:
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
ut_ad(!"wrong state");
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
Validates the lock queue on a table.
|
Validates the lock queue on a table.
|
||||||
@return TRUE if ok */
|
@return TRUE if ok */
|
||||||
@ -4798,9 +4815,7 @@ lock_table_queue_validate(
|
|||||||
lock = UT_LIST_GET_FIRST(table->locks);
|
lock = UT_LIST_GET_FIRST(table->locks);
|
||||||
|
|
||||||
while (lock) {
|
while (lock) {
|
||||||
ut_a(((lock->trx)->conc_state == TRX_ACTIVE)
|
ut_d(lock_trx_state_validate(lock->trx));
|
||||||
|| ((lock->trx)->conc_state == TRX_PREPARED)
|
|
||||||
|| ((lock->trx)->conc_state == TRX_COMMITTED_IN_MEMORY));
|
|
||||||
|
|
||||||
if (!lock_get_wait(lock)) {
|
if (!lock_get_wait(lock)) {
|
||||||
|
|
||||||
@ -4848,15 +4863,7 @@ lock_rec_queue_validate(
|
|||||||
lock = lock_rec_get_first(block, heap_no);
|
lock = lock_rec_get_first(block, heap_no);
|
||||||
|
|
||||||
while (lock) {
|
while (lock) {
|
||||||
switch(lock->trx->conc_state) {
|
ut_d(lock_trx_state_validate(lock->trx));
|
||||||
case TRX_ACTIVE:
|
|
||||||
case TRX_PREPARED:
|
|
||||||
case TRX_COMMITTED_IN_MEMORY:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ut_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
ut_a(trx_in_trx_list(lock->trx));
|
ut_a(trx_in_trx_list(lock->trx));
|
||||||
|
|
||||||
if (lock_get_wait(lock)) {
|
if (lock_get_wait(lock)) {
|
||||||
@ -4935,9 +4942,7 @@ lock_rec_queue_validate(
|
|||||||
lock = lock_rec_get_first(block, heap_no);
|
lock = lock_rec_get_first(block, heap_no);
|
||||||
|
|
||||||
while (lock) {
|
while (lock) {
|
||||||
ut_a(lock->trx->conc_state == TRX_ACTIVE
|
ut_d(lock_trx_state_validate(lock->trx));
|
||||||
|| lock->trx->conc_state == TRX_PREPARED
|
|
||||||
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
|
|
||||||
ut_a(trx_in_trx_list(lock->trx));
|
ut_a(trx_in_trx_list(lock->trx));
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
@ -5014,10 +5019,8 @@ loop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ut_d(lock_trx_state_validate(lock->trx));
|
||||||
ut_a(trx_in_trx_list(lock->trx));
|
ut_a(trx_in_trx_list(lock->trx));
|
||||||
ut_a(lock->trx->conc_state == TRX_ACTIVE
|
|
||||||
|| lock->trx->conc_state == TRX_PREPARED
|
|
||||||
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
|
|
||||||
|
|
||||||
# ifdef UNIV_SYNC_DEBUG
|
# ifdef UNIV_SYNC_DEBUG
|
||||||
/* Only validate the record queues when this thread is not
|
/* Only validate the record queues when this thread is not
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
|
||||||
|
Copyright (c) 2019, 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
|
||||||
@ -272,15 +273,19 @@ read_view_open_now(
|
|||||||
view->low_limit_id = view->low_limit_no;
|
view->low_limit_id = view->low_limit_no;
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
|
||||||
|
|
||||||
/* No active transaction should be visible, except cr_trx */
|
/* No active transaction should be visible, except cr_trx */
|
||||||
|
|
||||||
while (trx) {
|
for (trx = UT_LIST_GET_FIRST(trx_sys->trx_list); trx;
|
||||||
if (trx->id != cr_trx_id
|
trx = UT_LIST_GET_NEXT(trx_list, trx)) {
|
||||||
&& (trx->conc_state == TRX_ACTIVE
|
if (trx->id == cr_trx_id) {
|
||||||
|| trx->conc_state == TRX_PREPARED)) {
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (trx->conc_state) {
|
||||||
|
case TRX_ACTIVE:
|
||||||
|
case TRX_PREPARED:
|
||||||
|
case TRX_PREPARED_RECOVERED:
|
||||||
read_view_set_nth_trx_id(view, n, trx->id);
|
read_view_set_nth_trx_id(view, n, trx->id);
|
||||||
|
|
||||||
n++;
|
n++;
|
||||||
@ -296,8 +301,6 @@ read_view_open_now(
|
|||||||
view->low_limit_no = trx->no;
|
view->low_limit_no = trx->no;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trx = UT_LIST_GET_NEXT(trx_list, trx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
view->n_trx_ids = n;
|
view->n_trx_ids = n;
|
||||||
@ -437,18 +440,15 @@ read_cursor_view_create_for_mysql(
|
|||||||
view->low_limit_id = view->low_limit_no;
|
view->low_limit_id = view->low_limit_no;
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
|
||||||
|
|
||||||
/* No active transaction should be visible */
|
/* No active transaction should be visible */
|
||||||
|
for (trx = UT_LIST_GET_FIRST(trx_sys->trx_list); trx;
|
||||||
while (trx) {
|
trx = UT_LIST_GET_NEXT(trx_list, trx)) {
|
||||||
|
switch (trx->conc_state) {
|
||||||
if (trx->conc_state == TRX_ACTIVE
|
case TRX_ACTIVE:
|
||||||
|| trx->conc_state == TRX_PREPARED) {
|
case TRX_PREPARED:
|
||||||
|
case TRX_PREPARED_RECOVERED:
|
||||||
read_view_set_nth_trx_id(view, n, trx->id);
|
read_view_set_nth_trx_id(view, n++, trx->id);
|
||||||
|
|
||||||
n++;
|
|
||||||
|
|
||||||
/* NOTE that a transaction whose trx number is <
|
/* NOTE that a transaction whose trx number is <
|
||||||
trx_sys->max_trx_id can still be active, if it is
|
trx_sys->max_trx_id can still be active, if it is
|
||||||
@ -461,8 +461,6 @@ read_cursor_view_create_for_mysql(
|
|||||||
view->low_limit_no = trx->no;
|
view->low_limit_no = trx->no;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trx = UT_LIST_GET_NEXT(trx_list, trx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
view->n_trx_ids = n;
|
view->n_trx_ids = n;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
||||||
Copyright (c) 2017, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2019, 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
|
||||||
@ -564,6 +565,7 @@ loop:
|
|||||||
switch (trx->conc_state) {
|
switch (trx->conc_state) {
|
||||||
case TRX_NOT_STARTED:
|
case TRX_NOT_STARTED:
|
||||||
case TRX_PREPARED:
|
case TRX_PREPARED:
|
||||||
|
case TRX_PREPARED_RECOVERED:
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case TRX_COMMITTED_IN_MEMORY:
|
case TRX_COMMITTED_IN_MEMORY:
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2019, 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
|
||||||
@ -1031,7 +1032,7 @@ trx_sys_init_at_db_start(void)
|
|||||||
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
ut_ad(trx->conc_state != TRX_PREPARED_RECOVERED);
|
||||||
if (trx->conc_state != TRX_PREPARED) {
|
if (trx->conc_state != TRX_PREPARED) {
|
||||||
rows_to_undo += trx->undo_no;
|
rows_to_undo += trx->undo_no;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
|
||||||
|
Copyright (c) 2019, 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
|
||||||
@ -348,7 +349,8 @@ trx_free_prepared(
|
|||||||
trx_t* trx) /*!< in, own: trx object */
|
trx_t* trx) /*!< in, own: trx object */
|
||||||
{
|
{
|
||||||
ut_ad(mutex_own(&kernel_mutex));
|
ut_ad(mutex_own(&kernel_mutex));
|
||||||
ut_a(trx->conc_state == TRX_PREPARED);
|
ut_a(trx->conc_state == TRX_PREPARED
|
||||||
|
|| trx->conc_state == TRX_PREPARED_RECOVERED);
|
||||||
ut_a(trx->magic_n == TRX_MAGIC_N);
|
ut_a(trx->magic_n == TRX_MAGIC_N);
|
||||||
|
|
||||||
/* Prepared transactions are sort of active; they allow
|
/* Prepared transactions are sort of active; they allow
|
||||||
@ -932,10 +934,11 @@ trx_commit_off_kernel(
|
|||||||
lsn = 0;
|
lsn = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_ad(trx->conc_state == TRX_ACTIVE || trx->conc_state == TRX_PREPARED);
|
ut_ad(trx->conc_state == TRX_ACTIVE || trx->conc_state == TRX_PREPARED
|
||||||
|
|| trx->conc_state == TRX_PREPARED_RECOVERED);
|
||||||
ut_ad(mutex_own(&kernel_mutex));
|
ut_ad(mutex_own(&kernel_mutex));
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(trx->conc_state == TRX_PREPARED)) {
|
if (UNIV_UNLIKELY(trx->conc_state != TRX_ACTIVE)) {
|
||||||
ut_a(trx_n_prepared > 0);
|
ut_a(trx_n_prepared > 0);
|
||||||
trx_n_prepared--;
|
trx_n_prepared--;
|
||||||
}
|
}
|
||||||
@ -2072,6 +2075,7 @@ trx_recover_for_mysql(
|
|||||||
|
|
||||||
while (trx) {
|
while (trx) {
|
||||||
if (trx->conc_state == TRX_PREPARED) {
|
if (trx->conc_state == TRX_PREPARED) {
|
||||||
|
trx->conc_state = TRX_PREPARED_RECOVERED;
|
||||||
xid_list[count] = trx->xid;
|
xid_list[count] = trx->xid;
|
||||||
|
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
@ -2096,13 +2100,25 @@ trx_recover_for_mysql(
|
|||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (count == len) {
|
if (count == len) {
|
||||||
break;
|
goto partial;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trx = UT_LIST_GET_NEXT(trx_list, trx);
|
trx = UT_LIST_GET_NEXT(trx_list, trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* After returning the full list, reset the state, because
|
||||||
|
init_server_components() wants to recover the collection of
|
||||||
|
transactions twice, by first calling tc_log->open() and then
|
||||||
|
ha_recover() directly. */
|
||||||
|
for (trx = UT_LIST_GET_FIRST(trx_sys->trx_list); trx;
|
||||||
|
trx = UT_LIST_GET_NEXT(trx_list, trx)) {
|
||||||
|
if (trx->conc_state == TRX_PREPARED_RECOVERED) {
|
||||||
|
trx->conc_state = TRX_PREPARED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partial:
|
||||||
mutex_exit(&kernel_mutex);
|
mutex_exit(&kernel_mutex);
|
||||||
|
|
||||||
if (count > 0){
|
if (count > 0){
|
||||||
@ -2144,7 +2160,8 @@ trx_get_trx_by_xid(
|
|||||||
the same */
|
the same */
|
||||||
|
|
||||||
if (trx->is_recovered
|
if (trx->is_recovered
|
||||||
&& trx->conc_state == TRX_PREPARED
|
&& (trx->conc_state == TRX_PREPARED
|
||||||
|
|| trx->conc_state == TRX_PREPARED_RECOVERED)
|
||||||
&& xid->gtrid_length == trx->xid.gtrid_length
|
&& xid->gtrid_length == trx->xid.gtrid_length
|
||||||
&& xid->bqual_length == trx->xid.bqual_length
|
&& xid->bqual_length == trx->xid.bqual_length
|
||||||
&& memcmp(xid->data, trx->xid.data,
|
&& memcmp(xid->data, trx->xid.data,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
|
||||||
|
Copyright (c) 2019, 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
|
||||||
@ -802,6 +803,8 @@ struct trx_struct{
|
|||||||
#define TRX_ACTIVE 1
|
#define TRX_ACTIVE 1
|
||||||
#define TRX_COMMITTED_IN_MEMORY 2
|
#define TRX_COMMITTED_IN_MEMORY 2
|
||||||
#define TRX_PREPARED 3 /* Support for 2PC/XA */
|
#define TRX_PREPARED 3 /* Support for 2PC/XA */
|
||||||
|
#define TRX_PREPARED_RECOVERED 4 /* XA PREPARE transaction that
|
||||||
|
was returned to ha_recover() */
|
||||||
|
|
||||||
/* Transaction execution states when trx->conc_state == TRX_ACTIVE */
|
/* Transaction execution states when trx->conc_state == TRX_ACTIVE */
|
||||||
#define TRX_QUE_RUNNING 0 /* transaction is running */
|
#define TRX_QUE_RUNNING 0 /* transaction is running */
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2019, 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
|
||||||
@ -4811,6 +4812,22 @@ print_rec:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
|
/** Validate the state of a transaction that holds locks */
|
||||||
|
static void lock_trx_state_validate(const trx_t* trx)
|
||||||
|
{
|
||||||
|
switch (trx->state) {
|
||||||
|
case TRX_NOT_STARTED:
|
||||||
|
break;
|
||||||
|
case TRX_ACTIVE:
|
||||||
|
case TRX_PREPARED:
|
||||||
|
case TRX_PREPARED_RECOVERED:
|
||||||
|
case TRX_COMMITTED_IN_MEMORY:
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
ut_ad(!"wrong state");
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
Validates the lock queue on a table.
|
Validates the lock queue on a table.
|
||||||
@return TRUE if ok */
|
@return TRUE if ok */
|
||||||
@ -4827,9 +4844,7 @@ lock_table_queue_validate(
|
|||||||
lock = UT_LIST_GET_FIRST(table->locks);
|
lock = UT_LIST_GET_FIRST(table->locks);
|
||||||
|
|
||||||
while (lock) {
|
while (lock) {
|
||||||
ut_a(((lock->trx)->state == TRX_ACTIVE)
|
ut_d(lock_trx_state_validate(lock->trx));
|
||||||
|| ((lock->trx)->state == TRX_PREPARED)
|
|
||||||
|| ((lock->trx)->state == TRX_COMMITTED_IN_MEMORY));
|
|
||||||
|
|
||||||
if (!lock_get_wait(lock)) {
|
if (!lock_get_wait(lock)) {
|
||||||
|
|
||||||
@ -4877,15 +4892,7 @@ lock_rec_queue_validate(
|
|||||||
lock = lock_rec_get_first(block, heap_no);
|
lock = lock_rec_get_first(block, heap_no);
|
||||||
|
|
||||||
while (lock) {
|
while (lock) {
|
||||||
switch(lock->trx->state) {
|
ut_d(lock_trx_state_validate(lock->trx));
|
||||||
case TRX_ACTIVE:
|
|
||||||
case TRX_PREPARED:
|
|
||||||
case TRX_COMMITTED_IN_MEMORY:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ut_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
ut_a(trx_in_trx_list(lock->trx));
|
ut_a(trx_in_trx_list(lock->trx));
|
||||||
|
|
||||||
if (lock_get_wait(lock)) {
|
if (lock_get_wait(lock)) {
|
||||||
@ -4964,9 +4971,7 @@ lock_rec_queue_validate(
|
|||||||
lock = lock_rec_get_first(block, heap_no);
|
lock = lock_rec_get_first(block, heap_no);
|
||||||
|
|
||||||
while (lock) {
|
while (lock) {
|
||||||
ut_a(lock->trx->state == TRX_ACTIVE
|
ut_d(lock_trx_state_validate(lock->trx));
|
||||||
|| lock->trx->state == TRX_PREPARED
|
|
||||||
|| lock->trx->state == TRX_COMMITTED_IN_MEMORY);
|
|
||||||
ut_a(trx_in_trx_list(lock->trx));
|
ut_a(trx_in_trx_list(lock->trx));
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
@ -5043,10 +5048,8 @@ loop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ut_d(lock_trx_state_validate(lock->trx));
|
||||||
ut_a(trx_in_trx_list(lock->trx));
|
ut_a(trx_in_trx_list(lock->trx));
|
||||||
ut_a(lock->trx->state == TRX_ACTIVE
|
|
||||||
|| lock->trx->state == TRX_PREPARED
|
|
||||||
|| lock->trx->state == TRX_COMMITTED_IN_MEMORY);
|
|
||||||
|
|
||||||
# ifdef UNIV_SYNC_DEBUG
|
# ifdef UNIV_SYNC_DEBUG
|
||||||
/* Only validate the record queues when this thread is not
|
/* Only validate the record queues when this thread is not
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
||||||
Copyright (c) 2017, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2019, 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
|
||||||
@ -564,6 +565,7 @@ loop:
|
|||||||
switch (trx->state) {
|
switch (trx->state) {
|
||||||
case TRX_NOT_STARTED:
|
case TRX_NOT_STARTED:
|
||||||
case TRX_PREPARED:
|
case TRX_PREPARED:
|
||||||
|
case TRX_PREPARED_RECOVERED:
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case TRX_COMMITTED_IN_MEMORY:
|
case TRX_COMMITTED_IN_MEMORY:
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2019, 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
|
||||||
@ -1355,7 +1356,7 @@ trx_sys_init_at_db_start(void)
|
|||||||
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
ut_ad(trx->state != TRX_PREPARED_RECOVERED);
|
||||||
if (trx->state != TRX_PREPARED) {
|
if (trx->state != TRX_PREPARED) {
|
||||||
rows_to_undo += trx->undo_no;
|
rows_to_undo += trx->undo_no;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
|
||||||
|
Copyright (c) 2019, 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
|
||||||
@ -481,7 +482,8 @@ trx_free_prepared(
|
|||||||
trx_t* trx) /*!< in, own: trx object */
|
trx_t* trx) /*!< in, own: trx object */
|
||||||
{
|
{
|
||||||
ut_ad(mutex_own(&kernel_mutex));
|
ut_ad(mutex_own(&kernel_mutex));
|
||||||
ut_a(trx->state == TRX_PREPARED);
|
ut_a(trx->state == TRX_PREPARED
|
||||||
|
|| trx->state == TRX_PREPARED_RECOVERED);
|
||||||
ut_a(trx->magic_n == TRX_MAGIC_N);
|
ut_a(trx->magic_n == TRX_MAGIC_N);
|
||||||
|
|
||||||
/* Prepared transactions are sort of active; they allow
|
/* Prepared transactions are sort of active; they allow
|
||||||
@ -1148,10 +1150,11 @@ trx_commit_off_kernel(
|
|||||||
lsn = 0;
|
lsn = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_ad(trx->state == TRX_ACTIVE || trx->state == TRX_PREPARED);
|
ut_ad(trx->state == TRX_ACTIVE || trx->state == TRX_PREPARED
|
||||||
|
|| trx->state == TRX_PREPARED_RECOVERED);
|
||||||
ut_ad(mutex_own(&kernel_mutex));
|
ut_ad(mutex_own(&kernel_mutex));
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(trx->state == TRX_PREPARED)) {
|
if (UNIV_UNLIKELY(trx->state != TRX_ACTIVE)) {
|
||||||
ut_a(trx_n_prepared > 0);
|
ut_a(trx_n_prepared > 0);
|
||||||
trx_n_prepared--;
|
trx_n_prepared--;
|
||||||
}
|
}
|
||||||
@ -2359,6 +2362,7 @@ trx_recover_for_mysql(
|
|||||||
|
|
||||||
while (trx) {
|
while (trx) {
|
||||||
if (trx->state == TRX_PREPARED) {
|
if (trx->state == TRX_PREPARED) {
|
||||||
|
trx->state = TRX_PREPARED_RECOVERED;
|
||||||
xid_list[count] = trx->xid;
|
xid_list[count] = trx->xid;
|
||||||
|
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
@ -2383,13 +2387,25 @@ trx_recover_for_mysql(
|
|||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (count == len) {
|
if (count == len) {
|
||||||
break;
|
goto partial;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trx = UT_LIST_GET_NEXT(trx_list, trx);
|
trx = UT_LIST_GET_NEXT(trx_list, trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* After returning the full list, reset the state, because
|
||||||
|
init_server_components() wants to recover the collection of
|
||||||
|
transactions twice, by first calling tc_log->open() and then
|
||||||
|
ha_recover() directly. */
|
||||||
|
for (trx = UT_LIST_GET_FIRST(trx_sys->trx_list); trx;
|
||||||
|
trx = UT_LIST_GET_NEXT(trx_list, trx)) {
|
||||||
|
if (trx->state == TRX_PREPARED_RECOVERED) {
|
||||||
|
trx->state = TRX_PREPARED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partial:
|
||||||
mutex_exit(&kernel_mutex);
|
mutex_exit(&kernel_mutex);
|
||||||
|
|
||||||
if (count > 0){
|
if (count > 0){
|
||||||
@ -2431,7 +2447,8 @@ trx_get_trx_by_xid(
|
|||||||
the same */
|
the same */
|
||||||
|
|
||||||
if (trx->is_recovered
|
if (trx->is_recovered
|
||||||
&& trx->state == TRX_PREPARED
|
&& (trx->state == TRX_PREPARED
|
||||||
|
|| trx->state == TRX_PREPARED_RECOVERED)
|
||||||
&& xid->gtrid_length == trx->xid.gtrid_length
|
&& xid->gtrid_length == trx->xid.gtrid_length
|
||||||
&& xid->bqual_length == trx->xid.bqual_length
|
&& xid->bqual_length == trx->xid.bqual_length
|
||||||
&& memcmp(xid->data, trx->xid.data,
|
&& memcmp(xid->data, trx->xid.data,
|
||||||
|
Reference in New Issue
Block a user