日常开发中如何减少bug?将从数据库、代码层面、缓存使用篇
纯情博客为您提供最新网络安全黑客博客信息资讯
前言
今天就和大家聊一聊如何在日常开发中减少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