posts - 193,  comments - 520,  trackbacks - 0
          測(cè)試在sqlserver2000上進(jìn)行,對(duì)工作流操作的相關(guān)方法在單元測(cè)試?yán)镞M(jìn)行多線(xiàn)程并發(fā)。測(cè)試發(fā)現(xiàn)sqlserver出現(xiàn)死鎖的情況相當(dāng)多,一些典型的情況:

          1、對(duì)同一張表先insert再u(mài)pdate是很快會(huì)引起死鎖的,不管操作的是否是同一記錄
          解決方法:對(duì)于同一記錄,需要調(diào)整hibernate的映射策略,使得一次insert完成操作。對(duì)于不同的記錄需要在代碼中手動(dòng)flush,使得update先于insert。

          2、對(duì)兩張表進(jìn)行多次update操作時(shí),兩張表交替update也會(huì)很快引起死鎖
          解決方法:在代碼中手動(dòng)flush,保證對(duì)兩張表的update不會(huì)出現(xiàn)交替的情況。

          3、部分大范圍掃描的select和update混合也會(huì)導(dǎo)致死鎖
          解決方法:優(yōu)化sql,盡量減少sql語(yǔ)句,通過(guò)給po增加持久化字段的方式減少關(guān)聯(lián)查詢(xún)

          經(jīng)過(guò)優(yōu)化,大部分情況下數(shù)據(jù)庫(kù)死鎖的情況得以避免,另外奇怪的是通過(guò)事件探查器在死鎖時(shí)并未發(fā)現(xiàn)鎖升級(jí)的事件。但是在一些特殊情況下(例如多個(gè)并發(fā)匯聚的直接聯(lián)合),死鎖依舊發(fā)生。最后不得不對(duì)方法進(jìn)行synchronized關(guān)鍵字同步,這個(gè)通過(guò)synchronized flush完成。業(yè)務(wù)方法不必同步,最后批量操作數(shù)據(jù)庫(kù)時(shí)進(jìn)行同步。

          換oracle進(jìn)行測(cè)試,在未synchronized的情況下,未發(fā)生死鎖情況。由此可見(jiàn)sqlserver與oracle鎖實(shí)現(xiàn)機(jī)制存在很大的差別。對(duì)sqlserver鄙視之。另,同事說(shuō),sqlserver2005后性能和機(jī)制發(fā)生了很大的變化,未測(cè)試。

          補(bǔ)充一下我的一個(gè)最簡(jiǎn)單情況下的測(cè)試用例:
          PO:
          public class TestPO {
              String id;
              String name;
              
          int num;
              
              .
          }

          映射文件 hibernate3:
          <hibernate-mapping default-access="field">
            
          <class table="WFMS_TESTPO" name="com.eway.workflow.test.po.TestPO">

              
          <id name="id" column="ID"><generator class="uuid" /></id>

              
          <property name="name" column="NAME" type="string"/>

              
          <property name="num" column="NUM" type="integer"/>

            
          </class>
          </hibernate-mapping>

          被測(cè)試方法(都配置有事務(wù)):
              public void testSave(int num) {
                  TestPO po 
          = new TestPO();
                  po.setName(
          "ronghao");
                  po.setNum(num);
                  theadTestDao.save(po);
                  po.setName(
          "haorong");
              }

              
          public void testSaveByJdbc(int num) {
                  String sql 
          = "insert into WFMS_TESTPO (ID,NAME,NUM) values (?,'RONGHAO',?)";
                  Object[] params 
          = new Object[]{num,num};
                  jdbcTemplate.update(sql, params);
                  sql
          ="update WFMS_TESTPO set name='haorong' where id=?"  ;
                  params 
          = new Object[]{num};
                  jdbcTemplate.update(sql, params);
              }

          測(cè)試用例:
               public void testSave() throws Exception {
                  TheadtestTemplate template 
          = new TheadtestTemplate();
                  template.execute(
          new TheadtestCallback() {
                      
          public void doInThead(int suquence) {
          //               theadTestManager.testSave(suquence);
                          theadTestManager.testSaveByJdbc(suquence);
                      }
                  }, 
          10);
              }

          測(cè)試結(jié)果:不論是hibernate還是jdbc,并發(fā)情況下都很快就會(huì)引起sqlserver2000的死鎖,換用兩種數(shù)據(jù)庫(kù)驅(qū)動(dòng)jtds和jturbo死鎖的情況沒(méi)有變化。

          結(jié)論:sqlserver2000數(shù)據(jù)庫(kù)的lock配置策略,不支持,或者數(shù)據(jù)庫(kù)本身,就不支持對(duì)不同的行做同時(shí)操作(或者支持不完善),所謂的行鎖支持很不完善,死鎖情況非常容易發(fā)生。

          補(bǔ)充:我對(duì)數(shù)據(jù)庫(kù)的一些實(shí)現(xiàn)機(jī)制也并不是很了解,所以這里也只能列出現(xiàn)象而不能解釋死鎖的根本原因。另外感謝Alex的討論。


          http://www.aygfsteel.com/ronghao 榮浩原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處:)
          posted on 2008-06-19 13:34 ronghao 閱讀(6277) 評(píng)論(22)  編輯  收藏 所屬分類(lèi): 工作日志

          FeedBack:
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-19 15:02 | Alex
          xd ,你配置了事務(wù)了嘛?  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決
          2008-06-19 17:55 | flybean
          1、死鎖,還是鎖阻塞,這是個(gè)問(wèn)題。
          2、悲觀(guān)并發(fā)、樂(lè)觀(guān)并發(fā)生來(lái)以久,各有優(yōu)缺點(diǎn),搞清楚再來(lái)鄙視。  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 09:14 | Alex
          1、對(duì)同一張表先insert再u(mài)pdate是很快會(huì)引起死鎖的,不管操作的是否是同一記錄
          2、對(duì)兩張表進(jìn)行多次update操作時(shí),兩張表交替update也會(huì)很快引起死鎖
          3、部分大范圍掃描的select和update混合也會(huì)導(dǎo)致死鎖

          如果連這些問(wèn)題都解決不了,你覺(jué)得是數(shù)據(jù)庫(kù)問(wèn)題,還是你的問(wèn)題呢?

          別拿那么多名詞出來(lái)嚇人,這個(gè)招數(shù)我上小學(xué)的時(shí)候用來(lái)嚇唬老師的,現(xiàn)在已經(jīng)不用了。

          就撿最后一個(gè)說(shuō)吧,樂(lè)觀(guān)鎖,如果你控制不了,還是就不要用了,您還就是老老實(shí)實(shí)的本分點(diǎn),使用數(shù)據(jù)庫(kù)本地提供的鎖功能吧,犧牲點(diǎn)數(shù)據(jù)庫(kù)的性能,也總比你數(shù)據(jù)更新失敗要好,如果你非要使用hibernate的樂(lè)觀(guān)鎖,請(qǐng)控制好,內(nèi)存中的數(shù)據(jù)和數(shù)據(jù)庫(kù)中的數(shù)據(jù)一致性。  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 09:28 | ronghao
          @Alex
          我想你并沒(méi)有弄明白問(wèn)題的關(guān)鍵。樂(lè)觀(guān)鎖和悲觀(guān)鎖的作用是防止多個(gè)事務(wù)對(duì)同一數(shù)據(jù)操作產(chǎn)生沖突的兩種策略。而我的問(wèn)題是多個(gè)線(xiàn)程(即多個(gè)事務(wù))并發(fā)操作不同的數(shù)據(jù)。不知道明不明白意思。
          ps:以前我也把這兩者的概念經(jīng)常混淆。
            回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決
          2008-06-20 09:29 | BeanSoft
          說(shuō)不定是濫用 Hibernate 導(dǎo)致的后果  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 09:34 | ronghao
          @BeanSoft
          我倒真的認(rèn)為是數(shù)據(jù)庫(kù)的原因。
          一個(gè)簡(jiǎn)單的例子:很簡(jiǎn)單的po:
          String id;
          String name;
          兩個(gè)字段,執(zhí)行操作:
          TestPO po=new TestPO();
          po.setName("ronghao");
          dao.save(po);
          dao.flush();
          po.setName("haorong");
          配置事務(wù),單元測(cè)試兩個(gè)線(xiàn)程并發(fā),sqlserver2000下馬上死鎖。  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 09:39 | ronghao
          @BeanSoft
          當(dāng)然,我并沒(méi)有用jdbc直接測(cè)試  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 10:12 | Alex
          @ronghao
          如果不是多線(xiàn)程,那么配置事務(wù)還有何用,如果所有操作都在同一個(gè)流水線(xiàn)上,那么配置事務(wù)不是浪費(fèi)人民的感情嘛?

            回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 10:18 | Alex
          使用hibernate樂(lè)觀(guān)鎖 如果導(dǎo)致你保存失敗,簡(jiǎn)單點(diǎn)說(shuō),就是你的兩個(gè)線(xiàn)程或者多個(gè)線(xiàn)程所控制的內(nèi)存中的數(shù)據(jù)和數(shù)據(jù)庫(kù)中數(shù)據(jù)集已經(jīng)不一致了。

          如果使用悲觀(guān)鎖,導(dǎo)致你保存失敗,那么說(shuō)明你事務(wù)配置的問(wèn)題,或者至少說(shuō)明你測(cè)試用例的事務(wù)配置有問(wèn)題,要不你直接試試 jdbc 并且硬編碼事務(wù)看看。

          否則 sqlserver2000 真的不要玩了,兩個(gè)線(xiàn)程都是死鎖。。。

            回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 10:20 | Alex
          同時(shí)操作同的記錄集合,一方面要看你數(shù)據(jù)庫(kù)使用什么lock策略,一方面還要看你代碼的控制。  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 10:21 | Alex
          同時(shí)操作不同的記錄集合,一方面要看你數(shù)據(jù)庫(kù)使用什么lock策略,一方面還要看你代碼的控制.  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 10:21 | ronghao
          @Alex
          你的說(shuō)法沒(méi)有錯(cuò)。我想問(wèn)題的原因在于死鎖的原因你我的理解有差異。
          你理解的是對(duì)數(shù)據(jù)庫(kù)表同一記錄并發(fā)操作引起數(shù)據(jù)庫(kù)死鎖,這個(gè)顯然是應(yīng)用程序應(yīng)該控制和避免的。
          而我的意思是并發(fā)操作某一動(dòng)作,例如同時(shí)啟動(dòng)100個(gè)工作流流程,這個(gè)盡管操作的是同一張表但是顯然是針對(duì)不同的記錄,此時(shí),樂(lè)觀(guān)鎖、悲觀(guān)鎖都是沒(méi)有意義的。
          當(dāng)然,我對(duì)數(shù)據(jù)庫(kù)的一些實(shí)現(xiàn)機(jī)制也并不是很了解,所以這里也只能列出現(xiàn)象而不能解釋死鎖的根本原因。  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 10:26 | ronghao
          @Alex
          補(bǔ)充說(shuō)明一下,在我的測(cè)試中,不會(huì)出現(xiàn)兩個(gè)線(xiàn)程互相修改沖突的情況,甚至select也不會(huì)沖突,因?yàn)榱鞒虒?shí)例ID一開(kāi)始就將所有的數(shù)據(jù)區(qū)分開(kāi)來(lái)。我是并發(fā)啟動(dòng)多個(gè)流程,然后并發(fā)提交這些流程。  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 10:31 | Alex
          上面我也說(shuō)了,如果你直接使用hibernate的樂(lè)觀(guān)鎖,那么最細(xì)粒度的數(shù)據(jù)其實(shí)是由你自己來(lái)控制的,只要保持內(nèi)存中的當(dāng)前的數(shù)據(jù)在需要保存時(shí)和數(shù)據(jù)庫(kù)中的保存相同的version 就可以了,然后不管 有多少個(gè)線(xiàn)程insert 或者 update ,只要每個(gè)線(xiàn)程都滿(mǎn)足這個(gè)要求,就能保存成功了,當(dāng)然,如果你的數(shù)據(jù)庫(kù)的lock配置策略,不支持,或者數(shù)據(jù)庫(kù)本身,就不支持對(duì)不同的行做同時(shí)操作(或者支持不完善),所謂的行鎖,那么肯定會(huì)像你所說(shuō)的那樣發(fā)生死鎖。
            回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 10:37 | Alex
          @ronghao
          如果每個(gè)線(xiàn)程只處理 某一個(gè)或一些獨(dú)立 流程id相關(guān)的數(shù)據(jù),而沒(méi)有交叉數(shù)據(jù),那么還會(huì)出現(xiàn)這種現(xiàn)象。

          1.使用jdbc做這種測(cè)試,排除是否是hibernate的使用或者h(yuǎn)ibernate本身對(duì)2000支持的問(wèn)題問(wèn)題。(jdbc驅(qū)動(dòng)也很關(guān)鍵。)
          2.查閱sql2000 對(duì)行鎖的支持程度。
            回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 10:45 | ronghao
          @Alex
          哈哈,正如你說(shuō)的,我想問(wèn)題在這里:
          當(dāng)然,如果你的數(shù)據(jù)庫(kù)的lock配置策略,不支持,或者數(shù)據(jù)庫(kù)本身,就不支持對(duì)不同的行做同時(shí)操作(或者支持不完善),所謂的行鎖,那么肯定會(huì)像你所說(shuō)的那樣發(fā)生死鎖。
          這也是我想表達(dá)的。我想有時(shí)間應(yīng)該請(qǐng)個(gè)專(zhuān)業(yè)的DBA來(lái),我也查過(guò)了SQLSERVER的鎖機(jī)制,但是具體到這里理解還是存在問(wèn)題。
          另外你對(duì)樂(lè)觀(guān)鎖的理解也很到位。如果是多個(gè)事務(wù)同時(shí)提交一個(gè)流程,樂(lè)觀(guān)鎖就會(huì)起作用。
            回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決[未登錄](méi)
          2008-06-20 10:46 | ronghao
          @Alex
          好的,謝謝你的意見(jiàn)。我會(huì)用jdbc做這個(gè)測(cè)試。  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決
          2008-06-20 16:30 | BeanSoft
          是呀 JDBC 先測(cè)試下比較好 排除法 如果 JDBC 也不行 那八九成是 SQL Server 問(wèn)題 坊間的傳言都認(rèn)為 SQL Server 好多地方不如 Oracle  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決
          2008-06-21 19:45 | 鬼狗
          pk的這么熱烈丫, 我想可能先要搞清楚的是行鎖,頁(yè)鎖和表鎖這些基本概念,搞清楚不同數(shù)據(jù)庫(kù)的鎖機(jī)制,然后再來(lái)談樂(lè)觀(guān)鎖還是悲觀(guān)鎖會(huì)比較容易理解。

          我估計(jì)樓主缺少在sybase,db2下的工作經(jīng)驗(yàn), 所以才會(huì)這么激動(dòng)。不同數(shù)據(jù)庫(kù)的設(shè)計(jì)本身是有相當(dāng)大差異的,很難說(shuō)好壞,我印象中,缺省情況下對(duì)鎖的處理比較不傷腦筋的就是oracle了,其他的不管是sybase還是db2都不是缺省就可以很輕松做到高并發(fā)的,但是處理的好,至少db2 可以做到不輸給oracle的高并發(fā)。 至于sql server ,tpc網(wǎng)站上去翻一下,可以發(fā)現(xiàn)sql server也是常客。

          但是早期oracle的開(kāi)發(fā), 嗯, 我覺(jué)得在很多方面其實(shí)倒不如db2這樣的數(shù)據(jù)庫(kù)省事,比如大表和小表在sql中的位置,都會(huì)顯著影響sql性能。再比如sql是簡(jiǎn)單好,還是復(fù)雜好,這2個(gè)數(shù)據(jù)庫(kù)也是相反的。

          這只能說(shuō)明不同數(shù)據(jù)庫(kù)的機(jī)制是有很大差異的,用好一個(gè)數(shù)據(jù)庫(kù)需要點(diǎn)時(shí)間對(duì)他進(jìn)行比較深入的理解。現(xiàn)代程序員往往被各種框架屏蔽了底層,有時(shí)候也不是什么好事,以前項(xiàng)目中就有專(zhuān)門(mén)組織DBA對(duì)程序員進(jìn)行數(shù)據(jù)庫(kù)方面的培訓(xùn),目的也就是為了彌補(bǔ)這個(gè)問(wèn)題。

          對(duì)于鎖的問(wèn)題,在oracle9i&10g編程藝術(shù)那本書(shū)里,作者有很深入的介紹,也列舉了其他數(shù)據(jù)庫(kù)的處理情況。作者從其他數(shù)據(jù)庫(kù)轉(zhuǎn)向使用oracle的時(shí)候,對(duì)這個(gè)問(wèn)題,貌似和樓主一樣震驚,呵呵。當(dāng)年我也有個(gè)項(xiàng)目,被db2的鎖機(jī)制,搞的的死去活來(lái),呵呵。

          簡(jiǎn)單的說(shuō),搖身要是高可靠性數(shù)據(jù)庫(kù)都只是知道寫(xiě)sql這么簡(jiǎn)單, 人家DBA還怎么活?  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決
          2008-06-21 19:50 | 鬼狗
          另外不知道lz用的jdbc是什么版本? sqlserver 2000 的官方版本問(wèn)題多多,印象中諸多特性都不支持。  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決
          2008-06-22 15:24 | ronghao
          @鬼狗
          呵呵,你的意見(jiàn)非常中肯。  回復(fù)  更多評(píng)論
            
          # re: 高并發(fā)測(cè)試下的一些問(wèn)題及解決
          2008-07-03 22:55 | leekiang
          汗,我們公司做了很多項(xiàng)目了,可你們說(shuō)的這些問(wèn)題公司幾十號(hào)人沒(méi)有一個(gè)人清楚,那些項(xiàng)目能用嗎?請(qǐng)問(wèn)。  回復(fù)  更多評(píng)論
            
          <2008年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          關(guān)注工作流和企業(yè)業(yè)務(wù)流程改進(jìn)。現(xiàn)就職于ThoughtWorks。新浪微博:http://weibo.com/ronghao100

          常用鏈接

          留言簿(38)

          隨筆分類(lèi)

          隨筆檔案

          文章分類(lèi)

          文章檔案

          常去的網(wǎng)站

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 壶关县| 双鸭山市| 泗洪县| 邵东县| 罗江县| 温州市| 沽源县| 开平市| 娱乐| 新泰市| 科技| 普陀区| 伊春市| 内江市| 东港市| 洞头县| 广平县| 海城市| 汉寿县| 广水市| 望城县| 商丘市| 阜新市| 金秀| 黄平县| 万安县| 安溪县| 定西市| 禄丰县| 肥东县| 灵台县| 万山特区| 方城县| 萨迦县| 扶余县| 荣昌县| 宕昌县| 宁河县| 绍兴市| 宁阳县| 曲阜市|