From 32d280ba3202c416ecf3ad15f5d2a6316c7dd128 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Apr 2007 18:42:46 +0500 Subject: bug #27405 (Partitioning InnoDB auto_increment bug) InnoDB engine changes internal auto_increment counter only after ha_innodb::write_row, so two threads can't simultaneously operate between ha_innodb::update_autoincrement and ha_innodb::write_row. So concurrent execution of ha_partition::write_row prevented sql/ha_partition.cc: use table_share->mutex to avoid concurrent write_row for AUTO_INCREMENTed table --- sql/ha_partition.cc | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'sql/ha_partition.cc') diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 3c25dcd202f..5247e665b0f 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2647,6 +2647,7 @@ int ha_partition::write_row(byte * buf) uint32 part_id; int error; longlong func_value; + bool autoincrement_lock= false; #ifdef NOT_NEEDED byte *rec0= m_rec0; #endif @@ -2662,7 +2663,21 @@ int ha_partition::write_row(byte * buf) or a new row, then update the auto_increment value in the record. */ if (table->next_number_field && buf == table->record[0]) + { + /* + Some engines (InnoDB for example) can change autoincrement + counter only after 'table->write_row' operation. + So if another thread gets inside the ha_partition::write_row + before it is complete, it gets same auto_increment value, + which means DUP_KEY error (bug #27405) + Here we separate the access using table_share->mutex, and + use autoincrement_lock variable to avoid unnecessary locks. + Probably not an ideal solution. + */ + autoincrement_lock= true; + pthread_mutex_lock(&table_share->mutex); update_auto_increment(); + } my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set); #ifdef NOT_NEEDED @@ -2683,11 +2698,15 @@ int ha_partition::write_row(byte * buf) if (unlikely(error)) { m_part_info->err_value= func_value; - DBUG_RETURN(error); + goto exit; } m_last_part= part_id; DBUG_PRINT("info", ("Insert in partition %d", part_id)); - DBUG_RETURN(m_file[part_id]->write_row(buf)); + error= m_file[part_id]->write_row(buf); +exit: + if (autoincrement_lock) + pthread_mutex_unlock(&table_share->mutex); + DBUG_RETURN(error); } -- cgit v1.2.1