一区二区国产在线,国产精品久久久久久免费观看,国产精品久久久久国产精品日日http://www.aygfsteel.com/jiangshachina/category/16091.html同是Java愛好者,相逢何必曾相識!<br> &nbsp;&nbsp;&nbsp;a cup of Java, cheers!zh-cnFri, 10 Jul 2015 09:35:43 GMTFri, 10 Jul 2015 09:35:43 GMT60MySQL: MyISAM or InnoDB?(譯)http://www.aygfsteel.com/jiangshachina/archive/2009/05/31/279288.htmlSha JiangSha JiangSun, 31 May 2009 13:41:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2009/05/31/279288.htmlhttp://www.aygfsteel.com/jiangshachina/comments/279288.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2009/05/31/279288.html#Feedback2http://www.aygfsteel.com/jiangshachina/comments/commentRss/279288.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/279288.htmlMySQL: MyISAM or InnoDB?
通過JavaLobby看到的一篇博文,為選擇MySQL的數據表引擎提供了一些意見,希望對大家有幫助。(2009.05.31最后更新)
我這個可愛的小哥哥祝可愛的小朋友們節日愉快 ^_^

    MyISAM是MySQL的默認存儲引擎,但很多人忘記還有其它的選擇。決定使用哪種(哪些)存儲引擎可能需要些技巧,但評估一下MyISAM是否適合你的需要還是值得的。有一組存儲引擎可用,但我將只關注MyISAM和InnoDB,因為它們被用的最多。
需考慮的問題:
    你是否需要外鍵?
    你是否需要事務?
    你是否需要全文索引?
    你的數據訪問(查詢)模式是什么?
    你的數據集有多大?

    思考上述問題將使你走入正確的方向,但有些例外。如果你使用事務或外鍵,就使用InnoDB。要使用全文索引,你常需選擇MyISAM,因為它內建地支持這一特性;但是,MyISAM難以應對超過200萬的數據行。你可以使用Sphinx以使你的InnoDB表能獲取全文索引,但這需要花費一些時間。
    數據集的大小是決定你使用哪種引擎的主要因素。由于InnoDB的事務和崩潰恢復特性,對于較大的數據集,則傾向于該引擎。然而,恢復MyISAM數據表所花費的時間由數據集的大小來衡量,但恢復InnoDB所花費的時間由事務日志的大小來衡量-而你對日志有一定的控制力。例如,相較于恢復 InnoDB數據表所需要的幾分鐘,你可能需要幾小時甚至幾天時間來恢復MyISAM數據表。
    你讀/寫數據表的方式可能會極大地影響你所使用的存儲引擎的性能。在MyISAM數據表中執行COUNT()會很快,但對于InnoDB數據表則十分痛苦,最好避免。在InnoDB數據表中查找主鍵極其的快,但要注意到,太長的主鍵會影響到性能。批量插入在MyISAM數據表更快些,但批量更新在 InnoDB中會較快些--特別是當進行并發增加時。
    那么你應該選擇哪種引擎呢?如果你工作在一個小項目中,那么MyISAM可能正適合你。甚至在較大環境中使用MyISAM也能獲取很大的成功,但這依具體情況不同而不同。如果你計劃用于非常大的數據集,并且需要事務或外鍵約束,那就應該直接使用InnoDB。但需要記住,相較于MyISAM,InnoDB 數據表需要很大的內存和存儲空間。將100GB的MyISAM數據表轉化成InnoDB數據表就會表現得令人吃驚的壞。



Sha Jiang 2009-05-31 21:41 發表評論
]]>
深入db4o(譯)http://www.aygfsteel.com/jiangshachina/archive/2007/12/05/164430.htmlSha JiangSha JiangWed, 05 Dec 2007 04:31:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2007/12/05/164430.htmlhttp://www.aygfsteel.com/jiangshachina/comments/164430.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2007/12/05/164430.html#Feedback8http://www.aygfsteel.com/jiangshachina/comments/commentRss/164430.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/164430.html深入db4o
    這是Rick Grehan發表在TheServerSide上的一篇關于面向對象數據庫--db4o的文章,較全面地介紹了db4o的關鍵特性,希望對大家認識db4o能有所幫助。(2007.12.07最后更新)

    db4o-針對對象的數據庫-是一個完全的對象數據庫;它以使對象在其生命周期中-無論是在數據庫內或是在外-都保持著它們的本性這樣一種方式操縱對象。不論類的復雜性如何,對象的內容,結構和關系都能夠被保存。
    更準確地說,db4o是一個數據庫引擎,你只要將它的一個jar文件包含到你的數據庫應用的類路徑中就可以使用它了(至少對于Java是這樣的)。所以,db4o運行在與你的應用程序相同的進程空間中,并能被直接地調用;它不需要類似于在ODBC或JDBC中使用的驅動文件。db4o存在針對Java,.NET和Mono的版本;它們在功能上都彼此相等。(事實上,使用.NET創建的db4o數據庫也能由Java程序訪問;反之亦然。)
    db4o是開源的。可執行文件,源代碼和文檔可從http://www.db4objects.com/中下載。廣泛的例子程序,和一個活躍的用戶社區一樣,也都可以從這個站點中找到。
    db4o最引人的特性之一就是它在簡易性與強大的功能之間的顯著平衡。一方面,它的API是如此地易于掌握和方便使用,即使是初學者也能在相同的時間內創建一個功能完備的數據庫對象。另一方面,這些相同的API也提供了更底層的能夠深入調用數據庫引擎的方法,以允許核心開發者為了得到適當的性能而能深入到該引擎的內部中去調整db4o的工具。
    db4o的特性就是最好的證明--這勝過只是討論--所以我們將通過示例這種方法去證明db4o。然而,我們必須牢記本文通篇只是展示了db4o特性中的一部分罷了。感興趣的朋友會發現為了知曉該數據庫引擎的全部功能而去查閱db4o的文檔所花的時間是值得的。

db4o基礎
    讓我們以初學者使用db4o時可能會做的事情開始:定義了一些類,然后持久化這些類的對象。我們所假定的類為同樣也是假定的QA項目做一個跟蹤測試的系統。我們的系統由兩個類組成,首先是TestSuite類:
    public class TestSuite {
        private String name;  // Test Suite name
        private String description;
        private String configuration;
        private char overallScore;
        private ArrayList <TestCase> cases;
        private long dateExec;
        ... <remainder of TestSuite definition> ...
    }
    TestSuite是TestCase對象的容器,(一個測試用例就是一個可單獨執行的測試程序--相關的測試用例組合成一個測試組)。測試組使用額外的,全局的數據成員,每個數據成員的用途也是相對明顯的:configuration記錄被測試的指定系統;overallScore是對整個測試組一個簡要的評分('P'代表通過,'F'代表失敗,'B'代表被阻塞,等等。);dateExec是一個毫秒級的域,標識該測試組被執行時的日期與時刻。是ArrayList對象的cases含有單個的測試用例,由TestCase類定義:
    public class TestCase {
        private String name;
        private String comment;
        private char status;
        private long duration;
        private float result;
        ... <remainder of TestCase definition> ...
    }
    每個測試用例都有一個名稱,形式自由的注釋字段,狀態(通過或失敗),持續時間和結果(例如,為了與測試-字節/秒的吞吐量-的任意數據關聯)。
    因為我們所關注是db4o的使用,所以我們不想在描述這些類的使用細節上停留。就讓我們簡單地說,我們已經執行了一個特別地測試組中所有的測試用例,將測試的結果存放在一個TestSuite對象中(與TestCase對象相關的ArrayList對象cases中),然后關閉數據庫。是不是太容易了。
    // Create the database
    new File("testsuites.YAP").delete();
    ObjectContainer db = Db4o.openFile("testsuites.YAP");
    // Store the TestSuite object
    db.set(testsuite);
    // Close the database
    db.close();
    就是它。彈指一揮間,你就已經做到了。(當然,為了保持簡潔,我們去掉了創建TestSuite對象和它的TestCase組件的細節)
    停下來想想上述代碼做了什么事情。特別要考慮你沒有看到的--db4o已經做了但還未被告之的事情。
    首先,我們不需要告訴db4o任何關于TestSuite類的結構的信息;不需要我們的幫助,db4o就能發現這個結構。利用Java反射機制的能力,db4o測定TestSuite類的結構,并勾勒出該類的裝配方式以推導出此類對象的成員與關鍵數據。
    第二,我們不必建議db4o去關注ArrayList。不僅我們不必將ArrayList的大小告訴db4o,而且我們也不必把它里面的內容告訴db4o。正如db4o在它剛接觸testsuite對象時就能夠發現它所需要的一切,db4o也能知道它所需要的關于(在ArrayList中的)TestCase對象的所有信息。
    結果就是,如果我們把testsuite作為一個任意寵大而復雜的對象樹的根,db4o能找到并存儲整個樹而不需要我們的任何協助。所以,存儲這個處于根部的對象testsuite也就是存儲了整個ArrayList對象。
    最后,我們也沒有必須要求db4o以事務的保護性方式去調用set方法。任何會修改ObjectContainer(表示數據庫的db4o對象)的調用都會自動地開啟一個事務,除非已經有一個活躍的事務了。此外還會調用close方法去終止這個事務,所以上述代碼等價于:
    db.startTransaction();
    db.set(testsuite);
    db.commitTransaction();
    db.close();
    此處的startTransaction和commitTransaction方法是為了證明我們的觀點而虛構的。db4o也確實有顯示地提交或中止事務的方法,但為了使原先的代碼足夠的簡潔我們沒有使用這些方法。db4o隱式的事務使得數據庫能夠一直處于一致的狀態;一旦commit方法已經執行了,數據庫的完整性就能夠得到保證,甚至是發生了災難性失敗也能如此。

