oracle之 Got minus one from a read call 與 ORA-27154: post/wait create failed

張衝andy發表於2017-09-20

在部署應用的時候,有時候應用可以直接啟動,但偶爾應用卻無法啟動,報錯資訊是: 

java.sql.SQLRecoverableException: IO Error: Got minus one from a read call  如圖:

原因及解決方法

我有好幾個應用系統需要連線資料庫,測試發現如果這個應用在最開始啟動就不會報錯,如果是啟動了好幾個應用之後再啟動的話就會報錯了。
一個應用連線資料庫的時候是透過連線池的機制來連線的,資料庫用一個引數max-session來描述連線池的大小,而應用同樣也有一個引數,這個參數列示它連線資料庫連線池所佔用的最少資源,例如:總共有10個應用需要連線資料庫,如果每個應用連線資料庫的最小連線數為10,那麼10個應用總共會有100個連線(可以看做是執行緒數),這樣就要求資料庫連線池的max-session必須大於100,否則就會報“ Got minus one from a read call”的錯誤。 
因此,有兩種方法可以解決這個問題: 
(1)擴大資料庫連線池,這個需要系統資料庫管理員來協助完成 
(2)減小應用連線資料庫時需要的初始化連線數 
我的這個應用是java應用,關於資料庫的設定在配置檔案jdbc.properties裡面,內容如下:

jdbc.driverClass=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@nantianpaydb.baidupay.com:8002:ntpzn
jdbc.user=cif
jdbc.password=cif

#druid datasource
druid.initialSize=10
druid.minIdle=10
druid.maxIdle=100
druid.maxActive=500
druid.maxWait=30000
druid.timeBetweenEvictionRunsMillis=60000
druid.minEvictableIdleTimeMillis=300000
druid.validationQuery=SELECT 1 from dual
druid.testWhileIdle=true
druid.testOnBorrow=false
druid.testOnReturn=false
druid.poolPreparedStatements=true
druid.maxPoolPreparedStatementPerConnectionSize=20
druid.filters=wall,stat


其中

druid.initialSize=10


就是一個應用連線資料庫的初始化引數,只要將之調小即可解決問題。

擴充套件:如果由於調整了process 導致 資料庫啟動不來,報錯如下

ORA-27154: post/wait create failed
ORA-27300: OS system dependent operation:semget failed with status: 28
ORA-27301: OS failure message: No space left on device
ORA-27302: failure occurred at: sskgpcreates

確認 df -h 、free -m 儲存與記憶體充足情況下, 留意是不是 sem 訊號量設定不當

# cat /proc/sys/kernel/sem
250 32000 32 128
-- 與上面對應
# semaphores: semmsl, semmns, semopm, semmni

設定 SEMMSL
SEMMSL 核心引數用於控制每個訊號集合的最大訊號數。

Oracle 建議將 SEMMSL 設定為 init.ora 檔案(適用於 Linux 系統上所有資料庫)中的最大 PROCESS 例項引數設定再加上 10。此外,Oracle 建議將 SEMMSL 設定為不小於 100。

設定 SEMMNI

SEMMNI 核心引數用於控制整個 Linux 系統中訊號集的最大數量。Oracle 建議將 SEMMNI 設定為不小於 100。

設定 SEMMNS

SEMMNS 核心引數用於控制整個 Linux 系統中的訊號(而非訊號集)的最大數量。

Oracle 建議將 SEMMNS 設定為系統上每個資料庫的 PROCESSES 例項引數設定之和,加上最大的 PROCESSES 的兩倍,最後為系統上的每個 Oracle 資料庫加上 10。

使用以下計算式確定可以在 Linux 系統上分配的訊號的最大數量。它將是以下兩者中較小的一個值:

SEMMNS -or- (SEMMSL * SEMMNI) 

設定 SEMOPM

SEMOPM 核心引數用於控制每個 semop 系統呼叫可以執行的訊號運算元。

semop 系統呼叫(函式)能夠使用一個 semop 系統呼叫完成多個訊號的操作。一個訊號集可以擁有每個訊號集中最大數量的 SEMMSL,因此建議將 SEMOPM 設定為等於 SEMMSL。

Oracle 建議將 SEMOPM 設定為不小於 100。

設定訊號核心引數

最後,我們來看如何使用一些方法來設定所有訊號引數。在下文中,我想更改(增加)的唯一引數是 SEMOPM。所有其他的預設設定可以完全滿足我們的示例安裝。

可以透過使用以下命令直接更改 /proc 檔案系統 (/proc/sys/kernel/sem) 來更改所有訊號設定的預設設定,而不必重新引導計算機:
# sysctl -w kernel.sem="250 32000 100 128"

然後,透過將該核心引數插入到 /etc/sysctl.conf 啟動檔案中,您可以使這種更改永久有效:
# echo "kernel.sem=250 32000 100 128" >> /etc/sysctl.conf

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31383567/viewspace-2145198/,如需轉載,請註明出處,否則將追究法律責任。

相關文章