diff options
author | unknown <heikki@hundin.mysql.fi> | 2003-06-05 15:58:23 +0300 |
---|---|---|
committer | unknown <heikki@hundin.mysql.fi> | 2003-06-05 15:58:23 +0300 |
commit | 6d4ed167872eb6c29693fb0cbeaa79e0aecbe627 (patch) | |
tree | 844a81e1a24550dab23f781f72f3533f4fc13de3 /sql/ha_innodb.cc | |
parent | d6f2e8c1731b79765addac5c10f256ce91b7f0f7 (diff) | |
download | mariadb-git-6d4ed167872eb6c29693fb0cbeaa79e0aecbe627.tar.gz |
ha_innodb.cc, handler.cc:
Fix the BDB crash in the previous push; to save CPU remove duplicate calls of commit in InnoDB
sql/handler.cc:
Fix the BDB crash in the previous push; to save CPU remove duplicate calls of commit in InnoDB
sql/ha_innodb.cc:
Fix the BDB crash in the previous push; to save CPU remove duplicate calls of commit in InnoDB
Diffstat (limited to 'sql/ha_innodb.cc')
-rw-r--r-- | sql/ha_innodb.cc | 227 |
1 files changed, 149 insertions, 78 deletions
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 50bb4275eaa..9cc86edddf8 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -131,9 +131,11 @@ static void innobase_print_error(const char* db_errpfx, char* buffer); /********************************************************************** Releases possible search latch and InnoDB thread FIFO ticket. These should -be released at each SQL statement end. It does no harm to release these -also in the middle of an SQL statement. */ +be released at each SQL statement end, and also when mysqld passes the +control to the client. It does no harm to release these also in the middle +of an SQL statement. */ static +inline void innobase_release_stat_resources( /*============================*/ @@ -896,6 +898,11 @@ innobase_commit_low( /*================*/ trx_t* trx) /* in: transaction handle */ { + if (trx->conc_state == TRX_NOT_STARTED) { + + return; + } + /* TODO: Guilhem should check if master_log_name, pending etc. are right if the master log gets rotated! Possible bug here. Comment by Heikki March 4, 2003. */ @@ -910,11 +917,13 @@ innobase_commit_low( active_mi->rli.event_len + active_mi->rli.pending)); } - trx_commit_for_mysql(trx); + + trx_commit_for_mysql(trx); } /********************************************************************* -Commits a transaction in an InnoDB database. */ +Commits a transaction in an InnoDB database or marks an SQL statement +ended. */ int innobase_commit( @@ -932,29 +941,45 @@ innobase_commit( DBUG_ENTER("innobase_commit"); DBUG_PRINT("trans", ("ending transaction")); - trx = check_trx_exists(thd); + /* The flag thd->transaction.all.innodb_active_trans is set to 1 + in ::external_lock and ::start_stmt, and it is only set to 0 in + a commit or a rollback. If it is 0 we know there cannot be resources + to be freed and we can return immediately. */ - if (trx->auto_inc_lock) { - - /* If we had reserved the auto-inc lock for - some table in this SQL statement, we release it now */ - - srv_conc_enter_innodb(trx); - row_unlock_table_autoinc_for_mysql(trx); - srv_conc_exit_innodb(trx); + if (thd->transaction.all.innodb_active_trans == 0) { + + DBUG_RETURN(0); } - if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) { + trx = check_trx_exists(thd); + + if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle + || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + innobase_commit_low(trx); - thd->transaction.all.innodb_active_trans=0; + + thd->transaction.all.innodb_active_trans = 0; + } else { + if (trx->auto_inc_lock) { + /* If we had reserved the auto-inc lock for some + table in this SQL statement we release it now */ + + srv_conc_enter_innodb(trx); + row_unlock_table_autoinc_for_mysql(trx); + srv_conc_exit_innodb(trx); + } + /* Store the current undo_no of the transaction so that we + know where to roll back if we have to roll back the next + SQL statement */ + + trx_mark_sql_stat_end(trx); } - /* Release possible statement level resources */ + /* Release a possible FIFO ticket and search latch */ innobase_release_stat_resources(trx); - trx_mark_sql_stat_end(trx); - /* Tell InnoDB server that there might be work for - utility threads: */ + /* Tell the InnoDB server that there might be work for utility + threads: */ srv_active_wake_master_thread(); @@ -1025,7 +1050,7 @@ innobase_commit_complete( } /********************************************************************* -Rolls back a transaction in an InnoDB database. */ +Rolls back a transaction or the latest SQL statement in an InnoDB database. */ int innobase_rollback( @@ -1066,11 +1091,9 @@ innobase_rollback( srv_conc_exit_innodb(trx); - /* Release possible statement level resources */ + /* Release a possible FIFO ticket and search latch */ innobase_release_stat_resources(trx); - trx_mark_sql_stat_end(trx); - DBUG_RETURN(convert_error_code_to_mysql(error, NULL)); } @@ -2994,6 +3017,8 @@ create_index( KEY* key; KEY_PART_INFO* key_part; ulint ind_type; + ulint col_type; + ulint prefix_len; ulint i; DBUG_ENTER("create_index"); @@ -3021,10 +3046,32 @@ create_index( for (i = 0; i < n_fields; i++) { key_part = key->key_part + i; + if (key_part->length != key_part->field->pack_length()) { + prefix_len = key_part->length; + + col_type = get_innobase_type_from_mysql_type( + key_part->field); + if (col_type == DATA_INT + || col_type == DATA_FLOAT + || col_type == DATA_DOUBLE + || col_type == DATA_DECIMAL) { + fprintf(stderr, +"InnoDB: error: MySQL is trying to create a column prefix index field\n" +"InnoDB: on an inappropriate data type %lu. Table name %s, column name %s.\n", + col_type, table_name, + key_part->field->field_name); + + prefix_len = 0; + } + } else { + prefix_len = 0; + } + /* We assume all fields should be sorted in ascending order, hence the '0': */ dict_mem_index_add_field(index, - (char*) key_part->field->field_name, 0); + (char*) key_part->field->field_name, + 0, prefix_len); } error = row_create_index_for_mysql(index, trx); @@ -3562,8 +3609,7 @@ ha_innobase::records_in_range( /************************************************************************* Gives an UPPER BOUND to the number of rows in a table. This is used in -filesort.cc and its better if the upper bound hold. -*/ +filesort.cc. */ ha_rows ha_innobase::estimate_number_of_rows(void) @@ -3598,11 +3644,11 @@ ha_innobase::estimate_number_of_rows(void) /* Calculate a minimum length for a clustered index record and from that an upper bound for the number of rows. Since we only calculate - new statistics in row0mysql.c when a tablehas grown - by a threshold factor, we must add a safety factor 2 in front - of the formula below. */ + new statistics in row0mysql.c when a table has grown by a threshold + factor, we must add a safety factor 2 in front of the formula below. */ - estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index); + estimate = 2 * local_data_file_length / + dict_index_calc_min_rec_len(index); prebuilt->trx->op_info = (char*)""; @@ -3629,27 +3675,36 @@ ha_innobase::scan_time() return((double) (prebuilt->table->stat_clustered_index_size)); } -/* - Calculate the time it takes to read a set of ranges through and index - This enables us to optimise reads for clustered indexes. -*/ +/********************************************************************** +Calculate the time it takes to read a set of ranges through an index +This enables us to optimise reads for clustered indexes. */ -double ha_innobase::read_time(uint index, uint ranges, ha_rows rows) +double +ha_innobase::read_time( +/*===================*/ + /* out: estimated time measured in disk seeks */ + uint index, /* in: key number */ + uint ranges, /* in: how many ranges */ + ha_rows rows) /* in: estimated number of rows in the ranges */ { - ha_rows total_rows; - double time_for_scan; - if (index != table->primary_key) - return handler::read_time(index, ranges, rows); // Not clustered - if (rows <= 2) - return (double) rows; - /* - Assume that the read is proportional to scan time for all rows + one - seek per range. - */ - time_for_scan= scan_time(); - if ((total_rows= estimate_number_of_rows()) < rows) - return time_for_scan; - return (ranges + (double) rows / (double) total_rows * time_for_scan); + ha_rows total_rows; + double time_for_scan; + + if (index != table->primary_key) + return handler::read_time(index, ranges, rows); // Not clustered + + if (rows <= 2) + return (double) rows; + + /* Assume that the read time is proportional to the scan time for all + rows + at most one seek per range. */ + + time_for_scan= scan_time(); + + if ((total_rows= estimate_number_of_rows()) < rows) + return time_for_scan; + + return (ranges + (double) rows / (double) total_rows * time_for_scan); } /************************************************************************* @@ -3992,10 +4047,10 @@ ha_innobase::reset(void) } /********************************************************************** -Inside LOCK TABLES MySQL will not call external_lock() between SQL -statements. It will call this function at the start of each SQL statement. -Note also a spacial case: if a temporary table is created inside LOCK -TABLES, MySQL has not called external_lock() at all on that table. */ +MySQL calls this function at the start of each SQL statement. Inside LOCK +TABLES the ::external_lock method does not work to mark SQL statement +borders. Note also a special case: if a temporary table is created inside +LOCK TABLES, MySQL has not called external_lock() at all on that table. */ int ha_innobase::start_stmt( @@ -4010,8 +4065,14 @@ ha_innobase::start_stmt( trx = prebuilt->trx; + /* Here we release the search latch and the InnoDB thread FIFO ticket + if they were reserved. They should have been released already at the + end of the previous statement, but because inside LOCK TABLES the + lock count method does not work to mark the end of a SELECT statement, + that may not be the case. We MUST release the search latch before an + INSERT, for example. */ + innobase_release_stat_resources(trx); - trx_mark_sql_stat_end(trx); if (trx->isolation_level <= TRX_ISO_READ_COMMITTED && trx->read_view) { @@ -4034,7 +4095,8 @@ ha_innobase::start_stmt( prebuilt->select_lock_type = LOCK_X; } - + + /* Set the MySQL flag to mark that there is an active transaction */ thd->transaction.all.innodb_active_trans = 1; return(0); @@ -4098,17 +4160,20 @@ ha_innobase::external_lock( } if (lock_type != F_UNLCK) { - if (trx->n_mysql_tables_in_use == 0) { - trx_mark_sql_stat_end(trx); - } + /* MySQL is setting a new table lock */ + /* Set the MySQL flag to mark that there is an active + transaction */ thd->transaction.all.innodb_active_trans = 1; + trx->n_mysql_tables_in_use++; prebuilt->mysql_has_locked = TRUE; - trx->isolation_level = innobase_map_isolation_level( + if (trx->n_mysql_tables_in_use == 1) { + trx->isolation_level = innobase_map_isolation_level( (enum_tx_isolation) thd->variables.tx_isolation); + } if (trx->isolation_level == TRX_ISO_SERIALIZABLE && prebuilt->select_lock_type == LOCK_NONE) { @@ -4124,37 +4189,44 @@ ha_innobase::external_lock( trx->mysql_n_tables_locked++; } - } else { - trx->n_mysql_tables_in_use--; - prebuilt->mysql_has_locked = FALSE; - auto_inc_counter_for_this_stat = 0; - if (trx->n_mysql_tables_in_use == 0) { + DBUG_RETURN(error); + } - trx->mysql_n_tables_locked = 0; + /* MySQL is releasing a table lock */ - prebuilt->used_in_HANDLER = FALSE; + trx->n_mysql_tables_in_use--; + prebuilt->mysql_has_locked = FALSE; + auto_inc_counter_for_this_stat = 0; - /* Here we release the search latch and InnoDB - thread FIFO ticket if they were reserved. */ + /* If the MySQL lock count drops to zero we know that the current SQL + statement has ended */ - innobase_release_stat_resources(trx); + if (trx->n_mysql_tables_in_use == 0) { + trx->mysql_n_tables_locked = 0; + prebuilt->used_in_HANDLER = FALSE; + + if (!(thd->options + & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { + if (thd->transaction.all.innodb_active_trans != 0) { + innobase_commit(thd, trx); + } + } else { if (trx->isolation_level <= TRX_ISO_READ_COMMITTED && trx->read_view) { - /* At low transaction isolation levels we let + /* At low transaction isolation levels we let each consistent read set its own snapshot */ - read_view_close_for_mysql(trx); + read_view_close_for_mysql(trx); } - - if (!(thd->options - & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { - - innobase_commit(thd, trx); - } } + + /* Here we release the search latch and the InnoDB thread FIFO + ticket if they were reserved. */ + + innobase_release_stat_resources(trx); } DBUG_RETURN(error); @@ -4473,4 +4545,3 @@ ha_innobase::get_auto_increment() } #endif /* HAVE_INNOBASE_DB */ - |