前言
在單一的應用環境或業務相對簡單的系統下,系統性能問題,瓶頸所在往往是不言自明,解決問題的前提—— 定位問題是比較容易解決的, 但在一個復雜的應用環境下, 各應用系統對系統資源往往是一種共享和競爭的關系,而且應用系統之間也可能存在著共生或制約的關系, 資源利益的均衡往往是此消彼長, 而這種環境下的應用系統一旦出現資源競爭,系統的瓶頸往往難以斷定,甚至會發生不同應用設計人員之間互相推諉責任的扯皮現象,本文僅就此問題對Linux 平臺下各應用系統對ORACLE 數據庫的使用情況作一探討, ORACLE 數據庫的 TUNING 不是一個可以一言以蔽的主題, 本文無意概全,內容僅涉及問題的定位及各應用對數據庫資源的共享與競爭問題。
本文試驗及問題取證的環境
RedHat6.1 Web server(Apache1.3.9+PHP4.0)+Client/Server(Pro*C) 之 Server 端
RedHat6.2 + Oracle8.1.6.1.0
RedHat7.1 Web server(Apache1.3.20+PHP4.06) + Oracle8.1.7.0.0
為方便問題的討論,應用系統已做簡化,競爭方僅包括一個 Pro*C 的 daemon 程序作為 C/S 模式的服務端,和由 Apache+PHP 所支持的 WEB 網站業務。
1. 單個 SQL 語句的處理
首先,最簡單的情況莫過于單個 SQL 語句的分析,SQL 語句的優化也是數據庫優化的一個最直接最立竿見影的因素。 SQL 語句的性能監控從監控工具來說大致可分為由高級語言提供和由 ORACLE 本身提供,高級語言以典型的應用 C 語言和 WEB 開發語言 PHP 為例,C 語言中可以用 gettimeofday 函數來在某一數據庫操作之前和之后分別獲取一個時間值,將兩個時間值之差做為衡量該數據庫操作的效率,在 PHP 中,也可以用 gettimeofday, 操作方法當然與 C 語言中有所不同。 當然,PHP 中也有其它一些函數可以達到同樣的時間精度,關于時間精度的考慮,不能簡單以大小衡量微秒級的時間數值,因為時鐘中斷的時間間隔從根本上決定了時間計算所能達到的精度,此外,操作系統本身對進程的時間片分配,及進程切換的開銷等因素也在一定程度上影響時間數據的意義。 所以,以下時間的計算最理想的情況是對同一操作在盡可能避免緩存的情況下進行多次的循環操作,取總的時間值加以平均,從而得到比較接近真實情況的時間值。
C 語言的例子
#define TV_START 0
#define TV_END 1
int how_long(int cmd, char *res);
struct CMD_TIME{
int times;
/* times oclearcase/" target="_blank" >ccured within specified package number */
struct timeval time;
/* total time consumed by the cmd */
};
void foo()
{
int id;
how_long(TV_START, NULL);
EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL WHENEVER NOT FOUND CONTINUE;
EXEC SQL select user_id into :id from users where name='slimzhao';2;
how_long(TV_END, time_consume);
puts(time_consume);
}
int how_long(int cmd, char *res)
/* return value: -1 error, 0 sucess,res: 20 bytes is enough */
{
static struct timeval before, after;
if(cmd == TV_START) {
gettimeofday(&before, NULL);
return 0;
} else if(cmd == TV_END) {
gettimeofday(&after, NULL);
if(res) {
if(after.tv_usec > before.tv_usec) {
sprintf(res, "%ld %ld", after.tv_sec - before.tv_sec,
after.tv_usec - before.tv_usec);
} else {
sprintf(res, "%ld %ld",
after.tv_sec - before.tv_sec - 1,
1000000 + after.tv_usec - before.tv_usec);
}
}
return 0;
} else {
return -1;
}
}