Commit 8b0c705c authored by Konstantin Osipov's avatar Konstantin Osipov

A follow up patch for the fix for Bug#51263 "Deadlock between

 transactional SELECT and ALTER TABLE ...  REBUILD PARTITION".

Move declarations of sql_base.cc classes to sql_base.h
(previously declared in sql_class.h).
Became possible after a header file split.

parent 08589ba9
...@@ -16,11 +16,11 @@ ...@@ -16,11 +16,11 @@
/* Basic functions needed by many modules */ /* Basic functions needed by many modules */
#include "sql_base.h" // setup_table_map
#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h" #include "sql_priv.h"
#include "unireg.h" #include "unireg.h"
#include "debug_sync.h" #include "debug_sync.h"
#include "sql_base.h" // setup_table_map
#include "lock.h" // broadcast_refresh, mysql_lock_remove, #include "lock.h" // broadcast_refresh, mysql_lock_remove,
// mysql_unlock_tables, // mysql_unlock_tables,
// mysql_lock_have_duplicate // mysql_lock_have_duplicate
......
...@@ -322,6 +322,7 @@ inline TABLE_LIST *find_table_in_local_list(TABLE_LIST *table, ...@@ -322,6 +322,7 @@ inline TABLE_LIST *find_table_in_local_list(TABLE_LIST *table,
db_name, table_name); db_name, table_name);
} }
inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array, inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array,
List<Item> &item, List<Item> &item,
enum_mark_columns mark_used_columns, enum_mark_columns mark_used_columns,
...@@ -336,6 +337,89 @@ inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array, ...@@ -336,6 +337,89 @@ inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array,
return res; return res;
} }
/**
An abstract class for a strategy specifying how the prelocking
algorithm should extend the prelocking set while processing
already existing elements in the set.
*/
class Prelocking_strategy
{
public:
virtual ~Prelocking_strategy() { }
virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
Sroutine_hash_entry *rt, sp_head *sp,
bool *need_prelocking) = 0;
virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking) = 0;
virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking)= 0;
};
/**
A Strategy for prelocking algorithm suitable for DML statements.
Ensures that all tables used by all statement's SF/SP/triggers and
required for foreign key checks are prelocked and SF/SPs used are
cached.
*/
class DML_prelocking_strategy : public Prelocking_strategy
{
public:
virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
Sroutine_hash_entry *rt, sp_head *sp,
bool *need_prelocking);
virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking);
virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking);
};
/**
A strategy for prelocking algorithm to be used for LOCK TABLES
statement.
*/
class Lock_tables_prelocking_strategy : public DML_prelocking_strategy
{
virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking);
};
/**
Strategy for prelocking algorithm to be used for ALTER TABLE statements.
Unlike DML or LOCK TABLES strategy, it doesn't
prelock triggers, views or stored routines, since they are not
used during ALTER.
*/
class Alter_table_prelocking_strategy : public Prelocking_strategy
{
public:
Alter_table_prelocking_strategy(Alter_info *alter_info)
: m_alter_info(alter_info)
{}
virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
Sroutine_hash_entry *rt, sp_head *sp,
bool *need_prelocking);
virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking);
virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking);
private:
Alter_info *m_alter_info;
};
inline bool inline bool
open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags) open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags)
{ {
...@@ -355,4 +439,84 @@ inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables, ...@@ -355,4 +439,84 @@ inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
&prelocking_strategy); &prelocking_strategy);
} }
/**
A context of open_tables() function, used to recover
from a failed open_table() or open_routine() attempt.
*/
class Open_table_context
{
public:
enum enum_open_table_action
{
OT_NO_ACTION= 0,
OT_WAIT_MDL_LOCK,
OT_WAIT_TDC,
OT_DISCOVER,
OT_REPAIR
};
Open_table_context(THD *thd, ulong timeout);
bool recover_from_failed_open(THD *thd);
bool request_backoff_action(enum_open_table_action action_arg,
MDL_request *mdl_request, TABLE_LIST *table);
void add_request(MDL_request *request)
{ m_mdl_requests.push_front(request); }
bool can_recover_from_failed_open() const
{ return m_action != OT_NO_ACTION; }
/**
When doing a back-off, we close all tables acquired by this
statement. Return an MDL savepoint taken at the beginning of
the statement, so that we can rollback to it before waiting on
locks.
*/
MDL_ticket *start_of_statement_svp() const
{
return m_start_of_statement_svp;
}
MDL_request *get_global_mdl_request(THD *thd);
inline ulong get_timeout() const
{
return m_timeout;
}
private:
/** List of requests for all locks taken so far. Used for waiting on locks. */
MDL_request_list m_mdl_requests;
/** Back off action. */
enum enum_open_table_action m_action;
/** For OT_WAIT_MDL_LOCK action, the request for which we should wait. */
MDL_request *m_failed_mdl_request;
/**
For OT_DISCOVER and OT_REPAIR actions, the table list element for
the table which definition should be re-discovered or which
should be repaired.
*/
TABLE_LIST *m_failed_table;
MDL_ticket *m_start_of_statement_svp;
/**
Whether we had any locks when this context was created.
If we did, they are from the previous statement of a transaction,
and we can't safely do back-off (and release them).
*/
bool m_has_locks;
/**
Request object for global intention exclusive lock which is acquired during
opening tables for statements which take upgradable shared metadata locks.
*/
MDL_request *m_global_mdl_request;
/**
Lock timeout in seconds. Initialized to LONG_TIMEOUT when opening system
tables or to the "lock_wait_timeout" system variable for regular tables.
*/
uint m_timeout;
};
#endif /* SQL_BASE_INCLUDED */ #endif /* SQL_BASE_INCLUDED */
...@@ -1226,170 +1226,6 @@ class Drop_table_error_handler : public Internal_error_handler ...@@ -1226,170 +1226,6 @@ class Drop_table_error_handler : public Internal_error_handler
}; };
/**
An abstract class for a strategy specifying how the prelocking
algorithm should extend the prelocking set while processing
already existing elements in the set.
*/
class Prelocking_strategy
{
public:
virtual ~Prelocking_strategy() { }
virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
Sroutine_hash_entry *rt, sp_head *sp,
bool *need_prelocking) = 0;
virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking) = 0;
virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking)= 0;
};
/**
A Strategy for prelocking algorithm suitable for DML statements.
Ensures that all tables used by all statement's SF/SP/triggers and
required for foreign key checks are prelocked and SF/SPs used are
cached.
*/
class DML_prelocking_strategy : public Prelocking_strategy
{
public:
virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
Sroutine_hash_entry *rt, sp_head *sp,
bool *need_prelocking);
virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking);
virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking);
};
/**
A strategy for prelocking algorithm to be used for LOCK TABLES
statement.
*/
class Lock_tables_prelocking_strategy : public DML_prelocking_strategy
{
virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking);
};
/**
Strategy for prelocking algorithm to be used for ALTER TABLE statements.
Unlike DML or LOCK TABLES strategy, it doesn't
prelock triggers, views or stored routines, since they are not
used during ALTER.
*/
class Alter_table_prelocking_strategy : public Prelocking_strategy
{
public:
Alter_table_prelocking_strategy(Alter_info *alter_info)
: m_alter_info(alter_info)
{}
virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
Sroutine_hash_entry *rt, sp_head *sp,
bool *need_prelocking);
virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking);
virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking);
private:
Alter_info *m_alter_info;
};
/**
A context of open_tables() function, used to recover
from a failed open_table() or open_routine() attempt.
Implemented in sql_base.cc.
*/
class Open_table_context
{
public:
enum enum_open_table_action
{
OT_NO_ACTION= 0,
OT_WAIT_MDL_LOCK,
OT_WAIT_TDC,
OT_DISCOVER,
OT_REPAIR
};
Open_table_context(THD *thd, ulong timeout);
bool recover_from_failed_open(THD *thd);
bool request_backoff_action(enum_open_table_action action_arg,
MDL_request *mdl_request, TABLE_LIST *table);
void add_request(MDL_request *request)
{ m_mdl_requests.push_front(request); }
bool can_recover_from_failed_open() const
{ return m_action != OT_NO_ACTION; }
/**
When doing a back-off, we close all tables acquired by this
statement. Return an MDL savepoint taken at the beginning of
the statement, so that we can rollback to it before waiting on
locks.
*/
MDL_ticket *start_of_statement_svp() const
{
return m_start_of_statement_svp;
}
MDL_request *get_global_mdl_request(THD *thd);
inline ulong get_timeout() const
{
return m_timeout;
}
private:
/** List of requests for all locks taken so far. Used for waiting on locks. */
MDL_request_list m_mdl_requests;
/** Back off action. */
enum enum_open_table_action m_action;
/** For OT_WAIT_MDL_LOCK action, the request for which we should wait. */
MDL_request *m_failed_mdl_request;
/**
For OT_DISCOVER and OT_REPAIR actions, the table list element for
the table which definition should be re-discovered or which
should be repaired.
*/
TABLE_LIST *m_failed_table;
MDL_ticket *m_start_of_statement_svp;
/**
Whether we had any locks when this context was created.
If we did, they are from the previous statement of a transaction,
and we can't safely do back-off (and release them).
*/
bool m_has_locks;
/**
Request object for global intention exclusive lock which is acquired during
opening tables for statements which take upgradable shared metadata locks.
*/
MDL_request *m_global_mdl_request;
/**
Lock timeout in seconds. Initialized to LONG_TIMEOUT when opening system
tables or to the "lock_wait_timeout" system variable for regular tables.
*/
uint m_timeout;
};
/** /**
Tables that were locked with LOCK TABLES statement. Tables that were locked with LOCK TABLES statement.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment