环境:mysql5单库(innodb),php5,nginx
现在的逻辑判断如下:
通过mysql进行查询,有数据不进行任何操作,无数据进行写入一条新数据
问题:当并发量大的时候,mysql会同时插入相同的数据3条左右,也就是说mysql做不了这样的逻辑处理。
我的解决办法:根据来访用户的session写入一个标记,如果有标记则不进行下面的数据库操作,但是还是不能挡住重复数据的出现。
请教大家有没有其他的办法解决我遇到的问题?(消息队列做这个可以吗?如果不用消息队列用Redis做标记(逻辑类似上面的session)的话是否可行?再高并发的情况下Redis是否也会出现类似MySQL的情况)
session不妥,这个只能解决同一个用户的重复提交,但两个用户在不同浏览器上提交了重复数据,因为校验的查询和实际数据插入都有一个比较长的时间差,那就会出现业务上数据重复的问题
如果该字段不能建唯一索引的话,一般只能考虑在一个公共访问的数据上控制唯一,内存数据库或者关系数据库都可以做到这点的,redis可以考虑cas锁,关系数据库可以做一个中间表,每次业务开始前就往该表插入一条数据(该表有一个唯一索引,如何设计你自己考虑),业务结束就删掉,考虑到意外情况还是设置一个过期时间,定时任务批量删除过期时间,基本保证不会数据重复
mysql不清楚,我用过oracle,db2都是用唯一索引来控制。
######谢谢此法 可行,不过我们还有一个调用接口在调用数据库之前######唯一索引,联合唯一索引绝对可以避免。写入会被阻止。是以错误还是异常的形式抛出完全根据配置决定。######多谢你的回答###### 用事务加锁######是个好办法多谢######用pdo 做事务######消息队列可以######使用序列嘛!MySQL不是有主键么,不写的话,它是自动生成的么,如果你指定了,那主键无法重复,也就无法重复插入了。######唯一索引约束 插入的时候 可以考虑使用replace into
我觉得你这种情况可以先把数据放到redis里面 然后再通过一个一直运行的脚本读取redis插入到mysql中
######二次提交思路。。
首先,查询发现没有记录,而且标记位为0,然后更新标记位为0+1,表示准备插入了,然后再查询一遍标记位是否为1,若不为1,那么说明有冲突。若为1,那么正常插入。
插入后标记为更新为0.
解决冲突的策略:
1.重来一遍。。最省事
2.如果不愿意重来一遍,update标记位,将标记位减一,然后,再查一遍标记位,若还是大于1,那么放弃执行,若等于1,那么正常执行。。
######用队列是可以的。版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。