db-jdo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Craig L Russell <Craig.Russ...@Sun.COM>
Subject Re: enlistment of native connections for optimistic txs
Date Fri, 13 Apr 2007 18:36:10 GMT
Hi Guido,

A new proposal is attached below.

On Apr 10, 2007, at 2:03 AM, Guido Anzuoni wrote:

> Craig L Russell wrote:
>> Hi Erik,
>>
>> Thanks for clarifying your proposal.
>>
>> I agree that this improves portability, but with a penalty. You  
>> can no
>> longer use optimistic concurrency once you decide to do some native
>> SQL, even if you don't ever perform any INSERT, DELETE, or UPDATE
>> statements. And this will have negative performance consequences for
>> some applications.
>>
>> While backward compatibility is important, I would agree with you  
>> that
>> correctness is even more important. So it doesn't bother me too much
>> if we change the semantic so that by default, getting a datastore
>> connection is equivalent to doing a flush in an optimistic
>> transaction. But I'd still like to give the user the ability to get
>> the same level of performance they now enjoy by deferring the
>> enlistment in the datastore transaction to flush or commit.
>>
>> So how about adding a flag that defaults to true if not specified to
>> enlist the datastore connection in the datastore transaction?
>>
>> <proposed>
>> Connection getDataStoreConnection()
>>
>> This method is equivalent to getDataStoreConnection(true).

Seems like the default should be different based on whether you are  
in a JDO transaction.

So maybe the default should be getDataStoreConnection 
(pm.currentTransaction().isActive())
>>
>> Connection getDataStoreConnection(boolean enlist)
>>
>> If this method is called outside an active transaction, the object
>> returned will not be enlisted in any
>> transaction, regardless of the setting of the enlist parameter.
> In this case, the user does not know that his request has not been  
> honored.

Maybe it makes sense to throw a JDOUserException, since there is no  
transaction in which to enlist the connection, and the default is  
false. A user can only get the exception by asking for something that  
is impossible.
>
>>
>> If it is called while a datastore transaction is active, the object
>> returned will be enlisted in the current transaction,  regardless of
>> the setting of the enlist parameter.
>>
> Again, the implementation might do something different from what  
> requested.

Right, either a non-enlisted connection (enlist==false) or the  
connection enlisted in the current transaction.

The use case for this is to grab a non-enlisted connection that is  
used e.g. to get a sequence number that will never be rolled back.
>
>> If it is called while an optimistic transaction is active, and the
>> enlist parameter is true, a datastore transaction is begun if not
>> already begun, and the object returned will be enlisted in the  
>> current
>> datastore transaction.
>>
>> If it is called while an optimistic transaction is active, the enlist
>> parameter is false, and a datastore transaction is already begun, the
>> object returned will be enlisted in the datastore transaction.
> Same as above

Right, either a separate non-enlisted connection (enlist==false) or  
the connection enlisted in the current transaction (enlist==true).

>
>> If it is called while an optimistic transaction is active, the enlist
>> parameter is false, and a datastore transaction is not already begun,
>> the object returned will not be enlisted in any datastore  
>> transaction.
>> </proposed>
> What if the user issues some INSERT, DELETE, UPDATE ?

This is the user's choice, which is not a default behavior, but  
something explicitly asked for. The default will always be to get an  
enlisted connection, and the only way to get a non-enlisted  
connection is to ask for it.

> Is it possible to call conn.commit() ?

Yes, the non-enlisted connection changes were already committed (auto- 
commit). We should add this to the spec, that the non-enlisted  
connection is auto-commit.
>
> I agree that there is a potential penalty in optimistic  
> transactions if
> we blindly enlist native connections but, if we let the user know
> exactly what is going on,
> an aware decision can be taken.
> getDataStoreConnection() will always return the enlisted connection if
> any, otherwise null is returned (maybe getNativeConnection() could
> return null).

I think that returning null is never the right behavior.

> Now, if the user wants to access a consistent backend, he HAVE to
> flush(), triggering connection enlistment (what if there are no  
> pending
> updates ?).
> If the user wants to operate on an independent connection to the same
> datastore used by the PM he could use what is configured in the PMF
> (OK, some helper methods might...help).

I think that inventing a parallel mechanism is overkill if we can  
give users what the need from this one.

