记一次线上mysql死锁分析(一)

记录一次比较诡异的mysql死锁日志。系统运行几个月来,就在前几天发生了一次死锁,而且就只发生了一次死锁,整个排查过程耗时将近一天,最后感谢我们的DBA大神和老大一起分析找到原因。

诊断死锁

借助于我们dapeng开源的分布式日志查询系统(EFF)及日志告警系统,我们得益于及时发现了业务中的死锁日志。(想了解dapeng分布式日志查询系统请点击)

08-02 08:46:24 787 dapeng-eventbus--scheduler-0 ERROR [] - 
eventbus: 定时轮询线程内出现了异常,已捕获 msg:Deadlock found when trying to get lock; try restarting transaction
com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_161]
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_161]
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_161]
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_161]
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:400) ~[mysql-connector-java-5.1.36.jar:5.1.36]
        at com.mysql.jdbc.Util.getInstance(Util.java:383) ~[mysql-connector-java-5.1.36.jar:5.1.36]
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987) ~[mysql-connector-java-5.1.36.jar:5.1.36]
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3847) ~[mysql-connector-java-5.1.36.jar:5.1.36]
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3783) ~[mysql-connector-java-5.1.36.jar:5.1.36]
       // 省略部分...
        at com.today.eventbus.scheduler.ScalaSql$.executeUpdateWithGenerateKey(ScalaSql.scala:104) ~[event-bus_2.12-2.0.4.jar:2.0.4]
        at com.today.eventbus.scheduler.ScalaSql$.executeUpdate(ScalaSql.scala:57) ~[event-bus_2.12-2.0.4.jar:2.0.4]
        at com.today.eventbus.scheduler.MsgPublishTask.$anonfun$doPublishMessagesAsync$1(MsgPublishTask.scala:154) ~[event-bus_2.12-2.0.4.jar:2.0.4]
        at com.today.eventbus.scheduler.MsgPublishTask.$anonfun$doPublishMessagesAsync$1$adapted(MsgPublishTask.scala:144) ~[event-bus_2.12-2.0.4.jar:2.0.4]
        at com.today.eventbus.scheduler.ScalaSql$.withTransaction(ScalaSql.scala:26) ~[event-bus_2.12-2.0.4.jar:2.0.4]
        at com.today.eventbus.scheduler.MsgPublishTask.doPublishMessagesAsync(MsgPublishTask.scala:144) ~[event-bus_2.12-2.0.4.jar:2.0.4]
        at com.today.eventbus.scheduler.MsgPublishTask.$anonfun$startScheduled$2(MsgPublishTask.scala:95) ~[event-bus_2.12-2.0.4.jar:2.0.4]
        //省略部分...

当我们找到业务中的ERROR日志后,发现只有如下简单的一句发现死锁的日志,无法进行死锁定定位,我们需要诊断分析当时出现死锁的上下文信息以及相关的执行语句。这时候就需要查看mysql死锁日志了。

首先,需要打开mysql死锁日志开关,我们线上是已经打开的。打开方式

set global innodb_print_all_deadlocks=on

然后我们去mysql错误日志中捞这次的死锁日志

2018-08-02T08:46:24.758848+08:00 871635 [Note] InnoDB:
*** (1) TRANSACTION:

