Adding Foreign Key constraint sucks up memory and causes paging - tsql

I'm having a lot of issues adding a simple foreign key constraint to a newly created empty table. Reference table is a tiny one with less than 40 records in it, but it gets referenced quite a bit.
Here's what happens: new table gets created successfully, but when adding a FK constraint, it "thinks" for a really long time and increases CPU load. Memory usage increases, the server starts paging like crazy and becomes unresponsive (connections time out). Cancelling the query does not help. The only thing that works is rebooting the server, which is very costly.
Here's the script I'm trying to run. I'm hoping SQL server gurus can help out. Thx!
USE [my_db]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MyNewTable](
[Column1ID] [int] NOT NULL,
[Column2ID] [int] NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[MyNewTable] WITH CHECK ADD CONSTRAINT [FK_MyNewTable_Column1ID] FOREIGN KEY([Column1ID])
REFERENCES [dbo].[ReferenceTable] ([Column1ID])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[MyNewTable] CHECK CONSTRAINT [FK_MyNewTable_Column1ID]
GO
EDIT: ReferenceTable is a small table that looks something like this:
[Column1ID] [int] IDENTITY(1,1) NOT NULL,
[TxtCol1] [varchar](50) NOT NULL,
[TxtCol2] [varchar](50) NOT NULL,
[TxtCol3] [varchar](200) NOT NULL,
[TxtCol4] [nvarchar](2000) NOT NULL,
[TxtCol5] [varchar](200) NOT NULL,
[BitCol1] [bit] NOT NULL,
[TxtCol6] [varchar](200) NOT NULL,
[NumCol1] [smallint] NOT NULL,
[ExternalColumnId] [int] NOT NULL,
[NumCol2] [int] NOT NULL
Column1ID is referenced a lot by other tables (FK's). ExternalColumnId is a FK to another table. The problem happens during one of the ALTER TABLE calls. Unfortunately both of those were run together, so I'm unable to say which one caused it.
EDIT: Once the DB goes into "thinking" mode, it's possible to bring it back up by switching it to single mode and then back to multi user mode. It is much better than rebooting the server but still unacceptable.

Random thought: do you have any transaction open?
The ALTER TABLE will require exclusive access (as does most DDL) and it could be that it's blocked by a schema lock, which in turn will block ReferenceTable, which in turn will block other queries...

I'd suggest running each query batch in isolation.
First, create the table and see if that succeeds.
Next, try adding the foreign key constraint on its own using WITH NOCHECK instead of WITH CHECK. WITH NOCHECK will suppress any validation of the content in MyNewTable.Column1ID against the values in the column of the referenced table while the constraint is being created. If MyNewTable is empty or has few rows, I wouldn't think that this would have much effect, but I've encountered symptoms like you describe -- except that the table getting the new constraint had millions of rows in it.
Finally, run your last batch to try setting WITH CHECK on your new constraint. If this bogs down, you may just need to leave the new FK set WITH NOCHECK, however that isn't recommended since constraints defined WITH NOCHECK are ignored by the query optimizer until they are set back to WITH CHECK.

If this issue is reproducible, I would suggest you to open a Microsoft Support case. May be it's a bug and you are hitting it. If it's found that it's a known issue they would refund you the charges for opening up the case.

A handful of things to look into -- not solutions, but they might lead to something.
Are there any triggers defined?
Is the database being used or accessed at the time you are creating the new table, or is it idle?
Does anything (at time of deployment or otherwise) UPDATE Column1ID in the reference table, or delete rows in that table?
Is there a primary key or unique constraint on on Column1ID in the reference table? (You don't have one listed, but I'd think SQL would fail right off if one wasn't present.)

Related

Postgresql: why no automatic updates of a id sequence after bulk insert

Assuming, I have this table:
CREATE TABLE IF NOT EXISTS public.test
(
"Id" smallint NOT NULL GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
"Value" character varying(10)
);
and I insert some rows:
INSERT INTO public.test ("Id", "Value") VALUES
(1, 'Val1'),
(2, 'Val2'),
(3, 'Val3');
Everything is fine. But now I want to insert another row
INSERT INTO public.test ("Value") VALUES ('Val9');
and I get the error: duplicate key violates unique constraint
That is, how I learned, because the pk-sequence is out of sync. But why? Is there any senseful reason why pg do not update the sequence automatically? After single INSERTs it works well, but after BULK not? Is there any way to avoid these manually updates? Or is it standard to correct every pk-sequence of every table after every little bulk insert (if there is a serial id)?
For futher information, I use GENERATED BY DEFAULT because I want to migrate a database from mysql and I want to preserve the IDs. And I would like the idea of having a lot of flexibility with the keys (similar to mysql).
But what do I not understand here?
Is it possible to correct the sequence automatically without knowing it's concrete name?
Sorry, more questions than I wanted to ask. But ... I don't understand this concept. Would appreciate some explanation.
The problem is the BY DEFAULT in GENERATED BY DEFAULT AS IDENTITY. That means that you can override the automatically generated keys, like your INSERT statements do.
When that happens, the sequence that implements the identity column is not modified. So when you insert a row without specifying "Id", it will start counting at 1, which causes the conflict.
Never override the default. To make sure this doesn't happen by accident, use GENERATED ALWAYS AS IDENTITY.

Errors creating constraint trigger

Let me start by saying that I’m a Linux/Unix admin. That being said my manager has tasked me with moving older PostgreSQL databases to a RedHat server running 8.4.20. I was successful moving a 7.2.1 db but I’m running into issues moving a 7.4.20 db.
I use pg_dump –c filename and psql < filename. For the problematic db everything runs until I get to a CREATE CONSTRAINT TRIGGER statement. If I run it as it is in the file I get :
NOTICE: ignoring incomplete trigger group for constraint "" FOREIGN KEY data(ups) REFERENCES upsinfo(ups)
DETAIL: Found referenced table's DELETE trigger.
CREATE TRIGGER
If I run set schema 'pg_catalog'; I get:
ERROR: relation "upsinfo" does not exist
The tables (I think) involved are:
CREATE TABLE upsinfo (
ups text NOT NULL,
ipaddr inet,
rcomm text,
wcomm text,
reachable boolean,
managed boolean,
comments text,
region text
);
CREATE TABLE data (
date timestamp with time zone,
ups text,
mib text,
value text
);
The trigger problem trigger statement:
CREATE CONSTRAINT TRIGGER "<unnamed>"
AFTER DELETE ON upsinfo
FROM data
NOT DEFERRABLE INITIALLY IMMEDIATE
FOR EACH ROW
EXECUTE PROCEDURE "RI_FKey_cascade_del"('<unnamed>', 'data', 'upsinfo', 'UNSPECIFIED', 'ups', 'ups');
I know that the RI_FKey_cascade_del function is defined differently in the different versions of pg_catalog. Note that search_path is set to ‘public, pg_catalog’ so I’m also confused why I have to set the schema.
Again I’m not a real PostgreSQL DBA so try to be kind.
Oof, those are really old postgres versions, including the version you're upgrading to (8.4 was released in 2009, and support ended in 2014).
The short answer is that, as long as upsinfo and data are being created and populated, you're probably fine, and good to go. But one of your foreign key relationships is broken.
The long answer, well, let me see if I can explain what is going on (or, at least, what I think is going on).
I'm guessing that the original table definition of data included something like FOREIGN KEY (ups) REFERENCES upsinfo (ups) ON DELETE CASCADE. That causes postgres to automatically make some trigger constraints: 1- every time there's a new row for data, make sure that its ups column matches an existing row in upsinfo, and 2- every time you delete a row from upsinfo, delete the corresponding rows in data, based on the matching ups value.
That (not very informative) error message can come up when the foreign key relationship doesn't work. In order for a foreign key to make sense, the referenced value needs to be unique -- there should be only one row in upsinfo for each distinct value of ups. In order for postgres to know that, there needs to be a unique index or primary key on upsinfo.ups.
In this case, one of a couple things could be breaking it:
There's no primary key or unique index on upsinfo.ups (postgres should not have allowed a foreign key, but may have in very old versions)
There used to be a unique index, but it hadn't properly enforced uniqueness, so it didn't get successfully imported (a bug, again likely from a very old version)
In either case, if that foreign key relationship is important, you can try to fix it once the import is complete. Start by trying to make a unique index on upsinfo.ups, and see if you have problems. If you do, resolve the duplicate entries, and try again till it works. Then issue something like:
ALTER TABLE data
ADD FOREIGN KEY (ups) REFERENCES upsinfo (ups) ON DELETE CASCADE;
Of course, if things are working, it's possible you don't need to fix the foreign key, in which case you're probably able to ignore those errors and just move forward.
Hope that helps, and good luck!
This seems to be a part of ON DELETE CONSTRAINT. If I were you I would delete all such statements and replace them with a proper constraint definition on the target table.
Table definition should then look like this:
CREATE TABLE bookings (
boo_id serial NOT NULL,
boo_hotelid character varying NOT NULL,
boo_roomid integer NOT NULL,
CONSTRAINT pk_bookings
PRIMARY KEY (boo_id),
CONSTRAINT fk_bookings_boo_roomid
FOREIGN KEY (boo_roomid)
REFERENCES rooms (roo_id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
) WITHOUT OIDS;
And this part is what will internally create the trigger:
CONSTRAINT fk_bookings_boo_roomid
FOREIGN KEY (boo_roomid)
REFERENCES rooms (roo_id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
But, to be honest, I do not have an understanding for an upgrade to an unsupported version. You know the Postgres is version 9.5 now, right?

Dropping primary key from a materialized view but unable to recreate it - why?

I have created a materialized view with fast refresh. It has a primary key (with using index) which I want to alter. I ran the following statement in sqlplus:
SQL> alter table
2 MV
3 drop constraint PK_MV;
Table altered.
SQL> alter table
2 MV
3 add constraint PK_MV primary key
4 (
5 A_ID
6 , B_ID
7 )
8 using index
9 tablespace IDX;
alter table
*
ERROR in line 1:
ORA-00955: name is already being used by existing object
It seems that the primary key PK_MV still exists. However, isn't it dropped by the first statement?
Oracle version is Enterprise Edition Release 10.2.0.5.0 - 64bit.
Oracle tends to do certain things in an odd way, out of pure spite, causing odd errors, and to make things worse, when errors occur, it tends to give error messages that are anywhere from useless to outright misleading.
In your case, dropping the constraint PK_MV does not also drop the index behind it, so you are still left with a PK_MV index. Then, later, when you try to re-create the constraint, Oracle insists to also create an index for it, and it just won't stand the possibility that an index with that name might already exist.
To make matters worse, the error message does not give you any hints about the nature of the existing object, so it leaves you with the impression that the existing object is a constraint, since that's what you are trying to create, while in fact the existing object is an index, which you never dealt with, have no use for, and probably don't want to know anything about.
Ah, lovely Oracle. My condolences for having to use it.
So, try the following:
alter table MV drop constraint PK_MV cascade;
The cascade keyword will cause the index behind the constraint to also be dropped.

How to work around error "Delete Prevented by referential constraint" in DB2?

So the problem I have is in my task provided to us by the Professor we are to
create tables
insert records to each table.
update and delete (minimum of 1 record) from each table
using a DB2 Script that is following the old standard where COLLECTIONS are created instead of SCHEMAS
steps 1 and 2 are done. the updates are done. my deletes are giving me a hard time. an example would be this.
CREATE TABLE UMALIK8.CAMPUS (
CAMPUS_ID VARCHAR (10) NOT NULL,
CAMPUS_NAME VARCHAR (30) NOT NULL,
MANAGER_NUM VARCHAR (10) NOT NULL,
CONSTRAINT UMALIK8.CAMPUS_PK PRIMARY KEY (CAMPUS_ID),
CONSTRAINT UMALIK8.CAMPUS_FK FOREIGN KEY (MANAGER_NUM)
REFERENCES UMALIK8.MANAGER(MANAGER_NUM)
ON DELETE CASCADE);
INSERT INTO UMALIK8.CAMPUS (CAMPUS_ID, CAMPUS_NAME, MANAGER_NUM)
VALUES ('King', 'King Campus', 'M021386');
DELETE FROM UMALIK8.CAMPUS
WHERE CAMPUS_ID = 'King';
so when I try to delete it, it says delete prevented by referential constraint "roomassign_fk" which doesn't make sense to me because the roomassign table is like 3 or 4 tables AFTER the campus table, the campus is the parent table, and the manager number is from the manager table and the parent table for manager table is Employee table....all throughout the delete script im getting referential errors and I don't know why. Even in my adult table but my adult table has no foreign keys, its only got a primary key on its own, and its got a bunch of child tables....
Now the order of my script is
Tables,
Inserts,
Updates,
Deletes
all separated from each other in one long script
any idea how to fix this? what am i doing wrong?
your help is greatly appreciated, thanks!
As discussed on the comments with the OP turns out that the issue is about a trigger on the table CAMPUS. As the OP asked I'm putting this as an answer.
Is it possible to exist on this table UMALIK8.CAMPUS a trigger which is inserting registries in a table that has an FK to it?
What I mean with a trigger is that if your table has an after insert trigger that would mean something like this: you run the insert command on CAMPUS, after the insert happens the DB2 will call the trigger and insert in a ROOM (i think that is the name of other table given the FK name) one registry which will be linked (by FK) to the one you just inserted on CAMPUS, then if you try to delete the registry on CAMPUS the referential constraint "roomassign_fk" will happen because you have a child registry that is linked to the one in CAMPUS

django: manually adding a foreign key column (newcolumn_id_refs_id_4bfb2ece ?)

I need to add a foreign key field to an existing django model/postgres table. As per the django documentation, I ran the 'sqlall myapp' command to 'work out the difference'.
The obvious difference is that the table in question now has an extra column with a new contraint, which looks like this:
ALTER TABLE "myapp_mytable" ADD CONSTRAINT newcolumn_id_refs_id_4bfb2ece
FOREIGN KEY ("newcolumn_id") REFERENCES "myapp_theothertable" ("id")
DEFERRABLE INITIALLY DEFERRED;
Before messing with my database, I'd like to understand that statement, in particular, what does the last part of newcolumn_id_refs_id_4bfb2ece refer to?
Thanks,
Martin
It will make PostgreSQL understand and enforce your foreign key to the other table and guarantee there won't be anything in myapp_table.newcolumn that can't be found in myapp_theothertable.id
Actually, your django app will work just fine even without that constraint. However, it's a good idea to have one in place, and if you do afterwards a dumpdata - loaddata -cycle, it will be created.