问题描述
请教各位大神,对于从数据库查询一些数据,然后根据这些数据进行判断,判断通过再做数据插入或更新操作。那如果两个页面同时提交请求,就有可能存在数据判断时,这两个请求都是符合要求的,但是当最终数据更新到数据库中之后,数据就可能存在问题了。像这种情况一般是通过什么办法解决的?
解决方案
解决方案二:
传统上,数据库采用事务的方式来保持会话同步,来达到数据一致性。在你使用ado.net编程时,通过显式使用DbTransanction来将多个程序语句放到一个“数据库实务操作”范围内来处理。数据库系统默认的事务隔离级别,一般来说都是在一个事务中自动去禁止其它事务读取本事务已经访问过的记录,以此避免脏读、幻象读。这是传统上的做法。不过最近几年随着大规模电商的兴起,特别是互联网大型公司“去IOE潮流”的兴起,传统数据库做法被逐渐诟病了。例如用很低档次的电脑组成的服务器集群,例如用20万的投资,可以做硬软件投资200万的专用服务器和数据库系统的业务处理操作,而且速度还能提高几十倍。因此,实际上现在时兴的做法是用程序员的智慧、自己设计高效率的业务数据同步算法,来尽量避免滥用数据库事务加锁。甚至现在许多地方都讲究“最终一致性”而不是“数据库事务”。
解决方案三:
你的问题比较宽泛而没有具体业务应用场景,我也就随便举几个简单的例子来说。比如说有人说要什么“各个终端的业务流水号都是连续的”。你看到淘宝上的订单的流水号全都是连续的吗?这一个不科学的所谓空想,程序员自认为“真的好高大上啊”的想法,就会把淘宝网整垮!因此从业务分析上设计,去掉不合理的所谓约束,那“计算机脑袋”重新改为更合理的“业务的脑袋”这是第一步。一个服务器上的订单流水号是可以在进程内使用lock方式来同步的(而且也只是为订单号+1的操作进行lock,处理订单部分并不lock),于是订单就可以是“服务器编号+流水号”这样的形式。于是你看到,订单号至少是根据每一个服务器编号,而散列开的。并不是什么“大流水号”。更进一步地,许多关键业务id号连这个lock也觉得是个垃圾、可以去掉,于是可能是“随机号+服务器编号+当前时间”的组合这个算法来产生id号。目的就是尽量不要纠结什么“并发时同步”的问题。再比如说,假设我们要购火车票,那么一个终端在确定要两张票之后,这两张票瞬间就被从“待售”的库存里转到“正在售”的库存里了。这样就避免了数据库事务中不小心把这些没有用的数据行也上锁。这样就回避了事务(而不是像有些程序员那样,非要用技术才显得高大上)。再比如说,假设1000人在0.1秒钟内抢走任务去做,那么先把这些任务放到一个高速缓存或者一个简单的soa服务上去就行了。至于说每一个人抢到任务编号之后,再去后台真正地获取任务内容、执行任务,这整个冗长的过程,根本不加锁。而有些程序可能就会纠结于1000人执行任务时“并发”问题而头疼不已。总之,没有技术而能够解决问题,是最好的技术。其次就是现在比较流行分布式处理方式,避免加锁。
解决方案四:
把这个判断与写入放到一个事务里,这两步就是一起的操作,但是还是要有关系才行,比如判断有了就不写入了,那么第二个请求不可能写入。一般我们只对关系的地方做这种事务的处理,比如金额,库存等操作,普通的操作,如果出现了可以手动处理,一般这种出现很小,因为事务对性能会有一定的损耗。