TRANSACTION 206663716, ACTIVE 0 sec fetching rows
mysql tables in use 1, locked 1
LOCK WAIT 5 lock struct(s), heap size 1136, 10 row lock(s), undo log entries 5
MySQL thread id 872226, OS thread handle 140243727415040, query id 461709452 192.168.10.126 today_user updating
DELETE FROM dp_common_event WHERE id in (268241,268242,268243,268810,268811)
2018-08-02T08:46:24.758879+08:00 871635 [Note] InnoDB: *** (1) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 812 page no 3 n bits 80 index PRIMARY of table `order_db`.`dp_common_event` trx id 206663716 lock_mode X waiting
Record lock, heap no 10 PHYSICAL RECORD: n_fields 6; compact format; info bits 0
 0: len 8; hex 8000000000041a0c; asc         ;;
 1: len 6; hex 00000c517014; asc    Qp ;;
 2: len 7; hex b5000006a20110; asc        ;;
 3: len 30; hex 636f6d2e746f6461792e6170692e6f726465722e7363616c612e6576656e; asc com.today.api.order.scala.even; (total 52 bytes);
 4: len 30; hex 636f6d2e746f6461792e6170692e6f726465722e7363616c612e6576656e; asc com.today.api.order.scala.even; (total 371 bytes);
 5: len 4; hex 5b625460; asc [bT`;;

2018-08-02T08:46:24.759242+08:00 871635 [Note] InnoDB: *** (2) TRANSACTION:

TRANSACTION 206663700, ACTIVE 0 sec inserting, thread declared inside InnoDB 5000
mysql tables in use 1, locked 1
10 lock struct(s), heap size 1136, 6 row lock(s), undo log entries 6
MySQL thread id 871635, OS thread handle 140243167844096, query id 461709463 192.168.10.126 today_user update
INSERT INTO  dp_common_event set id=268244, event_type='com.today.api.order.scala.events.StoreOrderEndEventNew', event_binary=x'636F6D2E746F6461792E6170692E6F726465722E7363616C612E6576656E74732E53746F72654F72646572456E644576656E744E65770016A8DF2015181C16F8E9111814313136303035303135333331373037353336373615061504180731322E35303030180731322E353030304806302E30303030F806302E30303030080E01311808313136303035303016E699A80436D0EBCC819F59280018001680DCCC819F59150216D0F7C8819F5915021680DCCC819F5915DEB1931E00192C16EEFC1E18143131363030353031353333313730373533363736180832303531383430301502180CE7899BE88289E58DA4E7B289160018003806302E303030301502180731302E30303030180015002806302E3030303016000016F0FC1E181431313630303530313533333137303735333637361808323034373138303415041812E9A699E88F87E6B2B9E88F9CE58C85383067160018003806302E3030303015021806322E35303030180015002806302E30303030160000190800'
2018-08-02T08:46:24.759270+08:00 871635 [Note] InnoDB: *** (2) HOLDS THE LOCK(S):

RECORD LOCKS space id 812 page no 3 n bits 80 index PRIMARY of table `order_db`.`dp_common_event` trx id 206663700 lock_mode X locks rec but not gap
Record lock, heap no 10 PHYSICAL RECORD: n_fields 6; compact format; info bits 0
 0: len 8; hex 8000000000041a0c; asc         ;;
 1: len 6; hex 00000c517014; asc    Qp ;;
 2: len 7; hex b5000006a20110; asc        ;;
 3: len 30; hex 636f6d2e746f6461792e6170692e6f726465722e7363616c612e6576656e; asc com.today.api.order.scala.even; (total 52 bytes);
 4: len 30; hex 636f6d2e746f6461792e6170692e6f726465722e7363616c612e6576656e; asc com.today.api.order.scala.even; (total 371 bytes);
 5: len 4; hex 5b625460; asc [bT`;;

2018-08-02T08:46:24.759691+08:00 871635 [Note] InnoDB: *** (2) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 812 page no 3 n bits 80 index PRIMARY of table `order_db`.`dp_common_event` trx id 206663700 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 6 PHYSICAL RECORD: n_fields 6; compact format; info bits 32
 0: len 8; hex 8000000000041a0a; asc         ;;
 1: len 6; hex 00000c517024; asc    Qp$;;
 2: len 7; hex 40000001ac0a84; asc @      ;;
 3: len 30; hex 636f6d2e746f6461792e6170692e6f726465722e7363616c612e6576656e; asc com.today.api.order.scala.even; (total 54 bytes);
 4: len 30; hex 636f6d2e746f6461792e6170692e6f726465722e7363616c612e6576656e; asc com.today.api.order.scala.even; (total 476 bytes);
 5: len 4; hex 5b625460; asc [bT`;;

2018-08-02T08:46:24.760094+08:00 871635 [Note] InnoDB: *** WE ROLL BACK TRANSACTION (1)

解读死锁日志

死锁日志里面记录了两个事务,事务1事务2,其中事务1最终被回滚了

  • 事务1

持有的锁
事务1锁住了5个对象,持有10把锁。执行的sql语句为

DELETE FROM dp_common_event WHERE id in (268241,268242,268243,268810,268811)

等待的锁
等待order_db.dp_common_event的主键的排他锁(X锁)

  • 事务2

持有的锁
事务2锁住了10个对象,持有6把锁,sql语句如下

INSERT INTO  dp_common_event set id=268244, event_type='com.today.api.order.scala.events.StoreOrderEndEventNew', event_binary=x'二进制数据(略)'

等待的锁
lock_mode X locks gap before rec insert intention waiting
意思为事务2正在向表dp_common_event插入一行数据,在获取意向插入锁之前需要先获取到当前表的一个排他锁(LOCK_X)。

查看发生死锁时间上下文业务日志

//省略
08-02 08:46:24 684 dapeng-container-biz-pool-79 DEBUG [ac1e0002a068ab95] - SQL Preparing: INSERT INTO  dp_common_event set id=?, event_type=?, event_binary=? args: WrappedArray(JdbcValue(268812), JdbcValue(com.today.api.order.scala.events.CreateOrderEventNew), JdbcValue([B@255b9459))
08-02 08:46:24 688 dapeng-container-biz-pool-79 DEBUG [ac1e0002a068ab95] - SQL result: 1
// 省略中间业务代码
08-02 08:46:24 758 dapeng-container-biz-pool-79 DEBUG [ac1e0002a068ab95] - SQL Preparing: INSERT INTO  dp_common_event set id=?, event_type=?, event_binary=? args: WrappedArray(JdbcValue(268244), JdbcValue(com.today.api.order.scala.events.StoreOrderEndEventNew), JdbcValue([B@3f796e10))
08-02 08:46:24 762 dapeng-container-biz-pool-79 DEBUG [ac1e0002a068ab95] - SQL result: 1

在一个事务中(根据死锁日志,此事务为事务2),我们先后向dp_common_event表插入了两次数据,然后就在这时候发生了死锁。

//第一条数据
 INSERT INTO  dp_common_event set id= 268812, event_type='com.today.api.order.scala.events.CreateOrderEventNew', event_binary= [B@255b9459);
//第二条数据
 INSERT INTO  dp_common_event set id= 268244, event_type='com.today.api.order.scala.events.StoreOrderEndEventNew', event_binary=[B@3f796e10)

与此同时,事务1(发生死锁后被回滚的一方)的操作如下:

DELETE FROM dp_common_event WHERE id in (268241,268242,268243,268810,268811)

查看表结构

CREATE TABLE `dp_common_event` (
  `id` bigint(20) NOT NULL COMMENT '事件id,全局唯一, 可用于幂等操作',
  `event_type` varchar(255) DEFAULT NULL COMMENT '事件类型',
  `event_binary` blob COMMENT '事件内容',
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_dp_common_event` (`updated_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

可以看到,该表id字段为主键,update_at是普通索引。

分析

时间线分析

通过比对,我们整理出事务1和事务2执行的先后顺序,如下图:

时间线.png
t1 时刻

事务2dp_common_event表插入一条数据,插入的数据id为268812,插入完成后,此时事务2会持有锁,锁住的是一行记录。lock_mode X locks rec but not gap代表锁住的是一个索引,不是一个范围。

t2 时刻

事务1开启事务,并删除 dp_common_event一部分数据,使用的条件是in的形式,删除的数据为(268241,268242,268243,268810,268811)
我们在本地模拟插入上述5条数据,并使用desc分析这条删除语句。

desc delete from dp_common_event where id in (268241,268242,268243,268810,268811);

结果如下图:

desc.png
  • key栏为空,说明mysql并没有走主键索引,这是为什么呢?

原来,当mysql走索引查询的数据占全表30%以上时,mysql就不会选择走索引。由于dp_common_event表的数据量很少,使用 in 的模式并没有走索引。因此这里没有加行锁。这里加的锁就是Gap锁。需要锁住的是一个范围。

本例中,gap锁从左至右依次锁住 268241 到 268811之间的每一条记录,以及268811以上的所有的记录。由于事务2中锁住的记录id268812,该条记录的锁被事务2。因此gap锁当锁到268812这条记录时,会进行等待。等待巨鹿如下。lock_mode X locks rec but not gap代表的意思是等待的是一条记录而不是一个范围。

t3 时刻

事务2继续向下执行,插入第二条数据,id为268244,由于268244这条记录已经在事务1中被`gap锁锁。因此,这时候事务2反过来要去等待事务1的gap锁,而上一步事务1再等待事务2的记录锁。这就造成了循环等待,出现死锁。于是事务1回滚,事务2提交了。

t3时刻mysql错误日志日下

RECORD LOCKS space id 812 page no 3 n bits 80 index PRIMARY of table `order_db`.`dp_common_event` trx id 206663716 lock_mode X waiting
Record lock, heap no 10 PHYSICAL RECORD: n_fields 6; compact format; info bits 0

如何避免死锁

首先,上述例子中,如果事务2的两条插入语句的id是顺序递增的,那么再第二条语句插入时,它的id值不会被事务1的gap锁锁住,这样也不会造成死锁。

其次,如果事务2中每次往dp_common_event中只插入一条数据,也不会造成死锁。

第三,如果事务1中使用的时精确单条删,以多条语句单独删的形式,那么就不会锁住范围,而是精确的锁住每一行,这样也不回出现死锁。

总结,由于每次插入的id是通过一个分布式取号服务获取的,该取号服务会有两个节点,两个节点的id会有一个区间的差距,比如a节点目前取号的起始值为268241,那么b节点的起始值为268810。因此,每次插入时不能严格保证id的绝对递增。

因此,我们决定在删除操作时,精确到一行一行进行删除。

案例2

由于某次需要删除线上的脏数据时,与生产的业务相冲出现了死锁,如下日志显示。

08-05 18:55:56 582 dapeng-container-biz-pool-1 ERROR [ac190004bcca51e5] - 
Deadlock found when trying to get lock; try restarting transaction
com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: 
Deadlock found when trying to get lock; try restarting transaction
         // 省略部分
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:400) ~[mysql-connector-java-5.1.36.jar:5.1.36]
        at com.mysql.jdbc.Util.getInstance(Util.java:383) ~[mysql-connector-java-5.1.36.jar:5.1.36]
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987) ~[mysql-connector-java-5.1.36.jar:5.1.36]
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3847) ~[mysql-connector-java-5.1.36.jar:5.1.36]
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3783) ~[mysql-connector-java-5.1.36.jar:5.1.36]
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2447) ~[mysql-connector-java-5.1.36.jar:5.1.36]
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2594) ~[mysql-connector-java-5.1.36.jar:5.1.36]
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2545) ~[mysql-connector-java-5.1.36.jar:5.1.36]
         //省略部分
        at wangzx.scala_commons.sql.RichDataSource.$anonfun$generateKey$1(RichDataSource.scala:30) ~[scala-sql_2.12-2.0.6.jar:2.0.6]
        at wangzx.scala_commons.sql.RichDataSource.withConnection(RichDataSource.scala:12) ~[scala-sql_2.12-2.0.6.jar:2.0.6]
        at wangzx.scala_commons.sql.RichDataSource.generateKey(RichDataSource.scala:30) ~[scala-sql_2.12-2.0.6.jar:2.0.6]
        at com.today.service.order_new.sql.OrderSql$.createOrderDetail(OrderSql.scala:80) ~[order_service_2.12-0.2.0-SNAPSHOT.jar:0.2.0-SNAPSHOT]
        at com.today.service.order_new.action.CreateOrderAction.$anonfun$action$1(CreateOrderAction.scala:53) [order_service_2.12-0.2.0-SNAPSHOT.jar:0.2.0-SNAPSHOT]
        at com.today.service.order_new.action.CreateOrderAction.$anonfun$action$1$adapted(CreateOrderAction.scala:53) [order_service_2.12-0.2.0-SNAPSHOT.jar:0.2.0-SNAPSHOT]
        at scala.collection.immutable.List.foreach(List.scala:389) ~[scala-library.jar:na]
        at com.today.service.order_new.action.CreateOrderAction.action(CreateOrderAction.scala:53) [order_service_2.12-0.2.0-SNAPSHOT.jar:0.2.0-SNAPSHOT]
        at com.today.service.order_new.action.CreateOrderAction.action(CreateOrderAction.scala:24) [order_service_2.12-0.2.0-SNAPSHOT.jar:0.2.0-SNAPSHOT]
        at com.today.service.commons.Action.execute(Action.scala:15) [service-commons_2.12-1.5-SNAPSHOT.jar:1.5-SNAPSHOT]
        at com.today.service.commons.Action.execute$(Action.scala:10) [service-commons_2.12-1.5-SNAPSHOT.jar:1.5-SNAPSHOT]
        at com.today.service.order_new.action.CreateOrderAction.execute(CreateOrderAction.scala:24) [order_service_2.12-0.2.0-SNAPSHOT.jar:0.2.0-SNAPSHOT]
        at com.today.service.order_new.OrderService2Impl.createOrder(OrderService2Impl.scala:45) [order_service_2.12-0.2.0-SNAPSHOT.jar:0.2.0-SNAPSHOT]

