2006-04-11 15:45:10 +02:00
/* Copyright (C) 2006-2003 MySQL AB
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
2007-03-02 11:20:23 +01:00
the Free Software Foundation ; version 2 of the License .
2006-04-11 15:45:10 +02:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA */
/* Describe, check and repair of MARIA tables */
# include "ma_fulltext.h"
# include <myisamchk.h>
2006-08-11 01:16:51 +02:00
# include <my_bit.h>
2006-04-11 15:45:10 +02:00
# include <m_ctype.h>
# include <stdarg.h>
# include <my_getopt.h>
# ifdef HAVE_SYS_VADVICE_H
# include <sys/vadvise.h>
# endif
# ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
# endif
SET_STACK_SIZE ( 9000 ) /* Minimum stack size for program */
# ifndef USE_RAID
# define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G)
# define my_raid_delete(A,B,C) my_delete(A,B)
# endif
static uint decode_bits ;
static char * * default_argv ;
2007-01-18 20:38:14 +01:00
static const char * load_default_groups [ ] = { " maria_chk " , 0 } ;
2006-04-11 15:45:10 +02:00
static const char * set_collation_name , * opt_tmpdir ;
static CHARSET_INFO * set_collation ;
static int stopwords_inited = 0 ;
2007-01-18 20:38:14 +01:00
static MY_TMPDIR maria_chk_tmpdir ;
2008-01-07 17:54:41 +01:00
static my_bool opt_transaction_logging , opt_debug ;
2006-04-11 15:45:10 +02:00
static const char * type_names [ ] =
2007-01-18 20:38:14 +01:00
{
" impossible " , " char " , " binary " , " short " , " long " , " float " ,
2006-04-11 15:45:10 +02:00
" double " , " number " , " unsigned short " ,
" unsigned long " , " longlong " , " ulonglong " , " int24 " ,
2007-04-19 12:18:56 +02:00
" uint24 " , " int8 " , " varchar " , " varbin " , " varchar2 " , " varbin2 " , " bit " ,
" ? " , " ? "
2007-01-18 20:38:14 +01:00
} ;
2006-04-11 15:45:10 +02:00
static const char * prefix_packed_txt = " packed " ,
* bin_packed_txt = " prefix " ,
* diff_txt = " stripped " ,
* null_txt = " NULL " ,
* blob_txt = " BLOB " ;
static const char * field_pack [ ] =
2007-01-18 20:38:14 +01:00
{
" " , " no endspace " , " no prespace " ,
2006-04-11 15:45:10 +02:00
" no zeros " , " blob " , " constant " , " table-lockup " ,
2007-01-18 20:38:14 +01:00
" always zero " , " varchar " , " unique-hash " , " ? " , " ? "
} ;
static const char * record_formats [ ] =
First part of redo/undo for key pages
Added key_nr to st_maria_keydef for faster keyinfo->keynr conversion
For transactional tables, shift record number in keys up with 1 bit to have place to indicate if transid follows
Checksum for MyISAM now ignores NULL and not used part of VARCHAR
Renamed some variables that caused shadow compiler warnings
Moved extra() call when waiting for tables to not be used to after tables are removed from cache.
Fixed crashing bugs when using Maria TEMPORARY tables with TRUNCATE. Removed 'hack' code in sql directory to go around this bug.
pagecache_unlock_by_ulink() now has extra argument to say if page was changed.
Give error message if we fail to open control file
Mark page cache variables as not flushable
include/maria.h:
Made min page cache larger (needed for pinning key page)
Added key_nr to st_maria_keydef for faster keyinfo->keynr conversion
Added write_comp_flag to move some runtime code to maria_open()
include/my_base.h:
Added new error message to be used when handler initialization failed
include/my_global.h:
Renamed dummy to swap_dummy to avoid conflicts with local 'dummy' variables
include/my_handler.h:
Added const to some parameters
mysys/array.c:
More DBUG
mysys/my_error.c:
Fixed indentation
mysys/my_handler.c:
Added const to some parameters
Added missing error messages
sql/field.h:
Renamed variables to avoid variable shadowing
sql/handler.h:
Renamed parameter to avoid variable name conflict
sql/item.h:
Renamed variables to avoid variable shadowing
sql/log_event_old.h:
Renamed variables to avoid variable shadowing
sql/set_var.h:
Renamed variables to avoid variable shadowing
sql/sql_delete.cc:
Removed maria hack for temporary tables
Fixed indentation
sql/sql_table.cc:
Moved extra() call when waiting for tables to not be used to after tables are removed from cache.
This was needed to ensure we don't do a PREPARE_FOR_DROP or similar call while the table is still in use.
sql/table.cc:
Copy page_checksum from share
Removed Maria hack
storage/maria/Makefile.am:
Added new files
storage/maria/ha_maria.cc:
Renamed records -> record_count and info -> create_info to avoid variable name conflicts
Mark page cache variables as not flushable
storage/maria/ma_blockrec.c:
Moved _ma_unpin_all_pages() to ma_key_recover.c
Moved init of info->pinned_pages to ma_open.c
Moved _ma_finalize_row() to maria_key_recover.h
Renamed some variables to avoid variable name conflicts
Mark page_link.changed for blocks we change directly
Simplify handling of undo link when writing LOGREC_UNDO_ROW_INSERT (old code crashed when having redo for index)
storage/maria/ma_blockrec.h:
Removed extra empty line
storage/maria/ma_checkpoint.c:
Remove not needed trnman.h
storage/maria/ma_close.c:
Free pinned pages (which are now always allocated)
storage/maria/ma_control_file.c:
Give error message if we fail to open control file
storage/maria/ma_delete.c:
Changes for redo logging (first part, logging of underflow not yet done)
- Log undo-key-delete
- Log delete of key
- Updated arguments to _ma_fetch_keypage(), _ma_dispose(), _ma_write_keypage(), _ma_insert()
- Added new arguments to some functions to be able to write redo information
- Mark key pages as changed when we write with PAGECACHE_LOCK_LEFT_WRITELOCKED
Remove one not needed _ma_write_keypage() in d_search() when upper level will do the write anyway
Changed 2 bmove_upp() to bmove() as this made code easer to understand
More function comments
Indentation fixes
storage/maria/ma_ft_update.c:
New arguments to _ma_write_keypage()
storage/maria/ma_loghandler.c:
Fixed some DBUG_PRINT messages
Simplify code
Added new log entrys for key page redo
Renamed some variables to avoid variable name shadowing
storage/maria/ma_loghandler.h:
Moved some defines here
Added define for storing key number on key pages
Added new translog record types
Added enum for type of operations in LOGREC_REDO_INDEX
storage/maria/ma_open.c:
Always allocate info.pinned_pages (we need now also for normal key page usage)
Update keyinfo->key_nr
Added virtual functions to convert record position o number to be stored on key pages
Update keyinfo->write_comp_flag to value of search flag to be used when writing key
storage/maria/ma_page.c:
Added redo for key pages
- Extended _ma_fetch_keypage() with type of lock to put on page and address to used MARIA_PINNED_PAGE
- _ma_fetch_keypage() now pin's pages if needed
- Extended _ma_write_keypage() with type of locks to be used
- ma_dispose() now locks info->s->state.key_del from other threads
- ma_dispose() writes redo log record
- ma_new() locks info->s->state.key_del from other threads if it was used
- ma_new() now pins read page
Other things:
- Removed some not needed arguments from _ma_new() and _ma_dispose)
- Added some new variables to simplify code
- If EXTRA_DEBUG is used, do crc on full page to catch not unitialized bytes
storage/maria/ma_pagecache.h:
Applied patch from Sanja to add extra argument to pagecache_unlock_by_ulink() to mark if page was changed
Added some defines for pagecache priority levels that one can use
storage/maria/ma_range.c:
Added new arguments for call to _ma_fetch_keypage()
storage/maria/ma_recovery.c:
- Added hooks for new translog types:
REDO_INDEX, REDO_INDEX_NEW_PAGE, REDO_INDEX_FREE_PAGE, UNDO_KEY_INSERT, UNDO_KEY_DELETE and
UNDO_KEY_DELETE_WITH_ROOT.
- Moved variable declarations to start of function (portability fixes)
- Removed some not needed initializations
- Set only relevant state changes for each redo/undo entry
storage/maria/lockman.c:
Removed end space
storage/maria/ma_check.c:
Removed end space
storage/maria/ma_create.c:
Removed end space
storage/maria/ma_locking.c:
Removed end space
storage/maria/ma_packrec.c:
Removed end space
storage/maria/ma_pagecache.c:
Removed end space
storage/maria/ma_panic.c:
Removed end space
storage/maria/ma_rt_index.c:
Added new arguments for call to _ma_fetch_keypage(), _ma_write_keypage(), _ma_dispose() and _ma_new()
Fixed indentation
storage/maria/ma_rt_key.c:
Added new arguments for call to _ma_fetch_keypage()
storage/maria/ma_rt_split.c:
Added new arguments for call to _ma_new()
Use new keypage header
Added new arguments for call to _ma_write_keypage()
storage/maria/ma_search.c:
Updated comments & indentation
Added new arguments for call to _ma_fetch_keypage()
Made some variables and arguments const
Added virtual functions for converting row position to number to be stored in key
use MARIA_RECORD_POS of record position instead of my_off_t
Record in MARIA_KEY_PARAM how page was changed one key insert (needed for REDO)
storage/maria/ma_sort.c:
Removed end space
storage/maria/ma_statrec.c:
Updated arguments for call to _ma_rec_pos()
storage/maria/ma_test1.c:
Fixed too small buffer to init_pagecache()
Fixed bug when using insert_count and test_flag
storage/maria/ma_test2.c:
Use more resonable pagecache size
Remove not used code
Reset blob_length to fix wrong output message
storage/maria/ma_test_all.sh:
Fixed wrong test
storage/maria/ma_write.c:
Lots of new code to handle REDO of key pages
No logic changes because of REDO code, mostly adding new arguments and adding new code for logging
Added new arguments for calls to _ma_fetch_keypage(), _ma_write_keypage() and similar functions
Move setting of comp_flag in ma_ck_wrte_btree() from runtime to maria_open()
Zerofill new used pages for:
- To remove possible sensitive data left in buffer
- To get idenitical data on pages after running redo
- Better compression of pages if archived
storage/maria/maria_chk.c:
Added information if table is crash safe
storage/maria/maria_def.h:
New virtual function to convert between record position on key and normal record position
Aded mutex and extra variables to handle locking of share->state.key_del
Moved some structure variables to get things more aligned
Added extra arguments to MARIA_KEY_PARAM to be able to remember what was changed on key page on key insert
Added argument to MARIA_PINNED_PAGE to indicate if page was changed
Updated prototypes for functions
Added some structures for signaling changes in REDO handling
storage/maria/unittest/ma_pagecache_single.c:
Updated arguments for changed function calls
storage/myisam/mi_check.c:
Made calc_check_checksum virtual
storage/myisam/mi_checksum.c:
Update checksums to ignore null columns
storage/myisam/mi_create.c:
Mark if table has null column (to know when we have to use mi_checksum())
storage/myisam/mi_open.c:
Added virtual function for calculating checksum to be able to easily ignore NULL fields
storage/myisam/mi_test2.c:
Fixed bug
storage/myisam/myisamdef.h:
Added virtual function for calculating checksum during check table
Removed ha_key_cmp() as this is in handler.h
storage/maria/ma_key_recover.c:
New BitKeeper file ``storage/maria/ma_key_recover.c''
storage/maria/ma_key_recover.h:
New BitKeeper file ``storage/maria/ma_key_recover.h''
storage/maria/ma_key_redo.c:
New BitKeeper file ``storage/maria/ma_key_redo.c''
2007-11-14 18:08:06 +01:00
{
2007-01-18 20:38:14 +01:00
" Fixed length " , " Packed " , " Compressed " , " Block " , " ? "
} ;
2006-04-11 15:45:10 +02:00
static const char * maria_stats_method_str = " nulls_unequal " ;
WL#3072 - Maria Recovery
Bulk insert: don't log REDO/UNDO for rows, log one UNDO which will
truncate files; this is an optimization and a bugfix (table was left
half-repaired by crash).
Repair: mark table crashed-on-repair at start, bump skip_redo_lsn at start,
this is easier for recovery (tells it to skip old REDOs or even UNDO
phase) and user (tells it to repair) in case of crash, sync files
in the end.
Recovery skips missing or corrupted table and moves to next record
(in REDO or UNDO phase) to be more robust; warns if happens in UNDO phase.
Bugfix for UNDO_KEY_DELETE_WITH_ROOT (tested in ma_test_recovery)
and maria_enable_indexes().
Create missing bitmaps when needed (there can be more than one to create,
in rare cases), log a record for this.
include/myisamchk.h:
new flag: bulk insert repair mustn't bump create_rename_lsn
mysql-test/lib/mtr_report.pl:
skip normal warning in maria-recovery.test
mysql-test/r/maria-recovery.result:
result: crash before bulk insert is committed, causes proper rollback,
and crash right after OPTIMIZE replaces index file with new index file
leads to table marked corrupted and recovery not failing.
mysql-test/t/maria-recovery.test:
- can't check the table or it would commit the transaction,
but check is made after recovery.
- test of crash before bulk-insert-with-repair is committed
(to see if it is rolled back), and of crash after OPTIMIZE has replaced
index file but not finished all operations (to see if recovery fails -
it used to assert when trying to execute an old REDO on the new
index).
storage/maria/CMakeLists.txt:
new file
storage/maria/Makefile.am:
new file
storage/maria/ha_maria.cc:
- If bulk insert on a transactional table using an index repair:
table is initially empty, so don't log REDO/UNDO for data rows
(optimization), just log an UNDO_BULK_INSERT_WITH_REPAIR
which will, if executed, empty the data and index file. Re-enable
logging in end_bulk_insert().
- write log record for repair operation only after it's fully done,
index sort including (maria_repair*() used to write the log record).
- Adding back file->trn=NULL which was removed by mistake earlier.
storage/maria/ha_maria.h:
new member (see ha_maria.cc)
storage/maria/ma_bitmap.c:
Functions to create missing bitmaps:
- one function which creates missing bitmaps in page cache, except
the missing one with max offset which it does not put into page cache
as it will be modified very soon.
- one function which the one above calls, and creates bitmaps in page
cache
- one function to execute REDO_BITMAP_NEW_PAGE which uses the second
one above.
storage/maria/ma_blockrec.c:
- when logging REDO_DELETE_ALL, not only 'records' and 'checksum'
has to be reset under log's mutex.
- execution of REDO_INSERT_ROW_BLOBS now checks the dirty pages' list
- execution of UNDO_BULK_INSERT_WITH_REPAIR
storage/maria/ma_blockrec.h:
new functions
storage/maria/ma_check.c:
- table-flush-before-repair is moved to a separate function reused
by maria_sort_index(); syncing is added
- maria_repair() is allowed to re-enable logging only if it is the one
which disabled it.
- "_ma_flush_table_files_after_repair" was a bad name, it's not after
repair now, and it should not sync as we do more changes to the files
shortly after (sync is postponed to when writing the log record)
- REDO_REPAIR record should be written only after all repair
operations (in particular after sorting index in ha_mara::repair())
- close to the end of repair by sort, flushing of pages must happen
also in the non-quick case, to prepare for the sync at end.
- in parallel repair, some page flushes are not needed as done
by initialize_variables_for_repair().
storage/maria/ma_create.c:
Update skip_redo_lsn, create_rename_lsn optionally.
storage/maria/ma_delete_all.c:
Need to sync files at end of maria_delete_all_rows(), if transactional.
storage/maria/ma_extra.c:
During repair, we sometimes call _ma_flush_table_files() (via
_ma_flush_table_files_before_swap()) while there is a WRITE_CACHE.
storage/maria/ma_key_recover.c:
- when we see CLR_END for UNDO_BULK_INSERT_WITH_REPAIR, re-enable
indices.
- fixing bug: _ma_apply_undo_key_delete() parsed UNDO_KEY_DELETE_WITH_ROOT
wrongly, leading to recovery failure
storage/maria/ma_key_recover.h:
new prototype
storage/maria/ma_locking.c:
DBUG_VOID_RETURN missing
storage/maria/ma_loghandler.c:
UNDO for bulk insert with repair, and REDO for creating bitmaps.
LOGREC_FIRST_FREE to not have to change the for() every time we
add a new record type.
storage/maria/ma_loghandler.h:
new UNDO and REDO
storage/maria/ma_open.c:
Move share.kfile.file=kfile up a bit, so that _ma_update_state_lsns()
can get its value, this fixes a bug where LSN_REPAIRED_BY_MARIA_CHK
was not corrected on disk by maria_open().
Store skip_redo_lsn in index' header.
maria_enable_indexes() had a bug for BLOCK_RECORD, where an empty
file has one page, not 0 bytes.
storage/maria/ma_recovery.c:
- Skip a corrupted, missing, or repaired-with-maria_chk, table in
recovery: don't fail, just go to next REDO or UNDO; but if an UNDO
is skipped in UNDO phase we issue warnings.
- Skip REDO|UNDO in REDO phase if <skip_redo_lsn.
- If UNDO phase fails, delete transactions to not make trnman
assert.
- Update skip_redo_lsn when playing REDO_CREATE_TABLE
- Don't record UNDOs for old transactions which we don't know (long_trid==0)
- Bugfix for UNDO_KEY_DELETE_WITH_ROOT (see ma_key_recover.c)
- Execution of UNDO_BULK_INSERT_WITH_REPAIR
- Don't try to find a page number in REDO_DELETE_ALL
- Pieces moved to ma_recovery_util.c
storage/maria/ma_rename.c:
name change
storage/maria/ma_static.c:
I modified layout of the index' header (inserted skip_redo_lsn in its middle)
storage/maria/ma_test2.c:
allow breaking the test towards the end, tests execution of
UNDO_KEY_DELETE_WITH_ROOT
storage/maria/ma_test_recovery.expected:
6 as testflag instead of 4
storage/maria/ma_test_recovery:
Increase the amount of rollback work to do when testing recovery
with ma_test2; this reproduces the UNDO_KEY_DELETE_WITH_ROOT bug.
storage/maria/maria_chk.c:
skip_redo_lsn should be updated too, for consistency.
Write a REDO_REPAIR after all operations (including sort-records)
have been done.
No reason to flush blocks after maria_chk_data_link() and
maria_sort_records(), there is maria_close() in the end.
write_log_record() is a function, to not clutter maria_chk().
storage/maria/maria_def.h:
New member skip_redo_lsn in the state, and comments
storage/maria/maria_pack.c:
skip_redo_lsn should be updated too, for consistency
storage/maria/ma_recovery_util.c:
_ma_redo_not_needed_for_page(), defined in ma_recovery.c, is needed
by ma_blockrec.c; this causes link issues, resolved by putting
_ma_redo_not_needed_for_page() into a new file (so that it is not
in the same file as repair-related objects of ma_recovery.c).
storage/maria/ma_recovery_util.h:
new file
2008-01-17 23:59:32 +01:00
static char default_open_errmsg [ ] = " %d when opening MARIA-table '%s' " ;
static char default_close_errmsg [ ] = " %d when closing MARIA-table '%s' " ;
2006-04-11 15:45:10 +02:00
static void get_options ( int * argc , char * * * argv ) ;
static void print_version ( void ) ;
static void usage ( void ) ;
2007-01-18 20:38:14 +01:00
static int maria_chk ( HA_CHECK * param , char * filename ) ;
2007-07-02 19:45:15 +02:00
static void descript ( HA_CHECK * param , register MARIA_HA * info , char * name ) ;
2006-04-11 15:45:10 +02:00
static int maria_sort_records ( HA_CHECK * param , register MARIA_HA * info ,
2007-07-02 19:45:15 +02:00
char * name , uint sort_key ,
2007-01-18 20:38:14 +01:00
my_bool write_info , my_bool update_index ) ;
2006-04-11 15:45:10 +02:00
static int sort_record_index ( MARIA_SORT_PARAM * sort_param , MARIA_HA * info ,
MARIA_KEYDEF * keyinfo ,
2007-07-02 19:45:15 +02:00
my_off_t page , uchar * buff , uint sortkey ,
2006-04-11 15:45:10 +02:00
File new_file , my_bool update_index ) ;
WL#3072 - Maria Recovery
Bulk insert: don't log REDO/UNDO for rows, log one UNDO which will
truncate files; this is an optimization and a bugfix (table was left
half-repaired by crash).
Repair: mark table crashed-on-repair at start, bump skip_redo_lsn at start,
this is easier for recovery (tells it to skip old REDOs or even UNDO
phase) and user (tells it to repair) in case of crash, sync files
in the end.
Recovery skips missing or corrupted table and moves to next record
(in REDO or UNDO phase) to be more robust; warns if happens in UNDO phase.
Bugfix for UNDO_KEY_DELETE_WITH_ROOT (tested in ma_test_recovery)
and maria_enable_indexes().
Create missing bitmaps when needed (there can be more than one to create,
in rare cases), log a record for this.
include/myisamchk.h:
new flag: bulk insert repair mustn't bump create_rename_lsn
mysql-test/lib/mtr_report.pl:
skip normal warning in maria-recovery.test
mysql-test/r/maria-recovery.result:
result: crash before bulk insert is committed, causes proper rollback,
and crash right after OPTIMIZE replaces index file with new index file
leads to table marked corrupted and recovery not failing.
mysql-test/t/maria-recovery.test:
- can't check the table or it would commit the transaction,
but check is made after recovery.
- test of crash before bulk-insert-with-repair is committed
(to see if it is rolled back), and of crash after OPTIMIZE has replaced
index file but not finished all operations (to see if recovery fails -
it used to assert when trying to execute an old REDO on the new
index).
storage/maria/CMakeLists.txt:
new file
storage/maria/Makefile.am:
new file
storage/maria/ha_maria.cc:
- If bulk insert on a transactional table using an index repair:
table is initially empty, so don't log REDO/UNDO for data rows
(optimization), just log an UNDO_BULK_INSERT_WITH_REPAIR
which will, if executed, empty the data and index file. Re-enable
logging in end_bulk_insert().
- write log record for repair operation only after it's fully done,
index sort including (maria_repair*() used to write the log record).
- Adding back file->trn=NULL which was removed by mistake earlier.
storage/maria/ha_maria.h:
new member (see ha_maria.cc)
storage/maria/ma_bitmap.c:
Functions to create missing bitmaps:
- one function which creates missing bitmaps in page cache, except
the missing one with max offset which it does not put into page cache
as it will be modified very soon.
- one function which the one above calls, and creates bitmaps in page
cache
- one function to execute REDO_BITMAP_NEW_PAGE which uses the second
one above.
storage/maria/ma_blockrec.c:
- when logging REDO_DELETE_ALL, not only 'records' and 'checksum'
has to be reset under log's mutex.
- execution of REDO_INSERT_ROW_BLOBS now checks the dirty pages' list
- execution of UNDO_BULK_INSERT_WITH_REPAIR
storage/maria/ma_blockrec.h:
new functions
storage/maria/ma_check.c:
- table-flush-before-repair is moved to a separate function reused
by maria_sort_index(); syncing is added
- maria_repair() is allowed to re-enable logging only if it is the one
which disabled it.
- "_ma_flush_table_files_after_repair" was a bad name, it's not after
repair now, and it should not sync as we do more changes to the files
shortly after (sync is postponed to when writing the log record)
- REDO_REPAIR record should be written only after all repair
operations (in particular after sorting index in ha_mara::repair())
- close to the end of repair by sort, flushing of pages must happen
also in the non-quick case, to prepare for the sync at end.
- in parallel repair, some page flushes are not needed as done
by initialize_variables_for_repair().
storage/maria/ma_create.c:
Update skip_redo_lsn, create_rename_lsn optionally.
storage/maria/ma_delete_all.c:
Need to sync files at end of maria_delete_all_rows(), if transactional.
storage/maria/ma_extra.c:
During repair, we sometimes call _ma_flush_table_files() (via
_ma_flush_table_files_before_swap()) while there is a WRITE_CACHE.
storage/maria/ma_key_recover.c:
- when we see CLR_END for UNDO_BULK_INSERT_WITH_REPAIR, re-enable
indices.
- fixing bug: _ma_apply_undo_key_delete() parsed UNDO_KEY_DELETE_WITH_ROOT
wrongly, leading to recovery failure
storage/maria/ma_key_recover.h:
new prototype
storage/maria/ma_locking.c:
DBUG_VOID_RETURN missing
storage/maria/ma_loghandler.c:
UNDO for bulk insert with repair, and REDO for creating bitmaps.
LOGREC_FIRST_FREE to not have to change the for() every time we
add a new record type.
storage/maria/ma_loghandler.h:
new UNDO and REDO
storage/maria/ma_open.c:
Move share.kfile.file=kfile up a bit, so that _ma_update_state_lsns()
can get its value, this fixes a bug where LSN_REPAIRED_BY_MARIA_CHK
was not corrected on disk by maria_open().
Store skip_redo_lsn in index' header.
maria_enable_indexes() had a bug for BLOCK_RECORD, where an empty
file has one page, not 0 bytes.
storage/maria/ma_recovery.c:
- Skip a corrupted, missing, or repaired-with-maria_chk, table in
recovery: don't fail, just go to next REDO or UNDO; but if an UNDO
is skipped in UNDO phase we issue warnings.
- Skip REDO|UNDO in REDO phase if <skip_redo_lsn.
- If UNDO phase fails, delete transactions to not make trnman
assert.
- Update skip_redo_lsn when playing REDO_CREATE_TABLE
- Don't record UNDOs for old transactions which we don't know (long_trid==0)
- Bugfix for UNDO_KEY_DELETE_WITH_ROOT (see ma_key_recover.c)
- Execution of UNDO_BULK_INSERT_WITH_REPAIR
- Don't try to find a page number in REDO_DELETE_ALL
- Pieces moved to ma_recovery_util.c
storage/maria/ma_rename.c:
name change
storage/maria/ma_static.c:
I modified layout of the index' header (inserted skip_redo_lsn in its middle)
storage/maria/ma_test2.c:
allow breaking the test towards the end, tests execution of
UNDO_KEY_DELETE_WITH_ROOT
storage/maria/ma_test_recovery.expected:
6 as testflag instead of 4
storage/maria/ma_test_recovery:
Increase the amount of rollback work to do when testing recovery
with ma_test2; this reproduces the UNDO_KEY_DELETE_WITH_ROOT bug.
storage/maria/maria_chk.c:
skip_redo_lsn should be updated too, for consistency.
Write a REDO_REPAIR after all operations (including sort-records)
have been done.
No reason to flush blocks after maria_chk_data_link() and
maria_sort_records(), there is maria_close() in the end.
write_log_record() is a function, to not clutter maria_chk().
storage/maria/maria_def.h:
New member skip_redo_lsn in the state, and comments
storage/maria/maria_pack.c:
skip_redo_lsn should be updated too, for consistency
storage/maria/ma_recovery_util.c:
_ma_redo_not_needed_for_page(), defined in ma_recovery.c, is needed
by ma_blockrec.c; this causes link issues, resolved by putting
_ma_redo_not_needed_for_page() into a new file (so that it is not
in the same file as repair-related objects of ma_recovery.c).
storage/maria/ma_recovery_util.h:
new file
2008-01-17 23:59:32 +01:00
static my_bool write_log_record ( HA_CHECK * param ) ;
2006-04-11 15:45:10 +02:00
HA_CHECK check_param ;
/* Main program */
int main ( int argc , char * * argv )
{
int error ;
MY_INIT ( argv [ 0 ] ) ;
2008-01-30 07:01:45 +01:00
maria_data_root = ( char * ) " . " ;
2007-01-18 20:38:14 +01:00
maria_chk_init ( & check_param ) ;
2006-04-11 15:45:10 +02:00
check_param . opt_lock_memory = 1 ; /* Lock memory if possible */
check_param . using_global_keycache = 0 ;
get_options ( & argc , ( char * * * ) & argv ) ;
maria_quick_table_bits = decode_bits ;
error = 0 ;
maria_init ( ) ;
2007-12-10 02:23:15 +01:00
/*
WL#3072 - Maria recovery.
* fix for bitmap vs checkpoint bug which could lead to corrupted
tables in case of crashes at certain moments: a bitmap could be flushed
to disk even though it was inconsistent with the log (it could be
flushed before REDO-UNDO are written to the log). One bug remains, need
code from others. Tests added. Fix is to pin unflushable bitmap pages,
and let checkpoint wait for them to be flushable.
* fix for long_trid!=0 assertion failure at Recovery.
* less useless wakeups in the background flush|checkpoint thread.
* store global_trid_generator in checkpoint record.
mysql-test/r/maria-recovery.result:
result update
mysql-test/t/maria-recovery.test:
make it easier to locate subtests
storage/maria/ma_bitmap.c:
When we send a bitmap to the pagecache, if this bitmap is not in a
flushable state we keep it pinned and add it to a list, it will be
unpinned when the bitmap is flushable again.
A new function _ma_bitmap_flush_all() used by checkpoint.
A new function _ma_bitmap_flushable() used by block format to signal
when it starts modifying a bitmap and when it is done with it.
storage/maria/ma_blockrec.c:
When starting a row operation (insert/update/delete), mark that
the bitmap is not flushable (because for example INSERT is going
to over-allocate in the bitmap to prevent other threads from using
our data pages). If a checkpoint comes at this moment it will wait
for the bitmap to be flushable before flushing it.
When the operation ends, bitmap becomes flushable again; that
transition is done under the bitmap's mutex (needed for correct
synchro with a concurrent checkpoint); but for INSERT/UPDATE this
happens inside _ma_bitmap_release_unused() at a place where it already
has the mutex, so the only penalty (mutex adding) is in DELETE and UNDO
of INSERT. In case of errors after setting the bitmap unflushable,
we must always set it back to flushable or checkpoint would block.
Debug possibilities to force a sleep while the bitmap is over-allocated.
In case of error in get_head_or_tail() in allocate_and_write_block_record(),
we still need to unpin all pages.
Bugfix: _ma_apply_redo_insert_row_blobs() produced wrong
data_file_length.
storage/maria/ma_blockrec.h:
new bitmap calls.
storage/maria/ma_checkpoint.c:
filter_flush_indirect not needed anymore (flushing bitmap
pages happens in _ma_bitmap_flush_all() now). So
st_filter_param::is_data_file|pages_covered_by_bitmap not needed.
Other filter_flush* don't need to flush bitmap anymore.
Add debug possibility to flush all bitmap pages outside of a checkpoint,
to simulate pagecache LRU eviction.
When the background flush/checkpoint thread notices it has nothing
to flush, it now sleeps directly until the next potential checkpoint
moment instead of waking up every second.
When in checkpoint we decide to not store a table in the checkpoint record
(because it has logged no writes for example), we can also skip flushing
this table.
storage/maria/ma_commit.c:
comment is out-of-date
storage/maria/ma_key_recover.c:
comment fix
storage/maria/ma_loghandler.c:
comment is out-of-date
storage/maria/ma_open.c:
comment is out-of-date
storage/maria/ma_pagecache.c:
comment for bug to fix. And we don't take checkpoints at end of REDO
phase yet so can trust block->type.
storage/maria/ma_recovery.c:
Comments. Now-unneeded code for incomplete REDO-UNDO groups removed.
When we forget about an old transaction we must really forget
about it with bzero() (fixes the "long_trid!=0 assertion" recovery
bug). When we delete a row with maria_delete() we turn on
STATE_NOT_OPTIMIZED_ROWS so we do the same when we see a CLR_END
for an UNDO_ROW_INSERT or when we execute an UNDO_ROW_INSERT (in both
cases a row was deleted). Pick up max_long_trid from the checkpoint record.
storage/maria/maria_chk.c:
comment
storage/maria/maria_def.h:
MARIA_FILE_BITMAP gets new members: 'flushable', 'bitmap_cond' and
'pinned_pages'.
storage/maria/trnman.c:
I used to think that recovery only needs to know the maximum TrID
of the lists of active and committed transactions. But no, sometimes
both lists can even be empty and their TrID should not be reused.
So Checkpoint now saves global_trid_generator in the checkpoint record.
storage/maria/trnman_public.h:
macros to read/store a TrID
mysql-test/r/maria-recovery-bitmap.result:
result is ok. Without the code fix, we would get a corruption message
about the bitmap page in CHECK TABLE EXTENDED.
mysql-test/t/maria-recovery-bitmap-master.opt:
usual when we crash mysqld in tests
mysql-test/t/maria-recovery-bitmap.test:
test of recovery problems specific of the bitmap pages.
2007-12-14 16:14:12 +01:00
If we are doing a repair , user may want to store this repair into the log
so that the log has a complete history and can be used to replay .
2007-12-10 02:23:15 +01:00
*/
if ( opt_transaction_logging & & ( check_param . testflag & T_REP_ANY ) & &
( ma_control_file_create_or_open ( ) | |
init_pagecache ( maria_log_pagecache ,
TRANSLOG_PAGECACHE_SIZE , 0 , 0 ,
TRANSLOG_PAGE_SIZE , MY_WME ) = = 0 | |
translog_init ( maria_data_root , TRANSLOG_FILE_SIZE ,
0 , 0 , maria_log_pagecache ,
2007-12-15 18:16:41 +01:00
TRANSLOG_DEFAULT_FLAGS , 0 ) ) )
2007-12-10 02:23:15 +01:00
{
_ma_check_print_error ( & check_param ,
" Can't initialize transaction logging. Run "
" recovery with switch --skip-transaction-log " ) ;
error = 1 ;
argc = 1 ; /* Force loop out */
}
2006-04-11 15:45:10 +02:00
while ( - - argc > = 0 )
{
2007-01-18 20:38:14 +01:00
int new_error = maria_chk ( & check_param , * ( argv + + ) ) ;
2006-04-11 15:45:10 +02:00
if ( ( check_param . testflag & T_REP_ANY ) ! = T_REP )
check_param . testflag & = ~ T_REP ;
VOID ( fflush ( stdout ) ) ;
VOID ( fflush ( stderr ) ) ;
if ( ( check_param . error_printed | check_param . warning_printed ) & &
( check_param . testflag & T_FORCE_CREATE ) & &
( ! ( check_param . testflag & ( T_REP | T_REP_BY_SORT | T_SORT_RECORDS |
T_SORT_INDEX ) ) ) )
{
2007-08-29 08:03:10 +02:00
ulonglong old_testflag = check_param . testflag ;
2006-04-11 15:45:10 +02:00
if ( ! ( check_param . testflag & T_REP ) )
check_param . testflag | = T_REP_BY_SORT ;
2007-12-31 10:55:46 +01:00
check_param . testflag & = ~ T_EXTEND ; /* Not needed */
2007-01-18 20:38:14 +01:00
error | = maria_chk ( & check_param , argv [ - 1 ] ) ;
2006-04-11 15:45:10 +02:00
check_param . testflag = old_testflag ;
VOID ( fflush ( stdout ) ) ;
VOID ( fflush ( stderr ) ) ;
}
else
error | = new_error ;
2007-08-29 08:03:10 +02:00
if ( argc & & ( ! ( check_param . testflag & T_SILENT ) | |
check_param . testflag & T_INFO ) )
2006-04-11 15:45:10 +02:00
{
puts ( " \n --------- \n " ) ;
VOID ( fflush ( stdout ) ) ;
}
}
if ( check_param . total_files > 1 )
{ /* Only if descript */
char buff [ 22 ] , buff2 [ 22 ] ;
if ( ! ( check_param . testflag & T_SILENT ) | | check_param . testflag & T_INFO )
2007-11-28 20:38:30 +01:00
puts ( " \n --------- " ) ;
2006-04-11 15:45:10 +02:00
printf ( " \n Total of all %d MARIA-files: \n Data records: %9s Deleted blocks: %9s \n " , check_param . total_files , llstr ( check_param . total_records , buff ) ,
llstr ( check_param . total_deleted , buff2 ) ) ;
}
free_defaults ( default_argv ) ;
2007-01-18 20:38:14 +01:00
free_tmpdir ( & maria_chk_tmpdir ) ;
2006-04-11 15:45:10 +02:00
maria_end ( ) ;
my_end ( check_param . testflag & T_INFO ?
MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR ) ;
exit ( error ) ;
# ifndef _lint
return 0 ; /* No compiler warning */
# endif
} /* main */
enum options_mc {
OPT_CHARSETS_DIR = 256 , OPT_SET_COLLATION , OPT_START_CHECK_POS ,
2007-09-27 13:18:28 +02:00
OPT_CORRECT_CHECKSUM , OPT_PAGE_BUFFER_SIZE ,
2006-04-11 15:45:10 +02:00
OPT_KEY_CACHE_BLOCK_SIZE , OPT_MARIA_BLOCK_SIZE ,
OPT_READ_BUFFER_SIZE , OPT_WRITE_BUFFER_SIZE , OPT_SORT_BUFFER_SIZE ,
OPT_SORT_KEY_BLOCKS , OPT_DECODE_BITS , OPT_FT_MIN_WORD_LEN ,
OPT_FT_MAX_WORD_LEN , OPT_FT_STOPWORD_FILE ,
2008-01-07 17:54:41 +01:00
OPT_MAX_RECORD_LENGTH , OPT_AUTO_CLOSE , OPT_STATS_METHOD , OPT_TRANSACTION_LOG ,
OPT_SKIP_SAFEMALLOC
2006-04-11 15:45:10 +02:00
} ;
static struct my_option my_long_options [ ] =
{
{ " analyze " , ' a ' ,
" Analyze distribution of keys. Will make some joins in MySQL faster. You can check the calculated distribution. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
# ifdef __NETWARE__
{ " autoclose " , OPT_AUTO_CLOSE , " Auto close the screen on exit for Netware. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
# endif
{ " block-search " , ' b ' ,
" No help available. " ,
0 , 0 , 0 , GET_ULONG , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " backup " , ' B ' ,
2007-12-31 10:55:46 +01:00
" Make a backup of the .MAD file as 'filename-time.BAK'. " ,
2006-04-11 15:45:10 +02:00
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " character-sets-dir " , OPT_CHARSETS_DIR ,
" Directory where character sets are. " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & charsets_dir , 0 , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2006-04-11 15:45:10 +02:00
{ " check " , ' c ' ,
" Check table for errors. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " check-only-changed " , ' C ' ,
" Check only tables that have changed since last check. It also applies to other requested actions (e.g. --analyze will be ignored if the table is already analyzed). " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " correct-checksum " , OPT_CORRECT_CHECKSUM ,
" Correct checksum information for table. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
# ifndef DBUG_OFF
{ " debug " , ' # ' ,
" Output debug log. Often this is 'd:t:o,filename'. " ,
0 , 0 , 0 , GET_STR , OPT_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
# endif
{ " description " , ' d ' ,
" Prints some information about table. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " data-file-length " , ' D ' ,
" Max length of data file (when recreating data-file when it's full). " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & check_param . max_data_file_length ,
( uchar * * ) & check_param . max_data_file_length ,
2006-04-11 15:45:10 +02:00
0 , GET_LL , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " extend-check " , ' e ' ,
" If used when checking a table, ensure that the table is 100 percent consistent, which will take a long time. If used when repairing a table, try to recover every possible row from the data file. Normally this will also find a lot of garbage rows; Don't use this option with repair if you are not totally desperate. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " fast " , ' F ' ,
" Check only tables that haven't been closed properly. It also applies to other requested actions (e.g. --analyze will be ignored if the table is already analyzed). " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " force " , ' f ' ,
" Restart with -r if there are any errors in the table. States will be updated as with --update-state. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " HELP " , ' H ' ,
" Display this help and exit. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " help " , ' ? ' ,
" Display this help and exit. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " information " , ' i ' ,
" Print statistics information about table that is checked. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " keys-used " , ' k ' ,
" Tell MARIA to update only some specific keys. # is a bit mask of which keys to use. This can be used to get faster inserts. " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & check_param . keys_in_use ,
( uchar * * ) & check_param . keys_in_use ,
2006-04-11 15:45:10 +02:00
0 , GET_ULL , REQUIRED_ARG , - 1 , 0 , 0 , 0 , 0 , 0 } ,
{ " max-record-length " , OPT_MAX_RECORD_LENGTH ,
2007-01-18 20:38:14 +01:00
" Skip rows bigger than this if maria_chk can't allocate memory to hold it " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & check_param . max_record_length ,
( uchar * * ) & check_param . max_record_length ,
2006-04-11 15:45:10 +02:00
0 , GET_ULL , REQUIRED_ARG , LONGLONG_MAX , 0 , LONGLONG_MAX , 0 , 0 , 0 } ,
{ " medium-check " , ' m ' ,
" Faster than extend-check, but only finds 99.99% of all errors. Should be good enough for most cases. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " quick " , ' q ' , " Faster repair by not modifying the data file. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " read-only " , ' T ' ,
" Don't mark table as checked. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " recover " , ' r ' ,
" Can fix almost anything except unique keys that aren't unique. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " parallel-recover " , ' p ' ,
" Same as '-r' but creates all the keys in parallel. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " safe-recover " , ' o ' ,
" Uses old recovery method; Slower than '-r' but can handle a couple of cases where '-r' reports that it can't fix the data file. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " sort-recover " , ' n ' ,
" Force recovering with sorting even if the temporary file was very big. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
# ifdef DEBUG
{ " start-check-pos " , OPT_START_CHECK_POS ,
" No help available. " ,
0 , 0 , 0 , GET_ULL , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
# endif
{ " set-auto-increment " , ' A ' ,
" Force auto_increment to start at this or higher value. If no value is given, then sets the next auto_increment value to the highest used value for the auto key + 1. " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & check_param . auto_increment_value ,
( uchar * * ) & check_param . auto_increment_value ,
2006-04-11 15:45:10 +02:00
0 , GET_ULL , OPT_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " set-collation " , OPT_SET_COLLATION ,
" Change the collation used by the index " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & set_collation_name , 0 , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2006-04-11 15:45:10 +02:00
{ " set-variable " , ' O ' ,
" Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value. " ,
0 , 0 , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " silent " , ' s ' ,
2007-01-18 20:38:14 +01:00
" Only print errors. One can use two -s to make maria_chk very silent. " ,
2006-04-11 15:45:10 +02:00
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2008-01-07 17:54:41 +01:00
# ifndef DBUG_OFF
# ifdef SAFEMALLOC
{ " skip-safemalloc " , OPT_SKIP_SAFEMALLOC ,
" Don't use the memory allocation checking. " , 0 , 0 , 0 , GET_NO_ARG , NO_ARG ,
0 , 0 , 0 , 0 , 0 , 0 } ,
# endif
# endif
2006-04-11 15:45:10 +02:00
{ " sort-index " , ' S ' ,
" Sort index blocks. This speeds up 'read-next' in applications. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " sort-records " , ' R ' ,
" Sort records according to an index. This makes your data much more localized and may speed up things. (It may be VERY slow to do a sort the first time!) " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & check_param . opt_sort_key ,
( uchar * * ) & check_param . opt_sort_key ,
2006-04-11 15:45:10 +02:00
0 , GET_UINT , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " tmpdir " , ' t ' ,
" Path for temporary files. " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & opt_tmpdir ,
2006-04-11 15:45:10 +02:00
0 , 0 , GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2007-12-10 02:23:15 +01:00
{ " transaction-log " , OPT_TRANSACTION_LOG ,
" Log repair command to transaction log " ,
( uchar * * ) & opt_transaction_logging , ( uchar * * ) & opt_transaction_logging ,
0 , GET_BOOL , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2006-04-11 15:45:10 +02:00
{ " update-state " , ' U ' ,
" Mark tables as crashed if any errors were found. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " unpack " , ' u ' ,
" Unpack file packed with mariapack. " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
{ " verbose " , ' v ' ,
" Print more information. This can be used with --description and --check. Use many -v for more verbosity! " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2007-12-10 02:23:15 +01:00
{ " version " , ' V ' , " Print version and exit. " ,
2006-04-11 15:45:10 +02:00
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2007-12-10 02:23:15 +01:00
{ " wait " , ' w ' , " Wait if table is locked. " ,
2006-04-11 15:45:10 +02:00
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2007-12-10 02:23:15 +01:00
{ " page_buffer_size " , OPT_PAGE_BUFFER_SIZE ,
" Size of page buffer. Used by --safe-repair " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & check_param . use_buffers , ( uchar * * ) & check_param . use_buffers , 0 ,
2008-01-31 02:06:04 +01:00
GET_ULONG , REQUIRED_ARG , ( long ) USE_BUFFER_INIT , 1024L * 1024L ,
2006-04-11 15:45:10 +02:00
( long ) ~ 0L , ( long ) MALLOC_OVERHEAD , ( long ) IO_SIZE , 0 } ,
{ " read_buffer_size " , OPT_READ_BUFFER_SIZE , " " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & check_param . read_buffer_length ,
( uchar * * ) & check_param . read_buffer_length , 0 , GET_ULONG , REQUIRED_ARG ,
2006-04-11 15:45:10 +02:00
( long ) READ_BUFFER_INIT , ( long ) MALLOC_OVERHEAD ,
( long ) ~ 0L , ( long ) MALLOC_OVERHEAD , ( long ) 1L , 0 } ,
{ " write_buffer_size " , OPT_WRITE_BUFFER_SIZE , " " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & check_param . write_buffer_length ,
( uchar * * ) & check_param . write_buffer_length , 0 , GET_ULONG , REQUIRED_ARG ,
2006-04-11 15:45:10 +02:00
( long ) READ_BUFFER_INIT , ( long ) MALLOC_OVERHEAD ,
( long ) ~ 0L , ( long ) MALLOC_OVERHEAD , ( long ) 1L , 0 } ,
2007-12-10 02:23:15 +01:00
{ " sort_buffer_size " , OPT_SORT_BUFFER_SIZE ,
" Size of sort buffer. Used by --recover " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & check_param . sort_buffer_length ,
( uchar * * ) & check_param . sort_buffer_length , 0 , GET_ULONG , REQUIRED_ARG ,
2006-04-11 15:45:10 +02:00
( long ) SORT_BUFFER_INIT , ( long ) ( MIN_SORT_BUFFER + MALLOC_OVERHEAD ) ,
( long ) ~ 0L , ( long ) MALLOC_OVERHEAD , ( long ) 1L , 0 } ,
{ " sort_key_blocks " , OPT_SORT_KEY_BLOCKS , " " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & check_param . sort_key_blocks ,
( uchar * * ) & check_param . sort_key_blocks , 0 , GET_ULONG , REQUIRED_ARG ,
2006-04-11 15:45:10 +02:00
BUFFERS_WHEN_SORTING , 4L , 100L , 0L , 1L , 0 } ,
2007-07-02 19:45:15 +02:00
{ " decode_bits " , OPT_DECODE_BITS , " " , ( uchar * * ) & decode_bits ,
( uchar * * ) & decode_bits , 0 , GET_UINT , REQUIRED_ARG , 9L , 4L , 17L , 0L , 1L , 0 } ,
{ " ft_min_word_len " , OPT_FT_MIN_WORD_LEN , " " , ( uchar * * ) & ft_min_word_len ,
( uchar * * ) & ft_min_word_len , 0 , GET_ULONG , REQUIRED_ARG , 4 , 1 , HA_FT_MAXCHARLEN ,
2006-04-11 15:45:10 +02:00
0 , 1 , 0 } ,
2007-07-02 19:45:15 +02:00
{ " ft_max_word_len " , OPT_FT_MAX_WORD_LEN , " " , ( uchar * * ) & ft_max_word_len ,
( uchar * * ) & ft_max_word_len , 0 , GET_ULONG , REQUIRED_ARG , HA_FT_MAXCHARLEN , 10 ,
2006-04-11 15:45:10 +02:00
HA_FT_MAXCHARLEN , 0 , 1 , 0 } ,
{ " maria_ft_stopword_file " , OPT_FT_STOPWORD_FILE ,
" Use stopwords from this file instead of built-in list. " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & ft_stopword_file , ( uchar * * ) & ft_stopword_file , 0 , GET_STR ,
2006-04-11 15:45:10 +02:00
REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2007-12-31 10:55:46 +01:00
{ " stats_method " , OPT_STATS_METHOD ,
" Specifies how index statistics collection code should treat NULLs. "
" Possible values of name are \" nulls_unequal \" (default behavior for 4.1/5.0), "
" \" nulls_equal \" (emulate 4.0 behavior), and \" nulls_ignored \" . " ,
2007-07-02 19:45:15 +02:00
( uchar * * ) & maria_stats_method_str , ( uchar * * ) & maria_stats_method_str , 0 ,
2006-04-11 15:45:10 +02:00
GET_STR , REQUIRED_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2007-12-31 10:55:46 +01:00
{ " zerofill " , ' z ' ,
" Fill empty space in data and index files with zeroes " ,
0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 } ,
2006-04-11 15:45:10 +02:00
{ 0 , 0 , 0 , 0 , 0 , 0 , GET_NO_ARG , NO_ARG , 0 , 0 , 0 , 0 , 0 , 0 }
} ;
# include <help_start.h>
static void print_version ( void )
{
2007-01-18 20:38:14 +01:00
printf ( " %s Ver 1.0 for %s at %s \n " , my_progname , SYSTEM_TYPE ,
2006-04-11 15:45:10 +02:00
MACHINE_TYPE ) ;
NETWARE_SET_SCREEN_MODE ( 1 ) ;
}
static void usage ( void )
{
print_version ( ) ;
puts ( " By Monty, for your professional use " ) ;
puts ( " This software comes with NO WARRANTY: see the PUBLIC for details. \n " ) ;
puts ( " Description, check and repair of MARIA tables. " ) ;
puts ( " Used without options all tables on the command will be checked for errors " ) ;
2007-12-31 10:55:46 +01:00
printf ( " Usage: %s [OPTIONS] tables[.MAI] \n " , my_progname_short ) ;
2006-04-11 15:45:10 +02:00
printf ( " \n Global options: \n " ) ;
# ifndef DBUG_OFF
printf ( " \
- # , - - debug = . . . Output debug log . Often this is ' d : t : o , filename ' . \ n " );
# endif
printf ( " \
- ? , - - help Display this help and exit . \ n \
- O , - - set - variable var = option . \ n \
Change the value of a variable . Please note that \ n \
this option is deprecated ; you can set variables \ n \
directly with ' - - variable - name = value ' . \ n \
- t , - - tmpdir = path Path for temporary files . Multiple paths can be \ n \
specified , separated by " );
Completion of merge of mysql-5.1 into mysql-maria.
Manually imported changes done to MyISAM (include/myisam.h,
storage/myisam/*, sql/ha_myisam.*, mysql-test/t/myisam.test,
mysql-test/t/ps_2myisam.test) the last
months into Maria (tedious, should do it more frequently in the
future), including those not done at the previous 5.1->Maria merge
(please in the future don't forget to apply MyISAM changes to Maria
when you merge 5.1 into Maria).
Note: I didn't try to import anything which could be MyISAM-related
in other tests of mysql-test (I didn't want to dig in all csets),
but as QA is working to make most tests re-usable for other engines
(Falcon), it is likely that we'll benefit from this and just have
to set engine=Maria somewhere to run those tests on Maria.
func_group and partition tests fail but they already do in main 5.1
on my machine. No Valgrind error in t/*maria*.test.
Monty: please see the commit comment of maria.result and check.
BitKeeper/deleted/.del-ha_maria.m4:
Delete: config/ac-macros/ha_maria.m4
configure.in:
fix for the new way of enabling engines
include/maria.h:
importing changes done to MyISAM the last months into Maria
include/my_handler.h:
importing changes done to MyISAM the last months into Maria
include/myisam.h:
importing changes done to MyISAM the last months into Maria
mysql-test/r/maria.result:
identical to myisam.result, except the engine name in some places
AND in the line testing key_block_size=1000000000000000000:
Maria gives a key block size of 8192 while MyISAM gives 4096;
is it explainable by the difference between MARIA_KEY_BLOCK_LENGTH
and the same constant in MyISAM? Monty?
mysql-test/r/ps_maria.result:
identical to ps_2myisam.result (except the engine name in some places)
mysql-test/t/maria.test:
instead of engine=maria everywhere, I use @@storage_engine (reduces
the diff with myisam.test).
importing changes done to MyISAM the last months into Maria
mysys/my_handler.c:
importing changes done to MyISAM the last months into Maria
sql/ha_maria.cc:
importing changes done to MyISAM the last months into Maria
sql/ha_maria.h:
importing changes done to MyISAM the last months into Maria
sql/mysqld.cc:
unneeded
storage/maria/Makefile.am:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_check.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_create.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_delete_table.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_dynrec.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_extra.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_ft_boolean_search.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_ft_eval.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_ft_nlq_search.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_ft_parser.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_ft_test1.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_ft_update.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_ftdefs.h:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_key.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_open.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_page.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_rkey.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_rsamepos.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_rt_index.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_rt_mbr.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_search.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_sort.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_test1.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_test2.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_test3.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_update.c:
importing changes done to MyISAM the last months into Maria
storage/maria/ma_write.c:
importing changes done to MyISAM the last months into Maria
storage/maria/maria_chk.c:
importing changes done to MyISAM the last months into Maria
storage/maria/maria_def.h:
importing changes done to MyISAM the last months into Maria
storage/maria/maria_ftdump.c:
importing changes done to MyISAM the last months into Maria
storage/maria/maria_pack.c:
importing changes done to MyISAM the last months into Maria
2006-08-10 16:36:54 +02:00
# if defined( __WIN__) || defined(__NETWARE__)
2006-04-11 15:45:10 +02:00
printf ( " semicolon (;) " ) ;
# else
printf ( " colon (:) " ) ;
# endif
printf ( " , they will be used \n \
in a round - robin fashion . \ n \
- s , - - silent Only print errors . One can use two - s to make \ n \
2007-01-18 20:38:14 +01:00
maria_chk very silent . \ n \
2006-04-11 15:45:10 +02:00
- v , - - verbose Print more information . This can be used with \ n \
- - description and - - check . Use many - v for more verbosity . \ n \
- V , - - version Print version and exit . \ n \
- w , - - wait Wait if table is locked . \ n \ n " );
# ifdef DEBUG
puts ( " --start-check-pos=# Start reading file at given offset. \n " ) ;
# endif
2007-01-18 20:38:14 +01:00
puts ( " Check options (check is the default action for maria_chk): \n \
2006-04-11 15:45:10 +02:00
- c , - - check Check table for errors . \ n \
- e , - - extend - check Check the table VERY throughly . Only use this in \ n \
2007-01-18 20:38:14 +01:00
extreme cases as maria_chk should normally be able to \ n \
2006-04-11 15:45:10 +02:00
find out if the table is ok even without this switch . \ n \
- F , - - fast Check only tables that haven ' t been closed properly . \ n \
- C , - - check - only - changed \ n \
Check only tables that have changed since last check . \ n \
- f , - - force Restart with ' - r ' if there are any errors in the table . \ n \
States will be updated as with ' - - update - state ' . \ n \
- i , - - information Print statistics information about table that is checked . \ n \
- m , - - medium - check Faster than extend - check , but only finds 99.99 % of \ n \
all errors . Should be good enough for most cases . \ n \
- U - - update - state Mark tables as crashed if you find any errors . \ n \
- T , - - read - only Don ' t mark table as checked . \ n " );
2007-12-10 02:23:15 +01:00
puts ( " Recover (repair)/ options (When using '-r' or '-o'): \n \
2007-12-31 10:55:46 +01:00
- B , - - backup Make a backup of the . MAD file as ' filename - time . BAK ' . \ n \
2006-04-11 15:45:10 +02:00
- - correct - checksum Correct checksum information for table . \ n \
- D , - - data - file - length = # Max length of data file ( when recreating data \ n \
file when it ' s full ) . \ n \
- e , - - extend - check Try to recover every possible row from the data file \ n \
Normally this will also find a lot of garbage rows ; \ n \
Don ' t use this option if you are not totally desperate . \ n \
- f , - - force Overwrite old temporary files . \ n \
- k , - - keys - used = # Tell MARIA to update only some specific keys . # is a \ n \
bit mask of which keys to use . This can be used to \ n \
get faster inserts . \ n \
- - max - record - length = # \ n \
2007-01-18 20:38:14 +01:00
Skip rows bigger than this if maria_chk can ' t allocate \ n \
2006-04-11 15:45:10 +02:00
memory to hold it . \ n \
- r , - - recover Can fix almost anything except unique keys that aren ' t \ n \
unique . \ n \
- n , - - sort - recover Forces recovering with sorting even if the temporary \ n \
file would be very big . \ n \
- p , - - parallel - recover \ n \
Uses the same technique as ' - r ' and ' - n ' , but creates \ n \
2008-01-11 00:47:52 +01:00
all the keys in parallel , in different threads . " );
puts ( " \
- o , - - safe - recover Uses old recovery method ; Slower than ' - r ' but can \ n \
2006-04-11 15:45:10 +02:00
handle a couple of cases where ' - r ' reports that it \ n \
can ' t fix the data file . \ n \
2007-12-10 02:23:15 +01:00
- - transaction - log Log repair command to transaction log . This is needed \ n \
if one wants to use the maria_read_log to repeat the \ n \
repair \ n \
2006-04-11 15:45:10 +02:00
- - character - sets - dir = . . . \ n \
Directory where character sets are . \ n \
- - set - collation = name \ n \
Change the collation used by the index . \ n \
- q , - - quick Faster repair by not modifying the data file . \ n \
2007-01-18 20:38:14 +01:00
One can give a second ' - q ' to force maria_chk to \ n \
2006-04-11 15:45:10 +02:00
modify the original datafile in case of duplicate keys . \ n \
NOTE : Tables where the data file is currupted can ' t be \ n \
fixed with this option . \ n \
- u , - - unpack Unpack file packed with mariapack . \ n \
" );
puts ( " Other actions: \n \
- a , - - analyze Analyze distribution of keys . Will make some joins in \ n \
MySQL faster . You can check the calculated distribution \ n \
by using ' - - description - - verbose table_name ' . \ n \
- - stats_method = name Specifies how index statistics collection code should \ n \
2007-10-04 19:33:42 +02:00
treat NULLs . Possible values of name are \ " nulls_unequal \" \n \
2006-04-11 15:45:10 +02:00
( default for 4.1 / 5.0 ) , \ " nulls_equal \" (emulate 4.0), and \n \
\ " nulls_ignored \" . \n \
- d , - - description Prints some information about table . \ n \
- A , - - set - auto - increment [ = value ] \ n \
Force auto_increment to start at this or higher value \ n \
If no value is given , then sets the next auto_increment \ n \
value to the highest used value for the auto key + 1. \ n \
- S , - - sort - index Sort index blocks . This speeds up ' read - next ' in \ n \
applications . \ n \
- R , - - sort - records = # \ n \
Sort records according to an index . This makes your \ n \
data much more localized and may speed up things \ n \
( It may be VERY slow to do a sort the first time ! ) . \ n \
- b , - - block - search = # \ n \
2007-12-31 10:55:46 +01:00
Find a record , a block at given offset belongs to . \ n \
2008-01-11 00:47:52 +01:00
- z , - - zerofill Fill empty space in data and index files with zeroes . " );
2006-04-11 15:45:10 +02:00
print_defaults ( " my " , load_default_groups ) ;
my_print_variables ( my_long_options ) ;
}
# include <help_end.h>
const char * maria_stats_method_names [ ] = { " nulls_unequal " , " nulls_equal " ,
" nulls_ignored " , NullS } ;
TYPELIB maria_stats_method_typelib = {
array_elements ( maria_stats_method_names ) - 1 , " " ,
maria_stats_method_names , NULL } ;
/* Read options */
static my_bool
get_one_option ( int optid ,
const struct my_option * opt __attribute__ ( ( unused ) ) ,
char * argument )
{
switch ( optid ) {
# ifdef __NETWARE__
case OPT_AUTO_CLOSE :
setscreenmode ( SCR_AUTOCLOSE_ON_EXIT ) ;
break ;
# endif
case ' a ' :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_STATISTICS ;
else
check_param . testflag | = T_STATISTICS ;
break ;
case ' A ' :
if ( argument )
check_param . auto_increment_value = strtoull ( argument , NULL , 0 ) ;
else
check_param . auto_increment_value = 0 ; /* Set to max used value */
check_param . testflag | = T_AUTO_INC ;
break ;
case ' b ' :
check_param . search_after_block = strtoul ( argument , NULL , 10 ) ;
break ;
case ' B ' :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_BACKUP_DATA ;
else
check_param . testflag | = T_BACKUP_DATA ;
break ;
case ' c ' :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_CHECK ;
else
check_param . testflag | = T_CHECK ;
break ;
case ' C ' :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ ( T_CHECK | T_CHECK_ONLY_CHANGED ) ;
else
check_param . testflag | = T_CHECK | T_CHECK_ONLY_CHANGED ;
break ;
case ' D ' :
check_param . max_data_file_length = strtoll ( argument , NULL , 10 ) ;
break ;
case ' s ' : /* silent */
if ( argument = = disabled_my_option )
check_param . testflag & = ~ ( T_SILENT | T_VERY_SILENT ) ;
else
{
if ( check_param . testflag & T_SILENT )
check_param . testflag | = T_VERY_SILENT ;
check_param . testflag | = T_SILENT ;
check_param . testflag & = ~ T_WRITE_LOOP ;
}
break ;
case ' w ' :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_WAIT_FOREVER ;
else
check_param . testflag | = T_WAIT_FOREVER ;
break ;
case ' d ' : /* description if isam-file */
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_DESCRIPT ;
else
check_param . testflag | = T_DESCRIPT ;
break ;
case ' e ' : /* extend check */
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_EXTEND ;
else
check_param . testflag | = T_EXTEND ;
break ;
case ' i ' :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_INFO ;
else
check_param . testflag | = T_INFO ;
break ;
case ' f ' :
if ( argument = = disabled_my_option )
{
check_param . tmpfile_createflag = O_RDWR | O_TRUNC | O_EXCL ;
check_param . testflag & = ~ ( T_FORCE_CREATE | T_UPDATE_STATE ) ;
}
else
{
check_param . tmpfile_createflag = O_RDWR | O_TRUNC ;
check_param . testflag | = T_FORCE_CREATE | T_UPDATE_STATE ;
}
break ;
case ' F ' :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_FAST ;
else
check_param . testflag | = T_FAST ;
break ;
case ' k ' :
check_param . keys_in_use = ( ulonglong ) strtoll ( argument , NULL , 10 ) ;
break ;
case ' m ' :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_MEDIUM ;
else
check_param . testflag | = T_MEDIUM ; /* Medium check */
break ;
case ' r ' : /* Repair table */
check_param . testflag & = ~ T_REP_ANY ;
if ( argument ! = disabled_my_option )
check_param . testflag | = T_REP_BY_SORT ;
break ;
case ' p ' :
check_param . testflag & = ~ T_REP_ANY ;
if ( argument ! = disabled_my_option )
check_param . testflag | = T_REP_PARALLEL ;
break ;
case ' o ' :
check_param . testflag & = ~ T_REP_ANY ;
check_param . force_sort = 0 ;
if ( argument ! = disabled_my_option )
{
check_param . testflag | = T_REP ;
my_disable_async_io = 1 ; /* More safety */
}
break ;
case ' n ' :
check_param . testflag & = ~ T_REP_ANY ;
if ( argument = = disabled_my_option )
check_param . force_sort = 0 ;
else
{
check_param . testflag | = T_REP_BY_SORT ;
check_param . force_sort = 1 ;
}
break ;
case ' q ' :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ ( T_QUICK | T_FORCE_UNIQUENESS ) ;
else
check_param . testflag | =
( check_param . testflag & T_QUICK ) ? T_FORCE_UNIQUENESS : T_QUICK ;
break ;
case ' u ' :
if ( argument = = disabled_my_option )
2007-11-28 20:38:30 +01:00
check_param . testflag & = ~ T_UNPACK ;
2006-04-11 15:45:10 +02:00
else
2007-11-28 20:38:30 +01:00
{
check_param . testflag | = T_UNPACK ;
if ( ! ( check_param . testflag & T_REP_ANY ) )
check_param . testflag | = T_REP_BY_SORT ;
}
2006-04-11 15:45:10 +02:00
break ;
case ' v ' : /* Verbose */
if ( argument = = disabled_my_option )
{
check_param . testflag & = ~ T_VERBOSE ;
check_param . verbose = 0 ;
}
else
{
check_param . testflag | = T_VERBOSE ;
check_param . verbose + + ;
}
break ;
case ' R ' : /* Sort records */
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_SORT_RECORDS ;
else
{
check_param . testflag | = T_SORT_RECORDS ;
check_param . opt_sort_key = ( uint ) atoi ( argument ) - 1 ;
if ( check_param . opt_sort_key > = MARIA_MAX_KEY )
{
fprintf ( stderr ,
" The value of the sort key is bigger than max key: %d. \n " ,
MARIA_MAX_KEY ) ;
exit ( 1 ) ;
}
}
break ;
case ' S ' : /* Sort index */
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_SORT_INDEX ;
else
check_param . testflag | = T_SORT_INDEX ;
break ;
case ' T ' :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_READONLY ;
else
check_param . testflag | = T_READONLY ;
break ;
case ' U ' :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_UPDATE_STATE ;
else
check_param . testflag | = T_UPDATE_STATE ;
break ;
case ' # ' :
2007-07-01 15:20:57 +02:00
DBUG_SET_INITIAL ( argument ? argument : " d:t:o,/tmp/maria_chk.trace " ) ;
2008-01-07 17:54:41 +01:00
opt_debug = 1 ;
break ;
case OPT_SKIP_SAFEMALLOC :
# ifdef SAFEMALLOC
sf_malloc_quick = 1 ;
# endif
2006-04-11 15:45:10 +02:00
break ;
case ' V ' :
print_version ( ) ;
exit ( 0 ) ;
case OPT_CORRECT_CHECKSUM :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_CALC_CHECKSUM ;
else
check_param . testflag | = T_CALC_CHECKSUM ;
break ;
case OPT_STATS_METHOD :
{
int method ;
enum_handler_stats_method method_conv ;
2006-12-20 18:58:35 +01:00
LINT_INIT ( method_conv ) ;
2006-04-11 15:45:10 +02:00
maria_stats_method_str = argument ;
if ( ( method = find_type ( argument , & maria_stats_method_typelib , 2 ) ) < = 0 )
{
fprintf ( stderr , " Invalid value of stats_method: %s. \n " , argument ) ;
exit ( 1 ) ;
}
switch ( method - 1 ) {
case 0 :
method_conv = MI_STATS_METHOD_NULLS_EQUAL ;
break ;
case 1 :
method_conv = MI_STATS_METHOD_NULLS_NOT_EQUAL ;
break ;
case 2 :
method_conv = MI_STATS_METHOD_IGNORE_NULLS ;
break ;
2007-03-01 18:23:58 +01:00
default : assert ( 0 ) ; /* Impossible */
2006-04-11 15:45:10 +02:00
}
check_param . stats_method = method_conv ;
break ;
}
# ifdef DEBUG /* Only useful if debugging */
case OPT_START_CHECK_POS :
check_param . start_check_pos = strtoull ( argument , NULL , 0 ) ;
break ;
# endif
2007-12-31 10:55:46 +01:00
case ' z ' :
if ( argument = = disabled_my_option )
check_param . testflag & = ~ T_ZEROFILL ;
else
check_param . testflag | = T_ZEROFILL ;
break ;
2006-04-11 15:45:10 +02:00
case ' H ' :
my_print_help ( my_long_options ) ;
exit ( 0 ) ;
case ' ? ' :
usage ( ) ;
exit ( 0 ) ;
}
return 0 ;
}
static void get_options ( register int * argc , register char * * * argv )
{
int ho_error ;
load_defaults ( " my " , load_default_groups , argc , argv ) ;
default_argv = * argv ;
if ( isatty ( fileno ( stdout ) ) )
check_param . testflag | = T_WRITE_LOOP ;
if ( ( ho_error = handle_options ( argc , argv , my_long_options , get_one_option ) ) )
exit ( ho_error ) ;
/* If using repair, then update checksum if one uses --update-state */
if ( ( check_param . testflag & T_UPDATE_STATE ) & &
( check_param . testflag & T_REP_ANY ) )
check_param . testflag | = T_CALC_CHECKSUM ;
if ( * argc = = 0 )
{
usage ( ) ;
exit ( - 1 ) ;
}
if ( ( check_param . testflag & T_UNPACK ) & &
( check_param . testflag & ( T_QUICK | T_SORT_RECORDS ) ) )
{
VOID ( fprintf ( stderr ,
" %s: --unpack can't be used with --quick or --sort-records \n " ,
my_progname_short ) ) ;
exit ( 1 ) ;
}
if ( ( check_param . testflag & T_READONLY ) & &
( check_param . testflag &
( T_REP_ANY | T_STATISTICS | T_AUTO_INC |
T_SORT_RECORDS | T_SORT_INDEX | T_FORCE_CREATE ) ) )
{
VOID ( fprintf ( stderr ,
" %s: Can't use --readonly when repairing or sorting \n " ,
my_progname_short ) ) ;
exit ( 1 ) ;
}
2008-01-07 17:54:41 +01:00
if ( ! opt_debug )
{
DEBUGGER_OFF ; /* Speed up things a bit */
}
2007-01-18 20:38:14 +01:00
if ( init_tmpdir ( & maria_chk_tmpdir , opt_tmpdir ) )
2006-04-11 15:45:10 +02:00
exit ( 1 ) ;
2007-01-18 20:38:14 +01:00
check_param . tmpdir = & maria_chk_tmpdir ;
2006-04-11 15:45:10 +02:00
if ( set_collation_name )
if ( ! ( set_collation = get_charset_by_name ( set_collation_name ,
MYF ( MY_WME ) ) ) )
exit ( 1 ) ;
return ;
} /* get options */
/* Check table */
2007-07-02 19:45:15 +02:00
static int maria_chk ( HA_CHECK * param , char * filename )
2006-04-11 15:45:10 +02:00
{
int error , lock_type , recreate ;
2008-01-10 20:21:36 +01:00
my_bool rep_quick = test ( param - > testflag & ( T_QUICK | T_FORCE_UNIQUENESS ) ) ;
2006-04-11 15:45:10 +02:00
MARIA_HA * info ;
File datafile ;
char llbuff [ 22 ] , llbuff2 [ 22 ] ;
my_bool state_updated = 0 ;
MARIA_SHARE * share ;
2007-01-18 20:38:14 +01:00
DBUG_ENTER ( " maria_chk " ) ;
2006-04-11 15:45:10 +02:00
param - > out_flag = error = param - > warning_printed = param - > error_printed =
recreate = 0 ;
datafile = 0 ;
param - > isam_file_name = filename ; /* For error messages */
if ( ! ( info = maria_open ( filename ,
2007-11-28 20:38:30 +01:00
( param - > testflag & ( T_DESCRIPT | T_READONLY ) ) ?
O_RDONLY : O_RDWR ,
HA_OPEN_FOR_REPAIR |
( ( param - > testflag & T_WAIT_FOREVER ) ?
HA_OPEN_WAIT_IF_LOCKED :
( param - > testflag & T_DESCRIPT ) ?
HA_OPEN_IGNORE_IF_LOCKED : HA_OPEN_ABORT_IF_LOCKED ) ) ) )
2006-04-11 15:45:10 +02:00
{
/* Avoid twice printing of isam file name */
param - > error_printed = 1 ;
switch ( my_errno ) {
case HA_ERR_CRASHED :
_ma_check_print_error ( param , " '%s' doesn't have a correct index definition. You need to recreate it before you can do a repair " , filename ) ;
break ;
case HA_ERR_NOT_A_TABLE :
_ma_check_print_error ( param , " '%s' is not a MARIA-table " , filename ) ;
break ;
case HA_ERR_CRASHED_ON_USAGE :
_ma_check_print_error ( param , " '%s' is marked as crashed " , filename ) ;
break ;
case HA_ERR_CRASHED_ON_REPAIR :
_ma_check_print_error ( param , " '%s' is marked as crashed after last repair " , filename ) ;
break ;
case HA_ERR_OLD_FILE :
_ma_check_print_error ( param , " '%s' is a old type of MARIA-table " , filename ) ;
break ;
2007-10-09 20:09:50 +02:00
case HA_ERR_NEW_FILE :
_ma_check_print_error ( param , " '%s' uses new features not supported by this version of the MARIA library " , filename ) ;
break ;
2006-04-11 15:45:10 +02:00
case HA_ERR_END_OF_FILE :
_ma_check_print_error ( param , " Couldn't read complete header from '%s' " , filename ) ;
break ;
case EAGAIN :
_ma_check_print_error ( param , " '%s' is locked. Use -w to wait until unlocked " , filename ) ;
break ;
case ENOENT :
_ma_check_print_error ( param , " File '%s' doesn't exist " , filename ) ;
break ;
case EACCES :
2007-01-18 20:38:14 +01:00
_ma_check_print_error ( param , " You don't have permission to use '%s' " ,
filename ) ;
2006-04-11 15:45:10 +02:00
break ;
default :
_ma_check_print_error ( param , " %d when opening MARIA-table '%s' " ,
my_errno , filename ) ;
break ;
}
DBUG_RETURN ( 1 ) ;
}
2007-12-10 01:32:00 +01:00
share = info - > s ;
2006-04-11 15:45:10 +02:00
share - > tot_locks - = share - > r_locks ;
share - > r_locks = 0 ;
2007-04-19 17:48:36 +02:00
maria_block_size = share - > base . block_size ;
2007-01-18 20:38:14 +01:00
2007-07-01 15:20:57 +02:00
if ( share - > data_file_type = = BLOCK_RECORD | |
( ( param - > testflag & T_UNPACK ) & &
share - > state . header . org_data_file_type = = BLOCK_RECORD ) )
2007-01-18 20:38:14 +01:00
{
2007-07-01 15:20:57 +02:00
if ( param - > testflag & T_SORT_RECORDS )
{
_ma_check_print_error ( param ,
2008-01-07 17:54:41 +01:00
" Record format used by '%s' is is not yet supported with sort-records " ,
2007-07-01 15:20:57 +02:00
filename ) ;
param - > error_printed = 0 ;
error = 1 ;
goto end2 ;
}
/* We can't do parallell repair with BLOCK_RECORD yet */
2007-11-28 20:38:30 +01:00
if ( param - > testflag & T_REP_PARALLEL )
2007-07-01 15:20:57 +02:00
{
2007-11-28 20:38:30 +01:00
param - > testflag & = ~ T_REP_PARALLEL ;
param - > testflag | = T_REP_BY_SORT ;
2007-07-01 15:20:57 +02:00
}
2007-01-18 20:38:14 +01:00
}
2006-04-11 15:45:10 +02:00
/*
Skip the checking of the file if :
We are using - - fast and the table is closed properly
We are using - - check - only - changed - tables and the table hasn ' t changed
*/
if ( param - > testflag & ( T_FAST | T_CHECK_ONLY_CHANGED ) )
{
2007-01-18 20:38:14 +01:00
my_bool need_to_check = ( maria_is_crashed ( info ) | |
share - > state . open_count ! = 0 ) ;
2006-04-11 15:45:10 +02:00
if ( ( param - > testflag & ( T_REP_ANY | T_SORT_RECORDS ) ) & &
( ( share - > state . changed & ( STATE_CHANGED | STATE_CRASHED |
STATE_CRASHED_ON_REPAIR ) | |
! ( param - > testflag & T_CHECK_ONLY_CHANGED ) ) ) )
need_to_check = 1 ;
if ( info - > s - > base . keys & & info - > state - > records )
{
if ( ( param - > testflag & T_STATISTICS ) & &
( share - > state . changed & STATE_NOT_ANALYZED ) )
need_to_check = 1 ;
if ( ( param - > testflag & T_SORT_INDEX ) & &
( share - > state . changed & STATE_NOT_SORTED_PAGES ) )
need_to_check = 1 ;
if ( ( param - > testflag & T_REP_BY_SORT ) & &
( share - > state . changed & STATE_NOT_OPTIMIZED_KEYS ) )
need_to_check = 1 ;
}
if ( ( param - > testflag & T_CHECK_ONLY_CHANGED ) & &
( share - > state . changed & ( STATE_CHANGED | STATE_CRASHED |
STATE_CRASHED_ON_REPAIR ) ) )
need_to_check = 1 ;
if ( ! need_to_check )
{
if ( ! ( param - > testflag & T_SILENT ) | | param - > testflag & T_INFO )
printf ( " MARIA file: %s is already checked \n " , filename ) ;
if ( maria_close ( info ) )
{
_ma_check_print_error ( param , " %d when closing MARIA-table '%s' " ,
my_errno , filename ) ;
DBUG_RETURN ( 1 ) ;
}
DBUG_RETURN ( 0 ) ;
}
}
if ( ( param - > testflag & ( T_REP_ANY | T_STATISTICS |
T_SORT_RECORDS | T_SORT_INDEX ) ) & &
( ( ( param - > testflag & T_UNPACK ) & &
share - > data_file_type = = COMPRESSED_RECORD ) | |
mi_uint2korr ( share - > state . header . state_info_length ) ! =
MARIA_STATE_INFO_SIZE | |
mi_uint2korr ( share - > state . header . base_info_length ) ! =
MARIA_BASE_INFO_SIZE | |
maria_is_any_intersect_keys_active ( param - > keys_in_use , share - > base . keys ,
~ share - > state . key_map ) | |
maria_test_if_almost_full ( info ) | |
info - > s - > state . header . file_version [ 3 ] ! = maria_file_magic [ 3 ] | |
( set_collation & &
2007-04-19 17:48:36 +02:00
set_collation - > number ! = share - > state . header . language ) ) )
2006-04-11 15:45:10 +02:00
{
if ( set_collation )
param - > language = set_collation - > number ;
if ( maria_recreate_table ( param , & info , filename ) )
{
VOID ( fprintf ( stderr ,
" MARIA-table '%s' is not fixed because of errors \n " ,
filename ) ) ;
return ( - 1 ) ;
}
recreate = 1 ;
if ( ! ( param - > testflag & T_REP_ANY ) )
{
param - > testflag | = T_REP_BY_SORT ; /* if only STATISTICS */
if ( ! ( param - > testflag & T_SILENT ) )
printf ( " - '%s' has old table-format. Recreating index \n " , filename ) ;
2008-01-10 20:21:36 +01:00
rep_quick = 1 ;
2006-04-11 15:45:10 +02:00
}
2007-12-10 01:32:00 +01:00
share = info - > s ;
2006-04-11 15:45:10 +02:00
share - > tot_locks - = share - > r_locks ;
share - > r_locks = 0 ;
}
if ( param - > testflag & T_DESCRIPT )
{
param - > total_files + + ;
param - > total_records + = info - > state - > records ;
param - > total_deleted + = info - > state - > del ;
descript ( param , info , filename ) ;
2007-04-19 17:48:36 +02:00
maria_close ( info ) ; /* Should always succeed */
return ( 0 ) ;
2006-04-11 15:45:10 +02:00
}
2007-04-19 17:48:36 +02:00
if ( ! stopwords_inited + + )
ft_init_stopwords ( ) ;
if ( ! ( param - > testflag & T_READONLY ) )
lock_type = F_WRLCK ; /* table is changed */
2006-04-11 15:45:10 +02:00
else
2007-04-19 17:48:36 +02:00
lock_type = F_RDLCK ;
if ( info - > lock_type = = F_RDLCK )
info - > lock_type = F_UNLCK ; /* Read only table */
if ( _ma_readinfo ( info , lock_type , 0 ) )
{
_ma_check_print_error ( param , " Can't lock indexfile of '%s', error: %d " ,
filename , my_errno ) ;
param - > error_printed = 0 ;
error = 1 ;
goto end2 ;
}
/*
_ma_readinfo ( ) has locked the table .
We mark the table as locked ( without doing file locks ) to be able to
use functions that only works on locked tables ( like row caching ) .
*/
maria_lock_database ( info , F_EXTRA_LCK ) ;
datafile = info - > dfile . file ;
if ( init_pagecache ( maria_pagecache , param - > use_buffers , 0 , 0 ,
2007-12-04 22:23:42 +01:00
maria_block_size , MY_WME ) = = 0 )
2006-04-11 15:45:10 +02:00
{
2007-04-19 17:48:36 +02:00
_ma_check_print_error ( param , " Can't initialize page cache with %lu memory " ,
( ulong ) param - > use_buffers ) ;
error = 1 ;
goto end2 ;
}
2006-04-11 15:45:10 +02:00
2007-12-31 10:55:46 +01:00
if ( param - > testflag & ( T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX |
T_ZEROFILL ) )
2007-04-19 17:48:36 +02:00
{
- fix for segfault in rpl_trigger/rpl_found_rows with default engine=maria
(fix is keeping the real TRN through a disable_logging/reenable cycle)
- fix for pagecache assertion failure in ps/type_ranges with default
engine=maria (fix is in sql_insert.cc)
- when reenabling logging we must either flush all dirty pages,
or at least verify (in debug build) that there are none. For example
a bulk insert with single UNDO_BULK_INSERT must flush them, no matter
if it uses repair or not (bugfix)
- UNDO_BULK_INSERT_WITH_REPAIR is also used with repair, changes name
mysql-test/r/maria.result:
tests for bugs fixed
mysql-test/t/maria.test:
tests for bugs fixed
sql/sql_insert.cc:
Bugfix: even if select_create::prepare() failed to create the 'table' object
we still have to re-enable logging.
storage/maria/ha_maria.cc:
Bugfix: when a transactional table does a bulk insert without
repair, it still sometimes skips logging of REDOs thus needs a full
flush and sync at the end. Not if repair is done, as repair does
it internally already (see end of maria_repair*()).
storage/maria/ha_maria.h:
variable now can have 3 states not 2
storage/maria/ma_bitmap.c:
name change
storage/maria/ma_blockrec.c:
name change
storage/maria/ma_blockrec.h:
name change
storage/maria/ma_check.c:
* When maria_repair() re-enables logging it does not need to ask for
a flush&sync as it did it by itself already a few lines before.
* the log record of bulk insert can be used even without repair
* disable logging in maria_zerofill(): without that, it puts LSN pages
in the cache, so when it flushes them it flushes the log; the change
makes auto-ha_maria::zerofill-if-moved faster (no log flush).
storage/maria/ma_key_recover.c:
name change
storage/maria/ma_loghandler.c:
name change
storage/maria/ma_loghandler.h:
name change
storage/maria/ma_pagecache.c:
A function, to check in debug builds that no dirty pages exist for a file.
storage/maria/ma_pagecache.h:
new function (nothing in non-debug)
storage/maria/ma_recovery.c:
_ma_tmp_disable_logging() sets info->trn to dummy_transaction_object
when needed now. The changes done here about info->trn are to allow
a table to retain its original, real TRN through a disable/reenable
cycle (see replication scenario in _ma_reenable_logging_for_table()).
When we reenable, we offer the caller to flush and sync the table;
if the caller doesn't accept our offer, we verify that it's ok
(no REDOs => no dirty pages are allowed to exist).
storage/maria/maria_chk.c:
comment
storage/maria/maria_def.h:
new names
mysql-test/suite/rpl/r/rpl_stm_maria.result:
result (it used to crash)
mysql-test/suite/rpl/t/rpl_stm_maria.test:
Test of replication-specific Maria bug fixed
2008-01-20 05:25:26 +01:00
/*
Mark table as not transactional to avoid logging . Should not be needed ,
maria_repair and maria_zerofill do it already .
*/
WL#3072 - Maria Recovery
* to honour WAL we now force the whole log when flushing a bitmap page.
* ability to intentionally crash in various places for recovery testing
* bugfix (dirty pages list found in checkpoint record was ignored)
* smaller checkpoint record
* misc small cleanups and comments
mysql-test/include/maria_empty_logs.inc:
maria-purge.test creates ~11 logs, remove them all
mysql-test/r/maria-recovery-bitmap.result:
result is good; without the _ma_bitmap_get_log_address() call,
we got
check error Bitmap at 0 has pages reserved outside of data file length
mysql-test/r/maria-recovery.result:
result update
mysql-test/t/maria-recovery-bitmap.test:
enable test of "bitmap-flush should flush whole log otherwise
corrupted data file (bitmap ahead of data pages)".
mysql-test/t/maria-recovery.test:
test of checkpoint
sql/sql_table.cc:
comment
storage/maria/ha_maria.cc:
_ma_reenable_logging_for_table() now includes file->trn=0.
At the end of repair() we don't need to re-enable logging, it is
done already by caller (like copy_data_between_tables()); it sounds
strange that this function could decide to re-enable, it should be
up to caller who knows what other operations it plans. Removing this
line led to assertion failure in maria_lock_database(F_UNLCK), fixed
by removing the assertion: maria_lock_database()
is here called in a context where F_UNLCK does not make the
table visible to others so assertion is excessive, and external_lock()
is already designed to honour the asserted condition.
Ability to crash at the end of bulk insert when indices
have been enabled.
storage/maria/ma_bitmap.c:
Better use pagecache_file_init() than set pagecache callbacks directly;
and a new function to set those callbacks for bitmap so that we can
reuse it.
_ma_bitmap_get_log_address() is a pagecache get_log_address callback
which causes the whole log to be flushed when a bitmap page
is flushed by the page cache. This was required by WAL.
storage/maria/ma_blockrec.c:
get_log_address pagecache callback for data (non bitmap) pages:
just reads the LSN from the page's content, like was hard-coded
before in ma_pagecache.c.
storage/maria/ma_blockrec.h:
functions which need to be exported
storage/maria/ma_check.c:
create_new_data_handle() can be static.
Ability to crash after rebuilding the index in OPTIMIZE,
in REPAIR. my_lock() implemented already.
storage/maria/ma_checkpoint.c:
As MARIA_SHARE* is now accessible to pagecache_collect_changed_blocks_LSN(),
we don't need to store kfile/dfile descriptors in checkpoint record,
2-byte-id of the table plus one byte to say if this is data or index
file is enough. So we go from 4+4 bytes per table down to 2+1.
storage/maria/ma_commit.c:
removing duplicate functions (see _ma_tmp_disable_logging_for_table())
storage/maria/ma_extra.c:
Monty fixed
storage/maria/ma_key_recover.c:
comment
storage/maria/ma_locking.c:
Sometimes other code does funny things with maria_lock_database(),
like ha_maria::repair() calling it at start and end without going
through ha_maria::external_lock(). So it happens that maria_lock_database()
is called with now_transactional!=born_transactional.
storage/maria/ma_loghandler.c:
update to new prototype
storage/maria/ma_open.c:
set_data|index_pagecache_callbacks() need to be exported as
they are now called when disabling/enabling transactionality.
storage/maria/ma_pagecache.c:
Removing PAGE_LSN_OFFSET, as much of the code relies on it being
0 anyway (let's not give impression we can just change this constant).
When flushing a page to disk, call the get_log_address callback to
know up to which LSN the log should be flushed.
As we now can access MARIA_SHARE* we can know share->id and store
it into the checkpoint record; we thus go from 4 bytes per dirty page
to 2+1.
storage/maria/ma_pagecache.h:
get_log_address callback
storage/maria/ma_panic.c:
No reason to reset pagecache callbacks in HA_PANIC_READ:
all we do is reopen files if they were closed; callbacks should
be in place already as 'info' exists; we just want to modify
the file descriptors, not the full PAGECACHE_FILE structure.
If we open data file and it was closed, share->bitmap.file needs
to be set.
Note that the modified code is disabled anyway.
storage/maria/ma_recovery.c:
Checkpoint record does not contain kfile/dfile descriptors anymore
so code can be simplified. Hash key in all_dirty_pages is
not made from file_descriptor & pageno anymore, but
index_or_data & table-short-id & pageno.
If a table's create_rename_lsn is higher than record's LSN,
we skip the table and don't fail if it's corrupted (because the LSNs
say that we don't have to look at this table).
If a table is skipped (for example due to create_rename_lsn),
its UNDOs still cause undo_lsn to advance; this is so that if later
we notice the transaction has to rollback we fail (as table should
not be skipped in this case).
Fixing a bug: the dirty_pages list was never used, because
the LSN below which it was used was the minimum rec_lsn of dirty pages!
It is now the min(checkpoint_start_log_horizon, min(trn's rec_lsn)).
When we disable/reenable transactionality, we modify pagecache
callbacks (needed for example for get_log_address: changing
share->page_type is not enough anymore).
storage/maria/ma_write.c:
'records' and 'checksum' are protected: they are updated under
log's mutex in write-hooks when UNDO is written.
storage/maria/maria_chk.c:
remove use of duplicate functions.
storage/maria/maria_def.h:
set_data|index_pagecache_callbacks() need to be exported;
_ma_reenable_logging_for_table() changes to a real function.
storage/maria/unittest/ma_pagecache_consist.c:
new prototype
storage/maria/unittest/ma_pagecache_single.c:
new prototype
storage/maria/unittest/ma_test_loghandler_pagecache-t.c:
new prototype
2007-12-30 21:32:07 +01:00
_ma_tmp_disable_logging_for_table ( info , FALSE ) ;
2007-11-20 16:42:16 +01:00
2007-04-19 17:48:36 +02:00
if ( param - > testflag & T_REP_ANY )
2006-04-11 15:45:10 +02:00
{
2007-04-19 17:48:36 +02:00
ulonglong tmp = share - > state . key_map ;
maria_copy_keys_active ( share - > state . key_map , share - > base . keys ,
param - > keys_in_use ) ;
if ( tmp ! = share - > state . key_map )
info - > update | = HA_STATE_CHANGED ;
2007-12-31 10:55:46 +01:00
if ( rep_quick & &
maria_chk_del ( param , info , param - > testflag & ~ T_VERBOSE ) )
2006-04-11 15:45:10 +02:00
{
2007-12-31 10:55:46 +01:00
if ( param - > testflag & T_FORCE_CREATE )
{
rep_quick = 0 ;
_ma_check_print_info ( param , " Creating new data file \n " ) ;
}
else
{
error = 1 ;
_ma_check_print_error ( param ,
" Quick-recover aborted; Run recovery without switch 'q' " ) ;
}
2006-04-11 15:45:10 +02:00
}
}
2007-04-19 17:48:36 +02:00
if ( ! error )
2006-04-11 15:45:10 +02:00
{
2007-06-27 12:58:08 +02:00
/*
Tell the server ' s Recovery to ignore old REDOs on this table ; we don ' t
know what the log ' s end LSN is now , so we just let the server know
that it will have to find and store it .
WL#3071 Maria checkpoint
Finally this is the real checkpoint code.
It however exhibits unstabilities when a checkpoint runs concurrently
with data-modifying clients (table corruption, transaction log's
assertions) so for now a checkpoint is taken only at startup after
recovery and at shutdown, i.e. not in concurrent situations. Later
we will let it run periodically, as well as flush dirty pages
periodically (almost all needed code is there already, only pagecache
code is written but not committed).
WL#3072 Maria recovery
* replacing UNDO_ROW_PURGE with CLR_END; testing of those CLR_END via
ma_test2 which has INSERTs failing with duplicate keys.
* replaying of REDO_RENAME_TABLE
Now, off to test Recovery in ha_maria :)
BitKeeper/deleted/.del-ma_least_recently_dirtied.c:
Delete: storage/maria/ma_least_recently_dirtied.c
BitKeeper/deleted/.del-ma_least_recently_dirtied.h:
Delete: storage/maria/ma_least_recently_dirtied.h
storage/maria/Makefile.am:
compile Checkpoint module
storage/maria/ha_maria.cc:
When ha_maria starts, do a recovery from last checkpoint.
Take a checkpoint when that recovery has ended and when ha_maria
shuts down cleanly.
storage/maria/ma_blockrec.c:
* even if my_sync() fails we have to my_close() (otherwise we leak
a descriptor)
* UNDO_ROW_PURGE is replaced by a simple CLR_END for UNDO_ROW_INSERT,
as promised in the old comment; it gives us skipping during the
UNDO phase.
storage/maria/ma_check.c:
All REDOs before create_rename_lsn are ignored by Recovery. So
create_rename_lsn must be set only after all data/index has been
flushed and forced to disk. We thus move write_log_record_for_repair()
to after _ma_flush_tables_files_after_repair().
storage/maria/ma_checkpoint.c:
Checkpoint module.
storage/maria/ma_checkpoint.h:
optional argument if caller wants a thread to periodically take
checkpoints and flush dirty pages.
storage/maria/ma_create.c:
* no need to init some vars as the initial bzero(share) takes care of this.
* update to new function's name
* even if we fail in my_sync() we have to my_close()
storage/maria/ma_extra.c:
Checkpoint reads share->last_version under intern_lock, so we make
maria_extra() update it under intern_lock. THR_LOCK_maria still needed
because of _ma_test_if_reopen().
storage/maria/ma_init.c:
destroy checkpoint module when Maria shuts down.
storage/maria/ma_loghandler.c:
* UNDO_ROW_PURGE gone (see ma_blockrec.c)
* we need to remember the LSN of the LOGREC_FILE_ID for a share,
because this LSN is needed into the checkpoint record (Recovery wants
to know the validity domain of an id->name mapping)
* translog_get_horizon_no_lock() needed for Checkpoint
* comment about failing assertion (Sanja knows)
* translog_init_reader_data() thought that translog_read_record_header_scan()
returns 0 in case of error, but 0 just means "0-length header".
* translog_assign_id_to_share() now needs the MARIA_HA because
LOGREC_FILE_ID uses a log-write hook.
* Verify that (de)assignment of share->id happens only under intern_lock,
as Checkpoint reads this id with intern_lock.
* translog_purge() can accept TRANSLOG_ADDRESS, not necessarily
a real LSN.
storage/maria/ma_loghandler.h:
prototype updates
storage/maria/ma_open.c:
no need to initialize "res"
storage/maria/ma_pagecache.c:
When taking a checkpoint, we don't need to know the maximum rec_lsn
of dirty pages; this LSN was intended to be used in the two-checkpoint
rule, but last_checkpoint_lsn is as good.
4 bytes for stored_list_size is enough as PAGECACHE::blocks (number
of blocks which the pagecache can contain) is int.
storage/maria/ma_pagecache.h:
new prototype
storage/maria/ma_recovery.c:
* added replaying of REDO_RENAME_TABLE
* UNDO_ROW_PURGE gone (see ma_blockrec.c), replaced by CLR_END
* Recovery from the last checkpoint record now possible
* In new_table() we skip the table if the id->name mapping is older than
create_rename_lsn (mapping dates from lsn_of_file_id).
* in get_MARIA_HA_from_REDO_record() we skip the record
if the id->name mapping is newer than the record (can happen if processing
a record which is before the checkpoint record).
* parse_checkpoint_record() has to return a LSN, that's what caller expects
storage/maria/ma_rename.c:
new function's name; log end zeroes of tables' names (ease recovery)
storage/maria/ma_test2.c:
* equivalent of ma_test1's --test-undo added (named -u here).
* -t=1 now stops right after creating the table, so that
we can test undoing of INSERTs with duplicate keys (which tests the
CLR_END logged by _ma_write_abort_block_record()).
storage/maria/ma_test_recovery.expected:
Result of testing undoing of INSERTs with duplicate keys; there are
some differences in maria_chk -dvv but they are normal (removing
records does not shrink data/index file, does not put back the
"analyzed, optimized keys"(etc) index state.
storage/maria/ma_test_recovery:
Test undoing of INSERTs with duplicate keys, using ma_test2;
when such INSERT happens, it logs REDO_INSERT, UNDO_INSERT, REDO_DELETE,
CLR_END; we abort after that, and test that CLR_END causes recovery
to jump over UNDO_INSERT.
storage/maria/ma_write.c:
comment
storage/maria/maria_chk.c:
comment
storage/maria/maria_def.h:
* a new bit in MARIA_SHARE::in_checkpoint, used to build a list
of unique shares during Checkpoint.
* MARIA_SHARE::lsn_of_file_id added: the LSN of the last LOGREC_FILE_ID
for this share; needed to know to which LSN domain the mappings
found in the Checkpoint record apply (new mappings should not apply
to old REDOs).
storage/maria/trnman.c:
* small changes to how trnman_collect_transactions() fills its buffer;
it also uses a non-dummy lsn_read_non_atomic() found in ma_checkpoint.h
2007-09-12 11:27:34 +02:00
This is the only case where create_rename_lsn can be a horizon and not
a LSN .
2007-06-27 12:58:08 +02:00
*/
Maria:
* Don't modify share->base.born_transactional; now it is a value carved
in stone at creation time. share->now_transactional is what can be
modified: it starts at born_transactional, can become false during
ALTER TABLE (when we want no logging), and restored later.
* Not resetting create_rename_lsn to 0 during delete_all or repair.
* when we temporarily disable transactionality, we also change
the page type to PAGECACHE_PLAIN_PAGE: it bypasses some work in the
page cache (optimization), and avoids assertions related to LSNs.
* Disable INSERT DELAYED for transactional tables, because
durability could not be guaranteed (insertion may even not happen)
mysys/mf_keycache.c:
comment
storage/maria/ha_maria.cc:
* a transactional table cannot do INSERT DELAYED
* ha_maria::save_transactional not needed anymore, as now instead
we don't modify MARIA_SHARE::MARIA_BASE_INFO::born_transactional
(born_transactional plays the role of save_transactional), and modify
MARIA_SHARE::now_transactional.
* REPAIR_TABLE log record is now logged by maria_repair()
* comment why we rely on born_transactional to know if we should
skipping a transaction.
* putting together two if()s which test for F_UNLCK
storage/maria/ha_maria.h:
ha_maria::save_transactional not needed anymore (moved to the C layer)
storage/maria/ma_blockrec.c:
* For the block record's code (writing/updating/deleting records),
all that counts is now_transactional, not born_transactional.
* As we now set the page type to PAGECACHE_PLAIN_PAGE for tables
which have now_transactional==FALSE, pagecache will not expect
a meaningful LSN for them in pagecache_unlock_by_link(), so
we can pass it LSN_IMPOSSIBLE.
storage/maria/ma_check.c:
* writing LOGREC_REPAIR_TABLE moves from ha_maria::repair()
to maria_repair(), sounds cleaner (less functions to export).
* when opening a table during REPAIR, don't use the realpath-ed name,
as this may fail if the table has symlinked files (maria_open()
would try to find the data and index file in the directory
of unique_file_name, it would fail if data and index files are in
different dirs); use the unresolved name, open_file_name, which is
the argument which was passed to the maria_open() which created 'info'.
storage/maria/ma_close.c:
assert that when a statement is done with a table, it cleans up
storage/maria/ma_create.c:
new name
storage/maria/ma_delete_all.c:
* using now_transactional
* no reason to reset create_rename_lsn during delete_all (a bug);
also no reason to do it during repair: it was put there because
a positive create_rename_lsn caused a call to check_and_set_lsn()
which asserted in DBUG_ASSERT(block->type == PAGECACHE_LSN_PAGE);
first solution was to use LSN_IMPOSSIBLE in _ma_unpin_all_pages() if
not transactional; but then in the case of ALTER TABLE, with
transactionality temporarily disabled, it asserted in
DBUG_ASSERT(LSN_VALID(lsn)) in pagecache_fwrite() (PAGECACHE_LSN_PAGE
page with zero LSN - bad). The additional solution is to use
PAGECACHE_PLAIN_PAGE when we disable transactionality temporarily: this
avoids checks on the LSN, and also bypasses (optimization) the "flush
log up to LSN" call when the pagecache flushes our page (in other
words, no WAL needed).
storage/maria/ma_delete_table.c:
use now_transactional
storage/maria/ma_locking.c:
assert that when a statement is done with a table, it cleans up.
storage/maria/ma_loghandler.c:
* now_transactional should be used to test if we want a log record.
* Assertions to make sure dummy_transaction_object is not spoilt
by its many users.
storage/maria/ma_open.c:
base.transactional -> base.born_transactional
storage/maria/ma_pagecache.c:
missing name for page's type. Comment for future.
storage/maria/ma_rename.c:
use now_transactional
storage/maria/maria_chk.c:
use born_transactional
storage/maria/maria_def.h:
MARIA_BASE_INFO::transactional renamed to born_transactional.
MARIA_SHARE::now_transactional introduced.
_ma_repair_write_log_record() is made local to ma_check.c.
Macros to temporarily disable, and re-enable, transactionality for a
table.
storage/maria/maria_read_log.c:
assertions and using the new macros. Adding a forgotten resetting
when we finally close all tables.
2007-07-03 15:20:41 +02:00
if ( share - > base . born_transactional )
WL#3071 Maria checkpoint
Finally this is the real checkpoint code.
It however exhibits unstabilities when a checkpoint runs concurrently
with data-modifying clients (table corruption, transaction log's
assertions) so for now a checkpoint is taken only at startup after
recovery and at shutdown, i.e. not in concurrent situations. Later
we will let it run periodically, as well as flush dirty pages
periodically (almost all needed code is there already, only pagecache
code is written but not committed).
WL#3072 Maria recovery
* replacing UNDO_ROW_PURGE with CLR_END; testing of those CLR_END via
ma_test2 which has INSERTs failing with duplicate keys.
* replaying of REDO_RENAME_TABLE
Now, off to test Recovery in ha_maria :)
BitKeeper/deleted/.del-ma_least_recently_dirtied.c:
Delete: storage/maria/ma_least_recently_dirtied.c
BitKeeper/deleted/.del-ma_least_recently_dirtied.h:
Delete: storage/maria/ma_least_recently_dirtied.h
storage/maria/Makefile.am:
compile Checkpoint module
storage/maria/ha_maria.cc:
When ha_maria starts, do a recovery from last checkpoint.
Take a checkpoint when that recovery has ended and when ha_maria
shuts down cleanly.
storage/maria/ma_blockrec.c:
* even if my_sync() fails we have to my_close() (otherwise we leak
a descriptor)
* UNDO_ROW_PURGE is replaced by a simple CLR_END for UNDO_ROW_INSERT,
as promised in the old comment; it gives us skipping during the
UNDO phase.
storage/maria/ma_check.c:
All REDOs before create_rename_lsn are ignored by Recovery. So
create_rename_lsn must be set only after all data/index has been
flushed and forced to disk. We thus move write_log_record_for_repair()
to after _ma_flush_tables_files_after_repair().
storage/maria/ma_checkpoint.c:
Checkpoint module.
storage/maria/ma_checkpoint.h:
optional argument if caller wants a thread to periodically take
checkpoints and flush dirty pages.
storage/maria/ma_create.c:
* no need to init some vars as the initial bzero(share) takes care of this.
* update to new function's name
* even if we fail in my_sync() we have to my_close()
storage/maria/ma_extra.c:
Checkpoint reads share->last_version under intern_lock, so we make
maria_extra() update it under intern_lock. THR_LOCK_maria still needed
because of _ma_test_if_reopen().
storage/maria/ma_init.c:
destroy checkpoint module when Maria shuts down.
storage/maria/ma_loghandler.c:
* UNDO_ROW_PURGE gone (see ma_blockrec.c)
* we need to remember the LSN of the LOGREC_FILE_ID for a share,
because this LSN is needed into the checkpoint record (Recovery wants
to know the validity domain of an id->name mapping)
* translog_get_horizon_no_lock() needed for Checkpoint
* comment about failing assertion (Sanja knows)
* translog_init_reader_data() thought that translog_read_record_header_scan()
returns 0 in case of error, but 0 just means "0-length header".
* translog_assign_id_to_share() now needs the MARIA_HA because
LOGREC_FILE_ID uses a log-write hook.
* Verify that (de)assignment of share->id happens only under intern_lock,
as Checkpoint reads this id with intern_lock.
* translog_purge() can accept TRANSLOG_ADDRESS, not necessarily
a real LSN.
storage/maria/ma_loghandler.h:
prototype updates
storage/maria/ma_open.c:
no need to initialize "res"
storage/maria/ma_pagecache.c:
When taking a checkpoint, we don't need to know the maximum rec_lsn
of dirty pages; this LSN was intended to be used in the two-checkpoint
rule, but last_checkpoint_lsn is as good.
4 bytes for stored_list_size is enough as PAGECACHE::blocks (number
of blocks which the pagecache can contain) is int.
storage/maria/ma_pagecache.h:
new prototype
storage/maria/ma_recovery.c:
* added replaying of REDO_RENAME_TABLE
* UNDO_ROW_PURGE gone (see ma_blockrec.c), replaced by CLR_END
* Recovery from the last checkpoint record now possible
* In new_table() we skip the table if the id->name mapping is older than
create_rename_lsn (mapping dates from lsn_of_file_id).
* in get_MARIA_HA_from_REDO_record() we skip the record
if the id->name mapping is newer than the record (can happen if processing
a record which is before the checkpoint record).
* parse_checkpoint_record() has to return a LSN, that's what caller expects
storage/maria/ma_rename.c:
new function's name; log end zeroes of tables' names (ease recovery)
storage/maria/ma_test2.c:
* equivalent of ma_test1's --test-undo added (named -u here).
* -t=1 now stops right after creating the table, so that
we can test undoing of INSERTs with duplicate keys (which tests the
CLR_END logged by _ma_write_abort_block_record()).
storage/maria/ma_test_recovery.expected:
Result of testing undoing of INSERTs with duplicate keys; there are
some differences in maria_chk -dvv but they are normal (removing
records does not shrink data/index file, does not put back the
"analyzed, optimized keys"(etc) index state.
storage/maria/ma_test_recovery:
Test undoing of INSERTs with duplicate keys, using ma_test2;
when such INSERT happens, it logs REDO_INSERT, UNDO_INSERT, REDO_DELETE,
CLR_END; we abort after that, and test that CLR_END causes recovery
to jump over UNDO_INSERT.
storage/maria/ma_write.c:
comment
storage/maria/maria_chk.c:
comment
storage/maria/maria_def.h:
* a new bit in MARIA_SHARE::in_checkpoint, used to build a list
of unique shares during Checkpoint.
* MARIA_SHARE::lsn_of_file_id added: the LSN of the last LOGREC_FILE_ID
for this share; needed to know to which LSN domain the mappings
found in the Checkpoint record apply (new mappings should not apply
to old REDOs).
storage/maria/trnman.c:
* small changes to how trnman_collect_transactions() fills its buffer;
it also uses a non-dummy lsn_read_non_atomic() found in ma_checkpoint.h
2007-09-12 11:27:34 +02:00
share - > state . create_rename_lsn = share - > state . is_of_horizon =
WL#3072 - Maria Recovery
Bulk insert: don't log REDO/UNDO for rows, log one UNDO which will
truncate files; this is an optimization and a bugfix (table was left
half-repaired by crash).
Repair: mark table crashed-on-repair at start, bump skip_redo_lsn at start,
this is easier for recovery (tells it to skip old REDOs or even UNDO
phase) and user (tells it to repair) in case of crash, sync files
in the end.
Recovery skips missing or corrupted table and moves to next record
(in REDO or UNDO phase) to be more robust; warns if happens in UNDO phase.
Bugfix for UNDO_KEY_DELETE_WITH_ROOT (tested in ma_test_recovery)
and maria_enable_indexes().
Create missing bitmaps when needed (there can be more than one to create,
in rare cases), log a record for this.
include/myisamchk.h:
new flag: bulk insert repair mustn't bump create_rename_lsn
mysql-test/lib/mtr_report.pl:
skip normal warning in maria-recovery.test
mysql-test/r/maria-recovery.result:
result: crash before bulk insert is committed, causes proper rollback,
and crash right after OPTIMIZE replaces index file with new index file
leads to table marked corrupted and recovery not failing.
mysql-test/t/maria-recovery.test:
- can't check the table or it would commit the transaction,
but check is made after recovery.
- test of crash before bulk-insert-with-repair is committed
(to see if it is rolled back), and of crash after OPTIMIZE has replaced
index file but not finished all operations (to see if recovery fails -
it used to assert when trying to execute an old REDO on the new
index).
storage/maria/CMakeLists.txt:
new file
storage/maria/Makefile.am:
new file
storage/maria/ha_maria.cc:
- If bulk insert on a transactional table using an index repair:
table is initially empty, so don't log REDO/UNDO for data rows
(optimization), just log an UNDO_BULK_INSERT_WITH_REPAIR
which will, if executed, empty the data and index file. Re-enable
logging in end_bulk_insert().
- write log record for repair operation only after it's fully done,
index sort including (maria_repair*() used to write the log record).
- Adding back file->trn=NULL which was removed by mistake earlier.
storage/maria/ha_maria.h:
new member (see ha_maria.cc)
storage/maria/ma_bitmap.c:
Functions to create missing bitmaps:
- one function which creates missing bitmaps in page cache, except
the missing one with max offset which it does not put into page cache
as it will be modified very soon.
- one function which the one above calls, and creates bitmaps in page
cache
- one function to execute REDO_BITMAP_NEW_PAGE which uses the second
one above.
storage/maria/ma_blockrec.c:
- when logging REDO_DELETE_ALL, not only 'records' and 'checksum'
has to be reset under log's mutex.
- execution of REDO_INSERT_ROW_BLOBS now checks the dirty pages' list
- execution of UNDO_BULK_INSERT_WITH_REPAIR
storage/maria/ma_blockrec.h:
new functions
storage/maria/ma_check.c:
- table-flush-before-repair is moved to a separate function reused
by maria_sort_index(); syncing is added
- maria_repair() is allowed to re-enable logging only if it is the one
which disabled it.
- "_ma_flush_table_files_after_repair" was a bad name, it's not after
repair now, and it should not sync as we do more changes to the files
shortly after (sync is postponed to when writing the log record)
- REDO_REPAIR record should be written only after all repair
operations (in particular after sorting index in ha_mara::repair())
- close to the end of repair by sort, flushing of pages must happen
also in the non-quick case, to prepare for the sync at end.
- in parallel repair, some page flushes are not needed as done
by initialize_variables_for_repair().
storage/maria/ma_create.c:
Update skip_redo_lsn, create_rename_lsn optionally.
storage/maria/ma_delete_all.c:
Need to sync files at end of maria_delete_all_rows(), if transactional.
storage/maria/ma_extra.c:
During repair, we sometimes call _ma_flush_table_files() (via
_ma_flush_table_files_before_swap()) while there is a WRITE_CACHE.
storage/maria/ma_key_recover.c:
- when we see CLR_END for UNDO_BULK_INSERT_WITH_REPAIR, re-enable
indices.
- fixing bug: _ma_apply_undo_key_delete() parsed UNDO_KEY_DELETE_WITH_ROOT
wrongly, leading to recovery failure
storage/maria/ma_key_recover.h:
new prototype
storage/maria/ma_locking.c:
DBUG_VOID_RETURN missing
storage/maria/ma_loghandler.c:
UNDO for bulk insert with repair, and REDO for creating bitmaps.
LOGREC_FIRST_FREE to not have to change the for() every time we
add a new record type.
storage/maria/ma_loghandler.h:
new UNDO and REDO
storage/maria/ma_open.c:
Move share.kfile.file=kfile up a bit, so that _ma_update_state_lsns()
can get its value, this fixes a bug where LSN_REPAIRED_BY_MARIA_CHK
was not corrected on disk by maria_open().
Store skip_redo_lsn in index' header.
maria_enable_indexes() had a bug for BLOCK_RECORD, where an empty
file has one page, not 0 bytes.
storage/maria/ma_recovery.c:
- Skip a corrupted, missing, or repaired-with-maria_chk, table in
recovery: don't fail, just go to next REDO or UNDO; but if an UNDO
is skipped in UNDO phase we issue warnings.
- Skip REDO|UNDO in REDO phase if <skip_redo_lsn.
- If UNDO phase fails, delete transactions to not make trnman
assert.
- Update skip_redo_lsn when playing REDO_CREATE_TABLE
- Don't record UNDOs for old transactions which we don't know (long_trid==0)
- Bugfix for UNDO_KEY_DELETE_WITH_ROOT (see ma_key_recover.c)
- Execution of UNDO_BULK_INSERT_WITH_REPAIR
- Don't try to find a page number in REDO_DELETE_ALL
- Pieces moved to ma_recovery_util.c
storage/maria/ma_rename.c:
name change
storage/maria/ma_static.c:
I modified layout of the index' header (inserted skip_redo_lsn in its middle)
storage/maria/ma_test2.c:
allow breaking the test towards the end, tests execution of
UNDO_KEY_DELETE_WITH_ROOT
storage/maria/ma_test_recovery.expected:
6 as testflag instead of 4
storage/maria/ma_test_recovery:
Increase the amount of rollback work to do when testing recovery
with ma_test2; this reproduces the UNDO_KEY_DELETE_WITH_ROOT bug.
storage/maria/maria_chk.c:
skip_redo_lsn should be updated too, for consistency.
Write a REDO_REPAIR after all operations (including sort-records)
have been done.
No reason to flush blocks after maria_chk_data_link() and
maria_sort_records(), there is maria_close() in the end.
write_log_record() is a function, to not clutter maria_chk().
storage/maria/maria_def.h:
New member skip_redo_lsn in the state, and comments
storage/maria/maria_pack.c:
skip_redo_lsn should be updated too, for consistency
storage/maria/ma_recovery_util.c:
_ma_redo_not_needed_for_page(), defined in ma_recovery.c, is needed
by ma_blockrec.c; this causes link issues, resolved by putting
_ma_redo_not_needed_for_page() into a new file (so that it is not
in the same file as repair-related objects of ma_recovery.c).
storage/maria/ma_recovery_util.h:
new file
2008-01-17 23:59:32 +01:00
share - > state . skip_redo_lsn = LSN_REPAIRED_BY_MARIA_CHK ;
2007-12-31 10:55:46 +01:00
}
if ( ! error & & ( param - > testflag & T_REP_ANY ) )
{
2007-04-19 17:48:36 +02:00
if ( ( param - > testflag & ( T_REP_BY_SORT | T_REP_PARALLEL ) ) & &
( maria_is_any_key_active ( share - > state . key_map ) | |
( rep_quick & & ! param - > keys_in_use & & ! recreate ) ) & &
maria_test_if_sort_rep ( info , info - > state - > records ,
info - > s - > state . key_map ,
param - > force_sort ) )
2006-04-11 15:45:10 +02:00
{
2007-04-19 17:48:36 +02:00
if ( param - > testflag & T_REP_BY_SORT )
error = maria_repair_by_sort ( param , info , filename , rep_quick ) ;
else
error = maria_repair_parallel ( param , info , filename , rep_quick ) ;
state_updated = 1 ;
2006-04-11 15:45:10 +02:00
}
2007-12-31 10:55:46 +01:00
else
2007-04-19 17:48:36 +02:00
error = maria_repair ( param , info , filename , rep_quick ) ;
}
2007-12-31 10:55:46 +01:00
if ( ! error & & ( param - > testflag & T_SORT_RECORDS ) )
2007-04-19 17:48:36 +02:00
{
/*
The data file is nowadays reopened in the repair code so we should
soon remove the following reopen - code
*/
# ifndef TO_BE_REMOVED
if ( param - > out_flag & O_NEW_DATA )
{ /* Change temp file to org file */
VOID ( my_close ( info - > dfile . file , MYF ( MY_WME ) ) ) ; /* Close new file */
error | = maria_change_to_newfile ( filename , MARIA_NAME_DEXT , DATA_TMP_EXT ,
MYF ( 0 ) ) ;
if ( _ma_open_datafile ( info , info - > s , - 1 ) )
error = 1 ;
param - > out_flag & = ~ O_NEW_DATA ; /* We are using new datafile */
param - > read_cache . file = info - > dfile . file ;
2006-04-11 15:45:10 +02:00
}
2007-04-19 17:48:36 +02:00
# endif
if ( ! error )
2006-04-11 15:45:10 +02:00
{
2007-04-19 17:48:36 +02:00
uint key ;
/*
We can ' t update the index in maria_sort_records if we have a
prefix compressed or fulltext index
*/
my_bool update_index = 1 ;
for ( key = 0 ; key < share - > base . keys ; key + + )
if ( share - > keyinfo [ key ] . flag & ( HA_BINARY_PACK_KEY | HA_FULLTEXT ) )
update_index = 0 ;
error = maria_sort_records ( param , info , filename , param - > opt_sort_key ,
/* what is the following parameter for ? */
( my_bool ) ! ( param - > testflag & T_REP ) ,
update_index ) ;
datafile = info - > dfile . file ; /* This is now locked */
if ( ! error & & ! update_index )
{
if ( param - > verbose )
puts ( " Table had a compressed index; We must now recreate the index " ) ;
error = maria_repair_by_sort ( param , info , filename , 1 ) ;
}
2006-04-11 15:45:10 +02:00
}
}
2007-12-31 10:55:46 +01:00
if ( ! error & & ( param - > testflag & T_SORT_INDEX ) )
error = maria_sort_index ( param , info , filename ) ;
if ( ! error & & ( param - > testflag & T_ZEROFILL ) )
error = maria_zerofill ( param , info , filename ) ;
2007-04-19 17:48:36 +02:00
if ( ! error )
share - > state . changed & = ~ ( STATE_CHANGED | STATE_CRASHED |
STATE_CRASHED_ON_REPAIR ) ;
else
maria_mark_crashed ( info ) ;
}
else if ( ( param - > testflag & T_CHECK ) | | ! ( param - > testflag & T_AUTO_INC ) )
{
if ( ! ( param - > testflag & T_SILENT ) | | param - > testflag & T_INFO )
printf ( " Checking MARIA file: %s \n " , filename ) ;
if ( ! ( param - > testflag & T_SILENT ) )
printf ( " Data records: %7s Deleted blocks: %7s \n " ,
llstr ( info - > state - > records , llbuff ) ,
llstr ( info - > state - > del , llbuff2 ) ) ;
error = maria_chk_status ( param , info ) ;
maria_intersect_keys_active ( share - > state . key_map , param - > keys_in_use ) ;
error = maria_chk_size ( param , info ) ;
if ( ! error | | ! ( param - > testflag & ( T_FAST | T_FORCE_CREATE ) ) )
error | = maria_chk_del ( param , info , param - > testflag ) ;
if ( ( ! error | | ( ! ( param - > testflag & ( T_FAST | T_FORCE_CREATE ) ) & &
! param - > start_check_pos ) ) )
{
error | = maria_chk_key ( param , info ) ;
if ( ! error & & ( param - > testflag & ( T_STATISTICS | T_AUTO_INC ) ) )
error = maria_update_state_info ( param , info ,
( ( param - > testflag & T_STATISTICS ) ?
UPDATE_STAT : 0 ) |
( ( param - > testflag & T_AUTO_INC ) ?
UPDATE_AUTO_INC : 0 ) ) ;
}
if ( ( ! rep_quick & & ! error ) | |
! ( param - > testflag & ( T_FAST | T_FORCE_CREATE ) ) )
{
VOID ( init_io_cache ( & param - > read_cache , datafile ,
( uint ) param - > read_buffer_length ,
READ_CACHE ,
( param - > start_check_pos ?
param - > start_check_pos :
share - > pack . header_length ) ,
1 ,
MYF ( MY_WME ) ) ) ;
maria_lock_memory ( param ) ;
if ( ( info - > s - > data_file_type ! = STATIC_RECORD ) | |
( param - > testflag & ( T_EXTEND | T_MEDIUM ) ) )
2008-01-10 20:21:36 +01:00
error | = maria_chk_data_link ( param , info ,
test ( param - > testflag & T_EXTEND ) ) ;
2007-04-19 17:48:36 +02:00
VOID ( end_io_cache ( & param - > read_cache ) ) ;
}
if ( ! error )
{
if ( ( share - > state . changed & STATE_CHANGED ) & &
( param - > testflag & T_UPDATE_STATE ) )
info - > update | = HA_STATE_CHANGED | HA_STATE_ROW_CHANGED ;
share - > state . changed & = ~ ( STATE_CHANGED | STATE_CRASHED |
STATE_CRASHED_ON_REPAIR ) ;
}
else if ( ! maria_is_crashed ( info ) & &
( param - > testflag & T_UPDATE_STATE ) )
{ /* Mark crashed */
maria_mark_crashed ( info ) ;
info - > update | = HA_STATE_CHANGED | HA_STATE_ROW_CHANGED ;
}
2006-04-11 15:45:10 +02:00
}
2007-04-19 17:48:36 +02:00
2006-04-11 15:45:10 +02:00
if ( ( param - > testflag & T_AUTO_INC ) | |
( ( param - > testflag & T_REP_ANY ) & & info - > s - > base . auto_key ) )
_ma_update_auto_increment_key ( param , info ,
( my_bool ) ! test ( param - > testflag & T_AUTO_INC ) ) ;
2007-04-19 17:48:36 +02:00
if ( info - > update & HA_STATE_CHANGED & & ! ( param - > testflag & T_READONLY ) )
error | = maria_update_state_info ( param , info ,
UPDATE_OPEN_COUNT |
( ( ( param - > testflag & T_REP_ANY ) ?
UPDATE_TIME : 0 ) |
( state_updated ? UPDATE_STAT : 0 ) |
( ( param - > testflag & T_SORT_RECORDS ) ?
UPDATE_SORT : 0 ) ) ) ;
info - > update & = ~ HA_STATE_CHANGED ;
- fix for segfault in rpl_trigger/rpl_found_rows with default engine=maria
(fix is keeping the real TRN through a disable_logging/reenable cycle)
- fix for pagecache assertion failure in ps/type_ranges with default
engine=maria (fix is in sql_insert.cc)
- when reenabling logging we must either flush all dirty pages,
or at least verify (in debug build) that there are none. For example
a bulk insert with single UNDO_BULK_INSERT must flush them, no matter
if it uses repair or not (bugfix)
- UNDO_BULK_INSERT_WITH_REPAIR is also used with repair, changes name
mysql-test/r/maria.result:
tests for bugs fixed
mysql-test/t/maria.test:
tests for bugs fixed
sql/sql_insert.cc:
Bugfix: even if select_create::prepare() failed to create the 'table' object
we still have to re-enable logging.
storage/maria/ha_maria.cc:
Bugfix: when a transactional table does a bulk insert without
repair, it still sometimes skips logging of REDOs thus needs a full
flush and sync at the end. Not if repair is done, as repair does
it internally already (see end of maria_repair*()).
storage/maria/ha_maria.h:
variable now can have 3 states not 2
storage/maria/ma_bitmap.c:
name change
storage/maria/ma_blockrec.c:
name change
storage/maria/ma_blockrec.h:
name change
storage/maria/ma_check.c:
* When maria_repair() re-enables logging it does not need to ask for
a flush&sync as it did it by itself already a few lines before.
* the log record of bulk insert can be used even without repair
* disable logging in maria_zerofill(): without that, it puts LSN pages
in the cache, so when it flushes them it flushes the log; the change
makes auto-ha_maria::zerofill-if-moved faster (no log flush).
storage/maria/ma_key_recover.c:
name change
storage/maria/ma_loghandler.c:
name change
storage/maria/ma_loghandler.h:
name change
storage/maria/ma_pagecache.c:
A function, to check in debug builds that no dirty pages exist for a file.
storage/maria/ma_pagecache.h:
new function (nothing in non-debug)
storage/maria/ma_recovery.c:
_ma_tmp_disable_logging() sets info->trn to dummy_transaction_object
when needed now. The changes done here about info->trn are to allow
a table to retain its original, real TRN through a disable/reenable
cycle (see replication scenario in _ma_reenable_logging_for_table()).
When we reenable, we offer the caller to flush and sync the table;
if the caller doesn't accept our offer, we verify that it's ok
(no REDOs => no dirty pages are allowed to exist).
storage/maria/maria_chk.c:
comment
storage/maria/maria_def.h:
new names
mysql-test/suite/rpl/r/rpl_stm_maria.result:
result (it used to crash)
mysql-test/suite/rpl/t/rpl_stm_maria.test:
Test of replication-specific Maria bug fixed
2008-01-20 05:25:26 +01:00
_ma_reenable_logging_for_table ( info , FALSE ) ;
2006-04-11 15:45:10 +02:00
maria_lock_database ( info , F_UNLCK ) ;
2007-04-19 17:48:36 +02:00
2006-04-11 15:45:10 +02:00
end2 :
2007-04-19 17:48:36 +02:00
end_pagecache ( maria_pagecache , 1 ) ;
2006-04-11 15:45:10 +02:00
if ( maria_close ( info ) )
{
WL#3072 - Maria Recovery
Bulk insert: don't log REDO/UNDO for rows, log one UNDO which will
truncate files; this is an optimization and a bugfix (table was left
half-repaired by crash).
Repair: mark table crashed-on-repair at start, bump skip_redo_lsn at start,
this is easier for recovery (tells it to skip old REDOs or even UNDO
phase) and user (tells it to repair) in case of crash, sync files
in the end.
Recovery skips missing or corrupted table and moves to next record
(in REDO or UNDO phase) to be more robust; warns if happens in UNDO phase.
Bugfix for UNDO_KEY_DELETE_WITH_ROOT (tested in ma_test_recovery)
and maria_enable_indexes().
Create missing bitmaps when needed (there can be more than one to create,
in rare cases), log a record for this.
include/myisamchk.h:
new flag: bulk insert repair mustn't bump create_rename_lsn
mysql-test/lib/mtr_report.pl:
skip normal warning in maria-recovery.test
mysql-test/r/maria-recovery.result:
result: crash before bulk insert is committed, causes proper rollback,
and crash right after OPTIMIZE replaces index file with new index file
leads to table marked corrupted and recovery not failing.
mysql-test/t/maria-recovery.test:
- can't check the table or it would commit the transaction,
but check is made after recovery.
- test of crash before bulk-insert-with-repair is committed
(to see if it is rolled back), and of crash after OPTIMIZE has replaced
index file but not finished all operations (to see if recovery fails -
it used to assert when trying to execute an old REDO on the new
index).
storage/maria/CMakeLists.txt:
new file
storage/maria/Makefile.am:
new file
storage/maria/ha_maria.cc:
- If bulk insert on a transactional table using an index repair:
table is initially empty, so don't log REDO/UNDO for data rows
(optimization), just log an UNDO_BULK_INSERT_WITH_REPAIR
which will, if executed, empty the data and index file. Re-enable
logging in end_bulk_insert().
- write log record for repair operation only after it's fully done,
index sort including (maria_repair*() used to write the log record).
- Adding back file->trn=NULL which was removed by mistake earlier.
storage/maria/ha_maria.h:
new member (see ha_maria.cc)
storage/maria/ma_bitmap.c:
Functions to create missing bitmaps:
- one function which creates missing bitmaps in page cache, except
the missing one with max offset which it does not put into page cache
as it will be modified very soon.
- one function which the one above calls, and creates bitmaps in page
cache
- one function to execute REDO_BITMAP_NEW_PAGE which uses the second
one above.
storage/maria/ma_blockrec.c:
- when logging REDO_DELETE_ALL, not only 'records' and 'checksum'
has to be reset under log's mutex.
- execution of REDO_INSERT_ROW_BLOBS now checks the dirty pages' list
- execution of UNDO_BULK_INSERT_WITH_REPAIR
storage/maria/ma_blockrec.h:
new functions
storage/maria/ma_check.c:
- table-flush-before-repair is moved to a separate function reused
by maria_sort_index(); syncing is added
- maria_repair() is allowed to re-enable logging only if it is the one
which disabled it.
- "_ma_flush_table_files_after_repair" was a bad name, it's not after
repair now, and it should not sync as we do more changes to the files
shortly after (sync is postponed to when writing the log record)
- REDO_REPAIR record should be written only after all repair
operations (in particular after sorting index in ha_mara::repair())
- close to the end of repair by sort, flushing of pages must happen
also in the non-quick case, to prepare for the sync at end.
- in parallel repair, some page flushes are not needed as done
by initialize_variables_for_repair().
storage/maria/ma_create.c:
Update skip_redo_lsn, create_rename_lsn optionally.
storage/maria/ma_delete_all.c:
Need to sync files at end of maria_delete_all_rows(), if transactional.
storage/maria/ma_extra.c:
During repair, we sometimes call _ma_flush_table_files() (via
_ma_flush_table_files_before_swap()) while there is a WRITE_CACHE.
storage/maria/ma_key_recover.c:
- when we see CLR_END for UNDO_BULK_INSERT_WITH_REPAIR, re-enable
indices.
- fixing bug: _ma_apply_undo_key_delete() parsed UNDO_KEY_DELETE_WITH_ROOT
wrongly, leading to recovery failure
storage/maria/ma_key_recover.h:
new prototype
storage/maria/ma_locking.c:
DBUG_VOID_RETURN missing
storage/maria/ma_loghandler.c:
UNDO for bulk insert with repair, and REDO for creating bitmaps.
LOGREC_FIRST_FREE to not have to change the for() every time we
add a new record type.
storage/maria/ma_loghandler.h:
new UNDO and REDO
storage/maria/ma_open.c:
Move share.kfile.file=kfile up a bit, so that _ma_update_state_lsns()
can get its value, this fixes a bug where LSN_REPAIRED_BY_MARIA_CHK
was not corrected on disk by maria_open().
Store skip_redo_lsn in index' header.
maria_enable_indexes() had a bug for BLOCK_RECORD, where an empty
file has one page, not 0 bytes.
storage/maria/ma_recovery.c:
- Skip a corrupted, missing, or repaired-with-maria_chk, table in
recovery: don't fail, just go to next REDO or UNDO; but if an UNDO
is skipped in UNDO phase we issue warnings.
- Skip REDO|UNDO in REDO phase if <skip_redo_lsn.
- If UNDO phase fails, delete transactions to not make trnman
assert.
- Update skip_redo_lsn when playing REDO_CREATE_TABLE
- Don't record UNDOs for old transactions which we don't know (long_trid==0)
- Bugfix for UNDO_KEY_DELETE_WITH_ROOT (see ma_key_recover.c)
- Execution of UNDO_BULK_INSERT_WITH_REPAIR
- Don't try to find a page number in REDO_DELETE_ALL
- Pieces moved to ma_recovery_util.c
storage/maria/ma_rename.c:
name change
storage/maria/ma_static.c:
I modified layout of the index' header (inserted skip_redo_lsn in its middle)
storage/maria/ma_test2.c:
allow breaking the test towards the end, tests execution of
UNDO_KEY_DELETE_WITH_ROOT
storage/maria/ma_test_recovery.expected:
6 as testflag instead of 4
storage/maria/ma_test_recovery:
Increase the amount of rollback work to do when testing recovery
with ma_test2; this reproduces the UNDO_KEY_DELETE_WITH_ROOT bug.
storage/maria/maria_chk.c:
skip_redo_lsn should be updated too, for consistency.
Write a REDO_REPAIR after all operations (including sort-records)
have been done.
No reason to flush blocks after maria_chk_data_link() and
maria_sort_records(), there is maria_close() in the end.
write_log_record() is a function, to not clutter maria_chk().
storage/maria/maria_def.h:
New member skip_redo_lsn in the state, and comments
storage/maria/maria_pack.c:
skip_redo_lsn should be updated too, for consistency
storage/maria/ma_recovery_util.c:
_ma_redo_not_needed_for_page(), defined in ma_recovery.c, is needed
by ma_blockrec.c; this causes link issues, resolved by putting
_ma_redo_not_needed_for_page() into a new file (so that it is not
in the same file as repair-related objects of ma_recovery.c).
storage/maria/ma_recovery_util.h:
new file
2008-01-17 23:59:32 +01:00
_ma_check_print_error ( param , default_close_errmsg , my_errno , filename ) ;
2006-04-11 15:45:10 +02:00
DBUG_RETURN ( 1 ) ;
}
if ( error = = 0 )
{
if ( param - > out_flag & O_NEW_DATA )
error | = maria_change_to_newfile ( filename , MARIA_NAME_DEXT , DATA_TMP_EXT ,
2007-01-18 20:38:14 +01:00
( ( param - > testflag & T_BACKUP_DATA ) ?
MYF ( MY_REDEL_MAKE_BACKUP ) : MYF ( 0 ) ) ) ;
2006-04-11 15:45:10 +02:00
if ( param - > out_flag & O_NEW_INDEX )
2007-01-18 20:38:14 +01:00
error | = maria_change_to_newfile ( filename , MARIA_NAME_IEXT , INDEX_TMP_EXT ,
MYF ( 0 ) ) ;
2006-04-11 15:45:10 +02:00
}
WL#3072 - Maria Recovery
Bulk insert: don't log REDO/UNDO for rows, log one UNDO which will
truncate files; this is an optimization and a bugfix (table was left
half-repaired by crash).
Repair: mark table crashed-on-repair at start, bump skip_redo_lsn at start,
this is easier for recovery (tells it to skip old REDOs or even UNDO
phase) and user (tells it to repair) in case of crash, sync files
in the end.
Recovery skips missing or corrupted table and moves to next record
(in REDO or UNDO phase) to be more robust; warns if happens in UNDO phase.
Bugfix for UNDO_KEY_DELETE_WITH_ROOT (tested in ma_test_recovery)
and maria_enable_indexes().
Create missing bitmaps when needed (there can be more than one to create,
in rare cases), log a record for this.
include/myisamchk.h:
new flag: bulk insert repair mustn't bump create_rename_lsn
mysql-test/lib/mtr_report.pl:
skip normal warning in maria-recovery.test
mysql-test/r/maria-recovery.result:
result: crash before bulk insert is committed, causes proper rollback,
and crash right after OPTIMIZE replaces index file with new index file
leads to table marked corrupted and recovery not failing.
mysql-test/t/maria-recovery.test:
- can't check the table or it would commit the transaction,
but check is made after recovery.
- test of crash before bulk-insert-with-repair is committed
(to see if it is rolled back), and of crash after OPTIMIZE has replaced
index file but not finished all operations (to see if recovery fails -
it used to assert when trying to execute an old REDO on the new
index).
storage/maria/CMakeLists.txt:
new file
storage/maria/Makefile.am:
new file
storage/maria/ha_maria.cc:
- If bulk insert on a transactional table using an index repair:
table is initially empty, so don't log REDO/UNDO for data rows
(optimization), just log an UNDO_BULK_INSERT_WITH_REPAIR
which will, if executed, empty the data and index file. Re-enable
logging in end_bulk_insert().
- write log record for repair operation only after it's fully done,
index sort including (maria_repair*() used to write the log record).
- Adding back file->trn=NULL which was removed by mistake earlier.
storage/maria/ha_maria.h:
new member (see ha_maria.cc)
storage/maria/ma_bitmap.c:
Functions to create missing bitmaps:
- one function which creates missing bitmaps in page cache, except
the missing one with max offset which it does not put into page cache
as it will be modified very soon.
- one function which the one above calls, and creates bitmaps in page
cache
- one function to execute REDO_BITMAP_NEW_PAGE which uses the second
one above.
storage/maria/ma_blockrec.c:
- when logging REDO_DELETE_ALL, not only 'records' and 'checksum'
has to be reset under log's mutex.
- execution of REDO_INSERT_ROW_BLOBS now checks the dirty pages' list
- execution of UNDO_BULK_INSERT_WITH_REPAIR
storage/maria/ma_blockrec.h:
new functions
storage/maria/ma_check.c:
- table-flush-before-repair is moved to a separate function reused
by maria_sort_index(); syncing is added
- maria_repair() is allowed to re-enable logging only if it is the one
which disabled it.
- "_ma_flush_table_files_after_repair" was a bad name, it's not after
repair now, and it should not sync as we do more changes to the files
shortly after (sync is postponed to when writing the log record)
- REDO_REPAIR record should be written only after all repair
operations (in particular after sorting index in ha_mara::repair())
- close to the end of repair by sort, flushing of pages must happen
also in the non-quick case, to prepare for the sync at end.
- in parallel repair, some page flushes are not needed as done
by initialize_variables_for_repair().
storage/maria/ma_create.c:
Update skip_redo_lsn, create_rename_lsn optionally.
storage/maria/ma_delete_all.c:
Need to sync files at end of maria_delete_all_rows(), if transactional.
storage/maria/ma_extra.c:
During repair, we sometimes call _ma_flush_table_files() (via
_ma_flush_table_files_before_swap()) while there is a WRITE_CACHE.
storage/maria/ma_key_recover.c:
- when we see CLR_END for UNDO_BULK_INSERT_WITH_REPAIR, re-enable
indices.
- fixing bug: _ma_apply_undo_key_delete() parsed UNDO_KEY_DELETE_WITH_ROOT
wrongly, leading to recovery failure
storage/maria/ma_key_recover.h:
new prototype
storage/maria/ma_locking.c:
DBUG_VOID_RETURN missing
storage/maria/ma_loghandler.c:
UNDO for bulk insert with repair, and REDO for creating bitmaps.
LOGREC_FIRST_FREE to not have to change the for() every time we
add a new record type.
storage/maria/ma_loghandler.h:
new UNDO and REDO
storage/maria/ma_open.c:
Move share.kfile.file=kfile up a bit, so that _ma_update_state_lsns()
can get its value, this fixes a bug where LSN_REPAIRED_BY_MARIA_CHK
was not corrected on disk by maria_open().
Store skip_redo_lsn in index' header.
maria_enable_indexes() had a bug for BLOCK_RECORD, where an empty
file has one page, not 0 bytes.
storage/maria/ma_recovery.c:
- Skip a corrupted, missing, or repaired-with-maria_chk, table in
recovery: don't fail, just go to next REDO or UNDO; but if an UNDO
is skipped in UNDO phase we issue warnings.
- Skip REDO|UNDO in REDO phase if <skip_redo_lsn.
- If UNDO phase fails, delete transactions to not make trnman
assert.
- Update skip_redo_lsn when playing REDO_CREATE_TABLE
- Don't record UNDOs for old transactions which we don't know (long_trid==0)
- Bugfix for UNDO_KEY_DELETE_WITH_ROOT (see ma_key_recover.c)
- Execution of UNDO_BULK_INSERT_WITH_REPAIR
- Don't try to find a page number in REDO_DELETE_ALL
- Pieces moved to ma_recovery_util.c
storage/maria/ma_rename.c:
name change
storage/maria/ma_static.c:
I modified layout of the index' header (inserted skip_redo_lsn in its middle)
storage/maria/ma_test2.c:
allow breaking the test towards the end, tests execution of
UNDO_KEY_DELETE_WITH_ROOT
storage/maria/ma_test_recovery.expected:
6 as testflag instead of 4
storage/maria/ma_test_recovery:
Increase the amount of rollback work to do when testing recovery
with ma_test2; this reproduces the UNDO_KEY_DELETE_WITH_ROOT bug.
storage/maria/maria_chk.c:
skip_redo_lsn should be updated too, for consistency.
Write a REDO_REPAIR after all operations (including sort-records)
have been done.
No reason to flush blocks after maria_chk_data_link() and
maria_sort_records(), there is maria_close() in the end.
write_log_record() is a function, to not clutter maria_chk().
storage/maria/maria_def.h:
New member skip_redo_lsn in the state, and comments
storage/maria/maria_pack.c:
skip_redo_lsn should be updated too, for consistency
storage/maria/ma_recovery_util.c:
_ma_redo_not_needed_for_page(), defined in ma_recovery.c, is needed
by ma_blockrec.c; this causes link issues, resolved by putting
_ma_redo_not_needed_for_page() into a new file (so that it is not
in the same file as repair-related objects of ma_recovery.c).
storage/maria/ma_recovery_util.h:
new file
2008-01-17 23:59:32 +01:00
if ( opt_transaction_logging & &
share - > base . born_transactional & & ! error & &
( param - > testflag & ( T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX |
T_ZEROFILL ) ) )
error = write_log_record ( param ) ;
2006-04-11 15:45:10 +02:00
VOID ( fflush ( stdout ) ) ; VOID ( fflush ( stderr ) ) ;
if ( param - > error_printed )
{
if ( param - > testflag & ( T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX ) )
{
VOID ( fprintf ( stderr ,
" MARIA-table '%s' is not fixed because of errors \n " ,
filename ) ) ;
if ( param - > testflag & T_REP_ANY )
VOID ( fprintf ( stderr ,
" Try fixing it by using the --safe-recover (-o), the --force (-f) option or by not using the --quick (-q) flag \n " ) ) ;
}
else if ( ! ( param - > error_printed & 2 ) & &
! ( param - > testflag & T_FORCE_CREATE ) )
VOID ( fprintf ( stderr ,
" MARIA-table '%s' is corrupted \n Fix it using switch \" -r \" or \" -o \" \n " ,
filename ) ) ;
}
else if ( param - > warning_printed & &
! ( param - > testflag & ( T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX |
T_FORCE_CREATE ) ) )
VOID ( fprintf ( stderr , " MARIA-table '%s' is usable but should be fixed \n " ,
filename ) ) ;
VOID ( fflush ( stderr ) ) ;
DBUG_RETURN ( error ) ;
2007-01-18 20:38:14 +01:00
} /* maria_chk */
2006-04-11 15:45:10 +02:00
2007-01-18 20:38:14 +01:00
/* Write info about table */
2006-04-11 15:45:10 +02:00
2007-07-02 19:45:15 +02:00
static void descript ( HA_CHECK * param , register MARIA_HA * info , char * name )
2006-04-11 15:45:10 +02:00
{
2007-04-19 12:18:56 +02:00
uint key , keyseg_nr , field ;
2006-04-11 15:45:10 +02:00
reg3 MARIA_KEYDEF * keyinfo ;
reg2 HA_KEYSEG * keyseg ;
reg4 const char * text ;
2007-12-31 10:55:46 +01:00
char buff [ 200 ] , length [ 10 ] , * pos , * end ;
2006-04-11 15:45:10 +02:00
enum en_fieldtype type ;
2007-12-10 01:32:00 +01:00
MARIA_SHARE * share = info - > s ;
2006-04-11 15:45:10 +02:00
char llbuff [ 22 ] , llbuff2 [ 22 ] ;
UNDO of rows now puts back all part of the row on their original pages and positions
Added variable _dbug_on_ to speed up execution when DBUG is not going to be used
Added --debug-on option to mysqld (to be able to turn of DBUG with --debug-on=0)
Fixed some bugs with 'non_flushable' marking of bitmap pages
Don't use 'non_flushable' marking of bitmap pages for not transactional tables
SHOW CREATE TABLE now shows if table was created with page checksums
Fixed a lot of bugs with BLOB handling in case of update/REDO and UNDO
More tests (especially for blobs) and DBUG_ASSERTS()
More readable output from maria_read_log and maria_chk
Fixed wrong shift that caused Maria to crash on files > 4G
Mark tables as crashed of REDO fails
dbug/dbug.c:
Changed to use my_bool (allowed me to remove some windows specific code)
Added variable _dbug_on_ to speed up execution when DBUG is not going to be used
Removed initialization of variables if not needed
include/my_dbug.h:
Use my_bool for some functions that was defined as BOOLEAN in dbug.c code
Added DBUGGER_ON/DEBUGGER_OFF to speed up execution when DBUG is not used
include/my_global.h:
Define my_bool early
Increase MY_HOW_OFTEN_TO_WRITE as computers are now faster than 10 years ago
mysql-test/mysql-test-run.pl:
Added debug-on=0 to speed up tests
mysql-test/r/maria-recovery.result:
Added new test by Guilhem to test if UNDO_ROW_DELETE preserves rowid
mysql-test/r/maria.result:
Added testing of page checksums
mysql-test/t/crash_commit_before-master.opt:
Added --debug-on as test require DBUG to work
mysql-test/t/maria-recovery-bitmap-master.opt:
Added --debug-on as test require DBUG to work
mysql-test/t/maria-recovery-master.opt:
Added --debug-on as test require DBUG to work
mysql-test/t/maria-recovery.test:
Added new test by Guilhem to test if UNDO_ROW_DELETE preserves rowid
mysql-test/t/maria.test:
Added testing of page checksums
sql/mysqld.cc:
Added --debug-on option (to be able to turn of DBUG with --debug-on=0)
Indentation fixes
Removed end spaces
sql/sql_show.cc:
Allow update_create_info() to inform MySQL if PACK_KEYS, NO_PACK_KEYS, CHECKSUM, PAGE_CHECKSUM or DELAY_KEY_WRITE is used
storage/maria/Makefile.am:
Added ma_test_big.sh
storage/maria/ha_maria.cc:
Store in create_info if page checksums are used (For SHOW CREATE TABLE)
storage/maria/ma_bitmap.c:
Added _ma_bitmap_wait_or_flush() to cause reader of bitmap pages to wait with reading until bitmap is flushed.
Use TAIL_PAGE_COUNT_MARKER for tail pages
Set 'sub_blocks' for and only for the head page or for the first extent of a blob. This is needed for store_extent_info() to be able to set START_EXTENT_BIT's
Don't allocate more than 0x3ffff pages in one extent (We need bit 0x4000 as a START_EXTENT_BIT)
Increase the calculated 'head_length' with the number of bytes used for extents.
Update row->space_on_head_page also in _ma_bitmap_find_new_place()
Make _ma_bitmap_get_page_bits() global. (Needed for UNDO handling)
Changed _ma_bitmap_flushable() to take MARIA_HA instead of MARIA_SHARE.
This was needed to be able to mark the handler if we had a 'non_flushable' call pending or not.
Don't use 'non_flushable' marking of bitmap pages for not transactional tables.
Added BLOCKUSED_USE_ORG_BITMAP handling also for tail pages.
Added more DBUG_ASSERT() to find possible errors in other code
Some code simplications by adding new local variables
storage/maria/ma_blockrec.c:
UNDO of rows now puts back all part of the row on their original pages and positions.
Changed UNDO of DELETE and UNDO of UPDATE to contain information about the original length of data on head block and also extent information
This changes a lot of logic as now an insert of a row on a page may happen to any position (and not just to the first or next free)
Use PAGE_COUNT to mark if an extent is the start of of a blob. (Needed for extent_to_bitmap_blocks())
Added check_directory() for checking that directroy entries are correct.
Added checking of row checksums when reading rows (with EXTRA_DEBUG)
Added make_space_for_directory() and extend_directory() for doing expansion of directory
Added get_rowpos_in_head_or_tail_page() to be able to store head/tail on original position in UNDO
Added extent_to_bitmap_blocks() to be able to generate original bitmap blocks from UNDO entry
Added _ma_update_at_original_place() for UNDO of DELETES
Added row->min_length to hold minmum required space needed on head page
Changed find_free_position() to use make_space_for_directory()
Changed make_empty_page() to allow optional creation of directory entry
Changed delete_head_or_tail() and _ma_apply_undo_row_isnert() to not copy pagecache block (speed optimization)
Changed _ma_apply_redo_insert_row_head_or_tail() to be able to insert new row at any position on 'new' page
Changed _ma_apply_undo_row_delete() and _ma_apply_undo_row_update() to put row in it's original position
Ensure allocation of tail blocks are of at least MIN_TAIL_SIZE.
Ensure we store pages in pinned pages even if read failed. (If not we will have pages pinned forever in page cache)
Write original extent information in UNDO entry, not compacted ones (we need position to tails!)
When setting BLOCKUSED_USED, don't clear other bits (we have to preserve BLOCKUSED_USE_ORG_BITMAP)
Fixed som bugs in directory handling
Fixed bug where we wrote wrong lsn to blob pages
Added separate blob_buffer for fixing bug when updating row that had char/varchar that spanned several pages and also had blobs
Ensure we call _ma_bitmap_flushable() also in case of errors
When doing an update, first delete old entries, then search in bitmap for where to put new information
Info->s -> share
Rowid -> rowid
More DBUG_ASSERT()
storage/maria/ma_blockrec.h:
Added START_EXTENT_BIT and TAIL_PAGE_COUNT_MARKER
Added _ma_bitmap_wait_or_flush() and _ma_bitmap_get_page_bits()
storage/maria/ma_check.c:
Don't write extra empty line if there is no deleted blocks
Ignore START_EXTENT_BIT's in page count
Call _ma_fast_unlock_key_del() to free key_del link
storage/maria/ma_close.c:
Ensure that used_key_del is 0. (If not, someone forgot to call _ma_unlock_key_del())
storage/maria/ma_create.c:
Changed constant to macro
storage/maria/ma_delete.c:
For deleted keys, log also position to row
storage/maria/ma_extra.c:
Release blob buffer at maria_reset() if bigger than MARIA_SMALL_BLOB_BUFFER
storage/maria/ma_key_recover.c:
Added bzero() of LSN that confused paged cache in case of uninitialized block
Mark file crashed if applying of index changes fails
Added calls to _ma_fast_unlock_key_del() for protection of shared key_del link.
storage/maria/ma_locking.c:
Added usage of MARIA_FILE_OPEN_COUNT_OFFSET
Added _ma_mark_file_crashed()
storage/maria/ma_loghandler.c:
Fixed bug where we logged uninitialized memory
storage/maria/ma_open.c:
Moved state->changed to be at start of state info on disk to allow one to easly mark files as crashed
storage/maria/ma_page.c:
Disable 'dummy' checksumming of pages as this gave false warnings.
(Need to investigate if this is ever needed)
storage/maria/ma_pagecache.c:
Fixed wrong shift that caused Maria to crash on files > 4G
storage/maria/ma_recovery.c:
In case of errors, start writing on new line if we where in %## %## printing mode (Made errors more readable)
Changed global variable name from warnings -> recovery_warnings
Use MARIA_FILE_CREATE_RENAME_LSN_OFFSET instead of constant
Removed special handling of row position for deleted keys. Keys now always includes row positions
_ma_apply_undo_row_delete() now gets page and row position
Added check that we don't loop forever when handling undo's (in case of bug in undo chain)
Print name of failed REDO/UNDO
storage/maria/ma_recovery.h:
Removed old comment
storage/maria/ma_static.c:
Chaned version number of Maria files to not accidently use old ones (becasue of change of ordering of status variables)
storage/maria/ma_test2.c:
Added option -u to specify number of rows to update
Changed old option -u to be -A, as for ma_test1
Fixed bug in update of rows with blobs (before blobs was always reset to empty on update)
First created blob is now of max blob length to ensure we have at least one big blob in the table
storage/maria/ma_test_all.sh:
More tests
storage/maria/ma_test_recovery.expected:
Updated results
storage/maria/ma_test_recovery:
Changed tests to use bigger blobs (not just 1K)
Added new tests that tests recovery of update with blobs
Removed comparision of .MAD file as it's not guranteed that recovery from scratch gives identical data file as original update
(compact_page() may be called at different times during normal execution and during REDO)
storage/maria/ma_update.c:
Simplify code (changed * to if)
storage/maria/maria_chk.c:
Make output more readable
storage/maria/maria_def.h:
Changed 'changed' to int to prepare for more bits
Added 2 more bytes to status information
Added 'st_mara_row->min_length' for storing min length needed on head page
Added 'st_mara_handler->blob_buff & blob_buff_size' for storing blobs
Moved all tunning parameters into one block
Added MARIA_SMALL_BLOB_BUFFER
Added _ma_mark_file_crashed()
storage/myisam/mi_test2.c:
Fixed bug in update of rows with blobs (before blobs was always reset to empty on update)
storage/maria/ma_test_big.sh:
Testing of insert, update, delete, recovery and undo of rows with blobs
Thanks to the random-ness of ma_test2 this is likely to find most bugs in the row handling
2007-12-30 21:40:03 +01:00
DBUG_ENTER ( " descript " ) ;
2006-04-11 15:45:10 +02:00
2007-08-29 08:03:10 +02:00
if ( param - > testflag & T_VERY_SILENT )
{
longlong checksum = info - > state - > checksum ;
if ( ! ( share - > options & ( HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD ) ) )
checksum = 0 ;
printf ( " %s %s %s \n " , name , llstr ( info - > state - > records , llbuff ) ,
llstr ( checksum , llbuff2 ) ) ;
DBUG_VOID_RETURN ;
}
2007-11-28 20:38:30 +01:00
printf ( " MARIA file: %s \n " , name ) ;
2007-01-18 20:38:14 +01:00
printf ( " Record format: %s \n " , record_formats [ share - > data_file_type ] ) ;
First part of redo/undo for key pages
Added key_nr to st_maria_keydef for faster keyinfo->keynr conversion
For transactional tables, shift record number in keys up with 1 bit to have place to indicate if transid follows
Checksum for MyISAM now ignores NULL and not used part of VARCHAR
Renamed some variables that caused shadow compiler warnings
Moved extra() call when waiting for tables to not be used to after tables are removed from cache.
Fixed crashing bugs when using Maria TEMPORARY tables with TRUNCATE. Removed 'hack' code in sql directory to go around this bug.
pagecache_unlock_by_ulink() now has extra argument to say if page was changed.
Give error message if we fail to open control file
Mark page cache variables as not flushable
include/maria.h:
Made min page cache larger (needed for pinning key page)
Added key_nr to st_maria_keydef for faster keyinfo->keynr conversion
Added write_comp_flag to move some runtime code to maria_open()
include/my_base.h:
Added new error message to be used when handler initialization failed
include/my_global.h:
Renamed dummy to swap_dummy to avoid conflicts with local 'dummy' variables
include/my_handler.h:
Added const to some parameters
mysys/array.c:
More DBUG
mysys/my_error.c:
Fixed indentation
mysys/my_handler.c:
Added const to some parameters
Added missing error messages
sql/field.h:
Renamed variables to avoid variable shadowing
sql/handler.h:
Renamed parameter to avoid variable name conflict
sql/item.h:
Renamed variables to avoid variable shadowing
sql/log_event_old.h:
Renamed variables to avoid variable shadowing
sql/set_var.h:
Renamed variables to avoid variable shadowing
sql/sql_delete.cc:
Removed maria hack for temporary tables
Fixed indentation
sql/sql_table.cc:
Moved extra() call when waiting for tables to not be used to after tables are removed from cache.
This was needed to ensure we don't do a PREPARE_FOR_DROP or similar call while the table is still in use.
sql/table.cc:
Copy page_checksum from share
Removed Maria hack
storage/maria/Makefile.am:
Added new files
storage/maria/ha_maria.cc:
Renamed records -> record_count and info -> create_info to avoid variable name conflicts
Mark page cache variables as not flushable
storage/maria/ma_blockrec.c:
Moved _ma_unpin_all_pages() to ma_key_recover.c
Moved init of info->pinned_pages to ma_open.c
Moved _ma_finalize_row() to maria_key_recover.h
Renamed some variables to avoid variable name conflicts
Mark page_link.changed for blocks we change directly
Simplify handling of undo link when writing LOGREC_UNDO_ROW_INSERT (old code crashed when having redo for index)
storage/maria/ma_blockrec.h:
Removed extra empty line
storage/maria/ma_checkpoint.c:
Remove not needed trnman.h
storage/maria/ma_close.c:
Free pinned pages (which are now always allocated)
storage/maria/ma_control_file.c:
Give error message if we fail to open control file
storage/maria/ma_delete.c:
Changes for redo logging (first part, logging of underflow not yet done)
- Log undo-key-delete
- Log delete of key
- Updated arguments to _ma_fetch_keypage(), _ma_dispose(), _ma_write_keypage(), _ma_insert()
- Added new arguments to some functions to be able to write redo information
- Mark key pages as changed when we write with PAGECACHE_LOCK_LEFT_WRITELOCKED
Remove one not needed _ma_write_keypage() in d_search() when upper level will do the write anyway
Changed 2 bmove_upp() to bmove() as this made code easer to understand
More function comments
Indentation fixes
storage/maria/ma_ft_update.c:
New arguments to _ma_write_keypage()
storage/maria/ma_loghandler.c:
Fixed some DBUG_PRINT messages
Simplify code
Added new log entrys for key page redo
Renamed some variables to avoid variable name shadowing
storage/maria/ma_loghandler.h:
Moved some defines here
Added define for storing key number on key pages
Added new translog record types
Added enum for type of operations in LOGREC_REDO_INDEX
storage/maria/ma_open.c:
Always allocate info.pinned_pages (we need now also for normal key page usage)
Update keyinfo->key_nr
Added virtual functions to convert record position o number to be stored on key pages
Update keyinfo->write_comp_flag to value of search flag to be used when writing key
storage/maria/ma_page.c:
Added redo for key pages
- Extended _ma_fetch_keypage() with type of lock to put on page and address to used MARIA_PINNED_PAGE
- _ma_fetch_keypage() now pin's pages if needed
- Extended _ma_write_keypage() with type of locks to be used
- ma_dispose() now locks info->s->state.key_del from other threads
- ma_dispose() writes redo log record
- ma_new() locks info->s->state.key_del from other threads if it was used
- ma_new() now pins read page
Other things:
- Removed some not needed arguments from _ma_new() and _ma_dispose)
- Added some new variables to simplify code
- If EXTRA_DEBUG is used, do crc on full page to catch not unitialized bytes
storage/maria/ma_pagecache.h:
Applied patch from Sanja to add extra argument to pagecache_unlock_by_ulink() to mark if page was changed
Added some defines for pagecache priority levels that one can use
storage/maria/ma_range.c:
Added new arguments for call to _ma_fetch_keypage()
storage/maria/ma_recovery.c:
- Added hooks for new translog types:
REDO_INDEX, REDO_INDEX_NEW_PAGE, REDO_INDEX_FREE_PAGE, UNDO_KEY_INSERT, UNDO_KEY_DELETE and
UNDO_KEY_DELETE_WITH_ROOT.
- Moved variable declarations to start of function (portability fixes)
- Removed some not needed initializations
- Set only relevant state changes for each redo/undo entry
storage/maria/lockman.c:
Removed end space
storage/maria/ma_check.c:
Removed end space
storage/maria/ma_create.c:
Removed end space
storage/maria/ma_locking.c:
Removed end space
storage/maria/ma_packrec.c:
Removed end space
storage/maria/ma_pagecache.c:
Removed end space
storage/maria/ma_panic.c:
Removed end space
storage/maria/ma_rt_index.c:
Added new arguments for call to _ma_fetch_keypage(), _ma_write_keypage(), _ma_dispose() and _ma_new()
Fixed indentation
storage/maria/ma_rt_key.c:
Added new arguments for call to _ma_fetch_keypage()
storage/maria/ma_rt_split.c:
Added new arguments for call to _ma_new()
Use new keypage header
Added new arguments for call to _ma_write_keypage()
storage/maria/ma_search.c:
Updated comments & indentation
Added new arguments for call to _ma_fetch_keypage()
Made some variables and arguments const
Added virtual functions for converting row position to number to be stored in key
use MARIA_RECORD_POS of record position instead of my_off_t
Record in MARIA_KEY_PARAM how page was changed one key insert (needed for REDO)
storage/maria/ma_sort.c:
Removed end space
storage/maria/ma_statrec.c:
Updated arguments for call to _ma_rec_pos()
storage/maria/ma_test1.c:
Fixed too small buffer to init_pagecache()
Fixed bug when using insert_count and test_flag
storage/maria/ma_test2.c:
Use more resonable pagecache size
Remove not used code
Reset blob_length to fix wrong output message
storage/maria/ma_test_all.sh:
Fixed wrong test
storage/maria/ma_write.c:
Lots of new code to handle REDO of key pages
No logic changes because of REDO code, mostly adding new arguments and adding new code for logging
Added new arguments for calls to _ma_fetch_keypage(), _ma_write_keypage() and similar functions
Move setting of comp_flag in ma_ck_wrte_btree() from runtime to maria_open()
Zerofill new used pages for:
- To remove possible sensitive data left in buffer
- To get idenitical data on pages after running redo
- Better compression of pages if archived
storage/maria/maria_chk.c:
Added information if table is crash safe
storage/maria/maria_def.h:
New virtual function to convert between record position on key and normal record position
Aded mutex and extra variables to handle locking of share->state.key_del
Moved some structure variables to get things more aligned
Added extra arguments to MARIA_KEY_PARAM to be able to remember what was changed on key page on key insert
Added argument to MARIA_PINNED_PAGE to indicate if page was changed
Updated prototypes for functions
Added some structures for signaling changes in REDO handling
storage/maria/unittest/ma_pagecache_single.c:
Updated arguments for changed function calls
storage/myisam/mi_check.c:
Made calc_check_checksum virtual
storage/myisam/mi_checksum.c:
Update checksums to ignore null columns
storage/myisam/mi_create.c:
Mark if table has null column (to know when we have to use mi_checksum())
storage/myisam/mi_open.c:
Added virtual function for calculating checksum to be able to easily ignore NULL fields
storage/myisam/mi_test2.c:
Fixed bug
storage/myisam/myisamdef.h:
Added virtual function for calculating checksum during check table
Removed ha_key_cmp() as this is in handler.h
storage/maria/ma_key_recover.c:
New BitKeeper file ``storage/maria/ma_key_recover.c''
storage/maria/ma_key_recover.h:
New BitKeeper file ``storage/maria/ma_key_recover.h''
storage/maria/ma_key_redo.c:
New BitKeeper file ``storage/maria/ma_key_redo.c''
2007-11-14 18:08:06 +01:00
printf ( " Crashsafe: %s \n " ,
share - > base . born_transactional ? " yes " : " no " ) ;
2006-04-11 15:45:10 +02:00
printf ( " Character set: %s (%d) \n " ,
get_charset_name ( share - > state . header . language ) ,
share - > state . header . language ) ;
if ( param - > testflag & T_VERBOSE )
{
printf ( " File-version: %d \n " ,
( int ) share - > state . header . file_version [ 3 ] ) ;
if ( share - > state . create_time )
{
get_date ( buff , 1 , share - > state . create_time ) ;
printf ( " Creation time: %s \n " , buff ) ;
}
if ( share - > state . check_time )
{
get_date ( buff , 1 , share - > state . check_time ) ;
printf ( " Recover time: %s \n " , buff ) ;
}
pos = buff ;
if ( share - > state . changed & STATE_CRASHED )
strmov ( buff , " crashed " ) ;
else
{
if ( share - > state . open_count )
pos = strmov ( pos , " open, " ) ;
if ( share - > state . changed & STATE_CHANGED )
pos = strmov ( pos , " changed, " ) ;
else
pos = strmov ( pos , " checked, " ) ;
if ( ! ( share - > state . changed & STATE_NOT_ANALYZED ) )
pos = strmov ( pos , " analyzed, " ) ;
if ( ! ( share - > state . changed & STATE_NOT_OPTIMIZED_KEYS ) )
pos = strmov ( pos , " optimized keys, " ) ;
if ( ! ( share - > state . changed & STATE_NOT_SORTED_PAGES ) )
pos = strmov ( pos , " sorted index pages, " ) ;
2007-12-31 10:55:46 +01:00
if ( ! ( share - > state . changed & STATE_NOT_ZEROFILLED ) )
pos = strmov ( pos , " zerofilled, " ) ;
if ( ! ( share - > state . changed & STATE_NOT_MOVABLE ) )
pos = strmov ( pos , " movable, " ) ;
2006-04-11 15:45:10 +02:00
pos [ - 1 ] = 0 ; /* Remove extra ',' */
}
printf ( " Status: %s \n " , buff ) ;
if ( share - > options & ( HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD ) )
2007-01-18 20:38:14 +01:00
printf ( " Checksum: %26s \n " , llstr ( info - > state - > checksum , llbuff ) ) ;
2006-04-11 15:45:10 +02:00
;
if ( share - > options & HA_OPTION_DELAY_KEY_WRITE )
printf ( " Keys are only flushed at close \n " ) ;
2007-10-09 20:09:50 +02:00
if ( share - > options & HA_OPTION_PAGE_CHECKSUM )
printf ( " Page checksums are used \n " ) ;
UNDO of rows now puts back all part of the row on their original pages and positions
Added variable _dbug_on_ to speed up execution when DBUG is not going to be used
Added --debug-on option to mysqld (to be able to turn of DBUG with --debug-on=0)
Fixed some bugs with 'non_flushable' marking of bitmap pages
Don't use 'non_flushable' marking of bitmap pages for not transactional tables
SHOW CREATE TABLE now shows if table was created with page checksums
Fixed a lot of bugs with BLOB handling in case of update/REDO and UNDO
More tests (especially for blobs) and DBUG_ASSERTS()
More readable output from maria_read_log and maria_chk
Fixed wrong shift that caused Maria to crash on files > 4G
Mark tables as crashed of REDO fails
dbug/dbug.c:
Changed to use my_bool (allowed me to remove some windows specific code)
Added variable _dbug_on_ to speed up execution when DBUG is not going to be used
Removed initialization of variables if not needed
include/my_dbug.h:
Use my_bool for some functions that was defined as BOOLEAN in dbug.c code
Added DBUGGER_ON/DEBUGGER_OFF to speed up execution when DBUG is not used
include/my_global.h:
Define my_bool early
Increase MY_HOW_OFTEN_TO_WRITE as computers are now faster than 10 years ago
mysql-test/mysql-test-run.pl:
Added debug-on=0 to speed up tests
mysql-test/r/maria-recovery.result:
Added new test by Guilhem to test if UNDO_ROW_DELETE preserves rowid
mysql-test/r/maria.result:
Added testing of page checksums
mysql-test/t/crash_commit_before-master.opt:
Added --debug-on as test require DBUG to work
mysql-test/t/maria-recovery-bitmap-master.opt:
Added --debug-on as test require DBUG to work
mysql-test/t/maria-recovery-master.opt:
Added --debug-on as test require DBUG to work
mysql-test/t/maria-recovery.test:
Added new test by Guilhem to test if UNDO_ROW_DELETE preserves rowid
mysql-test/t/maria.test:
Added testing of page checksums
sql/mysqld.cc:
Added --debug-on option (to be able to turn of DBUG with --debug-on=0)
Indentation fixes
Removed end spaces
sql/sql_show.cc:
Allow update_create_info() to inform MySQL if PACK_KEYS, NO_PACK_KEYS, CHECKSUM, PAGE_CHECKSUM or DELAY_KEY_WRITE is used
storage/maria/Makefile.am:
Added ma_test_big.sh
storage/maria/ha_maria.cc:
Store in create_info if page checksums are used (For SHOW CREATE TABLE)
storage/maria/ma_bitmap.c:
Added _ma_bitmap_wait_or_flush() to cause reader of bitmap pages to wait with reading until bitmap is flushed.
Use TAIL_PAGE_COUNT_MARKER for tail pages
Set 'sub_blocks' for and only for the head page or for the first extent of a blob. This is needed for store_extent_info() to be able to set START_EXTENT_BIT's
Don't allocate more than 0x3ffff pages in one extent (We need bit 0x4000 as a START_EXTENT_BIT)
Increase the calculated 'head_length' with the number of bytes used for extents.
Update row->space_on_head_page also in _ma_bitmap_find_new_place()
Make _ma_bitmap_get_page_bits() global. (Needed for UNDO handling)
Changed _ma_bitmap_flushable() to take MARIA_HA instead of MARIA_SHARE.
This was needed to be able to mark the handler if we had a 'non_flushable' call pending or not.
Don't use 'non_flushable' marking of bitmap pages for not transactional tables.
Added BLOCKUSED_USE_ORG_BITMAP handling also for tail pages.
Added more DBUG_ASSERT() to find possible errors in other code
Some code simplications by adding new local variables
storage/maria/ma_blockrec.c:
UNDO of rows now puts back all part of the row on their original pages and positions.
Changed UNDO of DELETE and UNDO of UPDATE to contain information about the original length of data on head block and also extent information
This changes a lot of logic as now an insert of a row on a page may happen to any position (and not just to the first or next free)
Use PAGE_COUNT to mark if an extent is the start of of a blob. (Needed for extent_to_bitmap_blocks())
Added check_directory() for checking that directroy entries are correct.
Added checking of row checksums when reading rows (with EXTRA_DEBUG)
Added make_space_for_directory() and extend_directory() for doing expansion of directory
Added get_rowpos_in_head_or_tail_page() to be able to store head/tail on original position in UNDO
Added extent_to_bitmap_blocks() to be able to generate original bitmap blocks from UNDO entry
Added _ma_update_at_original_place() for UNDO of DELETES
Added row->min_length to hold minmum required space needed on head page
Changed find_free_position() to use make_space_for_directory()
Changed make_empty_page() to allow optional creation of directory entry
Changed delete_head_or_tail() and _ma_apply_undo_row_isnert() to not copy pagecache block (speed optimization)
Changed _ma_apply_redo_insert_row_head_or_tail() to be able to insert new row at any position on 'new' page
Changed _ma_apply_undo_row_delete() and _ma_apply_undo_row_update() to put row in it's original position
Ensure allocation of tail blocks are of at least MIN_TAIL_SIZE.
Ensure we store pages in pinned pages even if read failed. (If not we will have pages pinned forever in page cache)
Write original extent information in UNDO entry, not compacted ones (we need position to tails!)
When setting BLOCKUSED_USED, don't clear other bits (we have to preserve BLOCKUSED_USE_ORG_BITMAP)
Fixed som bugs in directory handling
Fixed bug where we wrote wrong lsn to blob pages
Added separate blob_buffer for fixing bug when updating row that had char/varchar that spanned several pages and also had blobs
Ensure we call _ma_bitmap_flushable() also in case of errors
When doing an update, first delete old entries, then search in bitmap for where to put new information
Info->s -> share
Rowid -> rowid
More DBUG_ASSERT()
storage/maria/ma_blockrec.h:
Added START_EXTENT_BIT and TAIL_PAGE_COUNT_MARKER
Added _ma_bitmap_wait_or_flush() and _ma_bitmap_get_page_bits()
storage/maria/ma_check.c:
Don't write extra empty line if there is no deleted blocks
Ignore START_EXTENT_BIT's in page count
Call _ma_fast_unlock_key_del() to free key_del link
storage/maria/ma_close.c:
Ensure that used_key_del is 0. (If not, someone forgot to call _ma_unlock_key_del())
storage/maria/ma_create.c:
Changed constant to macro
storage/maria/ma_delete.c:
For deleted keys, log also position to row
storage/maria/ma_extra.c:
Release blob buffer at maria_reset() if bigger than MARIA_SMALL_BLOB_BUFFER
storage/maria/ma_key_recover.c:
Added bzero() of LSN that confused paged cache in case of uninitialized block
Mark file crashed if applying of index changes fails
Added calls to _ma_fast_unlock_key_del() for protection of shared key_del link.
storage/maria/ma_locking.c:
Added usage of MARIA_FILE_OPEN_COUNT_OFFSET
Added _ma_mark_file_crashed()
storage/maria/ma_loghandler.c:
Fixed bug where we logged uninitialized memory
storage/maria/ma_open.c:
Moved state->changed to be at start of state info on disk to allow one to easly mark files as crashed
storage/maria/ma_page.c:
Disable 'dummy' checksumming of pages as this gave false warnings.
(Need to investigate if this is ever needed)
storage/maria/ma_pagecache.c:
Fixed wrong shift that caused Maria to crash on files > 4G
storage/maria/ma_recovery.c:
In case of errors, start writing on new line if we where in %## %## printing mode (Made errors more readable)
Changed global variable name from warnings -> recovery_warnings
Use MARIA_FILE_CREATE_RENAME_LSN_OFFSET instead of constant
Removed special handling of row position for deleted keys. Keys now always includes row positions
_ma_apply_undo_row_delete() now gets page and row position
Added check that we don't loop forever when handling undo's (in case of bug in undo chain)
Print name of failed REDO/UNDO
storage/maria/ma_recovery.h:
Removed old comment
storage/maria/ma_static.c:
Chaned version number of Maria files to not accidently use old ones (becasue of change of ordering of status variables)
storage/maria/ma_test2.c:
Added option -u to specify number of rows to update
Changed old option -u to be -A, as for ma_test1
Fixed bug in update of rows with blobs (before blobs was always reset to empty on update)
First created blob is now of max blob length to ensure we have at least one big blob in the table
storage/maria/ma_test_all.sh:
More tests
storage/maria/ma_test_recovery.expected:
Updated results
storage/maria/ma_test_recovery:
Changed tests to use bigger blobs (not just 1K)
Added new tests that tests recovery of update with blobs
Removed comparision of .MAD file as it's not guranteed that recovery from scratch gives identical data file as original update
(compact_page() may be called at different times during normal execution and during REDO)
storage/maria/ma_update.c:
Simplify code (changed * to if)
storage/maria/maria_chk.c:
Make output more readable
storage/maria/maria_def.h:
Changed 'changed' to int to prepare for more bits
Added 2 more bytes to status information
Added 'st_mara_row->min_length' for storing min length needed on head page
Added 'st_mara_handler->blob_buff & blob_buff_size' for storing blobs
Moved all tunning parameters into one block
Added MARIA_SMALL_BLOB_BUFFER
Added _ma_mark_file_crashed()
storage/myisam/mi_test2.c:
Fixed bug in update of rows with blobs (before blobs was always reset to empty on update)
storage/maria/ma_test_big.sh:
Testing of insert, update, delete, recovery and undo of rows with blobs
Thanks to the random-ness of ma_test2 this is likely to find most bugs in the row handling
2007-12-30 21:40:03 +01:00
if ( share - > base . auto_key )
{
printf ( " Auto increment key: %16d Last value: %18s \n " ,
share - > base . auto_key ,
llstr ( share - > state . auto_increment , llbuff ) ) ;
}
2006-04-11 15:45:10 +02:00
}
2007-01-18 20:38:14 +01:00
printf ( " Data records: %16s Deleted blocks: %18s \n " ,
2006-04-11 15:45:10 +02:00
llstr ( info - > state - > records , llbuff ) , llstr ( info - > state - > del , llbuff2 ) ) ;
if ( param - > testflag & T_SILENT )
DBUG_VOID_RETURN ; /* This is enough */
if ( param - > testflag & T_VERBOSE )
{
# ifdef USE_RELOC
2007-01-18 20:38:14 +01:00
printf ( " Init-relocation: %16s \n " , llstr ( share - > base . reloc , llbuff ) ) ;
2006-04-11 15:45:10 +02:00
# endif
2007-01-18 20:38:14 +01:00
printf ( " Datafile parts: %16s Deleted data: %18s \n " ,
2006-04-11 15:45:10 +02:00
llstr ( share - > state . split , llbuff ) ,
llstr ( info - > state - > empty , llbuff2 ) ) ;
2007-01-18 20:38:14 +01:00
printf ( " Datafile pointer (bytes): %11d Keyfile pointer (bytes): %13d \n " ,
2006-04-11 15:45:10 +02:00
share - > rec_reflength , share - > base . key_reflength ) ;
2007-01-18 20:38:14 +01:00
printf ( " Datafile length: %16s Keyfile length: %18s \n " ,
2006-04-11 15:45:10 +02:00
llstr ( info - > state - > data_file_length , llbuff ) ,
llstr ( info - > state - > key_file_length , llbuff2 ) ) ;
if ( info - > s - > base . reloc = = 1L & & info - > s - > base . records = = 1L )
puts ( " This is a one-record table " ) ;
else
{
if ( share - > base . max_data_file_length ! = HA_OFFSET_ERROR | |
share - > base . max_key_file_length ! = HA_OFFSET_ERROR )
2007-01-18 20:38:14 +01:00
printf ( " Max datafile length: %16s Max keyfile length: %18s \n " ,
2006-04-11 15:45:10 +02:00
llstr ( share - > base . max_data_file_length - 1 , llbuff ) ,
llstr ( share - > base . max_key_file_length - 1 , llbuff2 ) ) ;
}
}
2007-01-18 20:38:14 +01:00
printf ( " Block_size: %16d \n " , ( int ) share - > block_size ) ;
printf ( " Recordlength: %16d \n " , ( int ) share - > base . pack_reclength ) ;
2006-04-11 15:45:10 +02:00
if ( ! maria_is_all_keys_active ( share - > state . key_map , share - > base . keys ) )
{
longlong2str ( share - > state . key_map , buff , 2 ) ;
printf ( " Using only keys '%s' of %d possibly keys \n " ,
buff , share - > base . keys ) ;
}
puts ( " \n table description: " ) ;
printf ( " Key Start Len Index Type " ) ;
if ( param - > testflag & T_VERBOSE )
printf ( " Rec/key Root Blocksize " ) ;
VOID ( putchar ( ' \n ' ) ) ;
for ( key = keyseg_nr = 0 , keyinfo = & share - > keyinfo [ 0 ] ;
key < share - > base . keys ;
key + + , keyinfo + + )
{
keyseg = keyinfo - > seg ;
if ( keyinfo - > flag & HA_NOSAME ) text = " unique " ;
else if ( keyinfo - > flag & HA_FULLTEXT ) text = " fulltext " ;
else text = " multip. " ;
pos = buff ;
if ( keyseg - > flag & HA_REVERSE_SORT )
* pos + + = ' - ' ;
pos = strmov ( pos , type_names [ keyseg - > type ] ) ;
* pos + + = ' ' ;
* pos = 0 ;
if ( keyinfo - > flag & HA_PACK_KEY )
pos = strmov ( pos , prefix_packed_txt ) ;
if ( keyinfo - > flag & HA_BINARY_PACK_KEY )
pos = strmov ( pos , bin_packed_txt ) ;
if ( keyseg - > flag & HA_SPACE_PACK )
pos = strmov ( pos , diff_txt ) ;
if ( keyseg - > flag & HA_BLOB_PART )
pos = strmov ( pos , blob_txt ) ;
if ( keyseg - > flag & HA_NULL_PART )
pos = strmov ( pos , null_txt ) ;
* pos = 0 ;
2008-01-31 02:06:04 +01:00
printf ( " %-4d%-6ld%-3d %-8s%-23s " ,
2006-04-11 15:45:10 +02:00
key + 1 , ( long ) keyseg - > start + 1 , keyseg - > length , text , buff ) ;
if ( share - > state . key_root [ key ] ! = HA_OFFSET_ERROR )
llstr ( share - > state . key_root [ key ] , buff ) ;
else
buff [ 0 ] = 0 ;
if ( param - > testflag & T_VERBOSE )
2008-01-31 02:06:04 +01:00
printf ( " %9.0f %12s %10d " ,
2006-04-11 15:45:10 +02:00
share - > state . rec_per_key_part [ keyseg_nr + + ] ,
buff , keyinfo - > block_length ) ;
VOID ( putchar ( ' \n ' ) ) ;
while ( ( + + keyseg ) - > type ! = HA_KEYTYPE_END )
{
pos = buff ;
if ( keyseg - > flag & HA_REVERSE_SORT )
* pos + + = ' - ' ;
pos = strmov ( pos , type_names [ keyseg - > type ] ) ;
* pos + + = ' ' ;
if ( keyseg - > flag & HA_SPACE_PACK )
pos = strmov ( pos , diff_txt ) ;
if ( keyseg - > flag & HA_BLOB_PART )
pos = strmov ( pos , blob_txt ) ;
if ( keyseg - > flag & HA_NULL_PART )
pos = strmov ( pos , null_txt ) ;
* pos = 0 ;
printf ( " %-6ld%-3d %-21s " ,
( long ) keyseg - > start + 1 , keyseg - > length , buff ) ;
if ( param - > testflag & T_VERBOSE )
2008-01-07 17:54:41 +01:00
printf ( " %11.0f " , share - > state . rec_per_key_part [ keyseg_nr + + ] ) ;
2006-04-11 15:45:10 +02:00
VOID ( putchar ( ' \n ' ) ) ;
}
keyseg + + ;
}
if ( share - > state . header . uniques )
{
MARIA_UNIQUEDEF * uniqueinfo ;
puts ( " \n Unique Key Start Len Nullpos Nullbit Type " ) ;
for ( key = 0 , uniqueinfo = & share - > uniqueinfo [ 0 ] ;
key < share - > state . header . uniques ; key + + , uniqueinfo + + )
{
my_bool new_row = 0 ;
char null_bit [ 8 ] , null_pos [ 8 ] ;
printf ( " %-8d%-5d " , key + 1 , uniqueinfo - > key + 1 ) ;
for ( keyseg = uniqueinfo - > seg ; keyseg - > type ! = HA_KEYTYPE_END ; keyseg + + )
{
if ( new_row )
fputs ( " " , stdout ) ;
null_bit [ 0 ] = null_pos [ 0 ] = 0 ;
if ( keyseg - > null_bit )
{
sprintf ( null_bit , " %d " , keyseg - > null_bit ) ;
sprintf ( null_pos , " %ld " , ( long ) keyseg - > null_pos + 1 ) ;
}
printf ( " %-7ld%-5d%-9s%-10s%-30s \n " ,
( long ) keyseg - > start + 1 , keyseg - > length ,
null_pos , null_bit ,
type_names [ keyseg - > type ] ) ;
new_row = 1 ;
}
}
}
if ( param - > verbose > 1 )
{
char null_bit [ 8 ] , null_pos [ 8 ] ;
printf ( " \n Field Start Length Nullpos Nullbit Type " ) ;
if ( share - > options & HA_OPTION_COMPRESS_RECORD )
printf ( " Huff tree Bits " ) ;
VOID ( putchar ( ' \n ' ) ) ;
2007-01-18 20:38:14 +01:00
2006-04-11 15:45:10 +02:00
for ( field = 0 ; field < share - > base . fields ; field + + )
{
if ( share - > options & HA_OPTION_COMPRESS_RECORD )
2007-04-19 12:18:56 +02:00
type = share - > columndef [ field ] . base_type ;
2006-04-11 15:45:10 +02:00
else
2007-04-19 12:18:56 +02:00
type = ( enum en_fieldtype ) share - > columndef [ field ] . type ;
2006-04-11 15:45:10 +02:00
end = strmov ( buff , field_pack [ type ] ) ;
if ( share - > options & HA_OPTION_COMPRESS_RECORD )
{
2007-04-19 12:18:56 +02:00
if ( share - > columndef [ field ] . pack_type & PACK_TYPE_SELECTED )
2006-04-11 15:45:10 +02:00
end = strmov ( end , " , not_always " ) ;
2007-04-19 12:18:56 +02:00
if ( share - > columndef [ field ] . pack_type & PACK_TYPE_SPACE_FIELDS )
2006-04-11 15:45:10 +02:00
end = strmov ( end , " , no empty " ) ;
2007-04-19 12:18:56 +02:00
if ( share - > columndef [ field ] . pack_type & PACK_TYPE_ZERO_FILL )
2006-04-11 15:45:10 +02:00
{
2007-04-19 12:18:56 +02:00
sprintf ( end , " , zerofill(%d) " , share - > columndef [ field ] . space_length_bits ) ;
2006-04-11 15:45:10 +02:00
end = strend ( end ) ;
}
}
if ( buff [ 0 ] = = ' , ' )
strmov ( buff , buff + 2 ) ;
2007-04-19 12:18:56 +02:00
int10_to_str ( ( long ) share - > columndef [ field ] . length , length , 10 ) ;
2006-04-11 15:45:10 +02:00
null_bit [ 0 ] = null_pos [ 0 ] = 0 ;
2007-04-19 12:18:56 +02:00
if ( share - > columndef [ field ] . null_bit )
2006-04-11 15:45:10 +02:00
{
2007-04-19 12:18:56 +02:00
sprintf ( null_bit , " %d " , share - > columndef [ field ] . null_bit ) ;
sprintf ( null_pos , " %d " , share - > columndef [ field ] . null_pos + 1 ) ;
2006-04-11 15:45:10 +02:00
}
2007-01-18 20:38:14 +01:00
printf ( " %-6d%-6u%-7s%-8s%-8s%-35s " , field + 1 ,
2007-04-19 12:18:56 +02:00
( uint ) share - > columndef [ field ] . offset + 1 ,
2007-01-18 20:38:14 +01:00
length , null_pos , null_bit , buff ) ;
2006-04-11 15:45:10 +02:00
if ( share - > options & HA_OPTION_COMPRESS_RECORD )
{
2007-04-19 12:18:56 +02:00
if ( share - > columndef [ field ] . huff_tree )
2006-04-11 15:45:10 +02:00
printf ( " %3d %2d " ,
2007-04-19 12:18:56 +02:00
( uint ) ( share - > columndef [ field ] . huff_tree - share - > decode_trees ) + 1 ,
share - > columndef [ field ] . huff_tree - > quick_table_bits ) ;
2006-04-11 15:45:10 +02:00
}
VOID ( putchar ( ' \n ' ) ) ;
}
}
DBUG_VOID_RETURN ;
} /* describe */
/* Sort records according to one key */
static int maria_sort_records ( HA_CHECK * param ,
2007-07-02 19:45:15 +02:00
register MARIA_HA * info , char * name ,
2006-04-11 15:45:10 +02:00
uint sort_key ,
my_bool write_info ,
my_bool update_index )
{
int got_error ;
uint key ;
MARIA_KEYDEF * keyinfo ;
File new_file ;
2007-07-02 19:45:15 +02:00
uchar * temp_buff ;
2006-04-11 15:45:10 +02:00
ha_rows old_record_count ;
2007-12-10 01:32:00 +01:00
MARIA_SHARE * share = info - > s ;
2006-04-11 15:45:10 +02:00
char llbuff [ 22 ] , llbuff2 [ 22 ] ;
MARIA_SORT_INFO sort_info ;
MARIA_SORT_PARAM sort_param ;
DBUG_ENTER ( " sort_records " ) ;
bzero ( ( char * ) & sort_info , sizeof ( sort_info ) ) ;
bzero ( ( char * ) & sort_param , sizeof ( sort_param ) ) ;
sort_param . sort_info = & sort_info ;
sort_info . param = param ;
keyinfo = & share - > keyinfo [ sort_key ] ;
got_error = 1 ;
temp_buff = 0 ;
new_file = - 1 ;
if ( ! maria_is_key_active ( share - > state . key_map , sort_key ) )
{
_ma_check_print_warning ( param ,
" Can't sort table '%s' on key %d; No such key " ,
name , sort_key + 1 ) ;
param - > error_printed = 0 ;
DBUG_RETURN ( 0 ) ; /* Nothing to do */
}
if ( keyinfo - > flag & HA_FULLTEXT )
{
_ma_check_print_warning ( param , " Can't sort table '%s' on FULLTEXT key %d " ,
name , sort_key + 1 ) ;
param - > error_printed = 0 ;
DBUG_RETURN ( 0 ) ; /* Nothing to do */
}
if ( share - > data_file_type = = COMPRESSED_RECORD )
{
_ma_check_print_warning ( param , " Can't sort read-only table '%s' " , name ) ;
param - > error_printed = 0 ;
DBUG_RETURN ( 0 ) ; /* Nothing to do */
}
if ( ! ( param - > testflag & T_SILENT ) )
{
printf ( " - Sorting records for MARIA-table '%s' \n " , name ) ;
if ( write_info )
printf ( " Data records: %9s Deleted: %9s \n " ,
llstr ( info - > state - > records , llbuff ) ,
llstr ( info - > state - > del , llbuff2 ) ) ;
}
if ( share - > state . key_root [ sort_key ] = = HA_OFFSET_ERROR )
DBUG_RETURN ( 0 ) ; /* Nothing to do */
if ( init_io_cache ( & info - > rec_cache , - 1 , ( uint ) param - > write_buffer_length ,
WRITE_CACHE , share - > pack . header_length , 1 ,
MYF ( MY_WME | MY_WAIT_IF_FULL ) ) )
goto err ;
info - > opt_flag | = WRITE_CACHE_USED ;
2007-07-02 19:45:15 +02:00
if ( ! ( temp_buff = ( uchar * ) my_alloca ( ( uint ) keyinfo - > block_length ) ) )
2006-04-11 15:45:10 +02:00
{
_ma_check_print_error ( param , " Not enough memory for key block " ) ;
goto err ;
}
2007-07-02 19:45:15 +02:00
if ( ! ( sort_param . record = ( uchar * ) my_malloc ( ( uint ) share - > base . pack_reclength ,
2006-04-11 15:45:10 +02:00
MYF ( 0 ) ) ) )
{
_ma_check_print_error ( param , " Not enough memory for record " ) ;
goto err ;
}
fn_format ( param - > temp_filename , name , " " , MARIA_NAME_DEXT , 2 + 4 + 32 ) ;
2007-01-18 20:38:14 +01:00
new_file = my_create ( fn_format ( param - > temp_filename ,
param - > temp_filename , " " ,
2007-04-19 12:18:56 +02:00
DATA_TMP_EXT ,
MY_REPLACE_EXT | MY_UNPACK_FILENAME ) ,
0 , param - > tmpfile_createflag ,
2007-01-18 20:38:14 +01:00
MYF ( 0 ) ) ;
2006-04-11 15:45:10 +02:00
if ( new_file < 0 )
{
_ma_check_print_error ( param , " Can't create new tempfile: '%s' " ,
param - > temp_filename ) ;
goto err ;
}
if ( share - > pack . header_length )
2007-04-04 22:37:09 +02:00
if ( maria_filecopy ( param , new_file , info - > dfile . file , 0L ,
share - > pack . header_length ,
" datafile-header " ) )
2006-04-11 15:45:10 +02:00
goto err ;
info - > rec_cache . file = new_file ; /* Use this file for cacheing*/
maria_lock_memory ( param ) ;
for ( key = 0 ; key < share - > base . keys ; key + + )
share - > keyinfo [ key ] . flag | = HA_SORT_ALLOWS_SAME ;
2007-04-04 22:37:09 +02:00
if ( my_pread ( share - > kfile . file , temp_buff ,
2006-04-11 15:45:10 +02:00
( uint ) keyinfo - > block_length ,
share - > state . key_root [ sort_key ] ,
MYF ( MY_NABP + MY_WME ) ) )
{
2007-12-18 02:21:32 +01:00
_ma_check_print_error ( param , " Can't read indexpage from filepos: %s " ,
llstr ( share - > state . key_root [ sort_key ] , llbuff ) ) ;
2006-04-11 15:45:10 +02:00
goto err ;
}
/* Setup param for _ma_sort_write_record */
sort_info . info = info ;
sort_info . new_data_file_type = share - > data_file_type ;
sort_param . fix_datafile = 1 ;
sort_param . master = 1 ;
sort_param . filepos = share - > pack . header_length ;
old_record_count = info - > state - > records ;
info - > state - > records = 0 ;
if ( sort_info . new_data_file_type ! = COMPRESSED_RECORD )
info - > state - > checksum = 0 ;
2007-01-18 20:38:14 +01:00
if ( sort_record_index ( & sort_param , info , keyinfo ,
share - > state . key_root [ sort_key ] ,
2006-04-11 15:45:10 +02:00
temp_buff , sort_key , new_file , update_index ) | |
maria_write_data_suffix ( & sort_info , 1 ) | |
flush_io_cache ( & info - > rec_cache ) )
goto err ;
if ( info - > state - > records ! = old_record_count )
{
_ma_check_print_error ( param , " found %s of %s records " ,
llstr ( info - > state - > records , llbuff ) ,
llstr ( old_record_count , llbuff2 ) ) ;
goto err ;
}
2007-04-04 22:37:09 +02:00
VOID ( my_close ( info - > dfile . file , MYF ( MY_WME ) ) ) ;
2006-04-11 15:45:10 +02:00
param - > out_flag | = O_NEW_DATA ; /* Data in new file */
2008-01-02 17:27:24 +01:00
info - > dfile . file = new_file ; /* Use new datafile */
_ma_set_data_pagecache_callbacks ( & info - > dfile , info - > s ) ;
2006-04-11 15:45:10 +02:00
info - > state - > del = 0 ;
info - > state - > empty = 0 ;
share - > state . dellink = HA_OFFSET_ERROR ;
info - > state - > data_file_length = sort_param . filepos ;
share - > state . split = info - > state - > records ; /* Only hole records */
share - > state . version = ( ulong ) time ( ( time_t * ) 0 ) ;
info - > update = ( short ) ( HA_STATE_CHANGED | HA_STATE_ROW_CHANGED ) ;
if ( param - > testflag & T_WRITE_LOOP )
{
VOID ( fputs ( " \r " , stdout ) ) ; VOID ( fflush ( stdout ) ) ;
}
got_error = 0 ;
err :
if ( got_error & & new_file > = 0 )
{
VOID ( end_io_cache ( & info - > rec_cache ) ) ;
( void ) my_close ( new_file , MYF ( MY_WME ) ) ;
2007-01-18 20:38:14 +01:00
( void ) my_delete ( param - > temp_filename , MYF ( MY_WME ) ) ;
2006-04-11 15:45:10 +02:00
}
if ( temp_buff )
{
2007-07-02 19:45:15 +02:00
my_afree ( ( uchar * ) temp_buff ) ;
2006-04-11 15:45:10 +02:00
}
my_free ( sort_param . record , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
info - > opt_flag & = ~ ( READ_CACHE_USED | WRITE_CACHE_USED ) ;
VOID ( end_io_cache ( & info - > rec_cache ) ) ;
my_free ( sort_info . buff , MYF ( MY_ALLOW_ZERO_PTR ) ) ;
sort_info . buff = 0 ;
share - > state . sortkey = sort_key ;
WL#3072 - Maria Recovery
Bulk insert: don't log REDO/UNDO for rows, log one UNDO which will
truncate files; this is an optimization and a bugfix (table was left
half-repaired by crash).
Repair: mark table crashed-on-repair at start, bump skip_redo_lsn at start,
this is easier for recovery (tells it to skip old REDOs or even UNDO
phase) and user (tells it to repair) in case of crash, sync files
in the end.
Recovery skips missing or corrupted table and moves to next record
(in REDO or UNDO phase) to be more robust; warns if happens in UNDO phase.
Bugfix for UNDO_KEY_DELETE_WITH_ROOT (tested in ma_test_recovery)
and maria_enable_indexes().
Create missing bitmaps when needed (there can be more than one to create,
in rare cases), log a record for this.
include/myisamchk.h:
new flag: bulk insert repair mustn't bump create_rename_lsn
mysql-test/lib/mtr_report.pl:
skip normal warning in maria-recovery.test
mysql-test/r/maria-recovery.result:
result: crash before bulk insert is committed, causes proper rollback,
and crash right after OPTIMIZE replaces index file with new index file
leads to table marked corrupted and recovery not failing.
mysql-test/t/maria-recovery.test:
- can't check the table or it would commit the transaction,
but check is made after recovery.
- test of crash before bulk-insert-with-repair is committed
(to see if it is rolled back), and of crash after OPTIMIZE has replaced
index file but not finished all operations (to see if recovery fails -
it used to assert when trying to execute an old REDO on the new
index).
storage/maria/CMakeLists.txt:
new file
storage/maria/Makefile.am:
new file
storage/maria/ha_maria.cc:
- If bulk insert on a transactional table using an index repair:
table is initially empty, so don't log REDO/UNDO for data rows
(optimization), just log an UNDO_BULK_INSERT_WITH_REPAIR
which will, if executed, empty the data and index file. Re-enable
logging in end_bulk_insert().
- write log record for repair operation only after it's fully done,
index sort including (maria_repair*() used to write the log record).
- Adding back file->trn=NULL which was removed by mistake earlier.
storage/maria/ha_maria.h:
new member (see ha_maria.cc)
storage/maria/ma_bitmap.c:
Functions to create missing bitmaps:
- one function which creates missing bitmaps in page cache, except
the missing one with max offset which it does not put into page cache
as it will be modified very soon.
- one function which the one above calls, and creates bitmaps in page
cache
- one function to execute REDO_BITMAP_NEW_PAGE which uses the second
one above.
storage/maria/ma_blockrec.c:
- when logging REDO_DELETE_ALL, not only 'records' and 'checksum'
has to be reset under log's mutex.
- execution of REDO_INSERT_ROW_BLOBS now checks the dirty pages' list
- execution of UNDO_BULK_INSERT_WITH_REPAIR
storage/maria/ma_blockrec.h:
new functions
storage/maria/ma_check.c:
- table-flush-before-repair is moved to a separate function reused
by maria_sort_index(); syncing is added
- maria_repair() is allowed to re-enable logging only if it is the one
which disabled it.
- "_ma_flush_table_files_after_repair" was a bad name, it's not after
repair now, and it should not sync as we do more changes to the files
shortly after (sync is postponed to when writing the log record)
- REDO_REPAIR record should be written only after all repair
operations (in particular after sorting index in ha_mara::repair())
- close to the end of repair by sort, flushing of pages must happen
also in the non-quick case, to prepare for the sync at end.
- in parallel repair, some page flushes are not needed as done
by initialize_variables_for_repair().
storage/maria/ma_create.c:
Update skip_redo_lsn, create_rename_lsn optionally.
storage/maria/ma_delete_all.c:
Need to sync files at end of maria_delete_all_rows(), if transactional.
storage/maria/ma_extra.c:
During repair, we sometimes call _ma_flush_table_files() (via
_ma_flush_table_files_before_swap()) while there is a WRITE_CACHE.
storage/maria/ma_key_recover.c:
- when we see CLR_END for UNDO_BULK_INSERT_WITH_REPAIR, re-enable
indices.
- fixing bug: _ma_apply_undo_key_delete() parsed UNDO_KEY_DELETE_WITH_ROOT
wrongly, leading to recovery failure
storage/maria/ma_key_recover.h:
new prototype
storage/maria/ma_locking.c:
DBUG_VOID_RETURN missing
storage/maria/ma_loghandler.c:
UNDO for bulk insert with repair, and REDO for creating bitmaps.
LOGREC_FIRST_FREE to not have to change the for() every time we
add a new record type.
storage/maria/ma_loghandler.h:
new UNDO and REDO
storage/maria/ma_open.c:
Move share.kfile.file=kfile up a bit, so that _ma_update_state_lsns()
can get its value, this fixes a bug where LSN_REPAIRED_BY_MARIA_CHK
was not corrected on disk by maria_open().
Store skip_redo_lsn in index' header.
maria_enable_indexes() had a bug for BLOCK_RECORD, where an empty
file has one page, not 0 bytes.
storage/maria/ma_recovery.c:
- Skip a corrupted, missing, or repaired-with-maria_chk, table in
recovery: don't fail, just go to next REDO or UNDO; but if an UNDO
is skipped in UNDO phase we issue warnings.
- Skip REDO|UNDO in REDO phase if <skip_redo_lsn.
- If UNDO phase fails, delete transactions to not make trnman
assert.
- Update skip_redo_lsn when playing REDO_CREATE_TABLE
- Don't record UNDOs for old transactions which we don't know (long_trid==0)
- Bugfix for UNDO_KEY_DELETE_WITH_ROOT (see ma_key_recover.c)
- Execution of UNDO_BULK_INSERT_WITH_REPAIR
- Don't try to find a page number in REDO_DELETE_ALL
- Pieces moved to ma_recovery_util.c
storage/maria/ma_rename.c:
name change
storage/maria/ma_static.c:
I modified layout of the index' header (inserted skip_redo_lsn in its middle)
storage/maria/ma_test2.c:
allow breaking the test towards the end, tests execution of
UNDO_KEY_DELETE_WITH_ROOT
storage/maria/ma_test_recovery.expected:
6 as testflag instead of 4
storage/maria/ma_test_recovery:
Increase the amount of rollback work to do when testing recovery
with ma_test2; this reproduces the UNDO_KEY_DELETE_WITH_ROOT bug.
storage/maria/maria_chk.c:
skip_redo_lsn should be updated too, for consistency.
Write a REDO_REPAIR after all operations (including sort-records)
have been done.
No reason to flush blocks after maria_chk_data_link() and
maria_sort_records(), there is maria_close() in the end.
write_log_record() is a function, to not clutter maria_chk().
storage/maria/maria_def.h:
New member skip_redo_lsn in the state, and comments
storage/maria/maria_pack.c:
skip_redo_lsn should be updated too, for consistency
storage/maria/ma_recovery_util.c:
_ma_redo_not_needed_for_page(), defined in ma_recovery.c, is needed
by ma_blockrec.c; this causes link issues, resolved by putting
_ma_redo_not_needed_for_page() into a new file (so that it is not
in the same file as repair-related objects of ma_recovery.c).
storage/maria/ma_recovery_util.h:
new file
2008-01-17 23:59:32 +01:00
DBUG_RETURN ( got_error ) ;
2006-04-11 15:45:10 +02:00
} /* sort_records */
2007-01-18 20:38:14 +01:00
/* Sort records recursive using one index */
2006-04-11 15:45:10 +02:00
static int sort_record_index ( MARIA_SORT_PARAM * sort_param , MARIA_HA * info ,
MARIA_KEYDEF * keyinfo ,
2007-07-02 19:45:15 +02:00
my_off_t page , uchar * buff , uint sort_key ,
2006-04-11 15:45:10 +02:00
File new_file , my_bool update_index )
{
2007-12-10 01:32:00 +01:00
MARIA_SHARE * share = info - > s ;
2006-04-11 15:45:10 +02:00
uint nod_flag , used_length , key_length ;
2007-07-02 19:45:15 +02:00
uchar * temp_buff , * keypos , * endpos ;
2006-04-11 15:45:10 +02:00
my_off_t next_page , rec_pos ;
2007-07-02 19:45:15 +02:00
uchar lastkey [ HA_MAX_KEY_BUFF ] ;
2006-04-11 15:45:10 +02:00
char llbuff [ 22 ] ;
MARIA_SORT_INFO * sort_info = sort_param - > sort_info ;
HA_CHECK * param = sort_info - > param ;
DBUG_ENTER ( " sort_record_index " ) ;
2007-12-10 01:32:00 +01:00
nod_flag = _ma_test_if_nod ( share , buff ) ;
2006-04-11 15:45:10 +02:00
temp_buff = 0 ;
if ( nod_flag )
{
2007-07-02 19:45:15 +02:00
if ( ! ( temp_buff = ( uchar * ) my_alloca ( ( uint ) keyinfo - > block_length ) ) )
2006-04-11 15:45:10 +02:00
{
_ma_check_print_error ( param , " Not Enough memory " ) ;
DBUG_RETURN ( - 1 ) ;
}
}
2007-12-10 01:32:00 +01:00
used_length = _ma_get_page_used ( share , buff ) ;
keypos = buff + share - > keypage_header + nod_flag ;
2007-10-09 20:09:50 +02:00
endpos = buff + used_length ;
2006-04-11 15:45:10 +02:00
for ( ; ; )
{
_sanity ( __FILE__ , __LINE__ ) ;
if ( nod_flag )
{
2007-01-18 20:38:14 +01:00
next_page = _ma_kpos ( nod_flag , keypos ) ;
2007-12-10 01:32:00 +01:00
if ( my_pread ( share - > kfile . file , ( uchar * ) temp_buff ,
2006-04-11 15:45:10 +02:00
( uint ) keyinfo - > block_length , next_page ,
MYF ( MY_NABP + MY_WME ) ) )
{
_ma_check_print_error ( param , " Can't read keys from filepos: %s " ,
llstr ( next_page , llbuff ) ) ;
goto err ;
}
2007-01-18 20:38:14 +01:00
if ( sort_record_index ( sort_param , info , keyinfo , next_page , temp_buff ,
sort_key ,
2006-04-11 15:45:10 +02:00
new_file , update_index ) )
goto err ;
}
_sanity ( __FILE__ , __LINE__ ) ;
if ( keypos > = endpos | |
( key_length = ( * keyinfo - > get_key ) ( keyinfo , nod_flag , & keypos , lastkey ) )
= = 0 )
break ;
rec_pos = _ma_dpos ( info , 0 , lastkey + key_length ) ;
2007-12-10 01:32:00 +01:00
if ( ( * share - > read_record ) ( info , sort_param - > record , rec_pos ) )
2006-04-11 15:45:10 +02:00
{
_ma_check_print_error ( param , " %d when reading datafile " , my_errno ) ;
goto err ;
}
if ( rec_pos ! = sort_param - > filepos & & update_index )
{
2007-12-10 01:32:00 +01:00
_ma_dpointer ( info , keypos - nod_flag - share - > rec_reflength ,
2006-04-11 15:45:10 +02:00
sort_param - > filepos ) ;
if ( maria_movepoint ( info , sort_param - > record , rec_pos , sort_param - > filepos ,
sort_key ) )
{
_ma_check_print_error ( param , " %d when updating key-pointers " , my_errno ) ;
goto err ;
}
}
if ( _ma_sort_write_record ( sort_param ) )
goto err ;
}
/* Clear end of block to get better compression if the table is backuped */
2007-07-02 19:45:15 +02:00
bzero ( ( uchar * ) buff + used_length , keyinfo - > block_length - used_length ) ;
2007-12-10 01:32:00 +01:00
if ( my_pwrite ( share - > kfile . file , ( uchar * ) buff , ( uint ) keyinfo - > block_length ,
2006-04-11 15:45:10 +02:00
page , param - > myf_rw ) )
{
_ma_check_print_error ( param , " %d when updating keyblock " , my_errno ) ;
goto err ;
}
if ( temp_buff )
2007-07-02 19:45:15 +02:00
my_afree ( ( uchar * ) temp_buff ) ;
2006-04-11 15:45:10 +02:00
DBUG_RETURN ( 0 ) ;
err :
if ( temp_buff )
2007-07-02 19:45:15 +02:00
my_afree ( ( uchar * ) temp_buff ) ;
2006-04-11 15:45:10 +02:00
DBUG_RETURN ( 1 ) ;
} /* sort_record_index */
WL#3072 - Maria Recovery
Bulk insert: don't log REDO/UNDO for rows, log one UNDO which will
truncate files; this is an optimization and a bugfix (table was left
half-repaired by crash).
Repair: mark table crashed-on-repair at start, bump skip_redo_lsn at start,
this is easier for recovery (tells it to skip old REDOs or even UNDO
phase) and user (tells it to repair) in case of crash, sync files
in the end.
Recovery skips missing or corrupted table and moves to next record
(in REDO or UNDO phase) to be more robust; warns if happens in UNDO phase.
Bugfix for UNDO_KEY_DELETE_WITH_ROOT (tested in ma_test_recovery)
and maria_enable_indexes().
Create missing bitmaps when needed (there can be more than one to create,
in rare cases), log a record for this.
include/myisamchk.h:
new flag: bulk insert repair mustn't bump create_rename_lsn
mysql-test/lib/mtr_report.pl:
skip normal warning in maria-recovery.test
mysql-test/r/maria-recovery.result:
result: crash before bulk insert is committed, causes proper rollback,
and crash right after OPTIMIZE replaces index file with new index file
leads to table marked corrupted and recovery not failing.
mysql-test/t/maria-recovery.test:
- can't check the table or it would commit the transaction,
but check is made after recovery.
- test of crash before bulk-insert-with-repair is committed
(to see if it is rolled back), and of crash after OPTIMIZE has replaced
index file but not finished all operations (to see if recovery fails -
it used to assert when trying to execute an old REDO on the new
index).
storage/maria/CMakeLists.txt:
new file
storage/maria/Makefile.am:
new file
storage/maria/ha_maria.cc:
- If bulk insert on a transactional table using an index repair:
table is initially empty, so don't log REDO/UNDO for data rows
(optimization), just log an UNDO_BULK_INSERT_WITH_REPAIR
which will, if executed, empty the data and index file. Re-enable
logging in end_bulk_insert().
- write log record for repair operation only after it's fully done,
index sort including (maria_repair*() used to write the log record).
- Adding back file->trn=NULL which was removed by mistake earlier.
storage/maria/ha_maria.h:
new member (see ha_maria.cc)
storage/maria/ma_bitmap.c:
Functions to create missing bitmaps:
- one function which creates missing bitmaps in page cache, except
the missing one with max offset which it does not put into page cache
as it will be modified very soon.
- one function which the one above calls, and creates bitmaps in page
cache
- one function to execute REDO_BITMAP_NEW_PAGE which uses the second
one above.
storage/maria/ma_blockrec.c:
- when logging REDO_DELETE_ALL, not only 'records' and 'checksum'
has to be reset under log's mutex.
- execution of REDO_INSERT_ROW_BLOBS now checks the dirty pages' list
- execution of UNDO_BULK_INSERT_WITH_REPAIR
storage/maria/ma_blockrec.h:
new functions
storage/maria/ma_check.c:
- table-flush-before-repair is moved to a separate function reused
by maria_sort_index(); syncing is added
- maria_repair() is allowed to re-enable logging only if it is the one
which disabled it.
- "_ma_flush_table_files_after_repair" was a bad name, it's not after
repair now, and it should not sync as we do more changes to the files
shortly after (sync is postponed to when writing the log record)
- REDO_REPAIR record should be written only after all repair
operations (in particular after sorting index in ha_mara::repair())
- close to the end of repair by sort, flushing of pages must happen
also in the non-quick case, to prepare for the sync at end.
- in parallel repair, some page flushes are not needed as done
by initialize_variables_for_repair().
storage/maria/ma_create.c:
Update skip_redo_lsn, create_rename_lsn optionally.
storage/maria/ma_delete_all.c:
Need to sync files at end of maria_delete_all_rows(), if transactional.
storage/maria/ma_extra.c:
During repair, we sometimes call _ma_flush_table_files() (via
_ma_flush_table_files_before_swap()) while there is a WRITE_CACHE.
storage/maria/ma_key_recover.c:
- when we see CLR_END for UNDO_BULK_INSERT_WITH_REPAIR, re-enable
indices.
- fixing bug: _ma_apply_undo_key_delete() parsed UNDO_KEY_DELETE_WITH_ROOT
wrongly, leading to recovery failure
storage/maria/ma_key_recover.h:
new prototype
storage/maria/ma_locking.c:
DBUG_VOID_RETURN missing
storage/maria/ma_loghandler.c:
UNDO for bulk insert with repair, and REDO for creating bitmaps.
LOGREC_FIRST_FREE to not have to change the for() every time we
add a new record type.
storage/maria/ma_loghandler.h:
new UNDO and REDO
storage/maria/ma_open.c:
Move share.kfile.file=kfile up a bit, so that _ma_update_state_lsns()
can get its value, this fixes a bug where LSN_REPAIRED_BY_MARIA_CHK
was not corrected on disk by maria_open().
Store skip_redo_lsn in index' header.
maria_enable_indexes() had a bug for BLOCK_RECORD, where an empty
file has one page, not 0 bytes.
storage/maria/ma_recovery.c:
- Skip a corrupted, missing, or repaired-with-maria_chk, table in
recovery: don't fail, just go to next REDO or UNDO; but if an UNDO
is skipped in UNDO phase we issue warnings.
- Skip REDO|UNDO in REDO phase if <skip_redo_lsn.
- If UNDO phase fails, delete transactions to not make trnman
assert.
- Update skip_redo_lsn when playing REDO_CREATE_TABLE
- Don't record UNDOs for old transactions which we don't know (long_trid==0)
- Bugfix for UNDO_KEY_DELETE_WITH_ROOT (see ma_key_recover.c)
- Execution of UNDO_BULK_INSERT_WITH_REPAIR
- Don't try to find a page number in REDO_DELETE_ALL
- Pieces moved to ma_recovery_util.c
storage/maria/ma_rename.c:
name change
storage/maria/ma_static.c:
I modified layout of the index' header (inserted skip_redo_lsn in its middle)
storage/maria/ma_test2.c:
allow breaking the test towards the end, tests execution of
UNDO_KEY_DELETE_WITH_ROOT
storage/maria/ma_test_recovery.expected:
6 as testflag instead of 4
storage/maria/ma_test_recovery:
Increase the amount of rollback work to do when testing recovery
with ma_test2; this reproduces the UNDO_KEY_DELETE_WITH_ROOT bug.
storage/maria/maria_chk.c:
skip_redo_lsn should be updated too, for consistency.
Write a REDO_REPAIR after all operations (including sort-records)
have been done.
No reason to flush blocks after maria_chk_data_link() and
maria_sort_records(), there is maria_close() in the end.
write_log_record() is a function, to not clutter maria_chk().
storage/maria/maria_def.h:
New member skip_redo_lsn in the state, and comments
storage/maria/maria_pack.c:
skip_redo_lsn should be updated too, for consistency
storage/maria/ma_recovery_util.c:
_ma_redo_not_needed_for_page(), defined in ma_recovery.c, is needed
by ma_blockrec.c; this causes link issues, resolved by putting
_ma_redo_not_needed_for_page() into a new file (so that it is not
in the same file as repair-related objects of ma_recovery.c).
storage/maria/ma_recovery_util.h:
new file
2008-01-17 23:59:32 +01:00
static my_bool write_log_record ( HA_CHECK * param )
{
/*
Now that all operations including O_NEW_DATA | INDEX are successfully
done , we can write a log record .
*/
MARIA_HA * info = maria_open ( param - > isam_file_name , O_RDWR , 0 ) ;
if ( info = = NULL )
_ma_check_print_error ( param , default_open_errmsg , my_errno ,
param - > isam_file_name ) ;
else
{
if ( write_log_record_for_repair ( param , info ) )
_ma_check_print_error ( param , " %d when writing log record for "
" MARIA-table '%s' " , my_errno ,
param - > isam_file_name ) ;
else if ( maria_close ( info ) )
_ma_check_print_error ( param , default_close_errmsg , my_errno ,
param - > isam_file_name ) ;
else
return FALSE ;
}
return TRUE ;
}
2007-10-03 18:10:32 +02:00
# include "ma_check_standalone.h"