sql線程池
『壹』 如何設置sql server的最大工作線程
使用 max worker threads 選項可以配置可用於 Microsoft SQL Server 進程的工作線程數。SQL Server 使用 Microsoft Windows 2000 和 Windows Server 2003 操作系統的本機線程服務,以便使一個或多個線程支持 SQL Server 同時支持的每一個網路,另一個線程處理資料庫檢查點,而線程池則處理所有用戶。
https://msdn.microsoft.com/zh-cn/library/ms190219(SQL.90).aspx
『貳』 想問下Mysql和MSSQL在多線程下寫入或讀取數據是否起沖突
樓上的解釋不太對。多線程雖然是最終單cpu執行,但是cpu執行並不是1 次處理完1個線程才到第2個的,多線程處理時候,cpu把各線程再分成片段,處理完1線程第一片段就到線程2第1片段,如此循環。
至於樓主問題,沖突可能性是存在的,資料庫一般是並發只讀,如果有寫入,默認鎖表或者鎖行。此時排他寫操作。完畢以後解鎖。如果寫進程不幸鎖死或者過長,會導致其他線程無法寫入。因此,沖突發生的概率其實和寫過程復雜度相關,和並發寫請求多少相關,如果後台100個線程寫入的話,沖突幾率還是有的,如果調試能監控到拒絕寫入錯誤,建議單進程負責寫入,其他工作線程提交請求至寫入線程輪候輸入。解決寫入沖突問題。
『叄』 mysql資料庫每次查詢是一條線程嗎
MySQL的查詢使用的是線程池。當有大量請求並發訪問時,一定伴隨著資源的不斷創建和釋放,導致資源利用率低,降低了服務質量。線程池技術,預先會創建一定數量的線程,當有請求達到時,線程池分配一個線程提供服務,請求結束後,該線程又去服務其他請求。 通過這種方式,避免了線程和內存對象的頻繁創建和釋放,降低了服務端的並發度,減少了上下文切換和資源的競爭,提高資源利用效率。在MySQL早期的版本中,處理連接的方式是One-Connection-Per-Thread,即對於每一個資料庫連接,MySQL-Server都會創建一個獨立的線程服務,請求結束後,銷毀線程。再來一個連接請求,則再創建一個連接,結束後再進行銷毀。但是,這種方式在高並發情況下,會導致線程的頻繁創建和釋放。當然,通過thread-cache,我們可以將線程緩存起來,以供下次使用,避免頻繁創建和釋放的問題,但是無法解決高連接數的問題。One-Connection-Per-Thread方式隨著連接數暴增,導致需要創建同樣多的服務線程,高並發線程意味著高的內存消耗,更多的上下文切換(cpu cache命中率降低)以及更多的資源競爭,導致服務出現抖動。相對於One-Thread-Per-Connection方式,一個線程對應一個連接,Thread-Pool實現方式中,線程處理的最小單位是statement(語句),一個線程可以處理多個連接的請求。這樣,在保證充分利用硬體資源情況下(合理設置線程池大小),可以避免瞬間連接數暴增導致的伺服器抖動。
『肆』 Oracle資料庫和Sql server資料庫各有什麼優缺點
1.Oracle跨平台,SQL
Server只能運行在Windows上,而Windows能夠安裝的硬體是有限的,如Sun的Sparc伺服器不能安裝Windows,一些大型機、小型機也只能裝UNIX,在這些高端機器上就只能跑Oracle了,這註定了Oracle就是高端資料庫,而SQL
Server呢,中低端。
2.Oracle真正實現了行級鎖,SQL
Server也宣稱實現了行級鎖,但你實際去試,如果不加索引,其實是不行的。
3.Oracle因為有多版本數據的技術,讀寫操作不會相互等待,雖然SQL
Server
2005學習Oracle增加了snapshot機制,從而也引進了多版本數據(MySQL也有多版本數據機制,不能說一定是學習Oracle),但是實際效果感覺就是2個版本的數據,隔離級別為read
committed時候,讀寫不再相互等待,但是把隔離設置為Serializable還是會產生讀寫相互等待。
4.Oracle的事務日誌歸檔相當方便,而SQL
Server要用事務日誌備份來實現,而且還要配置自動作業,啟動agent服務。
5.Oracle的數據字典豐富,使得DBA容易判斷資料庫的各種情況,雖然SQL
Server
2005學習了Oracle的數據字典的特點,但從數量及方便程度上還是相差太多。個人感覺這是Oracle最人性化的地方。
6.Oracle的PL/SQL比SQL
Server的T-SQL功能強大很多。
7.Oracle的觸發器比SQL
Server的種類多幾種。
8.oracle的備份恢復原理相當簡單明了,備份就在操作系統上拷貝數據文件好了,恢復呢,再拷貝回來,數據是舊的,不怕,應用重做日誌好了。SQLServer呢,雖然原理在本質上還是這些,但操作起來麻煩多了,麻煩到讓你體會不到其本質。
9.Oracle資料庫啟動可以有多個階段,使得DBA可以在不同的情況下,通過啟動到特定的階段解決一些特殊問題,而SQLServer只要服務一啟動,所有資料庫就都打開了。
10.SQLServer給人的感覺是簡單易用,但是我要說,如果你繼續向前走,就會發現SQLServer的體系結構相當復雜(注意我這里是說的復雜),大體還是沿襲的Sybase的體系結構,這種復雜結構,估計很難有根本性的改變,而Oracle呢,時間越長你越會覺得其體系結構嚴謹,雖然開始會感覺很難。我的一個比喻,SQLServer是傻瓜相機(就是那些一兩千的小數碼),Oracle是單反相機(40D,5D,D300),如果你是入門者,那用傻瓜相機好了,在各種環境下拍攝,基本都過得去,用單反,光圈、快門都要自己設定,反倒不如傻瓜相機的效果,如果你是高手了,那傻瓜相機就很難得心應手了。
11.Oracle的書籍一般都比較深,隨便一說就是一大批,EpertOracle、PracticalOracle8i、Cost-basedOracle,SQLServer呢,恐怕只有那套InsideSQLServer了,雖然SQLServer的書籍數量比Oracle的多的多(特別是在國內),但多數都是stepbystep的入門書。
12.對比SQL*Plus與sqlcmd(或2000的osql,6.5的isql),sqlcmd的功能是太簡陋,差得太多了。
13.SQLServer的最大優點就是和Windows結合緊密,易用,但是要注意事情都是兩面的,這些優點可能導致其致命的缺點,例如易用,使得搞SQLServer的人可以不求甚解,有時候不求甚解是沒問題的,但是有時候不求甚解可能會造成災難,特別是對搞資料庫的人來說。不好意思,本來要說SQLServer的優點呢,最後也成了缺點了。
『伍』 啥時候會使用線程池
編者註:java中的線程池是運用場景最多的並發組件,幾乎所有需要非同步或並發執行任務的程序都可以使用線程池。
在開發過程中,合理地使用線程池能夠帶來至少以下幾個好處。
降低資源消耗:通過重復利用已創建的線程降低線程創建和銷毀造成的消耗。
提高響應速度:當任務到達時,任務可以不需要等到線程創建就能立即執行。
提高線程的可管理性:線程是稀缺資源,如果無限制地創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一分配、調優和監控。但是,要做到合理利用線程池,必須了解其實現原理。
代碼解耦:比如生產者消費者模式。
線程池實現原理
當提交一個新任務到線程池時,線程池的處理流程如下:
如果當前運行的線程少於corePoolSize,則創建新線程來執行任務(注意,執行這一步驟需要獲取全局鎖)。
如果運行的線程等於或多於corePoolSize,則將任務加入BlockingQueue。
如果無法將任務加入BlockingQueue(隊列已滿),則創建新的線程來處理任務(注意,執行這一步驟也需要獲取全局鎖)。
如果創建新線程將使當前運行的線程數超出maximumPoolSize,該任務將被拒絕,並調用相應的拒絕策略來處理(RejectedExecutionHandler.rejectedExecution()方法,線程池默認的飽和策略是AbortPolicy,也就是拋異常)。
ThreadPoolExecutor採取上述步驟的總體設計思路,是為了在執行execute()方法時,盡可能地避免獲取全局鎖(那將會是一個嚴重的可伸縮瓶頸)。在ThreadPoolExecutor完成預熱之後(當前運行的線程數大於等於corePoolSize),幾乎所有的execute()方法調用都是執行步驟2,而步驟2不需要獲取全局鎖。
線程池任務 拒絕策略包括 拋異常、直接丟棄、丟棄隊列中最老的任務、將任務分發給調用線程處理。
線程池的創建:通過ThreadPoolExecutor來創建一個線程池。
new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, timeUnit, runnableTaskQueue, handler);
創建一個線程池時需要輸入以下幾個參數:
corePoolSize(線程池的基本大小):當提交一個任務到線程池時,線程池會創建一個線程來執行任務,即使其他空閑的基本線程能夠執行新任務也會創建線程,等到線程池的線程數等於線程池基本大小時就不再創建。如果調用了線程池的prestartAllCoreThreads()方法,線程池會提前創建並啟動所有基本線程。
maximumPoolSize(線程池最大數量):線程池允許創建的最大線程數。如果隊列滿了,並且已創建的線程數小於最大線程數,則線程池會再創建新的線程執行任務。值得注意的是,如果使用了無界的任務隊列這個參數就沒什麼效果。
keepAliveTime(線程活動保持時間):線程池的工作線程空閑後,保持存活的時間。所以,如果任務很多,並且每個任務執行的時間比較短,可以調大時間,提高線程的利用率。
TimeUnit(線程活動保持時間的單位):可選的單位有天(DAYS)、小時(HOURS)、分鍾(MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)和納秒(NANOSECONDS,千分之一微秒)。
runnableTaskQueue(任務隊列):用於保存等待執行的任務的阻塞隊列。可以選擇以下幾個阻塞隊列。
- ArrayBlockingQueue:是一個基於數組結構的有界阻塞隊列,此隊列按FIFO(先進先出)原則對元素進行排序。
LinkedBlockingQueue:一個基於鏈表結構的阻塞隊列,此隊列按FIFO排序元素,吞吐量通常要高於ArrayBlockingQueue。靜態工廠方法Executors.newFixedThreadPool()使用了這個隊列。
SynchronousQueue:一個不存儲元素的阻塞隊列。每個插入操作必須等到另一個線程調用移除操作,否則插入操作一直處於阻塞狀態,吞吐量通常要高於LinkedBlockingQueue,靜態工廠方法Executors.newCachedThreadPool使用了這個隊列。
PriorityBlockingQueue:一個具有優先順序的無界阻塞隊列。
線程的狀態
在HotSpot VM線程模型中,Java線程被一對一映射到本地系統線程,Java線程啟動時會創建一個本地系統線程;當Java線程終止時,這個本地系統線程也會被回收。操作系統調度所有線程並把它們分配給可用的CPU。
thread運行周期中,有以下6種狀態,在 java.lang.Thread.State 中有詳細定義和說明:
// Thread類
public enum State {
/**
* 剛創建尚未運行
*/
NEW,
/**
* 可運行狀態,該狀態表示正在JVM中處於運行狀態,不過有可能是在等待其他資源,比如CPU時間片,IO等待
*/
RUNNABLE,
/**
* 阻塞狀態表示等待monitor鎖(阻塞在等待monitor鎖或者在調用Object.wait方法後重新進入synchronized塊時阻塞)
*/
BLOCKED,
/**
* 等待狀態,發生在調用Object.wait、Thread.join (with no timeout)、LockSupport.park
* 表示當前線程在等待另一個線程執行某種動作,比如Object.notify()、Object.notifyAll(),Thread.join表示等待線程執行完成
*/
WAITING,
/**
* 超時等待,發生在調用Thread.sleep、Object.wait、Thread.join (in timeout)、LockSupport.parkNanos、LockSupport.parkUntil
*/
TIMED_WAITING,
/**
*線程已執行完成,終止狀態
*/
TERMINATED;
}
線程池操作
向線程池提交任務,可以使用兩個方法向線程池提交任務,分別為execute()和submit()方法。execute()方法用於提交不需要返回值的任務,所以無法判斷任務是否被線程池執行成功。通過以下代碼可知execute()方法輸入的任務是一個Runnable類的實例。
threadsPool.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
}
});
submit()方法用於提交需要返回值的任務。線程池會返回一個future類型的對象,通過這個future對象可以判斷任務是否執行成功,通過future的get()方法來獲取返回值,future的get()方法會阻塞當前線程直到任務完成,而使用get(long timeout,TimeUnit unit)方法則會阻塞當前線程一段時間後立即返回,這時候有可能任務還沒有執行完。
Future<Object> future = executor.submit(harReturnValuetask);
try {
Object s = future.get();
} catch (InterruptedException e) {
// 處理中斷異常
} catch (ExecutionException e) {
// 處理無法執行任務異常
} finally {
// 關閉線程池
executor.shutdown();
}
合理配置線程池
要想合理配置線程池,必須先分析任務的特點,可以從以下幾個角度分析:
任務的性質:CPU密集型任務、IO密集型任務和混合型任務。
任務的優先順序:高、中和低。
任務的執行時間:長、中和短。
任務的依賴性:是否依賴其他系統資源,如資料庫連接。
性質不同的任務可以用不同規模的線程池分開處理。CPU密集型任務應配置盡可能少的線程,如配置Ncpu+1個線程的線程池。由於IO密集型任務線程並不是一直在執行任務,則應配置多一點線程,如2*Ncpu。混合型的任務,如果可以拆分,將其拆分成一個CPU密集型任務和一個IO密集型任務,只要這兩個任務執行的時間相差不是太大,那麼分解後執行的吞吐量將高於串列執行的吞吐量。如果這兩個任務執行時間相差太大,則沒必要進行分解。可以通過Runtime.getRuntime().availableProcessors()方法獲得當前設備的CPU個數。
優先順序不同的任務可以使用優先順序隊列PriorityBlockingQueue來處理。它可以讓優先順序高的任務先執行。執行時間不同的任務可以交給不同規模的線程池來處理,或者可以使用優先順序隊列,讓執行時間短的任務先執行。依賴資料庫連接池的任務,因為線程提交SQL後需要等待資料庫返回結果,等待的時間越長,則CPU空閑時間就越長,那麼線程數應該設置得越大,這樣才能更好地利用CPU。
線程池中線程數量未達到coreSize時,這些線程處於什麼狀態?
這些線程處於RUNNING或者WAITING,RUNNING表示線程處於運行當中,WAITING表示線程阻塞等待在阻塞隊列上。當一個task submit給線程池時,如果當前線程池線程數量還未達到coreSize時,會創建線程執行task,否則將任務提交給阻塞隊列,然後觸發線程執行。(從submit內部調用的代碼也可以看出來)
ScheledThreadPoolExecutor
ScheledThreadPoolExecutor繼承自ThreadPoolExecutor。它主要用來在給定的延遲之後運行任務,或者定期執行任務。
ScheledThreadPoolExecutor的功能與Timer類似,但
ScheledThreadPoolExecutor功能更強大、更靈活。Timer對應的是單個後台線程,而
ScheledThreadPoolExecutor可以在構造函數中指定多個對應的後台線程數。
ScheledThreadPoolExecutor繼承自ThreadPoolExecutor,
ScheledThreadPoolExecutor和ThreadPoolExecutor的區別是,ThreadPoolExecutor獲取任務時是從BlockingQueue中獲取的,而
ScheledThreadPoolExecutor是從DelayedWorkQueue中獲取的(注意,DelayedWorkQueue是BlockingQueue的實現類)。
ScheledThreadPoolExecutor把待調度的任務(ScheledFutureTask)放到一個DelayQueue中,其中ScheledFutureTask主要包含3個成員變數:
sequenceNumber:任務被添加到ScheledThreadPoolExecutor中的序號;
time:任務將要被執行的具體時間;
period:任務執行的間隔周期。
ScheledThreadPoolExecutor會把待執行的任務放到工作隊列DelayQueue中,DelayQueue封裝了一個PriorityQueue,PriorityQueue會對隊列中的ScheledFutureTask進行排序,具體的排序比較演算法實現如下:
ScheledFutureTask在DelayQueue中被保存在一個PriorityQueue(基於數組實現的優先隊列,類似於堆排序中的優先隊列)中,在往數組中添加/移除元素時,會調用siftDown/siftUp來進行元素的重排序,保證元素的優先順序順序。
static class DelayedWorkQueue extends AbstractQueue<Runnable>
implements BlockingQueue<Runnable> {
private static final int INITIAL_CAPACITY = 16;
private RunnableScheledFuture<?>[] queue =
new RunnableScheledFuture<?>[INITIAL_CAPACITY];
private final ReentrantLock lock = new ReentrantLock();
private int size = 0;
private Thread leader = null;
private final Condition available = lock.newCondition();
}
從DelayQueue獲取任務的主要邏輯就在take()方法中,首先獲取lock,然後獲取queue[0],如果為null則await等待任務的來臨,如果非null查看任務是否到期,是的話就執行該任務,否則再次await等待。這里有一個leader變數,用來表示當前進行awaitNanos等待的線程,如果leader非null,表示已經有其他線程在進行awaitNanos等待,自己await等待,否則自己進行awaitNanos等待。
// DelayedWorkQueue
public RunnableScheledFuture<?> take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
RunnableScheledFuture<?> first = queue[0];
if (first == null)
available.await();
else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return finishPoll(first);
first = null; // don't retain ref while waiting
if (leader != null)
available.await();
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
available.awaitNanos(delay);
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && queue[0] != null)
available.signal();
lock.unlock();
}
}
獲取到任務之後,就會執行task的run()方法了,即ScheledFutureTask.run():
public void run() {
boolean periodic = isPeriodic();
if (!canRunInCurrentRunState(periodic))
cancel(false);
else if (!periodic)
ScheledFutureTask.super.run();
else if (ScheledFutureTask.super.runAndReset()) {
setNextRunTime();
reExecutePeriodic(outerTask);
}
}
推薦閱讀:
JMM Java內存模型
happens-before那些事兒
為什麼說LockSupport是Java並發的基石?
責任鏈的2種實現方式,你更pick哪一種
2閱讀
『陸』 SQL Server的線程池,內存池和連接池有什麼區別和關系
網上找了寫資料:�0�2資料庫連接池: �0�2�0�2�0�2�0�2�0�2 �0�2�0�2�0�2�0�2 資料庫連接是一種關鍵的有限的昂貴的資源,這一點在多用戶的網頁應用程序中體現得尤為突出。 �0�2�0�2 �0�2 一個資料庫連接對象均對應一個物理資料庫連接,每次操作都打開一個物理連接,使用完都關閉連接,這樣造成系統的 性能低下。 資料庫連接池的解決方案是在應用程序啟動時建立足夠的資料庫連接,並講這些連接組成一個連接池( 簡單說:在一個「 池」里放了好多半成品的資料庫聯接對象),由應用程序動態地對池中的連接進行申請、使用和釋放。對於多於連接池中連接數的並發請求,應該在請求隊列中排隊等待。並且應用程序可以根據池中連接的使用率,動態增加或減少池中的連接數。 �0�2�0�2 �0�2連接池技術盡可能多地重用了消耗內存地資源,大大節省了內存,提高了伺服器地服務效率,能夠支持更多的客戶服務。通過使用連接池,將大大提高程序運行效率,同時,我們可以通過其自身的管理機制來監視資料庫連接的數量、使用情況等。 �0�2�0�2�0�2 1) 最小連接數是連接池一直保持的資料庫連接,所以如果應用程序對資料庫連接的使用量不大,將會有大量的資料庫連接資源被浪費; �0�2�0�2�0�2 2) 最大連接數是連接池能申請的最大連接數,如果資料庫連接請求超過此數,後面的資料庫連接請求將被加入到等待隊列中,這會影響之後的資料庫操作。 �0�2線程池�0�2SQL Server 維護一個操作系統線程池,以便執行從客戶端送達的成批 SQL 語句。在 Microsoft Windows NT�0�3 上,如果伺服器的 lightweight pooling 配置選項設為 1,則 SQL Server 不再維護線程,轉而維護一個纖程池;纖程使用比線程更少的資源。使用線程池或纖程池,可以使 SQL Server 在同時執行多個 SQL 語句時優化處理時間分配。該池中的線程或纖程共同作為工作線程。 �0�2工作線程數是由伺服器配置選項 max worker threads 控制的。默認值為 255 而且幾乎不需要更改。 當從客戶端收到一批 Transact-SQL 語句時,如果現有的工作線程空閑,就會分配它來執行這個批處理。如果沒有空閑的現有工作線程而且工作線程數少於 max worker threads,那麼就會分配一個新的工作線程。如果沒有空閑的工作線程而且已經達到 max worker threads,那麼新的批處理就要一直等到現有工作線程完成其當前批處理任務而空閑為止。當工作線程數達到 max worker threads 時,SQL Server 顯示如下消息:工作線程限制 255 已經達到。 �0�2對所有工作線程進行分配,並不意味著 SQL Server 的性能會降低。通常,新的批處理等待空閑線程只需要很短的時間。分配更多的線程可能會降低性能,因為增加的工作需要在線程之間協調資源。很多在生產狀態運行的 SQL Server 系統都會達到這樣的狀態,而且以非常高的性能級別運行。 �0�2內存池內存池的思想通過這個池字表露無疑,應用程序可以通過系統的內存分配調用預先一次性申請適當大小的內存作為一個內存池,之後應用程序自己對內存的分配和釋放則可以通過這個內存池來完成。
『柒』 mysql資料庫線程池問題,為什麼總是報錯Cannot create PoolableConnectionFactory
一般這種情況可能的原因有這幾種:
1. 可能連接超過mysql設置的上限(你的應該沒超)
2. 程序問題,建立了連接不關閉(這個有可能,看看你的session)
3. 在沒有使用連接池的情況下,每次都建立一個新的連接到資料庫(即使每次操作完畢都及時准確的close了),但是由於可能建立到資料庫連接的頻率很高(比如在for循環里),那麼會迅速建立大量的tcp連接到mysql的指定埠,OS在關閉tcp連接是有一定的延遲的,也是有一定數量限制的,所以就會出現無法連接的情況(connection refused)。
-------------------------------------
我個人感覺設置最大連接數可能用處不大,因為默認的是100,你說剛10個就出問題~所以我覺得可能還是和系統有關系,因為你說刷新的不頻繁就不會報錯~
不過你到可以先試試看~萬一能行更好不是~
還有啊,你可以找別的機器試驗下,在別人的電腦上做下測試~