Subject | Metadata update corrupts database |
---|---|
Author | Ann W. Harrison |
Post date | 2001-07-08T22:04:21Z |
I got the following message recently:
the attached gdb got corrupted after the statement
ALTER TABLE ALBUM ADD LABID INTEGER
gfix repairs it but I lose half of my data.
Looking at the entrails I found the following, very
interesting situation: The relation ALBUM (known to
its friends as 129) had three formats, all numbered
3. And they were different ... well, two were the
same and one was different.
Those who follow this sort of thing will be aware that
RDB$FORMATS is the definitive description of the format
of a record. If the data retrieved from disk doesn't
decompress to exactly the length specified in the format,
there's an error. Each record's header includes its
format number. When there are two different formats with
the same number, there's going to be trouble.
I've just checked a change into Firebird that will keep
duplicate formats from being stored. I'll go see if I
can find the code that could store duplicates. Should
this problem happen to you, here's how you can fix it.
First, make a copy of the database. Working on the copy
find the rdb$relation_id of the table you changed.
select rdb$relation_id from rdb$relations
where rdb$relation_name = <bad table>;
Next, find out if there's a problem.
select max (rdb$format) from rdb$formats
where rdb$relation_id = <bad table id>;
select count (*) from rdb$formats
where rdb$relation_id = <bad table id>;
If those two aren't the same, there's a potential problem.
This next bit works better with qli.
QLI> list rdb$formats with
CON> rdb$relation_id = <bad table id> sorted by
CON> rdb$format
Look at those formats. If, as in the case below, there
are formats with the same name and different rdb$descriptors,
increment the rdb$format field of the one that matches your
new situation.
QLI> for x in rdb$formats with
CON> rdb$relation_id = <bad table id> sorted by
CON> rdb$format
CON print then
CON> if *.modify = 'Y' modify rdb$format
Regards,
Ann
www.ibphoenix.com
We have answers.
RDB$RELATION_ID 129
RDB$FORMAT 1
RDB$DESCRIPTOR 0: LONG, scale 0
1: VARYING, max length 128
RDB$RELATION_ID 129
RDB$FORMAT 2
RDB$DESCRIPTOR 0: LONG, scale 0
1: VARYING, max length 128
2: LONG, scale 0
RDB$RELATION_ID 129
RDB$FORMAT 3
RDB$DESCRIPTOR 0: LONG, scale 0
1: VARYING, max length 128
2: LONG, scale 0
RDB$RELATION_ID 129
RDB$FORMAT 3
RDB$DESCRIPTOR 0: LONG, scale 0
1: VARYING, max length 128
2: LONG, scale 0
RDB$RELATION_ID 129
RDB$FORMAT 3
RDB$DESCRIPTOR 0: LONG, scale 0
1: VARYING, max length 128
2: LONG, scale 0
3: LONG, scale 0
the attached gdb got corrupted after the statement
ALTER TABLE ALBUM ADD LABID INTEGER
gfix repairs it but I lose half of my data.
Looking at the entrails I found the following, very
interesting situation: The relation ALBUM (known to
its friends as 129) had three formats, all numbered
3. And they were different ... well, two were the
same and one was different.
Those who follow this sort of thing will be aware that
RDB$FORMATS is the definitive description of the format
of a record. If the data retrieved from disk doesn't
decompress to exactly the length specified in the format,
there's an error. Each record's header includes its
format number. When there are two different formats with
the same number, there's going to be trouble.
I've just checked a change into Firebird that will keep
duplicate formats from being stored. I'll go see if I
can find the code that could store duplicates. Should
this problem happen to you, here's how you can fix it.
First, make a copy of the database. Working on the copy
find the rdb$relation_id of the table you changed.
select rdb$relation_id from rdb$relations
where rdb$relation_name = <bad table>;
Next, find out if there's a problem.
select max (rdb$format) from rdb$formats
where rdb$relation_id = <bad table id>;
select count (*) from rdb$formats
where rdb$relation_id = <bad table id>;
If those two aren't the same, there's a potential problem.
This next bit works better with qli.
QLI> list rdb$formats with
CON> rdb$relation_id = <bad table id> sorted by
CON> rdb$format
Look at those formats. If, as in the case below, there
are formats with the same name and different rdb$descriptors,
increment the rdb$format field of the one that matches your
new situation.
QLI> for x in rdb$formats with
CON> rdb$relation_id = <bad table id> sorted by
CON> rdb$format
CON print then
CON> if *.modify = 'Y' modify rdb$format
Regards,
Ann
www.ibphoenix.com
We have answers.
RDB$RELATION_ID 129
RDB$FORMAT 1
RDB$DESCRIPTOR 0: LONG, scale 0
1: VARYING, max length 128
RDB$RELATION_ID 129
RDB$FORMAT 2
RDB$DESCRIPTOR 0: LONG, scale 0
1: VARYING, max length 128
2: LONG, scale 0
RDB$RELATION_ID 129
RDB$FORMAT 3
RDB$DESCRIPTOR 0: LONG, scale 0
1: VARYING, max length 128
2: LONG, scale 0
RDB$RELATION_ID 129
RDB$FORMAT 3
RDB$DESCRIPTOR 0: LONG, scale 0
1: VARYING, max length 128
2: LONG, scale 0
RDB$RELATION_ID 129
RDB$FORMAT 3
RDB$DESCRIPTOR 0: LONG, scale 0
1: VARYING, max length 128
2: LONG, scale 0
3: LONG, scale 0