Обсуждение: DELETE eats up all memory and crashes box
When I issue a fairly large DELETE query which has multiple tables
with FOREIGN KEY .... CASCADE on them, Postgres eats up *all* the
memory on my system and the system crashes. I figure that there are
two problems, one is PG eating up all of the memory, the other is the
system crashing and not telling me anything (neither /var/log/messages
nor kernel logging tell me anything). What could cause PG to eat up
all the memory on a system?
Any ideas and/or monitoring methods that I could use to figure out
what is going wrong? I had a top running, and the last thing that I
see is that PG is using up about 22gb of memory and postmaster and
kswapd is working hardest. Perhaps I also set some of my
postgresql.conf numbers incorrectly?
Thanks!
--------------------
Simplified schema:
CREATE TABLE ip_info (
ip IP4R PRIMARY KEY,
country VARCHAR,
...
);
CREATE TABLE flow (
fm_ip IP4R NOT NULL REFERENCES ip_info (ip) ON DELETE CASCADE,
...
);
Offending query: DELETE FROM ip_info WHERE country IN ('Canada',
'Yugoslavia', ...);
Hardware: Quad Dual-core Opteron, 16GB RAM, 8GB swap
Software: PostgreSQL 8.1.3 on RHEL4 x64_64
Purpose: Dedicated PG data-warehouse server
Changed config settings:
shared_buffers = 60000
temp_buffers = 10000
work_mem = 524288
maintenance_work_mem = 524288
max_fsm_pages=2000000
max_fsm_relations=100000
wal_buffers=128
checkpoint_segments=128
checkpoint_timeout=3000
effective_cache_size = 1200000
random_page_cost = 2
"Worky Workerson" <worky.workerson@gmail.com> writes:
> When I issue a fairly large DELETE query which has multiple tables
> with FOREIGN KEY .... CASCADE on them, Postgres eats up *all* the
> memory on my system and the system crashes.
Well, the memory eating is easy to explain: pending-trigger-event list.
System crash sounds like a kernel bug or misconfiguration. You might
want to make sure you have "strict" memory overcommit mode set, else the
problem might just be an inopportune choice of target by the OOM killer.
(I *think* they fixed the OOM killer to never select init, but there are
still plenty of processes you'd not like it to pick ...)
regards, tom lane
On 10/6/06, Tom Lane <tgl@sss.pgh.pa.us> wrote: > "Worky Workerson" <worky.workerson@gmail.com> writes: > > When I issue a fairly large DELETE query which has multiple tables > > with FOREIGN KEY .... CASCADE on them, Postgres eats up *all* the > > memory on my system and the system crashes. > > Well, the memory eating is easy to explain: pending-trigger-event list. > System crash sounds like a kernel bug or misconfiguration. You might > want to make sure you have "strict" memory overcommit mode set, else the > problem might just be an inopportune choice of target by the OOM killer. You were right ... had my vm.overcommit_memory set to 0 (default). Now the process gets killed soon after it starts. Is there any way to tune PG to execute such a query, or am I forced to forgo the convenience of the "ON DELETE CASCADE" and manually delete the records with a subselect?
"Worky Workerson" <worky.workerson@gmail.com> writes:
> On 10/6/06, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> Well, the memory eating is easy to explain: pending-trigger-event list.
> Is there any way to tune PG to execute such a query, or am I forced to
> forgo the convenience of the "ON DELETE CASCADE" and manually delete
> the records with a subselect?
You'd have to tweak the query to not delete so many records at once.
Note that whether you have CASCADE or not is not the issue --- if you
are doing a delete in a foreign-key-referenced relation at all, you
are going to have a trigger event per deleted row no matter what the
details of the FK are.
We've had a TODO item for awhile to spill the pending-trigger-event list
to disk when it gets too big, but no one's gotten around to it, probably
because once you're in that regime performance is going to suck anyway :-(
regards, tom lane
> Note that whether you have CASCADE or not is not the issue --- if you > are doing a delete in a foreign-key-referenced relation at all, you > are going to have a trigger event per deleted row no matter what the > details of the FK are. So the best/fastest* way to do this would be to remove the FK relationship from the tables, delete all my rows with DELETE ... WHERE ip IN (SELECT ...) in the previously FK-ed tables, delete all the rows in the PK table, then recreate the FK relationships? I tried this and it was pretty snappy, assuming that all the indexes are built. *note: loading/creating a datawarehouse, guaranteed exclusive access. Current DW size is about 10 GB.