Commit bb0507fa authored by unknown's avatar unknown
Browse files

Fixed a bug: deadlock without any locking, simple select and update (Bug #7975).


innobase/row/row0ins.c:
  If the SQL-query will update or replace duplicate key row we take X-lcok
  for duplicate row.
sql/ha_innodb.cc:
  INSERT ON DUPLICATE KEY UPDATE will also update duplicate key and we can
  take X-lock in this case for duplicate key records.
BitKeeper/etc/ignore:
  Added innobase/row/row0index.c to the ignore list
parent f32743b7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1055,3 +1055,4 @@ vio/viotest-ssl
include/mysqld_ername.h
include/mysqld_error.h
include/sql_state.h
innobase/row/row0index.c
+23 −18
Original line number Diff line number Diff line
@@ -51,14 +51,19 @@ innobase_invalidate_query_cache(
				chars count */

/**********************************************************************
This function returns true if SQL-query in the current thread
This function returns true if 

1) SQL-query in the current thread
is either REPLACE or LOAD DATA INFILE REPLACE. 

2) SQL-query in the current thread
is INSERT ON DUPLICATE KEY UPDATE.

NOTE that /mysql/innobase/row/row0ins.c must contain the 
prototype for this function ! */

ibool
innobase_query_is_replace(void);
/*===========================*/
innobase_query_is_update(void);

/*************************************************************************
Creates an insert node struct. */
@@ -1597,12 +1602,12 @@ row_ins_scan_sec_index_for_duplicate(
		offsets = rec_get_offsets(rec, index, offsets,
					ULINT_UNDEFINED, &heap);

		if (innobase_query_is_replace()) {
		if (innobase_query_is_update()) {

			/* The manual defines the REPLACE semantics that it 
			is either an INSERT or DELETE(s) for duplicate key
			+ INSERT. Therefore, we should take X-lock for 
			duplicates */
			/* If the SQL-query will update or replace
			duplicate key we will take X-lock for 
			duplicates ( REPLACE, LOAD DATAFILE REPLACE, 
			INSERT ON DUPLICATE KEY UPDATE). */
			
			err = row_ins_set_exclusive_rec_lock(LOCK_ORDINARY,
						rec, index, offsets, thr);
@@ -1720,12 +1725,12 @@ row_ins_duplicate_error_in_clust(
			sure that in roll-forward we get the same duplicate
			errors as in original execution */

			if (innobase_query_is_replace()) {
			if (innobase_query_is_update()) {

				/* The manual defines the REPLACE semantics 
				that it is either an INSERT or DELETE(s) 
				for duplicate key + INSERT. Therefore, we 
				should take X-lock for duplicates */
				/* If the SQL-query will update or replace
				duplicate key we will take X-lock for 
				duplicates ( REPLACE, LOAD DATAFILE REPLACE, 
				INSERT ON DUPLICATE KEY UPDATE). */
				
				err = row_ins_set_exclusive_rec_lock(
					LOCK_REC_NOT_GAP,rec,cursor->index,
@@ -1759,12 +1764,12 @@ row_ins_duplicate_error_in_clust(
			offsets = rec_get_offsets(rec, cursor->index, offsets,
						ULINT_UNDEFINED, &heap);

			/* The manual defines the REPLACE semantics that it 
			is either an INSERT or DELETE(s) for duplicate key
			+ INSERT. Therefore, we should take X-lock for
			duplicates. */
			if (innobase_query_is_update()) {

			if (innobase_query_is_replace()) {
				/* If the SQL-query will update or replace
				duplicate key we will take X-lock for 
				duplicates ( REPLACE, LOAD DATAFILE REPLACE, 
				INSERT ON DUPLICATE KEY UPDATE). */

				err = row_ins_set_exclusive_rec_lock(
						LOCK_REC_NOT_GAP, rec,
+15 −4
Original line number Diff line number Diff line
@@ -6142,13 +6142,19 @@ innobase_get_at_most_n_mbchars(

extern "C" {
/**********************************************************************
This function returns true if SQL-query in the current thread
This function returns true if 

1) SQL-query in the current thread
is either REPLACE or LOAD DATA INFILE REPLACE. 

2) SQL-query in the current thread
is INSERT ON DUPLICATE KEY UPDATE.

NOTE that /mysql/innobase/row/row0ins.c must contain the 
prototype for this function ! */

ibool
innobase_query_is_replace(void)
innobase_query_is_update(void)
/*===========================*/
{
	THD*	thd;
@@ -6160,9 +6166,14 @@ innobase_query_is_replace(void)
	     ( thd->lex->sql_command == SQLCOM_LOAD &&
	       thd->lex->duplicates == DUP_REPLACE )) {
		return true;
	} else {
		return false;
	}

	if ( thd->lex->sql_command == SQLCOM_INSERT &&
	     thd->lex->duplicates  == DUP_UPDATE ) {
		return true;
	}

	return false;
}
}