纯情博客为您提供最新网络安全黑客博客信息资讯

  前言

  今天就和大家聊一聊如何在日常开发中减少bug? 本文将从数据库、代码层面、缓存使用三大方向总结共计50多个关注点,帮助大家成为开发品质之星。

  1.数据库

  慢查询

  数据库章节,哪些地方容易出bug? 我总结了7个方面:慢查询、数据库字段注意点、事务失败场景、死锁、主从延迟、新旧数据兼容、一些SQL经典注意点。

  1.1 慢查询

  慢查询.gif1.1.1是否命中索引

  说到慢查询,我们马上就会想到索引。 如果一个SQL没有索引,或者没有命中索引,就会产生一个慢查询。

  什么情况下索引会失效

  1.1.2 数据量大,考虑分库分表

  如果单表数据量过大脚本源码,会影响SQL执行的性能。 我们知道,索引数据结构一般是B+树,一棵高度为3的B+树可以存储大约2000万条数据。 如果超过这个数,B+树会变高,查询性能会下降。

  因此,当数据量较大时,建议将数据库分表。 分库分表的中间件包括mycat、-jdbc

  1.1.3 不合理的SQL

  在日常开发中,笔者见过很多不合理的SQL:比如一条SQL居然用了6个表连接,表太多会影响查询性能; 又比如一张表,实际上加了10个索引等,索引会降低插入和更新SQL的性能,所以一般不建议索引太多,一般不要超过5个。

  1.2 数据库字段注意事项

  数据库字段的内容容易出现bug。 比如你在测试环境修改了表结构,增加了某个字段,生产环境忘记带脚本,那肯定是版本有问题。

  1.2.1 字段是否会过长

  假设您的数据库字段是:

  

`name varchar(255) DEFAULT NOT NULL    `

  如果请求参数自带变量名,字段长度为300,插入表时会报错。 因此需要对参数进行校验,防止字段过长。

  1.2.2 如果字段为空,会不会造成空指针

  我们在设计数据库表字段的时候,尽量把字段设置为not null。

  如果数据库字段设置为NULL值,很容易导致程序出现空指针; 如果数据库字段设置为NULL值,需要注意使用count(特定列),会有陷阱。

  1.2.3 缺失字段

  对于我们日常的开发任务,如果我们在测试环境修改表,比如增加新的字段,我们必须把SQL脚本带到生产环境,否则字段会丢失,发布时就会出现问题。

  1.2.4 字段类型是否支持表情

  如果表字段需要支持表达式存储,使用 .

  1.2.5 谨慎使用文本和blob字段

  如果您要在字段中存储文件,请考虑存储文件的路径而不是保存整个文件。 使用文本时,注意在查询条件时创建前缀索引。

  1.3 事务失败的场景 1.3.1 @ on non-

  @注解,添加到非修饰方法时,事务不会生效。 事务是基于AOP的思想,也是通过动态代理实现的。 事务本身在调用动态代理之前,已经过滤了非方法,所以非方法,事务不会生效。

  1.3.2 本地方法直接调用

  在下面的场景中,@ 也是无效的

  

public class TransactionTest{      public void A(){        //插入一条数据        //调用方法B (本地的类调用,事务失效了)        B();      }            @Transactional      public void B(){        //插入数据      }    }    

