Commit 98aad88f authored by unknown's avatar unknown

after-merge fixes and comments


mysql-test/include/maria_empty_logs.inc:
  At one moment in maria-recovery.test the first log has number 2,
  because log 1 was manually deleted.
mysql-test/r/maria-recovery.result:
  after-merge fix
mysql-test/t/maria-recovery.test:
  after-merge fix
storage/maria/ma_bitmap.c:
  after-merge fix. The todo is implemented now.
storage/maria/ma_blockrec.c:
  comment
storage/maria/ma_open.c:
  after-merge fix. Set write_fail also for index file or a write error
  would crash.
storage/maria/ma_pagecache.c:
  comment
storage/maria/ma_pagecache.h:
  I prefer to use NULL for 'no callback' instead of a dummy callback
  in the special case of get_log_address; indeed for non-transactional
  tables it uses an if(), while if using a dummy callback, it would
  use a function call plus an if() (the dummy callback would need to
  return a magic value to say "don't flush" and that value would be
  tested in if()).
storage/maria/unittest/ma_test_all-t:
  fix if running from outside storage/maria
parent a9c9364c
...@@ -17,6 +17,7 @@ if (!$mel_keep_control_file) ...@@ -17,6 +17,7 @@ if (!$mel_keep_control_file)
{ {
remove_file $MYSQLTEST_VARDIR/master-data/maria_log_control; remove_file $MYSQLTEST_VARDIR/master-data/maria_log_control;
} }
-- error 0,1
remove_file $MYSQLTEST_VARDIR/master-data/maria_log.00000001; remove_file $MYSQLTEST_VARDIR/master-data/maria_log.00000001;
-- error 0,1 -- error 0,1
remove_file $MYSQLTEST_VARDIR/master-data/maria_log.00000002; remove_file $MYSQLTEST_VARDIR/master-data/maria_log.00000002;
......
...@@ -214,6 +214,9 @@ t1 CREATE TABLE `t1` ( ...@@ -214,6 +214,9 @@ t1 CREATE TABLE `t1` (
KEY `c` (`c`) KEY `c` (`c`)
) ENGINE=MARIA AUTO_INCREMENT=16 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 ) ENGINE=MARIA AUTO_INCREMENT=16 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
drop table t1; drop table t1;
* TEST of removing logs manually
* shut down mysqld, removed logs, restarted it
use mysqltest;
* TEST of UNDO_ROW_DELETE preserving rowid * TEST of UNDO_ROW_DELETE preserving rowid
create table t1(a int) engine=maria; create table t1(a int) engine=maria;
insert into t1 values(1),(2); insert into t1 values(1),(2);
...@@ -222,17 +225,38 @@ flush table t1; ...@@ -222,17 +225,38 @@ flush table t1;
lock tables t1 write; lock tables t1 write;
insert into t1 values(3); insert into t1 values(3);
delete from t1 where a in (1,2,3); delete from t1 where a in (1,2,3);
drop table t1; SET SESSION debug="+d,maria_flush_whole_log,maria_crash";
* TEST of removing logs manually * crashing mysqld intentionally
* shut down mysqld, removed logs, restarted it set global maria_checkpoint_interval=1;
ERROR HY000: Lost connection to MySQL server during query
* recovery happens
check table t1 extended;
Table Op Msg_type Msg_text
mysqltest.t1 check status OK
* testing that checksum after recovery is as expected
Checksum-check
ok
use mysqltest; use mysqltest;
create table t1 (a varchar(1000)) engine=maria; drop table t1;
insert into t1 values ("00000000"); * TEST of checkpoint
set global debug="+d,info,query,enter,exit,loop,maria_checkpoint_indirect";
set global maria_checkpoint_interval=10000;
create table t1(a int, b varchar(10), index(a,b)) engine=maria;
insert into t1 values(1,"a"),(2,"b"),(3,"c");
delete from t1 where b="b";
update t1 set b="d" where a=1;
flush table t1; flush table t1;
* copied t1 for comparison * copied t1 for comparison
lock tables t1 write; lock tables t1 write;
insert into t1 values ("aaaaaaaaa"); insert into t1 values(4,"e"),(5,"f"),(6,"g");
SET SESSION debug="+d,maria_flush_whole_log,maria_crash"; update t1 set b="h" where a=5;
delete from t1 where b="g";
show status like "Maria_pagecache_blocks_not_flushed";
Variable_name Value
Maria_pagecache_blocks_not_flushed 3
set global maria_checkpoint_interval=10000;
update t1 set b="i" where a=5;
SET SESSION debug="+d,maria_crash";
* crashing mysqld intentionally * crashing mysqld intentionally
set global maria_checkpoint_interval=1; set global maria_checkpoint_interval=1;
ERROR HY000: Lost connection to MySQL server during query ERROR HY000: Lost connection to MySQL server during query
......
...@@ -205,6 +205,35 @@ delete from t1 where a in (1,2,3); ...@@ -205,6 +205,35 @@ delete from t1 where a in (1,2,3);
-- source include/maria_verify_recovery.inc -- source include/maria_verify_recovery.inc
drop table t1; drop table t1;
# A basic checkpoint test
--echo * TEST of checkpoint
# Don't take a full checkpoints, we want to test checkpoint vs dirty pages
set global debug="+d,info,query,enter,exit,loop,maria_checkpoint_indirect";
# restart checkpoint thread for it to notice the above
set global maria_checkpoint_interval=10000;
create table t1(a int, b varchar(10), index(a,b)) engine=maria;
insert into t1 values(1,"a"),(2,"b"),(3,"c");
delete from t1 where b="b";
update t1 set b="d" where a=1;
-- source include/maria_make_snapshot_for_comparison.inc
lock tables t1 write;
insert into t1 values(4,"e"),(5,"f"),(6,"g");
update t1 set b="h" where a=5;
delete from t1 where b="g";
show status like "Maria_pagecache_blocks_not_flushed";
# force a checkpoint; there should be dirty pages and an open transaction
set global maria_checkpoint_interval=10000;
# do some more work
update t1 set b="i" where a=5;
let $mvr_restore_old_snapshot=0;
let $mms_compare_physically=0;
let $mvr_debug_option="+d,maria_crash";
let $mvr_crash_statement= set global maria_checkpoint_interval=1;
# Now we have a recovery, which should use the checkpoint record
# and its dirty pages list.
-- source include/maria_verify_recovery.inc
drop table t1;
# clean up everything # clean up everything
let $mms_purpose=feeding_recovery; let $mms_purpose=feeding_recovery;
eval drop database mysqltest_for_$mms_purpose; eval drop database mysqltest_for_$mms_purpose;
......
...@@ -161,18 +161,6 @@ static inline my_bool write_changed_bitmap(MARIA_SHARE *share, ...@@ -161,18 +161,6 @@ static inline my_bool write_changed_bitmap(MARIA_SHARE *share,
} }
else else
{ {
/**
@todo RECOVERY BUG
Not flushable: its content is not reflected by the log, to honour WAL we
must keep the bitmap page pinned. Scenario of INSERT:
REDO - UNDO (written to log but not forced)
bitmap goes to page cache (because other INSERT needs to)
and then to disk (pagecache eviction)
crash: recovery will not find REDO-UNDO, table is corrupted.
Solutions:
give LSNs to bitmap pages or change pagecache to flush all log when
flushing a bitmap page or keep bitmap page pinned until checkpoint.
*/
MARIA_PINNED_PAGE page_link; MARIA_PINNED_PAGE page_link;
int res= pagecache_write(share->pagecache, int res= pagecache_write(share->pagecache,
&bitmap->file, bitmap->page, 0, &bitmap->file, bitmap->page, 0,
...@@ -221,7 +209,6 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file) ...@@ -221,7 +209,6 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file)
bitmap->block_size= share->block_size; bitmap->block_size= share->block_size;
bitmap->file.file= file; bitmap->file.file= file;
bitmap->file.write_fail= &maria_page_write_failure; aaaaa
_ma_bitmap_set_pagecache_callbacks(&bitmap->file, share); _ma_bitmap_set_pagecache_callbacks(&bitmap->file, share);
/* Size needs to be aligned on 6 */ /* Size needs to be aligned on 6 */
...@@ -2196,6 +2183,11 @@ void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc) ...@@ -2196,6 +2183,11 @@ void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc)
info->non_flushable_state= 0; info->non_flushable_state= 0;
if (--bitmap->non_flushable == 0) if (--bitmap->non_flushable == 0)
{ {
/*
We unlock and unpin pages locked and pinned by other threads. It does
not seem to be an issue as all bitmap changes are serialized with
the bitmap's mutex.
*/
_ma_bitmap_unpin_all(share); _ma_bitmap_unpin_all(share);
if (unlikely(bitmap->flush_all_requested)) if (unlikely(bitmap->flush_all_requested))
{ {
...@@ -2610,12 +2602,15 @@ void _ma_bitmap_set_pagecache_callbacks(PAGECACHE_FILE *file, ...@@ -2610,12 +2602,15 @@ void _ma_bitmap_set_pagecache_callbacks(PAGECACHE_FILE *file,
{ {
if (share->temporary) if (share->temporary)
pagecache_file_init(*file, &maria_page_crc_check_none, pagecache_file_init(*file, &maria_page_crc_check_none,
&maria_page_filler_set_none, NULL, share); &maria_page_filler_set_none,
&maria_page_write_failure,
NULL, share);
else else
pagecache_file_init(*file, &maria_page_crc_check_bitmap, pagecache_file_init(*file, &maria_page_crc_check_bitmap,
((share->options & HA_OPTION_PAGE_CHECKSUM) ? ((share->options & HA_OPTION_PAGE_CHECKSUM) ?
&maria_page_crc_set_normal : &maria_page_crc_set_normal :
&maria_page_filler_set_bitmap), &maria_page_filler_set_bitmap),
&maria_page_write_failure,
share->now_transactional ? share->now_transactional ?
&_ma_bitmap_get_log_address : NULL, share); &_ma_bitmap_get_log_address : NULL, share);
} }
...@@ -446,7 +446,13 @@ my_bool _ma_once_end_block_record(MARIA_SHARE *share) ...@@ -446,7 +446,13 @@ my_bool _ma_once_end_block_record(MARIA_SHARE *share)
share->bitmap.file.file= -1; share->bitmap.file.file= -1;
} }
if (share->id != 0) if (share->id != 0)
{
/*
We de-assign the id even though index has not been flushed, this is ok
as intern_lock serializes us with a Checkpoint looking at our share.
*/
translog_deassign_id_from_share(share); translog_deassign_id_from_share(share);
}
return res; return res;
} }
......
...@@ -1540,15 +1540,17 @@ void set_data_pagecache_callbacks(PAGECACHE_FILE *file, MARIA_SHARE *share) ...@@ -1540,15 +1540,17 @@ void set_data_pagecache_callbacks(PAGECACHE_FILE *file, MARIA_SHARE *share)
them. On the other hand, index file can always have page CRCs, for all them. On the other hand, index file can always have page CRCs, for all
data formats. data formats.
*/ */
file->write_fail= &maria_page_write_failure;
if (share->temporary) if (share->temporary)
pagecache_file_init(*file, &maria_page_crc_check_none, pagecache_file_init(*file, &maria_page_crc_check_none,
&maria_page_filler_set_none, NULL, share); &maria_page_filler_set_none,
&maria_page_write_failure,
NULL, share);
else else
pagecache_file_init(*file, &maria_page_crc_check_data, pagecache_file_init(*file, &maria_page_crc_check_data,
((share->options & HA_OPTION_PAGE_CHECKSUM) ? ((share->options & HA_OPTION_PAGE_CHECKSUM) ?
&maria_page_crc_set_normal : &maria_page_crc_set_normal :
&maria_page_filler_set_normal), &maria_page_filler_set_normal),
&maria_page_write_failure,
share->now_transactional ? share->now_transactional ?
&maria_page_get_lsn : NULL, share); &maria_page_get_lsn : NULL, share);
} }
...@@ -1556,15 +1558,17 @@ void set_data_pagecache_callbacks(PAGECACHE_FILE *file, MARIA_SHARE *share) ...@@ -1556,15 +1558,17 @@ void set_data_pagecache_callbacks(PAGECACHE_FILE *file, MARIA_SHARE *share)
void set_index_pagecache_callbacks(PAGECACHE_FILE *file, MARIA_SHARE *share) void set_index_pagecache_callbacks(PAGECACHE_FILE *file, MARIA_SHARE *share)
{ {
no write_fail set here?
if (share->temporary) if (share->temporary)
pagecache_file_init(*file, &maria_page_crc_check_none, pagecache_file_init(*file, &maria_page_crc_check_none,
&maria_page_filler_set_none, NULL, share); &maria_page_filler_set_none,
&maria_page_write_failure,
NULL, share);
else else
pagecache_file_init(*file, &maria_page_crc_check_index, pagecache_file_init(*file, &maria_page_crc_check_index,
((share->options & HA_OPTION_PAGE_CHECKSUM) ? ((share->options & HA_OPTION_PAGE_CHECKSUM) ?
&maria_page_crc_set_index : &maria_page_crc_set_index :
&maria_page_filler_set_normal), &maria_page_filler_set_normal),
&maria_page_write_failure,
share->now_transactional ? share->now_transactional ?
&maria_page_get_lsn : NULL, &maria_page_get_lsn : NULL,
share); share);
......
...@@ -3683,6 +3683,12 @@ static int flush_cached_blocks(PAGECACHE *pagecache, ...@@ -3683,6 +3683,12 @@ static int flush_cached_blocks(PAGECACHE *pagecache,
@todo IO If page is contiguous with next page to flush, group flushes @todo IO If page is contiguous with next page to flush, group flushes
in one single my_pwrite(). in one single my_pwrite().
*/ */
/*
It is important to use block->hash_link->file below and not 'file', as
the first one is right and the second may have different content (and
this matters for callbacks, bitmap pages and data pages have different
ones).
*/
error= pagecache_fwrite(pagecache, &block->hash_link->file, error= pagecache_fwrite(pagecache, &block->hash_link->file,
block->buffer, block->buffer,
block->hash_link->pageno, block->hash_link->pageno,
...@@ -3741,6 +3747,10 @@ static int flush_cached_blocks(PAGECACHE *pagecache, ...@@ -3741,6 +3747,10 @@ static int flush_cached_blocks(PAGECACHE *pagecache,
@param filter_arg an argument to pass to 'filter'. Information about @param filter_arg an argument to pass to 'filter'. Information about
the block will be passed too. the block will be passed too.
@note
Flushes all blocks having the same OS file descriptor as 'file->file', so
can flush blocks having '*block->hash_link->file' != '*file'.
@note @note
This function doesn't do any mutex locks because it needs to be called This function doesn't do any mutex locks because it needs to be called
both from flush_pagecache_blocks and flush_all_key_blocks (the later one both from flush_pagecache_blocks and flush_all_key_blocks (the later one
......
...@@ -88,7 +88,7 @@ typedef struct st_pagecache_file ...@@ -88,7 +88,7 @@ typedef struct st_pagecache_file
my_bool (*write_callback)(uchar *page, pgcache_page_no_t offset, my_bool (*write_callback)(uchar *page, pgcache_page_no_t offset,
uchar *data); uchar *data);
void (*write_fail)(uchar *data); void (*write_fail)(uchar *data);
/** Can be NULL */ or use dummy /** Can be NULL */
TRANSLOG_ADDRESS (*get_log_address_callback) TRANSLOG_ADDRESS (*get_log_address_callback)
(uchar *page, pgcache_page_no_t offset, uchar *data); (uchar *page, pgcache_page_no_t offset, uchar *data);
uchar *callback_data; uchar *callback_data;
......
...@@ -352,14 +352,14 @@ sub run_tests_on_clrs ...@@ -352,14 +352,14 @@ sub run_tests_on_clrs
"rm test2.MA?" "rm test2.MA?"
); );
my @t3= ("ma_test2 -s -L -K -W -P -M -T -c -b32768 -t4 -A1", my @t3= ("$maria_path/ma_test2 -s -L -K -W -P -M -T -c -b32768 -t4 -A1",
"maria_read_log -a -s", "$maria_path/maria_read_log -a -s",
"maria_chk -es test2", "$maria_path/maria_chk -es test2",
"maria_read_log -a -s", "$maria_path/maria_read_log -a -s",
"maria_chk -es test2", "$maria_path/maria_chk -es test2",
"rm test2.MA?", "rm test2.MA?",
"maria_read_log -a -s", "$maria_path/maria_read_log -a -s",
"maria_chk -es test2", "$maria_path/maria_chk -es test2",
"rm test2.MA?" "rm test2.MA?"
); );
......
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