1、數據庫鏈接池的做用html
數據庫鏈接池技術帶來的優點: java
1)資源重用mysql
因爲數據庫鏈接獲得重用,避免了頻繁建立、釋放鏈接引發的大量性能開銷。在減小系統消耗的基礎上,另外一方面也增進了系統運行環境的平穩性(減小內存碎片以及數據庫臨時進程線程的數量)。spring
2)更快的系統響應速度sql
數據庫鏈接池在初始化過程當中,每每已經建立了若干數據庫鏈接置於池中備用。此時鏈接的初始化工做均已完成。對於業務請求處理而言,直接利用現有可用鏈接,避免了數據庫鏈接初始化和釋放過程的時間開銷,從而縮減了系統總體響應時間。數據庫
3)新的資源分配手段 數組
對於多應用共享同一數據庫的系統而言,可在應用層經過數據庫鏈接的配置,實現數據庫鏈接池技術,幾年錢也許仍是個新鮮話題,對於目前的業務系統而言,若是設計中尚未考慮到鏈接池的應用,那麼…….快在設計文檔中加上這部分的內容吧。某一應用最大可用數據瀏覽器
庫鏈接數的限制,避免某一應用獨佔全部數據庫資源。緩存
4)統一的鏈接管理,避免數據庫鏈接泄漏 安全
在較爲完備的數據庫鏈接池實現中,可根據預先的鏈接佔用超時設定,強制收回被佔用鏈接。從而避免了常規數據庫鏈接操做中可能出現的資源泄漏。
2、java中有沒有內存泄漏?
首先,什麼叫內存泄露?就是一個對象已經再也不使用,但卻仍然佔據着內存得不到釋放。雖然JVM得到的物理內存有限,但大量的內存泄露會致使Java項目運行時效率降低,還有可能拋出OutOfMemory異常。
舉個例子:
Vector v = new Vector( 10 ); for ( int i = 1 ;i < 10 ; i ++ ){ Object o = new Object(); v.add(o); o = null ; }
在這個例子裏面,Vector裏面裝了一些對象,當o=null時,對象o已經再也不使用,原來o所在內存區域已經沒法取得,但因爲v中有o的引用,即便o再也不引用那塊地址,系統的GC機制也不會釋放掉o所在的內存,這就發生了內存泄露。
固然,DTS中物理鏈接(文件、數據庫、網絡)未顯式關閉,也會形成內存泄露。
3、String,StringBuffer,StringBuilder的區別
(1)都是final的,不能被繼承。
(2)String長度不可變,另外兩個長度是可變的(例如StringBuffer有append方法)
(3)StringBuffer是線程同步的,裏面的每個API都添加了synchronized修飾,而StringBuilder不是線程同步的,所以擁有更好的性能。
4、String有重寫Object的hashCode()和toString()方法嗎?若是重寫equals不重寫hashcode會怎麼樣?
有。Object.java的hashCode是native方法,應該是調用了C++的代碼。
/** * Returns a hash code for this string. The hash code for a * {@code String} object is computed as * <blockquote><pre> * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] * </pre></blockquote> * using {@code int} arithmetic, where {@code s[i]} is the * <i>i</i>th character of the string, {@code n} is the length of * the string, and {@code ^} indicates exponentiation. * (The hash value of the empty string is zero.) * * @return a hash code value for this object. */ public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
toString()方法返回的是該對象自己。
重寫equals不重寫hashCode會怎樣?
仍是看HashMap.java的代碼片斷:
while ((e = e.next) != null) { if (e.hash == h && ((ek = e.key) == key || (ek != null && key.equals(ek)))) return e.val; }
因此底層判斷的原則是先看hashcode是否是相等,再看equals是否是相等。若是重寫equals不重寫hashcode,就有可能出現兩個對象的hashCode不相等,但equals相等,這時HashMap就get不出對應的value,雖然用戶重寫equals,用本身的邏輯已經斷定是「同一對象」。
(若是你認爲這兩個對象不相同,那麼你重寫equals令其相同作什麼?)
5、Java的序列化
(1)什麼是Java的序列化?有什麼用?
將一個對象轉換成與平臺無關的二進制流儲存在外存儲器中,或在網絡中傳輸。其餘程序一旦得到這個二進制流(從文件、從數據庫、從網絡等)就能夠將其轉化爲Java對象進行操做。
舉例:Java的遠程方法調用(RMI)就是序列化的具體應用。RMI可讓一個JVM上的對象調用其餘JVM上對象的方法。RMI是J2EE的基礎。
也能夠將一個JavaBean序列化後存儲在數據庫中。
(2)怎麼實現Java的序列化和反序列化:
讓一個類實現Serializable接口:
public class Student implements Serializable{ private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } public Student(int id) { this.id = id; } }
而後使用ObjectOutputStream流寫入這個類:
public static void main(String[] args) { try { ObjectOutputStream s = new ObjectOutputStream(new FileOutputStream("E:\\1.txt")); Student s1 = new Student(1); s.writeObject(s1); s.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
運行程序,發現生成了E:\1.txt文件,其中存儲的就是s1對象。
接下來反序列化:
public static void main(String[] args) { try { ObjectInputStream s = new ObjectInputStream(new FileInputStream("E:\\1.txt")); Student s1 = (Student)s.readObject(); System.out.println(s1.getId()); s.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
運行程序,發現s1的學號1已經被讀出。
自定義序列化:在特殊狀況下,咱們有時候不能按照java底層的默認機制對一個對象序列化。這時咱們須要在序列化的類中添加readObject()和writeObject()方法,按照本身的邏輯進行序列化和反序列化。若是還須要引用默認序列化方法,則分別調用defaultReadObject()和defaultWriteObject().
有時候咱們不能將全部屬性都序列化(例如密碼等敏感信息),這時須要在不想序列化的屬性前面添加transient關鍵字。
注意:(1)static修飾的屬性不能被序列化;(2)若是被序列化對象的屬性裏面有對象(有點繞),要保證這個對象也是可序列化的。(3)對象的類名,屬性會被序列化,而方法不會被序列化。(4)反序列化時要有序列化對象的.class文件,不然強轉時會報錯。
(5)最好顯示聲明serialVersionUID:private static final long serialVersionUID = 7247714666080613254L;
由於不一樣JVM有可能對同一個類生成的serialVersionUID不一樣,也可能該類的屬性改變,這都會致使反序列化不回去,但若是人爲指定了serialVersionUID,就不存在上述狀況。
常見的序列化協議:XML,JSON
6、Java如何實現多線程?
這個基本上是必問的了,有3種方式:繼承Thread類重寫run函數,實現Runnable接口,實現Callable接口。
三種方式有什麼區別?
繼承Thread類,重寫run方法,並new這個類調用start方法。(由於java沒有多繼承,因此這種方式用的不多)
實現Runnable接口,也重寫run方法,並使用new Thread(MyThread).start()執行線程。
實現Callable接口和Runnable差很少,實現的是call方法,但能夠有返回值。
7、 線程安全
什麼是線程安全?若是一個類在多線程訪問的狀況下,其行爲永遠與預期一致,就稱爲線程安全。
反例:若是一個ArrayList類的addItem方法以下實現:
public void addItem(int item) { items[Size]=item; Size++; }
那麼假設有兩個線程1和2併發調用這個方法,假設此時數組爲空,Size=0。
線程1執行到items[Size]=item;
的時候系統調度到線程2工做,線程1暫停,那麼線程2也執行items[Size]=item;
語句,那麼就會覆蓋掉線程1加入的那個數據(由於此時Size都是0),而執行後,Size變成2,數組中卻只有1個元素,這就形成了混亂。
如何保證線程安全?
能夠對變量使用volatile修飾;也能夠對程序段或方法加synchronized修飾。
非線程安全的類(如ArrayList、HashMap等),不能在多線程中共享,但能夠在多線程環境中做爲某個線程獨享的屬性。
8、多線程環境中如何進行信息交互?Object類中的wait(),notify(),notifyAll()方法都是幹什麼用的?
關於這三個方法,JavaAPI是這麼解釋的(節選自Object.java):
/** * Causes the current thread to wait until another thread invokes the * {@link java.lang.Object#notify()} method or the * {@link java.lang.Object#notifyAll()} method for this object. * In other words, this method behaves exactly as if it simply * performs the call {@code wait(0)}. * <p> * The current thread must own this object's monitor. The thread * releases ownership of this monitor and waits until another thread * notifies threads waiting on this object's monitor to wake up * either through a call to the {@code notify} method or the * {@code notifyAll} method. The thread then waits until it can * re-obtain ownership of the monitor and resumes execution. */ public final void wait() throws InterruptedException { wait(0); } /** * Wakes up a single thread that is waiting on this object's * monitor. If any threads are waiting on this object, one of them * is chosen to be awakened. The choice is arbitrary and occurs at * the discretion of the implementation. A thread waits on an object's * monitor by calling one of the {@code wait} methods. * <p> * The awakened thread will not be able to proceed until the current * thread relinquishes the lock on this object. The awakened thread will * compete in the usual manner with any other threads that might be * actively competing to synchronize on this object; for example, the * awakened thread enjoys no reliable privilege or disadvantage in being * the next thread to lock this object. * @throws IllegalMonitorStateException if the current thread is not * the owner of this object's monitor. * @see java.lang.Object#notifyAll() * @see java.lang.Object#wait() */ public final native void notify(); /** * Wakes up all threads that are waiting on this object's monitor. A * thread waits on an object's monitor by calling one of the * {@code wait} methods. * <p> * The awakened threads will not be able to proceed until the current * thread relinquishes the lock on this object. The awakened threads * will compete in the usual manner with any other threads that might * be actively competing to synchronize on this object; for example, * the awakened threads enjoy no reliable privilege or disadvantage in * being the next thread to lock this object. * <p> * This method should only be called by a thread that is the owner * of this object's monitor. See the {@code notify} method for a * description of the ways in which a thread can become the owner of * a monitor. */ public final native void notifyAll();
這堆E文翻譯過來大概就是說,wait()方法使得持有該對象的鎖的線程阻塞掉,而notify()則是喚醒一個等待該對象的線程,notifyAll()是喚醒全部等待該對象的線程。
調用wait()方法必須在同步塊或者同步方法中進行(synchronized塊或者synchronized方法)。
這裏要注意一點:notify()和notifyAll()方法只是喚醒等待該對象的monitor的線程,並不決定哪一個線程可以獲取到monitor。而若是有多個線程等待該對象,則notify()方法喚醒的具體是哪個則由JVM底層的進程調度決定。
9、 多線程共用一個變量需注意什麼?
若是咱們實例化了一個實現Runnable接口的類的對象表明一個線程,這個類中定義了全局變量且run方法會修改變量時,若是有多個線程同時修改這個變量,就會出現異常狀況。(由於全局信息被並行的修改會形成錯誤。)
而ThreadLocal解決了這個問題。ThreadLocal類能夠封裝一個對象進去,被ThreadLocal封裝的對象對每一個線程來講是獨享的,也就是說即便 被ThreadLocal封裝的對象是全局的,它也會保證在各個線程間獨立。
接下來咱們簡單的研究一下ThreadLocal.java的源碼。
ThreadLocal提供了三個API,get(),set(),remove()。分別用於取出線程本地變量、設置、清空。
ThreadLocal底層維護了一個ThreadLocalMap,它是Thread類的一個屬性。因此每一個ThreadLocalMap均與當前線程一一對應,再裏面則是一個Entry[]數組,數組下標爲當前線程的Hash值,對應的Entry對象裏面封裝了Object value。
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }
因此get方法的具體實現邏輯是,先得到當前線程,再把當前的ThreadLocal對象自己(其中包含被封裝對象在每一個線程中的版本)傳進去,若是當前線程的Hash值命中,且對應下標中存有Entry對象,則返回這個對象,再取出封裝在裏面的value,強制轉換並返回。
set方法的實現細節是:
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
這個跟get差很少,若是當前線程中有ThreadLocalMap,則把value放進對應的下標中去。固然若是這個下標有可能在數組中不存在或者出現重複,這就要rehash了,在這裏不作討論。
ThreadLocalMap的set實現細節以下:
private void set(ThreadLocal<?> key, Object value) { // We don't use a fast path as with get() because it is at // least as common to use set() to create new entries as // it is to replace existing ones, in which case, a fast // path would fail more often than not. Entry[] tab = table; int len = tab.length; int i = key.threadLocalHashCode & (len-1); for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { ThreadLocal<?> k = e.get(); if (k == key) { e.value = value; return; } if (k == null) { replaceStaleEntry(key, value, i); return; } } tab[i] = new Entry(key, value); int sz = ++size; if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash(); }
接下來是remove方法:
public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this); }
哈哈,寫remove的時候好像做者都變懶了,把get和set裏面的前兩行壓縮到了一行。最後調用了map的remove方法,再看看map的remove方法怎麼實現的:
private void remove(ThreadLocal<?> key) { Entry[] tab = table; int len = tab.length; int i = key.threadLocalHashCode & (len-1); for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { if (e.get() == key) { e.clear(); expungeStaleEntry(i); return; } } }
挺簡單的,就是Hash命中了之後取消對封裝的那個value的引用,而後rehash一次。
接下來還有一個volatile關鍵字要介紹。用volatile修飾的變量,線程在每次使用變量的時候,都會去內存中讀取一下該變量最後的值。這樣不一樣的線程訪問同一變量,每次都看到的是最後的值。
10、 mysql索引類型,表類型
普通索引 惟一索引 主鍵索引 組合索引
MySQL爲咱們提供了不少表類型供選擇,有MyISAM、ISAM、HEAP、BerkeleyDB、InnoDB,MERGE表類型,蘿蔔白菜各有所愛是不假,但是真正選擇何種表類型仍是要看業務須要啊,每一種表類型都有其本身的屬性和優勢。
目前MyISAM與InnoDB是最經常使用的,http://www.youdiancms.com/info/348.html
MyISAM存儲引擎
MyISAM是 默認存儲引擎。它基於更老的ISAM代碼,但有不少有用的擴展。MyISAM存儲引擎的一些特徵:
全部數據值先存儲低字節。這使得數據機和操做系統分離。二進制輕便性的惟一要求是機器使用補碼(如最近20年的機器有的同樣)和IEEE浮點格式(在主流機器中也徹底是主導的)。惟一不支持二進制兼容性的機器是嵌入式系統。這些系統有時使用特殊的處理器。
先存儲數據低字節並不嚴重地影響速度;數據行中的字節通常是未聯合的,從一個方向讀未聯合的字節並不比從反向讀更佔用更多的資源。服務器上的獲取列值的代碼與其它代碼相比並不顯得時間緊。
大文件(達63位文件長度)在支持大文件的文件系統和操做系統上被支持。
當把刪除和更新及插入混合的時候,動態尺寸的行更少碎片。這要經過合併相鄰被刪除的塊,以及若下一個塊被刪除,就擴展到下一塊來自動完成。
每一個MyISAM表最大索引數是64。 這能夠經過從新編譯來改變。每一個索引最大的列數是16個。
最大的鍵長度是1000字節。這也能夠經過編譯來改變。對於鍵長度超過250字節的狀況,一個超過1024字節的的鍵塊被用上。
BLOB和TEXT列能夠被索引。
NULL值被容許在索引的列中。這個佔每一個鍵的0-1個字節。
全部數字鍵值以高字節爲先被存儲以容許一個更高地索引壓縮。
當記錄以排好序的順序插入(就像你使用一個AUTO_INCREMENT列之時),索引樹被劈開以便高節點僅包含一個鍵。這改善了索引樹的空間利用率。
每表一個AUTO_INCREMEN列的內部處理。MyISAM爲INSERT和UPDATE操做自動更新這一 列。這使得AUTO_INCREMENT列更快(至少10%)。在序列頂的值被刪除以後就不能再利用。(當AUTO_INCREMENT列被定義爲多列索 引的最後一列,能夠出現重使用從序列頂部刪除的值的狀況 )。AUTO_INCREMENT值可用ALTER TABLE或myisamch來重置。
若是數據文件中間的表沒有自由塊了,在其它線程從表讀的同時,你能夠INSERT新行到表中。(這被認識爲併發操做 )。自由塊的出現是做爲刪除行的結果,或者是用比當前內容多的數據對動態長度行更新的結果。當全部自由塊被用完(填滿),將來的插入又變成併發。
你能夠把數據文件和索引文件放在不一樣目錄,用DATA DIRECTORY和INDEX DIRECTORY選項CREATE TABLE以得到更高的速度,請參閱13.1.5節,「CREATE TABLE語法」。
每一個字符列能夠又不一樣的字符集。
在MyISAM索引文件裏又一個標誌,它代表表是否被正確關閉。若是用--myisam-recover選項啓動mysqld,MyISAM表在打開得時候被自動檢查,若是被表被不恰當地關閉,就修復表。
若是你用--update-state選項運行myisamchk,它標註表爲已檢查。myisamchk --fast只檢查那些沒有這個標誌的表。
myisamchk --analyze爲部分鍵存儲統計信息,也爲整個鍵存儲統計信息。
myisampack能夠打包BLOB和VARCHAR列。
MyISAM也支持下列特徵:
支持true VARCHAR類型;VARCHAR列以存儲在2個字節中的長度來開始。
有VARCHAR的表能夠有固定或動態記錄長度。
VARCHAR和CHAR列能夠多達64KB。
一個被搞亂的已計算索引對可對UNIQUE來使用。這容許你在表內任何列的合併上有UNIQUE。(儘管如此,你不能在一個UNIQUE已計算索引上搜索)。
InnoDB存儲引擎
InnoDB給MySQL提供 了具備提交,回滾和崩潰恢復能力的事務安全(ACID兼容)存儲引擎。InnoDB鎖定在行級而且也在SELECT語句提供一個Oracle風格一致的非 鎖定讀。這些特點增長 了多用戶部署和性能。沒有在InnoDB中擴大鎖定的須要,由於在InnoDB中行級鎖定適合很是小的空間。InnoDB也支持FOREIGN KEY強制。在SQL查詢中,你能夠自由地將InnoDB類型的表與其它MySQL的表的類型混合起來,甚至在同一個查詢中也能夠混合。
InnoDB是爲處理巨大數據量時的最大性能設計。它的CPU效率多是任何其它基於磁盤的關係數據庫引擎所不能匹敵的。
InnoDB存儲引擎被徹底與MySQL服務器整合,InnoDB存儲引擎爲在主內存中緩存數據和索引而維持它本身的緩衝池。 InnoDB存儲它的表&索引在一個表空間中,表空間能夠包含數個文件(或原始磁盤分區)。這與MyISAM表不一樣,好比在MyISAM表中每一個表被存在 分離的文件中。InnoDB 表能夠是任何尺寸,即便在文件尺寸被限制爲2GB的操做系統上。
InnoDB默認地被包含在MySQL二進制分發中。Windows Essentials installer使InnoDB成爲Windows上MySQL的 默認表。
InnoDB被用來在衆多須要高性能的大型數據庫站點上產生。著名的Internet新聞站點Slashdot.org運行在 InnoDB上。Mytrix, Inc.在InnoDB上存儲超過1TB的數據,還有一些其它站點在InnoDB上處理平均每秒800次插入/更新的負荷。
InnoDB和MyISAM的區別
區別概述:
MyISAM 是MySQL中默認的存儲引擎,通常來講不是有太多人關心這個東西。決定使用什麼樣的存儲引擎是一個很tricky的事情,可是仍是值咱們去研究一下,這裏的文章只考慮 MyISAM 和InnoDB這兩個,由於這兩個是最多見的。
下面先讓咱們回答一些問題:
你的數據庫有外鍵嗎?
你須要事務支持嗎?
你須要全文索引嗎?
你常用什麼樣的查詢模式?
你的數據有多大?
思考上面這些問題可讓你找到合適的方向,但那並非絕對的。若是你須要事務處理或是外鍵,那麼InnoDB 多是比較好的方式。若是你須要全文索引,那麼一般來講 MyISAM是好的選擇,由於這是系統內建的,然而,咱們其實並不會常常地去測試兩百萬行記錄。因此,就算是慢一點,咱們能夠經過使用Sphinx從 InnoDB中得到全文索引。
數據的大小,是一個影響你選擇什麼樣存儲引擎的重要因素,大尺寸的數據集趨向於選擇InnoDB方式,由於其支持事務處理和故障恢復。數據庫的在小 決定了故障恢復的時間長短,InnoDB能夠利用事務日誌進行數據恢復,這會比較快。而MyISAM可能會須要幾個小時甚至幾天來幹這些事,InnoDB 只須要幾分鐘。
您操做數據庫表的習慣可能也會是一個對性能影響很大的因素。好比: COUNT() 在 MyISAM 表中會很是快,而在InnoDB 表下可能會很痛苦。而主鍵查詢則在InnoDB下會至關至關的快,但須要當心的是若是咱們的主鍵太長了也會致使性能問題。大批的inserts 語句在MyISAM下會快一些,可是updates 在InnoDB 下會更快一些——尤爲在併發量大的時候。
因此,到底你檢使用哪個呢?根據經驗來看,若是是一些小型的應用或項目,那麼MyISAM 也許會更適合。固然,在大型的環境下使用MyISAM 也會有很大成功的時候,但卻不老是這樣的。若是你正在計劃使用一個超大數據量的項目,並且須要事務處理或外鍵支持,那麼你真的應該直接使用InnoDB方 式。但須要記住InnoDB 的表須要更多的內存和存儲,轉換100GB 的MyISAM 表到InnoDB 表可能會讓你有很是壞的體驗。
區別總結:
1.InnoDB不支持FULLTEXT類型的索引。
2.InnoDB 中不保存表的具體行數,也就是說,執行select count(*) from table時,InnoDB要掃描一遍整個表來計算有多少行,可是MyISAM只要簡單的讀出保存好的行數便可。注意的是,當count(*)語句包含 where條件時,兩種表的操做是同樣的。
3.對於AUTO_INCREMENT類型的字段,InnoDB中必須包含只有該字段的索引,可是在MyISAM表中,能夠和其餘字段一塊兒創建聯合索引。
4.DELETE FROM table時,InnoDB不會從新創建表,而是一行一行的刪除。
5.LOAD TABLE FROM MASTER操做對InnoDB是不起做用的,解決方法是首先把InnoDB表改爲MyISAM表,導入數據後再改爲InnoDB表,可是對於使用的額外的InnoDB特性(例如外鍵)的表不適用。
另外,InnoDB表的行鎖也不是絕對的,若是在執行一個SQL語句時MySQL不能肯定要掃描的範圍,InnoDB表一樣會鎖全表,例如update table set num=1 where name like 「%aaa%」
提高InnoDB性能的方法:
MyISAM和InnoDB存儲引擎性能差異並非很大,針對InnoDB來講,影響性能的主要是 innodb_flush_log_at_trx_commit 這個選項,若是設置爲1的話,那麼每次插入數據的時候都會自動提交,致使性能急劇降低,應該是跟刷新日誌有關係,設置爲0效率可以看到明顯提高,固然,同 樣你能夠SQL中提交「SET AUTOCOMMIT = 0」來設置達到好的性能。另外,還據說經過設置innodb_buffer_pool_size可以提高InnoDB的性能,可是我測試發現沒有特別明顯 的提高。
基本上咱們能夠考慮使用InnoDB來替代咱們的MyISAM引擎了,由於InnoDB自身不少良好的特色,好比事務支持、存儲 過程、視圖、行級鎖定等等,在併發不少的狀況下,相信InnoDB的表現確定要比MyISAM強不少,固然,相應的在my.cnf中的配置也是比較關鍵 的,良好的配置,可以有效的加速你的應用。
任何一種表都不是萬能的,只用恰當的針對業務類型來選擇合適的表類型,才能最大的發揮MySQL的性能優點。
11、http請求的過程
HTTP通訊機制是在一次完整的HTTP通訊過程當中,Web瀏覽器與Web服務器之間將完成下列7個步驟:
1. 創建TCP鏈接
在HTTP工做開始以前,Web瀏覽器首先要經過網絡與Web服務器創建鏈接,該鏈接是經過TCP來完成的,該協議與IP協議共同構建Internet,即著名的TCP/IP協議族,所以Internet又被稱做是TCP/IP網絡。HTTP是比TCP更高層次的應用層協議,根據規則,只有低層協議創建以後才能進行更高層協議的鏈接,所以,首先要創建TCP鏈接,通常TCP鏈接的端口號是80。
2. Web瀏覽器向Web服務器發送請求命令
一旦創建了TCP鏈接,Web瀏覽器就會向Web服務器發送請求命令。例如:GET/sample/hello.jsp HTTP/1.1。
3. Web瀏覽器發送請求頭信息
瀏覽器發送其請求命令以後,還要以頭信息的形式向Web服務器發送一些別的信息,以後瀏覽器發送了一空白行來通知服務器,它已經結束了該頭信息的發送。
4. Web服務器應答
客戶機向服務器發出請求後,服務器會客戶機回送應答, HTTP/1.1 200 OK ,應答的第一部分是協議的版本號和應答狀態碼。
5. Web服務器發送應答頭信息
正如客戶端會隨同請求發送關於自身的信息同樣,服務器也會隨同應答向用戶發送關於它本身的數據及被請求的文檔。
6. Web服務器向瀏覽器發送數據
Web服務器向瀏覽器發送頭信息後,它會發送一個空白行來表示頭信息的發送到此爲結束,接着,它就以Content-Type應答頭信息所描述的格式發送用戶所請求的實際數據。
7. Web服務器關閉TCP鏈接
通常狀況下,一旦Web服務器向瀏覽器發送了請求數據,它就要關閉TCP鏈接,而後若是瀏覽器或者服務器在其頭信息加入了這行代碼:Connection:keep-alive
TCP鏈接在發送後將仍然保持打開狀態,因而,瀏覽器能夠繼續經過相同的鏈接發送請求。保持鏈接節省了爲每一個請求創建新鏈接所需的時間,還節約了網絡帶寬。
TCP創建鏈接的過程是三次握手
在TCP/IP協議中,TCP協議提供可靠的鏈接服務,採用三次握手創建一個鏈接。
第一次握手:創建鏈接時,客戶端發送syn包(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認;
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時本身也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。 完成三次握手,客戶端與服務器開始傳送數據.
12、Hibernate數據對象的狀態
Hibernate中的對象有3種狀態:Transient(瞬時),Persistent(持久)和Detached(託管)。
1 瞬時狀態:
由new命令開闢內存空間的java對象,例如Student stu = new Student();若是沒有變量對他引用,它將被JVM回收。瞬時對象在內存中孤立存在,他的意義僅是攜帶信息的載體,不和數據庫中的數據有任何的關聯。經過session的save()和saveOrUpdate()方法能夠把一個瞬時對象與數據庫相關聯,並把瞬時對象攜帶的信息經過配置文件所作的映射插入到數據庫中,這個瞬時對象就成了持久化對象,擁有和數據庫記錄相同的id標示(Hibernate自動將id賦予它)
瞬時對象的特色是:
(1)不和Session實例關聯
(2)在數據庫中沒有和瞬時對象關聯的記錄
2 持久化狀態:
持久的實例在數據庫中有對應的記錄,擁有一個持久化標識。持久對象老是與Session和Transaction相關聯,在一個Session中,對持久對象的改變不會立刻對數據庫進行變動,而必須在Transaction終止,也就是執行commit()以後,纔在數據庫中真正運行SQL進行變動,持久對象的狀態纔會與數據庫進行同步。在同步以前的持久對象成爲髒(dirty)對象。
使用find(),get(),load()和iterater()等方法查詢到得數據對象,都是持久化對象;若是一個瞬時對象被持久對象引用,則該對象也會自動變爲持久對象。
若是使用delete()方法,它就會變爲瞬時對象;當一個Session執行close()或clear()、evict()以後,持久對象就會變爲託管對象。
持久對象的特色:
(1)和Session實例關聯
(2)在數據庫中有和持久對象關聯的記錄
3 託管狀態:
與持久對象關聯的Session被關閉後,對象就變爲託管的。對託管對象的引用依然有效,對象可繼續被修改。託管對象若是從新關聯到某個新的Session上,會再次轉變爲持久的。託管狀態期間的改動將會被持久化到數據庫。
託管狀態擁有數據庫標識id,因此它能夠經過update()、saveOrUpdate()和lock()等方法,再度與持久層關聯。
託管對象的特色:
(1)本質上和瞬時對象相同
(2)只是比瞬時對象多了一個數據庫記錄標識值id
十3、內存排序和數據庫排序分頁的優缺點
我的理解,
內存排序能夠將數據一會兒全取出來,放入內存中進行排序,可是佔用內存。
數據庫排序,每次換頁都要從數據庫中從新提取數據,可是不佔用太多內存。
十4、transient
Java的serialization提供了一種持久化對象實例的機制。當持久化對象時,可能有一個特殊的對象數據成員,咱們不想用 serialization機制來保存它。爲了在一個特定對象的一個域上關閉serialization,能夠在這個域前加上關鍵字transient。 當一個對象被序列化的時候,transient型變量的值不包括在序列化的表示中,然而非transient型的變量是被包括進去的。
十5、spring ioc容器配置元數據的方式
http://blog.csdn.net/helloboat/article/details/51199319
基於XML文件進行配置。
基於註解進行配置。 @service @repository @controller 自動掃描
基於Java程序進行配置(Spring 3+)
用@component標註Car Person