mysql多线程使用一个链接_探索多线程使用同一个数据库connection的后果
在項目中看到有用到數(shù)據(jù)庫的連接池,心里就思考著為什么需要數(shù)據(jù)庫連接池,只用一個連接會造成什么影響?(只用一個connection)?
1? 猜想:jdbc的事務是基于connection的,如果多線程共用一個connection,會造成多線程之間的事務相互干擾。(connection.setAutoCommit(false);//connection.commit())
2? 于是就模仿以下場景來做一個測試:
在多用戶請求的情況下,只用一個數(shù)據(jù)庫connection。
1)獲取connection工具類:
package jdbcPool.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class ConnectorUtil {
public static final String user="root";
public static final String pwd="123456";
public static final String driver="com.mysql.jdbc.Driver";
public static final String url ="jdbc:mysql://localhost:3306/test";
private static Connection conn;
private static int connectCount=0;
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
System.out.println("找不到數(shù)據(jù)庫驅(qū)動..");
e.printStackTrace();
}
}
/**
* 獲取數(shù)據(jù)庫連接實例
* @return
*/
public synchronized static Connection getInstance(){
if(conn==null){
try {
conn=DriverManager.getConnection(url,user, pwd);
conn.setAutoCommit(false);//設置為不自動提交。。。
connectCount++;
System.out.println("連接數(shù)據(jù)庫次數(shù):"+connectCount);
} catch (SQLException e) {
System.out.println("連接數(shù)據(jù)庫失敗....");
e.printStackTrace();
}
}
return conn;
}
}
2) 業(yè)務接口實現(xiàn)類:
package jdbcPool.business;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import jdbcPool.util.ConnectorUtil;
public class StudentService {
private Connection conn;
private static StudentService studentService;
private StudentService(){
conn=ConnectorUtil.getInstance();
}
public static synchronized? StudentService getInstance(){
if(studentService==null){
studentService=new StudentService();
}
return studentService;
}
public void insert(String id,String name,String no) throws Exception {
String addStr ="insert into student(id,name,no) values('"+id+"','"+name+"','"+no+"')";
Statement statement=null;
try {
statement = conn.createStatement();
statement.execute(addStr);
if("1350".equals(id)){//模仿某個線程執(zhí)行service某個方法中某個步驟出現(xiàn)異常
Thread.sleep(3000);//模仿當前線程執(zhí)行時間較長。。。。。
System.out.println("發(fā)生異常。。。。。");
System.out.println("記錄"+id+"插入失敗。。。。");
conn.rollback();? //出現(xiàn)異常事務回滾。。。
throw new Exception();
}else{
conn.commit();
System.out.println("記錄"+id+"插入成功。。。。");
}
} catch (SQLException e) {
System.out.println("創(chuàng)建statement失敗");
e.printStackTrace();
}finally{
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
3)模擬用戶請求的線程類:
package jdbcPool.thread;
import jdbcPool.business.StudentService;
public class Request implements Runnable{
private String id;
public Request(String id) {
this.id=id;
}
@Override
public void run() {
//模仿service的單例模式
try {
StudentService.getInstance().insert(this.id, "name"+id, "no"+id);
} catch (Exception e) {
e.printStackTrace();
}
}
}
4) 測試類:
package jdbcPool.test;
import jdbcPool.thread.Request;
public class Main {
//兩百個線程并發(fā)訪問同一個connection
public static void main(String[] args){
for(int i=1300;i<1500;i++){
Thread th=new Thread(new Request(String.valueOf(i)));
th.start();
}
}
}
5)結(jié)果分析:
打印臺出現(xiàn)的結(jié)果:
記錄1489插入成功。。。。
記錄1490插入成功。。。。
記錄1491插入成功。。。。
記錄1495插入成功。。。。
記錄1492插入成功。。。。
記錄1493插入成功。。。。
記錄1494插入成功。。。。
記錄1496插入成功。。。。
記錄1497插入成功。。。。
記錄1498插入成功。。。。
記錄1499插入成功。。。。
記錄1300插入成功。。。。
發(fā)生異常。。。。。
記錄1350插入失敗。。。。
java.lang.Exception
at jdbcPool.business.StudentService.insert(StudentService.java:38)
at jdbcPool.thread.Request.run(Request.java:18)
at java.lang.Thread.run(Unknown Source)
數(shù)據(jù)庫中的表數(shù)據(jù):
id為1350的記錄竟然成功的添加進數(shù)據(jù)庫了,造成這一現(xiàn)象的原因顯然是
在添加id為1350的記錄的線程遇到異常還沒有來得及數(shù)據(jù)回滾時,
別的線程先調(diào)用了 connection.commit()方法,以至于把不該提交的數(shù)據(jù)提交到數(shù)據(jù)庫了。
6)? 總結(jié):在多線程的環(huán)境中,在不對connection做線程安全處理的情況下,使用單個connection會引起事務的混亂....影響jdbc事務的使用。。。
總結(jié)
以上是生活随笔為你收集整理的mysql多线程使用一个链接_探索多线程使用同一个数据库connection的后果的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 假冒金融APP盛行 百利好环球提醒您谨慎
- 下一篇: 余额宝是货币基金吗