Failure to follow the downgrading procedure described in Section 13.7.11.3, “How to Downgrade” may lead to compatibility issues when files written by InnoDB 1.1 or the InnoDB Plugin are accessed by an earlier version of InnoDB. This section describes some internal recovery algorithms, to help explain why it is important to follow the downgrade procedure described above. It discusses the issues that may arise, and covers possible ways to fix them.
A general fix is to install the plugin as described in Section 13.7.9, “Installing the InnoDB Storage Engine” and then follow the downgrading procedure described in Section 13.7.11.3, “How to Downgrade”.
In the future, the file format management features described in Section 13.7.4, “InnoDB File Format Management” will guard against the types of problems described in this section.
The built-in InnoDB in MySQL can only open tables that were created in
REDUNDANT
or COMPACT
format. Starting with MySQL version
5.0.21, an attempt to open a table in some other format results
in ERROR 1146 (42S02): Table
'
.
Also, a message “test.t
' doesn't existunknown table
type
” appears in the error log.
In InnoDB 1.1, you can rebuild an incompatible table by issuing
a statement ALTER TABLE
.
table_name
ROW_FORMAT=COMPACT
As noted in
Section 13.7.11.3, “How to Downgrade”, you should
ensure a “slow” shutdown is done with the
InnoDB storage engine, before running with the built-in InnoDB in MySQL, to clean up
all buffers. To initiate a slow shutdown, execute the command
SET GLOBAL innodb_fast_shutdown=0
before
initiating the shutdown of the InnoDB storage engine.
We recommend “slow” shutdown
(innodb_fast_shutdown=0
) because the
InnoDB storage engine may write special records to the transaction
undo log that cause problems if the built-in InnoDB in MySQL attempts to read
the log. Specifically, these special records are written when a
record in a COMPRESSED
or DYNAMIC
table is updated or
deleted and the record contains columns stored off-page. The
built-in InnoDB in MySQL cannot read these undo log records. Also, the
built-in InnoDB in MySQL cannot roll back incomplete transactions that affect
tables that it is unable to read (tables in COMPRESSED
or
DYNAMIC
format).
Note that a “normal” shutdown does not
necessarily empty the undo log. A normal shutdown
occurs when innodb_fast_shutdown=1
, the
default. When InnoDB is shut down, some active transactions
may have uncommitted modifications, or they may be holding a
read view that prevents the purging of some version information
from the undo log. The next time InnoDB is started after a
normal shutdown (innodb_fast_shutdown=1
), it
rolls back any incomplete transactions and purge old version
information. Therefore, it is important to perform a
“slow” shutdown
(innodb_fast_shutdown=0
) as part of the
downgrade process.
In case it is not possible to have the InnoDB storage engine clear the
undo log, you can prevent the built-in InnoDB in MySQL from accessing the undo
log by setting innodb_force_recovery
=3. However, this is not a
recommended approach, since in addition to preventing the purge
of old versions, this recovery mode prevents the rollback of
uncommitted transactions. For more information, see
Section 13.6.7.2, “Forcing InnoDB
Recovery”.
When it comes to downgrading, there are also considerations with
respect to redo log information. For the purpose of crash
recovery, InnoDB writes to the log files information about
every modification to the data files. When recording changes to
tables that were created in DYNAMIC
or COMPRESSED
format,
the InnoDB storage engine writes redo log entries that cannot be
recognized by the built-in InnoDB in MySQL. The built-in InnoDB in MySQL refuses to start if
it sees any unknown entries in the redo log.
When InnoDB is shut down cleanly, it
flushes all unwritten changes from the buffer pool to the data
files and makes a checkpoint in the redo log. When InnoDB is
subsequently restarted, it scans the redo log starting from the
last checkpoint. After a clean shutdown, InnoDB crash recovery
only then sees the end-of-log marker in the redo log. In this
case, the built-in InnoDB in MySQL would not see any unrecognizable redo log
entries. This is a second reason why you should ensure a clean,
slow shutdown of MySQL
(innodb_fast_shutdown=0
) before you attempt a
downgrade.
In an emergency, you may prevent the redo log scan and the crash
recovery from the redo log by setting the parameter
innodb_force_recovery
=6. However, this is
strongly discouraged, because
it may lead into severe corruption. See
Section 13.6.7.2, “Forcing InnoDB
Recovery” for more information.
InnoDB uses a novel file flush technique called doublewrite. Before writing pages to a data file, InnoDB first writes them to a contiguous area called the doublewrite buffer. Only after the write and the flush to the doublewrite buffer have completed does InnoDB write the pages to their proper positions in the data file. If the operating system crashes in the middle of a page write, InnoDB can later find a good copy of the page from the doublewrite buffer during recovery.
The doublewrite buffer may also contain compressed pages.
However, the built-in InnoDB in MySQL cannot recognize such pages, and it
assumes that compressed pages in the doublewrite buffer are
corrupted. It also wrongly assumes that the tablespace (the
.ibd
file) consists of 16K byte pages. Thus,
you may find InnoDB warnings in the error log of the form
“a page in the doublewrite buffer is not within space
bounds”.
The doublewrite buffer is not scanned after a clean
shutdown. In an emergency, you may prevent crash
recovery by setting innodb_force_recovery
=6. However, this is
strongly discouraged,
because it may lead into severe corruption. See
Section 13.6.7.2, “Forcing InnoDB
Recovery” for more information.
Secondary indexes are usually non-unique, and DML operations on secondary indexes happen in a relatively random order. This would cause a lot of random disk I/O operations without a special mechanism used in InnoDB called the insert buffer.
When a change is made to a non-unique secondary index page that is not in the buffer pool, InnoDB inserts the record into a special B-tree: the insert buffer. Periodically, the insert buffer is merged into the secondary index trees in the database. A merge also occurs whenever a secondary index page is loaded to the buffer pool.
A “normal” shutdown does not clear the
insert buffer. A normal shutdown occurs when
innodb_fast_shutdown=1
, the default. If the
insert buffer is not empty when the InnoDB storage engine is shut
down, it may contain changes for tables in DYNAMIC
or
COMPRESSED
format. Thus, starting the built-in InnoDB in MySQL on the data
files may lead into a crash if the insert buffer is not empty.
A “slow” shutdown merges all changes from
the insert buffer. To initiate a slow shutdown,
execute the command SET GLOBAL
innodb_fast_shutdown=0
before initiating the shutdown
of the InnoDB storage engine.
To disable insert buffer merges, set innodb_force_recovery
=4
so that you can back up the uncompressed tables with the
built-in InnoDB in MySQL. Be sure not to use any WHERE
conditions that would require access to secondary indexes. For
more information, see
Section 13.6.7.2, “Forcing InnoDB
Recovery”.
In the InnoDB storage engine 1.0.3 and later, you can disable the
buffering of new operations by setting the parameter
innodb_change_buffering
. See
Section 13.7.7.4, “Controlling InnoDB Change Buffering” for
details.