  1.3.3异常被try...catch吃掉,导致事务失败。

  

@Transactional    public void method(){      try{        //插入一条数据        insertA();        //更改一条数据        updateB();      }catch(Exception e){        logger.error("异常被捕获了,那你的事务就失效咯",e);      }    }        

  1.3.4 属性设置错误

  默认抛出未检查异常(继承异常)或Error来回滚事务; 其他异常不会触发回滚事务。 如果事务中抛出其他类型的异常,则需要指定该属性。

  1.3.5 底层数据库引擎不支持事务

  存储引擎不支持事务,支持事务

  1.3.6 事务和业务逻辑代码必须在一个线程中

  业务代码必须和事务的源码在同一个线程中才能被事务控制。 比如下面的代码,方法的子线程,内部的事务操作都不会被方法上的事务控制。 每个人都应该注意这一点。 这是因为在事务实现中使用它来实现同一个线程中的数据共享。

  

@Transactional    public void mothed() {        new Thread() {          事务操作        }.start();    }    

  1.4 死锁

  死锁是指两个或多个事务在同一个资源上相互占用wordpress插件,并请求锁定对方的资源,从而形成恶性循环的现象。

  MySQL内部有一套死锁检测机制。 一旦发生死锁,它会立即回滚一个事务,让另一个事务继续执行。 但是带数据库的网站源码,死锁存在资源利用率降低、进程无法获得正确结果等危害。

  1.4.1 SQL锁9种情况分析

  为了避免死锁,你需要学会分析:SQL锁是如何工作的? 可以在九种情况下讨论 SQL 锁:

  1.4.2 如何分析和解决死锁?

  分析和解决死锁的步骤如下:

  有兴趣的朋友可以看看我之前写的这篇文章:教你分析Mysql死锁问题

  1.5 主从延时注意事项

  先插入,后查询。 这种代码逻辑比较常见,可能会有问题。 一般数据库有主库和从库。 写是写到主库,读一般是从库读。 如果出现主从延时,很有可能你已经插入成功,但是无法查询。

  1.5.1 需要强一致性,考虑阅读主库

  如果是重要业务,需要强一致性,考虑直接读主库

  1.5.2 不需要强一致性,从库中读取

  如果是一般业务,可以接受暂时的数据不一致,优先从库读取。 因为从库可以分担主库的读写压力,提高系统吞吐量。

  1.6 新旧数据兼容1.6.1新增字段,考虑股票数据默认值

  在我们的日常开发中,随着业务需求的变化,我们经常需要在某个数据库表中添加一个字段。 比如在一个APP配置表中,需要增加一个场景编号字段,比如它的枚举值为01、02、03,那么我们要和业务对齐,新增的字段,默认值是多少旧数据的,是空的还是默认01。如果是NULL,程序代码必须处理空指针。

  1.6.2 如果新业务使用旧字段,考虑旧数据的值是否有坑

  如果开发时需要继续使用数据库表的老字段,有股票数据,就需要考虑老股票数据库的值是否存在陷阱。 比如我们的表中有一个字段。 在旧数据中,它的枚举值为01:超级管理员 02:管理员 03:普通用户。 假设业务需求是一般用户分为03查询用户和04操作用户,那我们在开发的时候就得考虑旧数据值的问题。

  1.7 一些经典SQL注意点 1.7.1 限制大分页问题

  limit large 是一个非常经典的SQL问题,我们一般都有这三种对应的解决方案

  方案一:如果id是连续的,可以返回上次查询的最大记录(偏移量),然后往下限制

  

select id,name from employee where id>1000000 limit 10.    

  选项 2:如果业务允许,限制页数:

  建议和业务商量,最后是否需要检查分页。 因为绝大多数用户是不会翻太多页的。 搜索页面也限制了页面数量,所以不存在限制大分页的问题。

  方案三:使用延迟关联或者子查询来优化超多分页场景。 (先快速定位到需要获取的id段,再进行关联)

   带数据库的网站源码

带数据库的网站源码

  

SELECT a.* FROM employee a, (select id from employee where 条件 LIMIT 1000000,10 ) b where a.id=b.id    

  1.7.2 当修改和查询大量数据时,考虑批处理。

  我们在更新或者查询数据库数据的时候,尽量避免循环操作数据库,可以考虑分批进行。 比如要插入10万条数据,一次插入500条带数据库的网站源码,执行200次即可。

  正例:

  

remoteBatchQuery(param);    

  反例:

    for(int i=0;i