程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Mybatis update數據庫逝世鎖之獲得數據庫銜接池期待

Mybatis update數據庫逝世鎖之獲得數據庫銜接池期待

編輯:關於JAVA

Mybatis update數據庫逝世鎖之獲得數據庫銜接池期待。本站提示廣大學習愛好者:(Mybatis update數據庫逝世鎖之獲得數據庫銜接池期待)文章只能為提供參考,不一定能成為您想要的結果。以下是Mybatis update數據庫逝世鎖之獲得數據庫銜接池期待正文


 比來進修測試mybatis,單個增刪改查都沒成績,最初應用mvn test的時刻發明了幾個成績:

1.update掉敗,緣由是數據庫逝世鎖

2.select期待,緣由是connection銜接池被用光了,須要期待

get:

1.要勇於摸索,保持就是成功。剛看到毛病的時刻直接懵逼,由於毛病完整看不出來,屬於框架外部報錯,在遲疑是否是直接睡

認為了,究竟也快12點了。最初照樣給我一點點找到成績地點了。

2.同上,要勇於去深刻你不懂得的代碼,勇於研討不懂的代碼。

3.間隔一個及格的碼農愈來愈遠了,由於越學越認為破綻百出,本身的代碼隨處都是坑。所以,必定要記載上去。

上面記載這兩個成績。

1.mysql數據庫逝世鎖

這裡,感激http://www.cnblogs.com/lin-xuan/p/5280614.html,我找到了謎底。在這裡,我照樣重現一下:

數據庫逝世鎖是事務性數據庫 (如SQL Server, MySql等)常常碰到的成績。除非數據庫逝世鎖成績頻仍湧現招致用戶沒法操作,普通情形下數據庫逝世鎖成績不嚴重。在運用法式中停止try-catch便可以。那末數據逝世鎖是若何發生的呢?

InnoDB完成的是行鎖 (row level lock),分為同享鎖 (S) 和 互斥鎖 (X)。

•同享鎖用於事務read一行。
•互斥鎖用於事務update或delete一行。

當客戶A持有同享鎖S,並要求互斥鎖X;同時客戶B持有互斥鎖X,並要求同享鎖S。以下情況,會產生數據庫逝世鎖。假如還不敷清晰,請看上面的例子。

雙開兩個mysql客戶端

客戶端A:

開啟事務,並鎖定同享鎖S 在id=12的時刻:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM blog WHERE id = 12 LOCK IN SHARE MODE;
+----+-------+-----------+
| id | name | author_id |
+----+-------+-----------+
| 12 | testA | 50 |
+----+-------+-----------+
1 row in set (0.00 sec)

客戶端B:

開啟事務,測驗考試刪除id=12:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> DELETE FROM blog WHERE id = 12;

刪除操作須要互斥鎖 (X),然則互斥鎖X和同享鎖S是不克不及相容的。所以刪除事務被放到鎖要求隊列中,客戶B壅塞。

這時候候客戶端A也想要刪除12:

mysql> DELETE FROM blog WHERE id = 12;
Query OK, 1 row affected (0.00 sec)

和參考文章分歧的是,竟然刪除勝利了,但客戶端B失足了:

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

因而,我測驗考試刪除13,這下都壅塞了:

我的mybatis測試代碼中,由於上一個測試沒有commit招致逝世鎖,commit後就ok了。在這裡,我想說,數據庫的器械全還給先生了,關於鎖和事務須要從新復習一下了。

2.Mybatis中datasource的數據庫銜接數

當我mvn test的時刻,我發明有個查詢的test打印日記:

2016-07-21 23:43:53,356 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction] - Opening JDBC Connection
2016-07-21 23:43:53,356 DEBUG [org.apache.ibatis.datasource.pooled.PooledDataSource] - Waiting as long as 20000 milliseconds for connection.

因而,果真等了一段時光後才履行勝利。跟蹤源碼,找到這處日記就明確了。起首,我這裡應用的數據庫銜接設置裝備擺設是mybatis默許的:

<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment> 
當數據庫銜接池的銜接數用光了以後就要等2s再去獲得:
while (conn == null) {
synchronized (state) {
if (!state.idleConnections.isEmpty()) {
// Pool has available connection
conn = state.idleConnections.remove(0);
if (log.isDebugEnabled()) {
log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
}
} else {
// Pool does not have available connection
if (state.activeConnections.size() < poolMaximumActiveConnections) {
// Can create new connection
conn = new PooledConnection(dataSource.getConnection(), this);
if (log.isDebugEnabled()) {
log.debug("Created connection " + conn.getRealHashCode() + ".");
}
} else {
// Cannot create new connection
PooledConnection oldestActiveConnection = state.activeConnections.get(0);
long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
if (longestCheckoutTime > poolMaximumCheckoutTime) {
// Can claim overdue connection
state.claimedOverdueConnectionCount++;
state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
state.accumulatedCheckoutTime += longestCheckoutTime;
state.activeConnections.remove(oldestActiveConnection);
if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
try {
oldestActiveConnection.getRealConnection().rollback();
} catch (SQLException e) {
log.debug("Bad connection. Could not roll back");
} 
}
conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);
oldestActiveConnection.invalidate();
if (log.isDebugEnabled()) {
log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
}
} else {
// Must wait
try {
if (!countedWait) {
state.hadToWaitCount++;
countedWait = true;
}
if (log.isDebugEnabled()) {
log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection.");
}
long wt = System.currentTimeMillis();
state.wait(poolTimeToWait);
state.accumulatedWaitTime += System.currentTimeMillis() - wt;
} catch (InterruptedException e) {
break;
}
}
}
}
if (conn != null) {
if (conn.isValid()) {
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(), username, password));
conn.setCheckoutTimestamp(System.currentTimeMillis());
conn.setLastUsedTimestamp(System.currentTimeMillis());
state.activeConnections.add(conn);
state.requestCount++;
state.accumulatedRequestTime += System.currentTimeMillis() - t;
} else {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");
}
state.badConnectionCount++;
localBadConnectionCount++;
conn = null;
if (localBadConnectionCount > (poolMaximumIdleConnections + 3)) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Could not get a good connection to the database.");
}
throw new SQLException("PooledDataSource: Could not get a good connection to the database.");
}
}
}
}
}

當銜接數少於10個的時刻回創立,跨越10個就會期待,否則就報錯。

以上所述是小編給年夜家引見的Mybatis update數據庫逝世鎖之獲得數據庫銜接池期待,願望對年夜家有所贊助,假如年夜家有任何疑問請給我留言,小編會實時答復年夜家的。在此也異常感激年夜家對網站的支撐!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved