1
0
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:
Marko Mäkelä
2017-09-01 08:47:55 +03:00
318 changed files with 12436 additions and 1800 deletions

View File

@ -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);