Commit 6358cdee authored by unknown's avatar unknown
Browse files

ha_innodb.h, ha_innodb.cc:

  Fix bug #10359 : the critical AUTO-INC bug in InnoDB; since reading of the auto-inc counter in an INSERT was not protected by the AUTO-INC table lock of InnoDB, two inserted rows could get the same value for the auto-inc counter, leading to a duplicate key error


sql/ha_innodb.cc:
  Fix bug #10359 : the critical AUTO-INC bug in InnoDB; since reading of the auto-inc counter in an INSERT was not protected by the AUTO-INC table lock of InnoDB, two inserted rows could get the same value for the auto-inc counter, leading to a duplicate key error
sql/ha_innodb.h:
  Fix bug #10359 : the critical AUTO-INC bug in InnoDB; since reading of the auto-inc counter in an INSERT was not protected by the AUTO-INC table lock of InnoDB, two inserted rows could get the same value for the auto-inc counter, leading to a duplicate key error
parent afaa3c89
Loading
Loading
Loading
Loading
+34 −21
Original line number Diff line number Diff line
@@ -3170,10 +3170,26 @@ ha_innobase::write_row(
			prebuilt->sql_stat_start = TRUE;
		}

		/*
                  We must use the handler code to update the auto-increment
                  value to be sure that increment it correctly.
                */
		/* We have to use the transactional lock mechanism on the
		auto-inc counter of the table to ensure that replication and
		roll-forward of the binlog exactly imitates also the given
		auto-inc values. The lock is released at each SQL statement's
		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;
		}

		/* We must use the handler code to update the auto-increment
                value to be sure that we increment it correctly. */

    		update_auto_increment();
                auto_inc_used = 1;

@@ -3198,24 +3214,15 @@ ha_innobase::write_row(
          	auto_inc = table->next_number_field->val_int();

          	if (auto_inc != 0) {
			/* This call will calculate the max of the current
			value and the value supplied by the user and
			update the counter accordingly */

			/* We have to use the transactional lock mechanism
			on the auto-inc counter of the table to ensure
			that replication and roll-forward of the binlog
			exactly imitates also the given auto-inc values.
			The lock is released at each SQL statement's
			end. */

            		error = row_lock_table_autoinc_for_mysql(prebuilt);
			/* This call will update the counter according to the
			value that was inserted in the table */

            		if (error != DB_SUCCESS) {
              			error = convert_error_code_to_mysql(error,
								user_thd);
              			goto func_exit;
            		}

            		dict_table_autoinc_update(prebuilt->table, auto_inc);
          	}
        }
@@ -5795,7 +5802,6 @@ ha_innobase::start_stmt(
	    	read_view_close_for_mysql(trx);
	}

	auto_inc_counter_for_this_stat = 0;
	prebuilt->sql_stat_start = TRUE;
	prebuilt->hint_need_to_fetch_extra_cols = 0;
	prebuilt->read_just_key = 0;
@@ -5985,7 +5991,7 @@ ha_innobase::external_lock(

	trx->n_mysql_tables_in_use--;
	prebuilt->mysql_has_locked = FALSE;
	auto_inc_counter_for_this_stat = 0;

	if (trx->n_lock_table_exp) {
		row_unlock_tables_for_mysql(trx);
	}
@@ -6505,7 +6511,7 @@ ha_innobase::store_lock(
/***********************************************************************
This function initializes the auto-inc counter if it has not been
initialized yet. This function does not change the value of the auto-inc
counter if it already has been initialized. In paramete ret returns
counter if it already has been initialized. In parameter ret returns
the value of the auto-inc counter. */

int
@@ -6624,7 +6630,14 @@ ha_innobase::get_auto_increment()
	error = innobase_read_and_init_auto_inc(&nr);

	if (error) {
		/* This should never happen in the current (5.0.6) code, since
		we call this function only after the counter has been
		initialized. */
	
		ut_print_timestamp(stderr);
		fprintf(stderr,
		"  InnoDB: Error: error %lu in ::get_auto_increment()\n",
						(ulong)error);
          	return(~(ulonglong) 0);
	}

+0 −1
Original line number Diff line number Diff line
@@ -70,7 +70,6 @@ class ha_innobase: public handler
					ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX,
					or undefined */
	uint		num_write_row;	/* number of write_row() calls */
	longlong	auto_inc_counter_for_this_stat;
	ulong max_supported_row_length(const byte *buf);

	uint store_key_val_for_row(uint keynr, char* buff, uint buff_len,