插入報(bào)錯(cuò) SQLAllocHandle {HY000}
問題場景
應(yīng)用使用 ORM 開啟事務(wù),批量插入語句,起初正常,一定條數(shù)之后開始報(bào)錯(cuò):
SQLAllocHandle: {HY000} Stmt handle to the limit the number of statements or system of memory
解決方案
首先查看下報(bào)錯(cuò)中提到的兩個(gè)相關(guān)參數(shù) statements 和 memory 的當(dāng)前值:
SQL> select name,type,value,description from v$parameter where name in ('memory_pool', 'max_session_statement');
+------------------------+--------------+--------------+--------------------------------------------------------+
| name | TYPE | VALUE | description |
+------------------------+--------------+--------------+--------------------------------------------------------+
| MEMORY_POOL | IN FILE | 200 | Memory Pool Size In Megabyte |
| MAX_SESSION_STATEMENT | SYS | 100 | Maximum number of statement handles for each session |
+------------------------+--------------+--------------+--------------------------------------------------------+
SQLRowCount returns 2
2 rows fetched
可以看到 memory pool 只有 200M,session statement 也只有 100 條,都太小了,我們擴(kuò)大這兩個(gè)參數(shù)。
達(dá)夢中的參數(shù)類型(type)說明
IN FILE:靜態(tài)參數(shù)。只能修改 ini 文件,修改后重啟DB才能生效,為系統(tǒng)級參數(shù),生效后會影響所有的會話。
SYS和SESSION:ini 文件和內(nèi)存同時(shí)可修改,修改后即時(shí)生效。其中,SYS為系統(tǒng)級參數(shù),修改后會影響所有的會話;SESSION 為會話級參數(shù),服務(wù)器運(yùn)行過程中被修改時(shí),之前創(chuàng)建的會話不受影響,只有新創(chuàng)建的會話使用新的參數(shù)值。
READ ONLY:DB在運(yùn)行過程中,手動(dòng)參數(shù)不能被修改,靜態(tài)和動(dòng)態(tài)參數(shù)可以修改。
可以看出 memory pool 必須通過 ini 文件 修改,而要讓 session statement 永久生效(不要在重啟后就又變回去)也要在 ini 文件 中修改,所以我們找到文件所在路徑,備份后修改這兩個(gè)參數(shù)為自己需要的值:
root@Kylin:/opt/dmdbms/data/tinaliu# cat /opt/dmdbms/data/tinaliu/dm.ini | grep -E "MEMORY_POOL|MAX_SESSION_STATEMENT"
MEMORY_POOL = 4096 #Memory Pool Size In Megabyte
MAX_SESSION_STATEMENT = 5000 #Maximum number of statement handles for each session
順便說一句,如果只修改 session statement 是可以使用語句直接操作的:
SQL> alter system set 'max_session_statement' = 5000;
SQLRowCount returns 0
測試發(fā)現(xiàn):本次卡住我們的,正是參數(shù) max_session_statement。那為什么我們的程序,要由這么多的句柄支撐呢?
我們改小句柄數(shù)(100),分別對以下語句進(jìn)行測試:
- 普通插入:insert ???? ??
- 查詢
last_insert_id:select scope_identity() ???? ??(第101條報(bào)錯(cuò)) - 普通查詢:select * from test.tbl_test; ???? ?? (第101條報(bào)錯(cuò))
經(jīng)過簡單的測試,我們可以初步判斷:句柄數(shù)max_session_statement是用于限制查詢結(jié)果集的。
那么這個(gè)限制在什么維度生效?
我們進(jìn)行以下測試:
- 同一個(gè)session中,執(zhí)行200條查詢語句,每條單獨(dú)提交??????
- 同一個(gè)事務(wù)中,執(zhí)行200條查詢語句,統(tǒng)一提交 ??????(第101條報(bào)錯(cuò))
經(jīng)過測試,我們可以得出結(jié)論:句柄數(shù)max_session_statement是用于限制在一個(gè)事務(wù)中查詢結(jié)果集個(gè)數(shù)的。
我們將此參數(shù)修改為 5000。畢竟,再大些的事務(wù),就一定要拆分了。