===== include/my_base.h 1.90 vs edited ===== --- 1.90/include/my_base.h 2006-08-02 13:19:44 +02:00 +++ edited/include/my_base.h 2006-08-02 11:38:03 +02:00 @@ -127,6 +127,10 @@ HA_EXTRA_RESET_STATE, /* Reset positions */ HA_EXTRA_IGNORE_DUP_KEY, /* Dup keys don't rollback everything*/ HA_EXTRA_NO_IGNORE_DUP_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 */ ===== sql/ha_innodb.cc 1.283 vs edited ===== --- 1.283/sql/ha_innodb.cc 2006-08-02 13:19:57 +02:00 +++ edited/sql/ha_innodb.cc 2006-08-02 12:02:42 +02:00 @@ -1855,7 +1855,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 */ @@ -2012,7 +2012,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 */ @@ -2052,7 +2052,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 */ @@ -3417,19 +3417,13 @@ 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. */ + mutex_enter_noninline(&(prebuilt->table->autoinc_mutex_mysql)); update_auto_increment(); auto_inc_used = 1; @@ -3478,6 +3472,10 @@ } } + if (auto_inc_used != 0) { + mutex_exit_noninline(&(prebuilt->table->autoinc_mutex_mysql)); + } + innodb_srv_conc_exit_innodb(prebuilt->trx); error = convert_error_code_to_mysql(error, user_thd); @@ -6118,6 +6116,9 @@ 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; + break; default:/* Do nothing */ ; } @@ -7001,13 +7002,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); @@ -7143,13 +7139,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); @@ -7444,7 +7435,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 */ ===== sql/sql_insert.cc 1.216 vs edited ===== --- 1.216/sql/sql_insert.cc 2006-08-02 13:19:59 +02:00 +++ edited/sql/sql_insert.cc 2006-08-02 12:04:12 +02:00 @@ -451,6 +451,11 @@ if (duplic == DUP_REPLACE && (!table->triggers || !table->triggers->has_delete_triggers())) table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); + + /* 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 ===== storage/innobase/dict/dict0mem.c 1.22 vs edited ===== --- 1.22/storage/innobase/dict/dict0mem.c 2006-08-02 13:20:03 +02:00 +++ edited/storage/innobase/dict/dict0mem.c 2006-08-02 12:14:52 +02:00 @@ -85,6 +85,11 @@ table->max_row_size = 0; mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX); + mutex_create(&table->autoinc_mutex_mysql, SYNC_DICT_AUTOINC_MUTEX); + + rw_lock_create(&(table->auto_inc_rw_lock), SYNC_NO_ORDER_CHECK); + + table->autoinc_inited = FALSE; table->autoinc_inited = FALSE; @@ -104,6 +109,9 @@ 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_mysql)); mutex_free(&(table->autoinc_mutex)); mem_heap_free(table->heap); } ===== storage/innobase/include/dict0mem.h 1.30 vs edited ===== --- 1.30/storage/innobase/include/dict0mem.h 2006-08-02 13:20:03 +02:00 +++ edited/storage/innobase/include/dict0mem.h 2006-08-02 11:42:28 +02:00 @@ -382,7 +382,9 @@ any latch, because this is only used for heuristics */ /*----------------------*/ - mutex_t autoinc_mutex; + rw_lock_t auto_inc_rw_lock; + mutex_t autoinc_mutex; + mutex_t autoinc_mutex_mysql; /* mutex protecting the autoincrement counter */ ibool autoinc_inited; ===== storage/innobase/include/row0mysql.h 1.48 vs edited ===== --- 1.48/storage/innobase/include/row0mysql.h 2006-08-02 13:20:04 +02:00 +++ edited/storage/innobase/include/row0mysql.h 2006-08-02 11:43:32 +02:00 @@ -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 */ ===== storage/innobase/include/trx0trx.h 1.54 vs edited ===== --- 1.54/storage/innobase/include/trx0trx.h 2006-08-02 13:20:04 +02:00 +++ edited/storage/innobase/include/trx0trx.h 2006-08-02 11:44:38 +02:00 @@ -541,6 +541,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 or session is using READ COMMITTED ===== storage/innobase/lock/lock0lock.c 1.68 vs edited ===== --- 1.68/storage/innobase/lock/lock0lock.c 2006-08-02 13:20:04 +02:00 +++ edited/storage/innobase/lock/lock0lock.c 2006-08-02 12:18:24 +02:00 @@ -16,6 +16,7 @@ #include "trx0purge.h" #include "dict0mem.h" #include "trx0sys.h" +#include "row0mysql.h" /* 2 function prototypes copied from ha_innodb.cc: */ @@ -3910,7 +3911,11 @@ #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); count = 0; ===== storage/innobase/row/row0mysql.c 1.127 vs edited ===== --- 1.127/storage/innobase/row/row0mysql.c 2006-08-02 13:20:05 +02:00 +++ edited/storage/innobase/row/row0mysql.c 2006-08-02 11:50:35 +02:00 @@ -893,12 +893,15 @@ /*===============================*/ 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; } /************************************************************************* @@ -908,73 +911,24 @@ 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; + 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; } - - /* 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); + else + { + rw_lock_s_lock(&(prebuilt->table->auto_inc_rw_lock)); + prebuilt->trx->auto_inc_lock_mode= RW_S_LATCH; } - - que_thr_stop_for_mysql_no_error(thr, trx); - - trx->op_info = ""; - - return((int) err); + prebuilt->trx->auto_inc_rw_lock= &(prebuilt->table->auto_inc_rw_lock); } /************************************************************************* ===== storage/innobase/trx/trx0trx.c 1.66 vs edited ===== --- 1.66/storage/innobase/trx/trx0trx.c 2006-08-02 13:20:05 +02:00 +++ edited/storage/innobase/trx/trx0trx.c 2006-08-02 11:52:26 +02:00 @@ -185,6 +185,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;