走自己的路

          路漫漫其修遠(yuǎn)兮,吾將上下而求索

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            50 隨筆 :: 4 文章 :: 118 評(píng)論 :: 0 Trackbacks
          由于業(yè)務(wù)需要將quartz的jobstore從JobStoreTx更新為JobStoreCMT,接著啟動(dòng)servlet時(shí)發(fā)現(xiàn)被鎖住了。由于使用jobstorecmt我們使用了managed datasource,按照quartz文檔的要求我也配置了non managed datasource,在quartz中什么是managed datasource和non managed datasource呢?

          Managed datasource: 使用了cmt才有的概念,應(yīng)該主要是job執(zhí)行時(shí)還有一些其他和job有關(guān)的操作quartz會(huì)用到的datasource,這個(gè)datasource是由容器來管理的,也就是一般意義上我們使用的managed datasource,但是它還強(qiáng)調(diào)的是transaction是由容器或者用戶自己的程序來控制(JTA)。quartz的job執(zhí)行提供了一個(gè)UserTransaction的wrap。

          Non managed datasource; JobStoreTX默認(rèn)就是使用這個(gè)datasource,默認(rèn)是dbcp的pool,這個(gè)non managed datasource不是指我們不能使用容器管理的datasource,也可以配置成容器管理的datasource的,但要注意的是transaction level是local的,transaction是由quartz控制的,quartz來完成transaction的語義和邊界。


          一開始的配置如下:
          # The value of org.quartz.scheduler.instanceName
          # can be any string
          , and has no meaning to the scheduler itself -
          # but rather serves as a mechanism for client code to distinguish schedulers
          # when multiple instances are used within the same program.  If you are using
          # the clustering features
          , you must use the same name for every instance in 
          # the cluster that is 'logically' the same Scheduler.
          #
          # NOTE: Especially for the application using LTS
          , the instanceName is different and 
          #       specific per application to avoid the interruption between applications. For
          #       example in TMS project the instanceName could be named as TMS_APP
          , in DMS
          #       project the instanceName could be named as DMS_APP etc
          , the instanceName in
          #       different projects must be different. For more details
          , you could refer to
          #       the LTS installation guide.
          org.quartz.scheduler.instanceName 
          = LTS
          org.quartz.scheduler.rmi.export 
          = true
          org.quartz.scheduler.rmi.registryHost 
          = localhost
          org.quartz.scheduler.rmi.registryPort 
          = 1100
          org.quartz.scheduler.rmi.createRegistry 
          = as_needed
          org.quartz.scheduler.wrapJobExecutionInUserTransaction 
          = true


          org.quartz.threadPool.class 
          = org.quartz.simpl.SimpleThreadPool
          org.quartz.threadPool.threadCount 
          = 10
          org.quartz.threadPool.threadPriority 
          = 5
          org.quartz.jobStore.misfireThreshold 
          = 2592000000


          org.quartz.jobStore.class 
          = org.quartz.impl.jdbcjobstore.JobStoreCMT


          org.quartz.jobStore.driverDelegateClass 
          = org.quartz.impl.jdbcjobstore.oracle.OracleDelegate

          org.quartz.jobStore.useProperties 
          = false
          org.quartz.jobStore.dataSource 
          = myXADS
          org.quartz.jobStore.nonManagedTXDataSource 
          = myDS
          org.quartz.jobStore.tablePrefix 
          = QRTZ_
          org.quartz.jobStore.isClustered 
          = false
          org.quartz.jobStore.selectWithLockSQL 
          = 

          org.quartz.dataSource.myXADS.jndiURL 
          = jdbc/ltstxxatest

          org.quartz.dataSource.myDS.driver 
          = oracle.jdbc.OracleDriver
          org.quartz.dataSource.myDS.URL 
          = jdbc:oracle:thin:@shhpdv11:1521:WOSDB
          org.quartz.dataSource.myDS.user 
          = sysint
          org.quartz.dataSource.myDS.password 
          = sysint
          org.quartz.dataSource.myDS.maxConnections 
          = 5






          datasource的配置:
              <managed-data-source name="LTSTxTestXADataSource"
                  connection-pool-name
          ="LTSTxTestXAConnectionFactory"
                  jndi-name
          ="jdbc/ltstxxatest" tx-level='global' />
              
          <!-- tx-level='global' -->
              
          <connection-pool name="LTSTxTestXAConnectionFactory">
                  
          <connection-factory
                      
          factory-class="oracle.jdbc.xa.client.OracleXADataSource"
                      user
          ="sysint" password="sysint"
                      url
          ="jdbc:oracle:thin:@shhpdv11:1521:WOSDB">
                  
          </connection-factory>
              
          </connection-pool>

          但是發(fā)現(xiàn)servlet在啟動(dòng)時(shí)hold在那里了,跟了一下代碼,發(fā)現(xiàn)quartz jobstoreCMT默認(rèn)是使用的oracle db的TM鎖,而jobstoreTX使用的是java的邏輯鎖,于是登錄到db中,查了一下,發(fā)現(xiàn)一個(gè)insert quartz_simple_triggers的DML操作申請(qǐng)了Qaurtz_Locks的表鎖,而接著start quartz scheduler時(shí)也會(huì)去申請(qǐng)這個(gè)表鎖,但是前面的DML操作一直都沒有commit,所有quartz scheduler start時(shí)就被鎖在那里了。然后試著將non managed datasource和managed datasource配成同一個(gè)datasource啟動(dòng)ok沒有問題,但是正是因?yàn)榕淞送粋€(gè)datasource可能下一次從pool中拿的connection的oracle session還是擁有那個(gè)鎖資源的,鎖資源沒有被先前的connection釋放掉,因?yàn)槭聞?wù)沒有提交,connection的邏輯close不會(huì)釋放session擁有的資源。這樣又回到了原點(diǎn),白試了一把,后來仔細(xì)跟了一把程序,發(fā)現(xiàn)autocommit是false,也沒有地方顯著的提交,scheduleJob和unscheduleJob都會(huì)有這種情況,本來以為只有job執(zhí)行的時(shí)候會(huì)用到managed datasource,這樣看來很多對(duì)job信息的處理的地方都用到了managed datasource,但是為什么quartz不幫我們wrap起來提交呢,控制transaction的任務(wù)交給了我們自己或container,交給我們自己是指我們需要自己用JTA transaction封裝這些操作,交給container就需要把屬性:

          org.quartz.jobStore.dontSetAutoCommitFalse = true

          但是quartz文檔中提到下面這一段:

          org.quartz.jobStore.dontSetAutoCommitFalse

          False

          Description: Setting this parameter to true tells Quartz not to call setAutoCommit(false) on connections obtained from the DataSource(s). This can be helpful in a few situations, such as if you have a driver that complains if it is called when it is already off. This property defaults to false because most drivers require that setAutoCommit(false) be called.


          大概意思是大多數(shù)jdbc driver是不用去設(shè)置auto commit為true的,保持默認(rèn)值是false就可以了,又看到了這篇文章:

          http://forums.opensymphony.com/thread.jspa?threadID=14762&messageID=28963#28963

          主要是說auto commit設(shè)成true會(huì)改變quartz transaction的語義,本來時(shí)多步操作提交的,現(xiàn)在變成了每步dml操作都會(huì)提交。但是如果不設(shè)auto commit在oracle jdbc中似乎沒辦法再提交這個(gè)transaction了,鎖就不會(huì)被釋放。于是找了找,找到了下面這篇文章:

          http://forums.opensymphony.com/thread.jspa?threadID=365430&messageID=452688#452688

          這篇文章也遇到了類似這樣的問題,提交了trigger但是沒有到db中,應(yīng)該也是被鎖住了。提出的解決辦法就是把a(bǔ)uto commit設(shè)成true。接著嘗試了一下,順利成功啟動(dòng),trigger成功調(diào)度,job成功執(zhí)行。表面上看似沒有什么問題,但是一直還是有concern,因?yàn)槲覀冞@樣設(shè)置會(huì)不會(huì)更改了quartz事務(wù)的語義,仔細(xì)看了quartz jobstore相關(guān)的代碼,jobstorecmt中其實(shí)還有一個(gè)屬性:

              // Great name huh?
              protected boolean dontSetNonManagedTXConnectionAutoCommitFalse = false;

          文檔中的描述:

          org.quartz.jobStore.dontSetNonManagedTX ConnectionAutoCommitFalse

          False

          Description: This is the same as the property org.quartz.jobStore.dontSetAutoCommitFalse, except that it applies to the nonManagedTXDataSource.


          默認(rèn)值是false,所有non managed datasource都是用的這個(gè)值,auto commit是false,設(shè)置org.quartz.jobStore.dontSetAutoCommitFalse = false不會(huì)影響non managed datasource的transaction語義。這樣想想把這個(gè)值設(shè)成true也不會(huì)有什么問題,不過進(jìn)一步還是要進(jìn)行大量的測(cè)試。所以oracle application server使用jobstorecmt后quartz的配置應(yīng)該如下:

          # The value of org.quartz.scheduler.instanceName
          # can be any string
          , and has no meaning to the scheduler itself -
          # but rather serves as a mechanism for client code to distinguish schedulers
          # when multiple instances are used within the same program.  If you are using
          # the clustering features
          , you must use the same name for every instance in 
          # the cluster that is 'logically' the same Scheduler.
          #
          # NOTE: Especially for the application using LTS
          , the instanceName is different and 
          #       specific per application to avoid the interruption between applications. For
          #       example in TMS project the instanceName could be named as TMS_APP
          , in DMS
          #       project the instanceName could be named as DMS_APP etc
          , the instanceName in
          #       different projects must be different. For more details
          , you could refer to
          #       the LTS installation guide.
          org.quartz.scheduler.instanceName 
          = LTS
          org.quartz.scheduler.rmi.export 
          = true
          org.quartz.scheduler.rmi.registryHost 
          = localhost
          org.quartz.scheduler.rmi.registryPort 
          = 1101
          org.quartz.scheduler.rmi.createRegistry 
          = as_needed
          org.quartz.scheduler.wrapJobExecutionInUserTransaction 
          = true


          org.quartz.threadPool.class 
          = org.quartz.simpl.SimpleThreadPool
          org.quartz.threadPool.threadCount 
          = 10
          org.quartz.threadPool.threadPriority 
          = 5
          org.quartz.jobStore.misfireThreshold 
          = 2592000000


          org.quartz.jobStore.class 
          = org.quartz.impl.jdbcjobstore.JobStoreCMT


          org.quartz.jobStore.driverDelegateClass 
          = org.quartz.impl.jdbcjobstore.oracle.OracleDelegate

          org.quartz.jobStore.useProperties 
          = false
          org.quartz.jobStore.dataSource 
          = myXADS
          org.quartz.jobStore.nonManagedTXDataSource 
          = myDS
          org.quartz.jobStore.tablePrefix 
          = QRTZ_
          org.quartz.jobStore.isClustered 
          = false
          org.quartz.jobStore.dontSetAutoCommitFalse 
          = true
          org.quartz.jobStore.selectWithLockSQL 
          = 

          org.quartz.dataSource.myXADS.jndiURL 
          = jdbc/ltstxxatest


          org.quartz.dataSource.myDS.driver 
          = oracle.jdbc.OracleDriver
          org.quartz.dataSource.myDS.URL 
          = jdbc:oracle:thin:@shhpdv11:1521:WOSDB
          org.quartz.dataSource.myDS.user 
          = sysint
          org.quartz.dataSource.myDS.password 
          = sysint
          org.quartz.dataSource.myDS.maxConnections 
          = 5




          posted on 2009-02-06 17:13 叱咤紅人 閱讀(4251) 評(píng)論(2)  編輯  收藏 所屬分類: Other Java and J2EE frameworks

          評(píng)論

          # re: Oracle application server使用Quartz JobStoreCMT遇到程序被鎖問題 2009-06-25 17:00 Tenny
          樓主:
           我因?yàn)轫?xiàng)目需要也是將quartz的jobstore從JobStoreTx更新為JobStoreCMT,我在servlet啟動(dòng)時(shí)沒錯(cuò),但是當(dāng)我調(diào)度執(zhí)行一個(gè)job時(shí),在持久化存儲(chǔ)job的Blob信息時(shí)出錯(cuò):
          配置環(huán)境:weblogic9.22 + oracle 10g + quartz1.6
          org.quartz.JobPersistenceException: Couldn't store job: Driver's Blob representation is of an unsupported type: weblogic.jdbc.wrapper.Blob_oracle_sql_BLOB [See nested exception: java.sql.SQLException: Driver's Blob representation is of an unsupported type: weblogic.jdbc.wrapper.Blob_oracle_sql_BLOB]
          ....
          Caused by: java.sql.SQLException: Driver's Blob representation is of an unsupported type: weblogic.jdbc.wrapper.Blob_oracle_sql_BLOB
          ...
          我更新了oracle10g的最新jdbc驅(qū)動(dòng)亦于事無補(bǔ).我也不確信我的quartz配置是否正確,請(qǐng)幫我檢查一下:
          org.quartz.scheduler.instanceName = OnlineTaskQuartzScheduler
          #org.quartz.scheduler.rmi.export = true
          #org.quartz.scheduler.rmi.registryHost = localhost
          #org.quartz.scheduler.rmi.registryPort = 1101
          #org.quartz.scheduler.rmi.createRegistry = as_needed
          org.quartz.scheduler.wrapJobExecutionInUserTransaction = true

          org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
          org.quartz.threadPool.threadCount = 5
          org.quartz.threadPool.threadPriority = 5
          org.quartz.jobStore.misfireThreshold = 2592000000


          org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT


          org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.oracle.OracleDelegate

          org.quartz.jobStore.useProperties = false
          org.quartz.jobStore.dataSource = myXADS
          org.quartz.jobStore.nonManagedTXDataSource = myDS
          org.quartz.jobStore.tablePrefix = QRTZ_
          org.quartz.jobStore.isClustered = false
          org.quartz.jobStore.dontSetAutoCommitFalse = true
          org.quartz.jobStore.selectWithLockSQL =

          org.quartz.dataSource.myXADS.jndiURL = ReportDataSource
          org.quartz.dataSource.myXADS.jndiAlwaysLookup = DB_JNDI_ALWAYS_LOOKUP
          org.quartz.dataSource.myXADS.java.naming.factory.initial = weblogic.jndi.WLInitialContextFactory
          org.quartz.dataSource.myXADS.java.naming.provider.url = t3://localhost:7001
          org.quartz.dataSource.myXADS.java.naming.security.principal = weblogic
          org.quartz.dataSource.myXADS.java.naming.security.credentials = weblogic


          org.quartz.dataSource.myDS.driver = oracle.jdbc.OracleDriver
          org.quartz.dataSource.myDS.URL = jdbc:oracle:thin:@XXXXXXX:1521:dhcs
          org.quartz.dataSource.myDS.user = XXXXX
          org.quartz.dataSource.myDS.password = XXXXX
          org.quartz.dataSource.myDS.maxConnections = 5
          org.quartz.dataSource.myDS.validationQuery = select table_name from user_tables   回復(fù)  更多評(píng)論
            

          # re: Oracle application server使用Quartz JobStoreCMT遇到程序被鎖問題 2009-06-26 05:10 ldd600
          請(qǐng)使用 WebLogicDelegate  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 孙吴县| 新野县| 牟定县| 雅江县| 宁城县| 山阳县| 安龙县| 阿瓦提县| 棋牌| 平乐县| 佛山市| 九龙坡区| 潼南县| 吴江市| 深州市| 奇台县| 东兰县| 密山市| 四会市| 昆山市| 通许县| 大同县| 郸城县| 鲜城| 阿拉善右旗| 申扎县| 芮城县| 苍南县| 平远县| 治县。| 汽车| 涿州市| 连南| 疏附县| 富川| 吴川市| 登封市| 海伦市| 南开区| 汶川县| 弋阳县|