針對bbosspersistent,在oracle 10上做了一個簡單的性能測試:
環境配置:
連接配接池最大連接配接數設定為10
連接配接池初始連接配接數位2
測試場景:
300個線程并發往一張3字段的表中插入資料,每個線程執行3條記錄插入操作
測試結果:
插入完畢後,統計結果如下
不使用事務 :357條/秒
使用RW_TRANSACTION事務:820條/秒
測試程式:
package com.frameworkset.common.poolman;
import javax.transaction.RollbackException;
import com.frameworkset.orm.transaction.TransactionManager;
/**
*
* <p>Title: CurrentTest.java</p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2007</p>
* @Date 2010-8-2 下午12:02:44
* @author biaoping.yin
* @version 1.0
*/
public class CurrentTest {
public static void main(String[] args) throws InterruptedException {
// for(int j = 0; j < 300; j ++)
// {
// CurrentTest i = new CurrentTest();
// i.test(false);
// }
for(int j = 0; j < 300; j ++)
{
CurrentTest i = new CurrentTest();
i.test(true);
}
}
public void test(boolean usetx)
{
if(!usetx)
{
Task t = new Task();
t.start();
}
else
{
TXTask t = new TXTask();
t.start();
}
}
static class Task extends Thread
{
/* (non-Javadoc)
* @see java.lang.Thread#run()
*/
@Override
public void run() {
DBUtil db = new DBUtil();
try {
db.executeInsert("insert into TEST_CURRENT(id,name) values(10,'test')");
db.executeInsert("insert into TEST_CURRENT(id,name) values(10,'test')");
db.executeInsert("insert into TEST_CURRENT(id,name) values(10,'test')");
db.executeInsert("insert into TEST_CURRENT(id,name) values(10,'test')");
} catch (Throwable e) {
e.printStackTrace();
}
}
}
static class TXTask extends Thread
{
/* (non-Javadoc)
* @see java.lang.Thread#run()
*/
@Override
public void run() {
DBUtil db = new DBUtil();
TransactionManager tm = new TransactionManager();
try {
tm.begin(tm.RW_TRANSACTION);
db.executeInsert("insert into TEST_CURRENT(id,name) values(10,'test')");
db.executeInsert("insert into TEST_CURRENT(id,name) values(10,'test')");
db.executeInsert("insert into TEST_CURRENT(id,name) values(10,'test')");
db.executeInsert("insert into TEST_CURRENT(id,name) values(10,'test')");
tm.commit();
} catch (Throwable e) {
try {
tm.rollback();
} catch (RollbackException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
}
測試結果說明:
為什麼啟用RW_TRANSACTION事務後性能要好于沒有啟用事務的情況呢,這是由于資料庫連接配接池的特性決定,連接配接池中的連接配接資源是一種共享資源,要想擷取一個db connection,首先要獲得pool中的共享鎖,擷取完畢後再釋放鎖。在沒有事務上下文的情況下,每個db操作都是一個獨立的事務,都會從db pool中擷取連接配接,是以擷取鎖的次數比較頻繁,這樣就會導緻性能下降;相反一個RW_TRANSACTION上下文中隻會擷取一個db connection,隻有一次擷取鎖的情況,性能要好很多。
影響持久層操作性能因素分析:
1.頻繁地申請連接配接池中連接配接會導緻性能降低
2.頻繁地釋放資料庫連接配接到連接配接池中也會導緻性能降低
3.開啟連接配接池中連接配接校驗特性會導緻新能降低
連接配接池連接配接在以下情況下會執行校驗邏輯:
a.申請連接配接(預設開啟),可以通過以下方式進行控制
<testOnBorrow>false</testOnBorrow>
b.釋放連接配接(預設關閉),可以通過以下方式進行控制(目前bboss沒有開放改配置開關,即使配置也無效)
<testOnReturn>false</testOnReturn>
c.空閑連接配接回收掃描操作(預設關閉),可以通過以下方式進行控制
<testWhileIdle>true</testWhileIdle>
同時我們也可以通過指定validationQuery屬性來控制執行校驗操作時是否執行一條指定的sql語句,來校驗連接配接的可用性,而且在執行的時候會占用共享鎖,這個性能開銷比較大。
我們可以不配置validationQuery屬性來提升系統性能
<!--
連結有效性檢查sql語句
-->
<validationQuery>select 1 from dual</validationQuery>
4.開啟強制回收長時間占用連接配接機制,會對性能有一定的影響,屏蔽方法:
<removeAbandoned>false</removeAbandoned>
removeAbandoned開關主要在開發環境下開啟,用來檢測是否有洩露的事務連結,并且在連接配接占用比較多的情況下,回收占用時間較長的連結,生産環境下必須将removeAbandoned設定為false。
上述4個因素也可以通過在程式設計過程采用資料庫事務來優化性能,将密集的資料操作包含在事務中,bboss資料庫事務開啟方法:
TransactionManager tm = new TransactionManager();
try {
tm.begin(tm.RW_TRANSACTION);
//db操作
tm.commit();
} catch (Throwable e) {
try {
tm.rollback();
} catch (RollbackException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
或者
TransactionManager tm = new TransactionManager();
try {
tm.begin();
//db操作
tm.commit();
} catch (Throwable e) {
try {
tm.rollback();
} catch (RollbackException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
詳細的資料庫事務請參考文檔
bbossgroups教育訓練.ppt中的事務管理部分
同時也可以參考另一篇文章《
bbossgroups持久層架構連結池配置優化政策之一 空閑連結回收配置》
5.補充說明
如果你的應用部署在weblogic或者websphere下面,盡量使用應用伺服器本身的資料源,bboss持久層中配置外部資料源的方法參考文檔《
bboss persistent通過jndi引用外部資料源(datasource)方法