死锁日志

*** (1) TRANSACTION:

TRANSACTION 216689660, ACTIVE 27 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 2
MySQL thread id 995341, OS thread handle 140243168642816, query id 539333372 192.168.10.131 today_user update
INSERT INTO `order_detail` SET
            id = 379373,
            order_no = '11600202533466529666',
            detail_seq = 1,
            sku_no='20507572',
            sku_name='海氏海诺创可贴',
            sku_version=0,
            barcode='',
            coupon_id=0,
            sku_count=1,
            sku_selling_price=7.0,
            discount_amount = 0.0,
            remark = '',
            created_at = now(),
            created_by = 1,
            updated_at = now(),
            updated_by=1
         ,promotion_id = 0
2018-08-05T18:55:56.524630+08:00 995779 [Note] InnoDB: *** (1) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 1045 page no 6219 n bits 440 index idx_order_detail of table `order_db`.`order_detail` trx id 216689660 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 20; hex 3131363030353031353333303531333137333333; asc 11600501533051317333;;
 1: len 8; hex 8000000000032b87; asc       + ;;

2018-08-05T18:55:56.524779+08:00 995779 [Note] InnoDB: *** (2) TRANSACTION:

TRANSACTION 216688923, ACTIVE 49 sec fetching rows, thread declared inside InnoDB 1251
mysql tables in use 2, locked 2
1653 lock struct(s), heap size 172240, 160498 row lock(s), undo log entries 43
MySQL thread id 995779, OS thread handle 140243732473600, query id 539339615 localhost root Sending data
delete from orders where order_no in (
select a.order_no from (
select order_no from orders where  finish_time between '2018-07-01 00:00:00' and '2018-07-31 00:00:00' and store_id  in ('11866600','11888700','10008000','11866601','10009000','11703083','10003502','11608093','10004102','10010100', 
'11699800','11888900') ) as a
)
2018-08-05T18:55:56.524820+08:00 995779 [Note] InnoDB: *** (2) HOLDS THE LOCK(S):

