我正在开展一个学校项目,我的团队必须确保数据的一致性和完整性,以及提高交易网站的性能。该网站使用JSP和JAVA编码。我们也在为我们的项目使用MySQL及其ndb集群。
首先,我已对使用100,175和250个虚拟用户的负载测试的预准备语句进行了实验。结果表明,重用预准备语句可以缩短响应时间和吞吐量。通过改进,我的意思是平均响应时间减少,最大吞吐量增加。
其次,我还使用连接池进行了实验,并对100,175和250个虚拟用户进行了相同的负载测试。同样,结果显示性能有所改善。只是一个附加信息,我使用c3p0作为连接池。
通过这些结果,我计划为交易网站使用预准备语句和连接池。同时,我们还会使用事务来确保数据的一致性和完整性。
目前,我实施预准备报表和交易的方式如下:
public class ExchangeBean {
private PreparedStatement psSelectFromBuy = null;
private PreparedStatement psSelectFromSell = null;
private PreparedStatement psInsertBuy = null;
private PreparedStatement psInsertSell = null;
private Connection tranDbConnection = null;
public ExchangeBean() {
reusePreparedStatements();
}
public void reusePreparedStatements() {
tranDbConnection = DbBean.getDBConnection();
dbConnection.setAutoCommit(false);
try {
psSelectFromBuy = dbConnection.prepareStatement("SELECT * FROM buy WHERE stock = ?" FOR UPDATE);
psSelectFromSell = dbConnection.prepareStatement("SELECT * FROM sell WHERE stock = ?" FOR UPDATE);
psInsertBuy = tranDbConnection.prepareStatement("INSERT INTO buy (userid, date, price, stock) VALUES (?, ?, ?, ?)")
psInsertSell = tranDbConnection.prepareStatement("INSERT INTO sell (userid, date, price, stock) VALUES (?, ?, ?, ?)");
} catch (Exception e) {
}
}
public boolean buy(//some parameters) {
try {
selectFromBuy(); //a method that contains psSelectFromBuy
psInsertBuy.clearParameters();
psInsertBuy.setInt(1, buy.getUserId());
psInsertBuy.setLong(2, buy.getDate().getTime());
psInsertBuy.setInt(3, buy.getPrice());
psInsertBuy.setString(4, buy.getStock());
psInsertBuy.executeUpdate();
//some other codes
psInsertBuy.commit();
} catch (Exception e) {
dbConnection.rollback();
}
}
public boolean sell(//some parameters) {
try {
selectFromSell(); //a method that contains psSelectFromSell
psInsertSell.clearParameters();
psInsertSell.setInt(1, sell.getUserId());
psInsertSell.setLong(2, sell.getDate().getTime());
psInsertSell.setInt(3, sell.getPrice());
psInsertSell.setString(4, sell.getStock());
psInsertSell.executeUpdate();
//some other codes
psInsertSell.commit();
} catch (Exception e) {
dbConnection.rollback();
}
}
}
注意:为简洁起见,此代码示例不完整;相当多的代码和逻辑不在其中。
基本上,我的方法是将预处理语句声明为类变量,然后在第一次调用类时实例化它们。
问题
我的方法是否正确?我觉得这不完全正确,因为我所有准备好的语句都与一个连接相关联。我担心如果多个用户同时尝试买卖,可能会出现问题,因为只使用了一个连接。但是,我不能关闭连接,否则我准备好的语句将在每次交易后关闭,因此不会被重用。此外,当我提交时,交易中涉及的所有准备好的语句应该一起提交,因此如果我只使用一个连接就会更容易。
您对如何使用连接池与预准备语句和事务有任何建议吗?我想在每次从池创建连接时将所有准备好的语句缓存到连接中。当连接用于买入或卖出时,该方法本身将禁用该连接上的自动提交,并在方法结束时再次启用自动提交。这种方法是否合适?或者我应该有两个连接池(一个用于非事务连接,一个用于事务连接)?
谢谢!