AI摘要
文章讨论了MySQL数据库中死锁的排查和解决方法。首先,通过分析业务和数据库死锁日志,确定了死锁发生的时间、事务信息和锁的类型。然后,结合理论知识,了解了死锁的条件和数据库锁类型。接着,通过业务日志分析,还原了死锁场景,并确定了导致死锁的具体SQL语句。最后,提出了临时和长期的解决方法,包括限流、降低并发冲突、检查索引、增加重试机制等,并强调了运维和开发的责任分配。
一. 死锁日志
1.1 故障现象
一直运行了很久的项目,突然在最近几天频出现死锁异常,业务机器大概每一两天在业务高峰期发生一次。
如下的业务死锁日志:
INFO 57553 --- [ConsumerThread2] org.example.controller.TestController : 全局链路跟踪id:2的日志:[TransactionReqVO(userId=4, money=4), TransactionReqVO(userId=2, money=2), TransactionReqVO(userId=5, money=5)]
INFO 57553 --- [ConsumerThread1] org.example.controller.TestController : 全局链路跟踪id:1的日志:[TransactionReqVO(userId=5, money=5), TransactionReqVO(userId=1, money=1), TransactionReqVO(userId=4, money=4)]
ERROR 57553 --- [ConsumerThread2] org.example.controller.TestController : 全局链路跟踪id:2的异常:
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
### The error may exist in org/example/mapper/TestTableMapper.java (best guess)
### The error may involve org.example.mapper.TestTableMapper.update-Inline
### The error occurred while setting parameters
### SQL: UPDATE test_table SET money = money + ? WHERE user_id = ?
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
; Deadlock found when trying to get lock; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
org.springframework.dao.DeadlockLoserDataAccessException:
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
### The error may exist in org/example/mapper/TestTableMapper.java (best guess)
### The error may involve org.example.mapper.TestTableMapper.update-Inline
### The error occurred while setting parameters
### SQL: UPDATE test_table SET money = money + ? WHERE user_id = ?
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
; Deadlock found when trying to get lock; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:266) ~[spring-jdbc-5.0.13.RELEASE.jar:5.0.13.RELEASE]
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) ~[spring-jdbc-5.0.13.RELEASE.jar:5.0.13.RELEASE]
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73) ~[mybatis-spring-2.0.1.jar:2.0.1]
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446) ~[mybatis-spring-2.0.1.jar:2.0.1]
at com.sun.proxy.$Proxy59.update(Unknown Source) ~[na:na]
at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:294) ~[mybatis-spring-2.0.1.jar:2.0.1]
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:67) ~[mybatis-3.5.1.jar:3.5.1]
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:58) ~[mybatis-3.5.1.jar:3.5.1]
at com.sun.proxy.$Proxy62.update(Unknown Source) ~[na:na]
at org.example.service.impl.TestServiceImpl.update(TestServiceImpl.java:16) ~[classes/:na]
at org.example.manager.impl.BizManagerImpl.transactionMoney(BizManagerImpl.java:25) ~[classes/:na]
at org.example.manager.impl.BizManagerImpl$$FastClassBySpringCGLIB$$824241b9.invoke(<generated>) ~[classes/:na]Deadlock 非常显眼,说明业务上出现了死锁,肯定是业务上有问题。但是该业务代码一直运行了大半年,查看 Git 记录也发现最近没人动该业务相关代码,说明该业务之前就可能有问题,只是最近才达到了触发这种异常的条件。
对该日志做个简单的总结:
1.这是什么错误日志?
8行:### SQL: UPDATE test\_table SET money = money + ? WHERE user\_id = ?
9行:### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
从第 8\~9 行可以得知,该错误是数据库的错误,是死锁错误异常而导致的回滚。
关键 SQL 是:UPDATE test_table SET money = money + ? WHERE user_id = ?
2.核心错误的调用方法是哪个,即事务开始的方法是哪个?
30行:at org.example.manager.impl.BizManagerImpl.transactionMoney(BizManagerImpl.java:25) \~[classes/:na] 31行:at org.example.manager.impl.BizManagerImpl$$FastClassBySpringCGLIB$$824241b9.invoke() \~[classes/:na]过滤了 jdk 类、spring 类、mybatis 类后,得到核心的业务错误代码(30\~31 行),31 行为 Spring 的代理执行,30 行才是真正最开始执行业务代码:BizManagerImpl.transactionMoney
1.2 数据库死锁日志
接着去查看该库对应的数据库死锁日志,使用命令:show innodb engine status,过滤掉非重要的日志后如下:
------------------------
LATEST DETECTED DEADLOCK
------------------------
2025-08-20 23:34:29 0x7f958f1d5700
*** (1) TRANSACTION:
TRANSACTION 95146580, ACTIVE 2 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1136, 5 row lock(s), undo log entries 2
MySQL thread id 6264489, OS thread handle 140273305761536, query id 837446998 10.10.59.164 root updating
UPDATE test_table SET money = money + 5 WHERE user_id = 5
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 71816 page no 4 n bits 80 index idx_user_id of table `mall`.`test_table` trx id 95146580 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 8; hex 8000000000000005; asc ;;
1: len 8; hex 8000000000000006; asc ;;
*** (2) TRANSACTION:
TRANSACTION 95146581, ACTIVE 2 sec starting index read
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1136, 5 row lock(s), undo log entries 2
MySQL thread id 6264490, OS thread handle 140280327919360, query id 837446999 10.10.59.164 root updating
UPDATE test_table SET money = money + 4 WHERE user_id = 4
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 71816 page no 4 n bits 80 index idx_user_id of table `mall`.`test_table` trx id 95146581 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 8; hex 8000000000000005; asc ;;
1: len 8; hex 8000000000000006; asc ;;
Record lock, heap no 5 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 8; hex 8000000000000001; asc ;;
1: len 8; hex 8000000000000002; asc ;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 71816 page no 4 n bits 80 index idx_user_id of table `mall`.`test_table` trx id 95146581 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 8; hex 8000000000000004; asc ;;
1: len 8; hex 8000000000000005; asc ;;
*** WE ROLL BACK TRANSACTION (2)关键点总结如下:
1.该库中最近一次死锁发生的时间是什么时候?
4行:2025-08-20 23:34:29 0x7f958f1d5700
得知,最近一次死锁发生在 2025-08-20 23:34:29
2.该次死锁导致的两个事务的重要信息?
12行:RECORD LOCKS space id 71816 page no 4 n bits 80 index idx\_user\_id of table
mall.test_tabletrx id 95146580 lock\_mode X locks rec but not gap waiting
得知,事务 1 等待的锁为:lock\_mode X locks rec but not gap waiting24行:RECORD LOCKS space id 71816 page no 4 n bits 80 index idx\_user\_id of table
mall.test_tabletrx id 95146581 lock\_mode X locks rec but not gap
得知,事务 2 持有的锁为:lock\_mode X locks rec but not gap34行:RECORD LOCKS space id 71816 page no 4 n bits 80 index idx\_user\_id of table
mall.test_tabletrx id 95146581 lock\_mode X locks rec but not gap waiting
得知,事务 2 等待的锁为:lock\_mode X locks rec but not gap waiting39行:*** WE ROLL BACK TRANSACTION (2)
得知,最后回滚的是事务 1从 12、24、34 行:index idx\_user\_id of table
mall.test_table
得知:导致该次死锁的索引为:idx_user_id
3.能知道导致死锁的两个具体 SQL 吗?
不能,产生死锁的情况各式各样,事务中的 SQL 可能不止有两个 SQL,单从死锁日志是没法知道具体原因的,必须要结合业务代码查看事务上下文查看
二. 理论知识
排查过程中发现有个特点,影响的都是是线上的大用户。由于当时我很久没看死锁相关的理论知识,因此先去了解下相关死锁的基本知识。
2.1 死锁的条件
- 互斥条件:一个资源每次只能被一个进程使用。
- 占有且等待:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不可强行占有:进程已获得的资源,在末使用完之前,不能强行剥夺。
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
破坏死锁也很简单,四个条件破一个即可。(本案例是破坏的 4)
2.2 数据库的锁类型
数据库的死锁比较复杂,主要是由 Insert、Update(其实在开发中 Delete 或 For Update 是不怎么不考虑的,因为在实际业务代码中我们一般不会有 Delete 或 For Update 的操作,删除都是物理删除,for update 建议少用,除非你知道非用不可)。
InnoDB 的锁:
- 共享锁与独占锁(S、X)
- 意向锁
- 记录锁(Record Locks)
- 间隙锁(Gap Locks)
- Next-Key Locks
- 插入意向锁
- 自增锁
- 空间索引断言锁
这里参考了官网的 Innodb 锁分类,从死锁日志的 lock_mode X locks rec but not gap ,大致能知道,这里可能涉及了 X 锁、记录锁、间隙锁(但是有个 not,说明不涉及)。
三. 从死锁日志分析
分析之前先得到该表的建表语句:show create table test_table;:
CREATE TABLE `test_table` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`money` bigint(20) NOT NULL,
`user_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8接着结合死锁日志、锁的种类、建表语句得出以下模糊的结论:
3.1 从死锁日志的 10、12 行结合建表索引得知
10行:UPDATE test\_table SET money = money + 5 WHERE user\_id = 5
12行:RECORD LOCKS space id 71816 page no 4 n bits 80 index idx\_user\_id of tablemall.test_tabletrx id 95146580
事务1的 UPDATE test_table SET money = money + 5 WHERE user_id = 5 语句在等待锁:它通过普通索引 idx\_user\_id 更新,先获取了 user\_id=5 的 X 锁,接着去申请对应行的主键(Record Lock)的行锁但是被阻塞(waiting),并不包括间隙锁(not gap)。具体是哪个主键我们并不清楚。
3.2 从死锁日志的 22、24 行结合建表索引得知
22行:UPDATE test\_table SET money = money + 4 WHERE user\_id = 4
24行:Record lock, heap no 3 PHYSICAL RECORD: n\_fields 2; compact format; info bits 0
事务2的 UPDATE test_table SET money = money + 4 WHERE user_id = 4 语句在持有锁:它通过普通索引 idx\_user\_id 更新,先获取了 user\_id=4 的 X 锁,接着去申请对应行的主键(Record Lock)的行锁成功了,并不包括间隙锁(not gap)。具体是成功的哪个主键我们并不清楚。
3.3 从死锁日志的 22、34 行结合建表索引得知
22行:UPDATE test\_table SET money = money + 4 WHERE user\_id = 4
34行:RECORD LOCKS space id 71816 page no 4 n bits 80 index idx\_user\_id of tablemall.test_tabletrx id 95146581 lock\_mode X locks rec but not gap waiting
事务2的 UPDATE test_table SET money = money + 4 WHERE user_id = 4 语句在等待锁:它通过普通索引 idx\_user\_id 更新,先获取了 user\_id=4 的 X 锁,接着去申请对应行的主键(Record Lock)的行锁但是被阻塞(waiting),并不包括间隙锁(not gap)。具体是哪个主键我们并不清楚。
模糊结论肯定是有问题的,最大的问题在于导致的 SQL 语句不正确,即:死锁的原因是真实的,但是具体是因为哪些 SQL 导致的死锁是不清楚的。接着我们整理得到了以下可能有问题的表格:
| 事务1 | 事务2 |
|---|---|
| 某些 SQL | 某些 SQL |
| 某个 SQL 的 user\_id = 5 行更新操作被阻塞了 | 某个 SQL 的 user\_id = 4 获得了锁但是又阻塞了 |
| 某些 SQL | 某些 SQL |
可以得知,其实单从死锁日志分析是比较片面的,因为 user\_id 为 4、5 这两个 update 操作是不会有互相阻塞的问题,肯定是有别的 SQL 影响,我们需要额外从业务日志分析才能还原完整的现场。
四. 从业务日志分析
从死锁日志是不能完全知道导致的关键 SQL 和故障现场的整体流程,因此我们要借助业务日志来完成最后对故障现场的分析:
通过前面对业务日志的分析,我们知道最关键的调用方法是 BizManagerImpl.transactionMoney,查看对应源码:
@Override
@Transactional
public boolean transactionMoney(List<TransactionReqVO> transactionReqVOList) throws Exception {
for (TransactionReqVO transactionReqVO : transactionReqVOList) {
// 模拟业务操作
Thread.sleep(1000);
int updateCount = testTableService.update(transactionReqVO.getUserId(), transactionReqVO.getMoney());
if (updateCount == 0) {
log.error("转账异常:" + transactionReqVO);
}
}
return true;
}可以知道,应该是 for 循环事务的问题,但是具体是哪些 user\_id 是不清楚的,接着我们查看业务日志的上下文,通过全链路 traceId(模拟) 做搜索,得到以下的日志:
[ConsumerThread2] org.example.controller.TestController : 全局链路跟踪id:2的日志:[TransactionReqVO(userId=4, money=4), TransactionReqVO(userId=2, money=2), TransactionReqVO(userId=5, money=5)]
[ConsumerThread1] org.example.controller.TestController : 全局链路跟踪id:1的日志:[TransactionReqVO(userId=5, money=5), TransactionReqVO(userId=1, money=1), TransactionReqVO(userId=4, money=4)]分析到这一步,我们已经可以还原死锁场景了,事务流程图如下:
| 事务1 | 事务2 |
|---|---|
| UPDATE test\_table SET money = money + 4 WHERE user\_id = 4 | UPDATE test\_table SET money = money + 5 WHERE user\_id = 5 |
| UPDATE test\_table SET money = money + 2 WHERE user\_id = 2 | UPDATE test\_table SET money = money + 1 WHERE user\_id = 1 |
| UPDATE test\_table SET money = money + 5 WHERE user\_id = 5 | UPDATE test\_table SET money = money + 4 WHERE user\_id = 4 |
五. 业务日志、死锁日志结合分析
将死锁日志分析得出的不正确表格加上业务日志分析得出正确表格,我们得出最终带有理解的最终正确的事务表格:
| 事务1 | 事务2 |
|---|---|
| UPDATE test\_table SET money = money + 4 WHERE user\_id = 4 持有 user\_id 为 4 的行锁 | UPDATE test\_table SET money = money + 5 WHERE user\_id = 5 持有 user\_id 为 5 的行锁 |
| UPDATE test\_table SET money = money + 2 WHERE user\_id = 2 持有 user\_id 为 2 的行锁 | UPDATE test\_table SET money = money + 1 WHERE user\_id = 1 持有 user\_id 为 1 的行锁 |
| UPDATE test\_table SET money = money + 5 WHERE user\_id = 5 | <br/> |
| 阻塞中...等待持有 user\_id 为 5 的行锁解锁 | UPDATE test\_table SET money = money + 4 WHERE user\_id = 4 |
| 阻塞中...user\_id等待持有 user\_id 为 4 的行锁解锁 | <br/> |
| <br/> | 回滚 |
| 提交 | <br/> |
可以知道,其实死锁日志的 SQL 是模糊的,但是原因是正确的,至于具体是哪些 SQL 导致的死锁,是需要从业务日志来判定。
六、临时及长期解决方法
6.1 确认死锁事务SQL
数据库 SHOW ENGINE INNODB STATUS\G 显示死锁日志,确认存在循环等待。
6.2 临时处置措施
降低并发冲突
- 临时 限流/降级应用写操作,减少同时进入数据库的更新事务。
- 调整连接池/线程池大小,降低高峰期并发写入压力。
处理长事务
查询正在执行的事务:
SELECT * FROM information_schema.innodb_trx\G;- 对异常耗时过长的事务,执行:
KILL <thread_id>;索引检查
- 检查死锁 SQL 的
WHERE条件是否使用索引:
EXPLAIN UPDATE test_table SET money=money+5 WHERE user_id=5;如果未命中索引,考虑临时加索引或确认 user_id 为主键/唯一索引。七、后续优化
运维侧
- 建立 死锁监控:定期采集
SHOW ENGINE INNODB STATUS。 - 配置慢查询日志,定位高风险 SQL。
开发侧
对高并发热点表(如账户余额表)考虑:
- 消息队列串行化更新
- 分布式锁控制并发
- 分库分表/分区表,降低单点冲突
八、结论
- 临时解决:运维限流 + 杀长事务 + 调整隔离级别;开发增加重试机制。
- 根本优化:索引优化、访问顺序统一、事务拆分、应用架构调整。
- 本次死锁为 典型的并发更新不同记录但访问顺序相反 导致。
📌 责任部门:运维负责短期止血;开发负责应用层改造。
📌 下一步计划:
- 运维确认
user_id是否唯一索引/主键。 - 开发在代码中增加重试机制。
- 联合评估是否需要调整隔离级别或架构优化。
10 条评论
华纳公司官方开户渠道?(183-8890-9465)-薇-STS5099【6011643】
如何通过官方渠道申请华纳公司账户?(183-8890-9465)-薇-STS5099【6011643】
华纳总公司官方开户指南?(183-8890-9465)-薇-STS5099【6011643】
华纳公司官方开户所需材料?(183-8890-9465)-薇-STS5099【6011643】
华纳官方开户流程?(183-8890-9465)-薇-STS5099【6011643】
华纳公司官方开户申请步骤?(183-8890-9465)-薇-STS5099【6011643】
华纳官方开户指南?(183-8890-9465)-薇-STS5099【6011643】
华纳总公司官方开户?(183-8890-9465)-薇-STS5099【6011643】
华纳公司官方开户所需材料?(183-8890-9465)-薇-STS5099【6011643】
华纳官方开户申请流程?(183-8890-9465)-薇-STS5099【6011643】
寻找华纳圣淘沙公司开户代理(183-8890-9465薇-STS5099】
华纳圣淘沙官方合作开户渠道(183-8890-9465薇-STS5099】
华纳圣淘沙公司开户代理服务(183-8890-9465薇-STS5099】
华纳圣淘沙公司开户咨询热线(183-8890-9465薇-STS5099】
联系客服了解华纳圣淘沙开户
(183-8890-9465薇-STS5099】
华纳圣淘沙公司开户专属顾问
(183-8890-9465薇-STS5099】
华纳圣淘沙公司开户新手教程
零基础学会(183-8890-9465薇-STS5099)
华纳圣淘沙公司开户
华纳圣淘沙公司开户保姆级教程(183-8890-9465薇-STS5099)
一步步教你开通华纳圣淘沙公司账户(183-8890-9465薇-STS5099)
华纳圣淘沙公司开户分步图解
首次开户必看:(183-8890-9465薇-STS5099)
华纳圣淘沙全攻略
华纳圣淘沙公司开户实操手册(183-8890-9465薇-STS5099)
华纳圣淘沙开户流程视频教程
手把手教学:(183-8890-9465薇-STS5099)
华纳圣淘沙公司开户
华纳圣淘沙公司开户完全指南(183-8890-9465薇-STS5099)
东方明珠客服开户联系方式【182-8836-2750—】?μ- cxs20250806
东方明珠客服电话联系方式【182-8836-2750—】?- cxs20250806】
东方明珠开户流程【182-8836-2750—】?薇- cxs20250806】
东方明珠客服怎么联系【182-8836-2750—】?薇- cxs20250806】
东方明珠客服开户联系方式【182-8836-2750—】?μ- cxs20250806
东方明珠客服电话联系方式【182-8836-2750—】?- cxs20250806】
东方明珠开户流程【182-8836-2750—】?薇- cxs20250806】
东方明珠客服怎么联系【182-8836-2750—】?薇- cxs20250806】
华纳东方明珠客服电话是多少?(??155--8729--1507?《?薇-STS5099】【?扣6011643?】
华纳东方明珠开户专线联系方式?(??155--8729--1507?《?薇-STS5099】【?扣6011643?】
华纳东方明珠客服电话是多少?(??155--8729--1507?《?薇-STS5099】【?扣6011643?】
华纳东方明珠开户专线联系方式?(??155--8729--1507?《?薇-STS5099】【?扣6011643?】
华纳东方明珠客服电话是多少?(▲18288362750?《?微信STS5099? 】
如何联系华纳东方明珠客服?(▲18288362750?《?微信STS5099? 】
华纳东方明珠官方客服联系方式?(▲18288362750?《?微信STS5099?
华纳东方明珠客服热线?(▲18288362750?《?微信STS5099?
华纳东方明珠24小时客服电话?(▲18288362750?《?微信STS5099? 】
华纳东方明珠官方客服在线咨询?(▲18288362750?《?微信STS5099?
2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com
2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com