Found this here:
In general, consider creating an index on a column in any of the following situations:
A referential integrity constraint exists on the indexed column or
columns. The index is a means to avoid a full table lock that would
otherwise be required if you update the parent table primary key,
merge into the parent table, or delete from the parent table.
I don't understand why a full table lock would occurr in such situation. I would've thought that if I tried to delete/update the primary key in the parent table that a full table scan would be performed on the child table.
Where does the lock come from?
Have a look at this Tom Kyte blog entry. In it, he refers to the Oracle documentation, where this explanation is offered:
Prevents a full table lock on the child table. Instead, the database acquires a row lock on the index.
Removes the need for a full table scan of the child table. As an illustration, assume that a user removes the record for department 10 from the departments table. If employees.department_id is not indexed, then the database must scan employees to see if any employees exist in department 10.
In the first scenario, if the column is not indexed, the entire table must be locked because Oracle does not know which rows must be updated in the child table. With an index, Oracle can identify the rows in question and just lock them. Without the full table lock, it would be possible to modify the parent and have another session modify the child to something that violated the constraint.
Related
Scenario: We have table A (Parent Table) referring to table B (Child Table) and also we have Foreign Key Index for every Foreign Key.
Operation: Now when any user is deleting a row from table A then table B is getting locked even if there are no referring record in child table. Because of this other user cannot do anything on table A anymore since the table is locked.
Understanding: I suppose when there are some child record exists in table B then the selected row should only be locked if the parent record is involved in some transaction and other users can still work on other rows of table A.
Question: How does it work when we have foreign key and foreign key index are created but there are no child record exists. The whole table is still locked? If yes how to get rid of it then?
Note: I am using Oracle 12c.
You should have indexes on all foreign keys, otherwise you'll get TM table locks:
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:292016138754
http://www.oaktable.net/content/tm-locking-checking-missing-indexes-foreign-key-constraints
Now when any user is deleting a row from table A then table B is getting locked even if there are no referring record in child table.
If you have index on foreign key in child table, you get only TX row locks in child table. If you foerign key is not indexes, you get TM table lock on whole child table.
I need to update the primary key of a large Index Organized Table (20 million rows) on Oracle 11g.
Is it possible to do this using multiple UPDATE queries? i.e. Many smaller UPDATEs of say 100,000 rows at a time. The problem is that one of these UPDATE batches could temporarily produce a duplicate primary key value (there would be no duplicates after all the UPDATEs have completed.)
So, I guess I'm asking is it somehow possible to temporarily disable the primary key constraint (but which is required for an IOT!) or alter the table temporarily some other way. I can have exclusive and offline access to this table.
The only solution I can see is to create a new table and when complete, drop the original table and rename the new table to the original table name.
Am I missing another possibility?
You can't disable / drop the primary key constraint from an IOT, since it is a unique index by definition.
When I need to change an IOT like this, I either do a CTAS (create table as) for a new plain heap table, do my maintenance, and then CTAS a new IOT.
Something like:
create table t_temp as select * from t_iot;
-- do maintenance
create table t_new_iot as select * from t_temp;
If, however, you need to simply add or join a new field to the existing key, you can do this in one step by creating the new IOT structure, then populating directly from the old IOT with a query.
Unfortunately, this is one of the downsides to IOTs.
I would recommend following method:
Create new IOT table partitioned by system with single partition
with exactly same structure as current one.
Lock current IOT table to prevent any DML.
insert into new table as select from current table changing PK values in select. This step
could be repeated several times if needed. In this case it's better
to do it in another session to keep lock on original table.
Exchange partition of new table with original table.
We have deadlock issue in Oracle 11.2g. One potential reason why deadlock occurs is deleting from child table locks parent table. I searched from oracle documentations, and did't find any specification this kind of lock. Any explanation or reference of documentation would be greatly appreciated.
Here is the code.
CREATE TABLE table_parent (a NUMBER PRIMARY KEY);
CREATE TABLE table_child (b NUMBER, a NUMBER,PRIMARY KEY (b), CONSTRAINT fk_relation FOREIGN KEY (a) REFERENCES table_parent(a));
INSERT INTO table_parent VALUES (1);
INSERT INTO table_parent VALUES (2);
INSERT INTO table_child VALUES (1,1);
INSERT INTO table_child VALUES (2,1);
INSERT INTO table_child VALUES (3,1);
INSERT INTO table_child VALUES (4,1);
COMMIT;
Then delete 1 record from child table.
DELETE FROM table_child WHERE b=4;
When we look V$LOCK table before executing commit. There is two new lock that 'table_child' and 'table_parent' in type of 'TM'.
Here is the query to look V$LOCK table.
SELECT O.OWNER, O.OBJECT_ID, O.OBJECT_NAME, O.OBJECT_TYPE, L.TYPE
FROM DBA_OBJECTS O, V$LOCK L
WHERE O.OBJECT_ID = L.ID1;
The question is why 'table_parent' has been locked?
For maintaining constraints that 'span multiple rows', which is the case for a foreign key, there are moments when one (ie. the DBMS) needs to serialize transactions. The moments at which serialization is required depend one-on-one on the type of changes that a transaction performs on the involved tables. Theoretically (in a DBMS that offers snapshot isolation, which is what Oracle does), only if the type of change is such that it could potentially violate the multi-row constraint, would the DBMS need to automatically serialize transactions (for instance by acquiring various types of locks).
Now in the case of a foreign key, one needs to ask oneself: when can a foreign key be violated? There are four scenarios.
a parent row is deleted: will violate FK if child-rows still exist.
a parent row's key is updated: will violate FK if child-rows till 'point to' old value of key.
a child row is inserted: will violate FK if row points-to non-existent parent-row.
a child row's fk-column value is updated: will violate FK if new column value points to non-existent parent-row.
All other types of transactions on the (2) tables involved can never violate the FK. So in your case, a child row is deleted, no serialization should be necessary. However Oracle probably has some 'implementation specific' reason, which forces it to do acquire some kind of lock.
I've seen a different scenario where Oracle performs this kind of "unnecessary" locking too: you can find it here https://forums.oracle.com/forums/thread.jspa?messageID=10050753�
Toon
Add an index on the table_child(a) column -- you always index foreign key columns for just this reason.
An answer to this is explained with examples here http://www.oraclebin.com/2012/12/what-is-deadlock-in-oracle.html
Situation:
Table TBL has ~10k entries for deletion,
Table TBL has 14 child tables with delete rule "no action",
I want to delete 10k entries and referenced entries in child tables.
Procedure:
Delete records in child tables,
Disable constraints (if constraints are not disabled deletion in next step takes forever),
Delete records in TBL table,
Enable constraints.
Is there more elegant way for doing this?
The problem is that third step takes too long because it is checking 14 big tables for existence of non existent records. My procedure has good execution time but I think that there is more elegant way.
It sounds like you need to index your foreign keys on your child tables. Every time you delete a parent record without an index on the child table it must do a full table scan of the child to check if the foreign key constraint was broken.
With the index, it is at worst case an index range scan.
Edit:
More info, and a script to determine if this is your problem can be found here.
http://asktom.oracle.com/tkyte/unindex/index.html
So we've been told that one source of TM Enq contention can be unindexed FK's. My question is which one.
I have an INSERT INTO Table_B that is recording TM Enq Wait.
It contains a PK that is the parent to other tables and it has columns that are FK constrained to other PKs.
So which FKs need indexed: that table's columns or its children?
NB: I know that this isn't the only cause of TM Contention. Can you explain why it couldn't possibly be this if that's the case.
Not sure about Oracle TM Contention, but I'd say normally both sides of a foreign key relation are indexed. Otherwise, the database will have to do table scans.
The index on the parent record is used whenever you insert a new child record, to verify that the parent exists. Often this is a primary key as well, so of course has an index.
The index on the child record is used whenever you change or delete a parent record, to perform cascades (including refusing the update/delete).
The indices on both sides also give the database a good chance of doing fast (indexed) joins, no matter which side its optimizer prefers to come from.
EDIT: Having Googled TM contention, it sounds like you're probably missing the keys on the child records. But make sure to have them on both sides, really.
EDIT 2: Answering the comment,
If you have a OLTP table that has 13 FKs to lookup tables, I'm not
keen on 13 index updates in addition to the table, pk and any other
indexes. An index is important but for specific reasons. If you never
update the parent PK nor delete from the parent, the child index is
not so useful. Or is it?
Depends on the joins and queries you're running, then. E.g., if you run
a query like:
SELECT o.something
FROM oltp_tab o JOIN lookup l ON (o.lookup_no = l.lookup_no)
WHERE l.lookup_name = ?
then the query optimizer would probably like the index on the child
records.
Also, according to http://ashmasters.com/waits/enq-tm-contention/ you
pretty much need to have the indices if you change the parent tables at
all. Apparently you get them from having concurrent changes to the
parent and child tables, unless you have the index. So this is probably
what you're seeing (assuming you're not doing the obvious things, like
updating the referred to columns or deleting rows)
The parent (referenced) column of an enabled foreign key relationship has to be indexed because it has to have an enabled unique or primary key constraint on it.
What mode of TM Enqueue are you seeing?