别人手牵手-我牵我的狗
异常是什么?程序运行过程中超出预期行为都属于异常。
在进行运算( computation)时,出现例外的情况(需要特殊处理的非常规或例外的情况)对应的处理,这种情况经常会破坏程序正常的流程。它通常由特殊的编程语言结构、计算机硬件机制(如:中断或者如信号等操作系统IPC设施)所构成的。具体实现由硬件和软件自身定义而决定。一些异常,尤其是硬件,将会在被中断后进行恢复。如果某个查询方法应当返回一条记录,但是查出来多条应该如何处理?
程序设计的第一要求就可以保证用户的正常使用。应当返回一条数据,但出现了多条数据,出现这种情况有很多种原因,业务出现问题,数据本身出现脏数据。
此时最好的处理方式,应该保证程序的正常运行,记录告警消息。需要有检查异常消息的机制,可以及时跟踪异常日志。
极客架构
你好,我是一名撸码老手,很高兴能回答你的问题,对于程序中本应返回一条记录的方法,结果返回了多条的情况,我是强烈建议先抛异常,然后查找问题,最后解决问题。
前言
不知道大家有没有看过《少年包青天》,这部经典的国产悬疑推理片告诉我们一个道理,不管遇到什么样的问题,总有它的起因,当然最终也会尘埃落定,因为真相只有一个。
同样的,在我们写程序的时候也会遇到这样那样的问题(或者说Bug更符合撸码身份),有时候我们会很烦,甚至想要一度地忽视它,但是它就像一颗雷一样地暗藏在那里,随时都有可能爆掉,可能在调试的时候,也有可能在测试的时候,当然更有可能在上线的时候。
虽然我们总是掩耳盗铃般地慰藉自己,没事的,一个小小的Bug而已,影响不大,但有时候就是因为这个小小的Bug可能会损失惨重,这不是夸大其词,真的是真人真事,曾经有同事因为电话号码位数的设置不合理,导致手机没法接拨部分国外地区的电话,从而使得已量产的手机全部返工,损失不小。
所以不管遇到什么样的问题,我们都不要抱侥幸心理,要知道墨菲定律无时无刻都在我们身边,我们要尽量杜绝所有可能发生的情况,特别是不要忽视已经出现的问题。
实战剖析
一、抛出异常,问题复现
我们假设自己就是那个线上正在操作的幸运儿,操作得正嗨的时候,突然嘣地一声给你弹了个异常提示框,然后怎么办?火急火燎地找客服,然后客服把问题反馈给测试验证,本地验证没问题啊,还是叫开发看一下吧,开发看了错误日志,基本锁定是数据库查询出问题了,本来用的是selectOne方法查询的,结果查出来的是List,从而导致异常。
在这里,可能有的小伙伴就建议,没事干嘛抛个异常呀,太不友好了,如果有多条记录,叫开发取最新的那条就好了,对此,我想说,遇到问题,我们要虚心接受并着手解决,而不是规避或逃避问题,当只能有一条记录的时候,那无论如何都得有且只有一条,而不能特意地去投机取巧,不然可能会爆发更严重的问题。
- 除此之外,我们也要安抚一下那个幸运儿的情绪,并且在一定的酌情考虑下,可以广发英雄帖,发现问题者给予一定的奖励,我想大部分的幸运儿都乐意为之的。
二、查找问题根源
发现问题后,开发就百思不得其解,这明明只会有一条记录的啊,怎么会在数据库出现多条呢,哪里出了问题,代码?人工?误操作?根据我多年的经验以及曾经遇到过类似的问题,来说说可能的情况。
1、有人误动了数据库,人为地添加了多条数据。(一般人可能没这个权限,可能性小)
2、新增该记录的接口操作引起。(如果没处理好,高并发情况下可能性很大)
3、其它定时或其它接口操作引起。(如果查询的记录所在的数据库表在其它接口也使用,那这种可能性还是存在的)
以上几点最有可能的是第2点,因为在高并发的情况下,如果没有把锁处理好,以及网络延迟的情况下是很可能同时插入多条数据的。
三、解决问题
查到了问题的根源,我们就应该一一排查及解决问题,这才是最终问题尘埃落定的时候。
1、核查人员,查找记录,确认无人动数据库。
2、在新增记录的时候,特别是高并发场景,一定要设好互斥锁,要么做悲观锁,要么做乐观锁,要么通过缓存来存储该操作动作,确保某一时刻只有一次操作,然后数据库可以根据某个字段做一下唯一键控制。
3、仔细查看及分析其它可能引起该记录所在数据库表的操作代码。
经过以上几点排查及处理,我想问题应该已经寿寝正终了。
总结
作为程序猿,遇到Bug不用怕,这只是正常的情况而已,如果开发一个项目一点Bug都没有,那就真的不敢想象了,遇到问题,查找原因,解决问题,这才是我们该做的。
都市心声
本人10年开发培训经验,期间经历了Java Web,Android,H5,大数据,PHP等多个不同的方向的开发,也做过软件培训公司的金牌讲师,很有兴趣回答你这个问题。
你这个问题已经把需求说明的很清楚了,”某个查询方法应当返回一条记录,但是查出来多条“!也就是说,你的这个查询只应该有一个结果,但是在此时或者某些时候有了多个结果,那么就说明你的这个业务接口可能不符合幂等性要求啊。根据幂等性设计原则,无论你怎么查,只要参数一样,返回结果应该一样。
那么对于这种问题该怎么解决,抛出异常?返回多条中的第一条?
我觉得都不是很完美的解决方案。
抛异常,这是有些人的一种解决方式,但是问题解决了吗?没有啊!问题还在那里,下次触发了这个条件,还是会抛异常。这就好比说,森林里有只虎,有一天吃了人,然后你不去解决老虎,只是在森林里挂了个牌子说:慎入,里面有虎!这......
然后返回多个结果中的第一条,其实这也不是一种好办法,可能本就应该只返回一条,为什么查询到了多个呢?你数据库里数据的唯一性做了校验了吗?不说别的,每次都查询多个结果然后拿第一条数据,你不觉得这很影响效率吗?
所以要从根源上解决问题!为什么会导致数据有多条?该人工排查数据就人工排查,该加锁就加锁,尽可能保证查询时入参一样,结果也一样!
我从事互联网开发10年,主要的研究方向集中在Java web微服务架构领域,Android移动端研发,HTML5前端方向,我会陆续写一些关于互联网技术方面的文章,感兴趣的朋友可以关注我,相信你一定会有所收获。
如果有Java,Android,H5等开发方面的问题,或者是开发求职方面的问题,都可以在评论区留言,或者私信我。
一一哥Sun
如果某个查询方法应当返回一条记录而查出来多条,那么你第一件要做的事情就是抛出异常,其次要考虑是不是有bug存在于你的软件系统中。
抛出异常
抛出异常是为了保护程序,保护用户,保护公司。
假设你是一个登录系统,需要通过查询用户名来让用户进行登录操作,但是查询方法却查出了两个用户,这个时候你不可能随便选一个用户登录。
假设你是一个银行系统,有一个用户A来取钱,银行系统需要通过银行卡号来获取用户A的余额信息。当用户A插入银行卡后,银行系统开始查询用户信息,但是查询方法却返回了两个用户信息,这个时候你不可能随便选一个用户。
假设你是一个快递系统,需要通过单号来查询派送地址信息,但是当你调用查询方法一个单号却出现两个收货地址,这个时候你不可能随便选一个地址让快递小哥去派送。
考虑bug
当程序执行的结果和你的预期不相同时,你就需要考虑是不是出现了bug。
这个bug可能出现在与你系统任何的角落,此时你需要做的事情就是去一步步调试去定位bug,然后去解决它。
比如说上面的快递系统,你要考虑为什么一个订单出现了两个收货地址,是因为存入数据库时出了差错还是读取数据库时出了差错或者是其他什么可能的原因,总之你要不断地去设想和验证才能快速的解决bug。
结论
综上,当一个方法应当返回一条数据但实际却返回多条时,我的答案就是果断抛出异常保护系统保护用户保护公司。
羊羽科技说
具体业务具体分析,两害相比取其轻。
1,抛异常用户就看不到数据,感觉很不爽,说你不专业,可能对公司形象有不利影响。
2,取第一条数据可能,
得到正确的结果,皆大欢喜
得到错误的结果,这个数据错误除了让用户一头雾水,没啥糟糕的结果。
得到错误的结果,但会造成错误进一步扩大,比如做出错误的决策,一条错误数据会导致产生多条错误数据,那可能会付出更多的时间去纠正错误数据,得不偿失。
你可以让用户不爽,但不能给用户造成损失
你可以适当让用户发发牢骚,但不要给自己找太多的麻烦
但一定要在第一时间得到通知,记日志,发邮件,在用户反应过来之前改掉。
疯喵
看业务需求
- 如果是需要精准数据的话,抛异常无疑。
- 如果需要的是模糊数据,对于准确性不高,那么可以随意获取一条。
根源解决
接口和得到的数据不统一,如果接口使用正确的话,肯定是数据库问题,为了业务稳定性,这个一定要解决的。
K哥聊科技
这个要看数据的重要性而定。金融级数据(和钱有关系的)没有二话,直接报异常。如果异常多了,甚至做熔断。但是有些数据是非敏感性的数据,比如操作历史。最常用的方法是取最近的一条记录返回。同时,记录在错误日志里
Adam_Luo
既然已知现象,就应直接程序处理。抛异常是甩包袱行为,而且触发异常的反应很慢。对这种已知的情况,设计程序逻辑,预先定义如何取结果,或者弹窗口临时让用户决定,都好过抛异常。异常了,还是没决定到底该怎么办,除了结束程序,你还能怎么样?下次还抛。我不欣赏那种让程序用异常来处理错误的做法,认为那是懒政,你编程就是要处理各种错误和修复的,动不动抛异常终结程序,要你何用。
TonyDeng
这个必须抛异常!按正常逻辑不该出现重复的数据,出现了重复,要么程序处理中有BUG,要么数据库损坏了。如果是前者,有可能是内存泄露,假如对安全性要求高的话,应立即关闭系统以防出现数据泄露的严重后果。如果是后者就更糟糕了,这等于损坏了用户财产,为了防止损失扩大,也应立即停止系统运行,及时分析原因。
以上,说的是上线之后的应对措施。如果还在开发,也应假如相应的异常处理机制才好。
日冲信息 黄
既然你能预料到可能会查询出多条数据,那说明是你的框架设计出现了漏洞,作为一个严谨的程序员,你应该改善自己的设计,避免这种情况的发生。如果实现难以避免,那也应该用适当的方式让他通知你这里有错误了