RECORD LOCKS space id 1045 page no 6219 n bits 440 index idx_order_detail of table `order_db`.`order_detail` trx id 216688923 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 20; hex 3131363030353031353333303531333137333333; asc 11600501533051317333;;
 1: len 8; hex 8000000000032b87; asc       + ;;

2018-08-05T18:55:56.524993+08:00 995779 [Note] InnoDB: *** (2) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 817 page no 2397 n bits 184 index PRIMARY of table `order_db`.`orders` trx id 216688923 lock mode S waiting
Record lock, heap no 106 PHYSICAL RECORD: n_fields 26; compact format; info bits 0
 0: len 8; hex 8000000000032336; asc       #6;;
 1: len 6; hex 00000cea6bfc; asc     k ;;
 2: len 7; hex aa000001430110; asc     C  ;;
 3: len 20; hex 3131363030323032353333343636353239363636; asc 11600202533466529666;;
 4: len 2; hex 8001; asc   ;;
 5: len 4; hex 80000001; asc     ;;
 6: len 5; hex 8000070000; asc      ;;
 7: len 5; hex 8000070000; asc      ;;
 8: len 8; hex 8000000000000002; asc         ;;
 9: len 4; hex 80b1014a; asc    J;;
 10: len 8; hex 8000000000000000; asc         ;;
 11: len 5; hex 8000000000; asc      ;;
 12: len 5; hex 8000000000; asc      ;;
 13: len 5; hex 8000000000; asc      ;;
 14: len 2; hex 8000; asc   ;;
 15: SQL NULL;
 16: SQL NULL;
 17: len 5; hex 99a08b2dde; asc    - ;;
 18: len 0; hex ; asc ;;
 19: len 0; hex ; asc ;;
 20: SQL NULL;
 21: len 4; hex 81e24944; asc   ID;;
 22: len 5; hex 99a08b2ddd; asc    - ;;
 23: len 4; hex 80000001; asc     ;;
 24: len 4; hex 5b66d7a1; asc [f  ;;
 25: len 4; hex 80000001; asc     ;;

2018-08-05T18:55:56.525617+08:00 995779 [Note] InnoDB: *** WE ROLL BACK TRANSACTION (1)

分析死锁日志

主要是事务1 insert操作时在插入order_detail表时,需要获取插入意向锁之前,需要获取一个gap x锁。

事务2在删除数据时,需要获取一个 S锁,共享锁。orders表的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352

推荐阅读更多精彩内容