InnoDB在RR級別下能否防止幻讀

本文討論大部分基于下表進(jìn)行:

class_teacher table

開始討論之前舒裤,先讓我們了解一些基本概念淘这。

一掉伏、并發(fā)事務(wù)帶來的問題

在典型的應(yīng)用程序中,經(jīng)常會產(chǎn)生多個事務(wù)并發(fā)運行两曼。雖然并發(fā)事務(wù)能夠極大的提升系統(tǒng)的可用性皂甘,但是也帶來了如下問題:

臟讀(Dirty Read)

事務(wù)T1修改了一行數(shù)據(jù)Row,事務(wù)T2在T1未提交前讀到了該行數(shù)據(jù)(Row)并使用該數(shù)據(jù)進(jìn)行業(yè)務(wù)操作悼凑。

丟失修改(Lost To Modify)

事務(wù)T1讀取了一行數(shù)據(jù)Row偿枕,事務(wù)T2在隨后也訪問了該行數(shù)據(jù)璧瞬,隨后事務(wù)T1對Row進(jìn)行了更新,事務(wù)T2也隨后對Row進(jìn)行更新渐夸,事務(wù)T2對Row的更新導(dǎo)致了事務(wù)T1對Row的更新丟失嗤锉。

不可重復(fù)讀(Non-repeatable Read)

事務(wù)T1讀取了一行數(shù)據(jù)Row,事務(wù)T2在T1讀取Row后對Row數(shù)據(jù)進(jìn)行了更新墓塌,T1再次讀取行Row瘟忱,發(fā)現(xiàn)與第一次讀取數(shù)據(jù)不一致,即在同一事務(wù)內(nèi)兩次執(zhí)行同一查詢得到的結(jié)果不一致苫幢。

幻讀(Phantom Read)

事務(wù)T1讀取了一個結(jié)果集ResultSet1访诱,事務(wù)T2在T1讀取ResultSet1后新增了一行數(shù)據(jù)Row,剛好這個事務(wù)T2新插入的這條數(shù)據(jù)滿足T1的抓取規(guī)則韩肝,導(dǎo)致事務(wù)T1再次讀取數(shù)據(jù)時触菜,得到了比ResultSet1更多的結(jié)果集ResultSet2。

關(guān)于不可重復(fù)讀和幻讀的區(qū)別

從上述定義看不可重復(fù)讀和幻讀伞梯,都是在一個事務(wù)中多次讀取得到了不同的數(shù)據(jù)結(jié)果玫氢。不可重復(fù)讀的重點在于修改,而幻讀的重點在于新增或刪除谜诫。

二漾峡、SQL隔離級別

ANSI SQL STANDARD定義了4類隔離級別(READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE),不同版本的數(shù)據(jù)庫分別實現(xiàn)了上述隔離級別的一個或者多個喻旷,這些不同的事務(wù)隔離級別用來限定事務(wù)內(nèi)外的哪些改變是可見的(指對其他事務(wù))生逸。一般說來,低級別的隔離級別一般支持更高的并發(fā)處理且预,并擁有更低的系統(tǒng)開銷送丰。ANSI SQL STANDARD定義的4類事務(wù)隔離級別如下:

Read Uncommitted(讀未提交)

允許讀取其他事務(wù)未提交的數(shù)據(jù)瘪菌,在該隔離級別下名党,所有事務(wù)都可以看到其他未提交事務(wù)的執(zhí)行結(jié)果帝际。由于本隔離級別很容易讀取到其他事務(wù)未提交的臟數(shù)據(jù),所以一般很少用于實際應(yīng)用涮拗。

Read Committed(讀已提交)

只能讀取其他事務(wù)已提交的更改乾戏。Oracle、SqlServer等大部分?jǐn)?shù)據(jù)庫的默認(rèn)隔離級別三热。

Repeatable Read(可重讀)

同一事務(wù)多次讀取數(shù)據(jù)時鼓择,會看到同樣的數(shù)據(jù)行。這是Mysql默認(rèn)的隔離級別就漾。ANSI SQL STANDARD對于可重讀隔離級別呐能,是允許出現(xiàn)幻讀的,而InnoDB存儲引擎通過多版本并發(fā)控制(MVCC抑堡,Multiversion Concurrency Control)機(jī)制解決了該問題摆出。但是對于InnoDB在RR隔離級別下是否完全解決幻讀朗徊,尚有爭議,我們將在下文進(jìn)行討論懊蒸。

