Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
P
postgres-lambda-diff
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Jakob Huber
postgres-lambda-diff
Commits
7e14593d
Commit
7e14593d
authored
25 years ago
by
Vadim B. Mikheev
Browse files
Options
Downloads
Patches
Plain Diff
Fix tuple chain moving bug found by "Hiroshi Inoue" <Inoue@tpf.co.jp>.
parent
b14c99d8
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/backend/commands/vacuum.c
+105
-17
105 additions, 17 deletions
src/backend/commands/vacuum.c
with
105 additions
and
17 deletions
src/backend/commands/vacuum.c
+
105
−
17
View file @
7e14593d
...
...
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.10
2
1999/05/
10 00:44:59 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.10
3
1999/05/
23 09:10:24 vadim
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -87,7 +87,7 @@ static void vc_scanheap(VRelStats *vacrelstats, Relation onerel, VPageList vacuu
static
void
vc_rpfheap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
VPageList
vacuum_pages
,
VPageList
fraged_pages
,
int
nindices
,
Relation
*
Irel
);
static
void
vc_vacheap
(
VRelStats
*
vacrelstats
,
Relation
onerel
,
VPageList
vpl
);
static
void
vc_vacpage
(
Page
page
,
VPageDescr
vpd
);
static
void
vc_vaconeind
(
VPageList
vpl
,
Relation
indrel
,
int
num_tuples
);
static
void
vc_vaconeind
(
VPageList
vpl
,
Relation
indrel
,
int
num_tuples
,
int
keep_tuples
);
static
void
vc_scanoneind
(
Relation
indrel
,
int
num_tuples
);
static
void
vc_attrstats
(
Relation
onerel
,
VRelStats
*
vacrelstats
,
HeapTuple
tuple
);
static
void
vc_bucketcpy
(
Form_pg_attribute
attr
,
Datum
value
,
Datum
*
bucket
,
int16
*
bucket_len
);
...
...
@@ -541,7 +541,7 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
if
(
vacuum_pages
.
vpl_num_pages
>
0
)
{
for
(
i
=
0
;
i
<
nindices
;
i
++
)
vc_vaconeind
(
&
vacuum_pages
,
Irel
[
i
],
vacrelstats
->
num_tuples
);
vc_vaconeind
(
&
vacuum_pages
,
Irel
[
i
],
vacrelstats
->
num_tuples
,
0
);
}
else
/* just scan indices to update statistic */
...
...
@@ -1042,9 +1042,11 @@ vc_rpfheap(VRelStats *vacrelstats, Relation onerel,
num_fraged_pages
,
vacuumed_pages
;
int
checked_moved
,
num_tuples
;
num_tuples
,
keep_tuples
=
0
;
bool
isempty
,
dowrite
;
dowrite
,
chain_tuple_moved
;
struct
rusage
ru0
,
ru1
;
...
...
@@ -1126,6 +1128,7 @@ vc_rpfheap(VRelStats *vacrelstats, Relation onerel,
else
Assert
(
!
isempty
);
chain_tuple_moved
=
false
;
/* no one chain-tuple was moved off this page, yet */
vpc
->
vpd_blkno
=
blkno
;
maxoff
=
PageGetMaxOffsetNumber
(
page
);
for
(
offnum
=
FirstOffsetNumber
;
...
...
@@ -1145,11 +1148,39 @@ vc_rpfheap(VRelStats *vacrelstats, Relation onerel,
{
if
((
TransactionId
)
tuple
.
t_data
->
t_cmin
!=
myXID
)
elog
(
ERROR
,
"Invalid XID in t_cmin"
);
if
(
tuple
.
t_data
->
t_infomask
&
HEAP_MOVED_OFF
)
continue
;
/* already removed by me */
if
(
tuple
.
t_data
->
t_infomask
&
HEAP_MOVED_IN
)
break
;
elog
(
ERROR
,
"HEAP_MOVED_OFF/HEAP_MOVED_IN was expected"
);
elog
(
ERROR
,
"HEAP_MOVED_IN was not expected"
);
/*
* If this (chain) tuple is moved by me already then
* I have to check is it in vpc or not - i.e. is it
* moved while cleaning this page or some previous one.
*/
if
(
tuple
.
t_data
->
t_infomask
&
HEAP_MOVED_OFF
)
{
if
(
keep_tuples
==
0
)
continue
;
if
(
chain_tuple_moved
)
/* some chains was moved while */
{
/* cleaning this page */
Assert
(
vpc
->
vpd_offsets_free
>
0
);
for
(
i
=
0
;
i
<
vpc
->
vpd_offsets_free
;
i
++
)
{
if
(
vpc
->
vpd_offsets
[
i
]
==
offnum
)
break
;
}
if
(
i
>=
vpc
->
vpd_offsets_free
)
/* not found */
{
vpc
->
vpd_offsets
[
vpc
->
vpd_offsets_free
++
]
=
offnum
;
keep_tuples
--
;
}
}
else
{
vpc
->
vpd_offsets
[
vpc
->
vpd_offsets_free
++
]
=
offnum
;
keep_tuples
--
;
}
continue
;
}
elog
(
ERROR
,
"HEAP_MOVED_OFF was expected"
);
}
/*
...
...
@@ -1386,9 +1417,15 @@ moving chain: failed to add item with len = %u to page %u",
tuple
.
t_data
->
t_infomask
|=
HEAP_MOVED_OFF
;
num_moved
++
;
/*
* Remember that we moved tuple from the current page
* (corresponding index tuple will be cleaned).
*/
if
(
Cbuf
==
buf
)
vpc
->
vpd_offsets
[
vpc
->
vpd_offsets_free
++
]
=
ItemPointerGetOffsetNumber
(
&
(
tuple
.
t_self
));
else
keep_tuples
++
;
if
(
Irel
!=
(
Relation
*
)
NULL
)
{
...
...
@@ -1418,6 +1455,7 @@ moving chain: failed to add item with len = %u to page %u",
}
cur_buffer
=
InvalidBuffer
;
pfree
(
vtmove
);
chain_tuple_moved
=
true
;
continue
;
}
...
...
@@ -1532,10 +1570,58 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
}
/* walk along page */
if
(
offnum
<
maxoff
&&
keep_tuples
>
0
)
{
OffsetNumber
off
;
for
(
off
=
OffsetNumberNext
(
offnum
);
off
<=
maxoff
;
off
=
OffsetNumberNext
(
off
))
{
itemid
=
PageGetItemId
(
page
,
off
);
if
(
!
ItemIdIsUsed
(
itemid
))
continue
;
tuple
.
t_data
=
(
HeapTupleHeader
)
PageGetItem
(
page
,
itemid
);
if
(
tuple
.
t_data
->
t_infomask
&
HEAP_XMIN_COMMITTED
)
continue
;
if
((
TransactionId
)
tuple
.
t_data
->
t_cmin
!=
myXID
)
elog
(
ERROR
,
"Invalid XID in t_cmin (4)"
);
if
(
tuple
.
t_data
->
t_infomask
&
HEAP_MOVED_IN
)
elog
(
ERROR
,
"HEAP_MOVED_IN was not expected (2)"
);
if
(
tuple
.
t_data
->
t_infomask
&
HEAP_MOVED_OFF
)
{
if
(
chain_tuple_moved
)
/* some chains was moved while */
{
/* cleaning this page */
Assert
(
vpc
->
vpd_offsets_free
>
0
);
for
(
i
=
0
;
i
<
vpc
->
vpd_offsets_free
;
i
++
)
{
if
(
vpc
->
vpd_offsets
[
i
]
==
off
)
break
;
}
if
(
i
>=
vpc
->
vpd_offsets_free
)
/* not found */
{
vpc
->
vpd_offsets
[
vpc
->
vpd_offsets_free
++
]
=
off
;
Assert
(
keep_tuples
>
0
);
keep_tuples
--
;
}
}
else
{
vpc
->
vpd_offsets
[
vpc
->
vpd_offsets_free
++
]
=
off
;
Assert
(
keep_tuples
>
0
);
keep_tuples
--
;
}
}
}
}
if
(
vpc
->
vpd_offsets_free
>
0
)
/* some tuples were moved */
{
qsort
((
char
*
)
(
vpc
->
vpd_offsets
),
vpc
->
vpd_offsets_free
,
if
(
chain_tuple_moved
)
/* else - they are ordered */
{
qsort
((
char
*
)
(
vpc
->
vpd_offsets
),
vpc
->
vpd_offsets_free
,
sizeof
(
OffsetNumber
),
vc_cmp_offno
);
}
vc_reappage
(
&
Nvpl
,
vpc
);
WriteBuffer
(
buf
);
}
...
...
@@ -1559,7 +1645,6 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
if
(
num_moved
>
0
)
{
/*
* We have to commit our tuple' movings before we'll truncate
* relation, but we shouldn't lose our locks. And so - quick hack:
...
...
@@ -1610,7 +1695,7 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
else
if
(
tuple
.
t_data
->
t_infomask
&
HEAP_MOVED_OFF
)
tuple
.
t_data
->
t_infomask
|=
HEAP_XMIN_INVALID
;
else
elog
(
ERROR
,
"HEAP_MOVED_OFF/HEAP_MOVED_IN was expected
(2)
"
);
elog
(
ERROR
,
"HEAP_MOVED_OFF/HEAP_MOVED_IN was expected"
);
}
}
Assert
((
*
vpp
)
->
vpd_offsets_used
==
num_tuples
);
...
...
@@ -1647,8 +1732,10 @@ Elapsed %u/%u sec.",
*
vpleft
=
*
vpright
;
*
vpright
=
vpsave
;
}
Assert
(
keep_tuples
>=
0
);
for
(
i
=
0
;
i
<
nindices
;
i
++
)
vc_vaconeind
(
&
Nvpl
,
Irel
[
i
],
vacrelstats
->
num_tuples
);
vc_vaconeind
(
&
Nvpl
,
Irel
[
i
],
vacrelstats
->
num_tuples
,
keep_tuples
);
}
/*
...
...
@@ -1678,7 +1765,7 @@ Elapsed %u/%u sec.",
num_tuples
++
;
}
else
elog
(
ERROR
,
"HEAP_MOVED_OFF was expected"
);
elog
(
ERROR
,
"HEAP_MOVED_OFF was expected
(2)
"
);
}
}
...
...
@@ -1854,7 +1941,7 @@ vc_scanoneind(Relation indrel, int num_tuples)
* pg_class.
*/
static
void
vc_vaconeind
(
VPageList
vpl
,
Relation
indrel
,
int
num_tuples
)
vc_vaconeind
(
VPageList
vpl
,
Relation
indrel
,
int
num_tuples
,
int
keep_tuples
)
{
RetrieveIndexResult
res
;
IndexScanDesc
iscan
;
...
...
@@ -1911,11 +1998,12 @@ vc_vaconeind(VPageList vpl, Relation indrel, int num_tuples)
getrusage
(
RUSAGE_SELF
,
&
ru1
);
elog
(
MESSAGE_LEVEL
,
"Index %s: Pages %u; Tuples %u: Deleted %u. Elapsed %u/%u sec."
,
indrel
->
rd_rel
->
relname
.
data
,
num_pages
,
num_index_tuples
,
tups_vacuumed
,
indrel
->
rd_rel
->
relname
.
data
,
num_pages
,
num_index_tuples
-
keep_tuples
,
tups_vacuumed
,
ru1
.
ru_stime
.
tv_sec
-
ru0
.
ru_stime
.
tv_sec
,
ru1
.
ru_utime
.
tv_sec
-
ru0
.
ru_utime
.
tv_sec
);
if
(
num_index_tuples
!=
num_tuples
)
if
(
num_index_tuples
!=
num_tuples
+
keep_tuples
)
elog
(
NOTICE
,
"Index %s: NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)"
,
indrel
->
rd_rel
->
relname
.
data
,
num_index_tuples
,
num_tuples
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment