深入理解InnoDB -- 架構(gòu)篇

最近看了《MySQL技術(shù)內(nèi)幕InnoDB存儲(chǔ)引擎》一書,受益良多,對(duì)Mysql InnoDB有了進(jìn)一步的了解。于是根據(jù)自己理解和搜集的資料,寫了一系列深入InnoDB的文章,其中不少知識(shí)來著《MySQL技術(shù)內(nèi)幕InnoDB存儲(chǔ)引擎》以及《MYSQL內(nèi)核:INNODB存儲(chǔ)引擎》,感謝這兩本書的作者,也向各位推薦這兩本書。

這一系列文章都是從MySql的使用和設(shè)計(jì)的出發(fā),不會(huì)涉及源碼,希望可以幫助大家更深入理解InnoDB的設(shè)計(jì)和實(shí)現(xiàn)。

概念區(qū)分

先明確兩個(gè)概念,雖然平常我們并不需要嚴(yán)格區(qū)分他們
數(shù)據(jù)庫:存儲(chǔ)數(shù)據(jù)的物理操作系統(tǒng)文件或其他形式文件的集合
數(shù)據(jù)庫實(shí)例:MySql數(shù)據(jù)庫實(shí)例由后臺(tái)線程以及一個(gè)共享內(nèi)存區(qū)組成,負(fù)責(zé)操作數(shù)據(jù)庫文件。
MySql是一個(gè)單進(jìn)程多線程架構(gòu)的數(shù)據(jù)庫,MySql數(shù)據(jù)庫實(shí)例在系統(tǒng)上表現(xiàn)就是一個(gè)進(jìn)程。

MySql架構(gòu)

MySql架構(gòu)圖如下


MySql中有以下組件

  • 連接池組件 -- Connection Pool
  • 管理服務(wù)和工具組件 -- Management Services & utilities
  • SQL接口組件 -- SQL Interface
  • 查詢分析器組件 -- Praser
  • 優(yōu)化器組件 -- Optimizer
  • 緩沖組件 -- Caches & Buffers
  • 插件式表存儲(chǔ)引擎 -- Pluggable Storage Enginess
  • 物理文件 -- Files & Logs

MySQL區(qū)別于其他數(shù)據(jù)庫的一個(gè)最重要的特點(diǎn)是插件式存儲(chǔ)引擎。它是基于表的,而不是數(shù)據(jù)庫。MySql常用存儲(chǔ)引擎如下:
MyISAM存儲(chǔ)引擎

  • 不支持事務(wù)
  • 緩沖池只緩存索引文件,不緩沖數(shù)據(jù)文件
  • 由MYD和MYI文件組成,MYD用來存放數(shù)據(jù)文件,MYI用來存放索引文件,

InnoDB存儲(chǔ)引擎
獨(dú)立表空間,支持MVCC,行鎖設(shè)計(jì),提供一致性非鎖定讀
支持外鍵,插入緩沖,二次寫,自適應(yīng)哈希索引,預(yù)讀
使用聚集的方式存儲(chǔ)數(shù)據(jù),每張表的存儲(chǔ)都是按主鍵順序存放。

此外還有NDB,Memory,Archive,F(xiàn)ederated,Marai等存儲(chǔ)引擎。

InnoDB架構(gòu)

InnoDB架構(gòu)圖如下


以下主要從內(nèi)存和線程的角度分析InnoDB的架構(gòu)。

內(nèi)存池

主要工作:

  • 維護(hù)所有進(jìn)程/線程需要使用的多個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu)
  • 緩存磁盤上的數(shù)據(jù),方便快速地讀取,同時(shí)對(duì)磁盤文件數(shù)據(jù)修改之前在這里緩存
  • 重做日志緩存

InnoDB內(nèi)存池主要有以下部分


緩沖池
InnoDB是基于磁盤存儲(chǔ)的,并將其中的記錄按照頁的方式進(jìn)行管理。
而緩沖池就是一塊內(nèi)存區(qū)域,主要緩沖數(shù)據(jù)頁和索引頁。
InnoDB中對(duì)頁的讀取操作,首先判斷該頁是否在緩沖池中,若在,直接讀取該頁,若不在則從磁盤讀取頁數(shù)據(jù),并存放在緩沖池中。
對(duì)頁的修改操作,首先修改在緩沖池中的頁,再以一定的頻率(Checkpoint機(jī)制)刷新到磁盤。
參數(shù):innodb_buffer_pool_size設(shè)置緩沖池大小

緩沖池通過LRU(Latest Recent Used,最近最少使用)算法進(jìn)行管理。最頻繁使用的頁在LRU列表前端,最少使用的頁在尾端,當(dāng)緩沖池不能存放新讀取的頁時(shí),首先釋放LRU列表尾端的頁(頁數(shù)據(jù)刷新到磁盤,并從緩沖池中刪除)。
InnoDB對(duì)于新讀取的頁,不是放到LRU列表最前端,而是放到midpoint位置(默認(rèn)為5/8處)。
這是因?yàn)橐恍㏒QL操作會(huì)訪問大量的頁(如全表掃描),讀取大量非熱點(diǎn)數(shù)據(jù),如果直接放到首部,可能導(dǎo)致真正的熱點(diǎn)數(shù)據(jù)被移除。

關(guān)于頁的概念會(huì)在存儲(chǔ)篇解釋,這里就理解為InnoDB將表數(shù)據(jù)拆分為若干固定大小的頁,每頁保存若干表記錄。

重做日志緩存
重做日志先放到這個(gè)緩沖區(qū),然后按一定頻率刷新到重做日志文件。
參數(shù):innodb_log_buffer_size

刷新規(guī)則:

  1. Master Thread每秒將一部分重做日志緩沖刷新到重做日志文件
  2. 每一事務(wù)提交時(shí)會(huì)將重做日志刷新到重做日志文件(如果配置了)
  3. 重做日志緩沖區(qū)使用空間大于1/2

額外的內(nèi)存池
內(nèi)存堆,對(duì)InnoDB內(nèi)部使用的數(shù)據(jù)結(jié)構(gòu)對(duì)象進(jìn)行管理

Checkpoint機(jī)制

InnoDB對(duì)于對(duì)于DML語句操作(如Update或Delete),事務(wù)提交時(shí)只需在緩沖池中中完成操作,然后再通過Checkpoint將修改后的臟頁數(shù)據(jù)刷新到磁盤。

InnoDB有兩種Checkpoint
Sharp Checkpoint:數(shù)據(jù)庫關(guān)閉是將所有臟頁刷新回磁盤
Fuzzy Checkpoint:

  • Master Thread Checkpoint
    Master Thread每個(gè)1秒或10秒按一定比例將緩存池的臟頁列表刷新回磁盤

  • FLUSH LRU LIST Checkpoint
    Page Cleaner線程發(fā)現(xiàn)LRU列表中可用頁數(shù)量少于innodb_lru_scan_depth(1024),就將LRU列表尾端移除,如果這些頁中有臟頁,就需要Checkpoint

  • Async/Sync Flush Checkpoint
    重做日志文件空間不可以用時(shí),將一部分臟頁刷新到磁盤。

  • Dirty Page too much Checkpoint:
    臟頁數(shù)量太多(超過比例innodb_max_dirty_pages_pct,默認(rèn)75),執(zhí)行Checkpoint。

重做日志

重做日志是為了保證事務(wù)的原子性,持久性。InnoDB采用Write Ahread Log策略,事務(wù)提交時(shí),先寫重做日志,再修改頁。
數(shù)據(jù)庫宕機(jī)重啟時(shí)通過執(zhí)行重做日志恢復(fù)數(shù)據(jù)。
但由于Checkpoint機(jī)制,數(shù)據(jù)庫宕機(jī)重啟并不需要重做所有的日志,因?yàn)镃heckpoint之前的頁都刷新到磁盤了,只需執(zhí)行最新一次Checkpoint后的重做日志進(jìn)行恢復(fù),這樣可以縮短數(shù)據(jù)庫的恢復(fù)時(shí)間。

InnoDB中重做日志文件是循環(huán)使用的。當(dāng)頁被Checkpoint刷新到磁盤后,對(duì)應(yīng)的重做日志就不需要使用 ,其空間可以被覆蓋重用。
如果待寫入的重做日志文件空間不可用(臟頁還沒有刷新到磁盤),就需要強(qiáng)制產(chǎn)生Checkpoint,將緩沖池中的頁至少刷新到當(dāng)前重做日志的位置。

InnoDB 1.2.x(MySql 5.6)后,F(xiàn)LUSH LRU LIST Checkpoint以及Async/Sync Flush Checkpoint操作放到Page Cleaner線程,以免阻塞用戶線程。

線程

主要作用:

  • 負(fù)責(zé)刷新內(nèi)存池中的數(shù)據(jù),保證緩沖池的內(nèi)存緩沖的是最近的數(shù)據(jù)
  • 已修改的數(shù)據(jù)文件刷新到磁盤文件
  • 保證數(shù)據(jù)庫發(fā)生異常的情況下InnoDB能恢復(fù)到正常狀態(tài)。

InnoDB運(yùn)行時(shí)主要有以下線程
Master Thread
負(fù)責(zé)將緩沖池中的數(shù)據(jù)異步刷新到磁盤,保證數(shù)據(jù)的一致性,包括臟頁的刷新,合并插入緩沖(INSERT BUFFER),UNDO頁的回收等。

IO Thread
負(fù)責(zé)AIO請(qǐng)求的回調(diào)處理。
參數(shù):innodb_read_io_threads,innodb_write_io_threads

Purge Thread
事務(wù)提交后,undo log可能不再需要,由Purge Thread負(fù)責(zé)回收并重新分配的這些已經(jīng)使用的undo頁。
注意:Purge Thread需要離散地讀取undo頁。

Page Cleaner Thread
InnoDB 1.2.x引入,將Master Threader中刷新臟頁的工作移至該線程,如上面說的FLUSH LRU LIST Checkpoint以及Async/Sync Flush Checkpoint。

Master Thread

Master Thread具有最高的線程優(yōu)先級(jí)別,內(nèi)部由多個(gè)循環(huán)組成:主循環(huán)(loop),后臺(tái)循環(huán)(backgroup loop),刷新循環(huán)(flush loop),暫停循環(huán)(suspend loop),Master Thread根據(jù)數(shù)據(jù)庫運(yùn)行狀態(tài)在以上循環(huán)切換。

Master Thread主要流程偽代碼如下

void master_thread() {
    goto loop;
// 主循環(huán)
loop:
for(int i = 0; i < 10; i++) {
    // 每秒一次操作
    thread_sleep(1)
    // 日志緩沖刷新到磁盤,即使這個(gè)事務(wù)沒提交
    do log buffer flush to disk
    // 合并插入緩沖(如果前一秒IO次數(shù)少于5次,InnoDB認(rèn)為IO壓力很小,執(zhí)行該操作)
    if(last_one_second_ios < 5)
        do merge at most 5 insert buffer
    // 至多刷新100個(gè)InnoDB的臟頁到磁盤(臟頁比例超過innodb_max_dirty_pages_pct)   
    if(buf_get_modified_ratio_pct > innodb_max_dirty_pages_pct)
        do buffer poll flush 100 dirty page
    // 沒有用戶活動(dòng),跳轉(zhuǎn)到   backgroupo loop
    if(no user activity)
        goto backgroupo loop
}   
// 每10秒操作
// 刷新100個(gè)臟頁到磁盤(過去10秒內(nèi)IO操作小于200次)
if(last_ten_second_ios < 200)
    do buffer pool flush 100 dirty page
// 合并最多5個(gè)插入緩沖
do merge at most 5 insert buffer
// 合并最多5個(gè)插入緩沖
do log buffer flush to disk
// 刪除無用的Undo頁(最多20個(gè)undo頁)
do full purge
//臟頁比例超過innodb_max_dirty_pages_pct,刷新100個(gè)臟頁到磁盤,否則刷新10個(gè)臟頁
if(buf_get_modified_ratio_pct > 70%)
    do buffer pool flush 100 dirty page
else    
    do buffer pool flush 10 dirty page
goto loop

// 后臺(tái)循環(huán)
backgroup loop:
// 刪除無用的Undo
do full purge
// 合并20個(gè)插入緩沖
do merge 20 insert buffer
if not idel:
    goto loop
else 
    goto flush loop

// 刷新循環(huán)
flush loop:
// 刷新100個(gè)臟頁到磁盤,直到臟頁比例小于innodb_max_dirty_pages_pct
do buffer pool flush 100 dirty page
if(buf_get_modified_ratio_pct>innodb_max_dirty_pages_pct)
    goto flush loop
goto suspend loop

// 暫停循環(huán)
suspend loop:
// 暫停線程
suspend_thread()
// 等待事件
waiting event;
goto loop;  
}

如上所示,主循環(huán)有兩大操作,每秒操作和十秒操作。

InnoDB1.0.x優(yōu)化:
在每秒操作中,Master Thread每次最多刷新100個(gè)臟頁(臟頁比例超過innodb_max_dirty_pages_pct),合并20個(gè)插入緩沖,如果在寫入密集的應(yīng)用,處理速度可能太慢了。
從InnoDB 1.0.x開始,提供了通過innodb_io_capacity參數(shù)

每秒操作中合并插入緩沖數(shù)量為innodb_io_capacity * 5%
刷新臟頁數(shù)量為innodb_io_capacity
而默認(rèn)innodb_max_dirty_pages_pct參數(shù)值從90調(diào)整為75

引入以下參數(shù)
innodb_adaptive_flushing:自適應(yīng)刷新
臟頁比例小于innodb_max_dirty_pages_pct,也會(huì)刷新一定量的臟頁(由InnoDB控制刷新策略和數(shù)量)
innodb_purge_batch_size:控制每次full purge回收Undo頁,默認(rèn)還是20

InnoDB1.2.x優(yōu)化:

  1. InnoDB空閑時(shí),執(zhí)行原來的10秒一次操作,繁忙時(shí),執(zhí)行原來的每秒一次操作
  2. 刷新臟頁操作,分離到單獨(dú)Page Cleaner Thread

InnoDB關(guān)鍵特性

插入緩沖

插入聚集索引一般是順序的,不需要磁盤的隨機(jī)讀取
但插入非聚集索引葉子節(jié)點(diǎn)不是順序的,需要離散訪問非聚集索引頁,速度較慢。
對(duì)于非聚集索引的插入或更新,先判斷插入的非聚集索引頁是否在緩存池中,若在,直接插入,或不在,先放到一個(gè)Inser Buffer對(duì)象中,
然后根據(jù)一些算法將Insert Buffer緩存的記錄通過后臺(tái)線程慢慢合并刷新回輔助索引。
插入緩沖將多次插入合并為一次操作,減少磁盤的離散操作。

使用Insert Buffer需滿足兩個(gè)條件:
索引是輔助索引
索引不是唯一的(不需要查找索引頁判斷唯一性)

InnoDB從1.0.x引入Change Buffer,對(duì)INSERT,DELETE,UPDATE都進(jìn)行緩沖。
參數(shù):innodb_change_buffer_max_size,Change Buffer最多使用緩沖池內(nèi)存空間。

兩次寫 doublewrite

部分寫失效:頁數(shù)據(jù)寫入到磁盤時(shí)只寫了一部分(如16K數(shù)據(jù)只寫了2K),數(shù)據(jù)庫就宕機(jī)了,導(dǎo)致頁數(shù)據(jù)損壞,這時(shí)無法使用重做日志恢復(fù)。(執(zhí)行重做日志時(shí)需要利用頁的一些變量,如checksum)

因此在使用重做日志恢復(fù)數(shù)據(jù)庫,需要有一個(gè)頁的副本,當(dāng)發(fā)生寫失效時(shí),先通過頁的副本還原該頁,再進(jìn)行重做。于是InnoDB實(shí)現(xiàn)了doublewrite技術(shù)。

doublewrite有兩部分,一部分是內(nèi)存中的doublewrite buffer,大小為2MB,另一部分是磁盤共享表空間連續(xù)的128個(gè)頁,也是2MB。
doublewrite要求刷新緩沖池的臟頁時(shí)執(zhí)行以下步驟

  1. 通過memcpy函數(shù)將臟頁復(fù)制到內(nèi)存的doublewrite buffer
  2. doublewrite buffer分兩次,每次1MB順序?qū)懭牍蚕肀砜臻g
  3. 調(diào)用fsync函數(shù)同步磁盤,避免緩沖寫帶來問題,確保數(shù)據(jù)刷新到共享表空間(順序?qū)懀_銷小)
  4. 將上述的臟頁數(shù)據(jù)寫入各個(gè)表空間文件(離散寫)

自適應(yīng)哈希索引

InnoDB會(huì)監(jiān)控對(duì)表上各索引頁的查詢執(zhí)行情況,如發(fā)現(xiàn)建立哈希索引可以提升速度,則建立哈希索引,這是過程不需要用戶干預(yù)。
參數(shù):innodb_adaptive_hash_index,默認(rèn)AHI為開啟狀態(tài)

異步IO

InnoDB使用異步IO操作磁盤,避免同步IO導(dǎo)致阻塞,也可以進(jìn)行IO Merge操作,將多個(gè)IO操作合并為一個(gè)IO操作。

刷新鄰接頁

當(dāng)刷新一個(gè)臟頁時(shí),InnoDB會(huì)檢測(cè)該頁所在區(qū)的所有頁,如果是臟頁,一起刷新,這是可以通過AIO將多個(gè)IO寫入操作合并為一個(gè)IO操作。
參數(shù):innodb_flush_neighbors,控制開關(guān)

文件

參數(shù)文件

在MySql實(shí)例啟動(dòng)時(shí)指定某些初始化參數(shù),如數(shù)據(jù)庫文件目錄,內(nèi)存池大小等。
參看參數(shù)文件所在目錄:mysql --help|grep my.cnf
linux下默認(rèn)目錄為/etc/mysql/my.cnf
/etc/mysql/conf.d/mysql.cnf為客戶端參數(shù)文件
/etc/mysql/mysql.conf.d/mysql.cnf為服務(wù)端參數(shù)文件

參數(shù)類型:

  • 動(dòng)態(tài)參數(shù),可以在MySql實(shí)例運(yùn)行中進(jìn)行更改
    SET [global | session] system_var_name = expr
    SET [@@golbal. | @@session. | @@]system_var_name = expr

  • 靜態(tài)參數(shù):只能在實(shí)例停止時(shí)修改

注意:datadir參數(shù)指定MySql數(shù)據(jù)目錄,它是數(shù)據(jù)文件,日志文件默認(rèn)存放目錄。

日志文件

錯(cuò)誤日志
遇到問題應(yīng)該查看該文件以便定位問題。
參數(shù):log-error

慢查詢?nèi)罩?/strong>
記錄執(zhí)行時(shí)間超過某一閥值的所有SQL
參數(shù):
log_slow_queries:記錄慢SQL的開關(guān)
long_query_time:慢SQl的閥值,默認(rèn)為10,單位秒
log_queries_not_using_indexes:是否記錄沒有使用索引的查詢
log_throttle_queries_not_using_indexs:每分鐘最多記錄沒使用索引的SQL的數(shù)量
slow-query-log-file:指定目錄,默認(rèn)在data目錄
log_output:輸出格式,默認(rèn)為FILE,可以配置為TABLE(記錄到slow_log表)
可以使用mysqldumpslow分析慢日志

查詢?nèi)罩?/strong>
記錄所有對(duì)MySql數(shù)據(jù)庫的請(qǐng)求信息。
默認(rèn)文件名為主機(jī)名.log,也可以輸出到mysql架構(gòu)的general_log表中。

二進(jìn)制日志
記錄對(duì)MySql數(shù)據(jù)庫執(zhí)行更改的所有操作,不包括select,show這類操作。
可用于恢復(fù),復(fù)制,審計(jì)(判斷是否有對(duì)數(shù)據(jù)庫進(jìn)行注入攻擊)
MySql官方手冊(cè)測(cè)試表明,開啟二進(jìn)制日志會(huì)使性能下降1%,但考慮到復(fù)制,point-in-time的恢復(fù)等功能,完成可以接受,建議開啟。
參數(shù):
log_bin:是否開啟二進(jìn)制日志,默認(rèn)No
log-bin:指定日志名稱,默認(rèn)為主機(jī)名,后綴為二進(jìn)制日志序列號(hào),如bin_log.000001
max_binlog_size:?jiǎn)蝹€(gè)二進(jìn)制日志文件最大值
binlog_cache_size:二進(jìn)制日志緩沖區(qū)大小,基于會(huì)話
sync_binlog:1 表示使用同步寫磁盤方法寫入二進(jìn)制日志,默認(rèn)為0
binlog_format:二進(jìn)制日志格式,可以為STATEMENT,ROW,MIXED
-- STATEMENT:記錄SQL語句
-- ROW:記錄表的行更改情況
-- MIXED:默認(rèn)使用STATEMENT,一些特定情況使用ROW
使用ROW可以為數(shù)據(jù)庫的恢復(fù)和復(fù)制帶來更好的可靠性,但會(huì)導(dǎo)致二進(jìn)制文件大小增加。復(fù)制的網(wǎng)絡(luò)開銷也有所增加。
可以使用mysqlbinlog可以分析二進(jìn)制日志