查詢I - QBE
    有了已經存于數據庫中的對象,下一步我們想要展示的操作將肯定就是查詢和恢復。db4o提供了三種查詢API:有一種簡單,有一種優雅,還有一種則復雜。每一種API都有其所長,并適用于不同的查詢條件。以db4o的眼光來看,你選擇哪一種API并沒有關系:它們都是可兼容的。
    我們以簡單的API開始:query by exampel(QBE)。
    使用QBE是如此的容易:為你的查詢目標構建一個'模板'對象,然后把它傳入ObjectContainer的query方法。實際上,你就是告訴db4o'去拿到所有與這個對象看起來一樣的對象'。(這與JavaSpaces查詢API非常相似;為了清楚地了解如何處理基本數據類型,可以看下面的內容,db4o的處理方式與JavaSpaces不同。也要注意,JavaSpace Entry對象期望使用public字段,db4o則沒有這種要求。)
    假設一個測試組名為"Network Throughput",我們想取出這個測試組執行的所有測試以便我們能確定失敗了的測試所占的百分比(基于TestSuite的overalScore值)。使用QBE,完成該工作的代碼如下:
    // Open the database
    ObjectContainer db = Db4o.openFile("testsuites.YAP");

    // Instantiate the template object, filling in
    // only the name field
    testTemplate = new TestSuite("Network Throughput");

    // Execute the query
    ObjectSet result = db.get(testTemplate);
    fails = 0.0f;
    total = 0.0f;

    // Step through results,
    while(result.hasNext())
    {
        testsuite = (TestSuite)result.next();
        if(testsuite.getOverallScore()=='F')
        fails += 1.0f;
        total += 1.0f;
    }

    if(total == 0.0f)
        System.out.println("No tests of that type found.");
    else
    {
        System.out.println("Percent failed: " + (fails/total * 100.0f) + "%");
        System.out.println("Total executed: " + total);
    }
    db.close();
    在上面的代碼中,testTemplate是QBE的模板對象。注意,只有它的name字段有真實的值;所有其它的成員變量不是為null就是為0。Null或0字段不參與QBE查詢;因此,調用db.get方法就會返回在該數據庫中name字段匹配"Network Throughput"的所有TestSuite對象。匹配的TestSuite對象將返回在一個ObjectSet結果對象中。上述代碼遍歷該結果,取出對象,然后計算結果并展示出來。
    QBE明顯的優點就是它的簡易性。不需要掌握其它單獨的查詢語言。另外,QBE也是類型安全的:你不需要創建一個類似于SQL的查詢語句
    SELECT TestSuite.overallScore FROM TestSuite WHERE TestSuite.name = 200.0
    另一方面,由于該查詢是由Java代碼創建的,編譯器不會允許你把一個浮點值賦給一個String字段;反之亦然。
    QBE明顯的缺點就是它只能執行"等于"查詢。另外,QBE使用null值去確定不參與查詢的String或對象引用成員變量,使用0值去指定不參與查詢的數字字段。所以,例如,我不能發明一個QBE查詢去獲得所有result字段的值為0的TestCase對象。
    更為精細的查詢要求一個能力更強的查詢機制,而db4o恰恰就有這樣一種機制。

查詢方式II - 原生查詢(Native Query)
    db4o的原生查詢系統應該是能想像得到的最具彈性的查詢機制。不像使用數據庫查詢語言去構建查詢,你是使用"無格式的普通Java語句"去構造原生查詢。原生查詢用兩種手段去實現這件不可思意的工作:一個是Predicate類;另一個是QueryComparator接口。這個類包含一個可重載的(overrideable)回調方法,該方法將指定如何從數據庫中選擇對象(如果你愿意,你將會看到查詢語句的主體....)。這個接口只聲明了一個方法,該方法用于指明如何對查詢結果進行排序。
    作為一個例子,我們假設想找到在給定的一周內執行過了的總得分為"failed",但與之關聯的測試用例中有超過一半的被評為"passed"的測試組。這不是一個簡單的"等于"查詢,所以它不能使用QBE構建。
    然而,db4o的原生查詢可以直接地生成該查詢。首先,我們繼承db4o的Predicate類:
    // Predicate class sub-class for native query example
    public class NativeQueryQuery extends Predicate<TestSuite>
    {
        ObjectContainer db;
        private long startdate;
        private long enddate;

        // 構造器要在本地獲得ObjectContainer對象和日期范圍
        public NativeQueryQuery(ObjectContainer _db,
            long _start, long _end)
        {
            db = _db;
            startdate = _start;
            enddate = _end;
        }

        // 這就是查詢的主體
        public boolean match(TestSuite testsuite)
        {
            float passed;
            float total;
            TestCase testcase;

            // 判斷testsuite是否在指定的日期范圍內
            if(testsuite.getDateExec()<startdate ||
              testsuite.getDateExec()>enddate) return false;

            // 如果該測試組對象中沒有測試用例對象,則拒絕將該測試組對象放入查詢結果中
            if(testsuite.getNumberOfCases()==0)
                return false;

            // 檢查該測試組對象中的測試用例的通過率是否超過50%
            passed = 0.0f;
            total = 0.0f;
            for(int i=0; i<testsuite.getNumberOfCases(); i++)
            {
                testcase = testsuite.getTestCase(i);
                if(testcase.getStatus()=='P')
                    passed+=1.0f;
                total+=1.0f;
            }
            if((passed/total)<.5) return false;
                return true;
        }
    }
    注意在這個類的使用中使用了Java泛型語義,這就是告訴db4o只去取TestSuite對象。當查詢執行時,TestSuite對象就會傳入match方法(我們之前提到過的回調方法),如果傳入的TestSuite對象符合查詢規范該方法就返回true,否則就返回false。
    match方法中的代碼首先確定侯選對象是否是在一周的日期范圍內。如果是,則循環該對象中的成員變量測試用例的對象,計算出所有通過了的測試用例的總數。如果,得到的通過率小于50%,該測試組就被拒絕;否則,就讓它通過。
    我們可以使用如下的代碼準確地展示該查詢程序:
    . . .
    TestSuite testsuite;
    NativeQueryQuery nqqClass;
    Date now;

    // Open the database
    ObjectContainer db = Db4o.openFile("testsuites.YAP");

    // Instantiate a NativeQueryQuery object,
    // setting the start and end dates for
    // any test in the past week
    // 604800000 = milliseconds in a week
    now = new Date();
    nqqClass = new NativeQueryQuery(db,
    now.getTime()-604800000L,
    now.getTime());

    // Execute the query and display the
    // results
    System.out.println("Results:");
    ObjectSet results = db.query(nqqClass);
    if(results.isEmpty())
        System.out.println("  NOTHING TO DISPLAY");

    while(results.hasNext())
    {
        testsuite = (TestSuite)(results.next());
        System.out.println(testsuite.toString());
    }

    db.close();
    . . .
    可以把原生查詢想像成這樣:目標類的對象一個接一個從數據庫中取出,然后把它們傳入match方法中。只有那些被match方法返回true的對象才會置于查詢結果ObjectSet對象中。基本上可以說,如果你會知道如何寫Java代碼,那么你就知道如何寫原生查詢。
    那么排序呢?如果想按日期的升序排列查詢結果,我們就要實現QueryComparator接口,如下所示:
    public class NativeQuerySort implements QueryComparator<TestSuite>{
        public int compare(TestSuite t1, TestSuite t2)
        {
            if (t1.getDateExec() < t2.getDateExec()) return -1;
            if (t1.getDateExec() > t2.getDateExec()) return 1;
            return 0;
        }
     }
compare方法的作用十分明顯。那些在查詢中得以勝出的對象會成對的傳入compare方法,如果第一個對象會排在第二個對象之前,相同或之后的位置,該方法就會分別返回一個小于,等于或大于0的值。為了準確地說明對查詢結果的排序,我們實例化NativeQuerySort,并把對query方法的調用修改成如下:
    . . .
    // Instantiate the sort class
    nqsClass = new NativeQuerySort();
    . . .
    ObjectSet results = db.query(nqqClass, nqsClass);
    . . .
其它的代碼仍然與原先的保持一致。
    好懷疑的讀者可能會抱怨道,原生查詢只是一種編程上的小伎倆--相比較于直接去拿到所有的TestSuite對象然后再排除其中不符合條件的對象這樣的程序,原生查詢并不快。
    是的,但并不十分準確。原生能夠被優化。你所需要做的只是把兩個jar文件--db4o-xxx-nqopt.jar(xxx表示db4o的版本)和bloat.jar--置于CLASSPATH環境變量中。在查詢執行的時候,這些類庫中的代碼會對(在match方法中)例如基本數據類型比較,算術和布爾表達式,簡單的對象成員訪問,以及更多方面的結構進行優化。這個被支持的優化的列表在不停的增長,因為db4o引擎還在擴展優化的范圍。

查詢方式III - S.O.D.A.
    db4o獨一無二的能力之一就是它的API被分層了。開發者能夠選擇通過高層次--賦予數據庫引擎相當大的自由度,讓它決定如何去實現它的操作--或者開發者也可以使用一種更直接地方式去訪問db4o。后一種選擇為程序員平添了更多的負擔,程序員必須更加小心地引導數據庫引擎的內部工作。但回報就是得到一個更快,能力更強的數據庫應用。
    db4o的S.O.D.A.(Simple Object Data Access)查詢機制就是該層次API的一個完美的例子。S.O.D.A.就是db4o的內部查詢系統--QBE和原生查詢都被翻譯成了S.O.D.A.。然而,應用程序也能直接地調用S.O.D.A.。
    假設我們想找到所有名為"Network Throughput",且至少擁有一個其result字段--我們使用這個參數作為字節/秒的量度--不小于指定值(比方說,100)的測試用例的測試組。為該請求而做的S.O.D.A.查詢可能就像這樣:
    . . .
    TestSuite testsuite;

    // Open the database
    ObjectContainer db = Db4o.openFile("testsuites.YAP");

    // Construct the query
    Query query = db.query();
    query.constrain(TestSuite.class);
    Constraint nameConst = query.descend("name").
    constrain("Network Throughput");
    query.descend("cases").descend("result").
    constrain(100.0f).smaller().and(nameConst);

    System.out.println("Results:");
    // Execute the query
    ObjectSet result = query.execute();
    if(result.isEmpty())
    System.out.println("NOTHING TO DISPLAY");

    while(result.hasNext())
    {
        testsuite = (TestSuite)(result.next());
        System.out.println(testsuite.toString());
    }

    db.close();
    . . .
    在由Illustration 1所示圖表的幫助下,這些有點兒神秘的代碼就變得不那么神秘了。該程序所構建的歸總起來就是一個用于指導底層數據庫引擎的查詢圖(Query Graph)。descend方法創建了該圖的一個分支,該分支向下步入對象的結構中。每個descend方法就在這個樹中構建一個結點,可以在這些結點上再附上一個約束(使用constrain方法)。用SQL的話來說,約束指定了查詢的"WHERE"子句部分。多個約束可以在與(and)或或(or)方法的協助下結合起來。在上面的查詢中我們已經使用了and方法去關聯這些約束。
                                    
與其它的查詢方式一樣,查詢結果返回到ObjectSet對象中,通過遍歷該對象就可取出那些拿到的對象。
    注意,由于S.O.D.A.是一種低層次的訪問方法,沒有智能的指示,它就沒有默認的行為。訪問cases對象的成員變量result字段的代碼很簡單
    query.descend("cases").descend("result"). ...
我們并沒有告訴S.O.D.A."cases"是一個集合對象。所以當查詢執行時,它會不被察覺地檢測ArrayList對象cases中所有元素(TestCase對象)的result字段,然后會正確地返回那些擁有符合搜索規范的測試用例的測試組。

db4o性能調優
    我們已經展示了db4o的基本操作(但無關緊要的刪除操作除外,下面將會提到它)。但,正如我們在本文通篇所提到的,db4o發布(expose)了一個API層次結構,以允許開發者能夠選擇以何種層次的API去控制建立在該數據庫引擎之上的應用程序。從另一方面看,如果你所想做的只是向數據庫存入,及從數據庫取出對象,那么你就已經看到了你所需要的一切。然而,如果你的應用的需求超出了添加,更新,查詢和刪除,可能還有一個db4o的特性可解決你的問題。
    db4o的ObjectContainer實際上發布(expose)了兩個API。第一個API非常的簡單,由十個方法組成。這些方法處理數據庫的打開與關閉;添加,更新,查詢和刪除對象;及提交或中止事務。短言之,該API為你提供了在操縱數據庫時所需要所有功能。然而,該API中的一個方法--ext()--是進入"被擴展的"ObjectContainer的一個入口。該被擴展的ObjectContainer為深入控制db4o的內部發布(expose)了更多方法。例如,你可以獲得并改變數據庫的配置上下文,使用它你能夠修改該引擎的行為。
    例如,假設你已經從數據庫中拿到了一個TestSuite對象,發現該對象中的數據是錯誤的,并決定該對象應該被刪除。此外,你還決定你必須刪除的不僅是該TestSuite對象,而且還有所有與之關聯的TestCase對象(在ArrayList對象cases中)。
    你是可以冗長而乏味地遍歷這個ArrayList對象,一個接一個地刪除每一個TestCase對象,然后再刪除TestSuite對象本身。可能一種更好的解決方案是為這個TestSuite對象啟用db4o的"級聯刪除"特性。
    . . .
    // Fetch the database's configuration context
    Configuration config = db.ext().configure();
    // Get the ObjectClass for TestSuite
    ObjectClass oc = config.objectClass("testsuites.TestSuite");
    // Turn on cascaded delete
    oc.cascadeOnDelete(true);
    ...  ...
    db.delete(ts1);
    . . .
在上述代碼中,我們實例化了一個ObjectClass對象,該對象使我們能夠訪問到TestSuite對象的db4o內部表現形式。我們打開cascadeOnDelete標記,以便當執行db4o.delete(ts1)時,不僅ts1對象會被刪除,而且所有由ts1引用的TestCase對象也會被刪除。(由于顯而易見的原因,默認情況下,級聯刪除是被關閉的)
    作為另一個例子,假設你想為數據庫預分配存儲空間,以至于要最小化磁盤驅動器的頭移動(head movement)。(最好是在硬盤碎片整理之后,并新創建一個數據庫時這樣做。)并且假設以ObjectContainer對象db作為打開了的數據庫:
    // Fetch the database's configuration context
    // 獲得數據庫的配置上下文
    Configuration config = db.ext().configure();
    // Pre-allocate 200,000 bytes
    // 預分配200000000字節
    config.reserveStorageSpace(200000000L);
把數據庫文件預擴展到200000000字節(略小于200兆字節)。假設該磁盤已經做碎片整理了,那么被分配的塊就是連續的,這可顯著提升數據庫的訪問。

db4o高級應用
    完全可以說,db4o在它不大的空間(約500K)內已裝入了足夠多的特性,相比較于db4o在運行過程中所做的眾多事情,我們不能花費更多的筆墨去解釋它們了。但是有兩個特性十分突出,以至于肯定要提到它們。
    db4o的對象復制實現了被總稱為面向對象版的數據庫同步。使用復制所提供的功能,你能為一個數據庫中的一個對象做一個副本,并將該副本放入另一個數據庫中。使用這樣的方法,副本對象就無形中和原始對象關聯在了一起。對任一對象--原始對象或副本對象--的改變都會被跟蹤到,以便在之后的某個時候,數據庫能夠被重組,并且這兩個數據庫中對象的不同之處可被分解(例如,可同步這兩個數據庫)。
    它工作起來就像這樣:為使一個數據庫可被復制,與事務計數器一樣,該數據庫中被創建的任何一個對象都用一個唯一全局標識符(UUID)進行了標記。當你從原始數據庫中"復制"一個對象到另一個數據庫中,副本對象會帶著與它的原始對象相同的UUID和事務計數器。副本數據庫現在就可以從它的原始數據庫那兒弄走了。修改副本對象的內容將會導致對象的事務計數器被修改。所以,當這兩個數據庫重新連接起來,db4o內建的同步處理機制就能一個對象一個對象地進行正確的匹配(使用UUID),并確定原始或副本對象是否已經改變了。db4o甚至能追蹤到每個對象發生最后一次修改時的時間,以便用戶寫的沖突解決代碼能確定哪個對象是最近更新的。
    從操作行為來看,db4o的同步處理機制與原生查詢十分相似。回想一下,當實現了一個原生查詢類時,我們要定義一個match方法,該方法確定哪些對象符合(或不符合)查詢規范。使用同步復制,我們要定義一個ReplicationProcess對象,我們會把沖突處理對象傳入該方法中。這些Java代碼可能像這樣:
    . . .
    ReplicationProcess replication = db1.ext().
        replicationBegin(db2, new ReplicationConflictHandler()
        {  
            public Object resolveConflict(
                ReplicationProcess rprocess, Object a, Object b)
                {
                    . . .  ...
                    return winning_object;
                }
            )
        };
在上述代碼中,Object a是來自于數據庫db1的對象,Object b則來自于數據庫db2。默認情況下,同步是雙向的。同步處理保證勝出的對象(由resolveConflict方法返回的對象)能存入這兩個數據庫中。所以當復制完成時,這兩個數據庫中被復制的對象就同步了。
    最后,db4o最強大的特性之一就是它能毫不費力地容忍類結構的演變。假設,在向數據庫內加入數百個TestSuite對象之后,我們決定這個類必須要被修改。就是說,我們已經被告之,該系統必須能追蹤到每個TestSuite的執行QA工程師,所以必須加入如下字段
    private int engineerID;
到TestSuite類的定義中。
    現在我們就遇到了兩個相關聯的問題。第一個問題不是很糟糕:已存在于數據庫中的用于表示測試的TestSuite對象,并沒有為它們記錄QA工程師的ID,所以我們將不得不將一個虛擬的值賦給這些對象的engineerID字段;該值會指出"未記錄QA工程師的ID"。第二個問題就更難應付了:我們必須不知原因地把已有的TestSuite對象移植到"新的"類結構中。我們必須為數據庫中所有已存在的TestSuite對象加上一個engineerID字段。除了把舊數據庫中的對象復制到一個中間性的文件,然后重新創建一個數據庫這種方法之外,我們還能怎么做呢?
    幸運地是,使用db4o,我們確實什么都不用做。為了能操縱新的engineerID字段,以完成業務邏輯上所要求的變化,如果就只是向(我們的應用程序中的)TestSuite類添加一個engineerID字段,我們完全不必觸動db4o API的任何調用。當db4o使用"新的"TestSuite類結構去讀取"舊的"TestSuite對象,db4o將認為這些對象中的engineerID字段消失了,并且會優雅地把該字段的值設為0。如果我們把0當作"未記錄QA工程師的ID",那么我們所做的移植就完成了。寫入到數據庫中的新TestSuite對象將會包括新字段。(事實上,對舊的TestSuite對象本身進行重寫,會使db4o不被察覺地為這些對象加上新字段。)所以,通過發布一個包含新的TestSuite定義的更新應用,我們完全可以不被察覺地從舊的TestSuite對象移植到新的...正如前述應用所做的那樣。

全方位數據庫
    通過適當地應用,db4o就能成為數據庫中的"瑞士軍刀"。它占用足夠小的內存空間,使它能夠被包含在一個不需要消耗大量資源的項目中。同樣地,一個數據庫只在磁盤上占用一個文件的事實可能會使人們在第一眼看到它時,不能認識到它豐富的功能。將數據庫從一個地方移到另一個地方就是一個簡單的文件拷貝;你不必擔心分離的索引文件,數據文件,數據庫結構文件等等這些文件的位置。對于快速部署和零管理的數據庫應用,db4o很能勝任。
    另外,根據我們已多次描述過的,db4o在簡單性和優雅之間達到了適度的平衡。db4o的QBE既如此的簡單,又如此的功能強大,對于一組令人驚奇的應用,它經常是我們唯一需要的查詢API。如果你主要是通過指針導航而不是查詢去訪問數據庫,QBE就特別有吸引力。在這種情況下,QBE經常能高效地拿到一個對象網絡(Object Network)的根對象。然后,你就能使用db4o的激活(activation)功能從根部向下進行對象引用導航,如果這些對象都完全在內存中的話,你就更可以這么做了。
    而在使用QBE并不高效的時候,原生查詢和S.O.D.A.就能派上用場了,并且它們伴隨著一堆特性和低層次的API。我們還沒有展示db4o的加密功能,插入式文件I/O(例如,它允許你添加"寫后讀(read-after-write)"驗證),信號量,客戶端/服務器端模式,以及其它難以計數的功能。我們結論性的建議很簡單:當你的下一個Java應用需要一個數據庫,在最終開始編碼之前,你可以去訪問一下http://www.db4objects.com/。這是很值得的。



