对web并发插入时出现重复记录的一点想法

       首先我们先了解下mysql的锁表机制。一种是共享锁,一种是独占锁。共享锁就是读锁,这种锁主要就是防止在读的时候又有新数据的插入,而并不排斥其他的线程读取。而独占锁就是在写的时候加的锁,既防止读,又防止写。好了,现在我们分析下为什么会出现重复记录。

 

假设一种情况:假设有两个表:a,b。a为订单表,b为帐务记录表。

if order1.state == not_confirm then

    update a set state=confirmed where orderid = order1.orderid

    insert into b

endif

上面的意思是,如果订单未被处理,则更新订单状态为被处理,并在b中插入一条记录。

 

好了,现在订单表非常大,而且查询频繁,在用户执行这个操作时,正好有个执行速度很慢的查询将表a锁住了(这时候不管是共享锁还是独占锁,这个操作都不能进行了,只能等待)。然后用户觉得慢,就使劲刷新了几次,而这刷新的几次请求使得web服务器又重新执行了几次该脚本,但是那个慢速查询依然没有完成,所以,无论多少个请求,都会卡在第二行update a表这个地方,因为第一个还未更新,因此,后续取到的order1.state依然是not_confirm。一旦那个慢速查询执行完毕,则写队列里的update执行是相当快的。接着每个请求便会执行insert into b这个sql,而这是无法避免的。

 

一点解释。

重复请求的数据,如果没有使用时间,则数据应该是完全一样的,如果使用了时间,则写的时间有可能有些差别。如果是使用客户端(相对于mysql服务器)生成的时间,则需要看用户刷新的频率。如果是使用mysql的now()时间函数,则差别应该在毫秒一下,普通的时间字段很难看出其差别,这就造成一种假象,就是同一秒内插入大量相同的数据。

 

当然这只是一种想法,并未实际操作过。这是我结合事务操作原理以及对隔离级别的测试,进行的一种猜想。这个猜想有待验证。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值