diff --git a/mysql-test/suite/versioning/r/trx_id.result b/mysql-test/suite/versioning/r/trx_id.result index 3bf5c5175c0..31989a30ebf 100644 --- a/mysql-test/suite/versioning/r/trx_id.result +++ b/mysql-test/suite/versioning/r/trx_id.result @@ -166,5 +166,20 @@ select * from t1 for system_time as of timestamp'1990-1-1 00:00'; x select * from t1 for system_time as of NULL; 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; create database test; diff --git a/mysql-test/suite/versioning/t/trx_id.opt b/mysql-test/suite/versioning/t/trx_id.opt new file mode 100644 index 00000000000..412290a7585 --- /dev/null +++ b/mysql-test/suite/versioning/t/trx_id.opt @@ -0,0 +1 @@ +--plugin-load-add=test_versioning diff --git a/mysql-test/suite/versioning/t/trx_id.test b/mysql-test/suite/versioning/t/trx_id.test index 0bf0e320835..4fb15f35366 100644 --- a/mysql-test/suite/versioning/t/trx_id.test +++ b/mysql-test/suite/versioning/t/trx_id.test @@ -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 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; create database test; diff --git a/sql/sql_class.h b/sql/sql_class.h index bc4f37175a5..e453eb9ce60 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2627,6 +2627,15 @@ public: WT_THD wt; ///< for deadlock detection 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). List contain only transactional tables, that not invalidated in query @@ -3470,6 +3479,13 @@ private: } public: + timeval transaction_time() + { + if (!in_multi_stmt_transaction_mode()) + transaction.start_time.reset(this); + return transaction.start_time; + } + inline void set_start_time() { if (user_time.val) diff --git a/sql/table.cc b/sql/table.cc index 3e0b601d49d..a6e445d0d2e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8612,12 +8612,10 @@ bool TR_table::update(ulonglong start_id, ulonglong end_id) if (!table && open()) return true; - timeval start_time= {thd->query_start(), long(thd->query_start_sec_part())}; - thd->set_start_time(); + store(FLD_BEGIN_TS, thd->transaction_time()); timeval end_time= {thd->query_start(), long(thd->query_start_sec_part())}; store(FLD_TRX_ID, start_id); store(FLD_COMMIT_ID, end_id); - store(FLD_BEGIN_TS, start_time); store(FLD_COMMIT_TS, end_time); store_iso_level(thd->tx_isolation); diff --git a/sql/transaction.cc b/sql/transaction.cc index e81e2dba9c6..1c2820200d1 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -203,6 +203,7 @@ bool trans_begin(THD *thd, uint flags) thd->transaction.all.reset(); thd->has_waiter= false; thd->waiting_on_group_commit= false; + thd->transaction.start_time.reset(thd); if (res) DBUG_RETURN(TRUE);