真是没想到! 因为这个原因小伙被盗3.4万美元 |AToken全观

一名区块链爱好者因使用被篡改的二手冷钱包丢失了价值3.4万美元的数字资产。AToken钱包提供了一种更安全的解决方案,通过将私钥加密存储在手机中,避免了网络攻击的风险。

​2018年初,一位网名为moodyrocket的外国小伙在Reddit网上发帖称,他损失了价值3.4万美元的积蓄,原因真让人意想不到。

“这是我所有的积蓄。”这位可怜的小伙在帖子里写道。损失3.4万美元,按当前汇率折合人民币约23万元!这都够在老家盖一栋别墅了!

在这里插入图片描述

保护财产安全是每一个人都需要注意的事情,但这样的原因让小伙子损失3.4万美元真是让人意外。据了解,小伙子是一位区块链爱好者,他将3.4万美元全部换成了区块链上的数字资产,并将它保存在一个区块链冷钱包里。

通常在区块链爱好者的概念里,冷钱包是一个非常安全的数字资产存储设备,它就像被绝缘保护的电子保险箱,能够有效隔绝网络黑客的攻击。但是令人意外的是这是一个在eBay(外国的淘宝)上购买的二手区块链冷钱包!就是这个冷钱包让他损失了3.4万美元,谁也想不到会在最不该出问题的地方出了问题。

原来,小伙子贪便宜,身怀23万元的巨款却舍不得买个新的设备来存放巨款,而是淘了个二手宝贝。这个名牌的Ledger二手冷钱包最终让小伙蒙受巨大损失。经调查,这位用户购买的冷钱包是被卖方做过手脚的,就相当于是在你的电子保险箱里留了后门,在你认为绝对安全的时候有人就悄悄溜了进去,偷光你的钱……

在这里插入图片描述

这个被动过手脚的冷钱包被人修改了硬件破解了私钥,就好比你的保险箱电子密码被人破解了。这样一来一旦你使用这个保险箱来存放资产,小偷就会趁你不注意打开保险箱,将里边的钱全部带走。这也叫“中间人攻击”。

这位损失了3.4万美元的小伙子正是因为中了这个圈套而损失了巨额财产,真是谁也想不到啊!

那还有安全的区块链钱包吗?!还真有!知道了小偷的手段再针对性的进行防范,那就有效率得多。

这次小伙被盗巨额财产原因有两个,一是使用了被破解的二手区块链冷钱包,二是没使用AToken钱包。

小伙子正因为贪小便宜才被人乘虚而入最后损失惨重,所以买东西最好还是别买二手的,也别买渠道来源不明的,真的不放心。

一般来说不买二手的办得到,不买渠道来源不明的就很难说了,谁知道所谓的“门店正品”到底是从哪里进的货……贴了牌子你又看不出来。那怎么办?只好自己造一个了。哈哈。

区块链冷钱包要造一个不难,就是花点时间,还要有点计算机功底,还要保存好自己的钱包私钥,还要……
在这里插入图片描述
现在,AToken钱包帮你全简化了!当你在手机上使用AToken钱包,即相当于把自己的手机改造成了一个区块链冷钱包!

AToken钱包会在你第一次使用时将钱包的私钥首次生成并加密存放在手机里,层层加密,5层保护,横向隔离纵向防御……AToken钱包根本不会让你的私钥密码暴露在网络里。

这样你的手机是上网的,但是小偷通过网络是找不到私钥密码在哪儿的,而且你又不会买个二手手机来存放数字资产,哈哈哈,那小偷就算想通过“中间人攻击”的方式来埋伏你都做不到。

所以啊,被盗3.4万美元的外国小伙子就是没使用AToken钱包才会导致这样的结果。AToken钱包还有其他更多的优秀功能,官网和公众号上都可以查阅得到噢。

