#At file:///G:/bzr/overflowpages/ based on revid:kevin.lewis@stripped
3129 Vladislav Vaintroub 2009-04-20
Bug #41840 Unbounded tablespace growth during recovery
Sometimes, after recovery the tablespaces get huge, orders of
magnitude larger than original tablespace.
The problem was that page overflow pages were not deleted
during recovery. If a record was modified several times during
recovery, the overflow pages that were created during recovery
also leaked.
The fix is to remove overflow pages , when it is possible.
- remove all SRLOverflowPages found in course of recovery
- just like during normal runtime,when record gets modified in
recovery, remove overflow pages if the removal is safe.
Safe means, that page referenced is a valid dataoverflow page.
Validity is guaranteed, if page is either not touched by recovery,
or the page was allocated during recovery and not yet freed.
modified:
storage/falcon/DataPage.cpp
storage/falcon/SRLOverflowPages.cpp
storage/falcon/Section.cpp
storage/falcon/SerialLog.cpp
storage/falcon/SerialLog.h
=== modified file 'storage/falcon/DataPage.cpp'
--- a/storage/falcon/DataPage.cpp 2008-12-04 12:22:04 +0000
+++ b/storage/falcon/DataPage.cpp 2009-04-20 18:40:49 +0000
@@ -55,7 +55,7 @@ int DataPage::updateRecord(Section *sect
int32 overflowPageNumber;
memcpy (&overflowPageNumber, ptr, sizeof (int32));
- if (overflowPageNumber && !dbb->serialLog->recovering)
+ if (overflowPageNumber)
deleteOverflowPages (dbb, overflowPageNumber, transId);
}
@@ -301,7 +301,7 @@ int DataPage::deleteLine (Dbb *dbb, int
int32 overflowPageNumber;
memcpy (&overflowPageNumber, ptr, sizeof (int32));
- if (overflowPageNumber && !dbb->serialLog->recovering)
+ if (overflowPageNumber)
deleteOverflowPages (dbb, overflowPageNumber, transId);
}
@@ -341,6 +341,16 @@ void DataPage::validate(Dbb *dbb)
void DataPage::deleteOverflowPages(Dbb * dbb, int32 overflowPageNumber, TransId transId)
{
+ SerialLog *log = dbb->serialLog;
+
+ if (log->recovering)
+ {
+ if (!log->isOverflowPageValid(overflowPageNumber, dbb->tableSpaceId))
+ return;
+ log->setOverflowPageInvalid(overflowPageNumber, dbb->tableSpaceId);
+ }
+
+
while (overflowPageNumber)
{
Bdb *bdb = dbb->fetchPage (overflowPageNumber, PAGE_data_overflow, Exclusive);
=== modified file 'storage/falcon/SRLOverflowPages.cpp'
--- a/storage/falcon/SRLOverflowPages.cpp 2008-03-11 16:15:47 +0000
+++ b/storage/falcon/SRLOverflowPages.cpp 2009-04-20 18:40:49 +0000
@@ -89,7 +89,11 @@ void SRLOverflowPages::pass2(void)
if (log->tracePage == pageNumber)
print();
- log->bumpPageIncarnation(pageNumber, tableSpaceId, objInUse);
+ if (log->bumpPageIncarnation(pageNumber, tableSpaceId, objInUse))
+ {
+ log->redoFreePage(pageNumber, tableSpaceId);
+ log->setOverflowPageInvalid(pageNumber, tableSpaceId);
+ }
}
}
=== modified file 'storage/falcon/Section.cpp'
--- a/storage/falcon/Section.cpp 2009-04-16 11:25:48 +0000
+++ b/storage/falcon/Section.cpp 2009-04-20 18:40:49 +0000
@@ -782,9 +782,16 @@ int Section::storeTail(Stream * stream,
*pLength = length;
- if (!dbb->serialLog->recovering && !dbb->noLog)
- dbb->serialLog->logControl->overflowPages.append(dbb, &pageNumbers);
-
+
+ SerialLog *log = dbb->serialLog;
+ if (log)
+ {
+ if (log->recovering)
+ log->setOverflowPageValid(overflowPageNumber, dbb->tableSpaceSectionId);
+ else if (!earlyWrite)
+ log->logControl->overflowPages.append(dbb, &pageNumbers);
+ }
+
return overflowPageNumber;
}
=== modified file 'storage/falcon/SerialLog.cpp'
--- a/storage/falcon/SerialLog.cpp 2009-04-13 22:37:55 +0000
+++ b/storage/falcon/SerialLog.cpp 2009-04-20 18:40:49 +0000
@@ -96,6 +96,7 @@ SerialLog::SerialLog(Database *db, JStri
bufferSpace = NULL;
recoveryPages = NULL;
recoveryIndexes = NULL;
+ recoveryOverflowPages = NULL;
recoverySections = NULL;
recoveryPhase = 0;
tracePage = TRACE_PAGE;
@@ -153,6 +154,7 @@ SerialLog::~SerialLog()
delete logControl;
delete recoveryIndexes;
delete recoverySections;
+ delete recoveryOverflowPages;
SerialLogWindow *window;
while ( (window = firstWindow) )
@@ -394,6 +396,7 @@ void SerialLog::recover()
recoveryPages = new RecoveryObjects(this);
recoverySections = new RecoveryObjects(this);
recoveryIndexes = new RecoveryObjects(this);
+ recoveryOverflowPages = new RecoveryObjects(this);
recoveryPhase = 1;
// Phase 1 - read from the start to end of the part of the
@@ -505,9 +508,12 @@ void SerialLog::recover()
delete recoveryPages;
delete recoverySections;
delete recoveryIndexes;
+ delete recoveryOverflowPages;
recoveryPages = NULL;
recoveryIndexes = NULL;
recoverySections = NULL;
+ recoveryOverflowPages = NULL;
+
droppedTablespaces.clear();
for (window = firstWindow; window; window = window->next)
@@ -1173,6 +1179,29 @@ bool SerialLog::isSectionActive(int sect
return recoverySections->isObjectActive(sectionId, tableSpaceId);
}
+bool SerialLog::isOverflowPageValid(int pageNumber, int tableSpaceId)
+{
+ // If page was not touched by recovery, assume it is valid
+ if (!recoveryPages->findRecoveryObject(pageNumber, tableSpaceId))
+ return true;
+
+ // Otherwise, if page was not created during recovery itself,
+ // or was deleted in course of recovery, it is invalid
+ if (!recoveryOverflowPages->findRecoveryObject(pageNumber, tableSpaceId))
+ return false;
+ return recoveryOverflowPages->isObjectActive(pageNumber, tableSpaceId);
+}
+
+void SerialLog::setOverflowPageValid(int pageNumber, int tableSpaceId)
+{
+ recoveryOverflowPages->setActive(pageNumber, tableSpaceId);
+}
+
+void SerialLog::setOverflowPageInvalid(int pageNumber, int tableSpaceId)
+{
+ recoveryOverflowPages->setInactive(pageNumber, tableSpaceId);
+}
+
uint32 SerialLog::appendLog(IO *shadow, int lastPage)
{
Sync sync(&syncWrite, "SerialLog::appendLog");
=== modified file 'storage/falcon/SerialLog.h'
--- a/storage/falcon/SerialLog.h 2009-04-13 22:37:55 +0000
+++ b/storage/falcon/SerialLog.h 2009-04-20 18:40:49 +0000
@@ -94,6 +94,7 @@ public:
uint32 appendLog (IO *shadow, int lastPage);
bool isSectionActive(int sectionId, int tableSpaceId);
bool isIndexActive(int indexId, int tableSpaceId);
+
SerialLogBlock* findLastBlock (SerialLogWindow *window);
void initializeWriteBlock (SerialLogBlock *block);
void checkpoint(bool force);
@@ -127,6 +128,9 @@ public:
void setSectionInactive(int id, int tableSpaceId);
void setIndexActive(int id, int tableSpaceId);
void setIndexInactive(int id, int tableSpaceId);
+ void setOverflowPageValid(int pageNumber, int tableSpaceId);
+ void setOverflowPageInvalid(int pageNumber, int tableSpaceId);
+ bool isOverflowPageValid(int pageNumber, int tableSpaceId);
void setTableSpaceDropped(int tableSpaceId);
bool isTableSpaceDropped(int tableSpaceId);
void updateSectionUseVector(uint sectionId, int tableSpaceId, int delta);
@@ -173,6 +177,7 @@ public:
RecoveryObjects *recoveryPages;
RecoveryObjects *recoverySections;
RecoveryObjects *recoveryIndexes;
+ RecoveryObjects *recoveryOverflowPages;
Bitmap droppedTablespaces;
Dbb *defaultDbb;
Gopher *gophers;
Attachment: [text/bzr-bundle] bzr/vvaintroub@mysql.com-20090420184049-ejyzmbtc9rhwl8r9.bundle