summaryrefslogtreecommitdiff
path: root/sql/sql_prepare.cc
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2019-04-17 15:50:59 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2022-01-24 14:41:06 +0100
commit349283c5e7a3a338445140156e866d6ade939edf (patch)
treeee5f87b18649f9b4ac55239bce87826c0f06bc31 /sql/sql_prepare.cc
parentecfa9361406f9007af8a808567909a519aa9984b (diff)
downloadmariadb-git-bb-10.2-MDEV-17124.tar.gz
MDEV-17124: mariadb 10.1.34, views and prepared statements: ERROR 1615 (HY000): Prepared statement needs to be re-preparedbb-10.2-MDEV-17124
The problem is that if table definition cache (TDC) is full of real tables which are in tables cache, view definition can not stay there so will be removed by its own underlying tables. In situation above old mechanism of detection matching definition in PS and current version always require reprepare and so prevent executing the PS. One work around is to increase TDC, other - improve version check for views/triggers (which is done here). Now in suspicious cases we check: - timestamp (ms) of the view to be sure that version really have changed; - time (ms) of creation of a trigger related to time (ms) of statement preparation.
Diffstat (limited to 'sql/sql_prepare.cc')
-rw-r--r--sql/sql_prepare.cc22
1 files changed, 21 insertions, 1 deletions
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 64e4cd30561..a4a24cc1a80 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -4177,6 +4177,9 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
Query_arena *old_stmt_arena;
DBUG_ENTER("Prepared_statement::prepare");
DBUG_ASSERT(m_sql_mode == thd->variables.sql_mode);
+
+ // The same format as for triggers to compare
+ ms_prepare_time= my_hrtime().val;
/*
If this is an SQLCOM_PREPARE, we also increase Com_prepare_sql.
However, it seems handy if com_stmt_prepare is increased always,
@@ -4435,8 +4438,9 @@ Prepared_statement::execute_loop(String *expanded_query,
uchar *packet_end)
{
Reprepare_observer reprepare_observer;
- bool error;
+ ulonglong first_prepared= ms_prepare_time;
int reprepare_attempt= 0;
+ bool error;
iterations= FALSE;
/*
@@ -4519,6 +4523,22 @@ reexecute:
DBUG_ASSERT(thd->get_stmt_da()->sql_errno() == ER_NEED_REPREPARE);
thd->clear_error();
+ {
+ /*
+ Check if we too fast with reprepare:
+ we can be so fast that:
+ 1) make change of a trigger,
+ 2) prepare,
+ 3) try to exacute and reprepare
+ in 1 microsecond, so we will wait till
+ next microsecond before last reprepare
+ */
+ while (first_prepared == my_hrtime().val)
+ {
+ pthread_yield();
+ }
+ }
+
error= reprepare();
if (! error) /* Success */