MDEV-16024 transaction_registry.begin_timestamp is wrong for explicit transactions

Store transaction start time in thd->transaction.start_time.
THD::transaction_time() wraps over transaction.start_time taking into
account current status of BEGIN.
This commit is contained in:
Aleksey Midenkov 2018-04-25 23:33:08 +03:00 committed by Sergei Golubchik
parent fd4153f083
commit 68cad6aa24
6 changed files with 50 additions and 3 deletions

View File

@ -166,5 +166,20 @@ select * from t1 for system_time as of timestamp'1990-1-1 00:00';
x x
select * from t1 for system_time as of NULL; select * from t1 for system_time as of NULL;
x x
# MDEV-16024 transaction_registry.begin_timestamp is wrong for explicit transactions
create or replace table t1 (
x int(11) default null,
row_start bigint(20) unsigned generated always as row start invisible,
row_end bigint(20) unsigned generated always as row end invisible,
period for system_time (row_start, row_end)
) engine=innodb with system versioning;
begin;
set @ts1= now(6);
insert into t1 values (1);
commit;
select row_start from t1 into @trx_id;
select trt_begin_ts(@trx_id) <= @ts1 as BEGIN_TS_GOOD;
BEGIN_TS_GOOD
1
drop database test; drop database test;
create database test; create database test;

View File

@ -0,0 +1 @@
--plugin-load-add=test_versioning

View File

@ -153,5 +153,21 @@ delete from t1;
select * from t1 for system_time as of timestamp'1990-1-1 00:00'; select * from t1 for system_time as of timestamp'1990-1-1 00:00';
select * from t1 for system_time as of NULL; select * from t1 for system_time as of NULL;
--echo # MDEV-16024 transaction_registry.begin_timestamp is wrong for explicit transactions
create or replace table t1 (
x int(11) default null,
row_start bigint(20) unsigned generated always as row start invisible,
row_end bigint(20) unsigned generated always as row end invisible,
period for system_time (row_start, row_end)
) engine=innodb with system versioning;
begin;
set @ts1= now(6);
--sleep 0.01
insert into t1 values (1);
commit;
select row_start from t1 into @trx_id;
select trt_begin_ts(@trx_id) <= @ts1 as BEGIN_TS_GOOD;
drop database test; drop database test;
create database test; create database test;

View File

@ -2627,6 +2627,15 @@ public:
WT_THD wt; ///< for deadlock detection WT_THD wt; ///< for deadlock detection
Rows_log_event *m_pending_rows_event; Rows_log_event *m_pending_rows_event;
struct st_trans_time : public timeval
{
void reset(THD *thd)
{
tv_sec= thd->query_start();
tv_usec= (long) thd->query_start_sec_part();
}
} start_time;
/* /*
Tables changed in transaction (that must be invalidated in query cache). Tables changed in transaction (that must be invalidated in query cache).
List contain only transactional tables, that not invalidated in query List contain only transactional tables, that not invalidated in query
@ -3470,6 +3479,13 @@ private:
} }
public: public:
timeval transaction_time()
{
if (!in_multi_stmt_transaction_mode())
transaction.start_time.reset(this);
return transaction.start_time;
}
inline void set_start_time() inline void set_start_time()
{ {
if (user_time.val) if (user_time.val)

View File

@ -8612,12 +8612,10 @@ bool TR_table::update(ulonglong start_id, ulonglong end_id)
if (!table && open()) if (!table && open())
return true; return true;
timeval start_time= {thd->query_start(), long(thd->query_start_sec_part())}; store(FLD_BEGIN_TS, thd->transaction_time());
thd->set_start_time();
timeval end_time= {thd->query_start(), long(thd->query_start_sec_part())}; timeval end_time= {thd->query_start(), long(thd->query_start_sec_part())};
store(FLD_TRX_ID, start_id); store(FLD_TRX_ID, start_id);
store(FLD_COMMIT_ID, end_id); store(FLD_COMMIT_ID, end_id);
store(FLD_BEGIN_TS, start_time);
store(FLD_COMMIT_TS, end_time); store(FLD_COMMIT_TS, end_time);
store_iso_level(thd->tx_isolation); store_iso_level(thd->tx_isolation);

View File

@ -203,6 +203,7 @@ bool trans_begin(THD *thd, uint flags)
thd->transaction.all.reset(); thd->transaction.all.reset();
thd->has_waiter= false; thd->has_waiter= false;
thd->waiting_on_group_commit= false; thd->waiting_on_group_commit= false;
thd->transaction.start_time.reset(thd);
if (res) if (res)
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);