ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Young, Alistair" <alistair.yo...@logica.com>
Subject RE: iBATIS caching / transaction isolation question
Date Tue, 20 Jan 2009 13:51:26 GMT
Thanks, Clinton.  I think I have it all straight in my head now!
 
Sounds like we need to proceed with caution.
 
Cheers,
 
 
Alistair.

________________________________

From: Clinton Begin [mailto:clinton.begin@gmail.com] 
Sent: 20 January 2009 05:25
To: user-java@ibatis.apache.org
Subject: Re: iBATIS caching / transaction isolation question


That's a fair assumption.  FWIW:  iBATIS 3 will have a transactional cache.  It might not
catch every case, but it will catch most, and can be unit tested to ensure that it behaves
as intended.  

Clinton


On Mon, Jan 19, 2009 at 2:22 AM, Young, Alistair <alistair.young@logica.com> wrote:


	Me again... :)
	
	I was having a think about this over the weekend and realized that the behaviour I'm after
would be very difficult to implement (and possibly very inefficient), so perhaps iBATIS does
NOT behave in this way.
	
	It struck me that, if iBATIS were maintaining multiple caches AND paying attention to transaction
boundaries the cache flushing logic would become very complex.  For example, if thread A executed
an 'update', iBATIS would have to flush the corresponding cache for that thread only.  If
the transaction were later rolled back, iBATIS would have to flush that cache again.  However,
if the transaction were committed, it would have to flush all OTHER caches...
	
	So, I've come to the conclusion that the only way to use caching safely is to ensure that
no cached SELECT statements are executed within transactions that may ultimately be rolled
back.
	
	I'd appreciate some input from anybody making use of iBATIS caching - is this a rule you've
had to adhere to?
	
	
	Cheers,
	
	
	Alistair.
	
	-----Original Message-----
	From: Young, Alistair
	
	Sent: 15 January 2009 10:31
	To: 'user-java@ibatis.apache.org'
	
	Subject: RE: iBATIS caching / transaction isolation question
	
	Sorry to rake this up again...  I hope you don't mind if I ask a couple of questions about
the expected behaviour of iBATIS in this area.
	
	1. Should different threads, sharing an SqlMapClient object, be seeing the SAME cache or
DIFFERENT caches?  I would expect the latter (though the behaviour I'm seeing suggests the
former).
	
	2. If a transaction is rolled back, should the cache be flushed?  I would expect yes but,
again, my tests suggest no.
	
	Fundamentally, I'd just like to know whether I'm mis-using iBATIS, or whether I'm going to
need to manage the caching myself (custom CacheController?) if I want things to behave as
above.
	
	Cheers,
	
	
	Alistair.
	
	-----Original Message-----
	
	From: Young, Alistair [mailto:alistair.young@logica.com]
	Sent: 12 January 2009 16:36
	To: user-java@ibatis.apache.org
	
	Subject: RE: iBATIS caching / transaction isolation question
	
	Many thanks for the reply, Clinton - but sadly this doesn't seem to fix the problem.  My
understanding was that readonly need only be set to "false" if a thread is likely to change
the contents of the returned object - this is not the case in my example application (indeed,
the returned object is a String).
	
	I've appended my code and iBATIS configuration files below - I'd appreciate it if you could
