Commit 7fc60861 authored by Michael Widenius's avatar Michael Widenius

Automatic merge with 5.1-release

parents 91a72ee3 8938ed57
...@@ -241,3 +241,60 @@ DROP TABLE t1; ...@@ -241,3 +241,60 @@ DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
SET SQL_MODE=''; SET SQL_MODE='';
sync_slave_with_master; sync_slave_with_master;
#
# Bug#54201: "SET INSERT_ID" event must be ignored if corresponding event is
# ignored.
#
connection master;
CREATE TABLE t1(s VARCHAR(10)) ENGINE=myisam;
# -slave.opt has --replicate-ignore-table=test.t_ignored1
CREATE TABLE t_ignored1(id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=myisam;
sync_slave_with_master;
connection slave;
CREATE TABLE test.slave_only(id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=myisam;
INSERT INTO slave_only VALUES(NULL);
CREATE TRIGGER t1_update AFTER UPDATE ON t1 FOR EACH ROW INSERT INTO slave_only VALUES(NULL);
connection master;
INSERT INTO t_ignored1 VALUES(NULL);
INSERT INTO t1 VALUES('s');
UPDATE t1 SET s='s1';
# With Bug#54201, slave stops with duplicate key error here due to trigger
# using the insert_id from insert on master into t1_ignored1
sync_slave_with_master;
connection slave;
SELECT * FROM t1;
connection master;
CREATE TABLE t_ignored2(id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=myisam;
sync_slave_with_master;
connection slave;
STOP SLAVE;
# Ignore the next INSERT into t_ignored2 and the INSERT_ID event just before it.
SET GLOBAL sql_slave_skip_counter = 2;
START SLAVE;
connection master;
INSERT INTO t_ignored2 VALUES(NULL);
UPDATE t1 SET s='s2';
sync_slave_with_master;
connection slave;
SELECT * FROM t1;
SHOW TABLES LIKE 't\_ignored_';
SELECT * FROM t_ignored2;
DROP TABLE slave_only;
connection master;
DROP TABLE t1;
DROP TABLE t_ignored1;
DROP TABLE t_ignored2;
sync_slave_with_master;
...@@ -76,6 +76,11 @@ UNLOCK TABLES; ...@@ -76,6 +76,11 @@ UNLOCK TABLES;
UNLOCK TABLES; UNLOCK TABLES;
-- connection con3 -- connection con3
#
# We may get a timeout error here if the tables are locked in a different
# order than expected. This is ok as the purpose of this patch is to ensure
# we don't get a crash in the previous unlock tables.
-- error 0, 1205
-- reap -- reap
UNLOCK TABLES; UNLOCK TABLES;
......
...@@ -72,6 +72,11 @@ UNLOCK TABLES; ...@@ -72,6 +72,11 @@ UNLOCK TABLES;
# clean up # clean up
-- connection con2 -- connection con2
#
# We may get a timeout error here if the tables are locked in a different
# order than expected. This is ok as the purpose of this patch is to ensure
# we don't get a crash in the previous unlock tables.
-- error 0, 1205
-- reap -- reap
UNLOCK TABLES; UNLOCK TABLES;
......
...@@ -312,3 +312,32 @@ Comparing tables master:test.t2 and slave:test.t2 ...@@ -312,3 +312,32 @@ Comparing tables master:test.t2 and slave:test.t2
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
SET SQL_MODE=''; SET SQL_MODE='';
CREATE TABLE t1(s VARCHAR(10)) ENGINE=myisam;
CREATE TABLE t_ignored1(id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=myisam;
CREATE TABLE test.slave_only(id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=myisam;
INSERT INTO slave_only VALUES(NULL);
CREATE TRIGGER t1_update AFTER UPDATE ON t1 FOR EACH ROW INSERT INTO slave_only VALUES(NULL);
INSERT INTO t_ignored1 VALUES(NULL);
INSERT INTO t1 VALUES('s');
UPDATE t1 SET s='s1';
SELECT * FROM t1;
s
s1
CREATE TABLE t_ignored2(id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=myisam;
STOP SLAVE;
SET GLOBAL sql_slave_skip_counter = 2;
START SLAVE;
INSERT INTO t_ignored2 VALUES(NULL);
UPDATE t1 SET s='s2';
SELECT * FROM t1;
s
s2
SHOW TABLES LIKE 't\_ignored_';
Tables_in_test (t\_ignored_)
t_ignored2
SELECT * FROM t_ignored2;
id
DROP TABLE slave_only;
DROP TABLE t1;
DROP TABLE t_ignored1;
DROP TABLE t_ignored2;
--replicate-ignore-table=test.t_ignored1
...@@ -1719,6 +1719,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) ...@@ -1719,6 +1719,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
if (action->execute) if (action->execute)
{ {
const char *old_proc_info; const char *old_proc_info;
LINT_INIT(old_proc_info);
action->execute--; action->execute--;
......
...@@ -3307,6 +3307,19 @@ START SLAVE; . Query: '%s'", expected_error, thd->query()); ...@@ -3307,6 +3307,19 @@ START SLAVE; . Query: '%s'", expected_error, thd->query());
/* If the query was not ignored, it is printed to the general log */ /* If the query was not ignored, it is printed to the general log */
if (!thd->is_error() || thd->main_da.sql_errno() != ER_SLAVE_IGNORED_TABLE) if (!thd->is_error() || thd->main_da.sql_errno() != ER_SLAVE_IGNORED_TABLE)
general_log_write(thd, COM_QUERY, thd->query(), thd->query_length()); general_log_write(thd, COM_QUERY, thd->query(), thd->query_length());
else
{
/*
Bug#54201: If we skip an INSERT query that uses auto_increment, then we
should reset any @@INSERT_ID set by an Intvar_log_event associated with
the query; otherwise the @@INSERT_ID will linger until the next INSERT
that uses auto_increment and may affect extra triggers on the slave etc.
We reset INSERT_ID unconditionally; it is probably cheaper than
checking if it is necessary.
*/
thd->auto_inc_intervals_forced.empty();
}
compare_errors: compare_errors:
......
...@@ -128,7 +128,9 @@ static void fix_net_write_timeout(THD *thd, enum_var_type type); ...@@ -128,7 +128,9 @@ static void fix_net_write_timeout(THD *thd, enum_var_type type);
static void fix_net_retry_count(THD *thd, enum_var_type type); static void fix_net_retry_count(THD *thd, enum_var_type type);
static void fix_max_join_size(THD *thd, enum_var_type type); static void fix_max_join_size(THD *thd, enum_var_type type);
static void fix_query_cache_size(THD *thd, enum_var_type type); static void fix_query_cache_size(THD *thd, enum_var_type type);
#ifdef HAVE_QUERY_CACHE
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type); static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
#endif
static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type); static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
static void fix_max_binlog_size(THD *thd, enum_var_type type); static void fix_max_binlog_size(THD *thd, enum_var_type type);
static void fix_max_relay_log_size(THD *thd, enum_var_type type); static void fix_max_relay_log_size(THD *thd, enum_var_type type);
......
/* Copyright (C) 2007 MySQL AB & Sanja Belkin /* Copyright (C) 2007 MySQL AB & Sanja Belkin. 2010 Monty Program Ab.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -2526,10 +2526,9 @@ static my_bool translog_buffer_flush(struct st_translog_buffer *buffer) ...@@ -2526,10 +2526,9 @@ static my_bool translog_buffer_flush(struct st_translog_buffer *buffer)
{ {
/* some other flush in progress */ /* some other flush in progress */
translog_wait_for_closing(buffer); translog_wait_for_closing(buffer);
}
if (buffer->file != file || buffer->offset != offset || buffer->ver != ver) if (buffer->file != file || buffer->offset != offset || buffer->ver != ver)
DBUG_RETURN(0); /* some the thread flushed the buffer already */ DBUG_RETURN(0); /* some the thread flushed the buffer already */
}
if (buffer->overlay && translog_prev_buffer_flush_wait(buffer)) if (buffer->overlay && translog_prev_buffer_flush_wait(buffer))
DBUG_RETURN(0); /* some the thread flushed the buffer already */ DBUG_RETURN(0); /* some the thread flushed the buffer already */
...@@ -7580,6 +7579,7 @@ my_bool translog_flush(TRANSLOG_ADDRESS lsn) ...@@ -7580,6 +7579,7 @@ my_bool translog_flush(TRANSLOG_ADDRESS lsn)
DBUG_ASSERT(translog_status == TRANSLOG_OK || DBUG_ASSERT(translog_status == TRANSLOG_OK ||
translog_status == TRANSLOG_READONLY); translog_status == TRANSLOG_READONLY);
LINT_INIT(sent_to_disk); LINT_INIT(sent_to_disk);
LINT_INIT(last_buffer_no);
pthread_mutex_lock(&log_descriptor.log_flush_lock); pthread_mutex_lock(&log_descriptor.log_flush_lock);
DBUG_PRINT("info", ("Everything is flushed up to (%lu,0x%lx)", DBUG_PRINT("info", ("Everything is flushed up to (%lu,0x%lx)",
...@@ -7648,18 +7648,28 @@ my_bool translog_flush(TRANSLOG_ADDRESS lsn) ...@@ -7648,18 +7648,28 @@ my_bool translog_flush(TRANSLOG_ADDRESS lsn)
struct st_translog_buffer *buffer= log_descriptor.bc.buffer; struct st_translog_buffer *buffer= log_descriptor.bc.buffer;
lsn= log_descriptor.bc.buffer->last_lsn; /* fix lsn if it was horizon */ lsn= log_descriptor.bc.buffer->last_lsn; /* fix lsn if it was horizon */
DBUG_PRINT("info", ("LSN to flush fixed to last lsn: (%lu,0x%lx)", DBUG_PRINT("info", ("LSN to flush fixed to last lsn: (%lu,0x%lx)",
LSN_IN_PARTS(log_descriptor.bc.buffer->last_lsn))); LSN_IN_PARTS(lsn)));
last_buffer_no= log_descriptor.bc.buffer_no; last_buffer_no= log_descriptor.bc.buffer_no;
log_descriptor.is_everything_flushed= 1; log_descriptor.is_everything_flushed= 1;
translog_force_current_buffer_to_finish(); translog_force_current_buffer_to_finish();
translog_buffer_unlock(buffer); translog_buffer_unlock(buffer);
} }
else else if (log_descriptor.bc.buffer->prev_last_lsn != LSN_IMPOSSIBLE)
{ {
/* fix lsn if it was horizon */
lsn= log_descriptor.bc.buffer->prev_last_lsn;
DBUG_PRINT("info", ("LSN to flush fixed to prev last lsn: (%lu,0x%lx)",
LSN_IN_PARTS(lsn)));
last_buffer_no= ((log_descriptor.bc.buffer_no + TRANSLOG_BUFFERS_NO -1) % last_buffer_no= ((log_descriptor.bc.buffer_no + TRANSLOG_BUFFERS_NO -1) %
TRANSLOG_BUFFERS_NO); TRANSLOG_BUFFERS_NO);
translog_unlock(); translog_unlock();
} }
else if (log_descriptor.bc.buffer->last_lsn == LSN_IMPOSSIBLE)
{
DBUG_PRINT("info", ("There is no LSNs yet generated => do nothing"));
translog_unlock();
goto out;
}
sent_to_disk= translog_get_sent_to_disk(); sent_to_disk= translog_get_sent_to_disk();
if (cmp_translog_addr(lsn, sent_to_disk) > 0) if (cmp_translog_addr(lsn, sent_to_disk) > 0)
{ {
......
...@@ -1025,6 +1025,7 @@ finish: ...@@ -1025,6 +1025,7 @@ finish:
*/ */
static inline void inc_counter_for_resize_op(PAGECACHE *pagecache) static inline void inc_counter_for_resize_op(PAGECACHE *pagecache)
{ {
safe_mutex_assert_owner(&pagecache->cache_lock);
pagecache->cnt_for_resize_op++; pagecache->cnt_for_resize_op++;
} }
...@@ -1037,6 +1038,7 @@ static inline void dec_counter_for_resize_op(PAGECACHE *pagecache) ...@@ -1037,6 +1038,7 @@ static inline void dec_counter_for_resize_op(PAGECACHE *pagecache)
{ {
#ifdef THREAD #ifdef THREAD
struct st_my_thread_var *last_thread; struct st_my_thread_var *last_thread;
safe_mutex_assert_owner(&pagecache->cache_lock);
if (!--pagecache->cnt_for_resize_op && if (!--pagecache->cnt_for_resize_op &&
(last_thread= pagecache->resize_queue.last_thread)) (last_thread= pagecache->resize_queue.last_thread))
{ {
...@@ -1044,6 +1046,7 @@ static inline void dec_counter_for_resize_op(PAGECACHE *pagecache) ...@@ -1044,6 +1046,7 @@ static inline void dec_counter_for_resize_op(PAGECACHE *pagecache)
("thread %ld", last_thread->next->id)); ("thread %ld", last_thread->next->id));
pagecache_pthread_cond_signal(&last_thread->next->suspend); pagecache_pthread_cond_signal(&last_thread->next->suspend);
} }
DBUG_ASSERT((longlong) pagecache->cnt_for_resize_op >= 0);
#else #else
pagecache->cnt_for_resize_op--; pagecache->cnt_for_resize_op--;
#endif #endif
...@@ -1084,6 +1087,37 @@ void change_pagecache_param(PAGECACHE *pagecache, uint division_limit, ...@@ -1084,6 +1087,37 @@ void change_pagecache_param(PAGECACHE *pagecache, uint division_limit,
} }
/*
Check that pagecache was used and cleaned up properly.
*/
#ifndef DBUG_OFF
void check_pagecache_is_cleaned_up(PAGECACHE *pagecache)
{
DBUG_ENTER("check_pagecache_is_cleaned_up");
/*
Ensure we called inc_counter_for_resize_op and dec_counter_for_resize_op
the same number of times. (If not, a resize() could never happen.
*/
DBUG_ASSERT(pagecache->cnt_for_resize_op == 0);
if (pagecache->disk_blocks > 0)
{
if (pagecache->block_mem)
{
uint i;
for (i=0 ; i < pagecache->blocks_used ; i++)
{
DBUG_ASSERT(pagecache->block_root[i].status == 0);
DBUG_ASSERT(pagecache->block_root[i].type == PAGECACHE_EMPTY_PAGE);
}
}
}
DBUG_VOID_RETURN;
}
#endif
/* /*
Removes page cache from memory. Does NOT flush pages to disk. Removes page cache from memory. Does NOT flush pages to disk.
...@@ -1106,6 +1140,10 @@ void end_pagecache(PAGECACHE *pagecache, my_bool cleanup) ...@@ -1106,6 +1140,10 @@ void end_pagecache(PAGECACHE *pagecache, my_bool cleanup)
if (pagecache->disk_blocks > 0) if (pagecache->disk_blocks > 0)
{ {
#ifndef DBUG_OFF
check_pagecache_is_cleaned_up(pagecache);
#endif
if (pagecache->block_mem) if (pagecache->block_mem)
{ {
my_large_free(pagecache->block_mem, MYF(0)); my_large_free(pagecache->block_mem, MYF(0));
...@@ -2250,6 +2288,7 @@ static my_bool pagecache_wait_lock(PAGECACHE *pagecache, ...@@ -2250,6 +2288,7 @@ static my_bool pagecache_wait_lock(PAGECACHE *pagecache,
&pagecache->cache_lock); &pagecache->cache_lock);
} }
while(thread->next); while(thread->next);
inc_counter_for_resize_op(pagecache);
#else #else
DBUG_ASSERT(0); DBUG_ASSERT(0);
#endif #endif
...@@ -3457,7 +3496,7 @@ static my_bool pagecache_delete_internal(PAGECACHE *pagecache, ...@@ -3457,7 +3496,7 @@ static my_bool pagecache_delete_internal(PAGECACHE *pagecache,
{ {
/* /*
this call is just 'hint' for the cache to free the page so we will this call is just 'hint' for the cache to free the page so we will
not interferes with flushing process but gust return success not interferes with flushing process but must return success
*/ */
goto out; goto out;
} }
...@@ -3527,8 +3566,17 @@ static my_bool pagecache_delete_internal(PAGECACHE *pagecache, ...@@ -3527,8 +3566,17 @@ static my_bool pagecache_delete_internal(PAGECACHE *pagecache,
page_link->requests--; page_link->requests--;
/* See NOTE for pagecache_unlock about registering requests. */ /* See NOTE for pagecache_unlock about registering requests. */
free_block(pagecache, block); free_block(pagecache, block);
dec_counter_for_resize_op(pagecache);
return 0;
out: out:
/* Cache is locked, so we can relese page before freeing it */
if (make_lock_and_pin(pagecache, block,
PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, FALSE))
DBUG_ASSERT(0);
page_link->requests--;
unreg_request(pagecache, block, 1);
dec_counter_for_resize_op(pagecache); dec_counter_for_resize_op(pagecache);
return error; return error;
} }
...@@ -3579,6 +3627,8 @@ my_bool pagecache_delete_by_link(PAGECACHE *pagecache, ...@@ -3579,6 +3627,8 @@ my_bool pagecache_delete_by_link(PAGECACHE *pagecache,
*/ */
DBUG_ASSERT((block->status & DBUG_ASSERT((block->status &
(PCBLOCK_IN_SWITCH | PCBLOCK_REASSIGNED)) == 0); (PCBLOCK_IN_SWITCH | PCBLOCK_REASSIGNED)) == 0);
inc_counter_for_resize_op(pagecache);
/* /*
make_lock_and_pin() can't fail here, because we are keeping pin on the make_lock_and_pin() can't fail here, because we are keeping pin on the
block and it can't be evicted (which is cause of lock fail and retry) block and it can't be evicted (which is cause of lock fail and retry)
...@@ -3695,6 +3745,7 @@ restart: ...@@ -3695,6 +3745,7 @@ restart:
if (!page_link) if (!page_link)
{ {
DBUG_PRINT("info", ("There is no such page in the cache")); DBUG_PRINT("info", ("There is no such page in the cache"));
dec_counter_for_resize_op(pagecache);
pagecache_pthread_mutex_unlock(&pagecache->cache_lock); pagecache_pthread_mutex_unlock(&pagecache->cache_lock);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -3707,6 +3758,7 @@ restart: ...@@ -3707,6 +3758,7 @@ restart:
"reassigned" : "in switch"))); "reassigned" : "in switch")));
PCBLOCK_INFO(block); PCBLOCK_INFO(block);
page_link->requests--; page_link->requests--;
dec_counter_for_resize_op(pagecache);
goto end; goto end;
} }
/* See NOTE for pagecache_unlock about registering requests. */ /* See NOTE for pagecache_unlock about registering requests. */
......
...@@ -247,10 +247,11 @@ rw_lock_create_func( ...@@ -247,10 +247,11 @@ rw_lock_create_func(
lock->mutex.cmutex_name = cmutex_name; lock->mutex.cmutex_name = cmutex_name;
ut_d(lock->mutex.mutex_type = 1); ut_d(lock->mutex.mutex_type = 1);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */ #endif /* INNODB_RW_LOCKS_USE_ATOMICS */
#if defined(INNODB_RW_LOCKS_USE_ATOMICS) || !defined(UNIV_DEBUG)
(void) cfile_name; (void) cfile_name;
(void) cline; (void) cline;
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */ #endif
lock->lock_word = X_LOCK_DECR; lock->lock_word = X_LOCK_DECR;
lock->waiters = 0; lock->waiters = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment