From c3b04553c475f5780fb3371c6a7492fc203d2dbd Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Tue, 28 Feb 2012 12:42:02 +0100 Subject: The current year is 2012, and nobody noticed ... Update the year in the copyright notice, file "README". --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 795d325e2d5..acc98e400bd 100644 --- a/README +++ b/README @@ -5,7 +5,7 @@ For the avoidance of doubt, this particular copy of the software is released under the version 2 of the GNU General Public License. MySQL is brought to you by Oracle. -Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. License information can be found in the COPYING file. -- cgit v1.2.1 From 2efa0ec676d203083aa63123651a6e09abfd8129 Mon Sep 17 00:00:00 2001 From: Karen Langford Date: Tue, 28 Feb 2012 17:20:30 +0100 Subject: AIX builds fail for comments using // --- client/mysqldump.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index a69c9306b4b..8601b533849 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2331,10 +2331,10 @@ static uint dump_routines_for_db(char *db) { if (opt_xml) { - if (i) // Procedures. + if (i) /* Procedures. */ print_xml_row(sql_file, "routine", routine_res, &row, "Create Procedure"); - else // Functions. + else /* Functions. */ print_xml_row(sql_file, "routine", routine_res, &row, "Create Function"); continue; -- cgit v1.2.1 From 5b49c7ce916be1bbf306d2fd9175ed2b5ddeeed9 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Fri, 2 Mar 2012 13:12:07 +0100 Subject: Further upgrade the yaSSL library to version 2.2.0 to pick up some new security fixes that are in it. Patch provided by Georgi Kodinov. --- extra/yassl/README | 3 +-- extra/yassl/include/openssl/ssl.h | 4 ++-- extra/yassl/src/yassl_imp.cpp | 20 +++++++++++++++++++- extra/yassl/src/yassl_int.cpp | 5 +++-- extra/yassl/taocrypt/include/file.hpp | 21 ++++++++++++++------- extra/yassl/taocrypt/src/asn.cpp | 26 ++++++++++++++++++++++++-- extra/yassl/taocrypt/src/integer.cpp | 5 ++++- 7 files changed, 67 insertions(+), 17 deletions(-) diff --git a/extra/yassl/README b/extra/yassl/README index 0ca656bb932..7720a9453dd 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -21,8 +21,7 @@ See normal build instructions below under 1.0.6. See libcurl build instructions below under 1.3.0 and note in 1.5.8. -*****************yaSSL Release notes, version 1.9.9 (1/26/2010) -yaSSL Release notes, version 2.0.0 (7/6/2010) +*****************yaSSL Release notes, version 2.0.0 (7/6/2010) This release of yaSSL contains bug fixes, new testing certs, and a security patch for a potential heap overflow on forged application diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index 0ae54f070bd..0d99888da88 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2005-2007 MySQL AB, 2008 Sun Microsystems, Inc. + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -35,7 +35,7 @@ #include "rsa.h" -#define YASSL_VERSION "2.1.4" +#define YASSL_VERSION "2.2.0" #if defined(__cplusplus) diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index 6d2549749f2..66a173bece8 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2005, 2012, 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 @@ -1087,19 +1087,37 @@ void Certificate::Process(input_buffer& input, SSL& ssl) uint32 list_sz; byte tmp[3]; + if (input.get_remaining() < sizeof(tmp)) { + ssl.SetError(YasslError(bad_input)); + return; + } tmp[0] = input[AUTO]; tmp[1] = input[AUTO]; tmp[2] = input[AUTO]; c24to32(tmp, list_sz); + + if (list_sz > (uint)MAX_RECORD_SIZE) { // sanity check + ssl.SetError(YasslError(bad_input)); + return; + } while (list_sz) { // cert size uint32 cert_sz; + + if (input.get_remaining() < sizeof(tmp)) { + ssl.SetError(YasslError(bad_input)); + return; + } tmp[0] = input[AUTO]; tmp[1] = input[AUTO]; tmp[2] = input[AUTO]; c24to32(tmp, cert_sz); + if (cert_sz > (uint)MAX_RECORD_SIZE || input.get_remaining() < cert_sz){ + ssl.SetError(YasslError(bad_input)); + return; + } x509* myCert; cm.AddPeerCert(myCert = NEW_YS x509(cert_sz)); input.read(myCert->use_buffer(), myCert->get_length()); diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp index 15a85e36909..73f8f2330c5 100644 --- a/extra/yassl/src/yassl_int.cpp +++ b/extra/yassl/src/yassl_int.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2005, 2012, 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 @@ -308,8 +308,9 @@ SSL::SSL(SSL_CTX* ctx) SetError(YasslError(err)); return; } - else if (serverSide) { + else if (serverSide && ctx->GetCiphers().setSuites_ == 0) { // remove RSA or DSA suites depending on cert key type + // but don't override user sets ProtocolVersion pv = secure_.get_connection().version_; bool removeDH = secure_.use_parms().removeDH_; diff --git a/extra/yassl/taocrypt/include/file.hpp b/extra/yassl/taocrypt/include/file.hpp index 0f85b46fdb2..820fd8ff431 100644 --- a/extra/yassl/taocrypt/include/file.hpp +++ b/extra/yassl/taocrypt/include/file.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2007 MySQL AB + Copyright (C) 2000, 2012, 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 @@ -39,25 +39,32 @@ public: explicit Source(word32 sz = 0) : buffer_(sz), current_(0) {} Source(const byte* b, word32 sz) : buffer_(b, sz), current_(0) {} + word32 remaining() { if (GetError().What()) return 0; + else return buffer_.size() - current_; } word32 size() const { return buffer_.size(); } void grow(word32 sz) { buffer_.CleanGrow(sz); } + + bool IsLeft(word32 sz) { if (remaining() >= sz) return true; + else { SetError(CONTENT_E); return false; } } const byte* get_buffer() const { return buffer_.get_buffer(); } const byte* get_current() const { return &buffer_[current_]; } word32 get_index() const { return current_; } - void set_index(word32 i) { current_ = i; } + void set_index(word32 i) { if (i < size()) current_ = i; } byte operator[] (word32 i) { current_ = i; return next(); } - byte next() { return buffer_[current_++]; } - byte prev() { return buffer_[--current_]; } + byte next() { if (IsLeft(1)) return buffer_[current_++]; else return 0; } + byte prev() { if (current_) return buffer_[--current_]; else return 0; } void add(const byte* data, word32 len) { - memcpy(buffer_.get_buffer() + current_, data, len); - current_ += len; + if (IsLeft(len)) { + memcpy(buffer_.get_buffer() + current_, data, len); + current_ += len; + } } - void advance(word32 i) { current_ += i; } + void advance(word32 i) { if (IsLeft(i)) current_ += i; } void reset(ByteBlock&); Error GetError() { return error_; } diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp index 72cbd092f9d..a502666d15b 100644 --- a/extra/yassl/taocrypt/src/asn.cpp +++ b/extra/yassl/taocrypt/src/asn.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2005-2007 MySQL AB, 2009, 2010 Sun Microsystems, Inc. + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -144,6 +144,8 @@ word32 GetLength(Source& source) if (b >= LONG_LENGTH) { word32 bytes = b & 0x7F; + if (source.IsLeft(bytes) == false) return 0; + while (bytes--) { b = source.next(); length = (length << 8) | b; @@ -578,8 +580,10 @@ void CertDecoder::StoreKey() read = source_.get_index() - read; length += read; + if (source_.GetError().What()) return; while (read--) source_.prev(); + if (source_.IsLeft(length) == false) return; key_.SetSize(length); key_.SetKey(source_.get_current()); source_.advance(length); @@ -611,6 +615,8 @@ void CertDecoder::AddDSA() word32 length = GetLength(source_); length += source_.get_index() - idx; + if (source_.IsLeft(length) == false) return; + key_.AddToEnd(source_.get_buffer() + idx, length); } @@ -620,6 +626,8 @@ word32 CertDecoder::GetAlgoId() { if (source_.GetError().What()) return 0; word32 length = GetSequence(); + + if (source_.GetError().What()) return 0; byte b = source_.next(); if (b != OBJECT_IDENTIFIER) { @@ -628,8 +636,9 @@ word32 CertDecoder::GetAlgoId() } length = GetLength(source_); + if (source_.IsLeft(length) == false) return 0; + word32 oid = 0; - while(length--) oid += source_.next(); // just sum it up for now @@ -662,6 +671,10 @@ word32 CertDecoder::GetSignature() } sigLength_ = GetLength(source_); + if (sigLength_ == 0 || source_.IsLeft(sigLength_) == false) { + source_.SetError(CONTENT_E); + return 0; + } b = source_.next(); if (b != 0) { @@ -728,6 +741,7 @@ void CertDecoder::GetName(NameType nt) if (length >= ASN_NAME_MAX) return; + if (source_.IsLeft(length) == false) return; length += source_.get_index(); char* ptr; @@ -753,7 +767,10 @@ void CertDecoder::GetName(NameType nt) } word32 oidSz = GetLength(source_); + if (source_.IsLeft(oidSz) == false) return; + byte joint[2]; + if (source_.IsLeft(sizeof(joint)) == false) return; memcpy(joint, source_.get_current(), sizeof(joint)); // v1 name types @@ -763,6 +780,8 @@ void CertDecoder::GetName(NameType nt) b = source_.next(); // strType word32 strLen = GetLength(source_); + if (source_.IsLeft(strLen) == false) return; + switch (id) { case COMMON_NAME: if (!(ptr = AddTag(ptr, buf_end, "/CN=", 4, strLen))) @@ -804,6 +823,7 @@ void CertDecoder::GetName(NameType nt) source_.advance(oidSz + 1); word32 length = GetLength(source_); + if (source_.IsLeft(length) == false) return; if (email) { if (!(ptr = AddTag(ptr, buf_end, "/emailAddress=", 14, length))) { @@ -837,6 +857,8 @@ void CertDecoder::GetDate(DateType dt) } word32 length = GetLength(source_); + if (source_.IsLeft(length) == false) return; + byte date[MAX_DATE_SZ]; if (length > MAX_DATE_SZ || length < MIN_DATE_SZ) { source_.SetError(DATE_SZ_E); diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 2d55f48e91f..bfced6d0c74 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2005, 2012, 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 @@ -2587,11 +2587,14 @@ void Integer::Decode(Source& source) } word32 length = GetLength(source); + if (length == 0 || source.GetError().What()) return; if ( (b = source.next()) == 0x00) length--; else source.prev(); + + if (source.IsLeft(length) == false) return; unsigned int words = (length + WORD_SIZE - 1) / WORD_SIZE; words = RoundupSize(words); -- cgit v1.2.1 From 6e6ba8654b0e6e078f5f3d41d504ad446ef759ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 8 Mar 2012 17:10:10 +0200 Subject: Fix a compiler warning about possibly uninitiaizlied variable. --- storage/innobase/btr/btr0pcur.c | 3 +-- storage/innodb_plugin/btr/btr0pcur.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c index 439ab3093b2..50aef035f2e 100644 --- a/storage/innobase/btr/btr0pcur.c +++ b/storage/innobase/btr/btr0pcur.c @@ -301,10 +301,9 @@ btr_pcur_restore_position( case BTR_PCUR_BEFORE: mode = PAGE_CUR_L; break; -#ifdef UNIV_DEBUG default: ut_error; -#endif /* UNIV_DEBUG */ + mode = 0; /* silence a warning */ } btr_pcur_open_with_no_init(index, tuple, mode, latch_mode, diff --git a/storage/innodb_plugin/btr/btr0pcur.c b/storage/innodb_plugin/btr/btr0pcur.c index 6cbfd8a64b7..33700501bc5 100644 --- a/storage/innodb_plugin/btr/btr0pcur.c +++ b/storage/innodb_plugin/btr/btr0pcur.c @@ -325,10 +325,9 @@ btr_pcur_restore_position_func( case BTR_PCUR_BEFORE: mode = PAGE_CUR_L; break; -#ifdef UNIV_DEBUG default: ut_error; -#endif /* UNIV_DEBUG */ + mode = 0; } btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode, -- cgit v1.2.1 From 29aaa6588d1bc6d943c32eaa03e5ccd4c0a6a036 Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Fri, 9 Mar 2012 11:07:16 +0530 Subject: Bug #11766634 59783: InnoDB data grows unexpectedly when inserting, truncating, inserting the same set of rows. When a table is re-created with the same set of rows, the data file size must not grow. rb:968 Approved by Marko. --- .../suite/innodb/r/innodb_bug11766634.result | 6 +++ mysql-test/suite/innodb/t/innodb_bug11766634.test | 51 ++++++++++++++++++++++ .../innodb_plugin/r/innodb_bug11766634.result | 6 +++ .../suite/innodb_plugin/t/innodb_bug11766634.test | 51 ++++++++++++++++++++++ storage/innobase/fsp/fsp0fsp.c | 32 ++++---------- storage/innodb_plugin/fsp/fsp0fsp.c | 37 ++++------------ 6 files changed, 131 insertions(+), 52 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb_bug11766634.result create mode 100644 mysql-test/suite/innodb/t/innodb_bug11766634.test create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_bug11766634.result create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test diff --git a/mysql-test/suite/innodb/r/innodb_bug11766634.result b/mysql-test/suite/innodb/r/innodb_bug11766634.result new file mode 100644 index 00000000000..90ce5315598 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug11766634.result @@ -0,0 +1,6 @@ +create table t1 (f1 char(255)) engine innodb; +ibdata1 size: 27262976 bytes +drop table t1; +create table t1 (f1 char(255)) engine innodb; +ibdata1 size: 27262976 bytes +drop table t1; diff --git a/mysql-test/suite/innodb/t/innodb_bug11766634.test b/mysql-test/suite/innodb/t/innodb_bug11766634.test new file mode 100644 index 00000000000..a830955c78a --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug11766634.test @@ -0,0 +1,51 @@ +# Bug 11766634 59783: InnoDB data grows unexpectedly when inserting, +# truncating, inserting the same set of rows. +# +# Scenario: +# create table t1. Insert $recs records. check size of ibdata1. +# drop table t1. create table t1. Insert the same set of $recs +# records. The size of ibdata1 must not increase. +# + +-- source include/not_embedded.inc +-- source include/have_innodb.inc + +create table t1 (f1 char(255)) engine innodb; +let $MYSQLD_DATADIR=`select @@datadir`; +let IBDATA1=$MYSQLD_DATADIR/ibdata1; + +let $recs = 36262; + +--disable_query_log +let $c = $recs; +while ($c) +{ + insert into t1 values ('Hello World'); + dec $c; +} +--enable_query_log + +perl; +my $filesize = -s $ENV{'IBDATA1'}; +print "ibdata1 size: $filesize bytes\n"; +EOF + +drop table t1; +create table t1 (f1 char(255)) engine innodb; + +--disable_query_log +let $c = $recs; +while ($c) +{ + insert into t1 values ('Hello World'); + dec $c; +} +--enable_query_log + +perl; +my $filesize = -s $ENV{'IBDATA1'}; +print "ibdata1 size: $filesize bytes\n"; +EOF + +drop table t1; + diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug11766634.result b/mysql-test/suite/innodb_plugin/r/innodb_bug11766634.result new file mode 100644 index 00000000000..90ce5315598 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_bug11766634.result @@ -0,0 +1,6 @@ +create table t1 (f1 char(255)) engine innodb; +ibdata1 size: 27262976 bytes +drop table t1; +create table t1 (f1 char(255)) engine innodb; +ibdata1 size: 27262976 bytes +drop table t1; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test b/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test new file mode 100644 index 00000000000..1780317675d --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test @@ -0,0 +1,51 @@ +# Bug 11766634 59783: InnoDB data grows unexpectedly when inserting, +# truncating, inserting the same set of rows. +# +# Scenario: +# create table t1. Insert $recs records. check size of ibdata1. +# drop table t1. create table t1. Insert the same set of $recs +# records. The size of ibdata1 must not increase. +# + +-- source include/not_embedded.inc +-- source include/have_innodb_plugin.inc + +create table t1 (f1 char(255)) engine innodb; +let $MYSQLD_DATADIR=`select @@datadir`; +let IBDATA1=$MYSQLD_DATADIR/ibdata1; + +let $recs = 36262; + +--disable_query_log +let $c = $recs; +while ($c) +{ + insert into t1 values ('Hello World'); + dec $c; +} +--enable_query_log + +perl; +my $filesize = -s $ENV{'IBDATA1'}; +print "ibdata1 size: $filesize bytes\n"; +EOF + +drop table t1; +create table t1 (f1 char(255)) engine innodb; + +--disable_query_log +let $c = $recs; +while ($c) +{ + insert into t1 values ('Hello World'); + dec $c; +} +--enable_query_log + +perl; +my $filesize = -s $ENV{'IBDATA1'}; +print "ibdata1 size: $filesize bytes\n"; +EOF + +drop table t1; + diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c index 90e6ad34a9a..b095d0a0275 100644 --- a/storage/innobase/fsp/fsp0fsp.c +++ b/storage/innobase/fsp/fsp0fsp.c @@ -245,13 +245,13 @@ fseg_n_reserved_pages_low( /************************************************************************ Marks a page used. The page must reside within the extents of the given segment. */ -static +static __attribute__((nonnull)) void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/* in: segment inode */ - ulint space, /* in: space id */ ulint page, /* in: page offset */ + xdes_t* descr, /* in: extent descriptor */ mtr_t* mtr); /* in: mtr */ /************************************************************************** Returns the first extent descriptor for a segment. We think of the extent @@ -635,10 +635,8 @@ xdes_calc_descriptor_index( /************************************************************************ Gets pointer to a the extent descriptor of a page. The page where the extent -descriptor resides is x-locked. If the page offset is equal to the free limit -of the space, adds new extents from above the free limit to the space free -list, if not free limit == space size. This adding is necessary to make the -descriptor defined, as they are uninitialized above the free limit. */ +descriptor resides is x-locked. This function no longer extends the data +file. */ UNIV_INLINE xdes_t* xdes_get_descriptor_with_space_hdr( @@ -666,19 +664,10 @@ xdes_get_descriptor_with_space_hdr( limit = mtr_read_ulint(sp_header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr); size = mtr_read_ulint(sp_header + FSP_SIZE, MLOG_4BYTES, mtr); - /* If offset is >= size or > limit, return NULL */ - - if ((offset >= size) || (offset > limit)) { - + if ((offset >= size) || (offset >= limit)) { return(NULL); } - /* If offset is == limit, fill free list of the space. */ - - if (offset == limit) { - fsp_fill_free_list(FALSE, space, sp_header, mtr); - } - descr_page_no = xdes_calc_descriptor_page(offset); if (descr_page_no == 0) { @@ -2552,7 +2541,7 @@ fseg_alloc_free_page_low( ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT, ret_page % FSP_EXTENT_SIZE, mtr) == TRUE); - fseg_mark_page_used(seg_inode, space, ret_page, mtr); + fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr); } return(ret_page); @@ -2946,22 +2935,17 @@ fsp_get_available_space_in_free_extents( /************************************************************************ Marks a page used. The page must reside within the extents of the given segment. */ -static +static __attribute__((nonnull)) void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/* in: segment inode */ - ulint space, /* in: space id */ ulint page, /* in: page offset */ + xdes_t* descr, /* in: extent descriptor */ mtr_t* mtr) /* in: mtr */ { - xdes_t* descr; ulint not_full_n_used; - ut_ad(seg_inode && mtr); - - descr = xdes_get_descriptor(space, page, mtr); - ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr) == mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr)); diff --git a/storage/innodb_plugin/fsp/fsp0fsp.c b/storage/innodb_plugin/fsp/fsp0fsp.c index c84cae302a6..e54629a7b67 100644 --- a/storage/innodb_plugin/fsp/fsp0fsp.c +++ b/storage/innodb_plugin/fsp/fsp0fsp.c @@ -273,15 +273,13 @@ fseg_n_reserved_pages_low( /********************************************************************//** Marks a page used. The page must reside within the extents of the given segment. */ -static +static __attribute__((nonnull)) void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/*!< in: segment inode */ - ulint space, /*!< in: space id */ - ulint zip_size,/*!< in: compressed page size in bytes - or 0 for uncompressed pages */ ulint page, /*!< in: page offset */ + xdes_t* descr, /* extent descriptor */ mtr_t* mtr); /*!< in: mtr */ /**********************************************************************//** Returns the first extent descriptor for a segment. We think of the extent @@ -705,12 +703,10 @@ xdes_calc_descriptor_index( /********************************************************************//** Gets pointer to a the extent descriptor of a page. The page where the extent -descriptor resides is x-locked. If the page offset is equal to the free limit -of the space, adds new extents from above the free limit to the space free -list, if not free limit == space size. This adding is necessary to make the -descriptor defined, as they are uninitialized above the free limit. +descriptor resides is x-locked. This function no longer extends the data +file. @return pointer to the extent descriptor, NULL if the page does not -exist in the space or if the offset exceeds the free limit */ +exist in the space or if the offset is >= the free limit */ UNIV_INLINE __attribute__((nonnull, warn_unused_result)) xdes_t* xdes_get_descriptor_with_space_hdr( @@ -740,19 +736,10 @@ xdes_get_descriptor_with_space_hdr( zip_size = dict_table_flags_to_zip_size( mach_read_from_4(sp_header + FSP_SPACE_FLAGS)); - /* If offset is >= size or > limit, return NULL */ - - if ((offset >= size) || (offset > limit)) { - + if ((offset >= size) || (offset >= limit)) { return(NULL); } - /* If offset is == limit, fill free list of the space. */ - - if (offset == limit) { - fsp_fill_free_list(FALSE, space, sp_header, mtr); - } - descr_page_no = xdes_calc_descriptor_page(zip_size, offset); if (descr_page_no == 0) { @@ -2877,7 +2864,7 @@ got_hinted_page: ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT, ret_page % FSP_EXTENT_SIZE, mtr) == TRUE); - fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr); + fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr); } return(fsp_page_create( @@ -3283,27 +3270,21 @@ fsp_get_available_space_in_free_extents( /********************************************************************//** Marks a page used. The page must reside within the extents of the given segment. */ -static +static __attribute__((nonnull)) void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/*!< in: segment inode */ - ulint space, /*!< in: space id */ - ulint zip_size,/*!< in: compressed page size in bytes - or 0 for uncompressed pages */ ulint page, /*!< in: page offset */ + xdes_t* descr, /* extent descriptor */ mtr_t* mtr) /*!< in: mtr */ { - xdes_t* descr; ulint not_full_n_used; - ut_ad(seg_inode && mtr); ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); - descr = xdes_get_descriptor(space, zip_size, page, mtr); - ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr) == mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr)); -- cgit v1.2.1 From 4a6c4d8603024663727972cc6178b5173f2d59e6 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Mon, 12 Mar 2012 12:28:27 +0000 Subject: BUG#12400313 RELAY_LOG_SPACE_LIMIT IS NOT WORKING IN MANY CASES BUG#64503: mysql frequently ignores --relay-log-space-limit When the SQL thread goes to sleep, waiting for more events, it sets the flag ignore_log_space_limit to true. This gives the IO thread a chance to queue some more events and ultimately the SQL thread will be able to purge the log once it is rotated. By then the SQL thread resets the ignore_log_space_limit to false. However, between the time the SQL thread has set the ignore flag and the time it resets it, the IO thread will be queuing events in the relay log, possibly going way over the limit. This patch makes the IO and SQL thread to synchronize when they reach the space limit and only ask for one event at a time. Thus the SQL thread sets ignore_log_space_limit flag and the IO thread resets it to false everytime it processes one more event. In addition, everytime the SQL thread processes the next event, and the limit has been reached, it checks if the IO thread should rotate. If it should, it instructs the IO thread to rotate, giving the SQL thread a chance to purge the logs (freeing space). Finally, this patch removes the resetting of the ignore_log_space_limit flag from purge_first_log, because this is now reset by the IO thread every time it processes the next event when the limit has been reached. If the SQL thread is in a transaction, it cannot purge so, there is no point in asking the IO thread to rotate. The only thing it can do is to ask for more events until the transaction is over (then it can ask the IO to rotate and purge the log right away). Otherwise, there would be a deadlock (SQL would not be able to purge and IO thread would not be able to queue events so that the SQL would finish the transaction). --- .../suite/rpl/r/rpl_stm_relay_ign_space.result | 4 + .../suite/rpl/t/rpl_stm_relay_ign_space-slave.opt | 1 + .../suite/rpl/t/rpl_stm_relay_ign_space.test | 96 ++++++++++++++++++++++ sql/log.cc | 2 - sql/rpl_rli.h | 7 ++ sql/slave.cc | 92 +++++++++++++++++++-- 6 files changed, 191 insertions(+), 11 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result create mode 100644 mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt create mode 100644 mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test diff --git a/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result b/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result new file mode 100644 index 00000000000..cbef4231798 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result @@ -0,0 +1,4 @@ +include/master-slave.inc +[connection master] +include/assert.inc [Assert that relay log space is close to the limit] +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt new file mode 100644 index 00000000000..f780540aba8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt @@ -0,0 +1 @@ +--relay-log-space-limit=8192 --relay-log-purge --max-relay-log-size=4096 diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test new file mode 100644 index 00000000000..afe9f8575d3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test @@ -0,0 +1,96 @@ +# +# BUG#12400313 / BUG#64503 test case +# +# +# Description +# ----------- +# +# This test case starts the slave server with: +# --relay-log-space-limit=8192 --relay-log-purge --max-relay-log-size=4096 +# +# Then it issues some queries that will cause the slave to reach +# relay-log-space-limit. We lock the table so that the SQL thread is +# not able to purge the log and then we issue some more statements. +# +# The purpose is to show that the IO thread will honor the limits +# while the SQL thread is not able to purge the relay logs, which did +# not happen before this patch. In addition we assert that while +# ignoring the limit (SQL thread needs to rotate before purging), the +# IO thread does not do it in an uncontrolled manner. + +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc +--source include/have_innodb.inc + +--disable_query_log +CREATE TABLE t1 (c1 TEXT) engine=InnoDB; + +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); + +--sync_slave_with_master + +# wait for the SQL thread to sleep +--let $show_statement= SHOW PROCESSLIST +--let $field= State +--let $condition= = 'Has read all relay log; waiting for the slave I/O thread to update it' +--source include/wait_show_condition.inc + +# now the io thread has set rli->ignore_space_limit +# lets lock the table so that once the SQL thread awakes +# it blocks there and does not set rli->ignore_space_limit +# back to zero +LOCK TABLE t1 WRITE; + +# now issue more statements that will overflow the +# rli->log_space_limit (in this case ~10K) +--connection master + +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); + +--connection slave + +# ASSERT that the IO thread waits for the SQL thread to release some +# space before continuing +--let $show_statement= SHOW PROCESSLIST +--let $field= State +--let $condition= LIKE 'Waiting for %' +# before the patch (IO would have transfered everything) +#--let $condition= = 'Waiting for master to send event' +# after the patch (now it waits for space to be freed) +#--let $condition= = 'Waiting for the slave SQL thread to free enough relay log space' +--source include/wait_show_condition.inc + +# without the patch we can uncomment the following two lines and +# watch the IO thread synchronize with the master, thus writing +# relay logs way over the space limit +#--connection master +#--source include/sync_slave_io_with_master.inc + +## ASSERT that the IO thread has honored the limit+few bytes required to be able to purge +--let $relay_log_space_while_sql_is_executing = query_get_value(SHOW SLAVE STATUS, Relay_Log_Space, 1) +--let $relay_log_space_limit = query_get_value(SHOW VARIABLES LIKE "relay_log_space_limit", Value, 1) +--let $assert_text= Assert that relay log space is close to the limit +--let $assert_cond= $relay_log_space_while_sql_is_executing <= $relay_log_space_limit * 1.1 +--source include/assert.inc + +# unlock the table and let SQL thread continue applying events +UNLOCK TABLES; + +--connection master +DROP TABLE t1; +--enable_query_log +--sync_slave_with_master + +--source include/rpl_end.inc diff --git a/sql/log.cc b/sql/log.cc index cca403ca1be..3714f1190be 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3194,8 +3194,6 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) pthread_mutex_lock(&rli->log_space_lock); rli->relay_log.purge_logs(to_purge_if_included, included, 0, 0, &rli->log_space_total); - // Tell the I/O thread to take the relay_log_space_limit into account - rli->ignore_log_space_limit= 0; pthread_mutex_unlock(&rli->log_space_lock); /* diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index 113fb04ce00..f49be72db46 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -189,6 +189,13 @@ public: ulonglong log_space_limit,log_space_total; bool ignore_log_space_limit; + /* + Used by the SQL thread to instructs the IO thread to rotate + the logs when the SQL thread needs to purge to release some + disk space. + */ + bool sql_force_rotate_relay; + /* When it commits, InnoDB internally stores the master log position it has processed so far; the position to store is the one of the end of the diff --git a/sql/slave.cc b/sql/slave.cc index 02d8cc2c199..be109a385da 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1450,6 +1450,54 @@ Waiting for the slave SQL thread to free enough relay log space"); !(slave_killed=io_slave_killed(thd,mi)) && !rli->ignore_log_space_limit) pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock); + + /* + Makes the IO thread read only one event at a time + until the SQL thread is able to purge the relay + logs, freeing some space. + + Therefore, once the SQL thread processes this next + event, it goes to sleep (no more events in the queue), + sets ignore_log_space_limit=true and wakes the IO thread. + However, this event may have been enough already for + the SQL thread to purge some log files, freeing + rli->log_space_total . + + This guarantees that the SQL and IO thread move + forward only one event at a time (to avoid deadlocks), + when the relay space limit is reached. It also + guarantees that when the SQL thread is prepared to + rotate (to be able to purge some logs), the IO thread + will know about it and will rotate. + + NOTE: The ignore_log_space_limit is only set when the SQL + thread sleeps waiting for events. + + */ + if (rli->ignore_log_space_limit) + { +#ifndef DBUG_OFF + { + char llbuf1[22], llbuf2[22]; + DBUG_PRINT("info", ("log_space_limit=%s " + "log_space_total=%s " + "ignore_log_space_limit=%d " + "sql_force_rotate_relay=%d", + llstr(rli->log_space_limit,llbuf1), + llstr(rli->log_space_total,llbuf2), + (int) rli->ignore_log_space_limit, + (int) rli->sql_force_rotate_relay)); + } +#endif + if (rli->sql_force_rotate_relay) + { + rotate_relay_log(rli->mi); + rli->sql_force_rotate_relay= false; + } + + rli->ignore_log_space_limit= false; + } + thd->exit_cond(save_proc_info); DBUG_RETURN(slave_killed); } @@ -4260,19 +4308,45 @@ static Log_event* next_event(Relay_log_info* rli) constraint, because we do not want the I/O thread to block because of space (it's ok if it blocks for any other reason (e.g. because the master does not send anything). Then the I/O thread stops waiting - and reads more events. - The SQL thread decides when the I/O thread should take log_space_limit - into account again : ignore_log_space_limit is reset to 0 - in purge_first_log (when the SQL thread purges the just-read relay - log), and also when the SQL thread starts. We should also reset - ignore_log_space_limit to 0 when the user does RESET SLAVE, but in - fact, no need as RESET SLAVE requires that the slave + and reads one more event and starts honoring log_space_limit again. + + If the SQL thread needs more events to be able to rotate the log (it + might need to finish the current group first), then it can ask for one + more at a time. Thus we don't outgrow the relay log indefinitely, + but rather in a controlled manner, until the next rotate. + + When the SQL thread starts it sets ignore_log_space_limit to false. + We should also reset ignore_log_space_limit to 0 when the user does + RESET SLAVE, but in fact, no need as RESET SLAVE requires that the slave be stopped, and the SQL thread sets ignore_log_space_limit to 0 when it stops. */ pthread_mutex_lock(&rli->log_space_lock); - // prevent the I/O thread from blocking next times - rli->ignore_log_space_limit= 1; + + /* + If we have reached the limit of the relay space and we + are going to sleep, waiting for more events: + + 1. If outside a group, SQL thread asks the IO thread + to force a rotation so that the SQL thread purges + logs next time it processes an event (thus space is + freed). + + 2. If in a group, SQL thread asks the IO thread to + ignore the limit and queues yet one more event + so that the SQL thread finishes the group and + is are able to rotate and purge sometime soon. + */ + if (rli->log_space_limit && + rli->log_space_limit < rli->log_space_total) + { + /* force rotation if not in an unfinished group */ + rli->sql_force_rotate_relay= !rli->is_in_group(); + + /* ask for one more event */ + rli->ignore_log_space_limit= true; + } + /* If the I/O thread is blocked, unblock it. Ok to broadcast after unlock, because the mutex is only destroyed in -- cgit v1.2.1 From 9eedf9b4526b83ec6e310fae768273b4ea042e14 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Mon, 12 Mar 2012 23:15:01 +0000 Subject: BUG#12400313 Hardening the test case: - including a diff_tables at the end. - increasing the tolerance on the relay limit size. --- mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result | 1 + mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result b/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result index cbef4231798..7820f1ef97f 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result +++ b/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result @@ -1,4 +1,5 @@ include/master-slave.inc [connection master] include/assert.inc [Assert that relay log space is close to the limit] +include/diff_tables.inc [master:test.t1,slave:test.t1] include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test index afe9f8575d3..2b10da00f76 100644 --- a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test +++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test @@ -82,12 +82,16 @@ INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --let $relay_log_space_while_sql_is_executing = query_get_value(SHOW SLAVE STATUS, Relay_Log_Space, 1) --let $relay_log_space_limit = query_get_value(SHOW VARIABLES LIKE "relay_log_space_limit", Value, 1) --let $assert_text= Assert that relay log space is close to the limit ---let $assert_cond= $relay_log_space_while_sql_is_executing <= $relay_log_space_limit * 1.1 +--let $assert_cond= $relay_log_space_while_sql_is_executing <= $relay_log_space_limit * 1.15 --source include/assert.inc # unlock the table and let SQL thread continue applying events UNLOCK TABLES; +--connection master +--let $diff_tables=master:test.t1,slave:test.t1 +--source include/diff_tables.inc + --connection master DROP TABLE t1; --enable_query_log -- cgit v1.2.1 From 7f84e70b8689c535828af7f696775c4391f20a66 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Mon, 12 Mar 2012 23:23:40 +0000 Subject: BUG#12400313 Adding missing sync_slave_with_master to the test case. --- mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test index 2b10da00f76..c90bcfea1b7 100644 --- a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test +++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test @@ -89,6 +89,7 @@ INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx UNLOCK TABLES; --connection master +--sync_slave_with_master --let $diff_tables=master:test.t1,slave:test.t1 --source include/diff_tables.inc -- cgit v1.2.1 From a8217b7cd3e31c7ff5212b84b9736af689a5ad39 Mon Sep 17 00:00:00 2001 From: Inaam Rana Date: Thu, 15 Mar 2012 11:53:30 -0400 Subject: Bug#13537504 VALGRIND: COND. JUMP/MOVE DEPENDS ON UNINITIALISED VALUES IN OS_THREAD_EQ rb://977 approved by: Marko Makela rw_lock::writer_thread field contains the thread id of current x-holder or wait-x thread. This field is un-initialized at lock creation and is written to for the first time when an attempt is made to x-lock. Current code considers ::writer_thread as valid memory region only when the lock is held in x-mode (or there is an x-waiter). This is an overkill and it generates valgrind warnings. The fix is to consider ::writer_thread as valid memory region once it has been written to. Reasoning: ========== The ::writer_thread can be safely considered valid because: * We only ever do comparison with current calling threads id. * We only ever do comparison when ::recursive flag is set * We always unset ::recursive flag in x-unlock * Same thread cannot be unlocking and attempting to lock at the same time * thread_id recycling is not an issue because before an id is recycled the thread must leave innodb meaning it must release all locks meaning it must unset ::recursive flag. --- storage/innodb_plugin/ChangeLog | 6 ++++++ storage/innodb_plugin/include/sync0rw.ic | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index b43aed5cc06..416227c84c3 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2012-03-15 The InnoDB Team + + * include/sync0rw.ic: + Fix Bug#13537504 VALGRIND: COND. JUMP/MOVE DEPENDS ON + UNINITIALISED VALUES IN OS_THREAD_EQ + 2012-03-08 The InnoDB Team * btr/btr0pcur.c: diff --git a/storage/innodb_plugin/include/sync0rw.ic b/storage/innodb_plugin/include/sync0rw.ic index 5eb3d017eca..cd997febc30 100644 --- a/storage/innodb_plugin/include/sync0rw.ic +++ b/storage/innodb_plugin/include/sync0rw.ic @@ -564,8 +564,6 @@ rw_lock_x_unlock_func( if (lock->lock_word == 0) { /* Last caller in a possible recursive chain. */ lock->recursive = FALSE; - UNIV_MEM_INVALID(&lock->writer_thread, - sizeof lock->writer_thread); } #ifdef UNIV_SYNC_DEBUG @@ -606,8 +604,6 @@ rw_lock_x_unlock_direct( if (lock->lock_word == 0) { lock->recursive = FALSE; - UNIV_MEM_INVALID(&lock->writer_thread, - sizeof lock->writer_thread); } #ifdef UNIV_SYNC_DEBUG -- cgit v1.2.1 From 04c96834ccf8880529865d6d34c67410af8e33b9 Mon Sep 17 00:00:00 2001 From: Inaam Rana Date: Thu, 15 Mar 2012 12:38:40 -0400 Subject: Bug#13851171 STRING OVERFLOW IN INNODB CODE FOUND BY STATIC ANALYSIS rb://976 approved by: Marko Makela Add an assertion to ensure that string overflow is not happening. Pointed by Coverity analysis. --- storage/innodb_plugin/ChangeLog | 6 ++++++ storage/innodb_plugin/handler/ha_innodb.cc | 2 ++ 2 files changed, 8 insertions(+) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 416227c84c3..058128a2200 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2012-03-15 The InnoDB Team + + * handler/ha_innodb.cc: + Fix Bug#13851171STRING OVERFLOW IN INNODB CODE FOUND BY STATIC + ANALYSIS + 2012-03-15 The InnoDB Team * include/sync0rw.ic: diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 09094c0146e..f16b9fabd20 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -6718,6 +6718,8 @@ ha_innobase::create( DBUG_RETURN(HA_ERR_TO_BIG_ROW); } + ut_a(strlen(name) < sizeof(name2)); + strcpy(name2, name); normalize_table_name(norm_name, name2); -- cgit v1.2.1 From 0023147055f7222a1d454e71729b0013af68881c Mon Sep 17 00:00:00 2001 From: Inaam Rana Date: Thu, 15 Mar 2012 13:30:17 -0400 Subject: Bug#13825266 RACE IN LOCK_VALIDATE() WHEN ACCESSING PAGES DIRECTLY FROM BUFFER POOL rb://975 approved by: Marko Makela There is a race in lock_validate() where we try to access a page without ensuring that the tablespace stays valid during the operation i.e.: it is not deleted. This patch tries to fix that by using an existing flag (the flag is renamed to make it's name more generic in line with it's new use). --- storage/innodb_plugin/ChangeLog | 7 ++++ storage/innodb_plugin/fil/fil0fil.c | 59 +++++++++++++++++---------------- storage/innodb_plugin/ibuf/ibuf0ibuf.c | 6 ++-- storage/innodb_plugin/include/fil0fil.h | 15 ++++----- storage/innodb_plugin/lock/lock0lock.c | 14 ++++++-- 5 files changed, 58 insertions(+), 43 deletions(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 058128a2200..8b767bc8141 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,10 @@ +2012-03-15 The InnoDB Team + + * fil/fil0fil.c, ibuf/ibuf0ibuf.c, include/fil0fil.h, + lock/lock0lock.c: + Fix Bug#13825266 RACE IN LOCK_VALIDATE() WHEN ACCESSING PAGES + DIRECTLY FROM BUFFER POOL + 2012-03-15 The InnoDB Team * handler/ha_innodb.cc: diff --git a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c index 01057c26d94..eebfbd9ccad 100644 --- a/storage/innodb_plugin/fil/fil0fil.c +++ b/storage/innodb_plugin/fil/fil0fil.c @@ -175,7 +175,7 @@ struct fil_space_struct { .ibd file of tablespace and want to stop temporarily posting of new i/o requests on the file */ - ibool stop_ibuf_merges; + ibool stop_new_ops; /*!< we set this TRUE when we start deleting a single-table tablespace */ ibool is_being_deleted; @@ -200,12 +200,13 @@ struct fil_space_struct { ulint n_pending_flushes; /*!< this is positive when flushing the tablespace to disk; dropping of the tablespace is forbidden if this is positive */ - ulint n_pending_ibuf_merges;/*!< this is positive - when merging insert buffer entries to - a page so that we may need to access - the ibuf bitmap page in the - tablespade: dropping of the tablespace - is forbidden if this is positive */ + ulint n_pending_ops;/*!< this is positive when we + have pending operations against this + tablespace. The pending operations can + be ibuf merges or lock validation code + trying to read a block. + Dropping of the tablespace is forbidden + if this is positive */ hash_node_t hash; /*!< hash chain node */ hash_node_t name_hash;/*!< hash chain the name_hash table */ #ifndef UNIV_HOTBACKUP @@ -1236,7 +1237,7 @@ try_again: } space->stop_ios = FALSE; - space->stop_ibuf_merges = FALSE; + space->stop_new_ops = FALSE; space->is_being_deleted = FALSE; space->purpose = purpose; space->size = 0; @@ -1245,7 +1246,7 @@ try_again: space->n_reserved_extents = 0; space->n_pending_flushes = 0; - space->n_pending_ibuf_merges = 0; + space->n_pending_ops = 0; UT_LIST_INIT(space->chain); space->magic_n = FIL_SPACE_MAGIC_N; @@ -1836,13 +1837,12 @@ fil_read_flushed_lsn_and_arch_log_no( #ifndef UNIV_HOTBACKUP /*******************************************************************//** -Increments the count of pending insert buffer page merges, if space is not -being deleted. -@return TRUE if being deleted, and ibuf merges should be skipped */ +Increments the count of pending operation, if space is not being deleted. +@return TRUE if being deleted, and operation should be skipped */ UNIV_INTERN ibool -fil_inc_pending_ibuf_merges( -/*========================*/ +fil_inc_pending_ops( +/*================*/ ulint id) /*!< in: space id */ { fil_space_t* space; @@ -1858,13 +1858,13 @@ fil_inc_pending_ibuf_merges( (ulong) id); } - if (space == NULL || space->stop_ibuf_merges) { + if (space == NULL || space->stop_new_ops) { mutex_exit(&fil_system->mutex); return(TRUE); } - space->n_pending_ibuf_merges++; + space->n_pending_ops++; mutex_exit(&fil_system->mutex); @@ -1872,11 +1872,11 @@ fil_inc_pending_ibuf_merges( } /*******************************************************************//** -Decrements the count of pending insert buffer page merges. */ +Decrements the count of pending operations. */ UNIV_INTERN void -fil_decr_pending_ibuf_merges( -/*=========================*/ +fil_decr_pending_ops( +/*=================*/ ulint id) /*!< in: space id */ { fil_space_t* space; @@ -1887,13 +1887,13 @@ fil_decr_pending_ibuf_merges( if (space == NULL) { fprintf(stderr, - "InnoDB: Error: decrementing ibuf merge of a" - " dropped tablespace %lu\n", + "InnoDB: Error: decrementing pending operation" + " of a dropped tablespace %lu\n", (ulong) id); } if (space != NULL) { - space->n_pending_ibuf_merges--; + space->n_pending_ops--; } mutex_exit(&fil_system->mutex); @@ -2183,15 +2183,15 @@ fil_delete_tablespace( char* path; ut_a(id != 0); -stop_ibuf_merges: +stop_new_ops: mutex_enter(&fil_system->mutex); space = fil_space_get_by_id(id); if (space != NULL) { - space->stop_ibuf_merges = TRUE; + space->stop_new_ops = TRUE; - if (space->n_pending_ibuf_merges == 0) { + if (space->n_pending_ops == 0) { mutex_exit(&fil_system->mutex); count = 0; @@ -2205,9 +2205,10 @@ stop_ibuf_merges: ut_print_filename(stderr, space->name); fprintf(stderr, ",\n" "InnoDB: but there are %lu pending" - " ibuf merges on it.\n" + " operations (most likely ibuf merges)" + " on it.\n" "InnoDB: Loop %lu.\n", - (ulong) space->n_pending_ibuf_merges, + (ulong) space->n_pending_ops, (ulong) count); } @@ -2216,7 +2217,7 @@ stop_ibuf_merges: os_thread_sleep(20000); count++; - goto stop_ibuf_merges; + goto stop_new_ops; } } @@ -2242,7 +2243,7 @@ try_again: } ut_a(space); - ut_a(space->n_pending_ibuf_merges == 0); + ut_a(space->n_pending_ops == 0); space->is_being_deleted = TRUE; diff --git a/storage/innodb_plugin/ibuf/ibuf0ibuf.c b/storage/innodb_plugin/ibuf/ibuf0ibuf.c index f2b51c7ebed..f1da399167c 100644 --- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c +++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c @@ -3281,7 +3281,7 @@ ibuf_merge_or_delete_for_page( function. When the counter is > 0, that prevents tablespace from being dropped. */ - tablespace_being_deleted = fil_inc_pending_ibuf_merges(space); + tablespace_being_deleted = fil_inc_pending_ops(space); if (UNIV_UNLIKELY(tablespace_being_deleted)) { /* Do not try to read the bitmap page from space; @@ -3305,7 +3305,7 @@ ibuf_merge_or_delete_for_page( mtr_commit(&mtr); if (!tablespace_being_deleted) { - fil_decr_pending_ibuf_merges(space); + fil_decr_pending_ops(space); } return; @@ -3537,7 +3537,7 @@ reset_bit: if (update_ibuf_bitmap && !tablespace_being_deleted) { - fil_decr_pending_ibuf_merges(space); + fil_decr_pending_ops(space); } ibuf_exit(); diff --git a/storage/innodb_plugin/include/fil0fil.h b/storage/innodb_plugin/include/fil0fil.h index f6a19646292..c95038b9231 100644 --- a/storage/innodb_plugin/include/fil0fil.h +++ b/storage/innodb_plugin/include/fil0fil.h @@ -340,20 +340,19 @@ fil_read_flushed_lsn_and_arch_log_no( ib_uint64_t* min_flushed_lsn, /*!< in/out: */ ib_uint64_t* max_flushed_lsn); /*!< in/out: */ /*******************************************************************//** -Increments the count of pending insert buffer page merges, if space is not -being deleted. -@return TRUE if being deleted, and ibuf merges should be skipped */ +Increments the count of pending operation, if space is not being deleted. +@return TRUE if being deleted, and operation should be skipped */ UNIV_INTERN ibool -fil_inc_pending_ibuf_merges( -/*========================*/ +fil_inc_pending_ops( +/*================*/ ulint id); /*!< in: space id */ /*******************************************************************//** -Decrements the count of pending insert buffer page merges. */ +Decrements the count of pending operations. */ UNIV_INTERN void -fil_decr_pending_ibuf_merges( -/*=========================*/ +fil_decr_pending_ops( +/*=================*/ ulint id); /*!< in: space id */ #endif /* !UNIV_HOTBACKUP */ /*******************************************************************//** diff --git a/storage/innodb_plugin/lock/lock0lock.c b/storage/innodb_plugin/lock/lock0lock.c index c8bbc5c02bd..49f732da175 100644 --- a/storage/innodb_plugin/lock/lock0lock.c +++ b/storage/innodb_plugin/lock/lock0lock.c @@ -5040,9 +5040,17 @@ lock_validate(void) lock_mutex_exit_kernel(); - lock_rec_validate_page(space, - fil_space_get_zip_size(space), - page_no); + /* Make sure that the tablespace is not + deleted while we are trying to access + the page. */ + if (!fil_inc_pending_ops(space)) { + lock_rec_validate_page( + space, + fil_space_get_zip_size(space), + page_no); + + fil_decr_pending_ops(space); + } lock_mutex_enter_kernel(); -- cgit v1.2.1 From 08f051df04675833ff819be306a204c0c9813e29 Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Fri, 16 Mar 2012 12:06:29 +0530 Subject: Bug #11766634 59783: INNODB DATA GROWS UNEXPECTEDLY WHEN INSERTING, TRUNCATING, INSERTING THE The test case must insert all the records using a single transaction. Otherwise the test case takes more than 15 minutes and will time out in pb2 and mtr. --- mysql-test/suite/innodb/t/innodb_bug11766634.test | 4 ++++ mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/mysql-test/suite/innodb/t/innodb_bug11766634.test b/mysql-test/suite/innodb/t/innodb_bug11766634.test index a830955c78a..91be4da0338 100644 --- a/mysql-test/suite/innodb/t/innodb_bug11766634.test +++ b/mysql-test/suite/innodb/t/innodb_bug11766634.test @@ -18,11 +18,13 @@ let $recs = 36262; --disable_query_log let $c = $recs; +start transaction; while ($c) { insert into t1 values ('Hello World'); dec $c; } +commit work; --enable_query_log perl; @@ -35,11 +37,13 @@ create table t1 (f1 char(255)) engine innodb; --disable_query_log let $c = $recs; +start transaction; while ($c) { insert into t1 values ('Hello World'); dec $c; } +commit work; --enable_query_log perl; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test b/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test index 1780317675d..cd46deb64fb 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test @@ -18,11 +18,13 @@ let $recs = 36262; --disable_query_log let $c = $recs; +start transaction; while ($c) { insert into t1 values ('Hello World'); dec $c; } +commit work; --enable_query_log perl; @@ -35,11 +37,13 @@ create table t1 (f1 char(255)) engine innodb; --disable_query_log let $c = $recs; +start transaction; while ($c) { insert into t1 values ('Hello World'); dec $c; } +commit work; --enable_query_log perl; -- cgit v1.2.1