-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 
Author Message
 Post subject: Insert and Update in same flush
PostPosted: Mon Feb 23, 2004 7:15 pm 
Regular
Regular

Joined: Tue Sep 09, 2003 9:37 pm
Posts: 56
Location: Ogden, Utah, USA
Apparently, if I 'save' a new object, change the data, and then flush it generates an insert with the initial values from the 'save' and then an update with the current data.

Is there a good reason for this behavior?

We made the change below to sessionimpl, which effectively replaces an insert with the new data rather than doing both an insert and an update when flushing a new object. It is a requirement for us because the insert and update are using different lock modes, which causes frequent deadlocks.

Is the change below a viable patch, or would it cause problems in areas we're unaware of?

Thanks for your help!
Jenica


--- SessionImpl.java 4 Feb 2004 23:59:27 -0000 1.4
+++ SessionImpl.java 20 Feb 2004 19:53:00 -0000 1.5
@@ -1,4 +1,4 @@
-//$Id: SessionImpl.java,v 1.4 2004/02/04 23:59:27 ron Exp $
+//$Id: SessionImpl.java,v 1.5 2004/02/20 19:53:00 ron Exp $
package net.sf.hibernate.impl;

import java.io.IOException;
@@ -2534,13 +2534,30 @@

checkNullability(values, persister, true);

- // schedule the update
- updates.add(
- //new Key(entry.id, persister),
- new ScheduledUpdate(entry.id, values, dirtyProperties, entry.loadedState, entry.version, nextVersion, object, updatedState, persister, this)
- //note that we intentionally did _not_ pass in currentPersistentState!
- );
-
+ // insert already scheduled?
+ // then just switch it!
+ boolean alreadyInserted = false;
+ int index = 0;
+ if ( insertions.size() > 0) {
+ for (Iterator i = insertions.iterator(); i.hasNext(); index++) {
+ ScheduledInsertion si = (ScheduledInsertion) i.next();
+ if (si.getInstance().equals(object)) {
+ alreadyInserted = true;
+ break;
+ }
+ }
+ }
+ if (alreadyInserted) {
+ insertions.remove(index);
+ insertions.add(index, new ScheduledInsertion( entry.id, values, object, persister, this ) );
+ } else {
+ // schedule the update
+ updates.add(
+ //new Key(entry.id, persister),
+ new ScheduledUpdate(entry.id, values, dirtyProperties, entry.loadedState, entry.version, nextVersion, object, updatedState, persister, this)
+ //note that we intentionally did _not_ pass in currentPersistentState!
+ );
+ }
}

if (status==DELETED) {


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 2:42 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Expected Hibernate behavior (we have debated whether this is really correct or not!) is that the INSERT statement will insert exactly the data that was set when save() was called. This gives the user a bit finer grained control, especially in a context where there are triggers etc. However, if you are not careful, it could perform badly.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 10:02 am 
Regular
Regular

Joined: Tue Sep 09, 2003 9:37 pm
Posts: 56
Location: Ogden, Utah, USA
Just in case you ever have the debate again --

The trouble it's causing us is that the insert requires a less restrictive lock than the update, so if we have two threads doing the same thing the first gets a row-level write lock, the second gets a row-level write lock, and then they deadlock on the update because the update is asking for a table lock.

Jenica


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 12:07 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
eh? how can they deadlock? This is all in the same session, right? Deadlocks only occur between concurrent txns.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 12:14 pm 
Regular
Regular

Joined: Tue Sep 09, 2003 9:37 pm
Posts: 56
Location: Ogden, Utah, USA
Two transactions, both doing the same sort of thing:

TX1: insert into incident ... (row lock)
TX2: insert into incident ... (row lock)
TX1: (misc other inserts)
TX2: (misc other inserts)
TX1: update incident (requires table lock, tx2 has row lock so can't acquire it)
TX2: update incident (requires table lock, tx1 has row lock so can't acquire it)

Does that make sense? If it just does the insert, it needs the same level of lock for the whole transaction. Doing both makes it upgrade the lock halfway through, causing deadlock potential.

Jenica


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 12:15 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
It acquires a table-level lock for an update??!!

Thats bizarre! What txn isolation level are we talking about here?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 12:42 pm 
Regular
Regular

Joined: Tue Sep 09, 2003 9:37 pm
Posts: 56
Location: Ogden, Utah, USA
I've tried TRANSACTION_READ_COMMITTED and TRANSACTION_READ_UNCOMMITTED both - it doesn't seem to make any difference on the write locks.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 12:44 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
What database is that? This sounds really freaky to me.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 12:47 pm 
Regular
Regular

Joined: Tue Sep 09, 2003 9:37 pm
Posts: 56
Location: Ogden, Utah, USA
DB2 UDB 7.2. I thought it was really odd too - but it deadlocks every time on that update and the snapshot of the locks show a requested "IX" table level lock for the table we're updating.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 4:01 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
I suggest you ask in some DB2 forum about this behavior, it doesn't seem right to me.

To avoid the INSERT-then-UPDATE, simply fully initialize the object before saving it.


Top
 Profile  
 
 Post subject: Re: Insert and Update in same flush
PostPosted: Fri Sep 17, 2010 12:42 am 
Newbie

Joined: Fri Jul 09, 2010 1:24 pm
Posts: 11
For those looking around, a co-worker and I have created patch for Hibernate 3.5.6-Final to accomplish this. You can find the whole Hibernate core project that we patched on GitHub:

http://github.com/sfraser/Hibernate-Cor ... nhancement

With more and more uses of an extended persistence context (session-per-converstaion), this behavior seems to be a feature that should be a configurable element of Hibernate. Is there a reason why it hasn't been?

Quote:
To avoid the INSERT-then-UPDATE, simply fully initialize the object before saving it.


With an extended persistence context, this may not always be possible or fit the use cases of the application.

We've found this problem to occur mostly with Oracle when using sequence based id generation. In HSQL, the INSERT happens immediately after a call to merge and is not scheduled to execute when the flush occurs.


Top
 Profile  
 
 Post subject: Re: Insert and Update in same flush
PostPosted: Fri Sep 17, 2010 11:36 am 
Regular
Regular

Joined: Tue Sep 09, 2003 9:37 pm
Posts: 56
Location: Ogden, Utah, USA
Thanks for the patch! We are considering upgrading to Hibernate 3 so this will be very useful for us.

Jenica


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.