Sha Jiang 2007-12-05 12:31 發表評論
]]>
MySQL索引(摘)http://www.aygfsteel.com/jiangshachina/archive/2007/07/03/127728.htmlSha JiangSha JiangTue, 03 Jul 2007 00:44:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2007/07/03/127728.htmlhttp://www.aygfsteel.com/jiangshachina/comments/127728.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2007/07/03/127728.html#Feedback0http://www.aygfsteel.com/jiangshachina/comments/commentRss/127728.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/127728.htmlMySQL索引
    本文介紹了數據庫索引,及其優、缺點。針對MySQL索引的特點、應用進行了詳細的描述。分析了如何避免MySQL無法使用,如何使用EXPLAIN分析查詢語句,如何優化MySQL索引的應用。本文摘自《MySQL 5權威指南》(3rd)的8.9節。(2007.07.05最后更新)

    索引是一種特殊的文件(InnoDB數據表上的索引是表空間的一個組成部分),它們包含著對數據表里所有記錄的引用指針。
    注:[1]索引不是萬能的!索引可以加快數據檢索操作,但會使數據修改操作變慢。每修改數據記錄,索引就必須刷新一次。為了在某種程序上彌補這一缺陷,許多SQL命令都有一個DELAY_KEY_WRITE項。這個選項的作用是暫時制止MySQL在該命令每插入一條新記錄和每修改一條現有之后立刻對索引進行刷新,對索引的刷新將等到全部記錄插入/修改完畢之后再進行。在需要把許多新記錄插入某個數據表的場合,DELAY_KEY_WRITE選項的作用將非常明顯。[2]另外,索引還會在硬盤上占用相當大的空間。因此應該只為最經常查詢和最經常排序的數據列建立索引。注意,如果某個數據列包含許多重復的內容,為它建立索引就沒有太大的實際效果。
    從理論上講,完全可以為數據表里的每個字段分別建一個索引,但MySQL把同一個數據表里的索引總數限制為16個。
    1. InnoDB數據表的索引
    與MyISAM數據表相比,索引對InnoDB數據的重要性要大得多。在InnoDB數據表上,索引對InnoDB數據表的重要性要在得多。在InnoDB數據表上,索引不僅會在搜索數據記錄時發揮作用,還是數據行級鎖定機制的苊、基礎。"數據行級鎖定"的意思是指在事務操作的執行過程中鎖定正在被處理的個別記錄,不讓其他用戶進行訪問。這種鎖定將影響到(但不限于)SELECT...LOCK IN SHARE MODE、SELECT...FOR UPDATE命令以及INSERT、UPDATE和DELETE命令。
    出于效率方面的考慮,InnoDB數據表的數據行級鎖定實際發生在它們的索引上,而不是數據表自身上。顯然,數據行級鎖定機制只有在有關的數據表有一個合適的索引可供鎖定的時候才能發揮效力。
    2. 限制
    如果WEHERE子句的查詢條件里有不等號(WHERE coloum != ...),MySQL將無法使用索引。
    類似地,如果WHERE子句的查詢條件里使用了函數(WHERE DAY(column) = ...),MySQL也將無法使用索引。
    在JOIN操作中(需要從多個數據表提取數據時),MySQL只有在主鍵和外鍵的數據類型相同時才能使用索引。
    如果WHERE子句的查詢條件里使用比較操作符LIKE和REGEXP,MySQL只有在搜索模板的第一個字符不是通配符的情況下才能使用索引。比如說,如果查詢條件是LIKE 'abc%',MySQL將使用索引;如果查詢條件是LIKE '%abc',MySQL將不使用索引。
    在ORDER BY操作中,MySQL只有在排序條件不是一個查詢條件表達式的情況下才使用索引。(雖然如此,在涉及多個數據表查詢里,即使有索引可用,那些索引在加快ORDER BY方面也沒什么作用)
    如果某個數據列里包含許多重復的值,就算為它建立了索引也不會有很好的效果。比如說,如果某個數據列里包含的凈是些諸如"0/1"或"Y/N"等值,就沒有必要為它創建一個索引。
   
    普通索引、唯一索引和主索引
    1. 普通索引
    普通索引(由關鍵字KEY或INDEX定義的索引)的唯一任務是加快對數據的訪問速度。因此,應該只為那些最經常出現在查詢條件(WHERE column = ...)或排序條件(ORDER BY column)中的數據列創建索引。只要有可能,就應該選擇一個數據最整齊、最緊湊的數據列(如一個整數類型的數據列)來創建索引。
    2. 唯一索引
    普通索引允許被索引的數據列包含重復的值。比如說,因為人有可能同名,所以同一個姓名在同一個"員工個人資料"數據表里可能出現兩次或更多次。
    如果能確定某個數據列將只包含彼此各不相同的值,在為這個數據列創建索引的時候就應該用關鍵字UNIQUE把它定義為一個唯一索引。這么做的好處:一是簡化了MySQL對這個索引的管理工作,這個索引也因此而變得更有效率;二是MySQL會在有新記錄插入數據表時,自動檢查新記錄的這個字段的值是否已經在某個記錄的這個字段里出現過了;如果是,MySQL將拒絕插入那條新記錄。也就是說,唯一索引可以保證數據記錄的唯一性。事實上,在許多場合,人們創建唯一索引的目的往往不是為了提高訪問速度,而只是為了避免數據出現重復。
    3. 主索引
    在前面已經反復多次強調過:必須為主鍵字段創建一個索引,這個索引就是所謂的"主索引"。主索引與唯一索引的唯一區別是:前者在定義時使用的關鍵字是PRIMARY而不是UNIQUE。
    4. 外鍵索引
    如果為某個外鍵字段定義了一個外鍵約束條件,MySQL就會定義一個內部索引來幫助自己以最有效率的方式去管理和使用外鍵約束條件。
    5. 復合索引
    索引可以覆蓋多個數據列,如像INDEX(columnA, columnB)索引。這種索引的特點是MySQL可以有選擇地使用一個這樣的索引。如果查詢操作只需要用到columnA數據列上的一個索引,就可以使用復合索引INDEX(columnA, columnB)。不過,這種用法僅適用于在復合索引中排列在前的數據列組合。比如說,INDEX(A, B, C)可以當做A或(A, B)的索引來使用,但不能當做B、C或(B, C)的索引來使用。
    6. 索引的長度
    在為CHAR和VARCHAR類型的數據列定義索引時,可以把索引的長度限制為一個給定的字符個數(這個數字必須小于這個字段所允許的最大字符個數)。這么做的好處是可以生成一個尺寸比較小、檢索速度卻比較快的索引文件。在絕大多數應用里,數據庫中的字符串數據大都以各種各樣的名字為主,把索引的長度設置為10~15個字符已經足以把搜索范圍縮小到很少的幾條數據記錄了。
    在為BLOB和TEXT類型的數據列創建索引時,必須對索引的長度做出限制;MySQL所允許的最大索引長度是255個字符。

    全文索引
    文本字段上的普通索引只能加快對出現在字段內容最前面的字符串(也就是字段內容開頭的字符)進行檢索操作。如果字段里存放的是由幾個、甚至是多個單詞構成的較大段文字,普通索引就沒什么作用了。這種檢索往往以LIKE %word%的形式出現,這對MySQL來說很復雜,如果需要處理的數據量很大,響應時間就會很長。
    這類場合正是全文索引(full-text index)可以大顯身手的地方。在生成這種類型的索引時,MySQL將把在文本中出現的所有單詞創建為一份清單,查詢操作將根據這份清單去檢索有關的數據記錄。全文索引即可以隨數據表一同創建,也可以等日后有必要時再使用下面這條命令添加:
        ALTER TABLE tablename ADD FULLTEXT(column1, column2)
    有了全文索引,就可以用SELECT查詢命令去檢索那些包含著一個或多個給定單詞的數據記錄了。下面是這類查詢命令的基本語法:
        SELECT * FROM tablename
        WHERE MATCH(column1, column2) AGAINST('word1', 'word2', 'word3')
    上面這條命令將把column1和column2字段里有word1、word2和word3的數據記錄全部查詢出來。
    注解:InnoDB數據表不支持全文索引。

    查詢和索引的優化
    只有當數據庫里已經有了足夠多的測試數據時,它的性能測試結果才有實際參考價值。如果在測試數據庫里只有幾百條數據記錄,它們往往在執行完第一條查詢命令之后就被全部加載到內存里,這將使后續的查詢命令都執行得非常快--不管有沒有使用索引。只有當數據庫里的記錄超過了1000條、數據總量也超過了MySQL服務器上的內存總量時,數據庫的性能測試結果才有意義。
    在不確定應該在哪些數據列上創建索引的時候,人們從EXPLAIN SELECT命令那里往往可以獲得一些幫助。這其實只是簡單地給一條普通的SELECT命令加一個EXPLAIN關鍵字作為前綴而已。有了這個關鍵字,MySQL將不是去執行那條SELECT命令,而是去對它進行分析。MySQL將以表格的形式把查詢的執行過程和用到的索引(如果有的話)等信息列出來。
    在EXPLAIN命令的輸出結果里,第1列是從數據庫讀取的數據表的名字,它們按被讀取的先后順序排列。type列指定了本數據表與其它數據表之間的關聯關系(JOIN)。在各種類型的關聯關系當中,效率最高的是system,然后依次是const、eq_ref、ref、range、index和All(All的意思是:對應于上一級數據表里的每一條記錄,這個數據表里的所有記錄都必須被讀取一遍--這種情況往往可以用一索引來避免)。
    possible_keys數據列給出了MySQL在搜索數據記錄時可選用的各個索引。key數據列是MySQL實際選用的索引,這個索引按字節計算的長度在key_len數據列里給出。比如說,對于一個INTEGER數據列的索引,這個字節長度將是4。如果用到了復合索引,在key_len數據列里還可以看到MySQL具體使用了它的哪些部分。作為一般規律,key_len數據列里的值越小越好(意思是更快)。
    ref數據列給出了關聯關系中另一個數據表里的數據列的名字。row數據列是MySQL在執行這個查詢時預計會從這個數據表里讀出的數據行的個數。row數據列里的所有數字的乘積可以讓我們大致了解這個查詢需要處理多少組合。
    最后,extra數據列提供了與JOIN操作有關的更多信息,比如說,如果MySQL在執行這個查詢時必須創建一個臨時數據表,就會在extra列看到using temporary字樣。



