<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-314  評(píng)論-209  文章-0  trackbacks-0
     
    我們從一個(gè)用戶請求開始講,ORACLE的完整的工作機(jī)制是怎樣的,首先一個(gè)用戶進(jìn)程發(fā)出一個(gè)連接請求,如果使用的是主機(jī)命名或者是本地服務(wù)命中的主機(jī)名使用的是機(jī)器名(非IP地址),那么這個(gè)請求都會(huì)通過DNS服務(wù)器或HOST文件的服務(wù)名解析然后傳送到ORACLE監(jiān)聽進(jìn)程,監(jiān)聽進(jìn)程接收到用戶請求后會(huì)采取兩種方式來處理這個(gè)用戶請求,下面我們分專用服務(wù)器和共享服務(wù)器分別采用這兩種方式時(shí)的情況來講:

        專用服務(wù)器模式下:一種方式是監(jiān)聽進(jìn)程接收到用戶進(jìn)程請求后,產(chǎn)生一個(gè)新的專用服務(wù)器進(jìn)程,并且將對(duì)用戶進(jìn)程的所有控制信息傳給此服務(wù)器進(jìn)程,也就是說新建的服務(wù)器進(jìn)程繼承了監(jiān)聽進(jìn)程的信息,然后服務(wù)器進(jìn)程給用戶進(jìn)程發(fā)一個(gè)RESEND包,通知用戶進(jìn)程可以開始給它發(fā)信息了,用戶進(jìn)程給這個(gè)新建的服務(wù)器進(jìn)程發(fā)一個(gè)CONNECT包,服務(wù)器進(jìn)程再以ACCEPT包回應(yīng)用戶進(jìn)程,致此,用戶進(jìn)程正式與服務(wù)器進(jìn)程確定連接。我們把這種連接叫做HAND-OFF連接,也叫轉(zhuǎn)換連接。另一種方式是監(jiān)聽進(jìn)程接收到用戶進(jìn)程的請求后產(chǎn)生一個(gè)新的專用服務(wù)器進(jìn)程,這個(gè)服務(wù)器進(jìn)程選用一個(gè)TCP/IP端口來控制與用戶進(jìn)程的交互,然后將此信息回傳給監(jiān)聽進(jìn)程,監(jiān)聽進(jìn)程再將此信息傳給用戶進(jìn)程,用戶進(jìn)程使用這個(gè)端口給服務(wù)器進(jìn)程發(fā)送一個(gè)CONNECT包,服務(wù)器進(jìn)程再給用戶進(jìn)程發(fā)送一個(gè)ACCEPT包,致此,用戶進(jìn)程可以正式向服務(wù)器進(jìn)程發(fā)送信息了。這種方式我們叫做重定向連接。HAND-OFF連接需要系統(tǒng)平臺(tái)具有進(jìn)程繼承的能力,為了使WINDOWS NT/2000支持HAND-OFF必須在HKEY_LOCAL_MACHINE>SOFTWARE>ORACLE>HOMEX中設(shè)置USE_SHARED_SOCKET。

        共享服務(wù)器模式下:只有重定向連接的方式,工作方式是監(jiān)聽進(jìn)程接收到用戶進(jìn)程的請求后產(chǎn)生一個(gè)新的調(diào)度進(jìn)程,這個(gè)調(diào)度進(jìn)程選用一個(gè)TCP/IP端口來控制與用戶進(jìn)程的交互,然后將此信息回傳給監(jiān)聽進(jìn)程,監(jiān)聽進(jìn)程再將此信息傳給用戶進(jìn)程,用戶進(jìn)程使用這個(gè)端口給調(diào)度進(jìn)程發(fā)送一個(gè)CONNECT包,調(diào)度進(jìn)程再給用戶進(jìn)程發(fā)送一個(gè)ACCEPT包,致此,用戶進(jìn)程可以正式向調(diào)度進(jìn)程發(fā)送信息了。可以通過設(shè)置MAX_DISPIATCHERS這個(gè)參數(shù)來確定調(diào)度進(jìn)程的最大數(shù)目,如果調(diào)度進(jìn)程的個(gè)數(shù)已經(jīng)達(dá)到了最大,或者已有的調(diào)度進(jìn)程不是滿負(fù)荷,監(jiān)聽進(jìn)程將不再創(chuàng)建新的調(diào)度進(jìn)程,而是讓其中一個(gè)調(diào)度進(jìn)程選用一個(gè)TCP/IP端口來與此用戶進(jìn)程交互。調(diào)度進(jìn)程每接收一個(gè)用戶進(jìn)程請求都會(huì)在監(jiān)聽進(jìn)程處作一個(gè)登記,以便監(jiān)聽進(jìn)程能夠均衡每個(gè)調(diào)度進(jìn)程的負(fù)荷,所有的用戶進(jìn)程請求將分別在有限的調(diào)度進(jìn)程中排隊(duì),所有調(diào)度進(jìn)程再順序的把各自隊(duì)列中的部分用戶進(jìn)程請求放入同一個(gè)請求隊(duì)列,等候多個(gè)ORACLE的共享服務(wù)器進(jìn)程進(jìn)行處理(可以通過SHARED_SERVERS參數(shù)設(shè)置共享服務(wù)器進(jìn)程的個(gè)數(shù)),也就是說所有的調(diào)度進(jìn)程共享同一個(gè)請求隊(duì)列,共享服務(wù)器模式下一個(gè)實(shí)例只有一個(gè)請求隊(duì)列,共享服務(wù)器進(jìn)程處理完用戶進(jìn)程的請求后將根據(jù)用戶進(jìn)程請求取自不同的調(diào)度進(jìn)程將返回結(jié)果放入不同的響應(yīng)隊(duì)列,也就是說有多少調(diào)度進(jìn)程就有多少響應(yīng)隊(duì)列,然后各個(gè)調(diào)度進(jìn)程從各自的響應(yīng)隊(duì)列中將結(jié)果取出再返回給用戶進(jìn)程。

        以上我們講完了用戶與ORACLE的連接方式,下面我們要講ORACLE服務(wù)器進(jìn)程如可處理用戶進(jìn)程的請求,當(dāng)一個(gè)用戶進(jìn)程發(fā)出了一條SQL語名:UPDATE TABBLEA SET SALARY=SALARY*2;首先,服務(wù)器進(jìn)程把這條語句的字符轉(zhuǎn)換成ASCII等效數(shù)字碼,接著這個(gè)ASCII碼被傳遞給一個(gè)HASH函數(shù),并返回一個(gè)HASH值,服務(wù)器進(jìn)程將到SHARED POOL 的共享PL/SQL區(qū)去查找是否存在同樣的HASH值,如果存在,服務(wù)器進(jìn)程將使用這條語句已高速緩存在SHARED POOL中的已分析過的版本來執(zhí)行,如果不存在,服務(wù)器進(jìn)程將對(duì)該語句進(jìn)行語法分析,首先檢查該語句的語法的正確性,接著對(duì)語句中涉及的表、索引、視圖等對(duì)象進(jìn)行解析,并對(duì)照數(shù)據(jù)字典檢查這些對(duì)象的名稱以及相關(guān)結(jié)構(gòu),并根據(jù)ORACLE選用的優(yōu)化模式以及數(shù)據(jù)字典中是否存在相應(yīng)對(duì)象的統(tǒng)計(jì)數(shù)據(jù)和是否使用了存儲(chǔ)大綱來生成一個(gè)執(zhí)行計(jì)劃或從存儲(chǔ)大綱中選用一個(gè)執(zhí)行計(jì)劃,然后再用數(shù)據(jù)字典核對(duì)此用戶對(duì)相應(yīng)對(duì)象的執(zhí)行權(quán)限,最后生成一個(gè)編譯代碼。ORACLE將這條語名的本身實(shí)際文本、HASH值、編譯代碼、與此語名相關(guān)聯(lián)的任何統(tǒng)計(jì)數(shù)據(jù)和該語句的執(zhí)行計(jì)劃緩存在SHARED POOL的共享PL/SQL區(qū)。服務(wù)器進(jìn)程通過SHARED POOL 鎖存器來申請可以向哪些共享PL/SQL區(qū)中緩存這此內(nèi)容,也就是說被SHARED POOL鎖存器鎖定的PL/SQL區(qū)中的塊不可被覆蓋,因?yàn)檫@些塊可能被其它進(jìn)程所使用。在SQL分析階段將用到LIBRARY CACHE,從數(shù)據(jù)字典中核對(duì)表、視圖等結(jié)構(gòu)的時(shí)候,需要將數(shù)據(jù)字典從磁盤讀入LIBRARY CACHE,因此,在讀入之前也要使用LIBRARY CACHE鎖存器來申請用于緩存數(shù)據(jù)字典。

        生成編譯代碼之后,接著下一步服務(wù)器進(jìn)程要準(zhǔn)備開始更新數(shù)據(jù),服務(wù)器進(jìn)程將到DB BUFFER中查找是否有相關(guān)對(duì)象的緩存數(shù)據(jù),下面分兩個(gè)可能進(jìn)行解釋:

        如果沒有,服務(wù)器進(jìn)程將在表頭部請求一些行鎖,如果成功加鎖,服務(wù)器進(jìn)程將從數(shù)據(jù)文件中讀這些行所在的數(shù)據(jù)塊放入DB BUFFER中空閑的區(qū)域或者覆蓋已被擠出LRU列表的非臟數(shù)據(jù)塊緩沖區(qū),并且排列在LRU列表的頭部,如果這些非臟數(shù)據(jù)緩沖區(qū)寫完也不能滿足新數(shù)據(jù)的請求時(shí),會(huì)立即觸發(fā)DBWN進(jìn)程將臟數(shù)據(jù)列表中指向的緩沖塊寫入數(shù)據(jù)文件,并且清洗掉這些緩沖區(qū),來騰出空間緩沖新讀入的數(shù)據(jù),也就是在放入DB BUFFER之前也是要先申請DB BUFFER中的鎖存器,成功鎖定后,再寫入DB BUFFER,然后服務(wù)器程將該語句影響的被讀入DB BUFFER塊中的這些行的ROWID及將要更新的原值和新值及SCN等信息逐條的寫入REDO LOG BUFFER,在寫入REDO LOG BUFFER之前也是先請求REDO LOG BUFFER塊的鎖存器,成功鎖定之后才開始寫入,當(dāng)寫入達(dá)到REDO LOG BUFFER大小的三分之一或?qū)懭肓窟_(dá)到1M或超過三秒后或發(fā)生檢查點(diǎn)時(shí)或者DBWN之前發(fā)生,LGWR將把REDO LOG BUFFER中的數(shù)據(jù)寫入磁盤上的重做日志文件,已被寫入重做日志文件的REDO LOG BUFFER中的塊上的鎖存器被釋放,并可被后來寫入的信息所覆蓋,REDO LOG BUFFER以循環(huán)的方式工作。當(dāng)一個(gè)重做日志文件寫滿后,LGWR將切換到下一個(gè)重做日志文件,如果是歸檔模式,歸檔進(jìn)程還將前一個(gè)寫滿的重做日志進(jìn)程寫入歸檔日志文件,重做日志文件也是循環(huán)工作方式。寫完所有的REDO LOG BUFFER之后,服務(wù)器進(jìn)程開始改寫這個(gè)DB BUFFER塊頭部的事務(wù)列表并寫入SCN,然后COPY包含這個(gè)塊的頭部事務(wù)列表及SCN信息的數(shù)據(jù)副本放入回滾段中,我們將回滾段中的副本稱為數(shù)據(jù)塊的“前映像”。(回滾段可以存儲(chǔ)在專門的回滾表空間中,這個(gè)表空間由一個(gè)或多個(gè)物理文件組成,并專用于回滾表空間,回滾段也可在其它表空間中的數(shù)據(jù)文件中開辟。)然后改寫這個(gè)DB BUFFER塊的數(shù)據(jù),并在其頭部寫入對(duì)應(yīng)的回滾段地址,如果對(duì)一行數(shù)據(jù)多次UPDATE而不COMMIT則在回滾段中將會(huì)有多個(gè)“前映像”,除第一個(gè)“前映像”含有SCN信息外,其它的每個(gè)“前映像”的頭部還含有SCN信息和“前前映像”的回滾段地址。一次UPDATE操作只對(duì)應(yīng)一個(gè)SCN。然后服務(wù)器進(jìn)程在臟數(shù)據(jù)列表中建立一條指向此緩沖塊的指針。接著服務(wù)器進(jìn)程會(huì)從數(shù)據(jù)文件讀入第二個(gè)塊重復(fù)以上讀入,記日志,建立回滾段,修改,放入臟列表的動(dòng)作,當(dāng)臟數(shù)據(jù)列表達(dá)到一定長度時(shí),DBWN進(jìn)程將臟數(shù)據(jù)列表中指向的緩沖塊全部寫入數(shù)據(jù)文件,也就是釋放加在這些DB BUFER 塊上的鎖存器。其實(shí)ORACLE可以一次從數(shù)據(jù)文件中讀入幾個(gè)塊放入DB BUFFER,可以通過參數(shù)DB_FILE_MULTIBLOCK_READ_COUNT來設(shè)置一次讀入的塊的個(gè)數(shù)。

        如果要查找的數(shù)據(jù)已緩存,則根據(jù)用戶的SQL操作類型決定如何操作,如果是SELECT 則查看DB BUFFER塊的頭部是否有事務(wù),如果有,將從回滾段讀取,如果沒有則比較SELECT 的SCN與DB BUFFER塊頭部的SCN如果比自己大,仍然從回滾段讀取,如果比自己小則認(rèn)這是一個(gè)非臟緩存,可以直接從這個(gè)DB BUFFER塊中讀取。如果是UPDATE則即使在DB BUFFER中找到一個(gè)沒有事務(wù),而且SCN比自己小的非臟緩存數(shù)據(jù)塊,服務(wù)器進(jìn)程仍然要到表的頭部對(duì)這條記錄申請加鎖,加鎖成功則進(jìn)行后續(xù)動(dòng)作,如果不成功,則要等待前面的進(jìn)程解鎖后才能進(jìn)行動(dòng)作。

        只有當(dāng)SQL語句影響的所有行所在的最后一個(gè)塊被讀入DB BUFFER并且重做信息被寫入REDO LOG BUFFER(僅是指重做日志緩沖,而非重做日志文件)之后,用戶才可以發(fā)出COMMIT,COMMIT觸發(fā)LGRW,但并不強(qiáng)制立即DBWN來釋放所有相應(yīng)的DB BUFFER塊上的鎖,也就是說有可能出現(xiàn)已COMMIT,但在隨后的一段時(shí)間內(nèi)DBWN還在寫這條語句涉及的數(shù)據(jù)塊的情形,表頭部的行鎖,并不是在COMMIT一發(fā)出就馬上釋放,實(shí)際上要等到相應(yīng)的DBWN進(jìn)程結(jié)束才會(huì)釋放。一個(gè)用戶請求鎖定另一個(gè)用戶已COMMIT的資源不成功的機(jī)會(huì)是存在的,從COMMIT到DBWN進(jìn)程結(jié)束之間的時(shí)間很短,如果恰巧在這個(gè)時(shí)間斷電,由于COMMIT已觸發(fā)LGWR進(jìn)程,所以這些未來得及寫入數(shù)據(jù)文件的改變會(huì)在實(shí)例重啟后由SMON進(jìn)程根據(jù)重做日志文件來前滾。如果未COMMIT就斷電,由于DBWN之前觸發(fā)LGWR,所有DBWN在數(shù)據(jù)文件上的修改都會(huì)被先一步記入重做日志文件,實(shí)例重啟后,SMON進(jìn)程再根據(jù)重做日志文件來回滾。

        如果用戶ROOLBACK,則服務(wù)器進(jìn)程會(huì)根據(jù)數(shù)據(jù)文件塊和DB BUFFER中塊的頭部的事務(wù)列表和SCN以及回滾段地址找到回滾段中相應(yīng)的修改前的副本,并且用這些原值來還原當(dāng)前數(shù)據(jù)文件中已修改但未提交的改變。如果有多個(gè)“前映像”,服務(wù)器進(jìn)程會(huì)在一個(gè)“前映像”的頭部找到“前前映像”的回滾段地址,一直找到同一事務(wù)下的最早的一個(gè)“前映像”為止。一旦發(fā)出了COMMIT,用戶就不能ROOLBACK,這使得COMMIT后DBWN進(jìn)程還沒有全部完成的后續(xù)動(dòng)作得到了保障。

        下面我們要提到檢查點(diǎn)的作用,當(dāng)一個(gè)全部檢查點(diǎn)發(fā)生的時(shí)候,首先讓LGWR進(jìn)程將REDO LOG BUFFER中的所有緩沖(包含未提交的重做信息)寫入重做日志文件,然后讓DBWN進(jìn)程將DB BUFFER中所有已提交的緩沖寫入數(shù)據(jù)文件(不強(qiáng)制寫未提交的)。然后更新控制文件和數(shù)據(jù)文件頭部的SCN,表明當(dāng)前數(shù)據(jù)庫是一致的,如果在發(fā)生檢點(diǎn)之前斷電,并且當(dāng)時(shí)有一個(gè)未提交的改變正在進(jìn)行,實(shí)例重啟之后,SMON進(jìn)程將從上一個(gè)檢查點(diǎn)開始核對(duì)這個(gè)檢查點(diǎn)之后記錄在重做日志文件中已提交的和未提交改變,因?yàn)镈BWN之前會(huì)觸發(fā)LGWR,所以DBWN對(duì)數(shù)據(jù)文件的修改一定會(huì)被先記錄在重做日志文件中。因此,斷電前被DBWN寫進(jìn)數(shù)據(jù)文件的改變將通過重做日志文件中的記錄進(jìn)行還原,叫做回滾,如果斷電時(shí)有一個(gè)已提交,但DBWN動(dòng)作還沒有完全完成的改變存在,因?yàn)橐呀?jīng)提交,提交會(huì)觸發(fā)LGWR進(jìn)程,所以不管DBWN動(dòng)作是否已完成,該語句將要影響的行及其產(chǎn)生的結(jié)果一定已經(jīng)記錄在重做日志文件中了,則實(shí)例重啟后,SMON進(jìn)程根據(jù)重做日志文件進(jìn)行前滾。由此可見,實(shí)例失敗后用于恢復(fù)的時(shí)間由兩個(gè)檢查點(diǎn)之間的間隔大小來決定,我們可以通個(gè)四個(gè)參數(shù)設(shè)置檢查點(diǎn)執(zhí)行的頻率,LOG_CHECKPOINT_IMTERVAL決定了兩個(gè)檢查點(diǎn)之間寫入重做日志文件的系統(tǒng)物理塊的大小,LOG_CHECKPOINT_TIMEOUT決定了兩個(gè)檢查點(diǎn)之間的時(shí)間長度,F(xiàn)AST_START_IO_TARGET決定了用于恢復(fù)時(shí)需要處理的塊的大小,F(xiàn)AST_START_MTTR_TARGET直接決定了用于恢復(fù)的時(shí)間的長短。SMON進(jìn)程執(zhí)行的前滾和回滾與用戶的回滾是不同的,SMON是根據(jù)重做日志文件進(jìn)行前滾或回滾,而用戶的回滾一定是根據(jù)回滾段的內(nèi)容進(jìn)行回滾的。在這里我們要說一下回滾段存儲(chǔ)的數(shù)據(jù),假如是delete操作,則回滾段將會(huì)記錄整個(gè)行的數(shù)據(jù),假如是update,則回滾段只記錄被修改了的字段的變化前的數(shù)據(jù)(前映像),也就是沒有被修改的字段是不會(huì)被記錄的,假如是insert,則回滾段只記錄插入記錄的rowid。這樣假如事務(wù)提交,那回滾段中簡單標(biāo)記該事務(wù)已經(jīng)提交;假如是回退,則如果操作是是delete,回退的時(shí)候把回滾段中數(shù)據(jù)重新寫回?cái)?shù)據(jù)塊,操作如果是update,則把變化前數(shù)據(jù)修改回去,操作如果是insert,則根據(jù)記錄的rowid 把該記錄刪除。

        下面我們要講DBWN如何來寫數(shù)據(jù)文件,在寫數(shù)據(jù)文件前首先要找到可寫的空閑數(shù)據(jù)塊,ORACLE中空閑數(shù)據(jù)塊可以通過FREELIST或BITMAP來維護(hù),它們位于一個(gè)段的頭部用來標(biāo)識(shí)當(dāng)前段中哪些數(shù)據(jù)塊可以進(jìn)行INSERT。在本地管理表空間中ORACLE自動(dòng)管理分配給段的區(qū)的大小,區(qū)的分配信息存儲(chǔ)在組成表空間的數(shù)據(jù)文件的頭部,而數(shù)據(jù)字典管理的表空間用戶可以在創(chuàng)建時(shí)決定區(qū)的大小,并且區(qū)的分配信息是存儲(chǔ)在數(shù)據(jù)字典中的,只在本地管理的表空間中才能選用段自動(dòng)管理,采用自動(dòng)段空間管理的本地管理表空間中的段中的空閑數(shù)據(jù)塊的信息就存放在段的頭部并且使用位圖來管理,采用手動(dòng)管理的本地管理表空間中的段和數(shù)據(jù)字典管理的表空間中的段中的空閑數(shù)據(jù)塊的管理都使用位于段頭部的空閑列表來管理,空閑列表的工作方式:首先一個(gè)空的數(shù)據(jù)塊被加入空閑列表,當(dāng)其中空閑空間小于PCTFREE設(shè)置的值之后,這個(gè)塊從空閑列表刪除,當(dāng)這個(gè)塊中的內(nèi)容降至PCTUSED設(shè)置的值之下后,這個(gè)數(shù)據(jù)塊被再次加入空閑列表,位于空閑列表中的數(shù)據(jù)塊都是可以向其中INSERT的塊,當(dāng)一個(gè)塊移出了空閑列表,但只要其中還有保留空間就可以進(jìn)行UPDATE,當(dāng)對(duì)其中一行UPDATE一個(gè)大數(shù)據(jù)時(shí),如果當(dāng)前塊不能完全放下整個(gè)行,只會(huì)把整個(gè)行遷移到一個(gè)新的數(shù)據(jù)塊,并在原塊位置留下一個(gè)指向新塊的指針,這叫行遷移。如果一個(gè)數(shù)據(jù)塊可以INSERT,當(dāng)插入一個(gè)當(dāng)前塊裝不下的行時(shí),這個(gè)行會(huì)溢出到兩個(gè)或兩個(gè)幾上的塊中,這叫行鏈接。如果用戶的動(dòng)作是INSERT 則服務(wù)器進(jìn)程會(huì)先鎖定FREELIST,然后找到空閑塊的地址,再釋放FREELIST,當(dāng)多個(gè)服務(wù)器進(jìn)程同時(shí)想要鎖定FREELIST時(shí)即發(fā)生FREELIST的爭用,可以在非采用自動(dòng)段空間管理的表空間中創(chuàng)建表時(shí)指定FREELIST的個(gè)數(shù),默認(rèn)為1,如果是在采用自動(dòng)段空間管理的表空間中創(chuàng)建表,即使指定了FREELIST也會(huì)被忽略,因?yàn)榇藭r(shí)將使用BITMAP而不是FREELIST來管理段中的空閑空間。如果用戶動(dòng)作是UPDATE服務(wù)器進(jìn)程將不會(huì)使用到FREELIST和BITMAP,因?yàn)椴灰ふ乙粋€(gè)空閑塊,而使用鎖的隊(duì)列。

        下面來講一下ORACLE鎖的機(jī)制,ORACLE分鎖存器和鎖兩種。鎖存器是用來保護(hù)對(duì)內(nèi)存結(jié)構(gòu)的訪問,比如對(duì)DB BUFFER中塊的鎖存器申請,只有在DBWN完成后,這些DB BUFFER塊被解鎖。然后用于其它的申請。鎖存器不可以在進(jìn)程間共享,鎖存器的申請要么成功要么失敗,沒有鎖存器申請隊(duì)列。主要的鎖存器有SHARED POOL鎖存器,LIBRARY CACHE鎖存器,CACHE BUFFERS LRU CHAIN鎖存器,CACHE BUFFERS CHAINS 鎖存器,REDO ALLOCATION 鎖存器,REDO COPY 鎖存器。ORACLE的鎖是用來保護(hù)數(shù)據(jù)訪問的,鎖的限制比鎖存器要更寬松,比如,多個(gè)用戶在修改同一表的不同行時(shí),可以共享一個(gè)表上的一個(gè)鎖,鎖的申請可以按照被申請的順序來排隊(duì)等候,然后依次應(yīng)用,這種排隊(duì)機(jī)制叫做隊(duì)列(ENPUEUE),如果兩個(gè)服務(wù)器進(jìn)程試圖對(duì)同一表的同一行進(jìn)行加鎖,則都進(jìn)入鎖的申請隊(duì)列,先進(jìn)的加鎖成功,后面的進(jìn)程要等待,直到前一個(gè)進(jìn)程解鎖才可以加鎖,這叫做鎖的爭用,而且一旦加鎖成功,這個(gè)鎖將一直保持到用戶發(fā)出COMMIT或ROOLBACK命令為止。如果兩個(gè)用戶鎖定各自的一行并請求對(duì)方鎖定的行的時(shí)候?qū)l(fā)生無限期等待即死鎖,死鎖的發(fā)生都是由于鎖的爭用而不是鎖存器的爭用引起的,ORACLE在遇到死鎖時(shí),自動(dòng)釋放其中一個(gè)用戶的鎖并回滾此用戶的改變。正常情況下發(fā)生鎖的爭用時(shí),數(shù)據(jù)的最終保存結(jié)果由SCN來決定哪個(gè)進(jìn)程的更改被最終保存。兩個(gè)用戶的服務(wù)器進(jìn)程在申請同一表的多個(gè)行的鎖的時(shí)候是可以交錯(cuò)進(jìn)入鎖的申請隊(duì)列的。只有其中發(fā)生爭用才會(huì)進(jìn)行等待。創(chuàng)建表時(shí)指定的MAXTRANS參數(shù)決了,表中的一個(gè)數(shù)據(jù)塊最多可以被幾個(gè)事務(wù)同時(shí)鎖定。

        下面是幾個(gè)關(guān)于回滾段和死鎖的事例:

        有表:Test (id number(10)) 有記錄1000000條

    一,大SELECT,小UPDATE
        A會(huì)話----Select * from test;----設(shè)scn=101----執(zhí)行時(shí)間09:10:11
        B會(huì)話-----Update test set id=9999999 where id=1000000----設(shè)scn=102-----執(zhí)行時(shí)間09:10:12

        我們會(huì)發(fā)現(xiàn)B會(huì)話會(huì)在A會(huì)話前完成,A會(huì)話中顯示的ID=100000是從回滾段中讀取的,因?yàn)锳會(huì)話在讀到ID=1000000所在的BLOCK時(shí)發(fā)現(xiàn)BLOCK上有事務(wù)信息,因此要從回滾段中讀,如果UPDATE在SELECT讀到此BLOCK之前已經(jīng)COMMIT,則SELECT 讀到此BLOCK時(shí)發(fā)現(xiàn)其BLOCK上沒有事務(wù)信息,但是會(huì)發(fā)現(xiàn)其BLICK的SCN比SELECT自己的SCN大,因此也會(huì)從回滾段中讀取。因此是否從回滾段讀一是看是否有事務(wù)信息二是比較SCN大小。如果B會(huì)話在A會(huì)話結(jié)束前連續(xù)多次對(duì)同一條記錄UPDATE并COMMIT,那么在回滾段中將記錄多個(gè)“前映像”,而每個(gè)“前映像”中不但包括了原BLOCK的數(shù)據(jù)和SCN也記錄了“前前映像”的回滾段地址,因此A會(huì)話在查詢到被UPDATE過的BLOCK時(shí),會(huì)根據(jù)BLOCK記錄的回滾段的地址,找到回滾段中的“前映像”,發(fā)現(xiàn)這個(gè)“前映像”的SCN也比自己的大,因此將根據(jù)這個(gè)“前映像”中記錄的“前前映像”的回滾段地址,在回滾段中找到“前前映像”,再與這個(gè)“前前映像”比較SCN,如果比自己小就讀取,如果還比自己大,則重復(fù)以上步驟,直到找到比自己SCN小的“前…前映像”為止,如果找不到,就會(huì)報(bào)ORA-01555快照太舊這個(gè)錯(cuò)誤。

    二、大UPDATE,小SELECT

        A會(huì)話----Update test set id=1;----設(shè)scn=101----執(zhí)行時(shí)間09:10:11
        B會(huì)話-----select * from test where id=1000000----設(shè)scn=102-----執(zhí)行時(shí)間09:10:12

        我們會(huì)發(fā)現(xiàn)B會(huì)話會(huì)在A會(huì)話前完成,B會(huì)話中顯示的ID=1000000是從BLOCK中直接讀取的,因?yàn)锽會(huì)話在讀到ID=1000000所在的BLOCK時(shí),A會(huì)話還沒有來得及對(duì)其鎖定,因此B會(huì)話既不會(huì)發(fā)現(xiàn)BLOCK上有事務(wù)信息,也不會(huì)發(fā)現(xiàn)BLOCK上的SCN比SELECT的大,因此會(huì)從BLOCK中直接讀取,如果SELECT在UPDATE鎖定此BLOCK后才發(fā)出,B會(huì)話讀到此BLOCK時(shí)發(fā)現(xiàn)其BLOCK上有事務(wù)信息,因此會(huì)從回滾段中讀取。

    三、大UPDATE,小UPDATE

        A會(huì)話----Update test set id=1;----設(shè)scn=101----執(zhí)行時(shí)間09:10:11
        B會(huì)話1-----Update test set id=999999 where id=1000000----設(shè)scn=102-----執(zhí)行時(shí)間09:10:12 
        B會(huì)話2----- select * from test where id=2----設(shè)scn=103-----執(zhí)行時(shí)間09:10:14 
        B會(huì)話3----- update test set id=3 where id=2----設(shè)scn=104-----執(zhí)行時(shí)間09:10:15

        我們會(huì)發(fā)現(xiàn)B會(huì)話1會(huì)完成,A會(huì)話將一直等待,因?yàn)锽會(huì)話1會(huì)先于A會(huì)話鎖定ID=1000000所在的BLOCK,并改寫頭部的事務(wù)信息,A會(huì)話在試圖鎖定此BLOCK時(shí),發(fā)現(xiàn)其上有事務(wù)信息,將會(huì)一直等待B會(huì)話1事務(wù)結(jié)束后再行鎖定, B會(huì)話2查詢到的ID=2是從回滾段中讀取的而不是從BLOCK中直接讀出來的。因?yàn)锳會(huì)話已將ID=2的BLOCK鎖定,并寫入了回滾段,從B會(huì)話3可以證明這一點(diǎn),B會(huì)話3發(fā)出后,B會(huì)話3會(huì)收到死鎖的信息,死鎖的原因是A會(huì)話在等待B會(huì)話對(duì)ID=1000000所在的BLOCK解鎖,現(xiàn)在B會(huì)話又在等待A會(huì)話對(duì)ID=2所在的BLOCK解鎖,因此形成死鎖,因此證明ID=2所在的BLOCK已被A會(huì)話鎖定,然后A會(huì)話也會(huì)收到死鎖的信息

    posted @ 2010-06-28 10:42 xzc 閱讀(175) | 評(píng)論 (0)編輯 收藏
    #文件行數(shù)
    file_count=`wc -l /odsstatfs/groupfile/${file_name} | awk '{print $1}'`
    echo "文件行數(shù):${file_count}"
    #文件大小
    file_size=`ls -l /odsstatfs/groupfile/${file_name} | awk '{print $5}'`
    echo "文件大小:${file_size}"


    總結(jié)了一下有五種方法:

      現(xiàn)在有一個(gè)a文件,共有55行

      第一種:

      # awk '{print NR}' a|tail -n1

      55

      第二種:

      begincwcw兄的這個(gè):

      # awk 'END{print NR}' a

      55

      第三種:

      # grep -n "" a|awk -F: '{print '}|tail -n1

      55

      第四種:

      honbj兄的也不錯(cuò):

      # sed -n '$=' a

      55

      第五種

      # wc -l a|awk '{print }'

      55

      第六種

      #cat a |wc -l

      55


    文件內(nèi)容統(tǒng)計(jì)命令:wc
    http://www.fanqiang.com (2001-05-08 14:24:15)
    wc命令的功能為統(tǒng)計(jì)指定文件中的字節(jié)數(shù)、字?jǐn)?shù)、行數(shù), 并將統(tǒng)計(jì)結(jié)果顯示輸出。 

    語法:wc [選項(xiàng)] 文件… 

    說明:該命令統(tǒng)計(jì)給定文件中的字節(jié)數(shù)、字?jǐn)?shù)、行數(shù)。如果沒有給出文件名,則從標(biāo)準(zhǔn)輸入讀取。wc同時(shí)也給出所有指定文件的總統(tǒng)計(jì)數(shù)。字是由空格字符區(qū)分開的最大字符串。 

    該命令各選項(xiàng)含義如下: 

    - c 統(tǒng)計(jì)字節(jié)數(shù)。 

    - l 統(tǒng)計(jì)行數(shù)。 

    - w 統(tǒng)計(jì)字?jǐn)?shù)。 

    這些選項(xiàng)可以組合使用。 

    輸出列的順序和數(shù)目不受選項(xiàng)的順序和數(shù)目的影響。總是按下述順序顯示并且每項(xiàng)最多一列。 

    行數(shù)、字?jǐn)?shù)、字節(jié)數(shù)、文件名 

    如果命令行中沒有文件名,則輸出中不出現(xiàn)文件名。 

    例如: 

    $ wc - lcw file1 file2 

    4 33 file1 

    7 52 file2 

    11 11 85 total 

    省略任選項(xiàng)-lcw,wc命令的執(zhí)行結(jié)果與上面一樣。 
    posted @ 2010-04-22 14:56 xzc 閱讀(4058) | 評(píng)論 (0)編輯 收藏

    一、特殊符號(hào)ascii定義
     制表符 chr(9)
     換行符 chr(10)
     回車符 chr(13)

    二、嵌套使用repalce,注意每次只能提交一個(gè)符號(hào),如先回車再換行
              select REPLACE(gg, chr(10), '') from dual
        要注意chr(13) | | chr(10) 此類結(jié)合使用的情況比較多,回車換行在notepad中是比較好看點(diǎn)的,所以要考慮此種情況
              select translate(string,chr(13)||chr(10),',') from dual;
    1、例子一
    create table TEST_1
    (
      VA  VARCHAR2(10),
      VB  NUMBER(2),
      VC  VARCHAR2(10),
      VD  NUMBER(11,2),
      VE  NUMBER(11,4),
      VCL CLOB
    );

    SQL> select vb,vc,replace(vc,chr(10),'') as TT, translate(vc,chr(10),',') from test_1;
     
     VB VC         TT         TRANSLATE(VC,CHR(10),',')
    --- ---------- ---------- -------------------------
      0 Aaaaaaaaa  Aaaaaaaaa  Aaaaaaaaa
      1 Aaaaaaaaa  Aaaaaaaaa  Aaaaaaaaa
      2 大Ba       大Babc帶   大Ba,b,c帶
        b                    
        c帶                  
     
      3 C          C          C
      1 D          D          D
      5 A          A          A
      5 A          A          A
      0 A          A          A
      0 A          A          A
     
     2、例子二
    要注意chr(13) | | chr(10) 此類結(jié)合使用的情況比較多,回車換行在notepad中是比較好看點(diǎn)的,所以要考慮此種情況
    select vb,vc,replace(vc,chr(10),'') as TT, translate(vc,chr(13)||chr(10),',') from test_1;
    SQL> select vb,vc,replace(vc,chr(10),'') as TT, translate(vc,chr(13)||chr(10),',') from test_1;
     
     VB VC         TT         TRANSLATE(VC,CHR(13)||CHR(10),
    --- ---------- ---------- ------------------------------
      0 Aaaaaaaaa  Aaaaaaaaa  Aaaaaaaaa
      1 Aaaaaaaaa  Aaaaaaaaa  Aaaaaaaaa
      2 大Ba       大Babc帶   大Babc帶
        b                    
        c帶                  
     
      3 C          C          C
      1 D          D          D
      5 A          A          A
      5 A          A          A
      0 A          A          A
      0 A          A          A
     
    11 rows selected

    三、對(duì)于字符大對(duì)象的符號(hào)處理
        對(duì)于clob字段中的符號(hào)處理,先to_char然后一樣的處理

    SQL> select to_char(vcl),replace(to_char(vcl),chr(10),'[]') from test_1;
     
    TO_CHAR(VCL)                                                                     REPLACE(TO_CHAR(VCL),CHR(10),'
    -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
    嵌套使用repalce,注意每次只能提交一個(gè)符號(hào),如先回車再換行                        嵌套使用repalce,注意每次只能提交一個(gè)符號(hào),如先回車再換行[]select REPLACE(gg, chr(10), '') from dual[]sel
    select REPLACE(gg, chr(10), '') from dual                                       
    select translate(string,chr(13)||chr(10),',') from dual;    

    func:

     

    2.2.1      單記錄字符函數(shù)

            函     數(shù)                      說                明
      ASCII                     返回對(duì)應(yīng)字符的十進(jìn)制值
      CHR                       給出十進(jìn)制返回字符 
     CONCAT                    拼接兩個(gè)字符串,與  ||       相同
      INITCAT                   將字符串的第一個(gè)字母變?yōu)榇髮?
      INSTR                     找出某個(gè)字符串的位置
      INSTRB                    找出某個(gè)字符串的位置和字節(jié)數(shù)
      LENGTH                    以字符給出字符串的長度
      LENGTHB                   以字節(jié)給出字符串的長度
      LOWER                     將字符串轉(zhuǎn)換成小寫
      LPAD                      使用指定的字符在字符的左邊填充
      LTRIM                     在左邊裁剪掉指定的字符
      RPAD                      使用指定的字符在字符的右邊填充
      RTRIM                     在右邊裁剪掉指定的字符
      REPLACE                   執(zhí)行字符串搜索和替換
      SUBSTR                    取字符串的子串
      SUBSTRB                   取字符串的子串(以字節(jié))
      SOUNDEX                   返回一個(gè)同音字符串
      TRANSLATE                 執(zhí)行字符串搜索和替換
      TRIM                      裁剪掉前面或后面的字符串
      UPPER                     將字符串變?yōu)榇髮?
      NVL                       以一個(gè)值來替換空值

    ASCII(<c1>)
    <c1>是字符串。返回與指定的字符對(duì)應(yīng)的十進(jìn)制數(shù)。
    SQL> select ascii('A') A,ascii('a') a,ascii('0') zero,ascii(' ') space from dual;

         A      a  ZERO   SPACE
    ---------- ---------- ---------- ----------
         65     97     48     32

    SQL> select ascii('趙') zhao,length('趙') leng from dual;

          ZHAO        LENG
        ----------  ----------
         54740         1

    CHR(<I>[NCHAR])
    給出整數(shù),返回對(duì)應(yīng)字符。如:

    SQL> select chr(54740) zhao,chr(65) chr65 from dual;

    ZH   C
    --  -
    趙  A

    CONCAT(<c1>,<c2>)
    SQL> select concat('010-','8801 8159')||'轉(zhuǎn)23' 趙元杰電話  from dual;

    趙元杰電話

    -----------------

    010-8801 8159 轉(zhuǎn)23

    INITCAP(<c1>)

    返回字符串c1       并第一個(gè)字母變?yōu)榇髮憽@纾?

    SQL> select initcap('simth') upp from dual;

    UPP
    -----
    Simth

    INSTR(<c1>,<c2>[,<I>[,<j>] ] )
    在一個(gè)字符串中搜索指定的字符,返回發(fā)現(xiàn)指定的字符的位置。
    C1: 被搜索的字符串 
    C2: 希望搜索的字符串 
    I: 搜索的開始位置,缺省是1 
    J: 出現(xiàn)的位置,缺省是1。 

    SQL> SELECT INSTR ('Oracle Training', 'ra', 1, 2) "Instring" FROM DUAL;

      Instring

    ----------

            9

    INSTRB(<c1>,<c2>[,<I>[,<j>] ] )

    除了返回的字節(jié)外 ,與INSTR              相同,

    LENGTH( <c> )

    返回字符串  c      的長度。

    SQL> l
     1  select name,length(name),addr,length(addr),sal,length(to_char(sal))
      2* from nchar_tst
    SQL> /

    NAME    LENGTH(NAME) ADDR            LENGTH(ADDR) SAL LENGTH(TO_CHAR(SAL))

    ------   ------------  ----------------  ------------  ----------  ----------------

    趙元杰          3        北京市海淀區(qū)                 6         99999.99    8

    LENGTHB( <c> )

    以字節(jié)返回字符串的字節(jié)數(shù)。

    SQL> select name,lengthb(name),length(name) from nchar_tst;

    NAME     LENGTHB(NAME)       LENGTH(NAME)

    ------   -------------   ------------

    趙元杰                 6             3

    LOWER ( <c> )
    返回字符串并將所有字符變?yōu)樾憽?

    SQL> select lower('AaBbCcDd') AaBbCcDd from dual;

    AABBCCDD

    --------

    aabbccdd

    UPPER( <c>)
    與  LOWER    相反,將給出字符串變?yōu)榇髮憽H纾?

    SQL>    select upper('AaBbCcDd') AaBbCcDd from dual;

    AABBCCDD

    --------

    AABBCCDD
    RPAD 和LPAD(粘貼字符)
     
    RPAD(string,Length[,'set']) 
    LPAD(string,Length[,'set']) 
          RPAD在列的右邊粘貼字符; 
          LPAD在列的左邊粘貼字符。 
     
    例 1: 
    SQL>select   RPAD(City,35,'.'),temperature    from  weather; 
     
            RPAD(City,35,'.')            temperature 
            -------------------------- ---------------- 
               CLEVELAND......                    85 
               LOS  ANGELES..                     81 
              ......................... 
     
            (即不夠 35 個(gè)字符用'.'填滿) 

    LTRIM(左截?cái)?RTRIM(右截?cái)啵?函數(shù) 
     

    LTRIM (string [,’set’])

    Left TRIM (左截?cái)?刪去左邊出現(xiàn)的任何set 字符。 

    RTRIM (string [,’set’])

    Right TRIM (右截?cái)?刪去右邊出現(xiàn)的任何set 字符。 

    例1: 

    SELECT RTRIM (‘Mother Theresa, The’, ‘The’) “Example of Right

    Trimming” FROM DUAL;

    Example of Right

    ----------------

    Mother Theresa,

    SUBSTR Substr(string,start[,Count])

    取子字符串中函數(shù) 
    對(duì)字串 (或字段),從 start字符 開始,連續(xù)取 count 個(gè)字符并返回結(jié)果,如果沒有指 count
    則一直取到尾。 
     
    select phone,substr(phone,1,3) || ‘0’ || substr(phone,4) 
    from telecommunication where master ’中國電信’; 
     

    SUBSTRB(string,start[,Count])
    對(duì)字串 (或字段),從 start字節(jié) 開始,連續(xù)取 count 個(gè)字節(jié)并返回結(jié)果,如果沒有指 count
    則一直取到尾。 
     
     
    REPLACE (‘string’ [,’string_in’,’string_out’])

    String: 希望被替換的字符串或變量。 
    String_in: 被替換字符串。 
    String_out: 要替換字符串。 
     
    SQL> select replace('Informaix 中國公司','Informaix','IBM Informix')
      2  IBM 數(shù)據(jù)庫  from dual;

    IBM 數(shù)據(jù)庫
    --------------------
    IBM Informix 中國公司

    SOUNDEX( <c> )

    返回一個(gè)與給定的字符串讀音相同的字符串(不管拼寫是否一樣)。

    SELECT DPL_NAME FROM DENIED_PARTIES_LIST WHERE
    SOUNDEX(DPL_NAME) = SOUNDEX(‘Saddam Hussain’) ;
    DPL_NAME
    ----------------------------------------------
    Al Husseni
    Sadda Al Sada.

    REPLACE (‘string’ [,’string_in’,’string_out’])

    String:希望被替換的字符串或變量。 
    String_in: 被替換字符串。 
    String_out: 要替換字符串。 
     
    SELECT REPLACE (‘Oracle’, ‘Or’, ‘Mir’) “Example “ FROM DUAL; 
    Example 
    ------- 
    Miracle 

    TRIM  ( [<leading>] <trailing> FROM <trim_char>     )
    RIM可以使你對(duì)給定的字符串進(jìn)行裁剪(前面,后面或前后)。 

    z 如果指定 LEADING, Oracle 從trim_char 中裁剪掉前面的字符; 
    z 如果指定TRAILING, Oracle 從trim_char 中裁剪掉尾面的字符; 
    z 如果指定兩個(gè)都指定或一個(gè)都沒有給出,Oracle從trim_char 中裁剪掉前面及尾面的字
       符; 
    z 如果不指定 trim_character, 缺省為空格符; 
    z 如果只指定trim_source, Oracle Oracle從trim_char 中裁剪掉前面及尾面的字符。 
     
    例子:將下面字符串中的前面和后面的‘0                   ‘字符都去掉:

    SELECT TRIM (0 FROM 0009872348900) "TRIM Example" FROM DUAL;

    TRIM example

    --------------------------------

    98723489

     

    語法:TRANSLATE(expr,from,to)

    om,to) expr: 代表一串字符,

    expr: 代表一串字符,from 與 to 是從左到右一一對(duì)應(yīng)的關(guān)系,如果不能對(duì)應(yīng),則視為空值。

    舉例:

    select translate('abcbbaadef','ba','#@') from dual (b將被#替代,a將被@替代)

    select translate(ab

    select translate('abcbbaadef','bad','#@') from dual (b將被#替代,a將被@替代,d對(duì)應(yīng)的值是空值,將被移走)

    因此:結(jié)果依次為:@#c##@@def 和@#c##@@ef

    posted @ 2010-04-22 11:10 xzc 閱讀(10680) | 評(píng)論 (0)編輯 收藏

    一個(gè)大型文件(總之不小),要求刪除該文件的最后一行,求一種效率比較高的解決方法。

    測試用的文本文件800M
    1.用sed解決,此法最易想,但也是最笨的一個(gè),
    解決方法來自問題的提出者:
    sed -e '$d' input.file > output.file
    用time測試了一下,效率是相當(dāng)?shù)牡停?br /> real    2m51.099s
    user    2m1.268s
    sys    0m4.260s
    2.用head解決,此法比sed有一個(gè)質(zhì)的的提升,提升來自增大了緩存,不過依然沒有抓住問題的本質(zhì),還是做了不少無用功!解決方法來時(shí)cu上的熱心網(wǎng)友。
    head -n-1 input.file > output.file
    real    0m23.687s
    user    0m0.212s
    sys    0m4.668s
    3.用vim解決,此法很別處心裁,這應(yīng)該是遇到這個(gè)問題的最先想到的一種。解決方法來自我加的unix like群里的一個(gè)叫石仔的管理員!
    vim + result
    dd
    這個(gè)沒測試,感覺效率和head法差不多,加載太慢!
    4.重量級(jí)要到場了,感謝cu版主的這個(gè)腳本,只能用四個(gè)字形容!五體投地!
    :|dd of=input.file seek=1 bs=$(($(find input.file -printf "%s")-$(tail -1 input.file|wc -c)))
    或者是
    :|dd of=input.file seek=1 bs=$(($(stat -c%s input.file)-$(tail -1 input.file|wc -c)))
    測試了一下!
    real    0m0.123s
    user    0m0.004s
    sys    0m0.012s
    5.感覺這個(gè)用c寫效率最高,但顯然,代碼也是最長的,我實(shí)現(xiàn)了代碼,
    測試了一下,
    real    0m0.002s
    user    0m0.000s
    sys    0m0.000s
    代碼如下:

    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <stdlib.h>

    #define GUESS_LINE_SIZE 80
    int get_line_size(char *ptr);

    int
    main(int argc, char *argv[])
    {
        char buf[GUESS_LINE_SIZE];
        int line_len, fd;
        struct stat stat_buf;
       
        fd = open(argv[1], O_RDWR);
        lstat(argv[1], &stat_buf);
        lseek(fd, -GUESS_LINE_SIZE, SEEK_END);
        read(fd, buf, GUESS_LINE_SIZE) ;
        line_len = get_line_size(buf);
        truncate(argv[1], stat_buf.st_size - line_len);
       
        exit(0);
    }

    int
    get_line_size(char *ptr)
    {
        int line_len = 0, i = GUESS_LINE_SIZE - 2;/*buf中的最后一個(gè)字符為'\n'*/
       
        while (*(ptr + i) != '\n') {
            //printf("%c", *(ptr + i));

            i--;
            line_len++;
        }
        return line_len;
    }

    posted @ 2010-04-21 18:45 xzc 閱讀(3295) | 評(píng)論 (2)編輯 收藏

    在linux下獲取時(shí)間字符串
    命令 date
    # 以yyyymmdd格式輸出23天之前現(xiàn)在這個(gè)時(shí)刻的時(shí)間
    $ date +%Y%m%d –date=’23 days ago’

    $ date -u
    Thu Sep 28 09:32:04 UTC 2006

    $ date -R
    Thu, 28 Sep 2006 17:32:28 +0800

    # 測試十億分之一秒
    $ date +’%Y%m%d %H:%M:%S.%N’;date +’%Y%m%d %H:%M:%S.%N’;date +’%Y%m%d %H:%M:%S.%N’;date +’%Y%m%d %H:%M:%S.%N’
    20060928 17:44:20.906805000
    20060928 17:44:20.909188000
    20060928 17:44:20.911535000
    20060928 17:44:20.913886000
    date 參考
    $ date –help
    Usage: date [OPTION]… [+FORMAT]
    or: date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
    Display the current time in the given FORMAT, or set the system date.

    -d, –date=STRING display time described by STRING, not `now’
    # such as ‘n days ago |1 month ago|n years ago’
    -f, –file=DATEFILE like –date once for each line of DATEFILE
    -ITIMESPEC, –iso-8601[=TIMESPEC] output date/time in ISO 8601 format.
    TIMESPEC=`date’ for date only,
    `hours’, `minutes’, or `seconds’ for date and
    time to the indicated precision.
    –iso-8601 without TIMESPEC defaults to `date’.
    -r, –reference=FILE display the last modification time of FILE
    -R, –rfc-2822 output RFC-2822 compliant date string
    -s, –set=STRING set time described by STRING
    -u, –utc, –universal print or set Coordinated Universal Time
    –help display this help and exit
    –version output version information and exit

    FORMAT controls the output. The only valid option for the second form
    specifies Coordinated Universal Time. Interpreted sequences are:

    %% 輸出%符號(hào) a literal %
    %a 當(dāng)前域的星期縮寫 locale’s abbreviated weekday name (Sun..Sat)
    %A 當(dāng)前域的星期全寫 locale’s full weekday name, variable length (Sunday..Saturday)
    %b 當(dāng)前域的月份縮寫 locale’s abbreviated month name (Jan..Dec)
    %B 當(dāng)前域的月份全稱 locale’s full month name, variable length (January..December)
    %c 當(dāng)前域的默認(rèn)時(shí)間格式 locale’s date and time (Sat Nov 04 12:02:33 EST 1989)
    %C n百年 century (year divided by 100 and truncated to an integer) [00-99]
    %d 兩位的天 day of month (01..31)
    %D 短時(shí)間格式 date (mm/dd/yy)
    %e 短格式天 day of month, blank padded ( 1..31)
    %F 文件時(shí)間格式 same as %Y-%m-%d
    %g the 2-digit year corresponding to the %V week number
    %G the 4-digit year corresponding to the %V week number
    %h same as %b
    %H 24小時(shí)制的小時(shí) hour (00..23)
    %I 12小時(shí)制的小時(shí) hour (01..12)
    %j 一年中的第幾天 day of year (001..366)
    %k 短格式24小時(shí)制的小時(shí) hour ( 0..23)
    %l 短格式12小時(shí)制的小時(shí) hour ( 1..12)
    %m 雙位月份 month (01..12)
    %M 雙位分鐘 minute (00..59)
    %n 換行 a newline
    %N 十億分之一秒 nanoseconds (000000000..999999999)
    %p 大寫的當(dāng)前域的上下午指示 locale’s upper case AM or PM indicator (blank in many locales)
    %P 小寫的當(dāng)前域的上下午指示 locale’s lower case am or pm indicator (blank in many locales)
    %r 12小時(shí)制的時(shí)間表示(時(shí):分:秒,雙位) time, 12-hour (hh:mm:ss [AP]M)
    %R 24小時(shí)制的時(shí)間表示 (時(shí):分,雙位)time, 24-hour (hh:mm)
    %s 自基礎(chǔ)時(shí)間 1970-01-01 00:00:00 到當(dāng)前時(shí)刻的秒數(shù) seconds since `00:00:00 1970-01-01 UTC’ (a GNU extension)
    %S 雙位秒 second (00..60); the 60 is necessary to accommodate a leap second
    %t 橫向制表位(tab) a horizontal tab
    %T 24小時(shí)制時(shí)間表示 time, 24-hour (hh:mm:ss)
    %u 數(shù)字表示的星期(從星期一開始 1-7)day of week (1..7); 1 represents Monday
    %U 一年中的第幾周星期天為開始 week number of year with Sunday as first day of week (00..53)
    %V 一年中的第幾周星期一為開始 week number of year with Monday as first day of week (01..53)
    %w 一周中的第幾天 星期天為開始 0-6 day of week (0..6); 0 represents Sunday
    %W 一年中的第幾周星期一為開始 week number of year with Monday as first day of week (00..53)
    %x 本地日期格式 locale’s date representation (mm/dd/yy)
    %X 本地時(shí)間格式 locale’s time representation (%H:%M:%S)
    %y 兩位的年 last two digits of year (00..99)
    %Y 年 year (1970…)
    %z RFC-2822 標(biāo)準(zhǔn)時(shí)間格式表示的域 RFC-2822 style numeric timezone (-0500) (a nonstandard extension)
    %Z 時(shí)間域 time zone (e.g., EDT), or nothing if no time zone is determinable

    By default, date pads numeric fields with zeroes. GNU date recognizes
    the following modifiers between `%’ and a numeric directive.

    `-’ (hyphen) do not pad the field
    `_’ (underscore) pad the field with spaces

    posted @ 2010-04-20 10:55 xzc 閱讀(6966) | 評(píng)論 (1)編輯 收藏
    oracle table-lock的5種模式

    Oracle中的鎖定可以分為幾類:
    1、DML lock(data lock),
    2、DDL lock(dictionary lock)
    3、internal lock/latch。

    DML lock又可以分為row lock和table lock。row lock在select.. for update/insert/update/delete時(shí)隱式自動(dòng)產(chǎn)生,而table lock除了隱式產(chǎn)生,也可以調(diào)用lock table <table_name> in </table_name> name來顯示鎖定。

    如果不希望別的session lock/insert/update/delete表中任意一行,只允許查詢,可以用lock table table_name in exclusive mode。(X)這個(gè)鎖定模式級(jí)別最高,并發(fā)度最小。

    如果允許別的session查詢或用select for update鎖定記錄,不允許insert/update/delete,可以用
    lock table table_name in share row exclusive mode。(SRX)

    如果允許別的session查詢或select for update以及l(fā)ock table table_name in share mode,只是不允許insert/update/delete,可以用
    lock table table_name in share mode。(share mode和share row exclusive mode的區(qū)別在于一個(gè)是非搶占式的而另一個(gè)是搶占式的。進(jìn)入share row exclusive mode后其他session不能阻止你insert/update/delete,而進(jìn)入share mode后其他session也同樣可以進(jìn)入share mode,進(jìn)而阻止你對(duì)表的修改。(S)

    還有兩種鎖定模式,row share(RS)和row exclusive(RX)。他們允許的并發(fā)操作更多,一般直接用DML語句自動(dòng)獲得,而不用lock語句。
    詳細(xì)參考concepts文檔中的"Type Of Locks":
    http://download-uk.oracle.com/docs/cd/B10501_01/server.920/a96524/c21cnsis.htm#2937


    -------------------------------------
    怎么unlock table 解鎖

    方法一、kill session:

    SQL> select object_id,session_id from v$locked_object;  //注意session_id 就是上鎖的 session標(biāo)志
    SQL> select username,sid,SERIAL#  from v$session where sid=。。;      //這里的SID = session_id
    SQL> alter system kill session 'id,serial#';     //殺死該session

    方法二、rollback/commit 終止事務(wù)處理
    posted @ 2010-04-02 16:05 xzc 閱讀(7242) | 評(píng)論 (1)編輯 收藏

    二元比較操作符,比較變量或者比較數(shù)字.注意數(shù)字與字符串的區(qū)別.
     
    整數(shù)比較
     
    -eq        等于,如:if [ "$a" -eq "$b" ]
    -ne        不等于,如:if [ "$a" -ne "$b" ]
    -gt        大于,如:if [ "$a" -gt "$b" ]
    -ge        大于等于,如:if [ "$a" -ge "$b" ]
    -lt        小于,如:if [ "$a" -lt "$b" ]
    -le        小于等于,如:if [ "$a" -le "$b" ]
    <        小于(需要雙括號(hào)),如:(("$a" < "$b"))
    <=        小于等于(需要雙括號(hào)),如:(("$a" <= "$b"))
    >        大于(需要雙括號(hào)),如:(("$a" > "$b"))
    >=        大于等于(需要雙括號(hào)),如:(("$a" >= "$b"))
     
    字符串比較
    =        等于,如:if [ "$a" = "$b" ]
    ==        等于,如:if [ "$a" == "$b" ],與=等價(jià)
            注意:==的功能在[[]]和[]中的行為是不同的,如下:
            1 [[ $a == z* ]]    # 如果$a以"z"開頭(模式匹配)那么將為true
            2 [[ $a == "z*" ]]  # 如果$a等于z*(字符匹配),那么結(jié)果為true
            3 
            4 [ $a == z* ]      # File globbing 和word splitting將會(huì)發(fā)生
            5 [ "$a" == "z*" ]  # 如果$a等于z*(字符匹配),那么結(jié)果為true
            一點(diǎn)解釋,關(guān)于File globbing是一種關(guān)于文件的速記法,比如"*.c"就是,再如~也是.
            但是file globbing并不是嚴(yán)格的正則表達(dá)式,雖然絕大多數(shù)情況下結(jié)構(gòu)比較像.
    !=        不等于,如:if [ "$a" != "$b" ]
            這個(gè)操作符將在[[]]結(jié)構(gòu)中使用模式匹配.
    <        小于,在ASCII字母順序下.如:
            if [[ "$a" < "$b" ]]
            if [ "$a" \< "$b" ]
            注意:在[]結(jié)構(gòu)中"<"需要被轉(zhuǎn)義.
    >        大于,在ASCII字母順序下.如:
            if [[ "$a" > "$b" ]]
            if [ "$a" \> "$b" ]
            注意:在[]結(jié)構(gòu)中">"需要被轉(zhuǎn)義.
            具體參考Example 26-11來查看這個(gè)操作符應(yīng)用的例子.
    -z        字符串為"null".就是長度為0.
    -n        字符串不為"null"
            注意:
            使用-n在[]結(jié)構(gòu)中測試必須要用""把變量引起來.使用一個(gè)未被""的字符串來使用! -z
            或者就是未用""引用的字符串本身,放到[]結(jié)構(gòu)中。雖然一般情況下可
            以工作,但這是不安全的.習(xí)慣于使用""來測試字符串是一種好習(xí)慣.

    本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/zhrmghl/archive/2006/10/22/1345115.aspx

    posted @ 2010-04-02 14:17 xzc 閱讀(1194) | 評(píng)論 (0)編輯 收藏
    測試平臺(tái):RHEL4.5

    一、最簡單的shell里調(diào)用sqlplus.


    $ vi test1.sh

    #!/bin/bash
    sqlplus -S /nolog > result.log <<EOF
    set heading off feedback off pagesize 0 verify off echo off
    conn u_test/iamwangnc
    select * from tab;
    exit
    EOF

    $ chmod +x test1.sh
    $ ./test1.sh

    二、把sqlplus執(zhí)行結(jié)果傳遞給shell方法一

    注意sqlplus段使用老板鍵`了, 賦變量的等號(hào)兩側(cè)不能有空格.

    $ vi test2.sh

    #!/bin/bash
    VALUE=`sqlplus -S /nolog <<EOF
    set heading off feedback off pagesize 0 verify off echo off numwidth 4
    conn u_test/iamwangnc
    select count(*) from tab;
    exit
    EOF`
    if [ "$VALUE" -gt 0 ]; then
            echo "The number of rows is $VALUE."
            exit 0
    else
            echo "There is no row in the table."
    fi

    $ chmod +x test2.sh
    $ ./test2.sh

    三、把sqlplus執(zhí)行結(jié)果傳遞給shell方法二

    注意sqlplus段使用 col .. new_value .. 定義了變量并帶參數(shù)exit, 然后自動(dòng)賦給了shell的$?

    $ vi test3.sh

    #!/bin/bash
    sqlplus -S /nolog > result.log <<EOF
    set heading off feedback off pagesize 0 verify off echo off numwidth 4
    conn u_test/iamwangnc
    col coun new_value v_coun
    select count(*) coun from tab;
    exit v_coun
    EOF
    VALUE="$?"
    echo "The number of rows is $VALUE."

    $ chmod +x test3.sh
    $ ./test3.sh

    四、把shell程序參數(shù)傳遞給sqlplus

    $1表示第一個(gè)參數(shù), sqlplus里可以直接使用, 賦變量的等號(hào)兩側(cè)不能有空格不能有空格.

    $ vi test4.sh

    #!/bin/bash
    NAME="$1"
    sqlplus -S u_test/iamwangnc <<EOF
    select * from tab where tname = upper('$NAME');
    exit
    EOF

    $ chmod +x test4.sh
    $ ./test4.sh ttt

    五、為了安全要求每次執(zhí)行shell都手工輸入密碼

    $ vi test5.sh

    #!/bin/bash
    echo -n "Enter password for u_test:"
    read PASSWD
    sqlplus -S /nolog <<EOF
    conn u_test/$PASSWD
    select * from tab;
    exit
    EOF

    $ chmod +x test5.sh
    $ ./test5.sh

    六、為了安全從文件讀取密碼

    對(duì)密碼文件設(shè)置權(quán)限, 只有用戶自己才能讀寫.

    $ echo 'iamwangnc' > u_test.txt
    $ chmod g-rwx,o-rwx u_test.txt
    $ vi test6.sh

    #!/bin/bash
    PASSWD=`cat u_test.txt`
    sqlplus -S /nolog <<EOF
    conn u_test/$PASSWD
    select * from tab;
    exit
    EOF

    $ chmod +x test6.sh
    $ ./test6.sh

    --End--
    posted @ 2010-04-01 12:05 xzc 閱讀(4799) | 評(píng)論 (0)編輯 收藏
    原文鏈接:http://bbs.linuxtone.org/thread-5317-1-1.html IT運(yùn)維專家網(wǎng)--"自由平等,互助分享!"
    shell中數(shù)組的下標(biāo)默認(rèn)是從0開始的

    1. 將字符串存放在數(shù)組中,獲取其長度
    #!/bin/bash
    str="a b --n d"
    array=($str)
    length=${#array[@]}
    echo $length

    for ((i=0; i<$length; i++))
    do
        echo ${array[$i]}
    done
    along@along-laptop:~/code/shell/shell/mycat/testfile$ ./test.sh
    4
    a
    b
    --n
    d

    打印字符串:
    [root@mc2 tmp]# cat test.sh
    #!/bin/bash
    str="a b c"
    for i in $str
    do
    echo $i
    done

    [root@mc2 tmp]# cat array.sh
    #!/bin/bash
    str="a b c"
    array=($str)
    for ((i=0;i<${#array[@]};i++))
    do
      echo ${array[$i]}
    done

    結(jié)果:
    a
    b
    c

    2. 字符串用其他字符分隔時(shí)
    #!/bin/bash

    str2="a#b#c"
    a=($(echo $str2 | tr '#' ' ' | tr -s ' '))
    length=${#a[@]}

    for ((i=0; i<$length; i++))
    do
        echo ${a[$i]}
    done
    #echo ${a[2]}

    along@along-laptop:~/code/shell/shell/mycat/testfile$ ./test.sh
    a
    b
    c

    3. 數(shù)組的其他操作
    #!/bin/bash
    str="a b --n dd"
    array=($str)
    length=${#array[@]}

    #直接輸出的是數(shù)組的第一個(gè)元素
    echo $array

    #用下標(biāo)的方式訪問數(shù)組元素
    echo ${array[1]}

    #輸出這個(gè)數(shù)組
    echo ${array[@]}

    #輸出數(shù)組中下標(biāo)為3的元素的長度
    echo ${#array[3]}

    #輸出數(shù)組中下標(biāo)為1到3的元素
    echo ${array[@]:1:3}

    #輸出數(shù)組中下標(biāo)大于2的元素
    echo ${array[@]:2}

    #輸出數(shù)組中下標(biāo)小于2的元素
    echo ${array[@]::2}

    along@along-laptop:~/code/shell/shell/mycat/testfile$ ./test.sh
    a
    b
    a b --n dd
    2
    b --n dd
    --n dd
    a b

    4. 遍歷訪問一個(gè)字符串(默認(rèn)是以空格分開的,當(dāng)字符串是由其他字符分隔時(shí)可以參考 2)
    #!/bin/bash
    str="a --m"
    for i in $str
    do
        echo $i
    done
    along@along-laptop:~/code/shell/shell/mycat/testfile$ ./para_test.sh
    a
    --m

    5. 如何用echo輸出一個(gè) 字符串str="-n". 由于-n是echo的一個(gè)參數(shù),所以一般的方法echo "$str"是無法輸出的.
    解決方法可以有:

    echo x$str | sed 's/^x//'
    echo -ne "$str\n"
    echo -e "$str\n\c"
    printf "%s\n" $str  (這樣也可以)
    posted @ 2010-03-31 15:28 xzc 閱讀(2990) | 評(píng)論 (1)編輯 收藏

    來源地址: http://hi.bccn.net/space-21499-do-blog-id-13524.html

    shell for 循環(huán)指令使用
    2008-11-02 22:34

    for可以使一些不支持通配符的命令對(duì)一系列文件進(jìn)行操作。在WIN9X中,TYPE命令(顯示文件內(nèi)容)是不支持*.txt這種格式的(WIN2K開始TYPE已支持通配)。遇到類似情況就可以用FOR:

        for %a in (*.txt) do type %a

    這些還不是FOR最強(qiáng)大的功能。我認(rèn)為它最強(qiáng)大的功能,表現(xiàn)在以下這些高級(jí)應(yīng)用:
    1. 可以用 /r 參數(shù)遍歷整個(gè)目錄樹
    2. 可以用 /f 參數(shù)將文本文件內(nèi)容作為循環(huán)范圍
    3. 可以用 /f 參數(shù)將某一命令執(zhí)行結(jié)果作為循環(huán)范圍
    4. 可以用 %~ 操作符將文件名分離成文件名、擴(kuò)展名、盤符等獨(dú)立部分

     

    現(xiàn)分別舉例說明如下:
    1. 用 /r 遍歷目錄樹
    當(dāng)用 *.* 或 *.txt 等文件名通配符作為 for /r 的循環(huán)范圍時(shí),可以對(duì)當(dāng)前目錄下所有文件(包括子目錄里面的文件)進(jìn)行操作。舉個(gè)例子,你想在當(dāng)前目錄的所有txt文件(包括子目錄)內(nèi)容中查找"bluebear"字樣,但由于find本身不能遍歷子目錄,所以我們用for:

        for /r . %a in (*.txt) do @find "bluebear" %a

    find 前面的 @ 只是讓輸出結(jié)果不包括 find 命令本身。這是DOS很早就有的功能。和FOR無關(guān)。
    當(dāng)用 . 作為循環(huán)范圍時(shí),for 只將子目錄的結(jié)構(gòu)(目錄名)作為循環(huán)范圍,而不包括里面的文件。有點(diǎn)象 TREE 命令,不過側(cè)重點(diǎn)不同。TREE 的重點(diǎn)是用很漂亮易讀的格式輸出,而FOR的輸出適合一些自動(dòng)任務(wù),例如,我們都知道用CVS管理的項(xiàng)目中,每個(gè)子目錄下都會(huì)有一個(gè)CVS目錄,有時(shí)在軟件發(fā)行時(shí)我們想把這些CVS目錄全部去掉:
        for /r . %a in (.) do @if exist %aCVS rd /s /q %aCVS

    先用 if exist 判斷一下,是因?yàn)?for 只是機(jī)械的對(duì)每個(gè)目錄進(jìn)行列舉,如果有些目錄下面沒有CVS也會(huì)被執(zhí)行到。用 if exist 判斷一下比較安全。
    這種刪除命令威力太大,請小心使用。最好是在真正執(zhí)行以上的刪除命令前,將 rd /s /q 換成 @echo 先列出要?jiǎng)h出的目錄,確認(rèn)無誤后再換回rd /s /q:
        for /r . %a in (.) do @if exist %aCVS @echo %aCVS

    可能目錄中會(huì)多出一層 ".",比如 c:proj elease.CVS ,但不會(huì)影響命令的執(zhí)行效果。
    2. 將某一文件內(nèi)容或命令執(zhí)行結(jié)果作為循環(huán)范圍:
    假如你有一個(gè)文件 todel.txt,里面是所有要?jiǎng)h除的文件列表,現(xiàn)在你想將里面列出的每個(gè)文件都刪掉。假設(shè)這個(gè)文件是每個(gè)文件名占一行,象這樣:
        c: empa1.txt
        c: empa2.txt
        c: empsubdir3.txt
        c: empsubdir4.txt

    那么可以用FOR來完成:
        for /f %a in (todel.txt) do del %a

    這個(gè)命令還可以更強(qiáng)大。比如你的 todel.txt 并不是象上面例子那么干凈,而是由DIR直接生成,有一些沒用的信息,比如這樣:
        Volume in drive D is DATA
        Volume Serial Number is C47C-9908
        Directory of D: mp
        09/26/2001 12:50 PM 18,426 alg0925.txt
        12/02/2001 04:29 AM 795 bsample.txt
        04/11/2002 04:18 AM 2,043 invitation.txt
        4 File(s) 25,651 bytes
        0 Dir(s) 4,060,700,672 bytes free

    for 仍然可以解出其中的文件名并進(jìn)行操作:
        for /f "skip=5 tokens=5" %a in (todel.txt) do @if exist %a DEL %a

    當(dāng)然,上面這個(gè)命令是在進(jìn)行刪除,如果你只是想看看哪些文件將被操作,把DEL換成echo:
        for /f "skip=5 tokens=5" %a in (todel.txt) do @if exist %a echo %a

    你將看到:
        alg0925.txt
        bsample.txt
        invitation.txt

    skip=5表示跳過前5行(就是DIR輸出的頭部信息),tokens=5表示將每行的第5列作為循環(huán)值放入%a,正好是文件名。在這里我加了一個(gè)文件存在判斷,是因?yàn)樽詈笠恍械?free"剛好也是第5列,目前還想不出好的辦法來濾掉最后兩行,所以檢查一下可保萬無一失。
    3. 可以用 /f 參數(shù)將某一命令執(zhí)行結(jié)果作為循環(huán)范圍
    非常有用的功能。比如,我們想知道目前的環(huán)境變量有哪些名字(我們只要名字,不要值)。可是SET命令的輸出是“名字=值”的格式,現(xiàn)在可以用FOR來只取得名字部分:
        FOR /F "delims==" %i IN ('set') DO @echo %i

    將看到:
        ALLUSERSPROFILE
        APPDATA
        CLASSPATH
        CommonProgramFiles
        COMPUTERNAME
        ComSpec
        dircmd
        HOMEDRIVE
        ......

    這里是將set命令執(zhí)行的結(jié)果拿來作為循環(huán)范圍。delims==表示用=作為分隔符,由于FOR /F默認(rèn)是用每行第一個(gè)TOKEN,所以可以分離出變量名。如果是想僅列出值:
        FOR /F "delims== tokens=2" %i IN ('set') DO @echo %i

    tokens=2和前例相同,表示將第二列(由=作為分隔符)作為循環(huán)值。
    再來個(gè)更有用的例子:
    我們知道 date /t (/t表示不要詢問用戶輸入)的輸出是象這樣的:
        Sat 07/13/2002

    現(xiàn)在我想分離出日期部分,也就是13:
        for /f "tokens=3 delims=/ " %a in ('date /t') do @echo %a

    實(shí)際上把 tokens后面換成1,2,3或4,你將分別得到Sat, 07, 13和2002。注意delims=/后面還有個(gè)空格,表示/和空格都是分隔符。由于這個(gè)空格delims必須是/f選項(xiàng)的最后一項(xiàng)。
    再靈活一點(diǎn),象本文開頭提到的,將日期用2002-07-13的格式輸出:
        for /f "tokens=2,3,4 delims=/ " %a in ('date /t') do @echo %c-%a-%b

    當(dāng)tokens后跟多個(gè)值時(shí),將分別映射到%a, %b, %c等。實(shí)際上跟你指定的變量有關(guān),如果你指定的是 %i, 它們就會(huì)用%i, %j, %k等。
    靈活應(yīng)用這一點(diǎn),幾乎沒有做不了的事。
    4. 可以用 %~ 操作符將文件名分離成文件名、擴(kuò)展名、盤符等獨(dú)立部分
    這個(gè)比較簡單,就是說將循環(huán)變量的值自動(dòng)分離成只要文件名,只要擴(kuò)展名,或只要盤符等等。
    例:要將 c:mp3下所有mp3的歌名列出,如果用一般的 dir /b/s 或 for /r ,將會(huì)是這樣:
        g:mp3Archived-18-01-A游鴻明-下沙游鴻明-01 下沙.mp3
        g:mp3Archived-18-01-A游鴻明-下沙游鴻明-02 21個(gè)人.mp3
        ......
        g:mp3Archived-18-01-A王菲-寓言王菲-阿修羅.mp3
        g:mp3Archived-18-01-A王菲-寓言王菲-彼岸花.mp3
        g:mp3Archived-18-01-A王菲-寓言王菲-不愛我的我不愛.mp3
        ......

    如果我只要歌名(不要路徑和".mp3"):
        游鴻明-01 下沙
        游鴻明-02 21個(gè)人
        ......
        王菲-阿修羅
        王菲-彼岸花
        王菲-不愛我的我不愛
        ......

    那么可以用FOR命令:
        for /r g:mp3 %a in (*.mp3) do @echo %~na

    凡是 %~ 開頭的操作符,都是文件名的分離操作。具體請看 for /? 幫助。
    本文舉的例子有些可能沒有實(shí)際用處,或可用其它辦法完成。僅用于體現(xiàn)FOR可以不借助其它工具,僅用DOS命令組合,就可完成相當(dāng)靈活的任務(wù)。
    posted @ 2010-03-31 14:41 xzc 閱讀(3005) | 評(píng)論 (0)編輯 收藏
    僅列出標(biāo)題
    共32頁: First 上一頁 13 14 15 16 17 18 19 20 21 下一頁 Last 
    主站蜘蛛池模板: 久久水蜜桃亚洲AV无码精品| 亚洲综合婷婷久久| 亚洲一本到无码av中文字幕| 国产羞羞的视频在线观看免费| 国产精品亚洲不卡一区二区三区| 国产亚洲精彩视频| 免费人成在线观看视频播放| 精品在线免费视频| 日批日出水久久亚洲精品tv| 麻豆一区二区三区蜜桃免费| 日韩毛片无码永久免费看| 亚洲暴爽av人人爽日日碰| 青青青青青青久久久免费观看| 亚洲欧洲日韩极速播放| 免费无码黄动漫在线观看| 国产偷国产偷亚洲清高APP| 波多野结衣视频在线免费观看| 羞羞漫画登录页面免费| 亚洲乱码日产精品a级毛片久久| 一级视频在线免费观看| 国产亚洲精品无码拍拍拍色欲| 天黑黑影院在线观看视频高清免费 | 国产亚洲午夜高清国产拍精品| jizz18免费视频| 亚洲AV日韩AV永久无码久久| 无码免费一区二区三区免费播放| 亚洲成a人片在线网站| 处破痛哭A√18成年片免费| 特级aa**毛片免费观看| 亚洲精品午夜无码电影网| 4444www免费看| 亚洲av日韩av永久无码电影 | 精品久久久久久久久免费影院| 亚洲日本在线电影| 久久精品国产亚洲AV不卡| 久久九九AV免费精品| 亚洲色大网站WWW永久网站| 亚洲AV成人潮喷综合网| 污污网站18禁在线永久免费观看| 亚洲制服丝袜中文字幕| 亚洲片国产一区一级在线观看|