• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            tbwshc

            tbw

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              95 Posts :: 8 Stories :: 3 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(4)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            #

            摘要:本文主要講述了使用DBGird等ActiveX控件來顯示Access數據庫記錄數據的一般方法。
             
              關鍵字:DBGird控件、ActiveX、Access數據庫

              一、 引言

              隨著數據庫技術的進一步發展,我們在生活、辦公時越來越多地同各式各樣的數據庫前臺程序打著交道,這就要求數據庫前臺程序必須擁有良好的人機界面,使用戶能有一種好的心情方便的同程序進行交互。Microsoft 的Office系列產品之所以能得到廣泛的認同,也是與其良好的人機界面分不開的。數據庫最基本的單位--表包含有若干條數據記錄,而每一條記錄又包含有許多的字段,如何能方便、美觀的將這些數據記錄顯示給用戶,并能方便實用的同用戶進行交互操作便成為一個程序能否為人接受的重要因素了。Microsoft的Access 97/2000在這方面就做的相當不錯,用一個網格式表單容納了表中所有的數據,顯得清晰簡潔。而我們在用Visual C++開發的數據庫前臺程序中如要實現類似的表格就不得不借助于提供的ActiveX控件--DBGrid Control來實現,因為自己重新開發類似的功能無疑是比較困難而又煩瑣的。本文著重對該控件的使用做了介紹。

              二、 程序的設計實現

              本程序采用ODBC接口同Access 2000數據源相連,并將數據庫中的記錄數據通過網格的形式顯示給用戶,并能完成同Access表單類似的諸如添加記錄、刪除記錄等功能。

              在開始編制程序之前首先要通過控制面板的32位ODBC數據源設置我們待操作的后臺Access數據源,建立名稱為"雇員"的系統DSN,并將其指向Employee.mdb。為簡單計,數據庫中有一個"雇員表",內含5個字段:"雇員ID","tb雇員姓名"、"所在部門","職務","備注"等,并預先填充幾條記錄備用。

              在用VC創建工程時,需要在第二步確認提供了對ActiveX控件的支持。需要有后臺數據庫的支持,并通過"DataSource"按扭選擇剛才注冊過的ODBC數據源。此時編譯運行程序,通過工具條上的數據庫導航條可以移動數據庫的記錄指針,說明此時已經同數據庫建立了連接,但由于沒有控件(編輯框或其他)同數據庫的字段相棒定,此時還無法顯示數據庫中的記錄。我們先插入網格控件DBGrid Control,方法如下:

              1)選擇菜單->Project->Add to Project->Components and Controls Gallery

              2)在部件選擇對話框中進入Registered ActiveX Controls

              3)選擇DBGrid Control,單擊Insert按鈕,確認后對類進行配置(可以按默認),我們不做任何修改單擊OK按鈕,插入完成。

              在VC工作區的ResourceView中可以如同使用標準控件一樣將剛添加來的DBGird網格控件拖入到對話框中,并對其屬性進行設置。下面將主要的屬性列表如下:

            屬性名稱 說明
            Caption 雇員表 設定DBGird控件的網格標題
            AllowAddNew True 是否允許添加記錄
            AllowDelete True 是否允許刪除記錄
            AllowDelete True 是否允許更新記錄
            ColumnHeaders True 是否顯示每列的標題
            DefColWidth 100 設定每列的寬度
            RowHeight 11 設定每行高度
            DataSource <Not bound to a DataSource> 設定綁定的數據源
            BackColor 0x8000000E 設定網格的背景色

              再次運行程序,可以看到類似Access表格風格的DBGird控件以按我們的屬性設定顯示了出來,但并沒有數據庫記錄的顯示,而且我們注意到剛才設定數據源屬性DataSource時,下拉選項只有<Not bound to a DataSource>一項,而并沒有我們所希望的ODBC數據源"雇員"的存在。所以我們還要繼續添加一些輔助的控件來完成同數據庫源的綁定。用同插入DBGird控件一樣的步驟,插入Microsoft RemoteData Control控件,同樣也要對其屬性進行設置:

            屬性名稱 說明
            ID IDC_REMOTEDATACTL1 控件ID
            Caption 人事管理系統--雇員表 設定導航條的標題
            UserName   由于沒有指定用戶及密碼,設為空
            Password   同上
            SQL SELECT * FROM "雇員表" 待執行的SQL結構化查詢語言

              在RemoteData控件里用SQL語言將ODBC數據源的"雇員表"打開并選取里面的所有字段,也即顯示表里的所有記錄信息。這時再打開DBGird控件的DataSource屬性就會發現下拉條里多了一個"IDC_REMOTEDATACTL1",正是RemoteData的ID號。此次編譯運行程序就在網格控件內顯示了數據源指定表的所有記錄信息,而且可以方便的添加、刪除記錄以及調整字段尺寸等。具體如圖所示:


              運行結果表明,在RemoteData控件的中介作用下實現了DBGird控件同ODBC數據源之間的交互。該程序設計實現過程是可靠、實用的。

              小結

              DBGrid數據網格控件以其短小精悍而深受大家的喜愛,,本文將在VC下使用DBGrid的具體步驟和方法作了簡要地介紹。其它類似的表格控件也可以大致參考這個過程,希望本文能有所啟迪與幫助。在Windows 2000 Professional下,由Microsoft Visual C++ 6.0編譯測試通過。后臺數據源為Microsoft Access 2000。
            posted @ 2012-08-05 14:29 tbwshc| 編輯 收藏

            前言

            在許多視窗應用軟件中,通常要在屏幕上同時顯示若干個子視窗,以顯示同一個文檔的不同部分,或者是在每個視窗中分別顯示不同文檔的內容。為了實現多視窗界面,可以采用MDI(Multiple Document Interface)的多文檔模式進行處理,但是多文檔的應用程序設計與維護相對于單文檔的應用程序而言比較復雜。而且,如果要在屏幕上同時顯示多個子視窗,通常要利用視窗重疊函數進行管理,每個子視窗的位置往往需要用鼠標人為設定,過多的人為干預降低了程序使用的效率。因此,如果能對單文檔視窗做適當的分裂,無疑程序使用者將可以得到更易于操作的接口,數據的顯示也更加直觀和方便。本文通過對單文檔視窗的靜態分裂原理進行分析,實現上述要求。

            二分裂視窗的類型

            視窗的分裂可分為兩種類型,一是動態分裂,二是靜態分裂。動態分裂可以讓使用者通過拖曳分裂方塊的使用,將視窗分裂。但是,動態分裂最多只可以將視窗分裂為2×2個子視窗,不能進行混合分裂視窗,所有子視窗的屬性和父視窗都是一樣的,而且子視窗的數據通常來源于同一處。而靜態分裂,使用者除了可以調整子視窗的大小和進行混合分裂視窗外,最多可將視窗分裂為16×16個子視窗,每個子視窗可以有各自不同的視圖類(CView),各個子視窗顯示的數據可以來自于不同的數據源。不論是要創建動態分裂視窗還是靜態分裂視窗,都必須要利用MFC的CSplitterWnd類別來完成視窗的分裂。

            混合靜態分裂視窗的實現

            混合分裂視窗是指在子視窗中進行視窗的再分裂。在MFC的框架下,混合分裂視窗必須完成三件工作:

            ⑴在視窗框架類別中定義CSplitterWnd控件為其屬性(數據成員)。

            ⑵重載視窗框架類別中的OnCreateClient函數(CFrameWnd::OnCreateClient),建立靜態分裂子視窗,為靜態分裂子視窗填充視圖。

            ⑶建立維持各子視窗同步更新的機制。

            首先,利用MFC AppWizard生成一個單文檔應用程序,在應用程序的CMainFrame類別中聲明CSplitterWnd類別的數據成員。

            其次,重載CMainFrame類別中的OnCreateClient(LPCREATESTRUCT,CCreateContext* pContext)函數。在該函數中利用CsplitterWnd類別的構造函數Create Static(CWnd *pParentWnd,int nRows,int nCols,DWORD dwstyle,UINT nID) 創建混合靜態分裂子視窗,即在Create Static分裂出的子視窗中利用CsplitterWnd類別的控件再一次分裂視窗。

            Create Static函數的參數含義為:

            ·pParentWnd是準備建立靜態分裂視窗的視窗框架控件的指針;

            ·nRows和nCols是準備建立靜態分裂視窗行數(nRows)與列數(nCols)

            因此,創建的靜態分裂子視窗個數為nRows × nCols個,這兩個參數最小不得小于0,最大不可超過16;dwstyle是設定子視窗的形式;nID靜態分裂的代號(ID),此代號預設為AFX_IDW_PANE_FIRST,若靜態分裂視窗位于另一個分裂視窗內時,不可以使用默認值,可以利用CsplitterWnd類別的成員函數IdFromRowCol(int row,int col)獲得。利用CsplitterWnd類別的成員函數Create View (int row,int col,CruntimeClass* pViewClass,SIZE sizeinit,CcreateContext* pContext) 為靜態分裂子視窗填充視圖,在將視圖與子視窗關聯時必須先完成子視窗的創建。

            Create View函數的參數含義為:

            ·row和col是指定準備建立View控件的子視窗,其指定的方式是以表示該子視窗所在的行列位置;

            ·pViewClass是指定用于建立子視窗View控件的View類別,該類別需要被聲明為Run-Time類別;

            ·Sizeini是View控件的起始大小;pContext是一個指向記錄應用程序所使用的視窗框架控件、Document控件,以及View控件之變量的指針,此參數在CMainFrame::OnCreateClient函數被調用時傳入,再由該tb函數傳遞給此函數。

            ·CsplitterWnd類別的成員函數SetColumnInfo(int col,int cxIdeal,int cxMin)和SetRowInfo(int row,int cyIdeal,cyMin)為設置子視窗的寬度和高度,參數cxIdeal和cxMin是指定子視窗的寬度和最小寬度,cyIdeal和cyMin是指定子視窗的高度和最小高度,在使用這兩個函數調整子視窗的大小后還應該使用該類別的成員函數RecalLayout()重新調整視窗框架的布局。如果要設定視窗框架里的活動子視窗,可以通過CsplitterWnd類別的成員函數SetActivePane(int row,int col,CWnd* pWnd=NULL)來完成,該函數指定子視窗的方式有兩種,一是指出子視窗所在的行列,二是傳入指向該子視窗的控件指針。

            最后,將視窗分裂成多個子視窗后,整個視窗程序中將存在多個View控件。當在其中一個View控件執行更新操作時,如何讓其它View控件同步更新數據?可以通過文檔類別(CDocument)的UpdateAllViews(CView* pSender,LPARAM lHint,CObject* pHint)成員函數的調用,再由該函數分別調用目前存在于視窗程序中各View控件的On Update函數來完成數據的同步更新。

            UpdateAllViews函數的參數含義為:

            ·pSender是指向引發更新操作的View控件指針,如果傳入NULL表示所有視圖都要執行更新操作;

            ·lHint是用于傳送更新視圖時,需要傳送的額外信息參數;

            ·pHint是指向記錄更新視圖所需額外信息的控件。在調用該函數時,將View控件的指針傳入的目的是要告訴該函數該子視圖已經完成數據更新,該函數不需要再調用該子視圖的On Update進行數據更新。


            子視圖的動態切換

            在多視圖應用程序中,可以通過改變CCreateContext對象的值,來創建更加靈活的視圖,實現多視圖的動態切換。CCreateContext是MFC框架所使用的一種數據結構,它將構成文檔/視圖結構的組件聯系起來。這個結構包括指向文檔的指針、視窗框架的指針、視圖的指針以及文檔模板的指針,它還包含一個指向CRuntimeClass結構的指針,以指明所創建的視圖的類型。

            其數據成員如下:

            ·m_pNewViewClass是指向創建上下文的視圖的CRuntimeClass結構的指針;

            ·m_pNewDocTemplate是指向與視窗框架的創建相聯系的文檔模板的指針;

            ·m_pCurrentDoc是指向文檔對象的指針,以和新視圖tb聯系起來;

            ·m_pLastView是指向已存在的視圖的指針,它是新產生的視圖的模型;

            ·m_pCurrentFrame是指向已存在的視窗框架的指針,它是新產生的視窗框架的模型。

            此外,任何一個從CObject類別繼承而來的子類別,在使用宏DECLARE_DYNAMIC、DECLARE_DYNCREATE、DECLARE_SERIAL三個中的任意一個時都會產生一個CRuntimeClass結構的靜態對象,RUNTIME_CLASS返回的就是這個對象的指針,這個對象包含了其基類和本身在運行時刻的信息。

            在單文檔靜態分裂視窗的應用程序中,利用CsplitterWnd類別的成員函數Delete View(int row,int col)可以刪除子視窗的原有視圖,然后再通過該類別的成員函數Create View為子視窗創建新的視圖。但是,創建新視圖前必須初始化創建上下文相關指針,即對CCreateContext結構賦值。值得注意的是,使用Create View函數創建的新視圖不能自動調用視圖類別的成員函數OnInitialUpdate和自動顯示并且激活新視圖,需要人工調用OnInitialUpdate函數和ShowWindow(SW_SHOW) 函數,這些函數的調用都可以通過CsplitterWnd類別的成員函數Get Pane(int row,int col)獲得新視圖的指針來完成。

            結束語

            在MFC的框架下,混合分裂視窗有多種編程方法,本文只是從CsplitterWnd類別的角度去分析混合靜態分裂視窗的實現方法,希望能給讀者起到拋磚引玉的作用。

            posted @ 2012-08-05 14:26 tbwshc| 編輯 收藏

            應用程序:一個異步的HTTP服務器的設計

              假設我們要設計一個HTTP服務器,它的設計目標包括:高并發性、精簡(部分支持HTTP/1.1)、支持plug-in結構。在不少場合可能都有這個需求。總體上來說,HTTP服務器可以類比成一個基于多線程的操作系統:OS調度每個工作線程在適當的時候獲得執行,而工作線程提供服務(也就是處理HTTP請求)。在這個基礎上,主要的考慮就是調度粒度的大小,粒度太大的時候并發性會降低,而粒度太小又可能因為任務切換(考慮OS的Context Switching)而導致效率降低,所以這又是一個折衷的結果。類似于Apache(以及其他的HTTP服務器),我們可以把一個HTTP處理過程分為若干個狀態,基于這些狀態可以構造出一個HTTP處理的狀態機。這種情況下,我們就可以把每個狀態的處理作為調度的粒度。一個調度過程就是:一個工作線程從全局的任務隊列里取出一個HTTP_Context結構;根據當前的狀態完成相應處理;然后根據狀態機設置下一個狀態;再放回到全局的任務隊列里。這樣子,若干個HTTP狀態就可以通過這個調度策略構成一個完整HTTP處理過程。顯而易見,一個狀態對于下一個狀態處理的調用都可以認為是異步的。一個HTTP狀態機的設計如下圖所示。

              工作線程的函數其實就是兩個操作:從狀態隊列里取出一個HTTP_Context,調用HTTP_Context的service()函數,周而復此。在這個架構上,就很容易引入異步I/O和Plug-in的機制了。事實上我們也可以使用基于事件(例如select/poll)的I/O策略來模擬異步I/O,實現中使用一個tb用戶線程就可以了。

              對于異步I/O和Plug-in的調用,我們也是采用類似于Linux 2.6里面aio的重試方案,而異步完成的時候采用回調函數。在某個狀態上,如果系統需要I/O操作(recv或者send),則會請求一個異步I/O(操作系統提供的異步I/O或者由用戶線程模擬的異步I/O),這時候相應的HTTP_Context不會重新回到狀態隊列里,而在I/O完成的回調函數里面才會重新放回到狀態隊列,得到重新調度的機會。HTTP_Context得到重新調度的時候會檢查I/O狀態(這個可以通過一些標志位來完成),如果已經完成,則處理然后設置下一狀態,重新調度,否則可以重新請求一個新的I/O請求。Plug-in也可以使用類似的方案,比如說一個Plug-in要跟外部的一個服務器通信,這時候就可以在通信完成的時候才把HTTP_Context重新放回到狀態隊列。顯然,Plug-in跟HTTP狀態是多對多的關系,一個Plug-in可以在若干個關心的狀態注冊自身,同時還可以設置一些short-path來提高處理的效率。

              結論

              總的來說,異步調用的設計和應用歸根結底就是對多個主動對象的管理問題:如何提供執行的動力以及如何保證執行的順序邏輯。主要考慮的問題是主動對象的粒度以及執行方式,同步或者回調來完成順序的調度,或者使用近似的調度而加一些魯棒的錯誤處理機制來保證語義的正確。后者可以考慮在使用基于事件的socket的時候,readable事件的通知可以是冗余的,或者說可以比實際中發生的readable事件更多,這個時候使用非阻塞的socket,有些read()(或者recv())會直接返回EWOULDBLOCK,系統只要考慮處理這種情況(使用non blocking socket而不是blocking socket),當例外的情況不多的時候是可以接受的。這時候可以說事件的報告就只是近似的。
            posted @ 2012-08-05 12:47 tbwshc| 編輯 收藏

            創建外鍵約束時如果使用Oracle默認的創建方式,在刪除被參照的數據時,將無法被刪除,這一點在Oracle9i中給了我們更多靈活的選擇,我們可是使用on delete cascade和 on delete set null關鍵字來決定刪除被參照數據時是否要將參照這個數據的那些數據一并刪除,還是將那些參照這條數據的數據的對應值賦空。

            例如下面這兩個表中分別存的時員工的基本信息和公司的部門信息。我們為

            create table dept
            (deptno number(10) not null,
            deptname varchar2(30) not null,
            constraint pk_dept primary key(deptno));

            create table emp
            ( empno number(10) not null,
            fname varchar2(20) ,
            lname varchar2(20) ,
            dept number(10) ,
            constraint pk_emp primary key(empno));

            然后我們現在分別使用這兩個關鍵字來增加外鍵試一下,首先我們來試一下on deletbe cascade

            alter table emp
            add constraint fk_emp_dept foreign key(dept) references dept(deptno) on delete cascade;

            先增加外鍵。然后插入數據。

            insert into dept values(1,’銷售部’);
            insert into dept values(2,’財務部’);
            insert into emp values (2,’Mary’,'Song’,1);
            insert into emp values (3,’Linda’,'Liu’,2);
            insert into emp values (4,’Linlin’,'Zhang’,1);

            然后現在我要刪除銷售部,會有什么后果呢?

            delete from dept where deptno = 1;

            我們發現除了dept中的一條數據被刪除了,emp中兩條數據也被刪除了,其中emp中的兩條數據是參照了銷售部的這條數據的,這就很容易理解on delete cascade了。

             

            創建外鍵約束時如果使用Oracle默認的創建方式,在刪除被參照的數據時,將無法被刪除,這一點在Oracle9i中給了我們更多靈活的選擇,我們可是使用on delete cascade和 on delete set null關鍵字來決定刪除被參照數據時是否要將參照這個數據的那些數據一并刪除,還是將那些參照這條數據的數據的對應值賦空。

            按照上文中介紹的就能夠實現在oracle數據庫中用非默認方式創建外鍵的目的,希望對大家能夠有所幫助。

            posted @ 2012-08-04 13:26 tbwshc| 編輯 收藏

            現在某家企業的Oracle數據庫中有一張產品信息表。這張表中的記錄已經超過了500萬條。其中成品信息大概30萬條。零件記錄有300萬條左右。剩余的都是包裝信息。數據庫工程師通過相關的分析與監測,用戶訪問這張表的時候,會有嚴重的等待現象。這主要是因為這張表中的數據存放在同一塊硬盤上。當不同的用戶并發訪問這張表時,會因為磁盤I/O性能的瓶頸,而導致等待。如下圖所示。當各位讀者遇到這種情況,該如何采取措施來優化性能呢?筆者這里的建議是采用Oracle分區表減少磁盤的I/O沖突,改善數據庫的性能。

            一、分區表的原理與優勢。

            分區表對于提高大表的訪問性能會有很大的幫助。如上圖所示,可以將一張產品信息表分按產品類別分為三個部分,分別為成品信息、零件信息和原材料信息。然后將這三部分對應一個單獨的分區,并將它們存放在不同的硬盤上。此時當不同的用戶訪問不同的信息時,就可以有效的降低磁盤的I/O沖突。即使是同一個用戶,需要同時訪問這三部分信息,如產品的物料清單時,由于其分別從不同的硬盤中讀取數據,為此也可以明顯的降低磁盤I/O沖突。

            所以分區的基本原理就是通過訪問一個表或者索引的較小片斷,而不是訪問整個表和索引,以提高數據庫的性能。當然這有一個前提條件,需要將一個表的不同分區放置在不同的磁盤上,此時磁盤整體的吞吐量就會成倍上升。

            采取分區,不僅可以提高用戶訪問時的性能,而且還可以提高備份時的靈活性。如上面這個例子,將產品信息根據其類別分為不同的區,并將它們保存在不同的硬盤上。此時就可以對各自的分區進行單獨的備份。如最近因為國家環保的要求,tb原材料信息進行了大規模的調整。此時就可以對原材料信息所在的分區數據進行單獨的備份。這不僅可以減少備份的時間,而且可以降低備份作業過程中出現的I/O沖突問題。

            一般來說,分區表的優勢有一個前提,就是需要將分區數據放置在不同的磁盤上。如果不這么做的話,那么分區往往很難起到降低磁盤I/O的效果。所以為了最大程度的降低一個大表的磁盤I/O(特別是經常會有并發行的訪問),此時應該將表分割到多個分區上。然后再將這些分區存放在不同的磁盤上。

            二、分區表模式的選擇。

            那么該如何對表進行分區呢?這又是一個比較關鍵的問題。根據經驗,筆者認為要讓分區取得更好的效果,分區表模式的選擇至關重要。也就是說,按什么內容對表進行分區管理。有時候,先同的數據,采取不同的分區表模式,往往會有不同的效果。在下面的內容中,筆者會結合企業實際應用的情景,對分區表模式的選擇進行舉例。希望這些內容能夠幫助各位讀者,更好的維護分區表。

            第一種模式:按行來進行分區。

            上面這個例子中,筆者談到有一張產品信息表,其包括成品信息、零件信息和原材料信息。當這張表的記錄比較多,并且當用戶訪問這張表時已經出現了嚴重的I/O沖突的時候,則就可以根據行記錄來進行分區。如在產品信息表中有一個產品類別的字段。數據庫管理員就可以根據這個字段對標進行分區。具體的分區方法也比較簡單。在建立表的時候,在產品類別字段后加上Partion關鍵字,然后指定按字段的內容進行分區。這個操作比較簡單,筆者就不過多展開了。筆者這里需要強調的是,分區完之后一定要將數據存放在不同的磁盤上,即不同的表空間。否則的話,不能夠起到改善磁盤I/O的效果。

            第二種模式:按列來進行分區。

            在實際工作中,還有這么一種情況。如現在有一張員工信息表。這這張表中除了包含員工的基本信息,如身份證號碼、姓名、籍貫等內容,還包括員工的身份證復印件或者照片等圖片信息。大家都知道,圖片信息的數據流量是很大的。有可能一張身份證復印件的數據流量相當于幾千條的員工基本信息。而且,當用戶訪問員工信息表的時候,并不是每個時候都需要查看身份證復印件。大部分時候他們可能只是查詢員工的聯系方式或者住址等等。另外,一般身份證復印件等照片不會隨意更改,而員工的聯系方式或這住址等等,則更改比較頻繁。此時如果需要更改員工信息,卻將不需要更改的員工身份證復印件也查詢出來,顯然那這會加重磁盤的I/O沖突。

            當企業存在這種情況時,也可以對這個表進行分區。此時分區并不是對行進行分區,而是對列進行分區。如可以將身份證復印件信息或者照片信息分為一個獨立的分區,并將其保存在另外一個硬盤上。這么做,能夠帶來如下的好處。

            一是在數據訪問時,可以指定是否需要查詢身份證信息所在的分區。在查詢員工信息的時候,在語句中可以指定從哪個分區中查詢信息。當用戶平時只是查詢員工的聯系方式或者住址時,就不需要訪問身份證復印件所在的分區。如可以使用如下語句查詢:

            Select * from ad_user partition(uinfo) –假設員工的基本信息存放在分區Unifo中。

            在查詢語句中,使用Partition關鍵字可以指定其查詢的是哪個分區。如果不特指的話,則系統會查詢這個表所對應的全部分區。而指定的話,就只訪問某個特定分區的內容。上面這條語句,就只讀取Uinfo分區中的信息。而不會讀取身份證復印件等相關信息。如此的話,就可以降低磁盤的I/O沖突,減少不必要的數據流量,提高查詢的性能。

            二是方便對數據的備份。根據使用習慣,一般身份證復印件或者員工照片等信息不怎么會更改。為此對這些數據的備份頻率可以比較低一點。況且這些信息的容量往往會很大。如果經常對其進行備份,顯然會增加磁盤的I/O負擔。而對于員工的聯系信息或者住址等等,其變化的頻率就會高許多。對這些信息就需要進行經常性的備份。對大表進行分區管理,還有一個很大的優勢就在于可以對各個分區中的數據采取獨立的備份。為此就可以對身份證復印件所在的分區進行單獨的備份,如一個月或者有大的變動時進行備份。而對于其他的信息則可以每天進行備份。這就可以實現在性能與安全方面的均衡。一般來說,在訪問某個表時,如果經常需要訪問的信息只是特定的幾列,而不需要訪問的信息容量比較大,此時就可以采用按列分區的模式。在這種情況下,用戶就可以在查看某個分區內容的時候避免訪問其他分區。同時還可以在不妨礙其它分區的情況下對某個分區的數據進行獨立的備份。

            第三種分區模式:散列分區。

            有時候某個表可能沒有明顯的分區特征,即不符合上面提到的這些情況。但是表中的記錄又非常的多。在這種情況下,也有必要進行分區。不過此時我們可以讓系統進行隨機的分區。這種分區模式就叫做散列分區。通常情況下,為了提高散列分區的效果,即得到一個比較均勻的分布,往往可以將2的N次方指定為散列分區數。一般來說,N越大,其分布的越均勻。

            也就是說,當數據庫管理員不知道該如何對表進行分區時,但確實有分區的必要時,可以使用散列分區。不過筆者需要提醒的是,散列分區其有一個重大的限制。在使用散列分區的時候,僅僅支持本地索引,而不支持其他的索引方式。這一點需要特別的注意。在實際工作中不能夠因為采取了散列分區,而降低或者取消了索引。這往往是得不償失的,不可行。

            希望通過上文的學習,大家能夠掌握好利用Oracle分區表來減少磁盤I/O沖突的知識,便于大家在以后的工作中靈活運用。

            posted @ 2012-08-04 13:25 tbwshc| 編輯 收藏

            下面就介紹一下Oracle手動創建數據庫的步驟:

            1、確定新建數據庫名稱和實例名稱;

            2、確定數據庫管理員的認證方式;

            3、創建初始化參數文件;

            4、創建實例;

            5、連接并啟動實例;

            6、使用create database語句Oracle創建數據庫;

            7、創建附加的表空間;

            8、運行腳本創建數據字典視圖;

            下面以創建一個名為“MYNEWDB”的數據庫為例

            1、確定數據庫名稱與實例名稱;

            1.DB_NAME=MYNEWDB

            2.SID=MYNEWDB

            2、確定數據庫管理員的認證方式;

            管理員的認證方式包括操作系統認證和口令認證兩種,本例采用操作系統認證

            3、創建初始化參數文件;

            Oracle提供的初始化參數樣本文件位于$ORACLE_HOME\admin\tbsample\pfile目錄中的initsmpl.ora

            我們采用修改樣本的方式,創建參數文件名為:initMYNEWDB.ora,存放在D:\oracle\ora92

            1.\database\initMYNEWDB.ora,

            主要內容設置如下:

            共享服務器設置

            1.dispatchers="(PROTOCOL=TCP)(SERVICE=MYNEWDBXDB)

            數據庫實例名設置

            1.instance=MYNEWDB

            安全與審計設置

            1.remote_login_passwordfile=EXCLUSIVE

            排序區大小設置

            1.pga_aggregate_target=25165824

            2.sort_area_size=524288

            全局數據庫名設置

            1.db_domain=""

            2.db_name=MYNEWDB

            控制文件設置

            1.control_files=("D:\oracle\oradata\MYNEWDB\CONTROL01.CTL",

            2."D:\oracle\oradata\MYNEWDB\CONTROL02.CTL",

            3."D:\oracle\oradata\MYNEWDB\CONTROL03.CTL")

            SGA區設置

            1.java_pool_size =33554432

            2.large_pool_size=8388608

            3.shared_pool_size=50331648

            以上的相關內容就是對Oracle創建數據庫的步驟的介紹,望你能有所收獲。

            按照上文中介紹的步驟,就能夠實現Oracle手動創建數據庫,希望上文中介紹的內容對大家能夠有所幫助。

            posted @ 2012-08-04 13:24 tbwshc 閱讀(746) | 評論 (0)編輯 收藏

            Oracle數據庫以其高可靠性、安全性、可兼容性,得到越來越多的企業的青睞。如何使Oracle數據庫保持優良性能,這是許多數據庫管理員關心的問題,根據筆者經驗建議不妨針對以下幾個方面加以考慮。

            一、分區

            根據實際經驗,在一個大數據庫中,數據空間的絕大多數是被少量的表所占有。為了簡化大型數據庫的管理,改善應用的查詢性能,一般可以使用分區這種手段。所謂分區就是動態表中的記錄分離到若干不同的表空間上,使數據在物理上被分割開來,便于維護、備份、恢復、事務及查詢性能。當使用的時候可建立一個連接所有分區的視圖,使其在邏輯上仍以一個整體出現。

            1.建立分區表
            Create table Employee(
            EmpNo varchar2(10) primary key,
            Name varchar2(30),
            DeptNo Number(2)

            Partition by range(DeptNo)
            (partition PART1 values less than (11)
            tablespace PART1_TS,
            partition PART2 values less than(21)
            tablespace PART2_TS,
            partition PART3 valuse less than(31)
            tablespace PART3_TS
            partition PART4 values less than(MAXVALUE)
            tablespace PART4_TS
            );

            表Employee依據DeptNo列進行分區。

            2.分區索引
            Create index Employee_DeptNo on Employee (DeptNo)local(
            partition PART1 tablespace PART1_NDX_TS,
            partition PART2 tablespace PART2_NDX_TS,
            partition PART3 tablespace PART3_NDX_TS,
            partition PART4 tablespace PART4_NDX_TS,
            );

            當分區中出現許多事務并且要保證所有分區中的數據記錄的惟一性時采用全局索引,在建立全局索引時,Global子句允許指定索引的范圍值,這個范圍值可以不同于表分區的范圍值。只有建立局部索引才會使索引分區與表分區間建立起一一對應關系。因此,在大多數情況下,應該使用局部索引分區。若使用了此索引,分區就能夠很容易地將索引分區與表分區建立關聯,局部索引比全局索引更易于管理。

            3.分區管理
            根據實際需要,還可以使用Alter table命令來增加、刪除、交換、移動、修改、重命名、劃分、截短一個已存在分區的結構。

            二、重建索引

            如果表中記錄頻繁地被刪除或插入,盡管表中的記錄總量保持不變,索引空間的使用量會不斷增加。雖然記錄從索引中被刪除,但是該記錄索引項的使用空間不能被重新使用。因此,如果表變化不定,索引空間量會不斷增加,不論表中記錄數量是否增加,只是因為索引中無效空間會增加。
            要回收那些曾被刪除記錄使用的空間,需要使用Alter index rebuild命令。可以做一個定期運行的批處理程序,來重建最活動表的索引。這個批處理程序可以在空閑時運行,以避免該程序與其他應用程序沖突。若能堅持索引的這一程序規劃,便可以及時回收那些未使用空間,提高空間利用率。

            三、段的碎片整理

            當生成一個數據庫對象時(一個表或一個索引),通過用戶缺省值或指定值來為它指定表空間。一個在表空間中生成的段,用于存儲對象的相關數據。在段被關閉、收縮、截斷之前,段所分配的空間將不被釋放。

            一個段是由范圍組成,而范圍是由相鄰的Oracle塊組成。一旦存在的范圍不能再存儲新的數據,這個段就會去獲得新的范圍,但并不要求這些范圍是彼此相鄰的。這樣的擴展會一直繼續下去,直到表空間中的數據文件不能提供更多的自由空間,或者范圍數量已達到極限。

            因此,一個碎片太多的數據段,不僅會影響運行,也會引發表空間中的空間管理問題。所以,每個數據段只含有一個范圍是十分有益的。借助監控系統,可以通過檢查DBA_SEGMENTS數據字典視圖來了解哪些數據庫對象含有10個或更多范圍的段,確定其數據段碎片。

            若一個段的碎片過多,可用兩種方法解決:
            1. 用正確的存儲參數建立一個新表,將舊表的數據插入到新表中,在刪除舊表;
            2. 利用Export/Import工具。

            如:exp system/manager file=exp.dmpcompress=Y grants=Y indexes=Y
            tables=(T1,T2)
            若輸出成功,進入Oracle,刪除上述表。
            注:compress=Y表示將在輸出過程中修改它們的存儲參數。
            imp system/manager file=exp.dmp commit=Y buffer=64000 full=Y

            四、自由范圍的碎片整理

            表空間中的一個自由范圍是表空間中相連的自由(空間)塊的集合。當一個段關閉時tb,它的范圍將被釋放,并被標記為自由范圍。然而,這些自由范圍再也不能與相鄰的自由范圍合并,它們之間的界線始終存在。但是當表空間的缺省值pctincrease設置不是0時,SMON后臺進程會定期將這些相鄰的自由范圍合作。若pctincrease設置為0,那么相鄰自由范圍不會被數據庫自動合并。但可以使用Alter table命令"coalesce"選項,來強迫進行相鄰自由范圍的合并。

            不進行自由范圍合并,在日后的空間請求中,會影響到表空間中的空間分配。當需要一個足夠大的范圍時,數據庫并不會合并相鄰的自由范圍,除非沒有其他選擇。這樣,當表空間中前面較小的自由范圍已被使用時,將使用表空間中后面部分最大的一個自由范圍。結果,會因為沒有足夠多的使用空間,從而導致表空間需求的矛盾。由于這樣的情況出現,使數據庫的空間分配距理想越來越遠。自由空間碎片常會出現在那些經常關閉又重新生成的數據庫表和索引中。

            在理想的Oracle表空間中,每一個數據庫對象存儲在一個單獨的范圍中,并且所有有效自由空間集中在一個巨大而連續的范圍中。這樣,在一個對象需要附加存儲空間時,可以在增加獲取足夠大自由空間的可能性的同時,最小化空間中的循環調用,提高自由空間使用率。


            posted @ 2012-08-04 13:23 tbwshc| 編輯 收藏

            1、DB2 訪問前10行數據與Oracle區別

            DB2 :    
            select * from test fetch first 10 rows only
            Oracle :   
            select * from test where rownum<=10
             
            查詢語句
            Db2:不提供隱形轉換
            select * from employee where empno=1010;
            oracle:提供隱形轉換
            select * from employee where empno='1010';
             
            2、DB2 Insert into 與Oracle區別
            DB2 允許有類似這樣多行插入:
            insert into staff values(1212,'cemy',20,'sales',3,90000,30000);
            (1212,'cemy',20,'sales',3,90000,30000); 
            oracle:
            SQL>  insert into staff values(1212,'cemy',20,'sales',3,90000,30000),(1212,'cemy'
            ,20,'sales',3,90000,30000)
                                                                
            3、DB2 Update 與Oracle Update
            Db2
            DB2 update staff set (salary,comm)=(80000,50000);
            DB2 update staff set salary=80000,comm=50000;
            Oracle:
            SQL> update staff set salary=80000,comm=50000;
            已更新 1 行。I
            4、取得系統日期
            Oracle:
            Select sysdate from dual;
            DB2:
            Select current timestamp from sysibm.sysdummy1;
             
            5、轉換日期時間到字符類型:
            Oracle  
            TO_CHAR(date_expression_r_r, 'YYYY-MM-DD')  
            TO_CHAR(date_expression_r_r, 'HH24:MI:SS')  
            DB2  
            CHAR(date_expression_r_r,ISO)  
            CHAR(time_expression_r_r,ISO) 
             
            6、轉換日期時間字符串到日期時間類型:
            Oracle  
            TO_CHAR(date_expression_r_r, 'YYYY-MM-DD')  
            TO_CHAR(date_expression_r_r, 'HH24:MI:SS')  
            DB2  
            DATE('2005-05-20')  
            TIME('18:59:59')  
            TIEMSTAMP('2007-2-1', '21:12:12')  
            TIEMSTAMP('2007-2-1 21:12:12')
             
            DB2也有TO_CHAR 和 TO_DATE函數,但只能提供固定的轉換格式,如下
            TO_CHAR (timestamp_expression_r_r,'YYY-MM-DD HH24:MI:SS')  
            TO_DATE (string_expression_r_r, 'YYY-MM-DD HH24:MI:SS') 
             
             
            7、快速清空大表
            Oracle:
            truncate table TableName ;
            DB2:
            alter table TableName active not logged initially with empty table;
             
            8、創建類似表
            Oracle:
            create table a as select * from b ;
            DB2:
            create table a like b ;
             
            9、修改字段長度或類型:
            ORACLE:
            ALTER TABLE NODES MODIFY NODE_NAME varchar(32);
            DB2:
            alter table NODES ALTER NODE_NAME SET DATA TYPE varchar(32);
             
            10、空值處理得到abc
            Oracle:
            SELECT 'abc' || c1 FROM t1 (c1 IS NULL)  
            DB2 :
            SELECT 'abc‘ || COALESCE(c1,'') FROM t1 
             
            11、創建 indexes 
            Oralce:
            Create TABLE T1 .............IN DATA_TA
            Create Index ........ ON T1  ...... IN INDX_TS
             
            DB2:
            Create TABLE T1 ........ IN DATA_TS INDEX IN INDX_TS
            Create INDEX  .....ON T1
             
            12、更改列名
            oracle :
            alter table test rename column mail to mail2;
            db2  
            不提供更改列名功能(解決辦法同刪除,或者通過建立一個新視圖解決)
            13、更改列類型
            oracle :alter table test modify column (mail2 integer);
            db2    :alter table test alter mail varchar(256) 只可以加寬,不能更改類型
             
            14 創建PROCEDURE的參數的區別
            1)參數類型和參數名稱的位置不同
            db2:
            CREATE PROCEDURE PRO1 (IN OrgID int)
            oracle:
            CREATE PROCEDURE PRO1 (OrgID IN int)
            2)同時作為輸入輸出參數的寫法不同
            db2:   
            CREATE PROCEDURE PRO1 (INOUT OrgID int)    INOUT連著寫
            oracle:
            CREATE PROCEDURE PRO1 (OrgID IN OUT int)    IN OUT中間空格隔開,而且必須IN在OUT之前
            3)沒有輸入或輸出參數時
            db2:  
            CREATE PROCEDURE PRO1 ()    
            oracle:
            CREATE PROCEDURE PRO1 不能有空的括號
             
            變量定義和BEGIN END體的位置不同
                    db2中變量定義在BEGIN END體內,并且每個變量都要用DECLARE聲明;存儲過程結束時,END后跟P1,并且不需要分號
                    oracle中變量定義必須在BEGIN END體外,變量都不需要用DECLARE聲明(有種說法是,第一個變量需要DECLARE,其他變量不需要);存儲過程結束時,END后跟存儲過程的名稱,并且需要分號        
             db2:
            CREATE PROCEDURE PRO1()
             LANGUAGE SQL    
                   P1: BEGIN
                      --變量定義
                       DECLARE INSERT_DATE TIMESTAMP; 
                       DECLARE ALLDEPT_NO  VARCHAR(20);
                       --具體操作
                       SELECT a FROM TAB_1;
                                      .........
                        END P1
                    
            oracle:  
            CREATE PROCEDURE PRO1
                      IS
                     --變量定義
                     INSERT_DATE TIMESTAMP; 
                     ALLDEPT_NO  VARCHAR(20);
                      BEGIN
                        --具體操作
                     SELECT a FROM TAB_1;
                                   .........
                     END PRO1;
            15、控制語句的不同
             db2:    
             IF …THEN ......ELSEIF THEN .... END IF;
             oracle: 
            IF …THEN ......ELSIF  THEN .... END IF;
             
            16、如何執行腳本SQL文件
            Oracle: 
            @$PATH/filename.sql; 
            DB2:
            db2 -tvf $PATH/filename.sql
             
            17、查看當前用戶的表和視圖
            DB2:
            LIST   TABLES 
            ORACLE:   
            SELECT   *   FROM   TBAB;
             
            DB2:DROP   TABLE刪除表和定義。LIST   TABLES發現表不存在了。 
            ORACLE:DROP   TABLE刪除表的內容保留表的定義。可以看到表。
             
             
             
             
            ---------------------------------------------------------------
            另外附上今天分享的東西:【快速復制表】
             
            1.復制表結構及數據到新表 
            CREATE TABLE 新表 SELECT * FROM 舊表 (DB2不適用)
             
            2.只復制表結構到新表 
            (1)oracle
            CREATE TABLE 新表 SELECT * FROM 舊表 WHERE 1=2 
            即:讓WHERE條件不成立. 
            (2)DB2
            CREATE TABLE 新表 LIKE 舊表 
             
            3.復制舊表的數據到新表(假設兩個表結構一樣) 
            INSERT INTO 新表 SELECT * FROM 舊表 
             
            4.復制舊表的數據到新表(假設兩個表結構不一樣) 
            INSERT INTO 新表(字段1,字段2,.......) SELECT 字段1,字段2,...... FROM 舊表
            posted @ 2012-07-28 12:46 tbwshc 閱讀(949) | 評論 (0)編輯 收藏

            java對象的初始化

            小冬(珠海)11:02:48
            我們知道一個對象可以有靜態變量、變量、靜態初始化塊、初始化塊,當我們創建一個對象時,它是怎么初始化的呢?按什么順序初始化的呢?
             
            1. public class Test { 
            2.  
            3.      
            4.     // 靜態變量 
            5.     public static String staticField = "靜態變量"; // 變量 
            6.     public String field = "變量"
            7.     // 靜態初始化塊 
            8.     static { 
            9.         System.out.println(staticField); 
            10.         System.out.println("靜態初始化塊"); 
            11.     } 
            12.     // 初始化塊 
            13.     { 
            14.         System.out.println(field); 
            15.         System.out.println("初始化塊"); 
            16.     } 
            17.     // 構造器 
            18.     public Test() { 
            19.         System.out.println("構造器"); 
            20.     } 
            21.     public static void main(String[] args) { 
            22.         Test test = new Testb(); 
            23.  
            24.     } 
             
            運行下代碼,輸出結果是:
            靜態變量
            靜態初始化塊
            變量
            初始化塊
            構造器
             
             
            由此可以看到,當new一個對象時,它并不是就是調構造方法,而是先初始化屬性變量,我們把變量的定義先后順序換下,再執行,會發現,靜態的是先于非靜態進行實始化的,那么對于靜態變量和靜態初始化塊之間、變量和初始化塊之間的先后順序又是怎樣呢?是否靜態變量總是先于靜態初始化塊,變量總是先于初始化塊就被初始化了呢?
            我們先改下代碼:
             
            1. public class Test { 
            2.  
            3.     public static TestA ta = new TestA(); 
            4.     // 靜態變量 
            5.     public static String staticField = "靜態變量"; // 變量 
            6.     public String field = "變量"
            7.     // 靜態初始化塊 
            8.     static { 
            9.         System.out.println(staticField); 
            10.         System.out.println("靜態初始化塊"); 
            11.     } 
            12.     // 初始化塊 
            13.     { 
            14.         System.out.println(field); 
            15.         System.out.println("初始化塊"); 
            16.     } 
            17.     // 構造器 
            18.     public Test() { 
            19.         System.out.println("構造器"); 
            20.     } 
            21.     public static void main(String[] args) { 
            22.         Test test = new Test(); 
            23.  
            24.     } 
            25.  
            26. class TestA { 
            27.     public TestA() { 
            28.         System.out.println("Test--A"); 
            29.     } 
             輸出是:
            Test--A
            靜態變量
            靜態初始化塊
            變量
            初始化塊
            構造器
             
             
            靜態變量:static TestA ta = new TestA()在靜態初始化塊前,所以先輸出Test--A
            再換下位置,把static TestA ta = new TestA()放到在靜態初始化塊后,我們發現輸出是:
            靜態變量
            靜態初始化塊
            Test--A
            變量
            初始化塊
            構造器
             
             
            由此可見這是取決于它們在類中出現的先后順序,同理可得:變量和初始化塊之間也如此,總結可得:初始化優先級是(靜態變量/靜態初始化塊)>(變量/初始化塊)>構造器。
             
             
            那繼承關系時的初始化又是怎樣的呢?如下:
            大家應該知道,初始化子類時會先初始化父類,再看代碼:
             
            1. public class Test extends Parent{ 
            2.     // 靜態變量 
            3.     public static String staticField = "子類靜態變量"; // 變量 
            4.     public String field = "子類變量"
            5.     // 靜態初始化塊 
            6.     static { 
            7.         System.out.println(staticField); 
            8.         System.out.println("子類靜態初始化塊"); 
            9.     } 
            10.     //public static TestA ta = new TestA(); 
            11.     // 初始化塊 
            12.     { 
            13.         System.out.println(field); 
            14.         System.out.println("子類初始化塊"); 
            15.     } 
            16.     // 構造器 
            17.     public Test() { 
            18.         System.out.println("子類構造器"); 
            19.     } 
            20.     public static void main(String[] args) { 
            21.         Test test = new Test(); 
            22.     } 
            23.  
            24. class Parent{ 
            25.  
            26.     public String field = "父類變量";// 變量 
            27.     public static String staticField = "父類靜態變量"; // 靜態變量 
            28.     // 靜態初始化塊 
            29.     static { 
            30.         System.out.println(staticField); 
            31.         System.out.println("父類靜態初始化塊"); 
            32.     } 
            33.     // 初始化塊 
            34.     { 
            35.         System.out.println(field); 
            36.         System.out.println("父類初始化塊"); 
            37.     } 
            38.     // 構造器 
            39.     public Parent() { 
            40.         System.out.println("父類構造器"); 
            41.     }    
            剛才結果應該是:
            父類靜態變量
            父類靜態初始化塊
            子類靜態變量
            子類靜態初始化塊
            父類變量
            父類初始化塊
            父類構造器
            子類變量
            子類初始化塊
            子類構造器
             
            從結果看到,并不是父類完全初始化完后再進行子類的初始化,子類的靜態變量和靜態初始化塊的初始化是在父類的變量、初始化塊和構造器初始化之前就完成了。
             
            我們在main方法再創建一個對象,Test test2 = new Test();
            大家就test2的初始化又如何?
             
            為了好看,我們子類構造器里加多行代碼System.out.println("***********");
            輸出結果:
            父類靜態變量
            父類靜態初始化塊
            子類靜態變量
            子類靜態初始化塊
            父類變量
            父類初始化塊
            父類構造器
            子類變量
            子類初始化塊
            子類構造器
            ***********
            父類變量
            父類初始化塊
            父類構造器
            子類變量
            子類初始化塊
            子類構造器
            ***********


            發現什么了?
            靜態變量和靜態代碼塊只加載一次 。
             
             
            總結:
            一、初始化優先級:
            1、靜態變量/靜態初始化塊)>(變量/初始化塊)>構造器
            2、父類>子類

            二、靜態變量和靜態代碼塊只加載一次,因為它們是全局共享的
             
            posted @ 2012-07-28 12:45 tbwshc 閱讀(912) | 評論 (0)編輯 收藏

            背景:先前在生產庫上配置了oracle監控,每5分鐘嘗試連接一次數據庫,若連接失敗則通過nagios+fetion自動報警,此配置參考文章:http://ylw6006.blog.51cto.com/470441/787496

            早晨收到報警信息后,登陸數據庫執行ps -ef查看oracle的后臺進程都在,使用conn /as sysdba的方式登陸數據庫,提示連接到空閑的實例,使用easy connect 方式連接則報oracle實例無法分配內存,從報錯提示上看,就像oracle數據庫實例未打開的狀態!分析alert日志不斷出現如下錯誤信息:
            Process J002 died, see its trace file
            kkjcre1p: unable to spawn jobq slave process
            Errors in file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_cjq0_18577.trc:

            trace文件摘要信息如下:
            *** 2012-07-26 10:20:31.068
            Process J002 is dead (pid=13857 req_ver=1136 cur_ver=1136 state=KSOSP_SPAWNED).

            *** 2012-07-26 10:20:32.069
            Process J002 is dead (pid=13876 req_ver=1594 cur_ver=1594 state=KSOSP_SPAWNED).

            google查詢一番后,發現大部分描述和oracle的進程數設置有關,又或者是內存不足引起!于是在oracle 10g環境下測試,線上數據庫環境為11.2.0.3

            一:設置processes初始化參數值為20,重啟數據庫后,已經占用19個進程

            1. SQL> select count(*) from v$process;  
            2.  
            3.   COUNT(*)  
            4. ----------  
            5.         19  
            6.  
            7. SQL> show parameter process;  
            8.  
            9. NAME                                 TYPE        VALUE  
            10. ------------------------------------ ----------- ------------------------------  
            11. aq_tm_processes                      integer     0  
            12. db_writer_processes                  integer     1  
            13. gcs_server_processes                 integer     0  
            14. job_queue_processes                  integer     10  
            15. log_archive_max_processes            integer     2  
            16. processes                            integer     20 

            新的會話連接,則報連接到空閑的實例,alert日志則出現相應的報錯

            1. [root@db1 ~]# su - oracle  
            2. [oracle@db1 ~]$ sqlplus /nolog  
            3. SQL*Plus: Release 10.2.0.1.0 - Production on Wed Jul 4 13:50:22 2012  
            4. Copyright (c) 1982, 2005, Oracle.  All rights reserved.  
            5.  
            6. SQL> conn /as sysdba  
            7. Connected to an idle instance.  
            8.  
            9. [oracle@db1 dbs]$ tail -f /u01/app/oracle/admin/db1/bdump/alert_db1.log   
            10. Wed Jul  4 13:52:23 2012  
            11. ksvcreate: Process(q000) creation failed  
            12. Wed Jul  4 13:52:35 2012  
            13. Process q001 died, see its trace file  
            14. Wed Jul  4 13:52:35 2012  
            15. ksvcreate: Process(q001) creation failed  
            16. Wed Jul  4 13:52:37 2012  
            17. Process m000 died, see its trace file  
            18. Wed Jul  4 13:52:37 2012  
            19. ksvcreate: Process(m000) creation failed 

            二:于是想到監控oracle的進程和會話數來進一步確定問題
            1:首先要對用戶進行顯示授權,否則后面創建存儲過程編譯將會報錯

            1. SQL> grant select on V_$SESSION tbo hr;  
            2. Grant succeeded.  
            3.  
            4. SQL> grant select on V_$PROCESS to hr;  
            5. Grant succeeded. 

            2:建表,用來存儲結果

            1. SQL> create table session_monitor(time timestamp,session_count number,process_count number);  
            2. Table created. 

            3:創建存儲過程,將數據插入表

            1. SQL> create or replace procedure proc_session  
            2.   2  is  
            3.   3  v_session number(8);  
            4.   4  v_process number(8);  
            5.   5  begin  
            6.   6   select count(*) into v_session from v$session;  
            7.   7   select count(*) into v_process from v$process;  
            8.   8   insert into session_monitor values (sysdate,v_session,v_process);  
            9.   9   commit;  
            10.  10  end proc_session;  
            11. Procedure created. 

            4:創建任務

            1. SQL> var job number;  
            2. SQL> begin  
            3.   2    sys.dbms_job.submit(job => :job,  
            4.   3                        what => 'proc_session();',  
            5.   4                        next_date => sysdate,  
            6.   5                        interval => 'sysdate+2/1440');  
            7.   6* end;  
            8. PL/SQL procedure successfully completed. 

            5:測試效果

            1. SQL> exec proc_session;  
            2. PL/SQL procedure successfully completed.  
            3.  
            4. SQL> alter session set nls_date_format='YYYY-MM-DD-HH24:MI:SS';  
            5. Session altered.  
            6.  
            7. SQL>  select * from session_monitor;  
            8.  
            9. TIME                                     SESSION_COUNT PROCESS_COUNT  
            10. ---------------------------------------- ------------- -------------  
            11. 26-JUL-12 03.02.12.000000 PM                       140           155  
            12. 26-JUL-12 03.02.14.000000 PM                       141           157  
            13.  
            14. SQL> select job,next_date from user_jobs where what='proc_session();';  
            15.  
            16.        JOB NEXT_DATE  
            17. ---------- -------------------  
            18.        145 2012-07-26-15:04:14  
            19.  
            20. SQL> select * from session_monitor;  
            21.  
            22. TIME                                     SESSION_COUNT PROCESS_COUNT  
            23. ---------------------------------------- ------------- -------------  
            24. 26-JUL-12 03.04.14.000000 PM                        87            94  
            25. 26-JUL-12 03.02.12.000000 PM                       140           155  
            26. 26-JUL-12 03.02.14.000000 PM                       141           157 

            6:如果要刪除任務,則運行下列的命令,145代表user_jobs視圖中的job列

            1. SQL> begin  
            2.   2  dbms_job.remove(145);  
            3.   3  end;  
            4. PL/SQL procedure successfully completed. 

            三:使用nagios+fetion,定時去監控會話和進程數
            1:創建監控腳本,該腳本放任務計劃中運行,每2分鐘自動執行

            1. [root@server240 libexec]# cat session_oracle.sh   
            2. #!/bin/sh  
            3. rm -rf /tmp/session_oracle.log  
            4. export ORACLE_HOME=/u01/app/oracle/product/11.2.0/db1  
            5. /u01/app/oracle/product/11.2.0/db1/bin/sqlplus hr/hr@192.168.1.240:1521/orcl <<EOF 
            6. set echo off  
            7. set feedback off  
            8. spool /tmp/session_oracle.log  
            9. alter session set nls_date_format='YYYY-MM-DD:HH24:MI:SS';  
            10. select session_count from (select * from session_monitor order by time desc ) where  rownum=1;  
            11. select process_count from (select * from session_monitor order by time desc ) where  rownum=1;  
            12. spool off  
            13. set echo on  
            14. set feedback on  EOF

            2:創建第二腳本,用來處理前面監控腳本的日志輸出,將結果返回給監控服務器

            1. [root@server240 ~]# cat /tmp/session_oracle.log
              SQL> alter session set nls_date_format='YYYY-MM-DD:HH24:MI:SS';
              SQL> select session_count from (select * from session_monitor order by time desc ) where  rownum=1;
            2. SESSION_COUNT                                                                  
              -------------                                                                  
                        138                                                                  
              SQL> select process_count from (select * from session_monitor order by time desc ) where  rownum=1;
            3. PROCESS_COUNT                                                                  
              -------------                                                                  
                        153                                                                  
              SQL> spool off
            4.  
            5. [root@server240 libexec]# cat check_oracle_session.sh   
            6. #!/bin/sh  
            7. STATE_OK=0 
            8. STATE_CRITICAL=2 
            9.  
            10. if  [ -f /tmp/session_oracle.log  ];then  
            11.      SESSION=$(grep -A 2 'SESSION_COUNT'  /tmp/session_oracle.log |tail -1|sed 's/[ ][ ]*//g')  
            12.      PROCESS=$(grep -A 2 'PROCESS_COUNT'  /tmp/session_oracle.log |tail -1|sed 's/[ ][ ]*//g')  
            13.      else   
            14.      echo "something wrong,please check monitor script"  
            15.      exit $STATE_CRITICAL  
            16. fi  
            17.  
            18. if   [ $SESSION -gt 500 ] || [ $PROCESS -gt 500 ];then   
            19.      echo "Current session is $SESSION,process is $PROCESS "  
            20.      exit $STATE_CRITICAL  
            21.      else   
            22.        echo "Current session is $SESSION,process is $PROCESS "  
            23.        exit $STATE_OK  
            24. fi 

            四:實際效果
            [root@server198 ~]# /usr/local/nagios/libexec/check_nrpe -H 192.168.1.240 -c check_oracle_session
            Current session is 138,process is 153

            五:后期觀察結果,估計和內存問題相關
            [oracle@server240 ~]$ sar -r |grep 10:20
            10:20:02 AM   3481492  21195164     85.89    675584  13661448   3683012    413552     10.10     
            [oracle@server240 ~]$ sar -r |grep 04:40
            04:40:01 PM   2076748  22599908     91.58    734088  14581728   4048864     47700      1.16

            posted @ 2012-07-28 12:43 tbwshc 閱讀(1052) | 評論 (0)編輯 收藏

            僅列出標題
            共10頁: First 2 3 4 5 6 7 8 9 10 
            久久久久久久久久久久久久| 99久久精品影院老鸭窝| 少妇人妻综合久久中文字幕| 日产精品99久久久久久| 九九久久精品无码专区| 日产精品久久久久久久性色| 欧洲性大片xxxxx久久久| 国产精品岛国久久久久| 国产 亚洲 欧美 另类 久久| 国产亚洲婷婷香蕉久久精品| 久久久久人妻精品一区二区三区| 国产精品久久久久蜜芽| 精品国产91久久久久久久| 四虎亚洲国产成人久久精品| 久久精品国产亚洲AV无码麻豆| 精品久久久久一区二区三区 | 久久综合九色综合久99| 中文字幕人妻色偷偷久久| 综合久久精品色| 亚洲午夜无码久久久久小说| 久久国产精品久久| 亚洲AV无一区二区三区久久 | 久久99精品国产麻豆宅宅| 一本大道久久香蕉成人网| 国产精品美女久久久久AV福利| 久久亚洲AV成人无码国产 | 久久久久久久女国产乱让韩| 国产高清国内精品福利99久久| 91精品国产91久久久久福利| 一本一本久久A久久综合精品 | 亚洲国产精品成人久久蜜臀 | 久久精品成人欧美大片 | 亚洲午夜久久久影院伊人| 国产一区二区久久久| 久久久久亚洲av毛片大| 狠狠色婷婷久久综合频道日韩| 欧洲性大片xxxxx久久久| 国产农村妇女毛片精品久久| 久久99精品久久久久久9蜜桃| 国产—久久香蕉国产线看观看| 久久露脸国产精品|