Serializable(可串行化)

強(qiáng)制事務(wù)排序荣倾,事務(wù)串行化執(zhí)行。讀數(shù)據(jù)會加上共享鎖骑丸,讀寫會相互阻塞,在這個級別下妒貌,可能會產(chǎn)生大量的超時現(xiàn)象和鎖競爭通危。

下圖是ANSI SQL STANDARD對于各種隔離級別下允許出現(xiàn)的并發(fā)事務(wù)問題的規(guī)定:

SQL-transaction isolation levels and the three phenomena

三、InnoDB MVCC理解

ANSI SQL STANDARD定義了4類隔離級別灌曙,隨著隔離級別的提升菊碟,并發(fā)事務(wù)產(chǎn)生數(shù)據(jù)不一致性的問題就會大大越低,但是并發(fā)處理能力也會大大降低在刺,而不同的隔離級別逆害,往往都是通過鎖機(jī)制來解決并發(fā)事務(wù)產(chǎn)生的各種問題。數(shù)據(jù)的鎖定分為兩種方法蚣驼,一種叫悲觀鎖魄幕,另外一種叫做樂觀鎖。絕大部分商業(yè)數(shù)據(jù)庫(MySQL颖杏、Oracle等)為了性能考慮纯陨,都是使用了以樂觀鎖為理論基礎(chǔ)的MVCC(Multi-Version Concurrency Control 多版本并發(fā)控制)來解決并發(fā)事務(wù)帶來的數(shù)據(jù)訪問問題。

悲觀鎖

數(shù)據(jù)對外界(包括本系統(tǒng)當(dāng)前的其他事務(wù)留储,以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度翼抠,在整個的數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)获讳。悲觀鎖的實現(xiàn)阴颖,往往依靠數(shù)據(jù)庫提供的鎖機(jī)制(也只有數(shù)據(jù)庫層提供的鎖機(jī)制才能真正保證數(shù)據(jù)訪問的排他性,否則丐膝,即使在本系統(tǒng)中實現(xiàn)了加鎖機(jī)制量愧,也無法保證外部系統(tǒng)不會修改數(shù)據(jù))。在悲觀鎖的情況下尤误,為了保證事務(wù)的隔離性侠畔,就需要一致性鎖定讀。讀取數(shù)據(jù)時給加鎖损晤,其它事務(wù)無法修改這些數(shù)據(jù)软棺。修改刪除數(shù)據(jù)時也要加鎖,其它事務(wù)無法讀取這些數(shù)據(jù)尤勋。悲觀鎖大多數(shù)情況下依靠數(shù)據(jù)庫的鎖機(jī)制實現(xiàn)喘落,以保證操作最大程度的獨占性茵宪。但隨之而來的就是數(shù)據(jù)庫性能的大量開銷(特別是長事務(wù))。

樂觀鎖

大多是基于數(shù)據(jù)版本( Version )記錄機(jī)制實現(xiàn)瘦棋。何謂數(shù)據(jù)版本稀火?即為數(shù)據(jù)增加一個版本標(biāo)識,在基于數(shù)據(jù)庫表的版本解決方案中赌朋,一般是通過為數(shù)據(jù)庫表增加一個 “version” 字段來實現(xiàn)凰狞。讀取出數(shù)據(jù)時,將此版本號一同讀出沛慢,之后更新時赡若,對此版本號加一。此時团甲,將提交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫表對應(yīng)記錄的當(dāng)前版本信息進(jìn)行比對逾冬,如果提交的數(shù)據(jù)版本號大于數(shù)據(jù)庫表當(dāng)前版本號,則予以更新躺苦,否則認(rèn)為是過期數(shù)據(jù)身腻。MVCC的實現(xiàn)沒有固定的規(guī)范,每個數(shù)據(jù)庫都會有不同的實現(xiàn)方式匹厘。

MVCC在MySQL的InnoDB實現(xiàn)

在InnoDB中嘀趟,會在每行數(shù)據(jù)后添加兩個額外的隱藏的值來實現(xiàn)MVCC,這兩個值一個記錄這行數(shù)據(jù)何時被創(chuàng)建集乔,另外一個記錄這行數(shù)據(jù)何時過期(或者被刪除)去件。 在實際操作中,存儲的并不是時間扰路,而是事務(wù)的版本號尤溜,每開啟一個新事務(wù),事務(wù)的版本號就會遞增汗唱。 在可重讀Repeatable Reads事務(wù)隔離級別下:

SELECT時宫莱,讀取創(chuàng)建版本號<=當(dāng)前事務(wù)版本號,刪除版本號為空或>當(dāng)前事務(wù)版本號哩罪。

INSERT時授霸,保存當(dāng)前事務(wù)版本號為行的創(chuàng)建版本號

DELETE時,保存當(dāng)前事務(wù)版本號為行的刪除版本號

UPDATE時际插,插入一條新紀(jì)錄碘耳,保存當(dāng)前事務(wù)版本號為行創(chuàng)建版本號,同時保存當(dāng)前事務(wù)版本號到原來刪除的行

通過MVCC框弛,雖然每行記錄都需要額外的存儲空間辛辨,更多的行檢查工作以及一些額外的維護(hù)工作,但可以減少鎖的使用,大多數(shù)讀操作都不用加鎖斗搞,讀數(shù)據(jù)操作很簡單指攒,性能很好,并且也能保證只會讀取到符合標(biāo)準(zhǔn)的行僻焚,也只鎖住必要行允悦。

四、InnoDB RR防止幻讀初探

Repeatable Read是nnoDB的默認(rèn)隔離級別虑啤,意味著在RR隔離級別下隙弛,一個事務(wù)在多個實例并發(fā)讀取數(shù)據(jù)時,會看到同樣的數(shù)據(jù)行狞山。關(guān)于RC(讀已提交)和RR(可重讀)的區(qū)別驶鹉,我們用如下兩圖進(jìn)行一個說明:

Read_Committed

可以看到,在RC隔離級別下铣墨,事務(wù)A前后兩次執(zhí)行同一查詢語句得到了不同的結(jié)果,這就很可能帶來一些問題办绝。下面我們看看在RR隔離級別下的查詢結(jié)果伊约,如下圖所示:

Repeatable_Read

從上圖可以看到,在RR隔離級別下孕蝉,事務(wù)A前后兩次執(zhí)行同一查詢語句得到的結(jié)果相同屡律,參閱并發(fā)事務(wù)帶來的問題,我們發(fā)現(xiàn)降淮,InnoDB在RR隔離級別下超埋,能夠解決并發(fā)事務(wù)帶來的臟讀、不可重復(fù)讀佳鳖、幻讀霍殴,因此很多人說InnoDB在RR級別下能夠防止幻讀(后文將展示出現(xiàn)幻讀的情況)。我們從MVCC的角度系吩,再來看看上述查詢:

RR_MVCC

五来庭、InnoDB RR無法防止幻讀初探

從上一小節(jié)中看到,InnoDB在RR隔離級別下穿挨,確實未讀取到其他并發(fā)事務(wù)的數(shù)據(jù)寫入和更新月弛,我們可能會認(rèn)為InnoDB的RR確實防止住了幻讀,但經(jīng)過測試科盛,發(fā)現(xiàn)了如下問題:

RR _Phantom Read

可以看到帽衙,session1在執(zhí)行一次update操作后,讀取到了session2中insert的數(shù)據(jù)贞绵,發(fā)生了幻讀厉萝,因此有人說InnoDB在RR隔離級別下無法防止幻讀。但是從ANSI SQL STANDARD定義的4類隔離級別可以看到,在RR隔離級別下冀泻,是允許出現(xiàn)幻讀的常侣,所以InnoDB在RR隔離級別下出現(xiàn)幻讀并不屬于BUG。

六弹渔、InnoDB在RR隔離級別下的當(dāng)前讀胳施、快照讀、行鎖肢专、Next-Key鎖

從上文內(nèi)容可以看到舞肆,InnoDB在RR隔離級別時,在某些情況下能夠防止幻讀博杖,但是在某些情況下會出現(xiàn)幻讀椿胯,為什么會出現(xiàn)這種情況?先讓我們了解如下幾個概念:

快照讀和當(dāng)前讀

事務(wù)的隔離級別其實都是對于讀數(shù)據(jù)的定義剃根,但是MySQL中的讀哩盲,和事務(wù)隔離級別中的讀,是不一樣的狈醉。在RR級別中廉油,通過MVCC機(jī)制,雖然讓數(shù)據(jù)變得可重復(fù)讀苗傅,但我們讀到的數(shù)據(jù)可能是歷史數(shù)據(jù)抒线,是不及時的數(shù)據(jù),不是數(shù)據(jù)庫當(dāng)前的數(shù)據(jù)渣慕!這在一些對于數(shù)據(jù)的時效特別敏感的業(yè)務(wù)中嘶炭,就很可能出問題。對于這種讀取歷史數(shù)據(jù)的方式逊桦,我們叫它快照讀 (snapshot read)眨猎,而讀取數(shù)據(jù)庫當(dāng)前版本數(shù)據(jù)的方式,叫當(dāng)前讀 (current read)卫袒。很顯然宵呛,在MVCC中:

快照讀:就是select

select * from table ….;

當(dāng)前讀:特殊的讀操作,插入/更新/刪除操作夕凝,屬于當(dāng)前讀宝穗,處理的都是當(dāng)前的數(shù)據(jù),需要加鎖码秉。

select * from table where ? lock in share mode;

select * from table where ? for update;

insert;

update ;

delete;

事務(wù)的隔離級別實際上都是定義了當(dāng)前讀的級別逮矛,MySQL為了減少鎖處理(包括等待其它鎖)的時間,提升并發(fā)能力转砖,引入了快照讀的概念须鼎,使得select不用加鎖鲸伴。而update、insert這些“當(dāng)前讀”晋控,就需要另外的模塊來解決了汞窗。

行鎖

MySQL中鎖的種類很多,有常見的表鎖和行鎖赡译,也有新加入的Metadata Lock等等仲吏。表鎖是對一整張表加鎖,雖然可分為讀鎖和寫鎖蝌焚,但畢竟是鎖住整張表裹唆,會導(dǎo)致并發(fā)能力下降,一般是做ddl處理時使用只洒。行鎖則是鎖住數(shù)據(jù)行许帐,這種加鎖方法比較復(fù)雜,但是由于只鎖住有限的數(shù)據(jù)毕谴,對于其它數(shù)據(jù)不加限制成畦,所以并發(fā)能力強(qiáng),MySQL一般都是用行鎖來處理并發(fā)事務(wù)涝开。

在RR級別下羡鸥,快照讀取都是不加鎖的(在Serializable隔離級別下,快照讀也會加鎖忠寻,此時不再區(qū)分快照讀和當(dāng)前讀,所有讀操作均為當(dāng)前讀)存和,但是當(dāng)前讀是需要加鎖的奕剃。通過如下實例,我們來看看行鎖(RR隔離級別):

X-Lock

事務(wù)A給teacher_id為1的數(shù)據(jù)行加鎖捐腿,如果一直不釋放纵朋,那么事務(wù)B將會一直等待(拿不到行鎖),直到超時茄袖。

此時需要注意一點操软,teacher_id是有索引的,如果我們將teacher_id更換為無索引的class_name宪祥,那么MySQL將會給整張表的數(shù)據(jù)行都加上行鎖聂薪。這聽起來有點不可思議,但是在SQL運行過程中蝗羊,如果一個條件無法通過索引快速過濾藏澳,存儲引擎層面就會將所有記錄加鎖后返回,再由MySQL Server層進(jìn)行過濾耀找。

但在實際使用過程當(dāng)中翔悠,MySQL做了一些改進(jìn),在MySQL Server過濾條件,發(fā)現(xiàn)不滿足后蓄愁,會調(diào)用unlock_row方法双炕,把不滿足條件的記錄釋放鎖 (違背了二段鎖協(xié)議的約束)。這樣做撮抓,保證了最后只會持有滿足條件記錄上的鎖妇斤,但是每條記錄的加鎖操作還是不能省略的≌凸觯可見即使是MySQL趟济,為了效率也是會違反規(guī)范的。所以對一個數(shù)據(jù)量很大的表做批量修改的時候咽笼,如果無法使用相應(yīng)的索引顷编,MySQL Server過濾數(shù)據(jù)的的時候特別慢,就會出現(xiàn)雖然沒有修改某些行的數(shù)據(jù)剑刑,但是它們還是被鎖住了的現(xiàn)象媳纬。

Next-Key 鎖

