mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge bk-internal.mysql.com:/home/bk/mysql-5.1
into bodhi.(none):/opt/local/work/mysql-5.1-27430 include/my_global.h: Auto merged mysql-test/r/grant.result: Auto merged mysql-test/t/disabled.def: Auto merged mysql-test/t/grant.test: Auto merged sql/item.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/set_var.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_yacc.yy: Auto merged sql/table.h: Auto merged storage/myisam/mi_create.c: Auto merged tests/mysql_client_test.c: Auto merged sql/share/errmsg.txt: Manual merge.
This commit is contained in:
130
sql/table.h
130
sql/table.h
@ -438,6 +438,105 @@ typedef struct st_table_share
|
||||
return table_map_id;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert unrelated members of TABLE_SHARE to one enum
|
||||
representing its metadata type.
|
||||
|
||||
@todo perhaps we need to have a member instead of a function.
|
||||
*/
|
||||
enum enum_metadata_type get_metadata_type() const
|
||||
{
|
||||
if (is_view)
|
||||
return METADATA_VIEW;
|
||||
switch (tmp_table) {
|
||||
case NO_TMP_TABLE:
|
||||
return METADATA_BASE_TABLE;
|
||||
case SYSTEM_TMP_TABLE:
|
||||
return METADATA_I_S_TABLE;
|
||||
default:
|
||||
return METADATA_TMP_TABLE;
|
||||
}
|
||||
}
|
||||
/**
|
||||
Return a table metadata version.
|
||||
* for base tables, we return table_map_id.
|
||||
It is assigned from a global counter incremented for each
|
||||
new table loaded into the table definition cache (TDC).
|
||||
* for temporary tables it's table_map_id again. But for
|
||||
temporary tables table_map_id is assigned from
|
||||
thd->query_id. The latter is assigned from a thread local
|
||||
counter incremented for every new SQL statement. Since
|
||||
temporary tables are thread-local, each temporary table
|
||||
gets a unique id.
|
||||
* for everything else (views, information schema tables),
|
||||
the version id is zero.
|
||||
|
||||
This choice of version id is a large compromise
|
||||
to have a working prepared statement validation in 5.1. In
|
||||
future version ids will be persistent, as described in WL#4180.
|
||||
|
||||
Let's try to explain why and how this limited solution allows
|
||||
to validate prepared statements.
|
||||
|
||||
Firstly, spaces (in mathematical sense) of version numbers
|
||||
never intersect for different metadata types. Therefore,
|
||||
version id of a temporary table is never compared with
|
||||
a version id of a view or a temporary table, and vice versa.
|
||||
|
||||
Secondly, for base tables, we know that each DDL flushes the
|
||||
respective share from the TDC. This ensures that whenever
|
||||
a table is altered or dropped and recreated, it gets a new
|
||||
version id.
|
||||
Unfortunately, since elements of the TDC are also flushed on
|
||||
LRU basis, this choice of version ids leads to false positives.
|
||||
E.g. when the TDC size is too small, we may have a SELECT
|
||||
* FROM INFORMATION_SCHEMA.TABLES flush all its elements, which
|
||||
in turn will lead to a validation error and a subsequent
|
||||
reprepare of all prepared statements. This is
|
||||
considered acceptable, since as long as prepared statements are
|
||||
automatically reprepared, spurious invalidation is only
|
||||
a performance hit. Besides, no better simple solution exists.
|
||||
|
||||
For temporary tables, using thd->query_id ensures that if
|
||||
a temporary table was altered or recreated, a new version id is
|
||||
assigned. This suits validation needs very well and will perhaps
|
||||
never change.
|
||||
|
||||
Metadata of information schema tables never changes.
|
||||
Thus we can safely assume 0 for a good enough version id.
|
||||
|
||||
Views are a special and tricky case. A view is always inlined
|
||||
into the parse tree of a prepared statement at prepare.
|
||||
Thus, when we execute a prepared statement, the parse tree
|
||||
will not get modified even if the view is replaced with another
|
||||
view. Therefore, we can safely choose 0 for version id of
|
||||
views and effectively never invalidate a prepared statement
|
||||
when a view definition is altered. Note, that this leads to
|
||||
wrong binary log in statement-based replication, since we log
|
||||
prepared statement execution in form Query_log_events
|
||||
containing conventional statements. But since there is no
|
||||
metadata locking for views, the very same problem exists for
|
||||
conventional statements alone, as reported in Bug#25144. The only
|
||||
difference between prepared and conventional execution is,
|
||||
effectively, that for prepared statements the race condition
|
||||
window is much wider.
|
||||
In 6.0 we plan to support view metadata locking (WL#3726) and
|
||||
extend table definition cache to cache views (WL#4298).
|
||||
When this is done, views will be handled in the same fashion
|
||||
as the base tables.
|
||||
|
||||
Finally, by taking into account metadata type, we always
|
||||
track that a change has taken place when a view is replaced
|
||||
with a base table, a base table is replaced with a temporary
|
||||
table and so on.
|
||||
|
||||
@sa TABLE_LIST::is_metadata_version_equal()
|
||||
*/
|
||||
ulong get_metadata_version() const
|
||||
{
|
||||
return tmp_table == SYSTEM_TMP_TABLE || is_view ? 0 : table_map_id;
|
||||
}
|
||||
|
||||
} TABLE_SHARE;
|
||||
|
||||
|
||||
@ -1233,6 +1332,33 @@ struct TABLE_LIST
|
||||
child_def_version= ~0UL;
|
||||
}
|
||||
|
||||
/**
|
||||
Compare the version of metadata from the previous execution
|
||||
(if any) with values obtained from the current table
|
||||
definition cache element.
|
||||
|
||||
@sa check_and_update_table_version()
|
||||
*/
|
||||
inline
|
||||
bool is_metadata_version_equal(TABLE_SHARE *s) const
|
||||
{
|
||||
return (m_metadata_type == s->get_metadata_type() &&
|
||||
m_metadata_version == s->get_metadata_version());
|
||||
}
|
||||
|
||||
/**
|
||||
Record the value of metadata version of the corresponding
|
||||
table definition cache element in this parse tree node.
|
||||
|
||||
@sa check_and_update_table_version()
|
||||
*/
|
||||
inline
|
||||
void set_metadata_version(TABLE_SHARE *s)
|
||||
{
|
||||
m_metadata_type= s->get_metadata_type();
|
||||
m_metadata_version= s->get_metadata_version();
|
||||
}
|
||||
|
||||
private:
|
||||
bool prep_check_option(THD *thd, uint8 check_opt_type);
|
||||
bool prep_where(THD *thd, Item **conds, bool no_where_clause);
|
||||
@ -1243,6 +1369,10 @@ private:
|
||||
|
||||
/* Remembered MERGE child def version. See top comment in ha_myisammrg.cc */
|
||||
ulong child_def_version;
|
||||
/** See comments for set_metadata_version() */
|
||||
enum enum_metadata_type m_metadata_type;
|
||||
/** See comments for set_metadata_version() */
|
||||
ulong m_metadata_version;
|
||||
};
|
||||
|
||||
class Item;
|
||||
|
Reference in New Issue
Block a user