diff -r -u mysql-5.0.21/include/my_base.h mysql-5.0.21-autoinc/include/my_base.h --- mysql-5.0.21/include/my_base.h 2006-04-26 20:31:13.000000000 +0200 +++ mysql-5.0.21-autoinc/include/my_base.h 2006-05-07 19:27:16.000000000 +0200 @@ -139,6 +139,10 @@ Instructs InnoDB to retrieve at least all the primary key columns */ HA_EXTRA_RETRIEVE_PRIMARY_KEY, + /* + Instructs InnoDB to set lock for multiple value insert + */ + HA_EXTRA_MULTIPLE_INSERT, HA_EXTRA_PREPARE_FOR_DELETE, HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */ HA_EXTRA_PRELOAD_BUFFER_SIZE, /* Set buffer size for preloading */ diff -r -u mysql-5.0.21/innobase/dict/dict0mem.c mysql-5.0.21-autoinc/innobase/dict/dict0mem.c --- mysql-5.0.21/innobase/dict/dict0mem.c 2006-04-26 20:30:55.000000000 +0200 +++ mysql-5.0.21-autoinc/innobase/dict/dict0mem.c 2006-05-07 23:05:10.000000000 +0200 @@ -90,6 +90,8 @@ mutex_create(&(table->autoinc_mutex)); mutex_set_level(&(table->autoinc_mutex), SYNC_DICT_AUTOINC_MUTEX); + rw_lock_create(&(table->auto_inc_rw_lock)); + table->autoinc_inited = FALSE; table->magic_n = DICT_TABLE_MAGIC_N; @@ -107,6 +109,8 @@ { ut_ad(table); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + + rw_lock_free(&(table->auto_inc_rw_lock)); mutex_free(&(table->autoinc_mutex)); mem_heap_free(table->heap); diff -r -u mysql-5.0.21/innobase/include/dict0mem.h mysql-5.0.21-autoinc/innobase/include/dict0mem.h --- mysql-5.0.21/innobase/include/dict0mem.h 2006-04-26 20:30:48.000000000 +0200 +++ mysql-5.0.21-autoinc/innobase/include/dict0mem.h 2006-05-07 19:27:16.000000000 +0200 @@ -431,6 +431,7 @@ any latch, because this is only used for heuristics */ /*----------------------*/ + rw_lock_t auto_inc_rw_lock; mutex_t autoinc_mutex; /* mutex protecting the autoincrement counter */ diff -r -u mysql-5.0.21/innobase/include/row0mysql.h mysql-5.0.21-autoinc/innobase/include/row0mysql.h --- mysql-5.0.21/innobase/include/row0mysql.h 2006-04-26 20:30:55.000000000 +0200 +++ mysql-5.0.21-autoinc/innobase/include/row0mysql.h 2006-05-07 19:27:16.000000000 +0200 @@ -165,7 +165,7 @@ It is not compatible with another AUTO_INC or exclusive lock on the table. */ -int +void row_lock_table_autoinc_for_mysql( /*=============================*/ /* out: error code or DB_SUCCESS */ diff -r -u mysql-5.0.21/innobase/include/trx0trx.h mysql-5.0.21-autoinc/innobase/include/trx0trx.h --- mysql-5.0.21/innobase/include/trx0trx.h 2006-04-26 20:30:56.000000000 +0200 +++ mysql-5.0.21-autoinc/innobase/include/trx0trx.h 2006-05-07 19:31:04.000000000 +0200 @@ -543,6 +543,9 @@ lock_t* auto_inc_lock; /* possible auto-inc lock reserved by the transaction; note that it is also in the lock list trx_locks */ + ibool auto_inc_lock_mode; /* 0, RW_S_LATCH, or RW_X_LATCH */ + rw_lock_t* auto_inc_rw_lock; + ibool is_multiple_insert; dict_index_t* new_rec_locks[2];/* these are normally NULL; if srv_locks_unsafe_for_binlog is TRUE, in a cursor search, if we set a new diff -r -u mysql-5.0.21/innobase/lock/lock0lock.c mysql-5.0.21-autoinc/innobase/lock/lock0lock.c --- mysql-5.0.21/innobase/lock/lock0lock.c 2006-04-26 20:30:37.000000000 +0200 +++ mysql-5.0.21-autoinc/innobase/lock/lock0lock.c 2006-05-07 19:27:16.000000000 +0200 @@ -3879,8 +3879,12 @@ #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ + + if (trx->auto_inc_lock_mode) { + row_unlock_table_autoinc_for_mysql(trx); + } - lock = UT_LIST_GET_LAST(trx->trx_locks); + lock = UT_LIST_GET_LAST(trx->trx_locks); count = 0; diff -r -u mysql-5.0.21/innobase/row/row0mysql.c mysql-5.0.21-autoinc/innobase/row/row0mysql.c --- mysql-5.0.21/innobase/row/row0mysql.c 2006-04-26 20:30:55.000000000 +0200 +++ mysql-5.0.21-autoinc/innobase/row/row0mysql.c 2006-05-07 19:27:16.000000000 +0200 @@ -887,12 +887,13 @@ /*===============================*/ trx_t* trx) /* in: transaction */ { - if (!trx->auto_inc_lock) { - - return; - } - - lock_table_unlock_auto_inc(trx); + if (trx->auto_inc_lock_mode == RW_X_LATCH) + rw_lock_x_unlock(trx->auto_inc_rw_lock); + if (trx->auto_inc_lock_mode == RW_S_LATCH) + rw_lock_s_unlock(trx->auto_inc_rw_lock); + trx->auto_inc_lock_mode= 0; + trx->auto_inc_rw_lock= NULL; + trx->is_multiple_insert= FALSE; } /************************************************************************* @@ -902,73 +903,25 @@ It is not compatible with another AUTO_INC or exclusive lock on the table. */ -int +void row_lock_table_autoinc_for_mysql( /*=============================*/ /* out: error code or DB_SUCCESS */ row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL table handle */ { - trx_t* trx = prebuilt->trx; - ins_node_t* node = prebuilt->ins_node; - que_thr_t* thr; - ulint err; - ibool was_lock_wait; - - ut_ad(trx); - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - - if (trx->auto_inc_lock) { - - return(DB_SUCCESS); - } - - trx->op_info = "setting auto-inc lock"; - - if (node == NULL) { - row_get_prebuilt_insert_row(prebuilt); - node = prebuilt->ins_node; - } - - /* We use the insert query graph as the dummy graph needed - in the lock module call */ - - thr = que_fork_get_first_thr(prebuilt->ins_graph); - - que_thr_move_to_run_state_for_mysql(thr, trx); - -run_again: - thr->run_node = node; - thr->prev_node = node; - - /* It may be that the current session has not yet started - its transaction, or it has been committed: */ - - trx_start_if_not_started(trx); - - err = lock_table(0, prebuilt->table, LOCK_AUTO_INC, thr); - - trx->error_state = err; - - if (err != DB_SUCCESS) { - que_thr_stop_for_mysql(thr); - - was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL); - - if (was_lock_wait) { - goto run_again; - } - - trx->op_info = ""; - - return((int) err); + if (prebuilt->trx->is_multiple_insert) + { + rw_lock_x_lock(&(prebuilt->table->auto_inc_rw_lock)); + prebuilt->trx->auto_inc_lock_mode= RW_X_LATCH; + } + else + { + rw_lock_s_lock(&(prebuilt->table->auto_inc_rw_lock)); + prebuilt->trx->auto_inc_lock_mode= RW_S_LATCH; } + prebuilt->trx->auto_inc_rw_lock= &(prebuilt->table->auto_inc_rw_lock); - que_thr_stop_for_mysql_no_error(thr, trx); - - trx->op_info = ""; - - return((int) err); } /************************************************************************* diff -r -u mysql-5.0.21/innobase/trx/trx0trx.c mysql-5.0.21-autoinc/innobase/trx/trx0trx.c --- mysql-5.0.21/innobase/trx/trx0trx.c 2006-04-26 20:30:48.000000000 +0200 +++ mysql-5.0.21-autoinc/innobase/trx/trx0trx.c 2006-05-07 19:29:18.000000000 +0200 @@ -186,6 +186,8 @@ trx->n_tickets_to_enter_innodb = 0; trx->auto_inc_lock = NULL; + trx->auto_inc_lock_mode= 0; + trx->is_multiple_insert= FALSE; trx->global_read_view_heap = mem_heap_create(256); trx->global_read_view = NULL; diff -r -u mysql-5.0.21/sql/ha_innodb.cc mysql-5.0.21-autoinc/sql/ha_innodb.cc --- mysql-5.0.21/sql/ha_innodb.cc 2006-04-26 20:30:47.000000000 +0200 +++ mysql-5.0.21-autoinc/sql/ha_innodb.cc 2006-05-07 20:24:30.000000000 +0200 @@ -1684,7 +1684,7 @@ /* We just mark the SQL statement ended and do not do a transaction commit */ - if (trx->auto_inc_lock) { + if (trx->auto_inc_lock_mode) { /* If we had reserved the auto-inc lock for some table in this SQL statement we release it now */ @@ -1841,7 +1841,7 @@ innobase_release_stat_resources(trx); - if (trx->auto_inc_lock) { + if (trx->auto_inc_lock_mode) { /* If we had reserved the auto-inc lock for some table (if we come here to roll back the latest SQL statement) we release it now before a possibly lengthy rollback */ @@ -1881,7 +1881,7 @@ innobase_release_stat_resources(trx); - if (trx->auto_inc_lock) { + if (trx->auto_inc_lock_mode) { /* If we had reserved the auto-inc lock for some table (if we come here to roll back the latest SQL statement) we release it now before a possibly lengthy rollback */ @@ -3241,15 +3241,8 @@ end. This lock also prevents a race where two threads would call ::get_auto_increment() simultaneously. */ - error = row_lock_table_autoinc_for_mysql(prebuilt); - - if (error != DB_SUCCESS) { - /* Deadlock or lock wait timeout */ - - error = convert_error_code_to_mysql(error, user_thd); - - goto func_exit; - } + if (!prebuilt->trx->auto_inc_lock_mode) + row_lock_table_autoinc_for_mysql(prebuilt); /* We must use the handler code to update the auto-increment value to be sure that we increment it correctly. */ @@ -5898,6 +5891,8 @@ case HA_EXTRA_KEYREAD_PRESERVE_FIELDS: prebuilt->keep_other_fields_on_keyread = 1; break; + case HA_EXTRA_MULTIPLE_INSERT: + prebuilt->trx->is_multiple_insert= 1; default:/* Do nothing */ ; } @@ -6755,13 +6750,8 @@ goto func_exit_early; } - error = row_lock_table_autoinc_for_mysql(prebuilt); - - if (error != DB_SUCCESS) { - error = convert_error_code_to_mysql(error, user_thd); - - goto func_exit_early; - } + if (!prebuilt->trx->auto_inc_lock_mode) + row_lock_table_autoinc_for_mysql(prebuilt); /* Check again if someone has initialized the counter meanwhile */ auto_inc = dict_table_autoinc_read(prebuilt->table); @@ -6890,13 +6880,8 @@ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; int error; - error = row_lock_table_autoinc_for_mysql(prebuilt); - - if (error != DB_SUCCESS) { - error = convert_error_code_to_mysql(error, user_thd); - - DBUG_RETURN(error); - } + if (!prebuilt->trx->auto_inc_lock_mode) + row_lock_table_autoinc_for_mysql(prebuilt); dict_table_autoinc_initialize(prebuilt->table, value); @@ -7191,7 +7176,7 @@ /* We just mark the SQL statement ended and do not do a transaction prepare */ - if (trx->auto_inc_lock) { + if (trx->auto_inc_lock_mode) { /* If we had reserved the auto-inc lock for some table in this SQL statement we release it now */ diff -r -u mysql-5.0.21/sql/sql_insert.cc mysql-5.0.21-autoinc/sql/sql_insert.cc --- mysql-5.0.21/sql/sql_insert.cc 2006-04-26 20:31:04.000000000 +0200 +++ mysql-5.0.21-autoinc/sql/sql_insert.cc 2006-05-07 19:27:16.000000000 +0200 @@ -401,6 +401,11 @@ thd->proc_info="update"; if (duplic != DUP_ERROR || ignore) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + + /* inform InnoDB we have multiple values insert */ + if (counter > 1) + table->file->extra(HA_EXTRA_MULTIPLE_INSERT); + /* let's *try* to start bulk inserts. It won't necessary start them as values_list.elements should be greater than