> It could be also achieved with a different handling of the proposed
> enlist flag for the 'false' scenarios, but it would be strange to
> request to the
> PM a datastore connection the PM is not using at all !!!. It would  
> look
> like a data source.

Yes, that's the intent. There is no need for the user to somehow go  
behind the scenes to figure out how the PMF is configured and get a  
connection from that same data source.

Craig

<proposed>
Connection getDataStoreConnection()

This method is equivalent to getDataStoreConnection 
(pm.currentTransaction().isActive()). That is, it defaults to  
getDataStoreConnection(true) is a JDO transaction is active, and  
getDataStoreConnection(false) if not.

JDOConnection getDataStoreConnection(boolean enlist)

This method returns either a JDOConnection whose underlying native  
connection is enlisted in the native datastore transaction in use by  
the persistence manager; or a JDOConnection whose underlying native  
connection is not enlisted in any native transaction. An unenlisted  
connection is set to auto-commit if using a data source that has this  
concept (e.g. JDBC).

If this method is called outside an active transaction, with the  
enlist parameter false, the object returned will not be enlisted in  
any transaction. If this method is called outside an active  
transaction, with the enlist parameter true, JDOUserException is thrown.

If this method is called while a datastore transaction is active,  
with the enlist parameter false, the object returned will not be  
enlisted in any transaction. If this method is called while a  
datastore transaction is active, with the enlist parameter true, the  
object returned will be enlisted in the current native datastore  
transaction.

If this method is called while an optimistic transaction is active,  
with the enlist parameter false, the object returned will not be  
enlisted in any transaction. If this method is called while an  
optimistic transaction is active, and the enlist parameter is true, a  
native datastore transaction is begun if not already begun, and the  
object returned will be enlisted in the current native datastore  
transaction.

</proposed>

Craig

>
> Guido.
>>
>> Craig
>>
>> On Apr 8, 2007, at 1:49 PM, Erik Bengtson wrote:
>>
>>>
>>> Hi,
>>>
>>> This is a change proposal to the spec with regards to enlistment of
>>> native
>>> connections when optimistic transactions are used.
>>>
>>> The enlistment of native connections into a JDO transaction is
>>> conditioned to
>>> the fact that a flush call has been performed before the  
>>> connection is
>>> obtained.
>>>
>>> The flush call is a JDO implementation decision which can differ  
>>> between
>>> different implementations. See the example:
>>>
>>> 1. tx.begin();
>>> 2. //more operations here....
>>> 3. JDOConnection conn = pm.getDataStoreConnection();
>>> 4. Connection sqlconn = (Connection) conn.getNativeConnection();
>>> 5. sqlconn.execute("DELETE FROM ANIMAL WHERE NAME = 'CAT'")
>>> 5. conn.close();
>>> 6. tx.rollback();
>>>
>>> There are two possible behaviors:
>>>
>>> - The JDO implementation decides to perform a flush between 1 and  
>>> 3: the
>>> connection is enlisted, and DELETE all CATS from ANIMAL is rolled  
>>> back
>>> - The JDO implementation decides to NOT perform a flush between 1  
>>> and
>>> 3: the
>>> connection is not enlisted, and DELETE all CATS from ANIMAL is not
>>> rolled back
>>>
>>> As you can see, this is not portable and not ACID, so I would  
>>> like to
>>> propose
>>> that enlistment of connections is done whenever a transaction is  
>>> opened.
>>>
>>> The change is to the following paragraph:
>>>
>>> The JDO spec ยง12.16 - getDataStoreConnection:
>>>
>>> "If this method is called while a datastore transaction is active,
>>> the object
>>> returned will be enlisted in the current transaction. If called  
>>> in an
>>> optimistic transaction before flush has been called, or outside an
>>> active
>>> transaction, the object returned will not be enlisted in any
>>> transaction."
>>>
>>> AS:
>>>
>>> "If this method is called while a datastore or optimistc transaction
>>> is active,
>>> the object returned will be enlisted in the current transaction. If
>>> called
>>> outside an active transaction, the object returned will not be
>>> enlisted in any
>>> transaction."
>>>
>>>
>>
>> Craig Russell
>> Architect, Sun Java Enterprise System http://java.sun.com/products/ 
>> jdo
>> 408 276-5638 mailto:Craig.Russell@sun.com
>> P.S. A good JDO? O, Gasp!
>>
>

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:Craig.Russell@sun.com
P.S. A good JDO? O, Gasp!


Mime
View raw message