tell me if I'm doing anything obviously wrong.  My understanding was that a SqlMapClient object
could safely be used from multiple threads (and that it would handle the caching appropriately).
	
	Thanks,
	
	
	Alistair.
	
	IBatisTest.java:
	------------------------------------------------------------
	package test;
	
	public class IBatisTest implements Runnable {
	
	   private SqlMapClient sql;
	
	   public IBatisTest() throws Exception {
	       // create the SQL map
	       Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
	       this.sql = SqlMapClientBuilder.buildSqlMapClient(reader);
	   }
	
	   public void runTest() throws Exception {
	
	       this.sql.startTransaction();
	
	       String value = (String)this.sql.queryForObject("db.getValue");
	       System.out.println("Value is " + value); // "1"
	
	       this.sql.update("db.updateValue", "2");
	
	       value = (String)this.sql.queryForObject("db.getValue");
	       System.out.println("Value is " + value);  // "2"
	
	       // start the other thread
	       new Thread(this).start();
	
	       // wait for a bit
	       Thread.sleep(2000);
	
	       // roll back the transaction
	       this.sql.endTransaction();
	
	       value = (String)this.sql.queryForObject("db.getValue");
	       System.out.println("Value is " + value); // "2" (expecting "1")
	   }
	
	   // second thread
	   public void run() {
	       try {
	           String value = (String)this.sql.queryForObject("db.getValue");
	           System.out.println("    Value is " + value); // "2" (expecting "1")
	       } catch (Exception x) {
	           throw new RuntimeException(x);
	       }
	   }
	
	   public static void main(String[] args) throws Exception {
	       new IBatisTest().runTest();
	   }
	
	}
	------------------------------------------------------------
	
	SqlMapConfig.xml:
	------------------------------------------------------------
	<?xml version="1.0" encoding="windows-1252" ?>
	
	<!DOCTYPE sqlMapConfig
	   PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
	   "sql-map-config-2.dtd">
	
	<sqlMapConfig>
	
	   <settings
	       useStatementNamespaces="true"
	       lazyLoadingEnabled="true"
	       enhancementEnabled="true"
	       statementCachingEnabled="false" />
	
	   <transactionManager type="JDBC">
	
	       <dataSource type="SIMPLE">
	           <property name="JDBC.Driver" value="oracle.jdbc.OracleDriver"/>
	           <property name="JDBC.ConnectionURL" value="..."/>
	           <property name="JDBC.Username" value="..."/>
	           <property name="JDBC.Password" value="..."/>
	       </dataSource>
	
	   </transactionManager>
	
	   <!-- at least one SQL Map is required for this to be a
	        valid configuration file -->
	   <sqlMap resource="SqlMap.xml"/>
	
	</sqlMapConfig>
	------------------------------------------------------------
	
	and SqlMap.xml:
	------------------------------------------------------------
	<?xml version="1.0" encoding="windows-1252" ?>
	
	<!DOCTYPE sqlMap
	   PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
	   "sql-map-2.dtd">
	
	<sqlMap namespace="db">
	
	   <cacheModel id="cache" type="FIFO" readOnly="false" serialize="true">
	       <flushOnExecute statement="db.updateValue"/>
	       <property name="size" value="10"/>
	   </cacheModel>
	
	   <insert id="updateValue" parameterClass="String">
	       update VALUES set VALUE=#value# where ID=1
	   </insert>
	
	   <select id="getValue" resultClass="String" cacheModel="cache">
	       select VALUE from VALUES where ID=1
	   </select>
	
	</sqlMap>
	------------------------------------------------------------
	
	-----Original Message-----
	From: Clinton Begin [mailto:clinton.begin@gmail.com]
	Sent: 12 January 2009 15:23
	To: user-java@ibatis.apache.org
	Subject: Re: iBATIS caching / transaction isolation question
	
	The uncommitted data would be seen by thread B as you expect, *if* the cache is configured
