Commit 2f3779d3 authored by Monty's avatar Monty

Fixes for Aria transaction handling with lock tables

MDEV-10130 Assertion `share->in_trans == 0' failed in storage/maria/ma_close.c
MDEV-10378 Assertion `trn' failed in virtual int ha_maria::start_stmt

The problem was that maria_handler->trn was not properly reset
at commit/rollback and ha_maria::exernal_lock() could get confused
because.

There was some old code in ha_maria::implicit_commit() that tried
to take care of this, but it was not bullet proof.

Fixed by adding list of all tables that is part of the maria transaction to
TRN.

A nice side effect was of the fix is that loops in
ha_maria::implict_commit() got to be much simpler.

Other things:
- Fixed a bug in mysql_admin_table() where argument open_for_modify
  was wrongly reset for the next table in the chain
- rollback admin command also in case of fatal error.
- Split _ma_set_trn_for_table() to three version to simplify code
  and debugging.
- Several new asserts to detect the original problem (that file was
  not properly removed from trn before calling ma_close())
parent c1b5d280
......@@ -99,3 +99,13 @@ f2
3
unlock tables;
DROP TABLE t1,t2,tmp;
#
# MDEV-10378 Assertion `trn' failed in virtual int ha_maria::start_stmt
#
CREATE TABLE t1 (f1 VARCHAR(3), f2 INT, pk INT, PRIMARY KEY (pk)) ENGINE=Aria;
INSERT INTO t1 VALUES ('foo',10,1), ('foo',1,2);
LOCK TABLE t1 WRITE;
ALTER TABLE t1 ADD UNIQUE KEY (f1);
ERROR 23000: Duplicate entry 'foo' for key 'f1'
ALTER TABLE t1 ADD KEY (f2);
DROP TABLE t1;
......@@ -105,3 +105,15 @@ INSERT INTO t2 (f2) SELECT f3 FROM tmp AS tmp_alias;
select * from t2;
unlock tables;
DROP TABLE t1,t2,tmp;
--echo #
--echo # MDEV-10378 Assertion `trn' failed in virtual int ha_maria::start_stmt
--echo #
CREATE TABLE t1 (f1 VARCHAR(3), f2 INT, pk INT, PRIMARY KEY (pk)) ENGINE=Aria;
INSERT INTO t1 VALUES ('foo',10,1), ('foo',1,2);
LOCK TABLE t1 WRITE;
--error ER_DUP_ENTRY
ALTER TABLE t1 ADD UNIQUE KEY (f1);
ALTER TABLE t1 ADD KEY (f2);
DROP TABLE t1;
......@@ -302,7 +302,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
HA_CHECK_OPT* check_opt,
const char *operator_name,
thr_lock_type lock_type,
bool open_for_modify,
bool org_open_for_modify,
bool repair_table_use_frm,
uint extra_open_options,
int (*prepare_func)(THD *, TABLE_LIST *,
......@@ -359,10 +359,10 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
for (table= tables; table; table= table->next_local)
{
char table_name[SAFE_NAME_LEN*2+2];
char* db = table->db;
char *db= table->db;
bool fatal_error=0;
bool open_error;
bool open_for_modify= org_open_for_modify;
DBUG_PRINT("admin", ("table: '%s'.'%s'", table->db, table->table_name));
strxmov(table_name, db, ".", table->table_name, NullS);
thd->open_options|= extra_open_options;
......@@ -395,8 +395,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
/*
CHECK TABLE command is allowed for views as well. Check on alter flags
to differentiate from ALTER TABLE...CHECK PARTITION on which view is not
allowed.
to differentiate from ALTER TABLE...CHECK PARTITION on which view is
not allowed.
*/
if (lex->alter_info.flags & Alter_info::ALTER_ADMIN_PARTITION ||
view_operator_func == NULL)
......@@ -1053,7 +1053,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
}
}
/* Error path, a admin command failed. */
if (thd->transaction_rollback_request)
if (thd->transaction_rollback_request || fatal_error)
{
/*
Unlikely, but transaction rollback was requested by one of storage
......
......@@ -155,10 +155,11 @@ static void mysql_ha_close_table(SQL_HANDLER *handler)
{
THD *thd= handler->thd;
TABLE *table= handler->table;
DBUG_ENTER("mysql_ha_close_table");
/* check if table was already closed */
if (!table)
return;
DBUG_VOID_RETURN;
if (!table->s->tmp_table)
{
......@@ -184,6 +185,7 @@ static void mysql_ha_close_table(SQL_HANDLER *handler)
}
my_free(handler->lock);
handler->init();
DBUG_VOID_RETURN;
}
/*
......
......@@ -37,6 +37,7 @@ C_MODE_START
#include "ma_checkpoint.h"
#include "ma_recovery.h"
C_MODE_END
#include "ma_trnman.h"
//#include "sql_priv.h"
#include "protocol.h"
......@@ -1384,7 +1385,8 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
}
/* Reset trn, that may have been set by repair */
_ma_set_trn_for_table(file, old_trn);
if (old_trn && old_trn != file->trn)
_ma_set_trn_for_table(file, old_trn);
thd_proc_info(thd, old_proc_info);
thd_progress_end(thd);
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
......@@ -1518,7 +1520,8 @@ int ha_maria::zerofill(THD * thd, HA_CHECK_OPT *check_opt)
error=maria_zerofill(param, file, share->open_file_name.str);
/* Reset trn, that may have been set by repair */
_ma_set_trn_for_table(file, old_trn);
if (old_trn && old_trn != file->trn)
_ma_set_trn_for_table(file, old_trn);
if (!error)
{
......@@ -1758,7 +1761,8 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize)
maria_lock_database(file, F_UNLCK);
/* Reset trn, that may have been set by repair */
_ma_set_trn_for_table(file, old_trn);
if (old_trn && old_trn != file->trn)
_ma_set_trn_for_table(file, old_trn);
error= error ? HA_ADMIN_FAILED :
(optimize_done ?
(write_log_record_for_repair(param, file) ? HA_ADMIN_FAILED :
......@@ -2579,9 +2583,12 @@ int ha_maria::extra(enum ha_extra_function operation)
without calling commit/rollback in between. If file->trn is not set
we can't remove file->share from the transaction list in the extra() call.
We also ensure that we set file->trn to 0 if THD_TRN is 0 as in
this case we have already freed the trn. This can happen when one
implicit_commit() is called as part of alter table.
In current code we don't have to do this for HA_EXTRA_PREPARE_FOR_RENAME
as this is only used the intermediate table used by ALTER TABLE which
is not part of the transaction (it's not in the TRN list). Better to
keep this for now, to not break anything in a stable release.
When HA_EXTRA_PREPARE_FOR_RENAME is not handled below, we can change
the warnings in _ma_remove_table_from_trnman() to asserts.
table->in_use is not set in the case this is a done as part of closefrm()
as part of drop table.
......@@ -2594,7 +2601,7 @@ int ha_maria::extra(enum ha_extra_function operation)
{
THD *thd= table->in_use;
TRN *trn= THD_TRN;
_ma_set_trn_for_table(file, trn);
_ma_set_tmp_trn_for_table(file, trn);
}
DBUG_ASSERT(file->s->base.born_transactional || file->trn == 0 ||
file->trn == &dummy_transaction_object);
......@@ -2710,6 +2717,7 @@ int ha_maria::external_lock(THD *thd, int lock_type)
if (file->trn)
{
/* This can only happen with tables created with clone() */
DBUG_PRINT("info",("file->trn: %p", file->trn));
trnman_increment_locked_tables(file->trn);
}
......@@ -2730,7 +2738,7 @@ int ha_maria::external_lock(THD *thd, int lock_type)
}
else
{
TRN *trn= THD_TRN;
TRN *trn= (file->trn != &dummy_transaction_object ? file->trn : 0);
/* End of transaction */
/*
......@@ -2745,8 +2753,7 @@ int ha_maria::external_lock(THD *thd, int lock_type)
*/
if (_ma_reenable_logging_for_table(file, TRUE))
DBUG_RETURN(1);
/** @todo zero file->trn also in commit and rollback */
_ma_set_trn_for_table(file, NULL); // Safety
_ma_reset_trn_for_table(file);
/*
Ensure that file->state points to the current number of rows. This
is needed if someone calls maria_info() without first doing an
......@@ -2802,13 +2809,6 @@ int ha_maria::start_stmt(THD *thd, thr_lock_type lock_type)
DBUG_ASSERT(lock_type != TL_UNLOCK);
DBUG_ASSERT(file->trn == trn);
/*
If there was an implicit commit under this LOCK TABLES by a previous
statement (like a DDL), at least if that previous statement was about a
different ha_maria than 'this' then this->file->trn is a stale
pointer. We fix it:
*/
_ma_set_trn_for_table(file, trn);
/*
As external_lock() was already called, don't increment locked_tables.
Note that we call the function below possibly several times when
......@@ -2833,6 +2833,23 @@ int ha_maria::start_stmt(THD *thd, thr_lock_type lock_type)
}
/*
Reset THD_TRN and all file->trn related to the transaction
This is needed as some calls, like extra() or external_lock() may access
it before next transaction is started
*/
static void reset_thd_trn(THD *thd, MARIA_HA *first_table)
{
DBUG_ENTER("reset_thd_trn");
THD_TRN= NULL;
for (MARIA_HA *table= first_table; table ;
table= table->trn_next)
_ma_reset_trn_for_table(table);
DBUG_VOID_RETURN;
}
/**
Performs an implicit commit of the Maria transaction and creates a new
one.
......@@ -2856,9 +2873,9 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
TRN *trn;
int error;
uint locked_tables;
DYNAMIC_ARRAY used_tables;
MARIA_HA *used_tables, *trn_next;
DBUG_ENTER("ha_maria::implicit_commit");
if (!maria_hton || !(trn= THD_TRN))
DBUG_RETURN(0);
if (!new_trn && (thd->locked_tables_mode == LTM_LOCK_TABLES ||
......@@ -2876,48 +2893,16 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
locked_tables= trnman_has_locked_tables(trn);
if (new_trn && trn && trn->used_tables)
{
MARIA_USED_TABLES *tables;
/*
Save locked tables so that we can move them to another transaction
We are using a dynamic array as locked_tables in some cases can be
smaller than the used_tables list (for example when the server does
early unlock of tables.
*/
my_init_dynamic_array2(&used_tables, sizeof(MARIA_SHARE*), (void*) 0,
locked_tables, 8, MYF(MY_THREAD_SPECIFIC));
for (tables= (MARIA_USED_TABLES*) trn->used_tables;
tables;
tables= tables->next)
{
if (tables->share->base.born_transactional)
{
if (insert_dynamic(&used_tables, (uchar*) &tables->share))
{
error= HA_ERR_OUT_OF_MEM;
goto end_and_free;
}
}
}
}
else
bzero(&used_tables, sizeof(used_tables));
used_tables= (MARIA_HA*) trn->used_instances;
error= 0;
if (unlikely(ma_commit(trn)))
error= 1;
if (!new_trn)
{
/*
To be extra safe, we should also reset file->trn for all open
tables as some calls, like extra() may access it. We take care
of this in extra() by resetting file->trn if THD_TRN is 0.
*/
THD_TRN= NULL;
reset_thd_trn(thd, used_tables);
goto end;
}
/*
We need to create a new transaction and put it in THD_TRN. Indeed,
tables may be under LOCK TABLES, and so they will start the next
......@@ -2927,8 +2912,9 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
THD_TRN= trn;
if (unlikely(trn == NULL))
{
reset_thd_trn(thd, used_tables);
error= HA_ERR_OUT_OF_MEM;
goto end_and_free;
goto end;
}
/*
Move all locked tables to the new transaction
......@@ -2938,35 +2924,25 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
in check table, we use the table without calling start_stmt().
*/
uint i;
for (i= 0 ; i < used_tables.elements ; i++)
for (MARIA_HA *handler= used_tables; handler ;
handler= trn_next)
{
MARIA_SHARE *share;
LIST *handlers;
trn_next= handler->trn_next;
DBUG_ASSERT(handler->s->base.born_transactional);
share= *(dynamic_element(&used_tables, i, MARIA_SHARE**));
/* Find table instances that was used in this transaction */
for (handlers= share->open_list; handlers; handlers= handlers->next)
/* If handler uses versioning */
if (handler->s->lock_key_trees)
{
MARIA_HA *handler= (MARIA_HA*) handlers->data;
if (handler->external_ref &&
((TABLE*) handler->external_ref)->in_use == thd)
{
_ma_set_trn_for_table(handler, trn);
/* If handler uses versioning */
if (handler->s->lock_key_trees)
{
if (_ma_setup_live_state(handler))
error= HA_ERR_OUT_OF_MEM;
}
}
/* _ma_set_trn_for_table() will be called indirectly */
if (_ma_setup_live_state(handler))
error= HA_ERR_OUT_OF_MEM;
}
else
_ma_set_trn_for_table(handler, trn);
}
/* This is just a commit, tables stay locked if they were: */
trnman_reset_locked_tables(trn, locked_tables);
end_and_free:
delete_dynamic(&used_tables);
end:
DBUG_RETURN(error);
}
......@@ -3340,10 +3316,10 @@ static int maria_commit(handlerton *hton __attribute__ ((unused)),
trnman_set_flags(trn, trnman_get_flags(trn) & ~TRN_STATE_INFO_LOGGED);
/* statement or transaction ? */
if ((thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && !all)
if ((thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
!all)
DBUG_RETURN(0); // end of statement
DBUG_PRINT("info", ("THD_TRN set to 0x0"));
THD_TRN= 0;
reset_thd_trn(thd, (MARIA_HA*) trn->used_instances);
DBUG_RETURN(ma_commit(trn)); // end of transaction
}
......@@ -3360,8 +3336,7 @@ static int maria_rollback(handlerton *hton __attribute__ ((unused)),
trnman_rollback_statement(trn);
DBUG_RETURN(0); // end of statement
}
DBUG_PRINT("info", ("THD_TRN set to 0x0"));
THD_TRN= 0;
reset_thd_trn(thd, (MARIA_HA*) trn->used_instances);
DBUG_RETURN(trnman_rollback_trn(trn) ?
HA_ERR_OUT_OF_MEM : 0); // end of transaction
}
......
......@@ -193,6 +193,7 @@ class ha_maria :public handler
private:
DsMrr_impl ds_mrr;
friend ICP_RESULT index_cond_func_maria(void *arg);
friend void reset_thd_trn(THD *thd);
};
#endif /* HA_MARIA_INCLUDED */
......@@ -271,6 +271,7 @@
#include "maria_def.h"
#include "ma_blockrec.h"
#include "trnman.h"
#include "ma_trnman.h"
#include "ma_key_recover.h"
#include "ma_recovery_util.h"
#include <lf.h>
......@@ -7488,7 +7489,7 @@ void maria_ignore_trids(MARIA_HA *info)
if (info->s->base.born_transactional)
{
if (!info->trn)
_ma_set_trn_for_table(info, &dummy_transaction_object);
_ma_set_tmp_trn_for_table(info, &dummy_transaction_object);
/* Ignore transaction id when row is read */
info->trn->min_read_from= ~(TrID) 0;
}
......
......@@ -36,6 +36,8 @@ int maria_close(register MARIA_HA *info)
/* Check that we have unlocked key delete-links properly */
DBUG_ASSERT(info->key_del_used == 0);
/* Check that file is not part of any uncommited transactions */
DBUG_ASSERT(info->trn == 0 || info->trn == &dummy_transaction_object);
if (share->reopen == 1)
{
......
......@@ -15,6 +15,7 @@
#include "maria_def.h"
#include "trnman.h"
#include "ma_trnman.h"
/**
writes a COMMIT record to log and commits transaction in memory
......@@ -43,9 +44,9 @@ int ma_commit(TRN *trn)
COMMIT record) and this is not an issue as
* transaction's updates were not made visible to other transactions
* "commit ok" was not sent to client
Alternatively, Recovery might commit trn (if MY_MIN(rec_lsn) is before COMMIT
record), which is ok too. All in all it means that "trn committed" is not
100% equal to "COMMIT record written".
Alternatively, Recovery might commit trn (if MY_MIN(rec_lsn) is before
COMMIT record), which is ok too. All in all it means that "trn committed"
is not 100% equal to "COMMIT record written".
- if COMMIT record is written after trnman_commit_trn():
if crash happens between the two, trn will be rolled back which is an
issue (transaction's updates were made visible to other transactions).
......@@ -93,7 +94,12 @@ int ma_commit(TRN *trn)
int maria_commit(MARIA_HA *info)
{
return info->s->now_transactional ? ma_commit(info->trn) : 0;
TRN *trn;
if (!info->s->now_transactional)
return 0;
trn= info->trn;
info->trn= 0; /* checked in maria_close() */
return ma_commit(trn);
}
......@@ -120,10 +126,7 @@ int maria_begin(MARIA_HA *info)
TRN *trn= trnman_new_trn(0);
if (unlikely(!trn))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
DBUG_PRINT("info", ("TRN set to 0x%lx", (ulong) trn));
_ma_set_trn_for_table(info, trn);
}
DBUG_RETURN(0);
}
......@@ -345,7 +345,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
_ma_decrement_open_count(info, 0);
if (info->trn)
{
_ma_remove_table_from_trnman(share, info->trn);
_ma_remove_table_from_trnman(info);
/* Ensure we don't point to the deleted data in trn */
info->state= info->state_start= &share->state.state;
}
......@@ -408,7 +408,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
if (info->trn)
{
mysql_mutex_lock(&share->intern_lock);
_ma_remove_table_from_trnman(share, info->trn);
_ma_remove_table_from_trnman(info);
/* Ensure we don't point to the deleted data in trn */
info->state= info->state_start= &share->state.state;
mysql_mutex_unlock(&share->intern_lock);
......
......@@ -19,6 +19,8 @@
#include "ma_sp_defs.h"
#include "ma_rt_index.h"
#include "ma_blockrec.h"
#include "trnman.h"
#include "ma_trnman.h"
#include <m_ctype.h>
#if defined(MSDOS) || defined(__WIN__)
......@@ -183,7 +185,7 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share,
if (!share->base.born_transactional) /* For transactional ones ... */
{
/* ... force crash if no trn given */
_ma_set_trn_for_table(&info, &dummy_transaction_object);
_ma_set_tmp_trn_for_table(&info, &dummy_transaction_object);
info.state= &share->state.state; /* Change global values by default */
}
else
......
......@@ -66,7 +66,7 @@ my_bool _ma_setup_live_state(MARIA_HA *info)
DBUG_RETURN(1);
trn= info->trn;
for (tables= (MARIA_USED_TABLES*) info->trn->used_tables;
for (tables= (MARIA_USED_TABLES*) trn->used_tables;
tables;
tables= tables->next)
{
......@@ -551,6 +551,7 @@ my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit,
my_free(tables);
}
trn->used_tables= 0;
trn->used_instances= 0;
DBUG_RETURN(error);
}
......@@ -565,18 +566,25 @@ my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit,
share->internal_lock must be locked when function is called
*/
void _ma_remove_table_from_trnman(MARIA_SHARE *share, TRN *trn)
void _ma_remove_table_from_trnman(MARIA_HA *info)
{
MARIA_SHARE *share= info->s;
TRN *trn= info->trn;
MARIA_USED_TABLES *tables, **prev;
MARIA_HA *handler, **prev_file;
DBUG_ENTER("_ma_remove_table_from_trnman");
DBUG_PRINT("enter", ("trn: %p used_tables: %p share: %p in_trans: %d",
trn, trn->used_tables, share, share->in_trans));
mysql_mutex_assert_owner(&share->intern_lock);
if (trn == &dummy_transaction_object)
DBUG_VOID_RETURN;
for (prev= (MARIA_USED_TABLES**) (char*) &trn->used_tables, tables= *prev;
tables;
tables= *prev)
/* First remove share from used_tables */
for (prev= (MARIA_USED_TABLES**) (char*) &trn->used_tables;
(tables= *prev);
prev= &tables->next)
{
if (tables->share == share)
{
......@@ -585,8 +593,36 @@ void _ma_remove_table_from_trnman(MARIA_SHARE *share, TRN *trn)
my_free(tables);
break;
}
prev= &tables->next;
}
if (tables != 0)
{
/*
This can only happens in case of rename of intermediate table as
part of alter table
*/
DBUG_PRINT("warning", ("share: %p where not in used_tables_list", share));
}
/* unlink table from used_instances */
for (prev_file= (MARIA_HA**) &trn->used_instances;
(handler= *prev_file);
prev_file= &handler->trn_next)
{
if (handler == info)
{
*prev_file= info->trn_next;
break;
}
}
if (handler != 0)
{
/*
This can only happens in case of rename of intermediate table as
part of alter table
*/
DBUG_PRINT("warning", ("table: %p where not in used_instances", info));
}
info->trn= 0; /* Not part of trans anymore */
DBUG_VOID_RETURN;
}
......
......@@ -84,5 +84,5 @@ my_bool _ma_row_visible_non_transactional_table(MARIA_HA *info);
my_bool _ma_row_visible_transactional_table(MARIA_HA *info);
void _ma_remove_not_visible_states_with_lock(struct st_maria_share *share,
my_bool all);
void _ma_remove_table_from_trnman(struct st_maria_share *share, TRN *trn);
void _ma_remove_table_from_trnman(MARIA_HA *info);
void _ma_reset_history(struct st_maria_share *share);
/* Copyright (C) 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
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 Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _ma_trnman_h
#define _ma_trnman_h
/**
Sets table's trn and prints debug information
Links table into used_instances if new_trn is not 0
@param tbl MARIA_HA of table
@param newtrn what to put into tbl->trn
*/
static inline void _ma_set_trn_for_table(MARIA_HA *tbl, TRN *newtrn)
{
DBUG_PRINT("info",("table: %p trn: %p -> %p",
tbl, tbl->trn, newtrn));
/* check that we are not calling this twice in a row */
DBUG_ASSERT(newtrn->used_instances != (void*) tbl);
tbl->trn= newtrn;
/* Link into used list */
tbl->trn_next= (MARIA_HA*) newtrn->used_instances;
newtrn->used_instances= tbl;
}
/*
Same as _ma_set_trn_for_table(), but don't link table into used_instance list
Used when we want to temporary set trn for a table in extra()
*/
static inline void _ma_set_tmp_trn_for_table(MARIA_HA *tbl, TRN *newtrn)
{
DBUG_PRINT("info",("table: %p trn: %p -> %p",
tbl, tbl->trn, newtrn));
tbl->trn= newtrn;
}
/*
Reset TRN in table
*/
static inline void _ma_reset_trn_for_table(MARIA_HA *tbl)
{
DBUG_PRINT("info",("table: %p trn: %p -> NULL", tbl, tbl->trn));
tbl->trn= 0;
}
#endif /* _ma_trnman_h */
......@@ -576,6 +576,7 @@ struct st_maria_handler
{
MARIA_SHARE *s; /* Shared between open:s */
struct st_ma_transaction *trn; /* Pointer to active transaction */
struct st_maria_handler *trn_next;
MARIA_STATUS_INFO *state, state_save;
MARIA_STATUS_INFO *state_start; /* State at start of transaction */
MARIA_USED_TABLES *used_tables;
......@@ -824,19 +825,6 @@ struct st_maria_handler
#define get_pack_length(length) ((length) >= 255 ? 3 : 1)
#define _ma_have_versioning(info) ((info)->row_flag & ROW_FLAG_TRANSID)
/**
Sets table's trn and prints debug information
@param tbl MARIA_HA of table
@param newtrn what to put into tbl->trn
@note cast of newtrn is because %p of NULL gives warning (NULL is int)
*/
#define _ma_set_trn_for_table(tbl, newtrn) do { \
DBUG_PRINT("info",("table: %p trn: %p -> %p", \
(tbl), (tbl)->trn, (void *)(newtrn))); \
(tbl)->trn= (newtrn); \
} while (0)
#define MARIA_MIN_BLOCK_LENGTH 20 /* Because of delete-link */
/* Don't use to small record-blocks */
#define MARIA_EXTEND_BLOCK_LENGTH 20
......
......@@ -366,6 +366,7 @@ TRN *trnman_new_trn(WT_THD *wt)
trn->commit_trid= MAX_TRID;
trn->rec_lsn= trn->undo_lsn= trn->first_undo_lsn= 0;
trn->used_tables= 0;
trn->used_instances= 0;
trn->locked_tables= 0;
trn->flags= 0;
......
......@@ -46,7 +46,8 @@ struct st_ma_transaction
LF_PINS *pins;
WT_THD *wt;
mysql_mutex_t state_lock;
void *used_tables; /**< Tables used by transaction */
void *used_tables; /**< Table shares used by transaction */
void *used_instances; /* table files used by transaction */
TRN *next, *prev;
TrID trid, min_read_from, commit_trid;
LSN rec_lsn, undo_lsn;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment