Below is the list of changes that have just been committed into a local
5.1 repository of mikron. When mikron does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.1895 05/08/23 20:21:52 mronstrom@stripped +6 -0
WL 2602, 2603, 2604: Partition Management
Generalised partition management, first step
sql/sql_table.cc
1.266 05/08/23 20:21:42 mronstrom@stripped +203 -103
Lots of new routines for generalised partition management
Tried to accomplish short code for each variant of partition
management using lots of support routines to place common code
to avoid code duplication. The variants are similar but sufficiently
different to not really benefit from a common code path.
sql/mysql_priv.h
1.326 05/08/23 20:21:41 mronstrom@stripped +2 -0
New method to downgrade write locks on table
sql/lock.cc
1.76 05/08/23 20:21:41 mronstrom@stripped +16 -0
New method to downgrade write locks on table
sql/handler.h
1.155 05/08/23 20:21:41 mronstrom@stripped +13 -1
New routine to copy partitions, no need of table object in call to
add partitions (already part of the handler)
mysys/thr_lock.c
1.48 05/08/23 20:21:41 mronstrom@stripped +15 -0
New routine to downgrade write locks
include/thr_lock.h
1.18 05/08/23 20:21:41 mronstrom@stripped +2 -0
New routine to downgrade write locks
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: mronstrom
# Host: c-6109e253.1238-1-64736c10.cust.bredbandsbolaget.se
# Root: /Users/mikron/wl2602
--- 1.17/include/thr_lock.h 2005-07-28 15:12:32 +02:00
+++ 1.18/include/thr_lock.h 2005-08-23 20:21:41 +02:00
@@ -147,6 +147,8 @@
my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread);
void thr_print_locks(void); /* For debugging */
my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data);
+void thr_downgrade_write_lock(THR_LOCK_DATA *data,
+ enum thr_lock_type new_lock_type);
my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data);
#ifdef __cplusplus
}
--- 1.47/mysys/thr_lock.c 2005-07-31 11:49:46 +02:00
+++ 1.48/mysys/thr_lock.c 2005-08-23 20:21:41 +02:00
@@ -1088,6 +1088,21 @@
}
+/* Downgrade a WRITE_* to a lower WRITE level */
+
+void thr_downgrade_write_lock(THR_LOCK_DATA *data,
+ enum thr_lock_type new_lock_type)
+{
+ THR_LOCK *lock=data->lock;
+ DBUG_ENTER("thr_downgrade_write_only_lock");
+
+ pthread_mutex_lock(&lock->mutex);
+ DBUG_ASSERT(data->type > new_lock_type);
+ data->type= new_lock_type;
+ check_locks(lock,"after downgrading lock",0);
+ pthread_mutex_unlock(&lock->mutex);
+ DBUG_VOID_RETURN;
+}
/* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */
--- 1.154/sql/handler.h 2005-08-22 17:56:50 +02:00
+++ 1.155/sql/handler.h 2005-08-23 20:21:41 +02:00
@@ -1252,7 +1252,7 @@
is ongoing in the server. This is used by ADD PARTITION all types
as well as by REORGANISE PARTITION.
*/
- virtual int add_partitions(TABLE *table, HA_CREATE_INFO *create_info,
+ virtual int add_partitions(HA_CREATE_INFO *create_info,
const char *path)
{ return HA_ERR_WRONG_COMMAND; }
@@ -1269,6 +1269,18 @@
*/
virtual int drop_partitions(const char *path)
{ return HA_ERR_WRONG_COMMAND; }
+
+ /*
+ SYNOPSIS
+ copy_partitions()
+ RETURN VALUES
+ TRUE Failure
+ FALSE Success
+ DESCRIPTION
+ Copy from reorged partitions to the new partitions
+ */
+ virtual int copy_partitions() { return HA_ERR_WRONG_COMMAND; }
+
/* lock_count() can be more than one if the table is a MERGE */
virtual uint lock_count(void) const { return 1; }
virtual THR_LOCK_DATA **store_lock(THD *thd,
--- 1.75/sql/lock.cc 2005-08-05 23:50:36 +02:00
+++ 1.76/sql/lock.cc 2005-08-23 20:21:41 +02:00
@@ -333,6 +333,22 @@
}
}
+/* Downgrade all locks on a table to new WRITE level from WRITE_ONLY */
+
+void mysql_lock_downgrade_write(THD *thd, TABLE *table,
+ thr_lock_type new_lock_type)
+{
+ MYSQL_LOCK *locked;
+ TABLE *write_lock_used;
+ if ((locked = get_lock_data(thd,&table,1,1,&write_lock_used)))
+ {
+ for (uint i=0; i < locked->lock_count; i++)
+ thr_downgrade_write_lock(locked->locks[i], new_lock_type);
+ my_free((gptr) locked,MYF(0));
+ }
+}
+
+
/* abort all other threads waiting to get lock in table */
void mysql_lock_abort(THD *thd, TABLE *table)
--- 1.325/sql/mysql_priv.h 2005-08-19 16:25:28 +02:00
+++ 1.326/sql/mysql_priv.h 2005-08-23 20:21:41 +02:00
@@ -1251,6 +1251,8 @@
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
void mysql_lock_abort(THD *thd, TABLE *table);
+void mysql_lock_downgrade_write(THD *thd, TABLE *table,
+ thr_lock_type new_lock_type);
bool mysql_lock_abort_for_thread(THD *thd, TABLE *table);
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);
bool lock_global_read_lock(THD *thd);
--- 1.265/sql/sql_table.cc 2005-08-22 18:03:09 +02:00
+++ 1.266/sql/sql_table.cc 2005-08-23 20:21:42 +02:00
@@ -43,7 +43,39 @@
ha_rows *copied,ha_rows *deleted);
static bool prepare_blob_field(THD *thd, create_field *sql_field);
static bool check_engine(THD *thd, const char *table_name,
- enum db_type *new_engine);
+ enum db_type *new_engine); static int
mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
+ List<create_field> *fields,
+ List<Key> *keys, bool tmp_table,
+ uint *db_options,
+ handler *file, KEY **key_info_buffer,
+ uint *key_count, int select_field_count);
+
+
+/*
+ Build the path to a file for a table (or the base path that can
+ then have various extensions stuck on to it).
+
+ SYNOPSIS
+ build_table_path()
+ buff Buffer to build the path into
+ bufflen sizeof(buff)
+ db Name of database
+ table Name of table
+ ext Filename extension
+
+ RETURN
+ 0 Error
+ # Size of path
+ */
+
+static uint build_table_path(char *buff, size_t bufflen, const char *db,
+ const char *table, const char *ext)
+{
+ strxnmov(buff, bufflen-1, mysql_data_home, "/", db, "/", table, ext,
+ NullS);
+ return unpack_filename(buff,buff);
+}
+
class write_frm_type
{
@@ -56,11 +88,19 @@
TABLE *table;
KEY *key_info_buffer;
uint key_count;
- uint syntax_len;
char *db;
char *table_name;
-}
+};
+static bool mysql_add_partitions(TABLE *table, HA_CREATE_INFO *create_info,
+ const char *db, const char *table_name)
+{
+ char path[FN_REFLEN+1];
+ DBUG_ENTER("mysql_add_partitions");
+
+ build_table_path(path, sizeof(path), db, table_name, "");
+ DBUG_RETURN(table->file->add_partitions(create_info, path));
+}
static bool mysql_write_frm(write_frm_type *wft,
bool initial_write,
@@ -71,15 +111,17 @@
partitions in add/drop state have temporarily changed their state
*/
partition_info *part_info= wft->table->s->part_info;
- char path[FN_REFLEN+1];
+ char path[FN_REFLEN+1], *part_syntax_buf;
+ uint syntax_len;
DBUG_ENTER("mysql_write_frm");
- if (initial_write)
+ if (initial_write &&
+ (mysql_prepare_table(wft->thd, wft->create_info, wft->create_list,
+ wft->key_list,/*tmp_table*/ 0, &wft->db_options,
+ wft->table->file, &wft->key_info_buffer,
+ &wft->key_count, /*select_field_count*/ 0)))
{
- mysql_prepare_table(wft->thd, wft->create_info, &wft->create_list,
- &wft->key_list, /*tmp_table*/ 0, &wft->db_options,
- wft->table->file, &wft->key_info_buffer,
- &wft->key_count, /*select_field_count*/ 0);
+ DBUG_RETURN(TRUE);
}
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
@@ -90,10 +132,11 @@
part_info->part_info_string= part_syntax_buf;
part_info->part_info_len= syntax_len;
build_table_path(path, sizeof(path), wft->db, wft->table_name, reg_ext);
- if (mysql_create_frm(wft->thd, path, wft->db, wft->table_name,
- wft->create_info, wft->create_list, wft->key_count,
- wft->key_info_buffer, wft->table->file) ||
- (create_handler_files && table->file->create_handler_files(path)))
+ if ((mysql_create_frm(wft->thd, path, wft->db, wft->table_name,
+ wft->create_info, *wft->create_list, wft->key_count,
+ wft->key_info_buffer, wft->table->file)) ||
+ (create_handler_files &&
+ wft->table->file->create_handler_files(path)))
{
DBUG_RETURN(TRUE);
}
@@ -145,7 +188,7 @@
static bool abort_and_upgrade_lock(THD *thd, TABLE *table, const char *db,
const char *table_name,
- uint *old_lock_level)
+ thr_lock_type *old_lock_level)
{
uint flags= RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG;
int error= FALSE;
@@ -165,31 +208,102 @@
}
/*
- Build the path to a file for a table (or the base path that can
- then have various extensions stuck on to it).
-
SYNOPSIS
- build_table_path()
- buff Buffer to build the path into
- bufflen sizeof(buff)
- db Name of database
- table Name of table
- ext Filename extension
+ mysql_drop_partitions()
+ thd Thread object
+ table Table object
+ db Database name
+ table_name Table name
+ RETURN VALUES
+ TRUE Failure
+ FALSE Success
+ DESCRIPTION
+ Drop the partitions marked with PART_TO_BE_DROPPED state and remove
+ those partitions from the list.
+*/
- RETURN
- 0 Error
- # Size of path
- */
+static bool mysql_drop_partitions(TABLE *table, const char *db,
+ const char *table_name)
+{
+ char path[FN_REFLEN+1];
+ partition_info *part_info= table->s->part_info;
+ List_iterator<partition_element> part_it(part_info->partitions);
+ uint i= 0, remove_count= 0;
+ DBUG_ENTER("mysql_drop_partitions");
-static uint build_table_path(char *buff, size_t bufflen, const char *db,
- const char *table, const char *ext)
+ build_table_path(path, sizeof(path), db, table_name, "");
+ if (table->file->drop_partitions(path))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ do
+ {
+ partition_element *part_elem= part_it++;
+ if (part_elem->part_state == PART_IS_DROPPED)
+ {
+ part_it.remove();
+ remove_count++;
+ }
+ } while (++i < part_info->no_parts);
+ part_info->no_parts-= remove_count;
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ SYNOPSIS
+ close_open_tables_and_downgrade()
+ thd Thread object
+ table Table object
+ db Database name
+ table_name Table name
+ old_lock_type Lock type to downgrade to
+ RESULT VALUES
+ NONE
+ DESCRIPTION
+ We need to ensure that any thread that has managed to open the table
+ but not yet encountered our lock on the table is also thrown out to
+ ensure that no threads see our frm changes premature to the final
+ version. The intermediate versions are only meant for use after a
+ crash and later REPAIR TABLE.
+ We also downgrade locks after the upgrade to WRITE_ONLY
+*/
+
+void close_open_tables_and_downgrade(THD *thd, TABLE *table, const char *db,
+ const char *table_name,
+ enum thr_lock_type old_lock_type)
{
- strxnmov(buff, bufflen-1, mysql_data_home, "/", db, "/", table, ext,
- NullS);
- return unpack_filename(buff,buff);
+ VOID(pthread_mutex_lock(&LOCK_open));
+ remove_table_from_cache(thd, db, table_name,
+ RTFC_WAIT_OTHER_THREAD_FLAG);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ mysql_lock_downgrade_write(thd, table, old_lock_type);
}
+/*
+ SYNOPSIS
+ mysql_wait_completed_table()
+ thd Thread object
+ table Table object
+ db Database name
+ table_name Table name
+ RETURN VALUES
+ NONE
+ DESCRIPTION
+ We have changed the frm file and now we want to wait for all users of
+ the old frm to complete before proceeding to ensure that no one
+ remains that uses the old frm definition.
+*/
+
+bool mysql_wait_completed_table(THD *thd, TABLE *table, const char *db,
+ const char *table_name)
+{
+ /* TODO RONM: Write this routine */
+ DBUG_ENTER("mysql_wait_completed_table");
+ DBUG_RETURN(FALSE);
+}
+
/*
delete (drop) tables.
@@ -3410,8 +3524,8 @@
enum db_type old_db_type,new_db_type;
uint need_copy_table= 0;
#ifdef HAVE_PARTITION_DB
- bool online_add_empty_partition= FALSE;
- bool online_drop_partition= FALSE;
+ bool online_drop_partition= FALSE, online_add_empty_partition= FALSE;
+ bool online_add_hash_partition= FALSE, online_reorg_partition= FALSE;
bool partition_changed= FALSE;
enum db_type default_engine_type;
#endif
@@ -4255,20 +4369,21 @@
#ifdef HAVE_PARTITION_DB
if (partition_changed &&
- (online_drop_partition || online_add_partition))
+ (online_drop_partition || online_add_empty_partition ||
+ online_add_hash_partition || online_reorg_partition))
{
/* Set-up struct used to write frm files */
partition_info *part_info= table->s->part_info;
+ thr_lock_type old_lock_type;
write_frm_type wft;
wft.thd= thd;
wft.create_info= create_info;
- wft.create_list= create_list;
- wft.key_list= key_list;
+ wft.create_list= &create_list;
+ wft.key_list= &key_list;
wft.db_options= 0;
wft.table= table;
- wft.key_info_buffer= key_info_buffer;
- wft.key_count= key_count;
- wft.syntax_len= 0;
+ wft.key_info_buffer= wft.key_info_buffer;
+ wft.key_count= wft.key_count;
wft.db= db;
wft.table_name= table_name;
thd->lex->part_info= part_info;
@@ -4293,72 +4408,24 @@
6) Write binlog and return from statement (including releasing all
remaining locks).
*/
- uint old_lock_type;
- if (abort_and_upgrade_lock(thd, table, db,
- table_name, &old_lock_type))
- {
- DBUG_RETURN(TRUE);
- }
- /*
- Prepare table to prepare for writing a new frm file where the
- partitions in add/drop state have temporarily changed their state
- */
- if (mysql_write_frm(&wft, TRUE, FALSE))
+ if ((abort_and_upgrade_lock(thd, table, db,
+ table_name, &old_lock_type)) ||
+ (mysql_write_frm(&wft, TRUE, FALSE)) ||
+ (mysql_drop_partitions(table, db, table_name)) ||
+ (mysql_write_frm(&wft, FALSE, TRUE)))
{
DBUG_RETURN(TRUE);
}
-
- /*
- Frm file have been updated to reflect the change about to happen.
- Now perform the change
- */
- {
- char path[FN_REFLEN+1];
- List_iterator<partition_element> part_it(part_info->partitions);
- uint i= 0, remove_count= 0;
-
- build_table_path(path, sizeof(path), db, table_name, "");
- if (table->file->drop_partitions(path))
- {
- DBUG_RETURN(TRUE);
- }
- do
- {
- partition_element *part_elem= part_it++;
- if (part_elem->part_state == PART_IS_DROPPED)
- {
- part_it.remove();
- remove_count++;
- }
- } while (++i < part_info->no_parts);
- part_info->no_parts-= remove_count;
- }
- /*
- Now we write the final version of the frm file to reflect the
- new partitioning after the change.
- */
- if (mysql_write_frm(&wft, FALSE, TRUE))
- {
- DBUG_RETURN(TRUE);
- }
- VOID(pthread_mutex_lock(&LOCK_open));
- /*
- We need to ensure that any thread that has managed to open the table
- but not yet encountered our lock on the table is also thrown out to
- ensure that no threads see our frm changes premature to the final
- version. The intermediate versions are only meant for use after a
- crash and later REPAIR TABLE.
- */
- remove_table_from_cache(thd, db, table_name,
- RTFC_WAIT_OTHER_THREAD_FLAG);
- VOID(pthread_mutex_unlock(&LOCK_open));
+ close_open_tables_and_downgrade(thd, table,
+ db, table_name, old_lock_type);
}
- else if (online_add_partition)
+ else if (online_add_empty_partition)
{
/*
ADD RANGE/LIST PARTITIONS
- 1) Downgrade all locks to TL_WRITE_ALLOW_WRITE
+ 1) Downgrade all locks to TL_WRITE_ALLOW_WRITE unless the user have
+ used lock table before starting ALTER TABLE.
2) Write the new frm file where state of added partitions is
changed to PART_TO_BE_ADDED
3) Add the new partitions
@@ -4370,8 +4437,20 @@
6) Write binlog and return from statement (including releasing all
remaining locks).
*/
+ if (table->reginfo.lock_type == TL_WRITE_ALLOW_READ)
+ mysql_lock_downgrade_write(thd, table, TL_WRITE_ALLOW_WRITE);
+ if ((mysql_write_frm(&wft, TRUE, FALSE)) ||
+ (mysql_add_partitions(table, create_info, db, table_name)) ||
+ (abort_and_upgrade_lock(thd, table, db,
+ table_name, &old_lock_type)) ||
+ (mysql_write_frm(&wft, FALSE, TRUE)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ close_open_tables_and_downgrade(thd, table,
+ db, table_name, old_lock_type);
}
- else if (TRUE)
+ else if (online_add_hash_partition || online_reorg_partition)
{
/*
ADD HASH PARTITION/
@@ -4389,6 +4468,19 @@
7) Write binlog and return from statement (including releasing all
remaining locks).
*/
+ if ((mysql_write_frm(&wft, TRUE, FALSE)) ||
+ (mysql_add_partitions(table, create_info, db, table_name)) ||
+ (table->file->copy_partitions()) ||
+ (abort_and_upgrade_lock(thd, table, db,
+ table_name, &old_lock_type)) ||
+ (mysql_drop_partitions(table, db, table_name)) ||
+ (mysql_write_frm(&wft, FALSE, TRUE)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ close_open_tables_and_downgrade(thd, table,
+ db, table_name, old_lock_type);
+
}
else
{
@@ -4410,6 +4502,18 @@
9) Write binlog and return from statement (including releasing all
remaining locks).
*/
+ if (table->reginfo.lock_type == TL_WRITE_ALLOW_READ)
+ mysql_lock_downgrade_write(thd, table, TL_WRITE_ALLOW_WRITE);
+ if ((mysql_write_frm(&wft, TRUE, FALSE)) ||
+ (mysql_add_partitions(table, create_info, db, table_name)) ||
+ (table->file->copy_partitions()) ||
+ (mysql_write_frm(&wft, FALSE, TRUE)) ||
+ (mysql_wait_completed_table(thd, table, db, table_name)) ||
+ (mysql_drop_partitions(table, db, table_name)) ||
+ (mysql_wait_completed_table(thd, table, db, table_name)))
+ {
+ DBUG_RETURN(TRUE);
+ }
}
/*
A final step is to write the query to the binlog and send ok to the
@@ -4422,10 +4526,6 @@
}
#endif
- if (table->file->add_partitions(table, create_info, path))
- {
- DBUG_RETURN(TRUE);
- }
/*
Handling of symlinked tables:
If no rename:
| Thread |
|---|
| • bk commit into 5.1 tree (mronstrom:1.1895) | mikael | 24 Aug |