mysql多线程使用一个链接_探索多线程使用同一个数据库connection的后果
在項(xiàng)目中看到有用到數(shù)據(jù)庫(kù)的連接池,心里就思考著為什么需要數(shù)據(jù)庫(kù)連接池,只用一個(gè)連接會(huì)造成什么影響?(只用一個(gè)connection)?
1? 猜想:jdbc的事務(wù)是基于connection的,如果多線程共用一個(gè)connection,會(huì)造成多線程之間的事務(wù)相互干擾。(connection.setAutoCommit(false);//connection.commit())
2? 于是就模仿以下場(chǎng)景來(lái)做一個(gè)測(cè)試:
在多用戶請(qǐng)求的情況下,只用一個(gè)數(shù)據(jù)庫(kù)connection。
1)獲取connection工具類(lèi):
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ù)庫(kù)驅(qū)動(dòng)..");
e.printStackTrace();
}
}
/**
* 獲取數(shù)據(jù)庫(kù)連接實(shí)例
* @return
*/
public synchronized static Connection getInstance(){
if(conn==null){
try {
conn=DriverManager.getConnection(url,user, pwd);
conn.setAutoCommit(false);//設(shè)置為不自動(dòng)提交。。。
connectCount++;
System.out.println("連接數(shù)據(jù)庫(kù)次數(shù):"+connectCount);
} catch (SQLException e) {
System.out.println("連接數(shù)據(jù)庫(kù)失敗....");
e.printStackTrace();
}
}
return conn;
}
}
2) 業(yè)務(wù)接口實(shí)現(xiàn)類(lèi):
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)){//模仿某個(gè)線程執(zhí)行service某個(gè)方法中某個(gè)步驟出現(xiàn)異常
Thread.sleep(3000);//模仿當(dāng)前線程執(zhí)行時(shí)間較長(zhǎng)。。。。。
System.out.println("發(fā)生異常。。。。。");
System.out.println("記錄"+id+"插入失敗。。。。");
conn.rollback();? //出現(xiàn)異常事務(wù)回滾。。。
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)模擬用戶請(qǐng)求的線程類(lèi):
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) 測(cè)試類(lèi):
package jdbcPool.test;
import jdbcPool.thread.Request;
public class Main {
//兩百個(gè)線程并發(fā)訪問(wèn)同一個(gè)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é)果分析:
打印臺(tái)出現(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ù)庫(kù)中的表數(shù)據(jù):
id為1350的記錄竟然成功的添加進(jìn)數(shù)據(jù)庫(kù)了,造成這一現(xiàn)象的原因顯然是
在添加id為1350的記錄的線程遇到異常還沒(méi)有來(lái)得及數(shù)據(jù)回滾時(shí),
別的線程先調(diào)用了 connection.commit()方法,以至于把不該提交的數(shù)據(jù)提交到數(shù)據(jù)庫(kù)了。
6)? 總結(jié):在多線程的環(huán)境中,在不對(duì)connection做線程安全處理的情況下,使用單個(gè)connection會(huì)引起事務(wù)的混亂....影響jdbc事務(wù)的使用。。。
總結(jié)
以上是生活随笔為你收集整理的mysql多线程使用一个链接_探索多线程使用同一个数据库connection的后果的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 假冒金融APP盛行 百利好环球提醒您谨慎
- 下一篇: 余额宝是货币基金吗