Thread: transaction locking

transaction locking

From
tom baker
Date:
hello all

i am (probably) shooting myself in the foot, but here goes the question.

inside of a begin transaction/commit block, i am attempting to insert a record
into a parts table, and then insert a record that references the part into an
application table. and the transaction fails with this error message:

ERROR: app_part_ins_trig referential integrity violation - key referenced from
application not found in parts

i understand that since the record was inserted into the parts table *after*
the BEGIN TRANSACTION statement, the insert into the application table cannot
see that a record exists until a commit.

any suggestions are greatly appreciated.

the tables are as shown:
CREATE TABLE parts (make character varying(16) DEFAULT 'AMC' NOT NULL,amc_part_no character varying(8) NOT
NULL,group_nocharacter varying(2) NOT NULL,subgroup_no character varying(8),part_name character varying(32) DEFAULT ''
NOTNULL,description character varying(255),prim_grp character(2),prim_sbg character(8),no_req integer,weight
numeric(6,2),countinteger DEFAULT 0,ordered integer DEFAULT 0,cost numeric(6,2),price numeric(6,2),graph character
varying(128),Constraintparts_pkey Primary Key (make, amc_part_no) 
);

CREATE TABLE application (make character varying(16) DEFAULT 'AMC' NOT NULL,amc_part_no character varying(8) NOT
NULL,yearinteger NOT NULL,model character varying(2) NOT NULL,Constraint application_pkey Primary Key (make,
amc_part_no,year, model) 
);

and the constraint that is causing problems is:
CREATE CONSTRAINT TRIGGER app_part_ins_trig AFTER INSERT OR UPDATE ON
application  FROM parts NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW
EXECUTE PROCEDURE "RI_FKey_check_ins" ('app_part_ins_trig', 'application',
'parts', 'UNSPECIFIED', 'make', 'make', 'amc_part_no', 'amc_part_no');

inside the program in question, i do a
$res=pg_query( "BEGIN TRANSACTION" ) ;
if (strlen ($r=pg_last_error( $db ) ) )
{$replaces.= $r."<br>\n" ;pg_connection_reset( $db ) ;$failed = -1 ;
}

$sql = "LOCK TABLE parts IN SHARE ROW EXCLUSIVE MODE" ;
$res = pg_query( $sql ) ;
if (strlen ($r=pg_last_error( $db ) ) )
{$replaces.="SQL: $sql<br>\n" ;$replaces.= $r."<br>\n" ;pg_connection_reset( $db ) ;$failed = -1 ;
}

$sql = "SET CONSTRAINTS ALL DEFERRED" ;
$res = pg_query( $sql ) ;
if (strlen ($r=pg_last_error( $db ) ) )
{$replaces.="SQL: $sql<br>\n" ;$replaces.= $r."<br>\n" ;pg_connection_reset( $db ) ;$failed = -1 ;
}

if ( $failed == 0 )
{
...


--
tia,
tom baker
former ingres programmer...
I'm using my X-RAY VISION to obtain a rare glimpse of the INNER
WORKINGS of this POTATO!!



Re: transaction locking

From
Stephan Szabo
Date:
On Wed, 17 Sep 2003, tom baker wrote:

> i am (probably) shooting myself in the foot, but here goes the question.
>
> inside of a begin transaction/commit block, i am attempting to insert a record
> into a parts table, and then insert a record that references the part into an
> application table. and the transaction fails with this error message:
>
> ERROR: app_part_ins_trig referential integrity violation - key referenced from
> application not found in parts
>
> i understand that since the record was inserted into the parts table *after*
> the BEGIN TRANSACTION statement, the insert into the application table cannot
> see that a record exists until a commit.

Assuming that they are both in the same transaction, the second insert
should be able to see the results of the first insert, can you send an
example sequence of inserts as well? (Also see the note below)

> and the constraint that is causing problems is:
> CREATE CONSTRAINT TRIGGER app_part_ins_trig AFTER INSERT OR UPDATE ON
> application  FROM parts NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW
> EXECUTE PROCEDURE "RI_FKey_check_ins" ('app_part_ins_trig', 'application',
> 'parts', 'UNSPECIFIED', 'make', 'make', 'amc_part_no', 'amc_part_no');
>
> $sql = "SET CONSTRAINTS ALL DEFERRED" ;

I'm not sure if you know, but this is not going to deferr the constraint
above because it was created with NOT DEFERRABLE.


Re: transaction locking

From
tom baker
Date:
On Wednesday 17 September 2003 22:33, Stephan Szabo pronounced:
> On Wed, 17 Sep 2003, tom baker wrote:
> > i am (probably) shooting myself in the foot, but here goes the question.
> >
> > inside of a begin transaction/commit block, i am attempting to insert a
> > record into a parts table, and then insert a record that references the
> > part into an application table. and the transaction fails with this error
> > message:
> >
> > ERROR: app_part_ins_trig referential integrity violation - key referenced
> > from application not found in parts
> >
> > i understand that since the record was inserted into the parts table
> > *after* the BEGIN TRANSACTION statement, the insert into the application
> > table cannot see that a record exists until a commit.
>
> Assuming that they are both in the same transaction, the second insert
> should be able to see the results of the first insert, can you send an
> example sequence of inserts as well? (Also see the note below)
>
> > and the constraint that is causing problems is:
> > CREATE CONSTRAINT TRIGGER app_part_ins_trig AFTER INSERT OR UPDATE ON
> > application  FROM parts NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW
> > EXECUTE PROCEDURE "RI_FKey_check_ins" ('app_part_ins_trig',
> > 'application', 'parts', 'UNSPECIFIED', 'make', 'make', 'amc_part_no',
> > 'amc_part_no');
> >
> > $sql = "SET CONSTRAINTS ALL DEFERRED" ;
>
> I'm not sure if you know, but this is not going to deferr the constraint
> above because it was created with NOT DEFERRABLE.
>
> ---------------------------(end of broadcast)---------------------------
> TIP 9: the planner will ignore your desire to choose an index scan if your
>       joining column's datatypes do not match

ah, yes, i DID not see the NOT. that is fixed. here is the code that is having
problems (paired down; all error checking has been removed!)

$res=pg_query( "BEGIN TRANSACTION" ) ;

$sql = "LOCK TABLE parts IN SHARE ROW EXCLUSIVE MODE" ;
$res = pg_query( $sql ) ;

$sql = "SET CONSTRAINTS ALL DEFERRED" ;
$res = pg_query( $sql ) ;

if ( $amc_part_no == "" )
{$sql = "SELECT max(amc_part_no) FROM parts WHERE amc_part_no like 'G%'" ;$res = pg_query( $sql ) ;$amc_part_no =
pg_fetch_result($res , 0 , 0 ) ;# and generate the next part number... 
}

$res = pg_query( $sql ) ;

$sql = "INSERT INTO parts VALUES ( '".$make."', '".$amc_part_no."',
'".$group_no."', '".$subgroup_no."', '".$part_name."', '".$description."',
'".$prim_grp."', '".$prim_sbg."', '".$no_req."', '".$weight."',
'".$graphic."' )" ;
$res = pg_query( $sql ) ;

if ( ( $alt_group > "" ) )
{$sql = "INSERT INTO part_group ( make, amc_part_no, group_no ) VALUES (
'$make' , '$amc_part_no' , '$alt_group' ) " ;$res = pg_query( $sql ) ;
}
$sql = "INSERT INTO application VALUES ( '$make','$amc_part_no','$tyears',
'$Amodel' )" ;$res = pg_query( $sql ) ;

if ( $cmplt == 0 || $failed )
{pg_query( "ROLLBACK TRANSACTION" ) ;
}
else
{pg_query( "COMMIT TRANSACTION" ) ;
}

--
regards,
tom baker
former ingres programmer...
You'll never be the man your mother was!



Re: transaction locking

From
Stephan Szabo
Date:
On Thu, 18 Sep 2003, tom baker wrote:

> ah, yes, i DID not see the NOT. that is fixed. here is the code that is having
> problems (paired down; all error checking has been removed!)
>
> $res=pg_query( "BEGIN TRANSACTION" ) ;
>
> $sql = "LOCK TABLE parts IN SHARE ROW EXCLUSIVE MODE" ;
> $res = pg_query( $sql ) ;
>
> $sql = "SET CONSTRAINTS ALL DEFERRED" ;
> $res = pg_query( $sql ) ;
>
> if ( $amc_part_no == "" )
> {
>     $sql = "SELECT max(amc_part_no) FROM parts WHERE amc_part_no like 'G%'" ;
>     $res = pg_query( $sql ) ;
>     $amc_part_no = pg_fetch_result( $res , 0 , 0 ) ;
>     # and generate the next part number...
> }
>
> $res = pg_query( $sql ) ;
>
> $sql = "INSERT INTO parts VALUES ( '".$make."', '".$amc_part_no."',
> '".$group_no."', '".$subgroup_no."', '".$part_name."', '".$description."',
> '".$prim_grp."', '".$prim_sbg."', '".$no_req."', '".$weight."',
> '".$graphic."' )" ;
> $res = pg_query( $sql ) ;
>
> if ( ( $alt_group > "" ) )
> {
>     $sql = "INSERT INTO part_group ( make, amc_part_no, group_no ) VALUES (
> '$make' , '$amc_part_no' , '$alt_group' ) " ;
>     $res = pg_query( $sql ) ;
> }
>
>     $sql = "INSERT INTO application VALUES ( '$make','$amc_part_no','$tyears',
> '$Amodel' )" ;
>     $res = pg_query( $sql ) ;

Can you print out the queries you think you're sending and turn on query
logging and see what the database things?  Inserting only the first three
columns into parts and then a matching application row doesn't seem to
fail for me in 7.3.4 or 7.4 beta 1.


Re: transaction locking

From
tom baker
Date:
On Thursday 18 September 2003 11:24, Stephan Szabo pronounced:
> On Thu, 18 Sep 2003, tom baker wrote:
> > ah, yes, i DID not see the NOT. that is fixed. here is the code that is
> > having problems (paired down; all error checking has been removed!)
> >
> > $res=pg_query( "BEGIN TRANSACTION" ) ;
> >
> > $sql = "LOCK TABLE parts IN SHARE ROW EXCLUSIVE MODE" ;
> > $res = pg_query( $sql ) ;
> >
> > $sql = "SET CONSTRAINTS ALL DEFERRED" ;
> > $res = pg_query( $sql ) ;
> >
> > if ( $amc_part_no == "" )
> > {
> >     $sql = "SELECT max(amc_part_no) FROM parts WHERE amc_part_no like 'G%'"
> > ; $res = pg_query( $sql ) ;
> >     $amc_part_no = pg_fetch_result( $res , 0 , 0 ) ;
> >     # and generate the next part number...
> > }
> >
> > $res = pg_query( $sql ) ;  <<============
> >
> > $sql = "INSERT INTO parts VALUES ( '".$make."', '".$amc_part_no."',
> > '".$group_no."', '".$subgroup_no."', '".$part_name."',
> > '".$description."', '".$prim_grp."', '".$prim_sbg."', '".$no_req."',
> > '".$weight."',
> > '".$graphic."' )" ;
> > $res = pg_query( $sql ) ;
> >
> > if ( ( $alt_group > "" ) )
> > {
> >     $sql = "INSERT INTO part_group ( make, amc_part_no, group_no ) VALUES (
> > '$make' , '$amc_part_no' , '$alt_group' ) " ;
> >     $res = pg_query( $sql ) ;
> > }
> >
> >     $sql = "INSERT INTO application VALUES (
> > '$make','$amc_part_no','$tyears', '$Amodel' )" ;
> >     $res = pg_query( $sql ) ;
>
> Can you print out the queries you think you're sending and turn on query
> logging and see what the database things?  Inserting only the first three
> columns into parts and then a matching application row doesn't seem to
> fail for me in 7.3.4 or 7.4 beta 1.

stephan:

i want to give you a great big thank you. THANK YOU!!!!!
i was shooting myself in the foot vigorously. one sql statements were being
executed twice, without the appropriate error checking (do i feel foolish or
what???? :(( ). see  where i put "<<=====" above!


--
regards,
tom baker
former ingres programmer...
Magary's Principle:When there is a public outcry to cut deadwood and fat from anygovernment bureaucracy, it is the
deadwoodand the fat that dothe cutting, and the public's services are cut.