as read-only.
	
	To stop this problem, set the cache to read/write and serializable.
	Sorry for the confusing configuration here.
	
	Clinton
	
	On 1/12/09, Young, Alistair <alistair.young@logica.com> wrote:
	> Apologies for following up my own post...
	>
	> I carried out a simple test and found that transaction isolation is
	> not maintained.  Also, the cache is not flushed in the event of a
	> transaction being rolled back.
	>
	> The sequence of events was:
	>
	> Thread A: start transaction
	> Thread A: select value ("1" is returned) Thread A: update value to "2"
	> Thread A: select value ("2" is returned)
	>
	>         Thread B: select value ("2" is returned - not "1")
	>
	> Thread A: rollback transaction
	> Thread A: select value ("2" is returned - not "1")
	>
	> Is this the expected behaviour?
	>
	> If not, what might I be doing wrong?  If so, how do people deal with
	> this behaviour?
	>
	> Thanks for any advice,
	>
	>
	> Alistair.
	>
	> ________________________________
	>
	> From: Young, Alistair
	> Sent: 12 January 2009 10:54
	> To: user-java@ibatis.apache.org
	> Subject: iBATIS caching / transaction isolation question
	>
	>
	> Hello all,
	>
	> I wonder if somebody could clarify for me how iBATIS caching works
	> with regards to transaction isolation.
	>
	> Suppose I have a cache set up with is used when a "selectAllItems"
	> statement is invoked, and flushed when an "updateItem" statement is
	> invoked.
	>
	> Suppose then that thread A starts a transaction, invokes updateItem
	> and then selectAllItems.  Then, before thread A completes the
	> transaction, thread B invokes selectAllItems.
	>
	> Is transaction isolation maintained, or does thread B end up seeing
	> the
	> (uncommitted) data that thread A has updated?
	>
	> I should add that I haven't actually tried this yet - but I'd like to
	> know what the expected behaviour is before getting stuck in.
	>
	> In our particular use case, we're making use of a custom
	> TransactionConfig (which is essentially the same as "EXTERNAL" but
	> handles connection creation slightly differently).  And we're not
	> making any explicit calls to the iBATIS transaction methods.
	>
	> Many thanks!
	>
	>
	> Alistair.
	>
	>
	>
	>
	> Please help Logica to respect the environment by not printing this
	> email  / Merci d'aider Logica à préserver l'environnement en évitant
	> d'imprimer ce mail /  Bitte drucken Sie diese Nachricht nicht aus und
	> helfen Sie so Logica dabei die Umwelt zu schuetzen  /  Por favor ajude
	> a Logica a respeitar o ambiente não imprimindo este correio electrónico.
	>
	>
	>
	> This e-mail and any attachment is for authorised use by the intended
	> recipient(s) only. It may contain proprietary material, confidential
	> information and/or be subject to legal privilege. It should not be
	> copied, disclosed to, retained or used by, any other party. If you are
	> not an intended recipient then please promptly delete this e-mail and
	> any attachment and all copies and inform the sender. Thank you.
	>
	>
	
	--
	Sent from my mobile device
	
	
	Please help Logica to respect the environment by not printing this email  /  Merci d'aider
Logica à préserver l'environnement en évitant d'imprimer ce mail /  Bitte drucken Sie diese
Nachricht nicht aus und helfen Sie so Logica dabei die Umwelt zu schuetzen  /  Por favor ajude
a Logica a respeitar o ambiente não imprimindo este correio electrónico.
	
	
	
	This e-mail and any attachment is for authorised use by the intended recipient(s) only. It
may contain proprietary material, confidential information and/or be subject to legal privilege.
It should not be copied, disclosed to, retained or used by, any other party. If you are not
an intended recipient then please promptly delete this e-mail and any attachment and all copies
and inform the sender. Thank you.
	
	
	
	
	Please help Logica to respect the environment by not printing this email  /  Merci d'aider
Logica à préserver l'environnement en évitant d'imprimer ce mail /  Bitte drucken Sie diese
Nachricht nicht aus und helfen Sie so Logica dabei die Umwelt zu schuetzen  /  Por favor ajude
a Logica a respeitar o ambiente não imprimindo este correio electrónico.
	
	
	
	This e-mail and any attachment is for authorised use by the intended recipient(s) only. It
may contain proprietary material, confidential information and/or be subject to legal privilege.
It should not be copied, disclosed to, retained or used by, any other party. If you are not
an intended recipient then please promptly delete this e-mail and any attachment and all copies
and inform the sender. Thank you.
	
	
	




Please help Logica to respect the environment by not printing this email  /  Merci d'aider
Logica à préserver l'environnement en évitant d'imprimer ce mail /  Bitte drucken Sie diese
Nachricht nicht aus und helfen Sie so Logica dabei die Umwelt zu schuetzen  /  Por favor ajude
a Logica a respeitar o ambiente não imprimindo este correio electrónico.



This e-mail and any attachment is for authorised use by the intended recipient(s) only. It
may contain proprietary material, confidential information and/or be subject to legal privilege.
It should not be copied, disclosed to, retained or used by, any other party. If you are not
an intended recipient then please promptly delete this e-mail and any attachment and all copies
and inform the sender. Thank you.


Mime
View raw message