Sha Jiang 2007-07-03 08:44 發表評論
]]>
My.cnf配置選項(摘)http://www.aygfsteel.com/jiangshachina/archive/2007/05/23/119308.htmlSha JiangSha JiangWed, 23 May 2007 01:26:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2007/05/23/119308.htmlhttp://www.aygfsteel.com/jiangshachina/comments/119308.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2007/05/23/119308.html#Feedback2http://www.aygfsteel.com/jiangshachina/comments/commentRss/119308.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/119308.htmlMy.cnf配置選項
本文中的配置都是從《MySQL5權威指南(3rd)》中摘抄出來的,個人認為對于使用MySQL十分有用。放在此處方便自己隨時查閱,也希望對其他朋友有所助益。(2007.05.30最后更新)

mysqld程序--目錄和文件
basedir = path  使用給定目錄作為根目錄(安裝目錄)。
character-sets-dir = path  給出存放著字符集的目錄。
datadir = path  從給定目錄讀取數據庫文件。
pid-file = filename  為mysqld程序指定一個存放進程ID的文件(僅適用于UNIX/Linux系統); Init-V腳本需要使用這個文件里的進程ID結束mysqld進程。
socket = filename  為MySQL客戶程序與服務器之間的本地通信指定一個套接字文件(僅適用于UNIX/Linux系統; 默認設置一般是/var/lib/mysql/mysql.sock文件)。
    在Windows環境下,如果MySQL客戶與服務器是通過命名管道進行通信的,--sock選項給出的將是該命名管道的名字(默認設置是MySQL)。
lower_case_table_name = 1/0  新目錄和數據表的名字是否只允許使用小寫字母; 這個選項在Windows環境下的默認設置是1(只允許使用小寫字母)。

mysqld程序--語言設置
character-sets-server = name  新數據庫或數據表的默認字符集。為了與MySQL的早期版本保持兼容,這個字符集也可以用--default-character-set選項給出; 但這個選項已經顯得有點過時了。
collation-server = name  新數據庫或數據表的默認排序方式。
lanuage = name  用指定的語言顯示出錯信息。

mysqld程序--通信、網絡、信息安全
enable-named-pipes  允許Windows 2000/XP環境下的客戶和服務器使用命名管道(named pipe)進行通信。這個命名管道的默認名字是MySQL,但可以用--socket選項來改變。
local-infile [=0]  允許/禁止使用LOAD DATA LOCAL語句來處理本地文件。
myisam-recover [=opt1, opt2, ...]  在啟動時自動修復所有受損的MyISAM數據表。這個選項的可取值有4種:DEFAULT、BACKUP、QUICK和FORCE; 它們與myisamchk程序的同名選項作用相同。
old-passwords  使用MySQL 3.23和4.0版本中的老算法來加密mysql數據庫里的密碼(默認使用MySQL 4.1版本開始引入的新加密算法)。
port = n  為MySQL程序指定一個TCP/IP通信端口(通常是3306端口)。
safe-user-create  只有在mysql.user數據庫表上擁有INSERT權限的用戶才能使用GRANT命令; 這是一種雙保險機制(此用戶還必須具備GRANT權限才能執行GRANT命令)。
shared-memory  允許使用內存(shared memory)進行通信(僅適用于Windows)。
shared-memory-base-name = name  給共享內存塊起一個名字(默認的名字是MySQL)。
skip-grant-tables  不使用mysql數據庫里的信息來進行訪問控制(警告:這將允許用戶任何用戶去修改任何數據庫)。
skip-host-cache  不使用高速緩存區來存放主機名和IP地址的對應關系。
skip-name-resovle  不把IP地址解析為主機名; 與訪問控制(mysql.user數據表)有關的檢查全部通過IP地址行進。
skip-networking  只允許通過一個套接字文件(Unix/Linux系統)或通過命名管道(Windows系統)進行本地連接,不允許ICP/IP連接; 這提高了安全性,但阻斷了來自網絡的外部連接和所有的Java客戶程序(Java客戶即使在本地連接里也使用TCP/IP)。
user = name  mysqld程序在啟動后將在給定UNIX/Linux賬戶下執行; mysqld必須從root賬戶啟動才能在啟動后切換到另一個賬戶下執行; mysqld_safe腳本將默認使用--user=mysql選項來啟動mysqld程序。

mysqld程序--內存管理、優化、查詢緩存區
bulk_insert_buffer_size = n  為一次插入多條新記錄的INSERT命令分配的緩存區長度(默認設置是8M)。
key_buffer_size = n  用來存放索引區塊的RMA值(默認設置是8M)。
join_buffer_size = n  在參加JOIN操作的數據列沒有索引時為JOIN操作分配的緩存區長度(默認設置是128K)。
max_heap_table_size = n  HEAP數據表的最大長度(默認設置是16M); 超過這個長度的HEAP數據表將被存入一個臨時文件而不是駐留在內存里。
max_connections = n  MySQL服務器同時處理的數據庫連接的最大數量(默認設置是100)。
query_cache_limit = n  允許臨時存放在查詢緩存區里的查詢結果的最大長度(默認設置是1M)。
query_cache_size = n  查詢緩存區的最大長度(默認設置是0,不開辟查詢緩存區)。
query_cache_type = 0/1/2  查詢緩存區的工作模式:0, 禁用查詢緩存區; 1,啟用查詢緩存區(默認設置); 2,"按需分配"模式,只響應SELECT SQL_CACHE命令。
read_buffer_size = n  為從數據表順序讀取數據的讀操作保留的緩存區的長度(默認設置是128KB); 這個選項的設置值在必要時可以用SQL命令SET SESSION read_buffer_size = n命令加以改變。
read_rnd_buffer_size = n  類似于read_buffer_size選項,但針對的是按某種特定順序(比如使用了ORDER BY子句的查詢)輸出的查詢結果(默認設置是256K)。
sore_buffer = n  為排序操作分配的緩存區的長度(默認設置是2M); 如果這個緩存區太小,則必須創建一個臨時文件來進行排序。
table_cache = n  同時打開的數據表的數量(默認設置是64)。
tmp_table_size = n  臨時HEAP數據表的最大長度(默認設置是32M); 超過這個長度的臨時數據表將被轉換為MyISAM數據表并存入一個臨時文件。

mysqld程序--日志
log [= file]  把所有的連接以及所有的SQL命令記入日志(通用查詢日志); 如果沒有給出file參數,MySQL將在數據庫目錄里創建一個hostname.log文件作為這種日志文件(hostname是服務器的主機名)。
log-slow-queries [= file]  把執行用時超過long_query_time變量值的查詢命令記入日志(慢查詢日志); 如果沒有給出file參數,MySQL將在數據庫目錄里創建一個hostname-slow.log文件作為這種日志文件(hostname是服務器主機 名)。
long_query_time = n  慢查詢的執行用時上限(默認設置是10s)。
long_queries_not_using_indexs  把慢查詢以及執行時沒有使用索引的查詢命令全都記入日志(其余同--log-slow-queries選項)。
log-bin [= filename]  把對數據進行修改的所有SQL命令(也就是INSERT、UPDATE和DELETE命令)以二進制格式記入日志(二進制變更日志,binary update log)。這種日志的文件名是filename.n或默認的hostname.n,其中n是一個6位數字的整數(日志文件按順序編號)。
log-bin-index = filename  二進制日志功能的索引文件名。在默認情況下,這個索引文件與二進制日志文件的名字相同,但后綴名是.index而不是.nnnnnn。
max_binlog_size = n  二進制日志文件的最大長度(默認設置是1GB)。在前一個二進制日志文件里的信息量超過這個最大長度之前,MySQL服務器會自動提供一個新的二進制日志文件接續上。
binlog-do-db = dbname  只把給定數據庫里的變化情況記入二進制日志文件,其他數據庫里的變化情況不記載。如果需要記載多個數據庫里的變化情況,就必須在配置文件使用多個本選項來設置,每個數據庫一行。
binlog-ignore-db = dbname  不把給定數據庫里的變化情況記入二進制日志文件。
sync_binlog = n  每經過n次日志寫操作就把日志文件寫入硬盤一次(對日志信息進行一次同步)。n=1是最安全的做法,但效率最低。默認設置是n=0,意思是由操作系統來負責二進制日志文件的同步工作。
log-update [= file]  記載出錯情況的日志文件名(出錯日志)。這種日志功能無法禁用。如果沒有給出file參數,MySQL會使用hostname.err作為種日志文件的名字。

mysqld程序--鏡像(主控鏡像服務器)
server-id = n  給服務器分配一個獨一無二的ID編號; n的取值范圍是1~2的32次方啟用二進制日志功能。
log-bin = name  啟用二進制日志功能。這種日志的文件名是filename.n或默認的hostname.n,其中的n是一個6位數字的整數(日志文件順序編號)。
binlog-do/ignore-db = dbname  只把給定數據庫里的變化情況記入二進制日志文件/不把給定的數據庫里的變化記入二進制日志文件。

