From 723c0a1ba5bcdfcf969e52295cf87f3fdaa8f40f Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Tue, 11 Feb 2014 16:44:37 +0530 Subject: [PATCH] Bug#18185930 UPD_NODE_INSERT_BLOB CAUSES BTR_EXTERN_OWNER_FLAG ASSERTION Problem: In the clustered index, when an update operation is done the overall scenario (after rb#4479) is as follows: 1. Delete mark the old record that is to be updated. 2. The old record disowns the blobs. 3. Insert the new record into clustered index. 4. For non-updated blobs, new record must own it. Verified by assert. 5. For non-updated blobs, in new record marked as inherited. Scenario involving DB_LOCK_WAIT: If step 3 times out, then we will skip 1 and 2 and will continue from step 3. This skipping is achieved by the UPD_NODE_INSERT_BLOB state. In this case, step 4 is not correct. Because of step 1, the new record need not own the blobs. Hence the assert failure. Solution: The assert in step 4 is removed. Instead code is added to ensure that the record owns the blob. Note: This is a regression caused by rb#4479. rb#4571 approved by Marko --- .../suite/innodb/r/blob-update-debug.result | 15 +++++++++++++++ .../suite/innodb/t/blob-update-debug.test | 17 +++++++++++++++++ storage/innobase/row/row0ins.c | 6 +++++- storage/innobase/row/row0upd.c | 4 +--- 4 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 mysql-test/suite/innodb/r/blob-update-debug.result create mode 100644 mysql-test/suite/innodb/t/blob-update-debug.test diff --git a/mysql-test/suite/innodb/r/blob-update-debug.result b/mysql-test/suite/innodb/r/blob-update-debug.result new file mode 100644 index 00000000000..3eb9d1dcaf5 --- /dev/null +++ b/mysql-test/suite/innodb/r/blob-update-debug.result @@ -0,0 +1,15 @@ +# +# Bug#18185930 UPD_NODE_INSERT_BLOB CAUSES BTR_EXTERN_OWNER_FLAG +# ASSERTION +# +create table t1 (f1 int primary key, f2 blob) engine = innodb; +insert into t1 values (1, repeat('*', 50000)); +select f1, substring(f2, 1, 40) from t1; +f1 substring(f2, 1, 40) +1 **************************************** +set debug = 'd,row_ins_index_entry_timeout'; +update t1 set f1 = 3; +select f1, substring(f2, 1, 40) from t1; +f1 substring(f2, 1, 40) +3 **************************************** +drop table t1; diff --git a/mysql-test/suite/innodb/t/blob-update-debug.test b/mysql-test/suite/innodb/t/blob-update-debug.test new file mode 100644 index 00000000000..e12c351e55f --- /dev/null +++ b/mysql-test/suite/innodb/t/blob-update-debug.test @@ -0,0 +1,17 @@ +# This file contains tests involving update operations on blob data type. + +--source include/have_innodb.inc +--source include/have_debug.inc + +--echo # +--echo # Bug#18185930 UPD_NODE_INSERT_BLOB CAUSES BTR_EXTERN_OWNER_FLAG +--echo # ASSERTION +--echo # + +create table t1 (f1 int primary key, f2 blob) engine = innodb; +insert into t1 values (1, repeat('*', 50000)); +select f1, substring(f2, 1, 40) from t1; +set debug = 'd,row_ins_index_entry_timeout'; +update t1 set f1 = 3; +select f1, substring(f2, 1, 40) from t1; +drop table t1; diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 7650bc07848..9d5212db6e8 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -2250,6 +2250,10 @@ row_ins_index_entry( { ulint err; + DBUG_EXECUTE_IF("row_ins_index_entry_timeout", { + DBUG_SET("-d,row_ins_index_entry_timeout"); + return(DB_LOCK_WAIT);}); + if (foreign && UT_LIST_GET_FIRST(index->table->foreign_list)) { err = row_ins_check_foreign_constraints(index->table, index, entry, thr); diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index dccfa5ceb5c..825902c4ff2 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -1769,9 +1769,7 @@ row_upd_clust_rec_by_insert_inherit_func( data += len - BTR_EXTERN_FIELD_REF_SIZE; /* The pointer must not be zero. */ ut_a(memcmp(data, field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE)); - /* The BLOB must be owned. */ - ut_a(!(data[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG)); - + data[BTR_EXTERN_LEN] &= ~BTR_EXTERN_OWNER_FLAG; data[BTR_EXTERN_LEN] |= BTR_EXTERN_INHERITED_FLAG; /* The BTR_EXTERN_INHERITED_FLAG only matters in rollback. Purge will always free the extern fields of