1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

BUG#11765650 - 58637: MARK UPDATES THAT DEPEND ON ORDER OF TWO KEYS UNSAFE

Description: When the table has more than one unique or primary key, 
 INSERT... ON DUP KEY UPDATE statement is sensitive to the order in which
 the storage engines checks the keys. Depending on this order, the storage
 engine may determine different rows to mysql, and hence mysql can update
 different rows on master and slave.
      
 Solution: We mark INSERT...ON DUP KEY UPDATE on a table with more than on unique
 key as unsafe therefore the event will be logged in row format if it is available
 (ROW/MIXED). If only STATEMENT format is available, a warning will be thrown. 

mysql-test/suite/binlog/r/binlog_unsafe.result:
  Updated result file
mysql-test/suite/binlog/t/binlog_unsafe.test:
  Added test to check  for warning being thrown when the unsafe statement is executed
mysql-test/suite/rpl/r/rpl_known_bugs_detection.result:
  Updated result file
sql/share/errmsg-utf8.txt:
  Added new warning message
sql/sql_base.cc:
  check for tables in the query with more than one UNIQUE KEY and INSERT ON DUPLICATE KEY UPDATE, and mark such statements unsafe.
This commit is contained in:
Rohit Kalhans
2012-03-30 18:35:53 +05:30
parent a4a5580ec4
commit 1a02c266d1
7 changed files with 55 additions and 1 deletions

View File

@ -5691,6 +5691,30 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count,
has_write_table_with_auto_increment_and_select(tables))
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT);
/*
INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys
can be unsafe.
*/
uint unique_keys= 0;
for (TABLE_LIST *query_table= tables; query_table && unique_keys <= 1;
query_table= query_table->next_global)
if(query_table->table)
{
uint keys= query_table->table->s->keys, i= 0;
unique_keys= 0;
for (KEY* keyinfo= query_table->table->s->key_info;
i < keys && unique_keys <= 1; i++, keyinfo++)
{
if (keyinfo->flags & HA_NOSAME)
unique_keys++;
}
if (!query_table->placeholder() &&
query_table->lock_type >= TL_WRITE_ALLOW_WRITE &&
unique_keys > 1 && thd->lex->sql_command == SQLCOM_INSERT &&
thd->lex->duplicates == DUP_UPDATE)
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS);
}
/* We have to emulate LOCK TABLES if we are statement needs prelocking. */
if (thd->lex->requires_prelocking())
{