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

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

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

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

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

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

          補(bǔ)充一下我的一個(gè)最簡單情況下的測試用例:
          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>

          被測試方法(都配置有事務(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);
              }

          測試用例:
               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);
              }

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

          常用鏈接

          留言簿(38)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          常去的網(wǎng)站

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 潜江市| 旬阳县| 大新县| 盖州市| 理塘县| 灵璧县| 肃北| 平阳县| 齐齐哈尔市| 铜鼓县| 太原市| 夏邑县| 历史| 永修县| 阳江市| 藁城市| 定州市| 景谷| 肇州县| 驻马店市| 岐山县| 门头沟区| 枣强县| 石泉县| 蓬安县| 宜良县| 竹溪县| 庐江县| 乌兰察布市| 北宁市| 扶风县| 南康市| 二手房| 建水县| 昌邑市| 罗甸县| 利辛县| 全州县| 定西市| 穆棱市| 五莲县|