mysqld程序--鏡像(從屬鏡像服務器)
server-id = n  給服務器分配一個唯一的ID編號
log-slave-updates  啟用從屬服務器上的日志功能,使這臺計算機可以用來構成一個鏡像鏈(A->B->C)。
master-host = hostname  主控服務器的主機名或IP地址。如果從屬服務器上存在mater.info文件(鏡像關系定義文件),它將忽略此選項。
master-user = replicusername  從屬服務器用來連接主控服務器的用戶名。如果從屬服務器上存在mater.info文件,它將忽略此選項。
master-password = passwd  從屬服務器用來連接主控服務器的密碼。如果從屬服務器上存在mater.info文件,它將忽略此選項。
master-port = n  從屬服務器用來連接主控服務器的TCP/IP端口(默認設置是3306端口)。
master-connect-retry = n  如果與主控服務器的連接沒有成功,則等待n秒(s)后再進行管理方式(默認設置是60s)。如果從屬服務器存在mater.info文件,
    它將忽略此選項。
master-ssl-xxx = xxx  對主、從服務器之間的SSL通信進行配置。
read-only = 0/1  0: 允許從屬服務器獨立地執行SQL命令(默認設置); 1: 從屬服務器只能執行來自主控服務器的SQL命令。
read-log-purge = 0/1  1: 把處理完的SQL命令立刻從中繼日志文件里刪除(默認設置); 0: 不把處理完的SQL命令立刻從中繼日志文件里刪除。
replicate-do-table = dbname.tablename  與--replicate-do-table選項的含義和用法相同,但數據庫和數據庫表名字里允許出現通配符"%"
    (例如: test%.%--對名字以"test"開頭的所有數據庫里的所以數據庫表進行鏡像處理)。
replicate-do-db = name  只對這個數據庫進行鏡像處理。
replicate-ignore-table = dbname.tablename  不對這個數據表進行鏡像處理。
replicate-wild-ignore-table = dbn.tablen  不對這些數據表進行鏡像處理。
replicate-ignore-db = dbname  不對這個數據庫進行鏡像處理。
replicate-rewrite-db = db1name > db2name  把主控數據庫上的db1name數據庫鏡像處理為從屬服務器上的db2name數據庫。
report-host = hostname  從屬服務器的主機名; 這項信息只與SHOW SLAVE HOSTS命令有關--主控服務器可以用這條命令生成一份從屬服務器的名單。
slave-compressed-protocol = 1  主、從服務器使用壓縮格式進行通信--如果它們都支持這么做的話。
slave-skip-errors = n1, n2, ...或all  即使發生出錯代碼為n1、n2等的錯誤,鏡像處理工作也繼續進行(即不管發生什么錯誤,鏡像處理工作也繼續進行)。
    如果配置得當,從屬服務器不應該在執行SQL命令時發生錯誤(在主控服務器上執行出錯的SQL命令不會被發送到從屬服務器上做鏡像處理); 如果不使用
    slave-skip-errors選項,從屬服務器上的鏡像工作就可能國為發生錯誤而中斷,中斷后需要有人工參與才能繼續進行。

mysqld--InnoDB--基本設置、表空間文件
skip-innodb  不加載InnoDB數據表驅動程序--如果用不著InnoDB數據表,可以用這個選項節省一些內存。
innodb-file-per-table  為每一個新數據表創建一個表空間文件而不是把數據表都集中保存在中央表空間里(后者是默認設置)。該選項始見于MySQL 4.1。
innodb-open-file = n  InnoDB數據表驅動程序最多可以同時打開的文件數(默認設置是300)。如果使用了innodb-file-per-table選項并且需要同時打開很多
    數據表的話,這個數字很可能需要加大。
innodb_data_home_dir = p  InnoDB主目錄,所有與InnoDB數據表有關的目錄或文件路徑都相對于這個路徑。在默認的情況下,這個主目錄就是MySQL的數據目錄。
innodb_data_file_path = ts  用來容納InnoDB為數據表的表空間: 可能涉及一個以上的文件; 每一個表空間文件的最大長度都必須以字節(B)、兆字節(MB)或
    千兆字節(GB)為單位給出; 表空間文件的名字必須以分號隔開; 最后一個表空間文件還可以帶一個autoextend屬性和一個最大長度(max:n)。
    例如,ibdata1:1G; ibdata2:1G:autoextend:max:2G的意思是: 表空間文件ibdata1的最大長度是1GB,ibdata2的最大長度也是1G,但允許它擴充到2GB。
    除文件名外,還可以用硬盤分區的設置名來定義表空間,此時必須給表空間的最大初始長度值加上newraw關鍵字做后綴,給表空間的最大擴充長度值加上
    raw關鍵字做后綴(例如/dev/hdb1:20Gnewraw或/dev/hdb1:20Graw); MySQL 4.0及更高版本的默認設置是ibdata1:10M:autoextend。
innodb_autoextend_increment = n  帶有autoextend屬性的表空間文件每次加大多少兆字節(默認設置是8MB)。這個屬性不涉及具體的數據表文件,那些文件的
    增大速度相對是比較小的。
innodb_lock_wait_timeout = n  如果某個事務在等待n秒(s)后還沒有獲得所需要的資源,就使用ROLLBACK命令放棄這個事務。這項設置對于發現和處理未能被
    InnoDB數據表驅動程序識別出來的死鎖條件有著重要的意義。這個選項的默認設置是50s。
innodb_fast_shutdown 0/1  是否以最快的速度關閉InnoDB,默認設置是1,意思是不把緩存在INSERT緩存區的數據寫入數據表,那些數據將在MySQL服務器下次
    啟動時再寫入(這么做沒有什么風險,因為INSERT緩存區是表空間的一個組成部分,數據不會丟失)。把這個選項設置為0反面危險,因為在計算機關閉時,
    InnoDB驅動程序很可能沒有足夠的時間完成它的數據同步工作,操作系統也許會在它完成數據同步工作之前強行結束InnoDB,而這會導致數據不完整。

mysqld程序--InnoDB--日志
innodb_log_group_home_dir = p  用來存放InnoDB日志文件的目錄路徑(如ib_logfile0、ib_logfile1等)。在默認的情況下,InnoDB驅動程序將使用MySQL數據目
    錄作為自己保存日志文件的位置。   
innodb_log_files_in_group = n  使用多少個日志文件(默認設置是2)。InnoDB數據表驅動程序將以輪轉方式依次填寫這些文件; 當所有的日志文件都寫滿以后,
    之后的日志信息將寫入第一個日志文件的最大長度(默認設置是5MB)。這個長度必須以MB(兆字節)或GB(千兆字節)為單位進行設置。
innodb_flush_log_at_trx_commit = 0/1/2  這個選項決定著什么時候把日志信息寫入日志文件以及什么時候把這些文件物理地寫(術語稱為"同步")到硬盤上。
    設置值0的意思是每隔一秒寫一次日志并進行同步,這可以減少硬盤寫操作次數,但可能造成數據丟失; 設置值1(設置設置)的意思是在每執行完一條COMMIT
    命令就寫一次日志并進行同步,這可以防止數據丟失,但硬盤寫操作可能會很頻繁; 設置值2是一般折衷的辦法,即每執行完一條COMMIT命令寫一次日志,
    每隔一秒進行一次同步。
innodb_flush_method = x  InnoDB日志文件的同步辦法(僅適用于UNIX/Linux系統)。這個選項的可取值有兩種: fdatasync,用fsync()函數進行同步; O_DSYNC,
    用O_SYNC()函數進行同步。
innodb_log_archive = 1  啟用InnoDB驅動程序的archive(檔案)日志功能,把日志信息寫入ib_arch_log_n文件。啟用這種日志功能在InnoDB與MySQL一起使用時沒有
    多大意義(啟用MySQL服務器的二進制日志功能就足夠用了)。

mysqld程序--InnoDB--緩存區的設置和優化
innodb_log_buffer_pool_size = n  為InnoDB數據表及其索引而保留的RAM內存量(默認設置是8MB)。這個參數對速度有著相當大的影響,如果計算機上只運行有
    MySQL/InnoDB數據庫服務器,就應該把全部內存的80%用于這個用途。
innodb_log_buffer_size = n  事務日志文件寫操作緩存區的最大長度(默認設置是1MB)。
innodb_additional_men_pool_size = n  為用于內部管理的各種數據結構分配的緩存區最大長度(默認設置是1MB)。
innodb_file_io_threads = n  I/O操作(硬盤寫操作)的最大線程個數(默認設置是4)。
innodb_thread_concurrency = n  InnoDB驅動程序能夠同時使用的最大線程個數(默認設置是8)。

mysqld程序--其它選項
bind-address = ipaddr  MySQL服務器的IP地址。如果MySQL服務器所在的計算機有多個IP地址,這個選項將非常重要。
default-storage-engine = type  新數據表的默認數據表類型(默認設置是MyISAM)。這項設置還可以通過--default-table-type選項來設置。
default-timezone = name  為MySQL服務器設置一個地理時區(如果它與本地計算機的地理時區不一樣)。
ft_min_word_len = n  全文索引的最小單詞長度工。這個選項的默認設置是4,意思是在創建全文索引時不考慮那些由3個或更少的字符構建單詞。
Max-allowed-packet = n  客戶與服務器之間交換的數據包的最大長度,這個數字至少應該大于客戶程序將要處理的最大BLOB塊的長度。這個選項的默認設置是1MB。
Sql-mode = model1, mode2, ...  MySQL將運行在哪一種SQL模式下。這個選項的作用是讓MySQL與其他的數據庫系統保持最大程度的兼容。這個選項的可取值包括
    ansi、db2、oracle、no_zero_date、pipes_as_concat。

注意:如果在配置文件里給出的某個選項是mysqld無法識別的(如,因為犯了一個愚蠢的打字錯誤),MySQL服務器將不啟動。



Sha Jiang 2007-05-23 09:26 發表評論
]]>
Apache2+MySQL5+PHP5安裝(原)http://www.aygfsteel.com/jiangshachina/archive/2007/01/02/91369.htmlSha JiangSha JiangTue, 02 Jan 2007 05:48:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2007/01/02/91369.htmlhttp://www.aygfsteel.com/jiangshachina/comments/91369.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2007/01/02/91369.html#Feedback2http://www.aygfsteel.com/jiangshachina/comments/commentRss/91369.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/91369.html 在Linux上安裝Apache2+MySQL5+PHP5
最近由于工作原因,在RedHat AS 4.0上安裝了Apache2+MySQL5+PHP5。現將安裝使用的命令記錄,以備日后查詢,也希望對其他朋友有幫助。(2007.10.17最后更新)
    使用Apache2.0.59,MySQL5.0.16和PHP5.1.4的源代碼包進行安裝。假設這三源代碼安裝包已經解壓,且路徑分別為:/home/jiang/tools/httpd-2.0.59
/home/jiang/tools/mysql-5.0.16 /home/jiang/tools/php-5.1.4。而且它們的安裝目標路徑分別為:/usr/local/apache2/usr/local/mysql5/usr/local/php5
1. 安裝Apache2
進入
/home/jiang/tools/httpd-2.0.59目錄,執行如下命令:
#./configure
--prefix=
/usr/local/apache2  -- 設置Apache安裝目標目錄
--enable-so
--enable-vhost-alias
--enable-rewrite
--enable-deflate
--with-mpm=worker
#make
#make install

編輯文件/usr/local/apache2/conf/httpd.conf:
[1]查找元素DocumentRoot,它的值默認為/usr/local/apache2/htdocs
[2]查找元素DirectoryIndex,在這一項可以添加實際應用中需要的首頁文件名

啟動/關閉Apache服務器:
進入/usr/local/apache2/bin目錄,執行命令./apachectl start(啟動服務器)或./apachectl stop(關閉服務器)。

2. 安裝MySQL5
#
groupadd mysql  -- 添加組mysql
#
useradd -g mysql mysql  -- 添加用戶mysql,并將它放入組mysql中
進入
/home/jiang/tools/mysql-5.0.16目錄,執行如下命令:
#./configure
--prefix=/path_to_mysql5  -- 設置MySQL安裝目標目錄
--with-charset=utf8  -- 設置默認字符集為utf8
#make
#make install
#./scripts/mysql_install_db  -- 初始化MySQL數據庫
進入/usr/local目錄,執行如下命令:
#chown -R mysql.mysql mysql5 -- 將/usr/local/mysql5目錄及其子目錄的屬主賦予mysql用戶

/home/jiang/tools/mysql-5.0.16/support-files
目錄 中選擇一個合適的.cnf文件放入/etc目錄中,并將文件修改為my.cnf。然后編輯該文件,使它更能切合實際的應用。

啟動/關閉服務器:
進入/usr/local/mysql5/bin目錄,執行命令./mysqld_safe -u mysql(用mysql用戶啟動服務器)或./mysqladmin -uroot shutdown(關閉服務器)。

3. 安裝PHP5
進入/home/jiang/tools/php-5.1.4目錄,執行如下命令:
#./configure
--prefix=/usr/local/php5
--enable-mbstring  -- 根據應用的需要,添加mbstring模塊
--with-apxs2=/usr/local/apache2/bin/apxs
--with-apache2=/home/jiang/tools/httpd-2.0.59
--with-png
--with-zlib
--with-config-file-path=/usr/local/php5/lib
--with-mysql=/usr/local/mysql5
--with-mysqli=/home/jiang/tools/mysql-5.0.16/scripts/mysql_config  -- 根據應用的需要,添加mysqli模塊

#make
#make install

/home/jiang/tools/php-5.1.4/php.ini-recommended文件放入/usr/local/php5/lib目錄中,并將文件名修改為php.ini
查看/usr/local/php5/lib/php.ini文件,看參數short_open_tag的值是否為On。如果是Off,請修改為On

查看/usr/local/apache2/conf/httpd.conf文件,看是否存在語句:
LoadModule php5_module        modules/libphp5.so
如果存在,即說明apache已經成功加載了php模塊;
并添加如下兩條語句(否則PHP頁面可能無法被解析):
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps


Sha Jiang 2007-01-02 13:48 發表評論
]]>
Maven入門--較復雜的實例(原)http://www.aygfsteel.com/jiangshachina/archive/2006/12/12/79093.htmlSha JiangSha JiangTue, 12 Dec 2006 10:03:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2006/12/12/79093.htmlhttp://www.aygfsteel.com/jiangshachina/comments/79093.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2006/12/12/79093.html#Feedback21http://www.aygfsteel.com/jiangshachina/comments/commentRss/79093.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/79093.htmlMaven入門--較復雜的實例
本文將使用一個較復雜的實例,講述如何定制目錄布局(即不使用Maven標準目錄布局),以及講述一些關鍵插件的使用(配置)。為了方便其它朋友能夠方便地使用該實例,后臺數據庫使用開源的面向對象數據庫--db4o,該數據庫無需安裝,已包含在與本文配套的實例中,文末附有該實例的下載鏈接。(2007.01.02最后更新)
注:轉載時請注明原作者(jiangshachina)及出處(http://www.aygfsteel.com/jiangshachina)!

1 實例的構想
文章開頭的摘要已經講述了,本文仍然將以一個實例描述如何使用Maven,
該實例將使用非Maven標準的目錄結構,并將呈現一些關鍵的Maven插件的配置與應用。 該實例是一個基于db4o的數據庫Web應用。該應用本身十分簡單,即從db4o數據庫中查詢出若干記錄并將它們顯現在Web頁面中。
    該實例仍然由一個普通應用工程(demo-app)與一個Web應用工程(demo-web),以及這兩個工程的父工程(demo)構成,最終的目標是將Web應用工程制作成war文件,并部署到JBoss服務器中。啟動服務器后,能夠在頁面中看到正確的查詢結果。
    該實例使用Eclipse3.2 + JDK1.5.0_10 + Windows2000開發。當然這僅僅只是我個人的開發平臺,但該實例并不受限于此平臺;由于我選擇使用db4o針對JDK1.5的產品包,所以該實例只能運行在JDK1.5.0或更高版本的JDK/JRE中; 該工程中的所有文件都使用UTF-8編碼方式。

2 demo工程
demo工程是其它兩個工程的父工程,它的主要職責是預定義子工程所需要依賴的jar文件(artifact),以及針對子工程所使用的插件進行通用配置。該工程完整的POM文件如下所示:
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>mvn.demo</groupId>
    <artifactId>demo</artifactId>
    <packaging>pom</packaging>
    <version>
1.0-SNAPSHOT</version>
    <description>Maven Demo Project</description>

    <modules>
        <module>demo-app</module>
        <module>demo-web</module>
    </modules>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>mvn.demo</groupId>
                <artifactId>demo-app</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>mvn.demo</groupId>
                <artifactId>demo-web</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>com.db4o</groupId>
                <artifactId>db4o-java5</artifactId>
                <version>
5.5</version>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>
2.4</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>commons-configuration</groupId>
                <artifactId>commons-configuration</artifactId>
                <version>
1.2</version>
                <exclusions>
                    <exclusion>
                        <groupId>dom4j</groupId>
                        <artifactId>dom4j</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>xml-apis</groupId>
                        <artifactId>xml-apis</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>xalan</groupId>
                        <artifactId>xalan</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>xerces</groupId>
                        <artifactId>xercesImpl</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
        <groupId>junit</groupId>
         <artifactId>junit</artifactId>
           <version>
3.8.1</version>
      <scope>test</scope>
    </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-
8</encoding>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>
1.5</source>
                    <target>
1.5</target>
                    <encoding>UTF-
8</encoding>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                    </archive>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                    </archive>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <configuration>
                    <charset>UTF16</charset>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
    預定義工程的依賴關系,就是把會被子工程依賴的artifact的詳細信息(groupId,artifactId,version,...)先聲明到<dependencyManagement>中。然后子工程只需要聲明使用某個artifact就可以了,即那時只需要設置groupId和artifactId(甚至更少)就可以了。
<dependencyManagement>中聲明的artifact并不一定真的會被使用到
2.1 聲明依賴關系
    根據實際情況,
該實例 需要使用db4o針對java5的產品包(jar文件)。由于該jar文件并不存在于Maven的中央倉庫中,所以我們不能直接通過Maven獲得該jar文件。我們只能另外下載db4o-5.5(Java版)的壓縮包,然后從壓縮包內獲得db4o-java5.jar。得到該jar后,必須先將它安裝到Maven的本地倉庫中(安裝方法參見資源[1],主題"向本地倉庫安裝文件時要生成POM文件"),以備后面的使用。此處將該artifact的groupId定義為com.db4o,artifactId定義為db4o-java5,version自然就是5.5了(請見上述POM腳本)。
    由于該實例最終是一個Web應用,所以它至少需要依賴Servlet的包(servlet-api-2.4.jar),還需要commons-configuration-1.2.jar。這兩個artifact都已經存在于Maven中央倉庫中,所以我查找到它們后,按照Maven中央倉庫的命名將它們聲明到了<dependencyManagement>中(請見上述POM腳本)。junit是進行單元測試時使用的artifact,(假設)它肯定會被每個工程使用,所以沒有將它設置到 <dependencyManagement>中,而直接設置到了 <dependency>中。
    細心的朋友肯定已經發現了,針對 commons-configuration的依賴聲明處多了一些語句。從表面上看,應該是排除了4個artifact(dom4j, xml-apis xalan xerces )。不錯,就是排除了這4個jar文件(artifact)。如果有興趣的話,可以將整個<exclusions>元素刪除,然后再嘗試一下制作war文件。你會發現在WEB-INF/lib目錄下存在著這4個artifact對應的jar文件。那我為什么要將它們“排除”呢?因為,它們是多余的!即,它們對于我的這個Web應用來說,根本就是無用的!
    Maven2加入了一個很好的特性:自動加載“依賴的依賴(Transitive Dependency)”。以commons-configuration為例。為了能夠讓它運行正常,我們實際上還需要其它一些jar(artifact),如commons-collections,commons-lang,...。但這些artifact我都沒有“顯示”地聲明需要依賴它們,但Maven會自動加載,因為
commons-configuration的POM文件將它們聲明為了dependency
    既然那個4個artifact是commons-configuration的依賴,為什么會認為它們是無用的呢?實際上,它們就不應該被聲明到commons-configuration的依賴關系中。這是commons-configuration開發者的失誤,他們沒有將依賴關系整理清晰,而將一些確實既不是runtime,更不是compile-time需要的artifact放入到了依賴關系中。在Maven中央倉庫中存在著很多這種情況,所以我們有時需要弄清楚“哪些文件是我們真正需要的,哪些是可以被清除的”。但有時候,很難做到一個不漏。正是由于這一原因,自動加載Transitive Dependency這一極好的特性,有時讓人十分無奈 ^_^
2.2 對插件進行基本配置
我們可以把對插件的全局性(如針對整個項目的)設置放到較高層次的POM文件中,因為它們被設置后,子工程們就會自然遵守它們,而且可以使每個子工程的情況都是一樣的。
    在第1節中,已經表明該工程使用JDK1.5平臺,并且所有文件都使用UTF-8
的編碼方式。而Maven默認使用JDK1.3級別的javac編譯器;默認使用本地編碼方式(簡體中文Windows操作系統默認使用GBK編碼方式)處理文件。這樣就必須對Maven進行適當設置,以滿足工程的實際需要。
    針對資源文件的處理,Maven使用maven-resources-plugin插件,需要將它的編碼方式設置為UTF-8。編譯Java源文件,是使用maven-compiler-plugin插件,需要將它的source(Java源文件)與target(class文件)的級別都設置為1.5,另外還要將它的encoding方式設置為UTF-8。(詳細設置請見POM腳本)

3 demo-app工程
demo-app工程是一個普通應用程序工程,它用于處理和數據庫相關的操作,如針對數據庫的增、刪、改、查等基本功能。該工程POM文件的主要內容如下所示:
<project>
    ......

    <build>
        <finalName>app</finalName>
        <directory>target</directory>

        <sourceDirectory>src/java</sourceDirectory>
        <outputDirectory>target/classes</outputDirectory>
        <resources>
            <resource>
                <directory>src/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
        </resources>

        <testSourceDirectory>src/test/java</testSourceDirectory>
        <testOutputDirectory>target/test-classes</testOutputDirectory>
        <testResources>
            <testResource>
                <directory>src/test/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </testResource>
        </testResources>
    </build>
</project>
    文章的開頭已經提到,本實例將會使用定制的目錄結構,但在前面卻一字不提此事,現在將描述如何定制目錄結構。Maven的標準目錄結構其實是在Super POM中設置的,由于任何POM都會繼承該POM,所以所有的工作都會默認使用標準目錄結構。要定制目錄,其實就是需要重新設置相關參數的值,即用新值覆蓋Super POM中的值。
[1]<finalName>,該元素指定了工程輸出的artifact的名稱,默認值為${artifactId}-${version},此處修改為app。
[2]<directory>,該元素指定了工程輸出的目標目錄。默認值為target,此處未修改變。
[3]<sourceDirectory>,該元素指定了Java源文件所在的目錄。默認值為src/main/java,此處修改為src/java。
[4]<outputDirectory>,該元素指定了編譯后的class文件的放置目錄。默認值為target/classes,此處未作改變。
[5]<resources> <resource>,該元素指定了Java源文件使用的資源文件的存放目錄。默認值為src/main/resources,此處修改為src/java。由于在編碼Java源文件時,Maven會將資源路徑中的文件全部拷貝到classes目錄。而此時將Java資源文件目錄與Java源文件目錄,設置為同一目錄,所以需要將.java文件排除在資源文件的范疇之外( <exclude>**/*.java</exclude> )。
[6]
<testSourceDirectory>,該元素指定了單元測試Java源文件的放置目錄。默認值為src/test/java,此處未作修改。
[7]
<testOutputDirectory>,該元素指定了單元測試Java源文件編譯后的class文件放置目錄。默認值為 target/test-classes,此處未作改變。
[8]
<testResources> <testResource>,該元素指定了單元測試Java源文件所使用的資源文件的放置目錄。默認值為src/test/resources,此處修改為 src/test/java。并且也做了與 設置<resources> <resource>時相同的處理(排除Java源文件)。
    通過上述設置后,就可以擁有一個定制的Maven工程目錄結構了。

4 demo-web工程
demo-web工程是整個應用最終的目標輸出,因為此處的目的就是制作一個war文件,然后將它部署到JBoss服務器中。與demo-app工程相比,demo-web工程的POM文件主要有如下不同內容:
<project >
    ......
    <build>
        ......
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>
2.0.1 </version>
                <configuration>
                    <webappDirectory>target/${artifactId}</webappDirectory>
                    <warSourceDirectory>src/webapp</warSourceDirectory>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jboss-maven-plugin</artifactId>
                <version>
1.3.1 </version>
                <configuration>
                    <jbossHome>E:/jboss-
4.0.2 </jbossHome>
                    <serverName>default</serverName>
                    <fileName>
                        ${project.build.directory}/${project.build.finalName}.${project.packaging}
                    </fileName>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
可以看出不同之處就在于對maven-war-plguin及jboss-maven-plugin插件的配置與使用。
    Maven使用maven-war-plugin插件對Web工程制作war文件。由于本文使用了定制目錄結構,這樣則會使maven-war-plugin無法找到Web工程的Web Root目錄(默認是src/main/webapp),所以需要對該插件進行適當地配置。<warSourceDirectory>就是Web工程的Web Root目錄,此處設置為;<webappDirectory>是制作war文件之前,相當于是一個被打開(exploded)的war文件的根目錄(默認是target/artifactId-version)。
    該工程的腳本中,還使用了一個JBoss插件。該插件可以將制作好的war文件部署(實質上是拷貝)到指定的JBoss部署目錄中。<jbossHome>是JBoss的安裝根目錄,<serverName>指JBoss Server的名稱,<fileName>是被部署war文件的名稱。

參考資源
[1]Maven入門--概念與實例. http://www.aygfsteel.com/jiangshachina/archive/2006/09/01/67080.html
[2]Maven + Continuum Weed. http://www.aygfsteel.com/jiangshachina/archive/2006/09/11/68944.aspx
[3]Maven POM Reference. http://maven.apache.org/pom.html
[3]db4o. http://www.db4objects.com
本文實例下載地址--http://www.aygfsteel.com/files/jiangshachina/mvn-demo.rar



Sha Jiang 2006-12-12 18:03 發表評論
]]>
Oracle Weed(原)http://www.aygfsteel.com/jiangshachina/archive/2006/08/12/63121.htmlSha JiangSha JiangSat, 12 Aug 2006 01:22:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2006/08/12/63121.htmlhttp://www.aygfsteel.com/jiangshachina/comments/63121.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2006/08/12/63121.html#Feedback0http://www.aygfsteel.com/jiangshachina/comments/commentRss/63121.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/63121.html閱讀全文

Sha Jiang 2006-08-12 09:22 發表評論
]]>
MySQL Weed(原)http://www.aygfsteel.com/jiangshachina/archive/2006/08/12/63120.htmlSha JiangSha JiangSat, 12 Aug 2006 01:19:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2006/08/12/63120.htmlhttp://www.aygfsteel.com/jiangshachina/comments/63120.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2006/08/12/63120.html#Feedback0http://www.aygfsteel.com/jiangshachina/comments/commentRss/63120.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/63120.html閱讀全文

Sha Jiang 2006-08-12 09:19 發表評論
]]>
在Linux上安裝MySQL Server 5.0(原)http://www.aygfsteel.com/jiangshachina/archive/2006/08/12/63117.htmlSha JiangSha JiangSat, 12 Aug 2006 01:10:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2006/08/12/63117.htmlhttp://www.aygfsteel.com/jiangshachina/comments/63117.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2006/08/12/63117.html#Feedback0http://www.aygfsteel.com/jiangshachina/comments/commentRss/63117.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/63117.html閱讀全文

Sha Jiang 2006-08-12 09:10 發表評論
]]>
在Linux上安裝Oracle10g(原)http://www.aygfsteel.com/jiangshachina/archive/2006/08/11/63050.htmlSha JiangSha JiangFri, 11 Aug 2006 09:06:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2006/08/11/63050.htmlhttp://www.aygfsteel.com/jiangshachina/comments/63050.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2006/08/11/63050.html#Feedback0http://www.aygfsteel.com/jiangshachina/comments/commentRss/63050.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/63050.html 其實我對Linux和Oracle都不熟悉,在實際的安裝過程中,還有許多不明白的地方,經常是“知其然,而不知其所以然”。如,為什么要配置kernel參數?相關kernel參數分別有什么作用?設置臨時交換空間所用的命令dd的功能是什么?......希望有朋友能夠針對其中的問題進行解答。如果文中有什么錯誤,也請大家指正。
  閱讀全文

Sha Jiang 2006-08-11 17:06 發表評論
]]>
主站蜘蛛池模板: 芜湖县| 内乡县| 凤庆县| 辽阳县| 汪清县| 锡林浩特市| 四会市| 宝清县| 清水河县| 大理市| 启东市| 德保县| 瓮安县| 海伦市| 鄂伦春自治旗| 巴塘县| 封开县| 广州市| 潼南县| 平舆县| 通许县| 林甸县| 文化| 仲巴县| 招远市| 博客| 万山特区| 东平县| 弋阳县| 新乐市| 登封市| 呼图壁县| 上饶县| 垫江县| 军事| 缙云县| 晋江市| 周至县| 德钦县| 通渭县| 板桥市|