summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/innodb_bug40565.result9
-rw-r--r--mysql-test/t/innodb_bug40565.test10
-rw-r--r--storage/innobase/include/fsp0fsp.h58
-rw-r--r--storage/innobase/include/fsp0types.h89
-rw-r--r--storage/innobase/include/mtr0log.ic24
-rw-r--r--storage/innobase/include/trx0sys.h6
-rw-r--r--storage/innobase/trx/trx0sys.c12
7 files changed, 141 insertions, 67 deletions
diff --git a/mysql-test/r/innodb_bug40565.result b/mysql-test/r/innodb_bug40565.result
new file mode 100644
index 00000000000..21e923d9336
--- /dev/null
+++ b/mysql-test/r/innodb_bug40565.result
@@ -0,0 +1,9 @@
+create table bug40565(value decimal(4,2)) engine=innodb;
+insert into bug40565 values (1), (null);
+update bug40565 set value=NULL;
+affected rows: 1
+info: Rows matched: 2 Changed: 1 Warnings: 0
+update bug40565 set value=NULL;
+affected rows: 0
+info: Rows matched: 2 Changed: 0 Warnings: 0
+drop table bug40565;
diff --git a/mysql-test/t/innodb_bug40565.test b/mysql-test/t/innodb_bug40565.test
new file mode 100644
index 00000000000..d7aa0fd514a
--- /dev/null
+++ b/mysql-test/t/innodb_bug40565.test
@@ -0,0 +1,10 @@
+# Bug #40565 Update Query Results in "1 Row Affected" But Should Be "Zero Rows"
+-- source include/have_innodb.inc
+
+create table bug40565(value decimal(4,2)) engine=innodb;
+insert into bug40565 values (1), (null);
+--enable_info
+update bug40565 set value=NULL;
+update bug40565 set value=NULL;
+--disable_info
+drop table bug40565;
diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h
index 82e95a2e920..17bfbeec2c1 100644
--- a/storage/innobase/include/fsp0fsp.h
+++ b/storage/innobase/include/fsp0fsp.h
@@ -15,29 +15,7 @@ Created 12/18/1995 Heikki Tuuri
#include "fut0lst.h"
#include "ut0byte.h"
#include "page0types.h"
-
-/* If records are inserted in order, there are the following
-flags to tell this (their type is made byte for the compiler
-to warn if direction and hint parameters are switched in
-fseg_alloc_free_page): */
-#define FSP_UP ((byte)111) /* alphabetically upwards */
-#define FSP_DOWN ((byte)112) /* alphabetically downwards */
-#define FSP_NO_DIR ((byte)113) /* no order */
-
-/* File space extent size in pages */
-#define FSP_EXTENT_SIZE 64
-
-/* On a page of any file segment, data may be put starting from this offset: */
-#define FSEG_PAGE_DATA FIL_PAGE_DATA
-
-/* File segment header which points to the inode describing the file segment */
-typedef byte fseg_header_t;
-
-#define FSEG_HDR_SPACE 0 /* space id of the inode */
-#define FSEG_HDR_PAGE_NO 4 /* page number of the inode */
-#define FSEG_HDR_OFFSET 8 /* byte offset of the inode */
-
-#define FSEG_HEADER_SIZE 10
+#include "fsp0types.h"
/**************************************************************************
Initializes the file space system. */
@@ -350,40 +328,6 @@ fseg_print(
fseg_header_t* header, /* in: segment header */
mtr_t* mtr); /* in: mtr */
-/* Flags for fsp_reserve_free_extents */
-#define FSP_NORMAL 1000000
-#define FSP_UNDO 2000000
-#define FSP_CLEANING 3000000
-
-/* Number of pages described in a single descriptor page: currently each page
-description takes less than 1 byte; a descriptor page is repeated every
-this many file pages */
-#define XDES_DESCRIBED_PER_PAGE UNIV_PAGE_SIZE
-
-/* The space low address page map */
-/*--------------------------------------*/
- /* The following two pages are repeated
- every XDES_DESCRIBED_PER_PAGE pages in
- every tablespace. */
-#define FSP_XDES_OFFSET 0 /* extent descriptor */
-#define FSP_IBUF_BITMAP_OFFSET 1 /* insert buffer bitmap */
- /* The ibuf bitmap pages are the ones whose
- page number is the number above plus a
- multiple of XDES_DESCRIBED_PER_PAGE */
-
-#define FSP_FIRST_INODE_PAGE_NO 2 /* in every tablespace */
- /* The following pages exist
- in the system tablespace (space 0). */
-#define FSP_IBUF_HEADER_PAGE_NO 3 /* in tablespace 0 */
-#define FSP_IBUF_TREE_ROOT_PAGE_NO 4 /* in tablespace 0 */
- /* The ibuf tree root page number in
- tablespace 0; its fseg inode is on the page
- number FSP_FIRST_INODE_PAGE_NO */
-#define FSP_TRX_SYS_PAGE_NO 5 /* in tablespace 0 */
-#define FSP_FIRST_RSEG_PAGE_NO 6 /* in tablespace 0 */
-#define FSP_DICT_HDR_PAGE_NO 7 /* in tablespace 0 */
-/*--------------------------------------*/
-
#ifndef UNIV_NONINL
#include "fsp0fsp.ic"
#endif
diff --git a/storage/innobase/include/fsp0types.h b/storage/innobase/include/fsp0types.h
new file mode 100644
index 00000000000..6756d9d285c
--- /dev/null
+++ b/storage/innobase/include/fsp0types.h
@@ -0,0 +1,89 @@
+/*****************************************************************************
+
+Copyright (c) 1995, 2009, Innobase Oy. 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
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/******************************************************
+File space management types
+
+Created May 26, 2009 Vasil Dimov
+*******************************************************/
+
+#ifndef fsp0types_h
+#define fsp0types_h
+
+#include "univ.i"
+
+#include "fil0fil.h" /* for FIL_PAGE_DATA */
+
+/* If records are inserted in order, there are the following
+flags to tell this (their type is made byte for the compiler
+to warn if direction and hint parameters are switched in
+fseg_alloc_free_page): */
+#define FSP_UP ((byte)111) /* alphabetically upwards */
+#define FSP_DOWN ((byte)112) /* alphabetically downwards */
+#define FSP_NO_DIR ((byte)113) /* no order */
+
+/* File space extent size in pages */
+#define FSP_EXTENT_SIZE 64
+
+/* On a page of any file segment, data may be put starting from this offset: */
+#define FSEG_PAGE_DATA FIL_PAGE_DATA
+
+/* File segment header which points to the inode describing the file segment */
+typedef byte fseg_header_t;
+
+#define FSEG_HDR_SPACE 0 /* space id of the inode */
+#define FSEG_HDR_PAGE_NO 4 /* page number of the inode */
+#define FSEG_HDR_OFFSET 8 /* byte offset of the inode */
+
+#define FSEG_HEADER_SIZE 10
+
+/* Flags for fsp_reserve_free_extents */
+#define FSP_NORMAL 1000000
+#define FSP_UNDO 2000000
+#define FSP_CLEANING 3000000
+
+/* Number of pages described in a single descriptor page: currently each page
+description takes less than 1 byte; a descriptor page is repeated every
+this many file pages */
+#define XDES_DESCRIBED_PER_PAGE UNIV_PAGE_SIZE
+
+/* The space low address page map */
+/*--------------------------------------*/
+ /* The following two pages are repeated
+ every XDES_DESCRIBED_PER_PAGE pages in
+ every tablespace. */
+#define FSP_XDES_OFFSET 0 /* extent descriptor */
+#define FSP_IBUF_BITMAP_OFFSET 1 /* insert buffer bitmap */
+ /* The ibuf bitmap pages are the ones whose
+ page number is the number above plus a
+ multiple of XDES_DESCRIBED_PER_PAGE */
+
+#define FSP_FIRST_INODE_PAGE_NO 2 /* in every tablespace */
+ /* The following pages exist
+ in the system tablespace (space 0). */
+#define FSP_IBUF_HEADER_PAGE_NO 3 /* in tablespace 0 */
+#define FSP_IBUF_TREE_ROOT_PAGE_NO 4 /* in tablespace 0 */
+ /* The ibuf tree root page number in
+ tablespace 0; its fseg inode is on the page
+ number FSP_FIRST_INODE_PAGE_NO */
+#define FSP_TRX_SYS_PAGE_NO 5 /* in tablespace 0 */
+#define FSP_FIRST_RSEG_PAGE_NO 6 /* in tablespace 0 */
+#define FSP_DICT_HDR_PAGE_NO 7 /* in tablespace 0 */
+/*--------------------------------------*/
+
+#endif /* fsp0types_h */
diff --git a/storage/innobase/include/mtr0log.ic b/storage/innobase/include/mtr0log.ic
index 5b1d1ed34d9..1626f1e77e5 100644
--- a/storage/innobase/include/mtr0log.ic
+++ b/storage/innobase/include/mtr0log.ic
@@ -9,6 +9,8 @@ Created 12/7/1995 Heikki Tuuri
#include "mach0data.h"
#include "ut0lst.h"
#include "buf0buf.h"
+#include "fsp0types.h"
+#include "trx0sys.h"
/************************************************************
Opens a buffer to mlog. It must be closed with mlog_close. */
@@ -174,6 +176,28 @@ mlog_write_initial_log_record_fast(
space = buf_block_get_space(block);
offset = buf_block_get_page_no(block);
+ /* check whether the page is in the doublewrite buffer;
+ the doublewrite buffer is located in pages
+ FSP_EXTENT_SIZE, ..., 3 * FSP_EXTENT_SIZE - 1 in the
+ system tablespace */
+ if (space == TRX_SYS_SPACE
+ && offset >= FSP_EXTENT_SIZE && offset < 3 * FSP_EXTENT_SIZE) {
+ if (trx_doublewrite_buf_is_being_created) {
+ /* Do nothing: we only come to this branch in an
+ InnoDB database creation. We do not redo log
+ anything for the doublewrite buffer pages. */
+ return(log_ptr);
+ } else {
+ fprintf(stderr,
+ "Error: trying to redo log a record of type "
+ "%d on page %lu of space %lu in the "
+ "doublewrite buffer, continuing anyway.\n"
+ "Please post a bug report to "
+ "bugs.mysql.com.\n",
+ type, offset, space);
+ }
+ }
+
mach_write_to_1(log_ptr, type);
log_ptr++;
log_ptr += mach_write_compressed(log_ptr, space);
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
index a8da5cd51a3..bad3c9d570c 100644
--- a/storage/innobase/include/trx0sys.h
+++ b/storage/innobase/include/trx0sys.h
@@ -13,15 +13,12 @@ Created 3/26/1996 Heikki Tuuri
#include "trx0types.h"
#include "mtr0mtr.h"
-#include "mtr0log.h"
#include "ut0byte.h"
#include "mem0mem.h"
#include "sync0sync.h"
#include "ut0lst.h"
#include "buf0buf.h"
#include "fil0fil.h"
-#include "fut0lst.h"
-#include "fsp0fsp.h"
#include "read0types.h"
/* In a MySQL replication slave, in crash recovery we store the master log
@@ -45,6 +42,8 @@ extern trx_sys_t* trx_sys;
/* Doublewrite system */
extern trx_doublewrite_t* trx_doublewrite;
+/* Set to TRUE when the doublewrite buffer is being created */
+extern ibool trx_doublewrite_buf_is_being_created;
extern ibool trx_doublewrite_must_reset_space_ids;
extern ibool trx_sys_multiple_tablespace_format;
@@ -302,6 +301,7 @@ trx_sys_print_mysql_master_log_pos(void);
/* Space id and page no where the trx system file copy resides */
#define TRX_SYS_SPACE 0 /* the SYSTEM tablespace */
+#include "fsp0fsp.h"
#define TRX_SYS_PAGE_NO FSP_TRX_SYS_PAGE_NO
/* The offset of the transaction system header on the page */
diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c
index 40348dd4199..7975950e912 100644
--- a/storage/innobase/trx/trx0sys.c
+++ b/storage/innobase/trx/trx0sys.c
@@ -25,6 +25,7 @@ Created 3/26/1996 Heikki Tuuri
/* The transaction system */
trx_sys_t* trx_sys = NULL;
trx_doublewrite_t* trx_doublewrite = NULL;
+ibool trx_doublewrite_buf_is_being_created = FALSE;
/* The following is set to TRUE when we are upgrading from the old format data
files to the new >= 4.1.x format multiple tablespaces format data files */
@@ -180,6 +181,7 @@ trx_sys_create_doublewrite_buf(void)
start_again:
mtr_start(&mtr);
+ trx_doublewrite_buf_is_being_created = TRUE;
page = buf_page_get(TRX_SYS_SPACE, TRX_SYS_PAGE_NO, RW_X_LATCH, &mtr);
#ifdef UNIV_SYNC_DEBUG
@@ -196,6 +198,7 @@ start_again:
trx_doublewrite_init(doublewrite);
mtr_commit(&mtr);
+ trx_doublewrite_buf_is_being_created = FALSE;
} else {
fprintf(stderr,
"InnoDB: Doublewrite buffer not found:"
@@ -274,14 +277,8 @@ start_again:
buf_page_dbg_add_level(new_page, SYNC_NO_ORDER_CHECK);
#endif /* UNIV_SYNC_DEBUG */
- /* Make a dummy change to the page to ensure it will
- be written to disk in a flush */
-
- mlog_write_ulint(new_page + FIL_PAGE_DATA,
- TRX_SYS_DOUBLEWRITE_MAGIC_N,
- MLOG_4BYTES, &mtr);
-
if (i == FSP_EXTENT_SIZE / 2) {
+ ut_a(page_no == FSP_EXTENT_SIZE);
mlog_write_ulint(doublewrite
+ TRX_SYS_DOUBLEWRITE_BLOCK1,
page_no, MLOG_4BYTES, &mtr);
@@ -291,6 +288,7 @@ start_again:
page_no, MLOG_4BYTES, &mtr);
} else if (i == FSP_EXTENT_SIZE / 2
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
+ ut_a(page_no == 2 * FSP_EXTENT_SIZE);
mlog_write_ulint(doublewrite
+ TRX_SYS_DOUBLEWRITE_BLOCK2,
page_no, MLOG_4BYTES, &mtr);