事務(wù)的隔離級別中雖然只定義了讀數(shù)據(jù)的要求,實際上這也可以說是寫數(shù)據(jù)的要求施掏,為了解決當(dāng)前讀中的幻讀問題钮惠,MySQL事務(wù)使用了Next-Key鎖。Next-Key鎖是行鎖和GAP(間隙鎖)的合并七芭。行鎖可以防止不同事務(wù)版本的數(shù)據(jù)修改提交時造成數(shù)據(jù)沖突的情況素挽。但如何避免別的事務(wù)插入數(shù)據(jù)就成了問題。為了理解GAP(間隙鎖)狸驳,我們看下RR和RC級別的對比:

RC級別:


Next-Key_RC

RR級別:


Next_Key_RR

通過RC和RR的對比我們發(fā)現(xiàn)预明,RC隔離級別下,發(fā)生了當(dāng)前讀的幻讀耙箍,事務(wù)A在update之后撰糠,將事務(wù)B insert的數(shù)據(jù)一并查詢了出來,并且是還未被事務(wù)A的update語句修改的數(shù)據(jù)(RC隔離級別下辩昆,當(dāng)前讀仍然會有可能發(fā)生幻讀現(xiàn)象)阅酪。

而RR隔離級別下,事務(wù)A在update之后汁针,事務(wù)B無法insert术辐,事務(wù)A在update前后讀的數(shù)據(jù)保持一致,避免了幻讀施无。而使事務(wù)B無法insert的這個鎖术吗,就是GAP(間隙鎖)。在class_teacher這張表中帆精,teacher_id是個索引较屿,那么它就會維護(hù)一套B+樹的數(shù)據(jù)關(guān)系隧魄,為了簡化,我們用鏈表結(jié)構(gòu)來表達(dá)(實際上是個樹形結(jié)構(gòu)隘蝎,但原理相同)

B+-GAP

如圖所示购啄,InnoDB使用的是聚集索引,teacher_id身為二級索引嘱么,就要維護(hù)一個索引字段和主鍵id的樹狀結(jié)構(gòu)(這里用鏈表形式表現(xiàn))狮含,并保持順序排列。InnoDB將這段數(shù)據(jù)分成幾個個區(qū)間

(negative infinity, 5],

(5,30],

(30,positive infinity)曼振;

update class_teacher set class_name=‘初三四班’ where teacher_id=30;不僅用行鎖几迄,鎖住了相應(yīng)的數(shù)據(jù)行;同時也在兩邊的區(qū)間冰评,(5,30]和(30映胁,positive infinity),都加入了GAP(間隙鎖)甲雅。這樣事務(wù)B就無法在這個兩個區(qū)間insert進(jìn)新數(shù)據(jù)解孙。受限于這種實現(xiàn)方式,InnoDB很多時候會鎖住不需要鎖的區(qū)間抛人。如下所示:

Next-Key Lock Other

teacher_id=20是在(5弛姜,30]區(qū)間,即使沒有修改任何數(shù)據(jù)妖枚,InnoDB也會在這個區(qū)間加GAP(間隙鎖)廷臼,而其它區(qū)間不會影響,事務(wù)C正常插入绝页。

如果使用的是沒有索引的字段中剩,比如update class_teacher set teacher_id=7 where class_name=‘初三八班(即使沒有匹配到任何數(shù)據(jù))’,那么會給全表加入GAP(間隙鎖)。同時抒寂,它不能像上文中行鎖一樣經(jīng)過MySQL Server過濾自動解除不滿足條件的鎖,因為沒有索引掠剑,則這些字段也就沒有排序屈芜,也就沒有區(qū)間。除非該事務(wù)提交朴译,否則其它事務(wù)無法插入任何數(shù)據(jù)井佑。

行鎖防止別的事務(wù)修改或刪除,GAP鎖防止別的事務(wù)新增眠寿,行鎖和GAP鎖結(jié)合形成的的Next-Key鎖共同解決了RR級別在寫數(shù)據(jù)(當(dāng)前讀)時的幻讀問題躬翁。

GAP(間隙鎖)RR隔離級別的當(dāng)前讀加鎖分析

WHERE字段無索引

無索引的條件字段的當(dāng)前讀不僅會把每條記錄都加上行(X)鎖,還會加上GAP鎖盯拱。再次強(qiáng)調(diào)盒发,當(dāng)前讀或者插入/更新/刪除操作需要加上索引例嘱。

