===== include/my_base.h 1.70 vs edited ===== --- 1.70/include/my_base.h 2005-06-24 11:34:50 -06:00 +++ edited/include/my_base.h 2005-06-28 15:17:54 -06:00 @@ -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 */ ===== innobase/dict/dict0dict.c 1.65 vs edited ===== --- 1.65/innobase/dict/dict0dict.c 2005-06-20 22:36:01 -06:00 +++ edited/innobase/dict/dict0dict.c 2005-06-28 15:48:25 -06:00 @@ -1251,6 +1251,8 @@ mutex_free(&(table->autoinc_mutex)); + rw_lock_free(&(table->auto_inc_rw_lock)); + size = mem_heap_get_size(table->heap); ut_ad(dict_sys->size >= size); ===== innobase/dict/dict0mem.c 1.17 vs edited ===== --- 1.17/innobase/dict/dict0mem.c 2005-04-22 04:44:55 -06:00 +++ edited/innobase/dict/dict0mem.c 2005-06-28 15:47:23 -06:00 @@ -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; ===== innobase/include/dict0mem.h 1.24 vs edited ===== --- 1.24/innobase/include/dict0mem.h 2005-01-14 04:54:15 -07:00 +++ edited/innobase/include/dict0mem.h 2005-06-28 15:46:54 -06:00 @@ -424,6 +424,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 */ ===== innobase/include/row0mysql.h 1.42 vs edited ===== --- 1.42/innobase/include/row0mysql.h 2005-06-08 06:45:47 -06:00 +++ edited/innobase/include/row0mysql.h 2005-06-28 16:01:05 -06: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 */ ===== innobase/include/trx0trx.h 1.47 vs edited ===== --- 1.47/innobase/include/trx0trx.h 2005-06-08 06:45:47 -06:00 +++ edited/innobase/include/trx0trx.h 2005-06-28 15:25:59 -06:00 @@ -495,6 +495,10 @@ 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; + ibool trx_create_lock;/* this is TRUE if we have created a new lock for a record accessed */ UT_LIST_NODE_T(trx_t) ===== innobase/lock/lock0lock.c 1.62 vs edited ===== --- 1.62/innobase/lock/lock0lock.c 2005-06-20 22:36:01 -06:00 +++ edited/innobase/lock/lock0lock.c 2005-06-28 16:42:47 -06:00 @@ -3795,8 +3795,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; ===== innobase/row/row0mysql.c 1.109 vs edited ===== --- 1.109/innobase/row/row0mysql.c 2005-06-20 22:36:02 -06:00 +++ edited/innobase/row/row0mysql.c 2005-06-28 23:16:26 -06:00 @@ -886,12 +886,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; } /************************************************************************* @@ -901,73 +902,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); + 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; } - - 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); + 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); } /************************************************************************* ===== innobase/trx/trx0trx.c 1.56 vs edited ===== --- 1.56/innobase/trx/trx0trx.c 2005-06-20 22:36:02 -06:00 +++ edited/innobase/trx/trx0trx.c 2005-06-28 15:16:33 -06:00 @@ -158,7 +158,9 @@ trx->n_tickets_to_enter_innodb = 0; trx->auto_inc_lock = NULL; - + trx->auto_inc_lock_mode= 0; + trx->is_multiple_insert= FALSE; + trx->read_view_heap = mem_heap_create(256); trx->read_view = NULL; ===== sql/ha_innodb.cc 1.221 vs edited ===== --- 1.221/sql/ha_innodb.cc 2005-06-21 02:49:46 -06:00 +++ edited/sql/ha_innodb.cc 2005-06-28 23:16:04 -06:00 @@ -1569,7 +1569,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 */ @@ -1949,7 +1949,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 */ @@ -1989,7 +1989,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 */ @@ -3196,15 +3196,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. */ @@ -5788,6 +5781,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 */ ; } @@ -6590,13 +6585,8 @@ return(0); } - error = row_lock_table_autoinc_for_mysql(prebuilt); - - if (error != DB_SUCCESS) { - 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); /* Check again if someone has initialized the counter meanwhile */ auto_inc = dict_table_autoinc_read(prebuilt->table); @@ -6968,7 +6958,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.163 vs edited ===== --- 1.163/sql/sql_insert.cc 2005-06-22 11:07:26 -06:00 +++ edited/sql/sql_insert.cc 2005-06-28 15:21:20 -06:00 @@ -369,6 +369,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