套接字文件
當(dāng)使用UNIX域套接字方式進(jìn)行連接時(shí)需要的文件。
參數(shù):socket

pid文件
MySql實(shí)例的進(jìn)程ID文件。
參數(shù):pid_file

表結(jié)構(gòu)定義文件
存放MySql表結(jié)構(gòu)定義。
在數(shù)據(jù)目錄下,每一個(gè)表都有一個(gè)子目錄,存放對(duì)應(yīng)的表結(jié)構(gòu)定義文件,后綴為frm
MySql8.0后,移除了.frm文件,表結(jié)構(gòu)定義存放到數(shù)據(jù)庫系統(tǒng)表中。

每個(gè)存儲(chǔ)引擎都可以自行定義的文件保存引擎所需的數(shù)據(jù)。InnoDB存儲(chǔ)引擎定義了以下文件:
表空間文件
InnoDB將所有數(shù)據(jù)(表數(shù)據(jù),索引,插入緩沖索引頁,回滾信息,插入緩沖索引頁,系統(tǒng)事務(wù)信息,二次寫緩沖等等)邏輯地放在一個(gè)空間中,稱為共享表空間。
表空間數(shù)據(jù)默認(rèn)保證在數(shù)據(jù)目錄下的ibdata1文件,該文件初始大小為10M。
一個(gè)表空間可以由多個(gè)文件組成。

參數(shù):innodb_data_file_path,可以通過多個(gè)文件組成一個(gè)表空間,同時(shí)指定文件屬性,如
/db/ibdata1:2000M;/db/ibdata2:2000M:autoextend,autoextend表示文件可以自動(dòng)擴(kuò)容,只有最后一個(gè)文件可以被指定為自動(dòng)擴(kuò)容。

開啟參數(shù)innodb_file_per_table后,每個(gè)表都產(chǎn)生一個(gè)獨(dú)立的表空間,文件命名為:表名.ibd,該表的數(shù)據(jù),索引和插入緩沖BITMAP等信息到保存到獨(dú)立表空間,但其它數(shù)據(jù)(如回滾信息,插入緩沖索引頁,系統(tǒng)事務(wù)信息,二次寫緩沖)還是存放在默認(rèn)的表空間。

重做日志文件
每個(gè)InnoDB存儲(chǔ)引擎至少有1個(gè)重做日志文件組,每個(gè)文件組下至少有2個(gè)重做日志文件,默認(rèn)為ib_logfile0,ib_logfile1,一個(gè)文件寫滿后,再寫另一個(gè)文件,循環(huán)復(fù)用。

Undo日志文件
undo log保證事務(wù)的原子性, 幫助事務(wù)回滾以及MVCC功能。

在InnoDB 1.2.x(MySQL 5.6)前,undo日志保存在共享表空間ibdata1文件中的,隨著數(shù)據(jù)庫的運(yùn)行時(shí)間的不斷增長(zhǎng),會(huì)導(dǎo)致共享表空間越來越大,
從InnoDB 1.2.x(MySQL 5.6)起,Undo日志被分離出來,由單獨(dú)的Undo表空間管理,這樣可以避免處理Undo日志的IO過于集中,有助于分散IO負(fù)載。
Undo日志默認(rèn)保存數(shù)據(jù)目錄下的undo_001,undo_002文件中。
MySQL 5.7,提供undo log在線回收功能
MySQL 8.0,可以通過SQL語句非常方便的管理 Undo 表空間

關(guān)于重做日志和undo日志會(huì)在事務(wù)篇詳細(xì)解析。

InnoDB配置參數(shù)文檔:InnoDB Startup Options and System Variables

如果您覺得本文不錯(cuò),歡迎關(guān)注我的微信公眾號(hào),您的關(guān)注是我堅(jiān)持的動(dòng)力!


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,196評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,456評(píng)論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,955評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,195評(píng)論 0 287
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,725評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,608評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,802評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,048評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評(píng)論 1 281
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,424評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,762評(píng)論 2 372