Skip to content

Commit 3bbc30c

Browse files
committed
MDEV-13727 top-level query timestamp reset at stored func/trigger internal statements
Being executed under slow_log is ON the test revealed a "side-effect" in MDEV-8305 implementation which inadvertently made the trigger or stored function statements to reset the top-level query's THD::start_time et al. (Details of the test failure analysis are footnoted). Unlike the SP case the SF and Trigger's internal statement should not do that. Fixed with revising the MDEV-8305 decision to backup/reset/restore the session timestamp inside sp_instr_stmt::execute(). The timestamp actually remains reset in the SP case by its caller per statement basis by ever existing logics. Timestamps related tests are extended to cover the trigger and stored function case. Note, commit 3395ab7 is reverted as its struct QUERY_START_TIME_INFO declaration is not in use anymore after this patch. Footnote: -------- Specifically to the failing test, a query on the master was logged okay with a timestamp of the query's top-level statement but its post update trigger managed to compute one more (later) timestamp which got inserted into another table. The latter table master-vs-slave no fractional part timestamp discrepancy became evident thanks to different execution time of the trigger combined with the fact of the logged with micro-second fractional part master timestamp was truncated on the slave. On master when the fractional part was close to 1 the trigger execution added up its own latency to overflow to next second value. That's how the master timestamp surprisingly turned out to bigger than the slave's one.
1 parent 83ec8c8 commit 3bbc30c

File tree

4 files changed

+89
-36
lines changed

4 files changed

+89
-36
lines changed

mysql-test/main/func_time.result

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3511,3 +3511,29 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
35113511
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
35123512
Warnings:
35133513
Note 1003 select TIMESTAMP'2001-01-01 10:20:30' + interval '10' year AS `c1`,TIMESTAMP'2001-01-01 10:20:30' + interval '10' year AS `c2`,TIMESTAMP'2001-01-01 10:20:30' + interval '10' year AS `c3`
3514+
CREATE TABLE t_ts (a timestamp(6));
3515+
CREATE TABLE t_trig (a timestamp(6));
3516+
CREATE FUNCTION fn_sleep_before_now() returns int
3517+
BEGIN
3518+
INSERT INTO t_ts SET a= current_timestamp(6);
3519+
RETURN 0;
3520+
END//
3521+
CREATE TRIGGER trg_insert_t_ts after INSERT on t_ts for each row
3522+
BEGIN
3523+
INSERT into t_trig set a= current_timestamp(6);
3524+
END//
3525+
SET @sav_slow_query_log= @@session.slow_query_log;
3526+
SET @@session.slow_query_log= ON;
3527+
SELECT current_timestamp(6),fn_sleep_before_now() INTO @ts_cur, @ts_func;
3528+
SELECT a FROM t_ts LIMIT 1 into @ts_func;
3529+
SELECT a FROM t_trig LIMIT 1 into @ts_trig;
3530+
DELETE FROM t_ts;
3531+
DELETE FROM t_trig;
3532+
SET @@session.slow_query_log= OFF;
3533+
SELECT current_timestamp(6),fn_sleep_before_now() INTO @ts_cur, @func_ts;
3534+
SELECT a FROM t_ts LIMIT 1 into @ts_func;
3535+
SELECT a FROM t_trig LIMIT 1 into @ts_trig;
3536+
SET @@session.slow_query_log= @sav_slow_query_log;
3537+
DROP FUNCTION fn_sleep_before_now;
3538+
DROP TRIGGER trg_insert_t_ts;
3539+
DROP TABLE t_ts, t_trig;

