![]() | |
![]() |
| | Thread Tools | Display Modes |
#1
| |||
| |||
|
#2
| ||||
| ||||
|
|
I have been submitted a challenge from a customer, which is the following: * we have a master table "item" with item_num as primary key * we have a detail table "operation, with operation_num as primary key, and item_num as foreign key, referencing item (item_num) session A initiates a session with begin work; update item set ( some item colums EXCEPT THE PRIMARY KEY ) = ( some values ) where item_num = 100 ; -- leave sesssion "as is" and open another session on other terminal So the change in session A is uncommitted. |
|
session B opens a new session and attempts: insert into operation VALUES ( operation_num_value,100,more values) ==> Session B receives error 691: Missing key in referenced table for referential constraint (PKconstraint). 107: ISAM error: record is locked. |
|
In my mind ( I can be wrong though), I do not expect this error |
|
modified the primary key value. In opposition, I would have expected the constraint violation if I had modified the primary key value in the update statement. It seems that the foreign key constraint does not refer to the primary key index, but only on the fact that the row is locked. In my same mind, I think this scenario would have worked in 7.XX versions, for the reason I stated just above, provided the condtion that I do not modify the primary key value. I have a simple and easy to execute test case with data available on request by email. I may have forgotten some referential constraint basics, my age would allow it :-) Any simple suggestion to achieve such a scenario? |
#3
| |||
| |||
|
|
On Sat, Jan 28, 2012 at 07:50, BeGooden-IT Vercelletto begooden... (AT) gmail (DOT) com> wrote: I have been submitted a challenge from a customer, which is the following: * we have a master table "item" with item_num as primary key * we have a detail table "operation, with operation_num as primary key, and item_num as foreign key, referencing item (item_num) session A initiates a session with begin work; update item set ( some item colums EXCEPT THE PRIMARY KEY ) = ( some values ) where item_num = 100 ; -- leave sesssion "as is" and open another session on other terminal So the change in session A is uncommitted. session B opens a new session and attempts: insert into operation VALUES ( operation_num_value,100,more values) ==> Session B receives error 691: Missing key in referenced table for referential constraint (PKconstraint). 107: ISAM error: *record is locked. This means that there wasn't a committed value 100 that could be referenced, so the statement should fail. This is the most basic requirement for COMMITTED READ or higher isolation.. I'm not sure it should work under DIRTY READ isolation even - although the value might exist at the moment, if the DR session (session B) was allowed to commit, session A might rollback, leaving the row inserted by B not referencing anything - a state of semantic disintegrity that referential integrity is supposed to avoid. In my mind ( I can be wrong though), I do not expect this error This error should be expected - as much because of isolation issues as because of referential integrity issues. because in the UPDATE statement, I have not modified the primary key value. In opposition, I would have expected the constraint violation if I had modified the primary key value in the update statement. It seems that the foreign key constraint does not refer to the primary key index, but only on the fact that the row is locked. In my same mind, I think this scenario would have worked in 7.XX versions, for the reason I stated just above, provided the condtion that I do not modify the primary key value. I have a simple and easy to execute test case with data available on request by email. I may have forgotten some referential constraint basics, my age *would allow it :-) Any simple suggestion to achieve such a scenario? Add a COMMIT to Session A. *That is the best, most reliable way to deal with it. *Pretty much anything else is at best dubious. -- Jonathan Leffler <jonathan.leff... (AT) gmail (DOT) com> *#include <disclaimer.h Guardian of DBD::Informix - v2011.0612 -http://dbi.perl.org "Blessed are we who can laugh at ourselves, for we shall never cease to be amused." |
#4
| |||||
| |||||
|
|
Jonathan, I know that the commit work is missing :-). I left this transaction uncommitted to simulate the real situation happening at my customer, which is: someone modifies the master table( but not the primary key ), goes for lunch, and no-one can insert a row in the detail table. |
|
row lock on table A for value 100. |
|
for primary key = 100 , which is expectable, but since the key is not modified ( ie the primary is not part of the SET (....) = ( ...) ) list by the update statement, there is for me no point in preventing an insert in the detail table for the foreign key = 100. I would accept it if the update statement modified the primary key, which would put this value "at risk" for the match foreign key. |
|
and not on the rows contents... therefore my concern, and this scenario was possible more than 10 years ago. |
|
On 28 jan, 17:48, Jonathan Leffler <jonathan.leff... (AT) gmail (DOT) com> wrote: On Sat, Jan 28, 2012 at 07:50, BeGooden-IT Vercelletto begooden... (AT) gmail (DOT) com> wrote: I have been submitted a challenge from a customer, which is the following: * we have a master table "item" with item_num as primary key * we have a detail table "operation, with operation_num as primary key, and item_num as foreign key, referencing item (item_num) session A initiates a session with begin work; update item set ( some item colums EXCEPT THE PRIMARY KEY ) = ( some values ) where item_num = 100 ; -- leave sesssion "as is" and open another session on other terminal So the change in session A is uncommitted. session B opens a new session and attempts: insert into operation VALUES ( operation_num_value,100,more values) ==> Session B receives error 691: Missing key in referenced table for referential constraint (PKconstraint). 107: ISAM error: record is locked. This means that there wasn't a committed value 100 that could be referenced, so the statement should fail. This is the most basic requirement for COMMITTED READ or higher isolation. I'm not sure it should work under DIRTY READ isolation even - although the value might exist at the moment, if the DR session (session B) was allowed to commit, session A might rollback, leaving the row inserted by B not referencing anything - a state of semantic disintegrity that referential integrity is supposed to avoid. In my mind ( I can be wrong though), I do not expect this error This error should be expected - as much because of isolation issues as because of referential integrity issues. because in the UPDATE statement, I have not modified the primary key value. In opposition, I would have expected the constraint violation if I had modified the primary key value in the update statement. It seems that the foreign key constraint does not refer to the primary key index, but only on the fact that the row is locked. In my same mind, I think this scenario would have worked in 7.XX versions, for the reason I stated just above, provided the condtion that I do not modify the primary key value. I have a simple and easy to execute test case with data available on request by email. I may have forgotten some referential constraint basics, my age would allow it :-) Any simple suggestion to achieve such a scenario? Add a COMMIT to Session A. That is the best, most reliable way to deal with it. Pretty much anything else is at best dubious. |
#5
| |||
| |||
|
|
On Sat, Jan 28, 2012 at 11:32, BeGooden-IT Vercelletto begooden... (AT) gmail (DOT) com> wrote: Jonathan, I know that the commit work is missing :-). I left this transaction uncommitted to simulate the real situation happening at my customer, which is: someone modifies the master table( but not the primary key ), goes for lunch, and no-one can insert a row in the detail table. Correct - don't let the slaves go to lunch! *:-D More accurately, design your systems so that long transactions like that are not a problem. *I also know that when the commit will be issues, it will release the row lock on table A for value 100. OK - I didn't read carefully enough. What is really happening here is that the master table row is locked for primary key = 100 , which is expectable, but since the key is not modified ( ie the primary is not part of the SET (....) = ( ...) ) list by the update statement, there is for me no point in preventing an insert in the detail table for the foreign key = 100. I would accept it if the update statement modified the primary key, which would put this value "at risk" for the match foreign key. The DBMS is good at queries about the state of things as they are, not about the state of things as they will be. *Predicting the future is hard! The DBMS cannot tell whether the locked row will be updated (so that the PK value is changed) after the insert is permitted; the row is locked because it has been changed, but until the new row value is committed, the DBMS cannot tell whether the referential constraint will be satisfied when the row is committed. *Indeed, the row could be deleted after the update but before the commit. It still comes down to isolation. *Until the update is committed, it isnot safe to allow newly added rows in the second table to reference the updated row in the first table. ...But what about the rows already in the second table that reference the row in the first table?... *Good question! *They're integrity will be checked in due course - and an UPDATE or DELETE that eliminates the row in the first table will be disallowed because of the existing references. However, Session A could be designed to go and delete those referencing rows from the second table, and therefore new references should not be inserted in the second table until the value in the first is committed. As far as I remember, referential constraints were based on indexes, and not on the rows contents... therefore my concern, and this scenario was possible more than 10 years ago. Behind the scenes, there is key-value locking on indexes - yes. *But that is mostly an implementation detail. *At the conceptual level, the issueis whether the referenced row is currently committed in the DB. *If it is not, then it is not safe to allow new references to the row. I wonder where LAST COMMITTED isolation fits into this? On 28 jan, 17:48, Jonathan Leffler <jonathan.leff... (AT) gmail (DOT) com> wrote: On Sat, Jan 28, 2012 at 07:50, BeGooden-IT Vercelletto begooden... (AT) gmail (DOT) com> wrote: I have been submitted a challenge from a customer, which is the following: * we have a master table "item" with item_num as primary key * we have a detail table "operation, with operation_num as primary key, and item_num as foreign key, referencing item (item_num) session A initiates a session with begin work; update item set ( some item colums EXCEPT THE PRIMARY KEY ) = ( some values ) where item_num = 100 ; -- leave sesssion "as is" and open another session on other terminal So the change in session A is uncommitted. session B opens a new session and attempts: insert into operation VALUES ( operation_num_value,100,more values) ==> Session B receives error 691: Missing key in referenced table for referential constraint (PKconstraint). 107: ISAM error: *record is locked. This means that there wasn't a committed value 100 that could be referenced, so the statement should fail. This is the most basic requirement for COMMITTED READ or higher isolation. I'm not sure it should work under DIRTY READ isolation even - although the value might exist at the moment, if the DR session (session B) was allowed to commit, session A might rollback, leaving the row inserted by B not referencing anything - a state of semantic disintegrity that referential integrity is supposed to avoid. In my mind ( I can be wrong though), I do not expect this error This error should be expected - as much because of isolation issues as because of referential integrity issues. because in the UPDATE statement, I have not modified the primary key value. In opposition, I would have expected the constraint violation if I had modified the primary key value in the update statement. It seems that the foreign key constraint does not refer to the primary key index, but only on the fact that the row is locked. In my same mind, I think this scenario would have worked in 7.XX versions, for the reason I stated just above, provided the condtion that I do not modify the primary key value. I have a simple and easy to execute test case with data available on request by email. I may have forgotten some referential constraint basics, my age *would allow it :-) Any simple suggestion to achieve such a scenario? Add a COMMIT to Session A. *That is the best, most reliable way to deal with it. *Pretty much anything else is at best dubious. -- Jonathan Leffler <jonathan.leff... (AT) gmail (DOT) com> *#include <disclaimer.h Guardian of DBD::Informix - v2011.0612 -http://dbi.perl.org "Blessed are we who can laugh at ourselves, for we shall never cease to be amused." |
#6
| |||
| |||
|
| On Sat, Jan 28, 2012 at 07:50, BeGooden-IT Vercelletto begooden.it (AT) gmail (DOT) com> wrote: I have been submitted a challenge from a customer, which is the following: * we have a master table "item" with item_num as primary key * we have a detail table "operation, with operation_num as primary key, and item_num as foreign key, referencing item (item_num) session A initiates a session with begin work; update item set ( some item colums EXCEPT THE PRIMARY KEY ) = ( some values ) where item_num = 100 ; -- leave sesssion "as is" and open another session on other terminal So the change in session A is uncommitted. session B opens a new session and attempts: insert into operation VALUES ( operation_num_value,100,more values) ==> Session B receives error 691: Missing key in referenced table for referential constraint (PKconstraint). 107: ISAM error: record is locked. This means that there wasn't a committed value 100 that could be referenced, so the statement should fail. This is the most basic requirement for COMMITTED READ or higher isolation. I'm not sure it should work under DIRTY READ isolation even - although the value might exist at the moment, if the DR session (session B) was allowed to commit, session A might rollback, leaving the row inserted by B not referencing anything - a state of semantic disintegrity that referential integrity is supposed to avoid. In my mind ( I can be wrong though), I do not expect this error This error should be expected - as much because of isolation issues as because of referential integrity issues. because in the UPDATE statement, I have not modified the primary key value. In opposition, I would have expected the constraint violation if I had modified the primary key value in the update statement. It seems that the foreign key constraint does not refer to the primary key index, but only on the fact that the row is locked. In my same mind, I think this scenario would have worked in 7.XX versions, for the reason I stated just above, provided the condtion that I do not modify the primary key value. I have a simple and easy to execute test case with data available on request by email. I may have forgotten some referential constraint basics, my age would allow it :-) Any simple suggestion to achieve such a scenario? Add a COMMIT to Session A. That is the best, most reliable way to deal with it. Pretty much anything else is at best dubious. -- Jonathan Leffler <jonathan.leffler (AT) gmail (DOT) com> #include <disclaimer.h Guardian of DBD::Informix - v2011.0612 - http://dbi.perl.org "Blessed are we who can laugh at ourselves, for we shall never cease to be amused." _______________________________________________ Informix-list mailing list Informix-list (AT) iiug (DOT) org http://www.iiug.org/mailman/listinfo/informix-list |
#7
| |||
| |||
|
|
I believe the OP's point was that even in case of a rollback on session A, the record with item_num = 100 would still be there. I'd have to test this and monitor it, but I believe the problem is that session B will try to lock the record from item. And because there is a lock on the row, it fails. But I'd have to check the existing locks in item to confirm this. In practice, session B should have a reasonable LOCK WAIT time that would allow session A to commit. Regards. On Sat, Jan 28, 2012 at 4:48 PM, Jonathan Leffler jonathan.leffler (AT) gmail (DOT) com> wrote: On Sat, Jan 28, 2012 at 07:50, BeGooden-IT Vercelletto begooden.it (AT) gmail (DOT) com> wrote: I have been submitted a challenge from a customer, which is the following: * we have a master table "item" with item_num as primary key * we have a detail table "operation, with operation_num as primary key, and item_num as foreign key, referencing item (item_num) session A initiates a session with begin work; update item set ( some item colums EXCEPT THE PRIMARY KEY ) = ( some values ) where item_num = 100 ; -- leave sesssion "as is" and open another session on other terminal So the change in session A is uncommitted. session B opens a new session and attempts: insert into operation VALUES ( operation_num_value,100,more values) ==> Session B receives error 691: Missing key in referenced table for referential constraint (PKconstraint). 107: ISAM error: record is locked. This means that there wasn't a committed value 100 that could be referenced, so the statement should fail. This is the most basic requirement for COMMITTED READ or higher isolation. I'm not sure it should work under DIRTY READ isolation even - although the value might exist at the moment, if the DR session (session B) was allowed to commit, session A might rollback, leaving the row inserted by B not referencing anything - a state of semantic disintegrity that referential integrity is supposed to avoid. In my mind ( I can be wrong though), I do not expect this error This error should be expected - as much because of isolation issues as because of referential integrity issues. because in the UPDATE statement, I have not modified the primary key value. In opposition, I would have expected the constraint violation if I had modified the primary key value in the update statement. It seems that the foreign key constraint does not refer to the primary key index, but only on the fact that the row is locked. In my same mind, I think this scenario would have worked in 7.XX versions, for the reason I stated just above, provided the condtion that I do not modify the primary key value. I have a simple and easy to execute test case with data available on request by email. I may have forgotten some referential constraint basics, my age would allow it :-) Any simple suggestion to achieve such a scenario? Add a COMMIT to Session A. That is the best, most reliable way to deal with it. Pretty much anything else is at best dubious. -- Jonathan Leffler <jonathan.leffler (AT) gmail (DOT) com> #include <disclaimer.h Guardian of DBD::Informix - v2011.0612 - http://dbi.perl.org "Blessed are we who can laugh at ourselves, for we shall never cease to be amused." _______________________________________________ Informix-list mailing list Informix-list (AT) iiug (DOT) org http://www.iiug.org/mailman/listinfo/informix-list -- Fernando Nunes Portugal http://informix-technology.blogspot.com My email works... but I don't check it frequently... _______________________________________________ Informix-list mailing list Informix-list (AT) iiug (DOT) org http://www.iiug.org/mailman/listinfo/informix-list |
#8
| |||
| |||
|
#9
| |||
| |||
|
|
Thanks folks, I was coming to the same conclusion: SET LOCK MODE TO WAIT aReasonableNumberOfSeconds, and have my customer think how relevant it is to keep the master row locked for an unlimited time. Fernando, I checked that effectively the master table was granted a ROW LOCK on the PK row, thus preventing from any INSERT in the detail table for the PK value. Appartently, the PK constraint implementation cannot discriminate whether the PK is subject to be modified by the UPDATE statement ( appearing in the SET ( columns list) = ( values )), or not to be modified. I was expecting a higher constraint check granularity the mere ROW level. Why am I prevented from updating the master row if I don't modify the primary ? Nevertheless, you can UPDATE on detail as long as you respect the constraint terms... Maybe a feature request for the insert case ? :-) Eric _______________________________________________ Informix-list mailing list Informix-list (AT) iiug (DOT) org http://www.iiug.org/mailman/listinfo/informix-list |
![]() |
| Thread Tools | |
| Display Modes | |
| |