Code Bye

多服务器单数据库,如何解决insert数据并发

问题是这样的,系统是按手机号来下单还款的,一个手机号同一时间只能下一次订单,我们的系统是多点模式的(分布式),那样的话JAVA的并发关键字就不起作用了,要在数据库中做并发控制,请问如何控制?关键点是手机号不能作为唯一键(业务需要)


5分
需求:
    一个手机号同一时间只能下一次订单,
    关键点是手机号不能作为唯一键(业务需要);
这两个需求有矛盾或者有表达歧义。

解决方案:
单独建个临时订单表 ,只适用于这段时间;临时表中,一个字段记录手机号,unique属性。抢购结束,批量导入正式订单表

引用 1 楼 tianfang 的回复:

需求:
    一个手机号同一时间只能下一次订单,
    关键点是手机号不能作为唯一键(业务需要);
这两个需求有矛盾或者有表达歧义。

解决方案:
单独建个临时订单表 ,只适用于这段时间;临时表中,一个字段记录手机号,unique属性。抢购结束,批量导入正式订单表

具体业务是这样的。体验还款,也就是输入手机号,获取验证码,然后输入信用卡发卡行和卡号,公司出钱,免费给客户还一笔款。一个手机号只能体验还款一次,如果这个手机号还款结果失败,就能够再体验一次。
如果一个手机号同时开多个浏览器进行还款,那么数据落订单的时候肯定会发生并发问题。
按照你说的临时表,我觉得也有可行性,也就是先把订单落入临时表,这样能够防止并发。然后把还款状态为失败的数据导入正式表。但是这之中会有一个问题,数据需要实时同步,这样会不会造成系统开销过大。还有同步的过程中肯定有时间差,比如临时表中数据还在,但是用户已经得知还款失败可以再还一笔了,于是用户再去还款的时候,造成还款订单下不了。


5分
楼主,你搞一个临时表,里面存放不完整交易的信息。当交易完成或者超时未完成时,清除临时表的记录,基本上就OK了。

你所说的并发控制,说白了,也就是不允许临时表里面出现重复的手机号码,那么,手机号码做个唯一约束就可以了。

临时表的长度,要尽量越小越好。如果并发量大,可以采取分表的方式,分担表的负载。这个是后话。

引用 3 楼 preferme 的回复:

楼主,你搞一个临时表,里面存放不完整交易的信息。当交易完成或者超时未完成时,清除临时表的记录,基本上就OK了。

你所说的并发控制,说白了,也就是不允许临时表里面出现重复的手机号码,那么,手机号码做个唯一约束就可以了。

临时表的长度,要尽量越小越好。如果并发量大,可以采取分表的方式,分担表的负载。这个是后话。

交易完成不能清除记录,唯一能做到的是把失败的记录在状态回写时转移数据。


5分
临时表里面,对于完整的交易,当然要进行删除操作了,但,这不妨碍你在删除前,先把数据迁移的别的表里面呀。

用户对数据的访问负载,大多在不完整交易的这张表里面,对于完整交易,是不存在插入操作的,只会是查询操作。
那么,针对查询,可以对这个表的数据结构进行优化,提高查询效率。
而不完整交易,则负载较大,插入操作也有,更新操作也有,查询操作也有,所以,要尽量缩短表长度。


5分
楼主可能没有明白我说的业务逻辑。
1. 先查询不完成交易表里,有没有当前用户的不完整交易,如果没有,进入2.  如果有进入4.
2. 查询历史记录(完整交易表)里,有没有当前用户的完整交易信息,如果没有,进入3.  如果有进入5.
3. 在不完整交易表里面插入记录,手机号码有唯一限定,如果插入失败,诱导用户进入1.
    如果插入成功,则进入支付环节,如果支付失败诱导用户进入4.
4. 重复支付操作一次,如果超过重复支付的最大次数,则终止支付
5. 提示用户已经体验过该服务,不能多次使用。
引用 6 楼 preferme 的回复:

楼主可能没有明白我说的业务逻辑。
1. 先查询不完成交易表里,有没有当前用户的不完整交易,如果没有,进入2.  如果有进入4.
2. 查询历史记录(完整交易表)里,有没有当前用户的完整交易信息,如果没有,进入3.  如果有进入5.
3. 在不完整交易表里面插入记录,手机号码有唯一限定,如果插入失败,诱导用户进入1.
    如果插入成功,则进入支付环节,如果支付失败诱导用户进入4.
4. 重复支付操作一次,如果超过重复支付的最大次数,则终止支付
5. 提示用户已经体验过该服务,不能多次使用。

我大致理解你的想法,结合我自己的逻辑业务,我已经能解决这个问题了。
这个问题解决的关键点是加UNIQUE属性的临时表。


5分
你应该有2种解决方式
1:放入一个队列,顺序解决,如果并发不大,应该没有问题
2:使用数据库乐观锁

5分
分布式一致性锁
引用 8 楼 yutaoaijingjing132 的回复:

你应该有2种解决方式
1:放入一个队列,顺序解决,如果并发不大,应该没有问题
2:使用数据库乐观锁

我知道UPDATE的时候可以用乐观锁,但是INSERT的时候应该无法用乐观锁吧?队列的话,2台机器,很难处理吧


5分
为啥会有一个手机号同时下单的情况,是担心重复提交么?
引用 11 楼 ygycomon 的回复:

为啥会有一个手机号同时下单的情况,是担心重复提交么?

如果他打开2个浏览器同时操作,那是不是就会造成并发的情况。


5分
引用 12 楼 huangyekan 的回复:
Quote: 引用 11 楼 ygycomon 的回复:

为啥会有一个手机号同时下单的情况,是担心重复提交么?

如果他打开2个浏览器同时操作,那是不是就会造成并发的情况。

如果是单个用户,是不可能造成并发的


5分
分布式数据库做离散表吧,可以分为物理分区和逻辑分区,按一定的业务规则进行拆分。
物理分区可以是物理库,也可以是schema
逻辑分区就是不同的表了,即:每个表的结构都一样,tblname不一样。
引用 13 楼 ygycomon 的回复:
Quote: 引用 12 楼 huangyekan 的回复:
Quote: 引用 11 楼 ygycomon 的回复:

为啥会有一个手机号同时下单的情况,是担心重复提交么?

如果他打开2个浏览器同时操作,那是不是就会造成并发的情况。

如果是单个用户,是不可能造成并发的

单个用户也是有可能的,和几个用户无关

引用 14 楼 AIX_HEAD 的回复:

分布式数据库做离散表吧,可以分为物理分区和逻辑分区,按一定的业务规则进行拆分。
物理分区可以是物理库,也可以是schema
逻辑分区就是不同的表了,即:每个表的结构都一样,tblname不一样。

不是很懂你的意思


5分
想一个简单的,可不可以弄个时间字段,将时间字段和手机号做个联合唯一
引用 17 楼 shijing266 的回复:

想一个简单的,可不可以弄个时间字段,将时间字段和手机号做个联合唯一

这个应该不好做吧,因为唯一字段是ORACLE本身提供的,ORACLE并不能提供联合唯一吧。不知道您有什么好的方法?


5分
引用 17 楼 shijing266 的回复:

想一个简单的,可不可以弄个时间字段,将时间字段和手机号做个联合唯一

这个也是可行的 ,但是不是时间字段,而是促销活动ID字段+手机号。oracle支持联合唯一


5分
通过队列或者MQ解决吧

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明多服务器单数据库,如何解决insert数据并发