mysql-test/main/func_time.test

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,3 +2077,61 @@ EXPLAIN EXTENDED SELECT
20772077
TIMESTAMP'2001-01-01 10:20:30' + INTERVAL '10' YEAR AS c1,
20782078
INTERVAL '10' YEAR + TIMESTAMP'2001-01-01 10:20:30' AS c2,
20792079
+INTERVAL '10' YEAR + TIMESTAMP'2001-01-01 10:20:30' AS c3;
2080+
2081+
############
2082+
# MDEV-13727
2083+
# Current timestamp functions inside stored functions must return the
2084+
# value of the top-level statement's timestamp (its start time).
2085+
# This must hold regardless of @@slow_query_log option.
2086+
#
2087+
2088+
CREATE TABLE t_ts (a timestamp(6));
2089+
CREATE TABLE t_trig (a timestamp(6));
2090+
delimiter //;
2091+
CREATE FUNCTION fn_sleep_before_now() returns int
2092+
BEGIN
2093+
INSERT INTO t_ts SET a= current_timestamp(6);
2094+
RETURN 0;
2095+
END//
2096+
CREATE TRIGGER trg_insert_t_ts after INSERT on t_ts for each row
2097+
BEGIN
2098+
INSERT into t_trig set a= current_timestamp(6);
2099+
END//
2100+
delimiter ;//
2101+
2102+
SET @sav_slow_query_log= @@session.slow_query_log;
2103+
2104+
# @@slow_query_log ON check
2105+
SET @@session.slow_query_log= ON;
2106+
SELECT current_timestamp(6),fn_sleep_before_now() INTO @ts_cur, @ts_func;
2107+
2108+
SELECT a FROM t_ts LIMIT 1 into @ts_func;
2109+
SELECT a FROM t_trig LIMIT 1 into @ts_trig;
2110+
if (!`SELECT @ts_cur = @ts_func and @ts_func = @ts_trig`)
2111+
{
2112+
SELECT @ts_cur, @ts_func, @ts_trig;
2113+
--die Error: timestamps must be equal but they diverge
2114+
}
2115+
DELETE FROM t_ts;
2116+
DELETE FROM t_trig;
2117+
2118+
# @@slow_query_log OFF check
2119+
SET @@session.slow_query_log= OFF;
2120+
SELECT current_timestamp(6),fn_sleep_before_now() INTO @ts_cur, @func_ts;
2121+
SELECT a FROM t_ts LIMIT 1 into @ts_func;
2122+
SELECT a FROM t_trig LIMIT 1 into @ts_trig;
2123+
if (!`SELECT @ts_cur = @ts_func and @ts_func = @ts_trig`)
2124+
{
2125+
SELECT @ts_cur, @ts_func, @ts_trig;
2126+
--die Error: timestamps must be equal but they diverge
2127+
}
2128+
2129+
# Cleanup
2130+
SET @@session.slow_query_log= @sav_slow_query_log;
2131+
DROP FUNCTION fn_sleep_before_now;
2132+
DROP TRIGGER trg_insert_t_ts;
2133+
DROP TABLE t_ts, t_trig;
2134+
2135+
#
2136+
# End of MDEV-13727
2137+
###################

sql/sp_head.cc

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3473,7 +3473,6 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
34733473
int res;
34743474
bool save_enable_slow_log;
34753475
const CSET_STRING query_backup= thd->query_string;
3476-
QUERY_START_TIME_INFO time_info;
34773476
Sub_statement_state backup_state;
34783477
DBUG_ENTER("sp_instr_stmt::execute");
34793478
DBUG_PRINT("info", ("command: %d", m_lex_keeper.sql_command()));
@@ -3483,15 +3482,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
34833482
thd->profiling.set_query_source(m_query.str, m_query.length);
34843483
#endif
34853484

3486-
if ((save_enable_slow_log= thd->enable_slow_log))
3487-
{
3488-
/*
3489-
Save start time info for the CALL statement and overwrite it with the
3490-
current time for log_slow_statement() to log the individual query timing.
3491-
*/
3492-
thd->backup_query_start_time(&time_info);
3493-
thd->set_time();
3494-
}
3485+
save_enable_slow_log= thd->enable_slow_log;
34953486
thd->store_slow_query_state(&backup_state);
34963487

34973488
if (!(res= alloc_query(thd, m_query.str, m_query.length)) &&
@@ -3555,9 +3546,6 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
35553546
thd->get_stmt_da()->reset_diagnostics_area();
35563547
}
35573548
}
3558-
/* Restore the original query start time */
3559-
if (thd->enable_slow_log)
3560-
thd->restore_query_start_time(&time_info);
35613549

35623550
DBUG_RETURN(res || thd->is_error());
35633551
}

sql/sql_class.h

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2139,26 +2139,6 @@ struct wait_for_commit
21392139
void reinit();
21402140
};
21412141

2142-
/*
2143-
Structure to store the start time for a query
2144-
*/
2145-
2146-
struct QUERY_START_TIME_INFO
2147-
{
2148-
my_time_t start_time;
2149-
ulong start_time_sec_part;
2150-
ulonglong start_utime, utime_after_lock;
2151-
2152-
void backup_query_start_time(QUERY_START_TIME_INFO *backup)
2153-
{
2154-
*backup= *this;
2155-
}
2156-
void restore_query_start_time(QUERY_START_TIME_INFO *backup)
2157-
{
2158-
*this= *backup;
2159-
}
2160-
};
2161-
21622142
extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
21632143

21642144
/**
@@ -2177,8 +2157,7 @@ class THD :public Statement,
21772157
*/
21782158
public Item_change_list,
21792159
public MDL_context_owner,
2180-
public Open_tables_state,
2181-
public QUERY_START_TIME_INFO
2160+
public Open_tables_state
21822161
{
21832162
private:
21842163
inline bool is_stmt_prepare() const
@@ -2403,10 +2382,12 @@ class THD :public Statement,
24032382
uint32 file_id;// for LOAD DATA INFILE
24042383
/* remote (peer) port */
24052384
uint16 peer_port;
2385+
my_time_t start_time; // start_time and its sec_part
2386+
ulong start_time_sec_part; // are almost always used separately
24062387
my_hrtime_t user_time;
24072388
// track down slow pthread_create
24082389
ulonglong prior_thr_create_utime, thr_create_utime;
2409-
ulonglong utime_after_query;
2390+
ulonglong start_utime, utime_after_lock, utime_after_query;
24102391

24112392
// Process indicator
24122393
struct {

0 commit comments

Comments
 (0)