mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge 10.2 into bb-10.2-ext
This commit is contained in:
@ -2,7 +2,7 @@
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
the Free Software Foundation; version 2 of the License.x1
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@ -16,6 +16,7 @@
|
||||
#include <mysqld.h>
|
||||
#include <sql_class.h>
|
||||
#include <sql_parse.h>
|
||||
#include <sql_base.h> /* find_temporary_table() */
|
||||
#include "slave.h"
|
||||
#include "rpl_mi.h"
|
||||
#include "sql_repl.h"
|
||||
@ -983,8 +984,6 @@ bool wsrep_must_sync_wait (THD* thd, uint mask)
|
||||
{
|
||||
return (thd->variables.wsrep_sync_wait & mask) &&
|
||||
thd->variables.wsrep_on &&
|
||||
!(thd->variables.wsrep_dirty_reads &&
|
||||
!is_update_query(thd->lex->sql_command)) &&
|
||||
!thd->in_active_multi_stmt_transaction() &&
|
||||
thd->wsrep_conflict_state != REPLAYING &&
|
||||
thd->wsrep_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED;
|
||||
@ -1113,83 +1112,70 @@ static bool wsrep_prepare_keys_for_isolation(THD* thd,
|
||||
const TABLE_LIST* table_list,
|
||||
wsrep_key_arr_t* ka)
|
||||
{
|
||||
ka->keys= 0;
|
||||
ka->keys_len= 0;
|
||||
ka->keys= 0;
|
||||
ka->keys_len= 0;
|
||||
|
||||
if (db || table)
|
||||
if (db || table)
|
||||
{
|
||||
if (!(ka->keys= (wsrep_key_t*)my_malloc(sizeof(wsrep_key_t), MYF(0))))
|
||||
{
|
||||
TABLE_LIST tmp_table;
|
||||
|
||||
memset(&tmp_table, 0, sizeof(tmp_table));
|
||||
tmp_table.table_name= (char*)table;
|
||||
tmp_table.db= (char*)db;
|
||||
tmp_table.mdl_request.init(MDL_key::GLOBAL, (db) ? db : "",
|
||||
(table) ? table : "",
|
||||
MDL_INTENTION_EXCLUSIVE, MDL_STATEMENT);
|
||||
|
||||
if (!table || !thd->find_temporary_table(&tmp_table))
|
||||
{
|
||||
if (!(ka->keys= (wsrep_key_t*)my_malloc(sizeof(wsrep_key_t), MYF(0))))
|
||||
{
|
||||
WSREP_ERROR("Can't allocate memory for key_array");
|
||||
goto err;
|
||||
}
|
||||
ka->keys_len= 1;
|
||||
if (!(ka->keys[0].key_parts= (wsrep_buf_t*)
|
||||
my_malloc(sizeof(wsrep_buf_t)*2, MYF(0))))
|
||||
{
|
||||
WSREP_ERROR("Can't allocate memory for key_parts");
|
||||
goto err;
|
||||
}
|
||||
ka->keys[0].key_parts_num= 2;
|
||||
if (!wsrep_prepare_key_for_isolation(
|
||||
db, table,
|
||||
(wsrep_buf_t*)ka->keys[0].key_parts,
|
||||
&ka->keys[0].key_parts_num))
|
||||
{
|
||||
WSREP_ERROR("Preparing keys for isolation failed");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
WSREP_ERROR("Can't allocate memory for key_array");
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (const TABLE_LIST* table= table_list; table; table= table->next_global)
|
||||
ka->keys_len= 1;
|
||||
if (!(ka->keys[0].key_parts= (wsrep_buf_t*)
|
||||
my_malloc(sizeof(wsrep_buf_t)*2, MYF(0))))
|
||||
{
|
||||
if (!thd->find_temporary_table(table))
|
||||
{
|
||||
wsrep_key_t* tmp;
|
||||
tmp= (wsrep_key_t*)my_realloc(
|
||||
ka->keys, (ka->keys_len + 1) * sizeof(wsrep_key_t),
|
||||
MYF(MY_ALLOW_ZERO_PTR));
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
WSREP_ERROR("Can't allocate memory for key_array");
|
||||
goto err;
|
||||
}
|
||||
ka->keys= tmp;
|
||||
if (!(ka->keys[ka->keys_len].key_parts= (wsrep_buf_t*)
|
||||
my_malloc(sizeof(wsrep_buf_t)*2, MYF(0))))
|
||||
{
|
||||
WSREP_ERROR("Can't allocate memory for key_parts");
|
||||
goto err;
|
||||
}
|
||||
ka->keys[ka->keys_len].key_parts_num= 2;
|
||||
++ka->keys_len;
|
||||
if (!wsrep_prepare_key_for_isolation(
|
||||
table->db, table->table_name,
|
||||
(wsrep_buf_t*)ka->keys[ka->keys_len - 1].key_parts,
|
||||
&ka->keys[ka->keys_len - 1].key_parts_num))
|
||||
{
|
||||
WSREP_ERROR("Preparing keys for isolation failed");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
WSREP_ERROR("Can't allocate memory for key_parts");
|
||||
goto err;
|
||||
}
|
||||
ka->keys[0].key_parts_num= 2;
|
||||
if (!wsrep_prepare_key_for_isolation(
|
||||
db, table,
|
||||
(wsrep_buf_t*)ka->keys[0].key_parts,
|
||||
&ka->keys[0].key_parts_num))
|
||||
{
|
||||
WSREP_ERROR("Preparing keys for isolation failed (1)");
|
||||
goto err;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const TABLE_LIST* table= table_list; table; table= table->next_global)
|
||||
{
|
||||
wsrep_key_t* tmp;
|
||||
if (ka->keys)
|
||||
tmp= (wsrep_key_t*)my_realloc(ka->keys,
|
||||
(ka->keys_len + 1) * sizeof(wsrep_key_t),
|
||||
MYF(0));
|
||||
else
|
||||
tmp= (wsrep_key_t*)my_malloc((ka->keys_len + 1) * sizeof(wsrep_key_t), MYF(0));
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
WSREP_ERROR("Can't allocate memory for key_array");
|
||||
goto err;
|
||||
}
|
||||
ka->keys= tmp;
|
||||
if (!(ka->keys[ka->keys_len].key_parts= (wsrep_buf_t*)
|
||||
my_malloc(sizeof(wsrep_buf_t)*2, MYF(0))))
|
||||
{
|
||||
WSREP_ERROR("Can't allocate memory for key_parts");
|
||||
goto err;
|
||||
}
|
||||
ka->keys[ka->keys_len].key_parts_num= 2;
|
||||
++ka->keys_len;
|
||||
if (!wsrep_prepare_key_for_isolation(table->db, table->table_name,
|
||||
(wsrep_buf_t*)ka->keys[ka->keys_len - 1].key_parts,
|
||||
&ka->keys[ka->keys_len - 1].key_parts_num))
|
||||
{
|
||||
WSREP_ERROR("Preparing keys for isolation failed (2)");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
wsrep_keys_free(ka);
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -1403,6 +1389,84 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len)
|
||||
static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len);
|
||||
static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
|
||||
|
||||
/*
|
||||
Decide if statement should run in TOI.
|
||||
|
||||
Look if table or table_list contain temporary tables. If the
|
||||
statement affects only temporary tables, statement should not run
|
||||
in TOI. If the table list contains mix of regular and temporary tables
|
||||
(DROP TABLE, OPTIMIZE, ANALYZE), statement should be run in TOI but
|
||||
should be rewritten at later time for replication to contain only
|
||||
non-temporary tables.
|
||||
*/
|
||||
static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
|
||||
const TABLE_LIST *table_list)
|
||||
{
|
||||
DBUG_ASSERT(!table || db);
|
||||
DBUG_ASSERT(table_list || db);
|
||||
|
||||
LEX* lex= thd->lex;
|
||||
SELECT_LEX* select_lex= &lex->select_lex;
|
||||
TABLE_LIST* first_table= select_lex->table_list.first;
|
||||
|
||||
switch (lex->sql_command)
|
||||
{
|
||||
case SQLCOM_CREATE_TABLE:
|
||||
DBUG_ASSERT(!table_list);
|
||||
if (thd->lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
case SQLCOM_CREATE_VIEW:
|
||||
|
||||
DBUG_ASSERT(!table_list);
|
||||
DBUG_ASSERT(first_table); /* First table is view name */
|
||||
/*
|
||||
If any of the remaining tables refer to temporary table error
|
||||
is returned to client, so TOI can be skipped
|
||||
*/
|
||||
for (TABLE_LIST* it= first_table->next_global; it; it= it->next_global)
|
||||
{
|
||||
if (thd->find_temporary_table(it))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
case SQLCOM_CREATE_TRIGGER:
|
||||
|
||||
DBUG_ASSERT(!table_list);
|
||||
DBUG_ASSERT(first_table);
|
||||
|
||||
if (thd->find_temporary_table(first_table))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
if (table && !thd->find_temporary_table(db, table))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (table_list)
|
||||
{
|
||||
for (TABLE_LIST* table= first_table; table; table= table->next_global)
|
||||
{
|
||||
if (!thd->find_temporary_table(table->db, table->table_name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !(table || table_list);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
returns:
|
||||
0: statement was replicated as TOI
|
||||
@ -1418,6 +1482,12 @@ static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_,
|
||||
int buf_err;
|
||||
int rc= 0;
|
||||
|
||||
if (wsrep_can_run_in_toi(thd, db_, table_, table_list) == false)
|
||||
{
|
||||
WSREP_DEBUG("No TOI for %s", WSREP_QUERY(thd));
|
||||
return 1;
|
||||
}
|
||||
|
||||
WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd),
|
||||
thd->wsrep_exec_mode, thd->query() );
|
||||
switch (thd->lex->sql_command)
|
||||
@ -1445,16 +1515,16 @@ static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_,
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), &buf,
|
||||
&buf_len);
|
||||
buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(),
|
||||
&buf, &buf_len);
|
||||
break;
|
||||
}
|
||||
|
||||
wsrep_key_arr_t key_arr= {0, 0};
|
||||
struct wsrep_buf buff = { buf, buf_len };
|
||||
if (!buf_err &&
|
||||
wsrep_prepare_keys_for_isolation(thd, db_, table_, table_list, &key_arr)&&
|
||||
key_arr.keys_len > 0 &&
|
||||
if (!buf_err &&
|
||||
!wsrep_prepare_keys_for_isolation(thd, db_, table_, table_list, &key_arr) &&
|
||||
key_arr.keys_len > 0 &&
|
||||
WSREP_OK == (ret = wsrep->to_execute_start(wsrep, thd->thread_id,
|
||||
key_arr.keys, key_arr.keys_len,
|
||||
&buff, 1,
|
||||
@ -1651,9 +1721,12 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
|
||||
if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE)
|
||||
{
|
||||
switch (thd->variables.wsrep_OSU_method) {
|
||||
case WSREP_OSU_TOI: ret = wsrep_TOI_begin(thd, db_, table_,
|
||||
table_list); break;
|
||||
case WSREP_OSU_RSU: ret = wsrep_RSU_begin(thd, db_, table_); break;
|
||||
case WSREP_OSU_TOI:
|
||||
ret = wsrep_TOI_begin(thd, db_, table_, table_list);
|
||||
break;
|
||||
case WSREP_OSU_RSU:
|
||||
ret = wsrep_RSU_begin(thd, db_, table_);
|
||||
break;
|
||||
default:
|
||||
WSREP_ERROR("Unsupported OSU method: %lu",
|
||||
thd->variables.wsrep_OSU_method);
|
||||
|
Reference in New Issue
Block a user