WHERE字段存在普通索引

普通索引的條件字段的當(dāng)前讀會把符合檢索條件的每條記錄加上行(X)鎖,還會在索引兩邊的區(qū)間加上對應(yīng)的GAP鎖宁舰。

WHERE字段存在唯一索引

唯一索引的條件字段的當(dāng)前讀只會為符合檢索條件的那條記錄加上行(X)鎖拼卵,不會加上GAP鎖。

七蛮艰、InnoDB在RR級別下能否防止幻讀

經(jīng)過上面的描述腋腮,我們可以得出如下結(jié)論:

在RR隔離級別下,只進(jìn)行快照讀(不進(jìn)行當(dāng)前讀)壤蚜,是能夠防止幻讀的即寡。但是可能會出現(xiàn)P4(Lost To Modify 丟失修改)現(xiàn)象,而針對MVCC實現(xiàn)定義的Snapshot Isolation袜刷,其實是不允許P4現(xiàn)象的聪富,出現(xiàn)更新沖突,遵循FIRST-COMMITER-WIN的原則水泉,其它事務(wù)需要回滾善涨。

在RR隔離級別下,只進(jìn)行當(dāng)前讀(SELECT使用排它鎖(不使用共享鎖))草则,也能夠防止幻讀(Next-Key Lock解決幻讀問題)钢拧,并且不會出現(xiàn)P4(Lost To Modify 丟失修改)現(xiàn)象。

在RR隔離級別下炕横,如果先快照讀源内、后進(jìn)行當(dāng)前讀(指的是后續(xù)進(jìn)行UPDATE、DELETE份殿,先快照讀和后面使用鎖定讀饶さ觥(如FOR UPDATE)兩次結(jié)果不一樣,不在討論范圍中卿嘲,個人認(rèn)為此種情況不能用來證明InnoDB不能防止幻讀)颂斜,是無法防止幻讀。MySQL官方對此種情況的答復(fù)是:如果一個事務(wù)確實更新或者刪除了其他事務(wù)提交的行拾枣,那么這些更改對當(dāng)前事務(wù)是可見的(If a transaction does update or delete rows committed by a different transaction, those changes do become visible to the current transaction)沃疮。我們從官方的答復(fù)中得知,如果先進(jìn)行快照讀梅肤,然后在快照讀中執(zhí)行更新或者刪除司蔬,而其他事務(wù)在快照讀之后(本事務(wù)執(zhí)行更新前)對當(dāng)前事務(wù)要更新的行也進(jìn)行了更新,那么其他事務(wù)的對滿足條件的行的更新對當(dāng)前事務(wù)是可見的姨蝴。

ANSI SQL STANDARD對于可重讀隔離級別俊啼,是允許出現(xiàn)幻讀的,但是MySQL可以通過Next-Key Lock來解決幻讀問題左医,當(dāng)然授帕,如果只進(jìn)行純快照讀也能避免幻讀同木。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者豪墅。
  • 序言:七十年代末泉手,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子偶器,更是在濱河造成了極大的恐慌斩萌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屏轰,死亡現(xiàn)場離奇詭異颊郎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)霎苗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門姆吭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人唁盏,你說我怎么就攤上這事内狸。” “怎么了厘擂?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵昆淡,是天一觀的道長。 經(jīng)常有香客問我刽严,道長昂灵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任舞萄,我火速辦了婚禮眨补,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘倒脓。我一直安慰自己撑螺,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布崎弃。 她就那樣靜靜地躺著甘晤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吊履。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天调鬓,我揣著相機(jī)與錄音艇炎,去河邊找鬼。 笑死腾窝,一個胖子當(dāng)著我的面吹牛缀踪,可吹牛的內(nèi)容都是我干的居砖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼驴娃,長吁一口氣:“原來是場噩夢啊……” “哼奏候!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起唇敞,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蔗草,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后疆柔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咒精,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年旷档,在試婚紗的時候發(fā)現(xiàn)自己被綠了模叙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡鞋屈,死狀恐怖范咨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情厂庇,我是刑警寧澤渠啊,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站宋列,受9級特大地震影響昭抒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜炼杖,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一灭返、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧坤邪,春花似錦熙含、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至黔衡,卻和暖如春蚓聘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盟劫。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工夜牡, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人侣签。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓塘装,卻偏偏與公主長得像急迂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蹦肴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355

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