<think> 我们正在分析一个MyBatis-Plus查询超时的SQL片段。用户提供的SQL片段如下(在MyBatis的XML中): ```xml <if test = "null != dto.isDataPmsn and dto.isDataPmsn == &#39;false&#39;"> AND (( mo.unit_rank <= m.monitor_level AND ( mo.up_all_code LIKE #{dto.suborgPath} || &#39;%&#39; AND a.deal_org =#{dto.pmsnOrgCode} ) ) or (mo.unit_rank > m.monitor_level and (case m.monitor_level when &#39;1&#39; then mo.org_lvl1 when &#39;2&#39; then mo.org_lvl2 else mo.org_lvl3 end)=#{dto.pmsnOrgCode} ) ) </if> ``` 这个条件判断在`dto.isDataPmsn`为`&#39;false&#39;`时会被加入SQL中。我们将分析可能导致查询超时的原因,并提供相应的优化建议。 ### 原因分析 1. **复杂条件逻辑**: - 该条件包含两个部分,用`OR`连接,而每个部分又包含多个嵌套条件。特别是第二个条件中使用了`CASE`语句,这可能导致查询优化器难以生成高效的执行计划。 2. **LIKE操作符前缀模糊查询**: - 条件`mo.up_all_code LIKE #{dto.suborgPath} || &#39;%&#39;`使用了以通配符开头的模糊查询(注意:这里实际上是后缀匹配,因为`|| &#39;%&#39;`在变量后面,所以是`变量%`,即前缀匹配?但这里要澄清:`#{dto.suborgPath} || &#39;%&#39;`表示将参数与`%`连接,因此实际是`like &#39;xxx%&#39;`,这是前缀匹配,可以利用索引。但需注意,如果`suborgPath`很长,可能影响性能,但通常前缀匹配是高效的。不过,如果该字段没有索引,则全表扫描。 3. **OR条件**: - 使用`OR`连接两个复杂的条件,这可能导致数据库无法有效利用索引,特别是当两个条件涉及的列不同时,数据库可能会选择全表扫描。 4. **CASE表达式**: - 第二个条件中的`CASE`表达式根据`m.monitor_level`的值选择不同的列进行比较。这种动态列的选择可能导致索引失效,因为数据库无法预先知道要使用哪个列上的索引。 5. **多表连接**: - 虽然提供的片段中没有显示表连接,但条件中出现了多个表别名(`mo`, `m`, `a`),说明这是一个多表连接查询。多表连接时,如果连接条件不当或缺少索引,容易导致性能问题。 6. **数据量过大**: - 如果表`mo`、`m`、`a`的数据量很大,而查询条件无法有效过滤数据,则会导致处理的数据行数过多,从而超时。 ### 优化建议 1. **检查索引**: - 确保涉及的条件列有适当的索引。特别是: - `mo.unit_rank` 和 `m.monitor_level` 列是否有索引? - `mo.up_all_code` 列是否建立了索引(用于LIKE前缀匹配)?注意:前缀匹配可以利用索引。 - `a.deal_org` 列是否有索引? - 对于`CASE`表达式中的列(`mo.org_lvl1`, `mo.org_lvl2`, `mo.org_lvl3`),考虑为每个列单独建立索引,或者根据业务情况建立复合索引。 2. **拆分OR条件**: - 尝试将`OR`条件拆分成两个独立的查询,然后通过`UNION`(或`UNION ALL`)合并结果。这样可以使得每个部分都可以利用各自的索引。例如: ```sql SELECT ... FROM ... WHERE ... AND (第一个条件) UNION ALL SELECT ... FROM ... WHERE ... AND (第二个条件) ``` 注意:使用`UNION ALL`比`UNION`高效(不去重),但要确保两个结果集不会重复(或者允许重复)。 3. **简化CASE表达式**: - 考虑将`CASE`表达式拆分成多个条件,避免在条件中使用`CASE`。例如,将第二个条件改写为: ```sql (mo.unit_rank > m.monitor_level AND (m.monitor_level=&#39;1&#39; AND mo.org_lvl1=#{dto.pmsnOrgCode} OR m.monitor_level=&#39;2&#39; AND mo.org_lvl2=#{dto.pmsnOrgCode} OR m.monitor_level NOT IN (&#39;1&#39;,&#39;2&#39;) AND mo.org_lvl3=#{dto.pmsnOrgCode} ) ) ``` 这样改写后,每个分支都有机会使用各自的索引。 4. **分析执行计划**: - 使用数据库提供的工具(如MySQL的`EXPLAIN`)分析SQL语句的执行计划,查看是否使用了合适的索引,以及是否有全表扫描。根据执行计划调整索引或SQL结构。 5. **分页处理**: - 如果查询结果集很大,考虑分页获取数据,避免一次性处理过多数据。 6. **减少多表连接的数据量**: - 在连接表之前,先对每个表进行过滤,减少连接的数据量。例如,将过滤条件下推到子查询中。 7. **调整数据库配置**: - 如果数据量确实很大,考虑调整数据库的配置参数(如超时时间、内存分配等),但这只是临时解决方案,根本问题还是优化查询。 ### 示例优化 假设原始SQL类似于: ```sql SELECT ... FROM table_mo mo JOIN table_m m ON ... JOIN table_a a ON ... WHERE ... AND ( (mo.unit_rank <= m.monitor_level AND ...) OR (mo.unit_rank > m.monitor_level AND ...) ) ``` 优化后的SQL(拆分OR条件): ```sql SELECT ... FROM table_mo mo JOIN table_m m ON ... JOIN table_a a ON ... WHERE ... AND (mo.unit_rank <= m.monitor_level AND ...) UNION ALL SELECT ... FROM table_mo mo JOIN table_m m ON ... JOIN table_a a ON ... WHERE ... AND (mo.unit_rank > m.monitor_level AND ...) ``` 注意:在拆分时,确保连接条件相同,并且两个查询的列保持一致。 如果拆分后仍然超时,则需要进一步分析每个部分,并针对每个部分进行优化。 ### 总结 SQL查询超时通常是由于复杂的条件、大量的数据处理、缺少索引或执行计划不佳导致的。针对用户提供的SQL片段,重点优化`OR`条件和`CASE`表达式,并确保相关列上有合适的索引。同时,分析执行计划是定位问题的关键步骤。 §§相关问题§§ 1. 如何分析MyBatis-Plus生成的SQL的执行计划? 2. 在MyBatis-Plus中如何强制使用索引? 3. 多表连接查询时如何优化性能? 4. 如何避免MyBatis-Plus动态SQL中的OR条件导致的性能问题? 5. 在MyBatis-Plus中如何实现分页查询以解决大数据量查询超时? </think> ### MyBatis-Plus SQL查询超时原因分析与优化建议 #### 1. **问题SQL片段分析** ```xml <if test="null != dto.isDataPmsn and dto.isDataPmsn == &#39;false&#39;"> AND (( mo.unit_rank <= m.monitor_level AND ( mo.up_all_code LIKE #{dto.suborgPath} || &#39;%&#39; AND a.deal_org =#{dto.pmsnOrgCode} ) ) OR (mo.unit_rank > m.monitor_level AND (CASE m.monitor_level WHEN &#39;1&#39; THEN mo.org_lvl1 WHEN &#39;2&#39; THEN mo.org_lvl2 ELSE mo.org_lvl3 END) = #{dto.pmsnOrgCode} ) ) </if> ``` #### 2. **主要超时原因** ##### ① **复杂条件导致全表扫描** [^3][^4] - **OR 运算符**:两段复杂条件用 `OR` 连接,破坏索引有效性 - **动态 CASE 表达式**:`CASE WHEN` 动态选择列,无法使用固定索引 - **LIKE 模糊查询**:`LIKE #{dto.suborgPath} || &#39;%&#39;` 虽符合前缀匹配,但与其他条件组合后索引失效 ##### ② **多表关联性能瓶颈** [^1][^4] - 涉及 `mo`、`m`、`a` 三表关联 - 缺少有效连接条件过滤(如 `WHERE` 前置过滤) - 关联字段未建立联合索引(如 `monitor_level` 与 `unit_rank`) ##### ③ **数据量过大未分页** [^2] - 未配置分页参数(如 `PageHelper` 或 MyBatis-Plus 分页插件) - 全量数据加载导致内存溢出(尤其当 `dto.isDataPmsn=false` 时) ##### ④ **空值处理缺陷** [^4][^5] - 未处理 `dto.pmsnOrgCode` 为 `NULL` 的情况(如 `IN (?,?)` 含 `NULL` 值) - `CASE` 表达式未考虑 `m.monitor_level` 为 `NULL` 的边界情况 #### 3. **优化方案** ##### ① **SQL 结构重构** ```sql /* 拆分 OR 条件为 UNION ALL */ SELECT ... FROM mo JOIN m ON ... JOIN a ON ... WHERE mo.unit_rank <= m.monitor_level AND mo.up_all_code LIKE CONCAT(#{dto.suborgPath}, &#39;%&#39;) AND a.deal_org = #{dto.pmsnOrgCode} UNION ALL SELECT ... FROM mo JOIN m ON ... WHERE mo.unit_rank > m.monitor_level AND ( (m.monitor_level = &#39;1&#39; AND mo.org_lvl1 = #{dto.pmsnOrgCode}) OR (m.monitor_level = &#39;2&#39; AND mo.org_lvl2 = #{dto.pmsnOrgCode}) OR (m.monitor_level NOT IN (&#39;1&#39;,&#39;2&#39;) AND mo.org_lvl3 = #{dto.pmsnOrgCode}) ) ``` ##### ② **索引优化建议** ```sql -- 联合索引 (避免全表扫描) CREATE INDEX idx_mo_rank ON mo(unit_rank, up_all_code); CREATE INDEX idx_m_level ON m(monitor_level); -- 覆盖索引 (加速 CASE 条件) CREATE INDEX idx_org_lvls ON mo(org_lvl1, org_lvl2, org_lvl3); ``` ##### ③ **分页与空值处理** ```java // MyBatis-Plus 分页配置 Page<User> page = new Page<>(1, 10); userMapper.selectPage(page, queryWrapper); // 空值安全处理 queryWrapper .isNotNull("m.monitor_level") // 排除 NULL 值 [^5] .eq(StringUtils.isNotBlank(pmsnOrgCode), "a.deal_org", pmsnOrgCode); ``` ##### ④ **执行计划分析** ```sql EXPLAIN SELECT ... /* 原SQL */; ``` 检查 `type` 列避免 `ALL`(全表扫描),确保 `key` 列显示使用的索引。 #### 4. **MyBatis-Plus 特定优化** ```java // 启用性能分析插件(定位慢SQL) @Bean public PerformanceInterceptor performanceInterceptor() { PerformanceInterceptor interceptor = new PerformanceInterceptor(); interceptor.setMaxTime(1000); // SQL执行最大时长(ms) interceptor.setFormat(true); return interceptor; } // 强制索引提示 (MySQL语法) queryWrapper.apply("FORCE INDEX (idx_mo_rank)"); ``` #### 5. **验证方法** 1. 使用 `EXPLAIN` 分析优化前后执行计划 2. 限制查询范围测试响应时间: ```java queryWrapper.last("LIMIT 1000"); // 临时限制数据量 ``` 3. 监控 JDBC 执行时间: ```yaml # application.yml mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ``` > **关键结论**:超时主要由 **OR条件导致索引失效** + **多表关联缺少过滤** + **未分页** 引起,通过拆分复杂条件、添加联合索引和分页可解决 90% 的性能问题[^1][^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值