mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
Bug#51851: Server with SBR locks mutex twice on LOAD DATA
into partitioned MyISAM table Problem was that the ha_data structure was introduced in 5.1 and only used for partitioning first, but with the intention of be of use for others engines as well, and when used by other engines it would clash if it also was partitioned. Solution is to move the partitioning specific data to a separate structure, with its own mutex (which is used for auto_increment). Also did rename PARTITION_INFO to PARTITION_STATS since there already exist a class named partition_info, also cleaned up some related variables. mysql-test/r/partition_binlog_stmt.result: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table New result file mysql-test/t/partition_binlog_stmt.test: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table New result file sql/ha_ndbcluster.cc: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Rename of PARTITION_INFO to PARTITION_STATS to better match the use (and there is also a class named partition_info...) sql/ha_ndbcluster.h: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Rename of PARTITION_INFO to PARTITION_STATS to better match the use (and there is also a class named partition_info...) sql/ha_partition.cc: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Removed the partitioning engines use of ha_data in TABLE_SHARE and added ha_part_data instead, since they collide if used in the same time. Rename of PARTITION_INFO to PARTITION_STATS to better match the use (and there is also a class named partition_info...) Removed some dead code. sql/ha_partition.h: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Removed some dead code. Rename of PARTITION_INFO to PARTITION_STATS to better match the use (and there is also a class named partition_info...) Removed the partitioning engines use of ha_data in TABLE_SHARE and added ha_part_data instead, since they collide if used in the same time. sql/handler.cc: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Rename of PARTITION_INFO to PARTITION_STATS to better match the use (and there is also a class named partition_info...) sql/handler.h: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Rename of PARTITION_INFO to PARTITION_STATS to better match the use (and there is also a class named partition_info...) sql/mysql_priv.h: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Removed the partitioning engines use of ha_data in TABLE_SHARE and added ha_part_data instead, since they collide if used in the same time. Added key_PARTITION_LOCK_auto_inc for instrumentation. sql/mysqld.cc: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Removed the partitioning engines use of ha_data in TABLE_SHARE and added ha_part_data instead, since they collide if used in the same time. Added key_PARTITION_LOCK_auto_inc for instrumentation. sql/partition_info.h: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Removed part_state* since it was not in use. sql/sql_partition.cc: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Removed part_state* since it was not in use. sql/sql_partition.h: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Cleaned up old commented out code. Removed part_state* since it was not in use. sql/sql_show.cc: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Rename of PARTITION_INFO to PARTITION_STATS to better match the use (and there is also a class named partition_info...) Renamed partition_info to partition_info_str, since partition_info is a name of a class. sql/sql_table.cc: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Renamed partition_info to partition_info_str, since partition_info is a name of a class. sql/table.cc: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Removed the partitioning engines use of ha_data in TABLE_SHARE and added ha_part_data instead, since they collide if used in the same time. Renamed partition_info to partition_info_str, since partition_info is a name of a class. removed part_state* since it was not in use. sql/table.h: Bug#51851: Server with SBR locks mutex twice on LOAD DATA into partitioned MyISAM table Removed the partitioning engines use of ha_data in TABLE_SHARE and added ha_part_data instead, since they collide if used in the same time. Renamed partition_info to partition_info_str, since partition_info is a name of a class. removed part_state* since it was not in use.
This commit is contained in:
parent
6da92d8f19
commit
47906997c7
17 changed files with 156 additions and 248 deletions
13
mysql-test/r/partition_binlog_stmt.result
Normal file
13
mysql-test/r/partition_binlog_stmt.result
Normal file
|
@ -0,0 +1,13 @@
|
|||
DROP TABLE IF EXISTS t1;
|
||||
#
|
||||
# Bug#51851: Server with SBR locks mutex twice on LOAD DATA into
|
||||
# partitioned MyISAM table
|
||||
CREATE TABLE t1
|
||||
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
name TINYBLOB NOT NULL,
|
||||
modified TIMESTAMP DEFAULT '0000-00-00 00:00:00',
|
||||
INDEX namelocs (name(255))) ENGINE = MyISAM
|
||||
PARTITION BY HASH(id) PARTITIONS 2;
|
||||
LOAD DATA LOCAL INFILE 'init_file.txt'
|
||||
INTO TABLE t1 (name);
|
||||
DROP TABLE t1;
|
28
mysql-test/t/partition_binlog_stmt.test
Normal file
28
mysql-test/t/partition_binlog_stmt.test
Normal file
|
@ -0,0 +1,28 @@
|
|||
--source include/have_partition.inc
|
||||
--source include/have_binlog_format_statement.inc
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
--enable_warnings
|
||||
|
||||
--echo #
|
||||
--echo # Bug#51851: Server with SBR locks mutex twice on LOAD DATA into
|
||||
--echo # partitioned MyISAM table
|
||||
perl;
|
||||
open( INIT, ">init_file.txt");
|
||||
print INIT "abcd\n";
|
||||
close( INIT );
|
||||
EOF
|
||||
|
||||
CREATE TABLE t1
|
||||
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
name TINYBLOB NOT NULL,
|
||||
modified TIMESTAMP DEFAULT '0000-00-00 00:00:00',
|
||||
INDEX namelocs (name(255))) ENGINE = MyISAM
|
||||
PARTITION BY HASH(id) PARTITIONS 2;
|
||||
|
||||
LOAD DATA LOCAL INFILE 'init_file.txt'
|
||||
INTO TABLE t1 (name);
|
||||
|
||||
--remove_file init_file.txt
|
||||
DROP TABLE t1;
|
|
@ -4238,7 +4238,7 @@ int ha_ndbcluster::info(uint flag)
|
|||
}
|
||||
|
||||
|
||||
void ha_ndbcluster::get_dynamic_partition_info(PARTITION_INFO *stat_info,
|
||||
void ha_ndbcluster::get_dynamic_partition_info(PARTITION_STATS *stat_info,
|
||||
uint part_id)
|
||||
{
|
||||
/*
|
||||
|
@ -4246,7 +4246,7 @@ void ha_ndbcluster::get_dynamic_partition_info(PARTITION_INFO *stat_info,
|
|||
implement ndb function which retrives the statistics
|
||||
about ndb partitions.
|
||||
*/
|
||||
bzero((char*) stat_info, sizeof(PARTITION_INFO));
|
||||
bzero((char*) stat_info, sizeof(PARTITION_STATS));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -273,7 +273,7 @@ class ha_ndbcluster: public handler
|
|||
ha_rows estimate_rows_upper_bound()
|
||||
{ return HA_POS_ERROR; }
|
||||
int info(uint);
|
||||
void get_dynamic_partition_info(PARTITION_INFO *stat_info, uint part_id);
|
||||
void get_dynamic_partition_info(PARTITION_STATS *stat_info, uint part_id);
|
||||
int extra(enum ha_extra_function operation);
|
||||
int extra_opt(enum ha_extra_function operation, ulong cache_size);
|
||||
int reset();
|
||||
|
|
|
@ -2496,12 +2496,12 @@ err1:
|
|||
A destructor for partition-specific TABLE_SHARE data.
|
||||
*/
|
||||
|
||||
void ha_data_partition_destroy(void *ha_data)
|
||||
void ha_data_partition_destroy(void *ha_part_data)
|
||||
{
|
||||
if (ha_data)
|
||||
if (ha_part_data)
|
||||
{
|
||||
HA_DATA_PARTITION *ha_data_partition= (HA_DATA_PARTITION*) ha_data;
|
||||
pthread_mutex_destroy(&ha_data_partition->mutex);
|
||||
HA_DATA_PARTITION *ha_data_partition= (HA_DATA_PARTITION*) ha_part_data;
|
||||
mysql_mutex_destroy(&ha_data_partition->LOCK_auto_inc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2641,28 +2641,29 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
|
|||
goto err_handler;
|
||||
|
||||
/*
|
||||
Use table_share->ha_data to share auto_increment_value among all handlers
|
||||
for the same table.
|
||||
Use table_share->ha_part_data to share auto_increment_value among
|
||||
all handlers for the same table.
|
||||
*/
|
||||
if (is_not_tmp_table)
|
||||
mysql_mutex_lock(&table_share->LOCK_ha_data);
|
||||
if (!table_share->ha_data)
|
||||
if (!table_share->ha_part_data)
|
||||
{
|
||||
HA_DATA_PARTITION *ha_data;
|
||||
HA_DATA_PARTITION *ha_part_data;
|
||||
/* currently only needed for auto_increment */
|
||||
table_share->ha_data= ha_data= (HA_DATA_PARTITION*)
|
||||
alloc_root(&table_share->mem_root,
|
||||
sizeof(HA_DATA_PARTITION));
|
||||
if (!ha_data)
|
||||
table_share->ha_part_data= alloc_root(&table_share->mem_root,
|
||||
sizeof(HA_DATA_PARTITION));
|
||||
ha_part_data= (HA_DATA_PARTITION*) table_share->ha_part_data;
|
||||
if (!ha_part_data)
|
||||
{
|
||||
if (is_not_tmp_table)
|
||||
mysql_mutex_unlock(&table_share->LOCK_ha_data);
|
||||
goto err_handler;
|
||||
}
|
||||
DBUG_PRINT("info", ("table_share->ha_data 0x%p", ha_data));
|
||||
bzero(ha_data, sizeof(HA_DATA_PARTITION));
|
||||
table_share->ha_data_destroy= ha_data_partition_destroy;
|
||||
pthread_mutex_init(&ha_data->mutex, MY_MUTEX_INIT_FAST);
|
||||
DBUG_PRINT("info", ("table_share->ha_part_data 0x%p", ha_part_data));
|
||||
bzero(ha_part_data, sizeof(HA_DATA_PARTITION));
|
||||
table_share->ha_part_data_destroy= ha_data_partition_destroy;
|
||||
mysql_mutex_init(key_PARTITION_LOCK_auto_inc, &ha_part_data->LOCK_auto_inc,
|
||||
MY_MUTEX_INIT_FAST);
|
||||
}
|
||||
if (is_not_tmp_table)
|
||||
mysql_mutex_unlock(&table_share->LOCK_ha_data);
|
||||
|
@ -3086,7 +3087,8 @@ int ha_partition::write_row(uchar * buf)
|
|||
longlong func_value;
|
||||
bool have_auto_increment= table->next_number_field && buf == table->record[0];
|
||||
my_bitmap_map *old_map;
|
||||
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
|
||||
HA_DATA_PARTITION *ha_part_data= (HA_DATA_PARTITION*)
|
||||
table_share->ha_part_data;
|
||||
THD *thd= ha_thd();
|
||||
timestamp_auto_set_type orig_timestamp_type= table->timestamp_field_type;
|
||||
#ifdef NOT_NEEDED
|
||||
|
@ -3106,7 +3108,7 @@ int ha_partition::write_row(uchar * buf)
|
|||
*/
|
||||
if (have_auto_increment)
|
||||
{
|
||||
if (!ha_data->auto_inc_initialized &&
|
||||
if (!ha_part_data->auto_inc_initialized &&
|
||||
!table->s->next_number_keypart)
|
||||
{
|
||||
/*
|
||||
|
@ -3247,7 +3249,7 @@ int ha_partition::update_row(const uchar *old_data, uchar *new_data)
|
|||
exit:
|
||||
/*
|
||||
if updating an auto_increment column, update
|
||||
table_share->ha_data->next_auto_inc_val if needed.
|
||||
table_share->ha_part_data->next_auto_inc_val if needed.
|
||||
(not to be used if auto_increment on secondary field in a multi-column
|
||||
index)
|
||||
mysql_update does not set table->next_number_field, so we use
|
||||
|
@ -3256,8 +3258,9 @@ exit:
|
|||
if (table->found_next_number_field && new_data == table->record[0] &&
|
||||
!table->s->next_number_keypart)
|
||||
{
|
||||
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
|
||||
if (!ha_data->auto_inc_initialized)
|
||||
HA_DATA_PARTITION *ha_part_data= (HA_DATA_PARTITION*)
|
||||
table_share->ha_part_data;
|
||||
if (!ha_part_data->auto_inc_initialized)
|
||||
info(HA_STATUS_AUTO);
|
||||
set_auto_increment_if_higher(table->found_next_number_field);
|
||||
}
|
||||
|
@ -3349,11 +3352,12 @@ int ha_partition::delete_all_rows()
|
|||
if (thd->lex->sql_command == SQLCOM_TRUNCATE)
|
||||
{
|
||||
Alter_info *alter_info= &thd->lex->alter_info;
|
||||
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
|
||||
HA_DATA_PARTITION *ha_part_data= (HA_DATA_PARTITION*)
|
||||
table_share->ha_part_data;
|
||||
/* TRUNCATE also means resetting auto_increment */
|
||||
lock_auto_increment();
|
||||
ha_data->next_auto_inc_val= 0;
|
||||
ha_data->auto_inc_initialized= FALSE;
|
||||
ha_part_data->next_auto_inc_val= 0;
|
||||
ha_part_data->auto_inc_initialized= FALSE;
|
||||
unlock_auto_increment();
|
||||
if (alter_info->flags & ALTER_ADMIN_PARTITION)
|
||||
{
|
||||
|
@ -5069,22 +5073,23 @@ int ha_partition::info(uint flag)
|
|||
if (flag & HA_STATUS_AUTO)
|
||||
{
|
||||
bool auto_inc_is_first_in_idx= (table_share->next_number_keypart == 0);
|
||||
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
|
||||
HA_DATA_PARTITION *ha_part_data= (HA_DATA_PARTITION*)
|
||||
table_share->ha_part_data;
|
||||
DBUG_PRINT("info", ("HA_STATUS_AUTO"));
|
||||
if (!table->found_next_number_field)
|
||||
stats.auto_increment_value= 0;
|
||||
else if (ha_data->auto_inc_initialized)
|
||||
else if (ha_part_data->auto_inc_initialized)
|
||||
{
|
||||
lock_auto_increment();
|
||||
stats.auto_increment_value= ha_data->next_auto_inc_val;
|
||||
stats.auto_increment_value= ha_part_data->next_auto_inc_val;
|
||||
unlock_auto_increment();
|
||||
}
|
||||
else
|
||||
{
|
||||
lock_auto_increment();
|
||||
/* to avoid two concurrent initializations, check again when locked */
|
||||
if (ha_data->auto_inc_initialized)
|
||||
stats.auto_increment_value= ha_data->next_auto_inc_val;
|
||||
if (ha_part_data->auto_inc_initialized)
|
||||
stats.auto_increment_value= ha_part_data->next_auto_inc_val;
|
||||
else
|
||||
{
|
||||
handler *file, **file_array;
|
||||
|
@ -5104,10 +5109,10 @@ int ha_partition::info(uint flag)
|
|||
stats.auto_increment_value= auto_increment_value;
|
||||
if (auto_inc_is_first_in_idx)
|
||||
{
|
||||
set_if_bigger(ha_data->next_auto_inc_val, auto_increment_value);
|
||||
ha_data->auto_inc_initialized= TRUE;
|
||||
set_if_bigger(ha_part_data->next_auto_inc_val, auto_increment_value);
|
||||
ha_part_data->auto_inc_initialized= TRUE;
|
||||
DBUG_PRINT("info", ("initializing next_auto_inc_val to %lu",
|
||||
(ulong) ha_data->next_auto_inc_val));
|
||||
(ulong) ha_part_data->next_auto_inc_val));
|
||||
}
|
||||
}
|
||||
unlock_auto_increment();
|
||||
|
@ -5281,7 +5286,7 @@ int ha_partition::info(uint flag)
|
|||
}
|
||||
|
||||
|
||||
void ha_partition::get_dynamic_partition_info(PARTITION_INFO *stat_info,
|
||||
void ha_partition::get_dynamic_partition_info(PARTITION_STATS *stat_info,
|
||||
uint part_id)
|
||||
{
|
||||
handler *file= m_file[part_id];
|
||||
|
@ -6496,11 +6501,12 @@ int ha_partition::reset_auto_increment(ulonglong value)
|
|||
{
|
||||
handler **file= m_file;
|
||||
int res;
|
||||
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
|
||||
HA_DATA_PARTITION *ha_part_data= (HA_DATA_PARTITION*)
|
||||
table_share->ha_part_data;
|
||||
DBUG_ENTER("ha_partition::reset_auto_increment");
|
||||
lock_auto_increment();
|
||||
ha_data->auto_inc_initialized= FALSE;
|
||||
ha_data->next_auto_inc_val= 0;
|
||||
ha_part_data->auto_inc_initialized= FALSE;
|
||||
ha_part_data->next_auto_inc_val= 0;
|
||||
do
|
||||
{
|
||||
if ((res= (*file)->ha_reset_auto_increment(value)) != 0)
|
||||
|
@ -6514,7 +6520,7 @@ int ha_partition::reset_auto_increment(ulonglong value)
|
|||
/**
|
||||
This method is called by update_auto_increment which in turn is called
|
||||
by the individual handlers as part of write_row. We use the
|
||||
table_share->ha_data->next_auto_inc_val, or search all
|
||||
table_share->ha_part_data->next_auto_inc_val, or search all
|
||||
partitions for the highest auto_increment_value if not initialized or
|
||||
if auto_increment field is a secondary part of a key, we must search
|
||||
every partition when holding a mutex to be sure of correctness.
|
||||
|
@ -6567,13 +6573,14 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment,
|
|||
else
|
||||
{
|
||||
THD *thd= ha_thd();
|
||||
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
|
||||
HA_DATA_PARTITION *ha_part_data= (HA_DATA_PARTITION*)
|
||||
table_share->ha_part_data;
|
||||
/*
|
||||
This is initialized in the beginning of the first write_row call.
|
||||
*/
|
||||
DBUG_ASSERT(ha_data->auto_inc_initialized);
|
||||
DBUG_ASSERT(ha_part_data->auto_inc_initialized);
|
||||
/*
|
||||
Get a lock for handling the auto_increment in table_share->ha_data
|
||||
Get a lock for handling the auto_increment in table_share->ha_part_data
|
||||
for avoiding two concurrent statements getting the same number.
|
||||
*/
|
||||
|
||||
|
@ -6600,8 +6607,8 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment,
|
|||
}
|
||||
|
||||
/* this gets corrected (for offset/increment) in update_auto_increment */
|
||||
*first_value= ha_data->next_auto_inc_val;
|
||||
ha_data->next_auto_inc_val+= nb_desired_values * increment;
|
||||
*first_value= ha_part_data->next_auto_inc_val;
|
||||
ha_part_data->next_auto_inc_val+= nb_desired_values * increment;
|
||||
|
||||
unlock_auto_increment();
|
||||
DBUG_PRINT("info", ("*first_value: %lu", (ulong) *first_value));
|
||||
|
@ -6621,15 +6628,16 @@ void ha_partition::release_auto_increment()
|
|||
}
|
||||
else if (next_insert_id)
|
||||
{
|
||||
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
|
||||
HA_DATA_PARTITION *ha_part_data= (HA_DATA_PARTITION*)
|
||||
table_share->ha_part_data;
|
||||
ulonglong next_auto_inc_val;
|
||||
lock_auto_increment();
|
||||
next_auto_inc_val= ha_data->next_auto_inc_val;
|
||||
next_auto_inc_val= ha_part_data->next_auto_inc_val;
|
||||
if (next_insert_id < next_auto_inc_val &&
|
||||
auto_inc_interval_for_cur_row.maximum() >= next_auto_inc_val)
|
||||
ha_data->next_auto_inc_val= next_insert_id;
|
||||
DBUG_PRINT("info", ("ha_data->next_auto_inc_val: %lu",
|
||||
(ulong) ha_data->next_auto_inc_val));
|
||||
ha_part_data->next_auto_inc_val= next_insert_id;
|
||||
DBUG_PRINT("info", ("ha_part_data->next_auto_inc_val: %lu",
|
||||
(ulong) ha_part_data->next_auto_inc_val));
|
||||
|
||||
/* Unlock the multi row statement lock taken in get_auto_increment */
|
||||
if (auto_increment_safe_stmt_log_lock)
|
||||
|
@ -6729,127 +6737,6 @@ int ha_partition::indexes_are_disabled(void)
|
|||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
MODULE Partition Share
|
||||
****************************************************************************/
|
||||
/*
|
||||
Service routines for ... methods.
|
||||
-------------------------------------------------------------------------
|
||||
Variables for partition share methods. A hash used to track open tables.
|
||||
A mutex for the hash table and an init variable to check if hash table
|
||||
is initialized.
|
||||
There is also a constant ending of the partition handler file name.
|
||||
*/
|
||||
|
||||
#ifdef NOT_USED
|
||||
static HASH partition_open_tables;
|
||||
static mysql_mutex_t partition_mutex;
|
||||
static int partition_init= 0;
|
||||
|
||||
|
||||
/*
|
||||
Function we use in the creation of our hash to get key.
|
||||
*/
|
||||
|
||||
static uchar *partition_get_key(PARTITION_SHARE *share, size_t *length,
|
||||
my_bool not_used __attribute__ ((unused)))
|
||||
{
|
||||
*length= share->table_name_length;
|
||||
return (uchar *) share->table_name;
|
||||
}
|
||||
|
||||
/*
|
||||
Example of simple lock controls. The "share" it creates is structure we
|
||||
will pass to each partition handler. Do you have to have one of these?
|
||||
Well, you have pieces that are used for locking, and they are needed to
|
||||
function.
|
||||
*/
|
||||
|
||||
static PARTITION_SHARE *get_share(const char *table_name, TABLE *table)
|
||||
{
|
||||
PARTITION_SHARE *share;
|
||||
uint length;
|
||||
char *tmp_name;
|
||||
|
||||
/*
|
||||
So why does this exist? There is no way currently to init a storage
|
||||
engine.
|
||||
Innodb and BDB both have modifications to the server to allow them to
|
||||
do this. Since you will not want to do this, this is probably the next
|
||||
best method.
|
||||
*/
|
||||
if (!partition_init)
|
||||
{
|
||||
/* Hijack a mutex for init'ing the storage engine */
|
||||
mysql_mutex_lock(&LOCK_mysql_create_db);
|
||||
if (!partition_init)
|
||||
{
|
||||
partition_init++;
|
||||
mysql_mutex_init(INSTRUMENT_ME, &partition_mutex, MY_MUTEX_INIT_FAST);
|
||||
(void) hash_init(&partition_open_tables, system_charset_info, 32, 0, 0,
|
||||
(hash_get_key) partition_get_key, 0, 0);
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_mysql_create_db);
|
||||
}
|
||||
mysql_mutex_lock(&partition_mutex);
|
||||
length= (uint) strlen(table_name);
|
||||
|
||||
if (!(share= (PARTITION_SHARE *) hash_search(&partition_open_tables,
|
||||
(uchar *) table_name, length)))
|
||||
{
|
||||
if (!(share= (PARTITION_SHARE *)
|
||||
my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
|
||||
&share, (uint) sizeof(*share),
|
||||
&tmp_name, (uint) length + 1, NullS)))
|
||||
{
|
||||
mysql_mutex_unlock(&partition_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
share->use_count= 0;
|
||||
share->table_name_length= length;
|
||||
share->table_name= tmp_name;
|
||||
strmov(share->table_name, table_name);
|
||||
if (my_hash_insert(&partition_open_tables, (uchar *) share))
|
||||
goto error;
|
||||
thr_lock_init(&share->lock);
|
||||
mysql_mutex_init(INSTRUMENT_ME, &share->mutex, MY_MUTEX_INIT_FAST);
|
||||
}
|
||||
share->use_count++;
|
||||
mysql_mutex_unlock(&partition_mutex);
|
||||
|
||||
return share;
|
||||
|
||||
error:
|
||||
mysql_mutex_unlock(&partition_mutex);
|
||||
my_free((uchar*) share, MYF(0));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Free lock controls. We call this whenever we close a table. If the table
|
||||
had the last reference to the share then we free memory associated with
|
||||
it.
|
||||
*/
|
||||
|
||||
static int free_share(PARTITION_SHARE *share)
|
||||
{
|
||||
mysql_mutex_lock(&partition_mutex);
|
||||
if (!--share->use_count)
|
||||
{
|
||||
hash_delete(&partition_open_tables, (uchar *) share);
|
||||
thr_lock_delete(&share->lock);
|
||||
mysql_mutex_destroy(&share->mutex);
|
||||
my_free((uchar*) share, MYF(0));
|
||||
}
|
||||
mysql_mutex_unlock(&partition_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* NOT_USED */
|
||||
|
||||
struct st_mysql_storage_engine partition_storage_engine=
|
||||
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
|
||||
|
||||
|
|
|
@ -26,30 +26,15 @@ enum partition_keywords
|
|||
PKW_COLUMNS
|
||||
};
|
||||
|
||||
/*
|
||||
PARTITION_SHARE is a structure that will be shared amoung all open handlers
|
||||
The partition implements the minimum of what you will probably need.
|
||||
*/
|
||||
|
||||
#ifdef NOT_USED
|
||||
typedef struct st_partition_share
|
||||
{
|
||||
char *table_name;
|
||||
uint table_name_length, use_count;
|
||||
mysql_mutex_t mutex;
|
||||
THR_LOCK lock;
|
||||
} PARTITION_SHARE;
|
||||
#endif
|
||||
|
||||
/**
|
||||
Partition specific ha_data struct.
|
||||
@todo: move all partition specific data from TABLE_SHARE here.
|
||||
*/
|
||||
typedef struct st_ha_data_partition
|
||||
{
|
||||
ulonglong next_auto_inc_val; /**< first non reserved value */
|
||||
bool auto_inc_initialized;
|
||||
pthread_mutex_t mutex;
|
||||
mysql_mutex_t LOCK_auto_inc; /**< protecting auto_inc val */
|
||||
ulonglong next_auto_inc_val; /**< first non reserved value */
|
||||
} HA_DATA_PARTITION;
|
||||
|
||||
#define PARTITION_BYTES_IN_POS 2
|
||||
|
@ -519,7 +504,7 @@ public:
|
|||
-------------------------------------------------------------------------
|
||||
*/
|
||||
virtual int info(uint);
|
||||
void get_dynamic_partition_info(PARTITION_INFO *stat_info,
|
||||
void get_dynamic_partition_info(PARTITION_STATS *stat_info,
|
||||
uint part_id);
|
||||
virtual int extra(enum ha_extra_function operation);
|
||||
virtual int extra_opt(enum ha_extra_function operation, ulong cachesize);
|
||||
|
@ -938,19 +923,23 @@ private:
|
|||
virtual int reset_auto_increment(ulonglong value);
|
||||
virtual void lock_auto_increment()
|
||||
{
|
||||
HA_DATA_PARTITION *ha_part_data;
|
||||
/* lock already taken */
|
||||
if (auto_increment_safe_stmt_log_lock)
|
||||
return;
|
||||
DBUG_ASSERT(table_share->ha_data && !auto_increment_lock);
|
||||
ha_part_data= (HA_DATA_PARTITION*) table_share->ha_part_data;
|
||||
DBUG_ASSERT(ha_part_data && !auto_increment_lock);
|
||||
if(table_share->tmp_table == NO_TMP_TABLE)
|
||||
{
|
||||
auto_increment_lock= TRUE;
|
||||
mysql_mutex_lock(&table_share->LOCK_ha_data);
|
||||
mysql_mutex_lock(&ha_part_data->LOCK_auto_inc);
|
||||
}
|
||||
}
|
||||
virtual void unlock_auto_increment()
|
||||
{
|
||||
DBUG_ASSERT(table_share->ha_data);
|
||||
HA_DATA_PARTITION *ha_part_data= (HA_DATA_PARTITION*)
|
||||
table_share->ha_part_data;
|
||||
DBUG_ASSERT(ha_part_data);
|
||||
/*
|
||||
If auto_increment_safe_stmt_log_lock is true, we have to keep the lock.
|
||||
It will be set to false and thus unlocked at the end of the statement by
|
||||
|
@ -958,20 +947,21 @@ private:
|
|||
*/
|
||||
if(auto_increment_lock && !auto_increment_safe_stmt_log_lock)
|
||||
{
|
||||
mysql_mutex_unlock(&table_share->LOCK_ha_data);
|
||||
mysql_mutex_unlock(&ha_part_data->LOCK_auto_inc);
|
||||
auto_increment_lock= FALSE;
|
||||
}
|
||||
}
|
||||
virtual void set_auto_increment_if_higher(Field *field)
|
||||
{
|
||||
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
|
||||
HA_DATA_PARTITION *ha_part_data= (HA_DATA_PARTITION*)
|
||||
table_share->ha_part_data;
|
||||
ulonglong nr= (((Field_num*) field)->unsigned_flag ||
|
||||
field->val_int() > 0) ? field->val_int() : 0;
|
||||
lock_auto_increment();
|
||||
DBUG_ASSERT(ha_data->auto_inc_initialized == TRUE);
|
||||
DBUG_ASSERT(ha_part_data->auto_inc_initialized == TRUE);
|
||||
/* must check when the mutex is taken */
|
||||
if (nr >= ha_data->next_auto_inc_val)
|
||||
ha_data->next_auto_inc_val= nr + 1;
|
||||
if (nr >= ha_part_data->next_auto_inc_val)
|
||||
ha_part_data->next_auto_inc_val= nr + 1;
|
||||
unlock_auto_increment();
|
||||
}
|
||||
|
||||
|
|
|
@ -3517,7 +3517,7 @@ int handler::index_next_same(uchar *buf, const uchar *key, uint keylen)
|
|||
}
|
||||
|
||||
|
||||
void handler::get_dynamic_partition_info(PARTITION_INFO *stat_info,
|
||||
void handler::get_dynamic_partition_info(PARTITION_STATS *stat_info,
|
||||
uint part_id)
|
||||
{
|
||||
info(HA_STATUS_CONST | HA_STATUS_TIME | HA_STATUS_VARIABLE |
|
||||
|
|
|
@ -954,7 +954,7 @@ typedef struct {
|
|||
ulong check_time;
|
||||
ulong update_time;
|
||||
ulonglong check_sum;
|
||||
} PARTITION_INFO;
|
||||
} PARTITION_STATS;
|
||||
|
||||
#define UNDEF_NODEGROUP 65535
|
||||
class Item;
|
||||
|
@ -1553,7 +1553,7 @@ public:
|
|||
{ return (ha_rows) 10; }
|
||||
virtual void position(const uchar *record)=0;
|
||||
virtual int info(uint)=0; // see my_base.h for full description
|
||||
virtual void get_dynamic_partition_info(PARTITION_INFO *stat_info,
|
||||
virtual void get_dynamic_partition_info(PARTITION_STATS *stat_info,
|
||||
uint part_id);
|
||||
virtual int extra(enum ha_extra_function operation)
|
||||
{ return 0; }
|
||||
|
|
|
@ -2718,8 +2718,8 @@ extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids,
|
|||
key_master_info_data_lock, key_master_info_run_lock,
|
||||
key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
|
||||
key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
|
||||
key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, key_LOCK_error_messages,
|
||||
key_LOCK_thread_count;
|
||||
key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
|
||||
key_LOCK_error_messages, key_LOCK_thread_count, key_PARTITION_LOCK_auto_inc;
|
||||
|
||||
extern PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
|
||||
key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
|
||||
|
|
|
@ -7872,8 +7872,9 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids,
|
|||
key_master_info_data_lock, key_master_info_run_lock,
|
||||
key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
|
||||
key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
|
||||
key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, key_LOCK_error_messages,
|
||||
key_LOG_INFO_lock, key_LOCK_thread_count;
|
||||
key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
|
||||
key_LOCK_error_messages, key_LOG_INFO_lock, key_LOCK_thread_count,
|
||||
key_PARTITION_LOCK_auto_inc;
|
||||
|
||||
static PSI_mutex_info all_server_mutexes[]=
|
||||
{
|
||||
|
@ -7927,7 +7928,8 @@ static PSI_mutex_info all_server_mutexes[]=
|
|||
{ &key_TABLE_SHARE_LOCK_ha_data, "TABLE_SHARE::LOCK_ha_data", 0},
|
||||
{ &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL},
|
||||
{ &key_LOG_INFO_lock, "LOG_INFO::lock", 0},
|
||||
{ &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL}
|
||||
{ &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL},
|
||||
{ &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0}
|
||||
};
|
||||
|
||||
PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
|
||||
|
|
|
@ -151,8 +151,6 @@ public:
|
|||
char *part_func_string;
|
||||
char *subpart_func_string;
|
||||
|
||||
const char *part_state;
|
||||
|
||||
partition_element *curr_part_elem;
|
||||
partition_element *current_partition;
|
||||
part_elem_value *curr_list_val;
|
||||
|
@ -173,7 +171,6 @@ public:
|
|||
partition_type subpart_type;
|
||||
|
||||
uint part_info_len;
|
||||
uint part_state_len;
|
||||
uint part_func_len;
|
||||
uint subpart_func_len;
|
||||
|
||||
|
@ -226,13 +223,12 @@ public:
|
|||
list_array(NULL), err_value(0),
|
||||
part_info_string(NULL),
|
||||
part_func_string(NULL), subpart_func_string(NULL),
|
||||
part_state(NULL),
|
||||
curr_part_elem(NULL), current_partition(NULL),
|
||||
curr_list_object(0), num_columns(0),
|
||||
default_engine_type(NULL),
|
||||
part_result_type(INT_RESULT),
|
||||
part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
|
||||
part_info_len(0), part_state_len(0),
|
||||
part_info_len(0),
|
||||
part_func_len(0), subpart_func_len(0),
|
||||
num_parts(0), num_subparts(0),
|
||||
count_curr_subparts(0), part_error_code(0),
|
||||
|
|
|
@ -4165,7 +4165,6 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index,
|
|||
|
||||
bool mysql_unpack_partition(THD *thd,
|
||||
const char *part_buf, uint part_info_len,
|
||||
const char *part_state, uint part_state_len,
|
||||
TABLE* table, bool is_create_table_ind,
|
||||
handlerton *default_db_type,
|
||||
bool *work_part_info_used)
|
||||
|
@ -4201,8 +4200,6 @@ bool mysql_unpack_partition(THD *thd,
|
|||
goto end;
|
||||
}
|
||||
part_info= lex.part_info;
|
||||
part_info->part_state= part_state;
|
||||
part_info->part_state_len= part_state_len;
|
||||
DBUG_PRINT("info", ("Parse: %s", part_buf));
|
||||
if (parse_sql(thd, & parser_state, NULL) ||
|
||||
part_info->fix_parser_data(thd))
|
||||
|
|
|
@ -26,19 +26,6 @@
|
|||
#define HA_CAN_PARTITION_UNIQUE (1 << 2)
|
||||
#define HA_USE_AUTO_PARTITION (1 << 3)
|
||||
|
||||
/*typedef struct {
|
||||
ulonglong data_file_length;
|
||||
ulonglong max_data_file_length;
|
||||
ulonglong index_file_length;
|
||||
ulonglong delete_length;
|
||||
ha_rows records;
|
||||
ulong mean_rec_length;
|
||||
time_t create_time;
|
||||
time_t check_time;
|
||||
time_t update_time;
|
||||
ulonglong check_sum;
|
||||
} PARTITION_INFO;
|
||||
*/
|
||||
typedef struct {
|
||||
longlong list_value;
|
||||
uint32 partition_id;
|
||||
|
@ -87,7 +74,6 @@ void get_full_part_id_from_key(const TABLE *table, uchar *buf,
|
|||
part_id_range *part_spec);
|
||||
bool mysql_unpack_partition(THD *thd, const char *part_buf,
|
||||
uint part_info_len,
|
||||
const char *part_state, uint part_state_len,
|
||||
TABLE *table, bool is_create_table_ind,
|
||||
handlerton *default_db_type,
|
||||
bool *work_part_info_used);
|
||||
|
|
|
@ -3726,7 +3726,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
|
|||
}
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if (share->db_type() == partition_hton &&
|
||||
share->partition_info_len)
|
||||
share->partition_info_str_len)
|
||||
{
|
||||
tmp_db_type= share->default_part_db_type;
|
||||
is_partitioned= TRUE;
|
||||
|
@ -5289,7 +5289,7 @@ static void store_schema_partitions_record(THD *thd, TABLE *schema_table,
|
|||
{
|
||||
TABLE* table= schema_table;
|
||||
CHARSET_INFO *cs= system_charset_info;
|
||||
PARTITION_INFO stat_info;
|
||||
PARTITION_STATS stat_info;
|
||||
MYSQL_TIME time;
|
||||
file->get_dynamic_partition_info(&stat_info, part_id);
|
||||
table->field[0]->store(STRING_WITH_LEN("def"), cs);
|
||||
|
|
|
@ -1725,11 +1725,12 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
|
|||
error= 1;
|
||||
goto err;
|
||||
}
|
||||
share->partition_info= tmp_part_syntax_str;
|
||||
share->partition_info_str= tmp_part_syntax_str;
|
||||
}
|
||||
else
|
||||
memcpy((char*) share->partition_info, part_syntax_buf, syntax_len + 1);
|
||||
share->partition_info_len= part_info->part_info_len= syntax_len;
|
||||
memcpy((char*) share->partition_info_str, part_syntax_buf,
|
||||
syntax_len + 1);
|
||||
share->partition_info_str_len= part_info->part_info_len= syntax_len;
|
||||
part_info->part_info_string= part_syntax_buf;
|
||||
}
|
||||
#endif
|
||||
|
|
24
sql/table.cc
24
sql/table.cc
|
@ -954,28 +954,28 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
|||
}
|
||||
if (next_chunk + 5 < buff_end)
|
||||
{
|
||||
uint32 partition_info_len = uint4korr(next_chunk);
|
||||
uint32 partition_info_str_len = uint4korr(next_chunk);
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if ((share->partition_info_buffer_size=
|
||||
share->partition_info_len= partition_info_len))
|
||||
share->partition_info_str_len= partition_info_str_len))
|
||||
{
|
||||
if (!(share->partition_info= (char*)
|
||||
if (!(share->partition_info_str= (char*)
|
||||
memdup_root(&share->mem_root, next_chunk + 4,
|
||||
partition_info_len + 1)))
|
||||
partition_info_str_len + 1)))
|
||||
{
|
||||
my_free(buff, MYF(0));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (partition_info_len)
|
||||
if (partition_info_str_len)
|
||||
{
|
||||
DBUG_PRINT("info", ("WITH_PARTITION_STORAGE_ENGINE is not defined"));
|
||||
my_free(buff, MYF(0));
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
next_chunk+= 5 + partition_info_len;
|
||||
next_chunk+= 5 + partition_info_str_len;
|
||||
}
|
||||
#if MYSQL_VERSION_ID < 50200
|
||||
if (share->mysql_version >= 50106 && share->mysql_version <= 50109)
|
||||
|
@ -1638,6 +1638,10 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
|||
my_hash_free(&share->name_hash);
|
||||
if (share->ha_data_destroy)
|
||||
share->ha_data_destroy(share->ha_data);
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if (share->ha_part_data_destroy)
|
||||
share->ha_part_data_destroy(share->ha_part_data);
|
||||
#endif
|
||||
|
||||
open_table_error(share, error, share->open_errno, errarg);
|
||||
DBUG_RETURN(error);
|
||||
|
@ -1829,7 +1833,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
|
|||
}
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if (share->partition_info_len && outparam->file)
|
||||
if (share->partition_info_str_len && outparam->file)
|
||||
{
|
||||
/*
|
||||
In this execution we must avoid calling thd->change_item_tree since
|
||||
|
@ -1850,10 +1854,8 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
|
|||
bool tmp;
|
||||
bool work_part_info_used;
|
||||
|
||||
tmp= mysql_unpack_partition(thd, share->partition_info,
|
||||
share->partition_info_len,
|
||||
share->part_state,
|
||||
share->part_state_len,
|
||||
tmp= mysql_unpack_partition(thd, share->partition_info_str,
|
||||
share->partition_info_str_len,
|
||||
outparam, is_create_table,
|
||||
share->default_part_db_type,
|
||||
&work_part_info_used);
|
||||
|
|
16
sql/table.h
16
sql/table.h
|
@ -495,13 +495,11 @@ struct TABLE_SHARE
|
|||
int cached_row_logging_check;
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
/** @todo: Move into *ha_data for partitioning */
|
||||
/* filled in when reading from frm */
|
||||
bool auto_partitioned;
|
||||
const char *partition_info;
|
||||
uint partition_info_len;
|
||||
const char *partition_info_str;
|
||||
uint partition_info_str_len;
|
||||
uint partition_info_buffer_size;
|
||||
const char *part_state;
|
||||
uint part_state_len;
|
||||
handlerton *default_part_db_type;
|
||||
#endif
|
||||
|
||||
|
@ -521,6 +519,14 @@ struct TABLE_SHARE
|
|||
void *ha_data;
|
||||
void (*ha_data_destroy)(void *); /* An optional destructor for ha_data */
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
/** place to store partition specific data, LOCK_ha_data hold while init. */
|
||||
void *ha_part_data;
|
||||
/* Destructor for ha_part_data */
|
||||
void (*ha_part_data_destroy)(void *);
|
||||
#endif
|
||||
|
||||
|
||||
/** Instrumentation for this table share. */
|
||||
PSI_table_share *m_psi;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue