Java 面試知識點解析(六)——數(shù)據(jù)庫篇

  • 前言:

在遨游了一番 Java Web 的世界之后,發(fā)現(xiàn)了自己的一些缺失脊髓,所以就著一篇深度好文:知名互聯(lián)網(wǎng)公司校招 Java 開發(fā)崗面試知識點解析 蜂科,來好好的對 Java 知識點進行復(fù)習和學習一番曼追,大部分內(nèi)容參照自這一篇文章窍仰,有一些自己補充的,也算是重新學習一下 Java 吧礼殊。

前序文章鏈接:

Java 面試知識點解析(一)——基礎(chǔ)知識篇

Java 面試知識點解析(二)——高并發(fā)編程篇

Java 面試知識點解析(三)——JVM篇

Java 面試知識點解析(四)——版本特性篇

Java 面試知識點解析(五)——網(wǎng)絡(luò)協(xié)議篇


前排引用說明及好文推薦:面試/筆試第三彈 —— 數(shù)據(jù)庫面試問題集錦驹吮、數(shù)據(jù)庫常見面試題(開發(fā)者篇)

1)什么是存儲過程针史?有哪些優(yōu)缺點?

存儲過程就像是編程語言中的函數(shù)一樣碟狞,封裝了我們的代碼(PLSQL啄枕,T-SQL)

例如:

-------------創(chuàng)建名為GetUserAccount的存儲過程----------------
create Procedure GetUserAccount
as
select * from UserAccount
go

-------------執(zhí)行上面的存儲過程----------------
exec GetUserAccount

存儲過程的優(yōu)點:

  • 能夠?qū)⒋a封裝起來
  • 保存在數(shù)據(jù)庫之中
  • 讓編程語言進行調(diào)用
  • 存儲過程是一個預(yù)編譯的代碼塊,執(zhí)行效率比較高
  • 一個存儲過程替代大量T_SQL語句 族沃,可以降低網(wǎng)絡(luò)通信量频祝,提高通信速率

存儲過程的缺點:

  • 每個數(shù)據(jù)庫的存儲過程語法幾乎都不一樣,十分難以維護(不通用)
  • 業(yè)務(wù)邏輯放在數(shù)據(jù)庫上脆淹,難以迭代

2)三大范式

  • 思考這樣的一個例子:

我們現(xiàn)在需要建立一個描述學校教務(wù)的數(shù)據(jù)庫智润,該數(shù)據(jù)庫涉及的對象包括學生的學號(Sno)、所在系(Sdept)未辆、系主任姓名(Mname)、課程號(Cno)和成績(Grade)锯玛,假設(shè)我們使用單一的關(guān)系模式 Student 來表示咐柜,那么根據(jù)現(xiàn)實世界已知的信息,會描述成以下這個樣子:

但是攘残,這個關(guān)系模式存在以下問題:

(1) 數(shù)據(jù)冗余
比如拙友,每一個系的系主任姓名重復(fù)出現(xiàn),重復(fù)次數(shù)與該系所有學生的所有課程成績出現(xiàn)次數(shù)相同歼郭,這將浪費大量的存儲空間遗契。
(2)更新異常(update anomalies)
由于數(shù)據(jù)冗余,當更新數(shù)據(jù)庫中的數(shù)據(jù)時病曾,系統(tǒng)要付出很大的代價來維護數(shù)據(jù)庫的完整性牍蜂,否則會面臨數(shù)據(jù)不一致的危險。比如泰涂,某系更換系主任后鲫竞,必須修改與該系學生有關(guān)的每一個元組。
(3)插入異常(insertion anomalies)
如果一個系剛成立逼蒙,尚無學生从绘,則無法把這個系及其系主任的信息存入數(shù)據(jù)庫。
(4)刪除異常(deletion anomalies)
如果某個系的學生全部畢業(yè)了是牢,則在刪除該系學生信息的同時僵井,這個系及其系主任的信息也丟失了。

  • 總結(jié): 所以驳棱,我們在設(shè)計數(shù)據(jù)庫的時候批什,就需要滿足一定的規(guī)范要求,而滿足不同程度要求的就是不同的范式社搅。
  • 第一范式: 列不可分

1NF(第一范式)是對屬性具有原子性的要求渊季,不可再分朋蔫,例如:

如果認為最后一列還可以再分成出生年,出生月却汉,出生日驯妄,則它就不滿足第一范式的要求。

  • 第二范式: 消除非主屬性對碼的部分函數(shù)依賴

2NF(第二范式)是對記錄有唯一性的要求合砂,即實體的唯一性青扔,不存在部分依賴,每一列與主鍵都相關(guān)翩伪,例如:

該表明顯說明了兩個事物:學生信息和課程信息微猖;正常的依賴應(yīng)該是:學分依賴課程號,姓名依賴學號缘屹,但這里存在非主鍵字段對碼的部分依賴凛剥,即與主鍵不相關(guān),不滿足第二范式的要求轻姿。

可能存在的問題:

  • 數(shù)據(jù)冗余:每條記錄都含有相同信息犁珠;
  • 刪除異常:刪除所有學生成績,就把課程信息全刪除了互亮;
  • 插入異常:學生未選課犁享,無法記錄進數(shù)據(jù)庫;
  • 更新異常:調(diào)整課程學分豹休,所有行都調(diào)整炊昆。

正確的做法:

  • 第三范式: 消除非主屬性對碼的傳遞函數(shù)依賴

3NF(第三范式)對字段有冗余性的要求,任何字段不能由其他字段派生出來威根,它要求字段沒有冗余凤巨,即不存在依賴傳遞,例如:

很明顯洛搀,學院電話是一個冗余字段磅甩,因為存在依賴傳遞:(學號)→(學生)→(學院)→(學院電話)

可能會存在的問題:

  • 數(shù)據(jù)冗余:有重復(fù)值;
  • 更新異常:有重復(fù)的冗余信息姥卢,修改時需要同時修改多條記錄卷要,否則會出現(xiàn)數(shù)據(jù)不一致的情況 。

正確的做法:


3)數(shù)據(jù)庫索引

  • 什么是索引独榴?

索引是對數(shù)據(jù)庫表中一個或多個列的值進行排序的數(shù)據(jù)結(jié)構(gòu)僧叉,以協(xié)助快速查詢、更新數(shù)據(jù)庫表中數(shù)據(jù)棺榔。

你也可以這樣理解:索引就是加快檢索表中數(shù)據(jù)的方法瓶堕。數(shù)據(jù)庫的索引類似于書籍的索引。在書籍中症歇,索引允許用戶不必翻閱完整個書就能迅速地找到所需要的信息郎笆。在數(shù)據(jù)庫中谭梗,索引也允許數(shù)據(jù)庫程序迅速地找到表中的數(shù)據(jù),而不必掃描整個數(shù)據(jù)庫宛蚓。

  • 底層數(shù)據(jù)結(jié)構(gòu)是什么激捏,為什么使用這種數(shù)據(jù)結(jié)構(gòu)?

(1)底層數(shù)據(jù)結(jié)構(gòu)是B+樹:
在數(shù)據(jù)結(jié)構(gòu)中凄吏,我們最為常見的搜索結(jié)構(gòu)就是二叉搜索樹和AVL樹(高度平衡的二叉搜索樹远舅,為了提高二叉搜索樹的效率,減少樹的平均搜索長度)了痕钢。然而图柏,無論二叉搜索樹還是AVL樹,當數(shù)據(jù)量比較大時任连,都會由于樹的深度過大而造成I/O讀寫過于頻繁蚤吹,進而導(dǎo)致查詢效率低下,因此對于索引而言随抠,多叉樹結(jié)構(gòu)成為不二選擇裁着。特別地,B-Tree的各種操作能使B樹保持較低的高度暮刃,從而保證高效的查找效率。

(2)使用B+樹的原因:
查找速度快爆土、效率高椭懊,在查找的過程中,每次都能拋棄掉一部分節(jié)點步势,減少遍歷個數(shù)氧猬。(此時,你應(yīng)該在白紙上畫出什么是B+樹)

  • 索引的分類坏瘩?
  • 唯一索引:唯一索引不允許兩行具有相同的索引值
  • 主鍵索引:為表定義一個主鍵將自動創(chuàng)建主鍵索引盅抚,主鍵索引是唯一索引的特殊類型。主鍵索引要求主鍵中的每個值是唯一的倔矾,并且不能為空
  • 聚集索引(Clustered):表中各行的物理順序與鍵值的邏輯(索引)順序相同妄均,每個表只能有一個
  • 非聚集索引(Non-clustered):非聚集索引指定表的邏輯順序。數(shù)據(jù)存儲在一個位置哪自,索引存儲在另一個位置丰包,索引中包含指向數(shù)據(jù)存儲位置的指針∪老铮可以有多個邑彪,小于249個
  • 索引的優(yōu)缺點?

(1)優(yōu)點:

  • 大大加快數(shù)據(jù)的檢索速度胧华,這也是創(chuàng)建索引的最主要的原因寄症;
  • 加速表和表之間的連接宙彪;
  • 在使用分組和排序子句進行數(shù)據(jù)檢索時,同樣可以顯著減少查詢中分組和排序的時間有巧;
  • 通過創(chuàng)建唯一性索引释漆,可以保證數(shù)據(jù)庫表中每一行數(shù)據(jù)的唯一性;

(2)缺點:

  • 時間方面:創(chuàng)建索引和維護索引要耗費時間剪决,具體地灵汪,當對表中的數(shù)據(jù)進行增加、刪除和修改的時候柑潦,索引也要動態(tài)的維護享言,這樣就降低了數(shù)據(jù)的維護速度;
  • 空間方面:索引需要占物理空間渗鬼。
  • 什么樣的字段適合創(chuàng)建索引览露?
  • 經(jīng)常作查詢選擇的字段
  • 經(jīng)常作表連接的字段
  • 經(jīng)常出現(xiàn)在order by, group by, distinct 后面的字段
  • 創(chuàng)建索引時需要注意什么?
  • 非空字段:應(yīng)該指定列為NOT NULL譬胎,除非你想存儲NULL差牛。在mysql中,含有空值的列很難進行查詢優(yōu)化堰乔,因為它們使得索引偏化、索引的統(tǒng)計信息以及比較運算更加復(fù)雜。你應(yīng)該用0镐侯、一個特殊的值或者一個空串代替空值侦讨;

  • 取值離散大的字段:(變量各個取值之間的差異程度)的列放到聯(lián)合索引的前面,可以通過count()函數(shù)查看字段的差異值苟翻,返回值越大說明字段的唯一值越多字段的離散程度高韵卤;

  • 索引字段越小越好:數(shù)據(jù)庫的數(shù)據(jù)存儲以頁為單位一頁存儲的數(shù)據(jù)越多一次IO操作獲取的數(shù)據(jù)越大效率越高。


4)聽說過事務(wù)嗎崇猫?(必考)

事務(wù)簡單來說:一個 Session 中所進行所有的操作沈条,要么同時成功,要么同時失敗诅炉;作為單個邏輯工作單元執(zhí)行的一系列操作蜡歹,滿足四大特性:

  1. 原子性(Atomicity):事務(wù)作為一個整體被執(zhí)行 ,要么全部執(zhí)行涕烧,要么全部不執(zhí)行
  2. 一致性(Consistency):保證數(shù)據(jù)庫狀態(tài)從一個一致狀態(tài)轉(zhuǎn)變?yōu)榱硪粋€一致狀態(tài)
  3. 隔離性(Isolation):多個事務(wù)并發(fā)執(zhí)行時季稳,一個事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行
  4. 持久性(Durability):一個事務(wù)一旦提交,對數(shù)據(jù)庫的修改應(yīng)該永久保存
  • 實例說明:
/*
 * 我們來模擬A向B賬號轉(zhuǎn)賬的場景
 *   A和B賬戶都有1000塊澈魄,現(xiàn)在我讓A賬戶向B賬號轉(zhuǎn)500塊錢
 *
 **/
//JDBC默認的情況下是關(guān)閉事務(wù)的景鼠,下面我們看看關(guān)閉事務(wù)去操作轉(zhuǎn)賬操作有什么問題

//A賬戶減去500塊
String sql = "UPDATE a SET money=money-500 ";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate();

//B賬戶多了500塊
String sql2 = "UPDATE b SET money=money+500";
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate();

從上面看,我們的確可以發(fā)現(xiàn)A向B轉(zhuǎn)賬,成功了铛漓∷菹悖可是如果A向B轉(zhuǎn)賬的過程中出現(xiàn)了問題呢?下面模擬一下

// A賬戶減去500塊
String sql = "UPDATE a SET money=money-500 ";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate();

// 這里模擬出現(xiàn)問題
int a = 3 / 0;

String sql2 = "UPDATE b SET money=money+500";
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate();

顯然浓恶,上面代碼是會拋出異常的玫坛,我們再來查詢一下數(shù)據(jù)。A賬戶少了500塊錢包晰,B賬戶的錢沒有增加湿镀。這明顯是不合理的。

我們可以通過事務(wù)來解決上面出現(xiàn)的問題:

    // 開啟事務(wù),對數(shù)據(jù)的操作就不會立即生效伐憾。
    connection.setAutoCommit(false);

    // A賬戶減去500塊
    String sql = "UPDATE a SET money=money-500 ";
    preparedStatement = connection.prepareStatement(sql);
    preparedStatement.executeUpdate();

    // 在轉(zhuǎn)賬過程中出現(xiàn)問題
    int a = 3 / 0;

    // B賬戶多500塊
    String sql2 = "UPDATE b SET money=money+500";
    preparedStatement = connection.prepareStatement(sql2);
    preparedStatement.executeUpdate();

    // 如果程序能執(zhí)行到這里勉痴,沒有拋出異常,我們就提交數(shù)據(jù)
    connection.commit();

    // 關(guān)閉事務(wù)【自動提交】
    connection.setAutoCommit(true);

} catch(SQLException e) {
    try {
        // 如果出現(xiàn)了異常树肃,就會進到這里來蒸矛,我們就把事務(wù)回滾【將數(shù)據(jù)變成原來那樣】
        connection.rollback();

        // 關(guān)閉事務(wù)【自動提交】
        connection.setAutoCommit(true);
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
}

上面的程序也一樣拋出了異常,A賬戶錢沒有減少胸嘴,B賬戶的錢也沒有增加雏掠。

  • 注意:當Connection遇到一個未處理的SQLException時,系統(tǒng)會非正常退出劣像,事務(wù)也會自動回滾乡话,但如果程序捕獲到了異常,是需要在catch中顯式回滾事務(wù)的耳奕。

5)事務(wù)的并發(fā)問題有哪幾種绑青?

  1. 丟失更新:一個事務(wù)的更新覆蓋了另一個事務(wù)的更新;
  2. 臟讀:一個事務(wù)讀取了另一個事務(wù)未提交的數(shù)據(jù)吮铭;
  3. 不可重復(fù)讀:不可重復(fù)讀的重點是修改时迫,同樣條件下兩次讀取結(jié)果不同颅停,也就是說谓晌,被讀取的數(shù)據(jù)可以被其它事務(wù)修改;
  4. 幻讀:幻讀的重點在于新增或者刪除癞揉,同樣條件下兩次讀出來的記錄數(shù)不一樣纸肉。

6)事務(wù)的隔離級別有哪幾種?

隔離級別決定了一個session中的事務(wù)可能對另一個session中的事務(wù)的影響喊熟。ANSI標準定義了4個隔離級別柏肪,MySQL的InnoDB都支持,分別是:

  1. 讀未提交(READ UNCOMMITTED):最低級別的隔離芥牌,通常又稱為dirty read烦味,它允許一個事務(wù)讀取另一個事務(wù)還沒 commit 的數(shù)據(jù),這樣可能會提高性能,但是會導(dǎo)致臟讀問題谬俄;

  2. 讀已提交(READ COMMITTED):在一個事務(wù)中只允許對其它事務(wù)已經(jīng) commit 的記錄可見柏靶,該隔離級別不能避免不可重復(fù)讀問題;

  3. 可重復(fù)讀(REPEATABLE READ):在一個事務(wù)開始后溃论,其他事務(wù)對數(shù)據(jù)庫的修改在本事務(wù)中不可見屎蜓,直到本事務(wù) commit 或 rollback。但是钥勋,其他事務(wù)的 insert/delete 操作對該事務(wù)是可見的炬转,也就是說,該隔離級別并不能避免幻讀問題算灸。在一個事務(wù)中重復(fù) select 的結(jié)果一樣扼劈,除非本事務(wù)中 update 數(shù)據(jù)庫。

  4. 序列化(SERIALIZABLE):最高級別的隔離乎婿,只允許事務(wù)串行執(zhí)行测僵。

MySQL默認的隔離級別是可重復(fù)讀(REPEATABLE READ)

  • MySql 的事務(wù)支持

MySQL的事務(wù)支持不是綁定在MySQL服務(wù)器本身,而是與存儲引擎相關(guān):

  • MyISAM:不支持事務(wù)谢翎,用于只讀程序提高性能捍靠;
  • InnoDB:支持ACID事務(wù)、行級鎖森逮、并發(fā)榨婆;
  • Berkeley DB:支持事務(wù)。

7)什么是視圖褒侧?以及視圖的使用場景有哪些良风?

視圖是一種虛擬的表,具有和物理表相同的功能闷供⊙萄耄可以對視圖進行增,改歪脏,查疑俭,操作,試圖通常是有一個表或者多個表的行或列的子集婿失。對視圖的修改不影響基本表钞艇。它使得我們獲取數(shù)據(jù)更容易,相比多表查詢豪硅。

如下兩種場景一般會使用到視圖:

  1. 不希望訪問者獲取整個表的信息哩照,只暴露部分字段給訪問者,所以就建一個虛表懒浮,就是視圖飘弧。
  2. 查詢的數(shù)據(jù)來源于不同的表,而查詢者希望以統(tǒng)一的方式查詢,這樣也可以建立一個視圖次伶,把多個表查詢結(jié)果聯(lián)合起來蹋岩,查詢者只需要直接從視圖中獲取數(shù)據(jù),不必考慮數(shù)據(jù)來源于不同表所帶來的差異学少。

注意:這個視圖是在數(shù)據(jù)庫中創(chuàng)建的 而不是用代碼創(chuàng)建的剪个。


8)drop,delete與truncate的區(qū)別?

drop 直接刪除表版确;truncate 刪除表中數(shù)據(jù)扣囊,再插入時自增長id又從1開始 ;delete 刪除表中數(shù)據(jù)绒疗,可以加where字句侵歇。

  • drop table:
  • 屬于DDL(Data Definition Language,數(shù)據(jù)庫定義語言)
  • 不可回滾
  • 不可帶 where
  • 表內(nèi)容和結(jié)構(gòu)刪除
  • 刪除速度快
  • truncate table:
  • 屬于DDL(Data Definition Language吓蘑,數(shù)據(jù)庫定義語言)
  • 不可回滾
  • 不可帶 where
  • 表內(nèi)容刪除
  • 刪除速度快
  • delete from:
  • 屬于DML
  • 可回滾
  • 可帶where
  • 表結(jié)構(gòu)在惕虑,表內(nèi)容要看where執(zhí)行的情況
  • 刪除速度慢,需要逐行刪除
  • 使用簡要說明:
  • 不再需要一張表的時候,用drop
  • 想刪除部分數(shù)據(jù)行時候磨镶,用delete溃蔫,并且?guī)蟱here子句
  • 保留表而刪除所有數(shù)據(jù)的時候用truncate

9)觸發(fā)器的作用?

觸發(fā)器是與表相關(guān)的數(shù)據(jù)庫對象琳猫,在滿足定義條件時觸發(fā)伟叛,并執(zhí)行觸發(fā)器中定義的語句集合。觸發(fā)器的這種特性可以協(xié)助應(yīng)用在數(shù)據(jù)庫端確保數(shù)據(jù)庫的完整性脐嫂。


10)數(shù)據(jù)庫的樂觀鎖和悲觀鎖是什么统刮?

數(shù)據(jù)庫管理系統(tǒng)(DBMS)中的并發(fā)控制的任務(wù)是確保在多個事務(wù)同時存取數(shù)據(jù)庫中同一數(shù)據(jù)時不破壞事務(wù)的隔離性和統(tǒng)一性以及數(shù)據(jù)庫的統(tǒng)一性。

樂觀并發(fā)控制(樂觀鎖)和悲觀并發(fā)控制(悲觀鎖)是并發(fā)控制主要采用的技術(shù)手段账千。

  • 悲觀鎖:假定會發(fā)生并發(fā)沖突侥蒙,屏蔽一切可能違反數(shù)據(jù)完整性的操作

悲觀鎖是一種利用數(shù)據(jù)庫內(nèi)部機制提供的鎖的方式,也就是對更新的數(shù)據(jù)加鎖匀奏,這樣在并發(fā)期間一旦有一個事務(wù)持有了數(shù)據(jù)庫記錄的鎖鞭衩,其他的線程將不能再對數(shù)據(jù)進行更新了,這就是悲觀鎖的實現(xiàn)方式攒射。

MySQL InnoDB中使用悲觀鎖:

要使用悲觀鎖醋旦,我們必須關(guān)閉mysql數(shù)據(jù)庫的自動提交屬性恒水,因為MySQL默認使用autocommit模式会放,也就是說,當你執(zhí)行一個更新操作后钉凌,MySQL會立刻將結(jié)果進行提交咧最。 set autocommit=0;

//0.開始事務(wù)
begin;/begin work;/start transaction; (三者選一就可以)
//1.查詢出商品信息
select status from t_goods where id=1 for update;
//2.根據(jù)商品信息生成訂單
insert into t_orders (id,goods_id) values (null,1);
//3.修改商品status為2
update t_goods set status=2;
//4.提交事務(wù)
commit;/commit work;

上面的查詢語句中,我們使用了 select…for update 的方式,這樣就通過開啟排他鎖的方式實現(xiàn)了悲觀鎖矢沿。此時在t_goods表中滥搭,id為1的 那條數(shù)據(jù)就被我們鎖定了,其它的事務(wù)必須等本次事務(wù)提交之后才能執(zhí)行捣鲸。這樣我們可以保證當前的數(shù)據(jù)不會被其它事務(wù)修改瑟匆。

上面我們提到,使用 select…for update 會把數(shù)據(jù)給鎖住栽惶,不過我們需要注意一些鎖的級別愁溜,MySQL InnoDB默認行級鎖。行級鎖都是基于索引的外厂,如果一條SQL語句用不到索引是不會使用行級鎖的冕象,會使用表級鎖把整張表鎖住,這點需要注意汁蝶。

優(yōu)點與不足:

悲觀并發(fā)控制實際上是“先取鎖再訪問”的保守策略渐扮,為數(shù)據(jù)處理的安全提供了保證。但是在效率方面掖棉,處理加鎖的機制會讓數(shù)據(jù)庫產(chǎn)生額外的開銷墓律,還有增加產(chǎn)生死鎖的機會;另外幔亥,在只讀型事務(wù)處理中由于不會產(chǎn)生沖突只锻,也沒必要使用鎖,這樣做只能增加系統(tǒng)負載紫谷;還有會降低了并行性齐饮,一個事務(wù)如果鎖定了某行數(shù)據(jù),其他事務(wù)就必須等待該事務(wù)處理完才可以處理那行數(shù)

  • 樂觀鎖:假設(shè)不會發(fā)生并發(fā)沖突笤昨,只在提交操作時檢查是否違反數(shù)據(jù)完整性祖驱。

樂觀鎖是一種不會阻塞其他線程并發(fā)的控制,它不會使用數(shù)據(jù)庫的鎖進行實現(xiàn)瞒窒,它的設(shè)計里面由于不阻塞其他線程捺僻,所以并不會引起線程頻繁掛起和恢復(fù),這樣便能夠提高并發(fā)能力崇裁,所以也有人把它稱為非阻塞鎖匕坯。一般的實現(xiàn)樂觀鎖的方式就是記錄數(shù)據(jù)版本。

數(shù)據(jù)版本,為數(shù)據(jù)增加的一個版本標識拔稳。當讀取數(shù)據(jù)時葛峻,將版本標識的值一同讀出,數(shù)據(jù)每更新一次巴比,同時對版本標識進行更新禁漓。當我們提交更新的時候,判斷數(shù)據(jù)庫表對應(yīng)記錄的當前版本信息與第一次取出來的版本標識進行比對阳谍,如果數(shù)據(jù)庫表當前版本號與第一次取出來的版本標識值相等,則予以更新佣耐,否則認為是過期數(shù)據(jù)。

實現(xiàn)數(shù)據(jù)版本有兩種方式唧龄,第一種是使用版本號兼砖,第二種是使用時間戳。

使用版本號實現(xiàn)樂觀鎖:

使用版本號時既棺,可以在數(shù)據(jù)初始化時指定一個版本號掖鱼,每次對數(shù)據(jù)的更新操作都對版本號執(zhí)行+1操作。并判斷當前版本號是不是該數(shù)據(jù)的最新的版本號援制。

1.查詢出商品信息
select (status,status,version) from t_goods where id=#{id}
2.根據(jù)商品信息生成訂單
3.修改商品status為2
update t_goods 
set status=2,version=version+1
where id=#{id} and version=#{version};

優(yōu)點與不足:

樂觀并發(fā)控制相信事務(wù)之間的數(shù)據(jù)競爭(data race)的概率是比較小的戏挡,因此盡可能直接做下去,直到提交的時候才去鎖定晨仑,所以不會產(chǎn)生任何鎖和死鎖褐墅。但如果直接簡單這么做,還是有可能會遇到不可預(yù)期的結(jié)果洪己,例如兩個事務(wù)都讀取了數(shù)據(jù)庫的某一行妥凳,經(jīng)過修改以后寫回數(shù)據(jù)庫,這時就遇到了問題答捕。

參考文章:深入理解樂觀鎖與悲觀鎖


11)超鍵逝钥、候選鍵、主鍵拱镐、外鍵分別是什么艘款?

  • 超鍵:在關(guān)系中能唯一標識元組的屬性集稱為關(guān)系模式的超鍵。一個屬性可以為作為一個超鍵沃琅,多個屬性組合在一起也可以作為一個超鍵哗咆。超鍵包含候選鍵和主鍵。

  • 候選鍵(候選碼):是最小超鍵益眉,即沒有冗余元素的超鍵晌柬。

  • 主鍵(主碼):數(shù)據(jù)庫表中對儲存數(shù)據(jù)對象予以唯一和完整標識的數(shù)據(jù)列或?qū)傩缘慕M合。一個數(shù)據(jù)列只能有一個主鍵郭脂,且主鍵的取值不能缺失年碘,即不能為空值(Null)。

  • 外鍵:在一個表中存在的另一個表的主鍵稱此表的外鍵展鸡。

候選碼和主碼:

例子:郵寄地址(城市名屿衅,街道名,郵政編碼娱颊,單位名傲诵,收件人)

  • 它有兩個候選鍵:{城市名,街道名} 和 {街道名箱硕,郵政編碼}
  • 如果我選取{城市名拴竹,街道名}作為唯一標識實體的屬性,那么{城市名剧罩,街道名} 就是主碼(主鍵)

12)SQL 約束有哪幾種栓拜?

  • NOT NULL: 用于控制字段的內(nèi)容一定不能為空(NULL)。
  • UNIQUE: 控件字段內(nèi)容不能重復(fù)惠昔,一個表允許有多個 Unique 約束幕与。
  • PRIMARY KEY: 也是用于控件字段內(nèi)容不能重復(fù),但它在一個表只允許出現(xiàn)一個镇防。
  • FOREIGN KEY: 用于預(yù)防破壞表之間連接的動作啦鸣,也能防止非法數(shù)據(jù)插入外鍵列,因為它必須是它指向的那個表中的值之一来氧。
  • CHECK: 用于控制字段的值范圍诫给。

13)MySQL存儲引擎中的MyISAM和InnoDB區(qū)別詳解

在MySQL 5.5之前,MyISAM是mysql的默認數(shù)據(jù)庫引擎啦扬,其由早期的ISAM(Indexed Sequential Access Method:有索引的順序訪問方法)所改良中狂。雖然MyISAM性能極佳,但卻有一個顯著的缺點: 不支持事務(wù)處理扑毡。不過胃榕,MySQL也導(dǎo)入了另一種數(shù)據(jù)庫引擎InnoDB,以強化參考完整性與并發(fā)違規(guī)處理機制瞄摊,后來就逐漸取代MyISAM勋又。

InnoDB是MySQL的數(shù)據(jù)庫引擎之一,其由Innobase oy公司所開發(fā)换帜,2006年五月由甲骨文公司并購赐写。與傳統(tǒng)的ISAM、MyISAM相比膜赃,InnoDB的最大特色就是支持ACID兼容的事務(wù)功能挺邀,類似于PostgreSQL。目前InnoDB采用雙軌制授權(quán)跳座,一是GPL授權(quán)端铛,另一是專有軟件授權(quán)。具體地疲眷,MyISAM與InnoDB作為MySQL的兩大存儲引擎的差異主要包括:

  • 存儲結(jié)構(gòu):每個MyISAM在磁盤上存儲成三個文件:第一個文件的名字以表的名字開始禾蚕,擴展名指出文件類型。.frm文件存儲表定義狂丝,數(shù)據(jù)文件的擴展名為.MYD (MYData)换淆,索引文件的擴展名是.MYI (MYIndex)哗总。InnoDB所有的表都保存在同一個數(shù)據(jù)文件中(也可能是多個文件,或者是獨立的表空間文件)倍试,InnoDB表的大小只受限于操作系統(tǒng)文件的大小讯屈,一般為2GB。

  • 存儲空間:MyISAM可被壓縮县习,占據(jù)的存儲空間較小涮母,支持靜態(tài)表、動態(tài)表躁愿、壓縮表三種不同的存儲格式叛本。InnoDB需要更多的內(nèi)存和存儲,它會在主內(nèi)存中建立其專用的緩沖池用于高速緩沖數(shù)據(jù)和索引彤钟。

  • 可移植性来候、備份及恢復(fù):MyISAM的數(shù)據(jù)是以文件的形式存儲,所以在跨平臺的數(shù)據(jù)轉(zhuǎn)移中會很方便逸雹,同時在備份和恢復(fù)時也可單獨針對某個表進行操作吠勘。InnoDB免費的方案可以是拷貝數(shù)據(jù)文件、備份 binlog峡眶,或者用 mysqldump剧防,在數(shù)據(jù)量達到幾十G的時候就相對痛苦了。

  • 事務(wù)支持:MyISAM強調(diào)的是性能辫樱,每次查詢具有原子性峭拘,其執(zhí)行數(shù)度比InnoDB類型更快,但是不提供事務(wù)支持狮暑。InnoDB提供事務(wù)鸡挠、外鍵等高級數(shù)據(jù)庫功能,具有事務(wù)提交搬男、回滾和崩潰修復(fù)能力拣展。

  • AUTO_INCREMENT:在MyISAM中,可以和其他字段一起建立聯(lián)合索引缔逛。引擎的自動增長列必須是索引备埃,如果是組合索引,自動增長可以不是第一列褐奴,它可以根據(jù)前面幾列進行排序后遞增按脚。InnoDB中必須包含只有該字段的索引,并且引擎的自動增長列必須是索引敦冬,如果是組合索引也必須是組合索引的第一列辅搬。

  • 表鎖差異:MyISAM只支持表級鎖,用戶在操作MyISAM表時脖旱,select堪遂、update介蛉、delete和insert語句都會給表自動加鎖,如果加鎖以后的表滿足insert并發(fā)的情況下溶褪,可以在表的尾部插入新的數(shù)據(jù)币旧。InnoDB支持事務(wù)和行級鎖。行鎖大幅度提高了多用戶并發(fā)操作的新能竿滨,但是InnoDB的行鎖佳恬,只是在WHERE的主鍵是有效的捏境,非主鍵的WHERE都會鎖全表的于游。

  • 全文索引:MyISAM支持 FULLTEXT類型的全文索引;InnoDB不支持FULLTEXT類型的全文索引垫言,但是innodb可以使用sphinx插件支持全文索引贰剥,并且效果更好。

  • 表主鍵:MyISAM允許沒有任何索引和主鍵的表存在筷频,索引都是保存行的地址蚌成。對于InnoDB,如果沒有設(shè)定主鍵或者非空唯一索引凛捏,就會自動生成一個6字節(jié)的主鍵(用戶不可見)担忧,數(shù)據(jù)是主索引的一部分,附加索引保存的是主索引的值坯癣。

  • 表的具體行數(shù):MyISAM保存表的總行數(shù)瓶盛,select count() from table;會直接取出出該值;而InnoDB沒有保存表的總行數(shù)示罗,如果使用select count() from table惩猫;就會遍歷整個表,消耗相當大蚜点,但是在加了wehre條件后轧房,myisam和innodb處理的方式都一樣。

  • CURD操作:在MyISAM中绍绘,如果執(zhí)行大量的SELECT奶镶,MyISAM是更好的選擇。對于InnoDB陪拘,如果你的數(shù)據(jù)執(zhí)行大量的INSERT或UPDATE实辑,出于性能方面的考慮,應(yīng)該使用InnoDB表藻丢。DELETE從性能上InnoDB更優(yōu)剪撬,但DELETE FROM table時,InnoDB不會重新建立表悠反,而是一行一行的刪除残黑,在innodb上如果要清空保存有大量數(shù)據(jù)的表馍佑,最好使用truncate table這個命令。

  • 外鍵:MyISAM不支持外鍵梨水,而InnoDB支持外鍵拭荤。

通過上述的分析,基本上可以考慮使用InnoDB來替代MyISAM引擎了疫诽,原因是InnoDB自身很多良好的特點舅世,比如事務(wù)支持、存儲過程奇徒、視圖雏亚、行級鎖、外鍵等等摩钙。尤其在并發(fā)很多的情況下罢低,相信InnoDB的表現(xiàn)肯定要比MyISAM強很多。另外胖笛,必須需要注意的是网持,任何一種表都不是萬能的,合適的才是最好的长踊,才能最大的發(fā)揮MySQL的性能優(yōu)勢功舀。如果是不復(fù)雜的、非關(guān)鍵的Web應(yīng)用身弊,還是可以繼續(xù)考慮MyISAM的辟汰,這個具體情況具體考慮。


14)MyIASM和Innodb兩種引擎所使用的索引的數(shù)據(jù)結(jié)構(gòu)是什么佑刷?

答案:都是B+樹!

MyIASM引擎莉擒,B+樹的數(shù)據(jù)結(jié)構(gòu)中存儲的內(nèi)容實際上是實際數(shù)據(jù)的地址值。也就是說它的索引和實際數(shù)據(jù)是分開的瘫絮,只不過使用索引指向了實際數(shù)據(jù)涨冀。這種索引的模式被稱為非聚集索引。

Innodb引擎的索引的數(shù)據(jù)結(jié)構(gòu)也是B+樹麦萤,只不過數(shù)據(jù)結(jié)構(gòu)中存儲的都是實際的數(shù)據(jù)鹿鳖,這種索引有被稱為聚集索引。


15)varchar和char的區(qū)別

char是一種固定長度的類型壮莹,varchar是一種可變長度的類型翅帜,例如:

定義一個char[10]和varchar[10],如果存進去的是 'test'命满,那么char所占的長度依然為10涝滴,除了字符 'test' 外,后面跟六個空格,varchar就立馬把長度變?yōu)?了歼疮,取數(shù)據(jù)的時候杂抽,char類型的要用trim()去掉多余的空格,而varchar是不需要的

char的存取速度還是要比varchar要快得多韩脏,因為其長度固定缩麸,方便程序的存儲于查找

char也為此付出的是空間的代價,因為其長度固定赡矢,所以難免會有多余的空格占位符占據(jù)空間杭朱,可謂是以空間換取時間效率。

varchar是以空間效率為首位吹散。

char的存儲方式是:對英文字符(ASCII)占用1個字節(jié)弧械,對一個漢字占用兩個字節(jié)。

varchar的存儲方式是:對每個英文字符占用2個字節(jié)送浊,漢字也占用2個字節(jié)梦谜。
兩者的存儲數(shù)據(jù)都非unicode的字符數(shù)據(jù)丘跌。


16)主鍵袭景、自增主鍵、主鍵索引與唯一索引概念區(qū)別

  1. 主鍵:指字段 唯一闭树、不為空值 的列耸棒;

  2. 主鍵索引:指的就是主鍵,主鍵是索引的一種报辱,是唯一索引的特殊類型与殃。創(chuàng)建主鍵的時候,數(shù)據(jù)庫默認會為主鍵創(chuàng)建一個唯一索引碍现;

  3. 自增主鍵:字段類型為數(shù)字幅疼、自增、并且是主鍵昼接;

  4. 唯一索引:索引列的值必須唯一爽篷,但允許有空值。主鍵是唯一索引慢睡,這樣說沒錯逐工;但反過來說,唯一索引也是主鍵就錯誤了漂辐,因為唯一索引允許空值泪喊,主鍵不允許有空值,所以不能說唯一索引也是主鍵髓涯。


17)主鍵就是聚集索引嗎袒啼?主鍵和索引有什么區(qū)別?

主鍵是一種特殊的唯一性索引,其可以是聚集索引蚓再,也可以是非聚集索引灶泵。在SQLServer中,主鍵的創(chuàng)建必須依賴于索引对途,默認創(chuàng)建的是聚集索引赦邻,但也可以顯式指定為非聚集索引。InnoDB作為MySQL存儲引擎時实檀,默認按照主鍵進行聚集惶洲,如果沒有定義主鍵,InnoDB會試著使用唯一的非空索引來代替膳犹。如果沒有這種索引恬吕,InnoDB就會定義隱藏的主鍵然后在上面進行聚集。所以须床,對于聚集索引來說铐料,你創(chuàng)建主鍵的時候,自動就創(chuàng)建了主鍵的聚集索引豺旬。


18)實踐中如何優(yōu)化MySQL

實踐中钠惩,MySQL的優(yōu)化主要涉及SQL語句及索引的優(yōu)化、數(shù)據(jù)表結(jié)構(gòu)的優(yōu)化族阅、系統(tǒng)配置的優(yōu)化和硬件的優(yōu)化四個方面篓跛,如下圖所示:

⑴ SQL語句優(yōu)化:

SQL語句的優(yōu)化主要包括三個問題,即如何發(fā)現(xiàn)有問題的SQL坦刀、如何分析SQL的執(zhí)行計劃以及如何優(yōu)化SQL愧沟,下面將逐一解釋。

① 怎么發(fā)現(xiàn)有問題的SQL?(通過MySQL慢查詢?nèi)罩緦τ行蕟栴}的SQL進行監(jiān)控)

MySQL的慢查詢?nèi)罩臼荕ySQL提供的一種日志記錄鲤遥,它用來記錄在MySQL中響應(yīng)時間超過閥值的語句沐寺,具體指運行時間超過long_query_time值的SQL,則會被記錄到慢查詢?nèi)罩局懈悄巍ong_query_time的默認值為10混坞,意思是運行10s以上的語句。慢查詢?nèi)罩镜南嚓P(guān)參數(shù)如下所示:

通過MySQL的慢查詢?nèi)罩静防剩覀兛梢圆樵兂鰣?zhí)行的次數(shù)多占用的時間長的SQL拔第、可以通過pt_query_disgest(一種mysql慢日志分析工具)分析Rows examine(MySQL執(zhí)行器需要檢查的行數(shù))項去找出IO大的SQL以及發(fā)現(xiàn)未命中索引的SQL,對于這些SQL场钉,都是我們優(yōu)化的對象蚊俺。

② 通過explain查詢和分析SQL的執(zhí)行計劃:

使用 EXPLAIN 關(guān)鍵字可以知道MySQL是如何處理你的SQL語句的,以便分析查詢語句或是表結(jié)構(gòu)的性能瓶頸逛万。通過explain命令可以得到表的讀取順序泳猬、數(shù)據(jù)讀取操作的操作類型批钠、哪些索引可以使用、哪些索引被實際使用得封、表之間的引用以及每張表有多少行被優(yōu)化器查詢等問題埋心。當擴展列extra出現(xiàn)Using filesort和Using temporay,則往往表示SQL需要優(yōu)化了忙上。

③ SQL語句的優(yōu)化:

⒈優(yōu)化insert語句:一次插入多值拷呆;

⒉應(yīng)盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描疫粥;

⒊應(yīng)盡量避免在 where 子句中對字段進行null值判斷茬斧,否則將導(dǎo)致引擎放棄使用索引而進行全表掃描;

⒋優(yōu)化嵌套查詢:子查詢可以被更有效率的連接(Join)替代梗逮;

⒌很多時候用 exists 代替 in 是一個好的選擇项秉。

⒍選擇最有效率的表名順序:數(shù)據(jù)庫的解析器按照從右到左的順序處理FROM子句中的表名,F(xiàn)ROM子句中寫在最后的表將被最先處理

在FROM子句中包含多個表的情況下:

  • 如果三個表是完全無關(guān)系的話慷彤,將記錄和列名最少的表娄蔼,寫在最后,然后依次類推
  • 也就是說:選擇記錄條數(shù)最少的表放在最后

如果有3個以上的表連接查詢:

  • 如果三個表是有關(guān)系的話底哗,將引用最多的表岁诉,放在最后,然后依次類推艘虎。
  • 也就是說:被其他表所引用的表放在最后

⒎用IN代替OR:

select * from emp where sal = 1500 or sal = 3000 or sal = 800;
select * from emp where sal in (1500,3000,800);

⒏SELECT子句中避免使用*號:

我們最開始接觸 SQL 的時候唉侄,“*” 號是可以獲取表中全部的字段數(shù)據(jù)的咒吐,但是它要通過查詢數(shù)據(jù)字典完成野建,這意味著將消耗更多的時間,而且使用 “*” 號寫出來的 SQL 語句也不夠直觀恬叹。


⑵ 索引優(yōu)化:

建議在經(jīng)常作查詢選擇的字段候生、經(jīng)常作表連接的字段以及經(jīng)常出現(xiàn)在 order by、group by绽昼、distinct 后面的字段中建立索引唯鸭。但必須注意以下幾種可能會引起索引失效的情形:

  • 以 “%(表示任意0個或多個字符)” 開頭的 LIKE 語句,模糊匹配硅确;

  • OR語句前后沒有同時使用索引目溉;

  • 數(shù)據(jù)類型出現(xiàn)隱式轉(zhuǎn)化(如varchar不加單引號的話可能會自動轉(zhuǎn)換為int型);

  • 對于多列索引菱农,必須滿足最左匹配原則(eg,多列索引col1缭付、col2和col3,則 索引生效的情形包括col1或col1循未,col2或col1陷猫,col2,col3)。


⑶ 數(shù)據(jù)庫表結(jié)構(gòu)的優(yōu)化:

① 選擇合適數(shù)據(jù)類型:

  • 使用較小的數(shù)據(jù)類型解決問題绣檬;
  • 使用簡單的數(shù)據(jù)類型(mysql處理int要比varchar容易)足陨;
  • 盡可能的使用not null 定義字段;
  • 盡量避免使用text類型娇未,非用不可時最好考慮分表墨缘;

② 表的范式的優(yōu)化:

一般情況下,表的設(shè)計應(yīng)該遵循三大范式零抬。

③ 表的垂直拆分:

把含有多個列的表拆分成多個表飒房,解決表寬度問題,具體包括以下幾種拆分手段:

  • 把不常用的字段單獨放在同一個表中媚值;
  • 把大字段獨立放入一個表中狠毯;
  • 把經(jīng)常使用的字段放在一起;

這樣做的好處是非常明顯的褥芒,具體包括:拆分后業(yè)務(wù)清晰嚼松,拆分規(guī)則明確、系統(tǒng)之間整合或擴展容易锰扶、數(shù)據(jù)維護簡單

④ 表的水平拆分:

表的水平拆分用于解決數(shù)據(jù)表中數(shù)據(jù)過大的問題献酗,水平拆分每一個表的結(jié)構(gòu)都是完全一致的。一般地坷牛,將數(shù)據(jù)平分到N張表中的常用方法包括以下兩種:

  • 對ID進行hash運算罕偎,如果要拆分成5個表,mod(id,5)取出0~4個值京闰;
  • 針對不同的hashID將數(shù)據(jù)存入不同的表中颜及;

表的水平拆分會帶來一些問題和挑戰(zhàn),包括跨分區(qū)表的數(shù)據(jù)查詢蹂楣、統(tǒng)計及后臺報表的操作等問題俏站,但也帶來了一些切實的好處:

  • 表分割后可以降低在查詢時需要讀的數(shù)據(jù)和索引的頁數(shù),同時也降低了索引的層數(shù)痊土,提高查詢速度肄扎;
  • 表中的數(shù)據(jù)本來就有獨立性,例如表中分別記錄各個地區(qū)的數(shù)據(jù)或不同時期的數(shù)據(jù)赁酝,特別是有些數(shù)據(jù)常用犯祠,而另外一些數(shù)據(jù)不常用。
  • 需要把數(shù)據(jù)存放到多個數(shù)據(jù)庫中酌呆,提高系統(tǒng)的總體可用性(分庫衡载,雞蛋不能放在同一個籃子里)。

⑷ 系統(tǒng)配置的優(yōu)化:

  • 操作系統(tǒng)配置的優(yōu)化:增加TCP支持的隊列數(shù)

  • mysql配置文件優(yōu)化:Innodb緩存池設(shè)置(innodb_buffer_pool_size肪笋,推薦總內(nèi)存的75%)和緩存池的個數(shù)(innodb_buffer_pool_instances)


⑸ 硬件的優(yōu)化:

  • CPU:核心數(shù)多并且主頻高的
  • 內(nèi)存:增大內(nèi)存
  • 磁盤配置和選擇:磁盤性能

歡迎轉(zhuǎn)載月劈,轉(zhuǎn)載請注明出處度迂!
簡書ID:@我沒有三顆心臟
github:wmyskxz
歡迎關(guān)注公眾微信號:wmyskxz_javaweb
分享自己的Java Web學習之路以及各種Java學習資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市猜揪,隨后出現(xiàn)的幾起案子惭墓,更是在濱河造成了極大的恐慌,老刑警劉巖而姐,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腊凶,死亡現(xiàn)場離奇詭異,居然都是意外死亡拴念,警方通過查閱死者的電腦和手機钧萍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來政鼠,“玉大人风瘦,你說我怎么就攤上這事」悖” “怎么了万搔?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長官帘。 經(jīng)常有香客問我瞬雹,道長,這世上最難降的妖魔是什么刽虹? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任酗捌,我火速辦了婚禮,結(jié)果婚禮上涌哲,老公的妹妹穿的比我還像新娘胖缤。我一直安慰自己,他們只是感情好膛虫,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布草姻。 她就那樣靜靜地躺著,像睡著了一般稍刀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上敞曹,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天账月,我揣著相機與錄音,去河邊找鬼澳迫。 笑死局齿,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的橄登。 我是一名探鬼主播抓歼,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼讥此,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谣妻?” 一聲冷哼從身側(cè)響起萄喳,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蹋半,沒想到半個月后他巨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡减江,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年染突,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辈灼。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡份企,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出巡莹,到底是詐尸還是另有隱情薪棒,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布榕莺,位于F島的核電站俐芯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏钉鸯。R本人自食惡果不足惜吧史,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一阴颖、第九天 我趴在偏房一處隱蔽的房頂上張望杈湾。 院中可真熱鬧衷旅,春花似錦怖糊、人聲如沸枪汪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棘脐。三九已至捕儒,卻和暖如春冰啃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背刘莹。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工阎毅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人点弯。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓扇调,卻偏偏與公主長得像,于是被迫代替她去往敵國和親抢肛。 傳聞我的和親對象是個殘疾皇子狼钮,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容