多人同时在线购买火车票的同步问题

JavaJstl 2012-02-02 04:46:07
表结构:
主表a
id:
name:列车号(如‘北京-上海’或‘北京-广州)
totalnum:该列火车全部的座位数

从表b
id:
aid:主表a里的列车id(主表a的id列的外键)
code:身份证号码
num:购买的火车票数量

描述:多人在线同时购买火车票,需要同步,避免某列火车出售的火车票数超过该列火车全部的座位数。但是如果在java类里对购票的方法C进行同步的话,明显不合理,如果全国同时有一万个人同时提交购票请求,第一万个用户想买北京-上海的车票,这么他必须等到前面9999个用户都买到票才轮到他进入方法C进行购票,不管前面9999个用户是不是都要买北京-上海的车票。所以
,有没有办法缩小同步范围,只对购买同一列火车车票的用户进行同步????
...全文
479 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
MiceRice 2012-02-02
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 javajstl 的回复:]
谢谢ldh911,我大概明白你的意思了。我先试试再给分。
[/Quote]

没错,我相信你理解了,整个过程一句Insert完成,大致类似如下:

Insert Into b (aid,code,num)
Select aid, code, #wantedNUM As num
From a
Where a.aid = #wantedID And (a.totalnum - #wantedNUM) >
(Select Sum(num) as salednum From b Where b.aid = a.aid )

如果插入了1行代表成功买到票;插入0行代表买票失败。
JavaJstl 2012-02-02
  • 打赏
  • 举报
回复
这个兄弟有何高见?
JavaJstl 2012-02-02
  • 打赏
  • 举报
回复
这个兄弟有和高见
三味书屋 2012-02-02
  • 打赏
  • 举报
回复
这涉及到了并发操作。。。。
JavaJstl 2012-02-02
  • 打赏
  • 举报
回复
谢谢ldh911,我大概明白你的意思了。我先试试再给分。
JavaJstl 2012-02-02
  • 打赏
  • 举报
回复
谢谢ldh991的热心回复

可能是我没描述清楚,我的思路是:
a表里的totalnum字段是该列火车全部的座位数,座位数是固定的。
在用户提交购某列火车的车票请求时,需要进行以下步骤:
1.取得用户需要购票的数量wantednum.
2.到b表里检索该列火车已经出售的车票数select sum(num) as salednum from b where aid=?。
3.用salednum、wantednum和a表里的totalnum比较
a.如果salednum==totalnum,车票售罄。退出。
b。如果salednum+wanted<=totalnum,购票成功。
insert into b (aid,code,num) values(?,?,?);退出。
c。如果salednum+wanted>totalnum,提示用户。退出。

如果不在方法C里进行同步,可能出现的极端情况,当某列火车只剩一张票时,X和Y两位同时提交购票请求,X和Y同时进入第3步的b环节,同时购票成功,结果该列火车出售的全部票数超过该列火车的固定座位数totalnum.
MiceRice 2012-02-02
  • 打赏
  • 举报
回复
“select sum(num) as salednum from b where aid=?” 这个设计在高并发下不好,低并发下问题不大,Anyway,也不算是问题。因为你没有写锁,但是你需要把整句话写成一行 insert,具体写法可以自己琢磨下。

JavaJstl 2012-02-02
  • 打赏
  • 举报
回复
谢谢ldh991的热心回复

可能是我没描述清楚,我的思路是:
a表里的totalnum字段是该列火车全部的座位数,座位数是固定的。
在用户提交购某列火车的车票请求时,需要进行以下步骤:
1.取得用户需要购票的数量wantednum.
1.到b表里检索该列火车已经出售的车票数select sum(num) as salednum from b where aid=?。
2.用salednum、wantednum和a表里的totalnum比较
a.如果salednum==totalnum,车票售罄。
b。如果salednum+wanted<=totalnum,购票成功
c。如果salednum+wanted>totalnum,提示用户
疯狂的驴子 2012-02-02
  • 打赏
  • 举报
回复
楼上的大牛 哈哈。收我为徒弟吧
MiceRice 2012-02-02
  • 打赏
  • 举报
回复
其实你的问题,它就不是个问题,因为商用数据库都是行级锁。

而你的问题本质上就是个行锁,“全国同时有一万个人同时提交购票请求”,除非都是集中在一个车次上,否则是不会相互影响的。

Update totalnum = totalnum - 1 From a Where name='北京-上海' and totalnum > 1;

每次只会锁定一行,只有请求同一行的人,才会排队。当然上面这个例子条件里面用name是不对的,应该用id。
JavaJstl 2012-02-02
  • 打赏
  • 举报
回复
谢谢回复

ldh911的方案对于我的需求来说不可行,我只是以火车票为例子来讲解,这样大家容易明白。列车数目是有限的而且列车是固定的,但是其实我的项目里a表的数据会无限增加。
MiceRice 2012-02-02
  • 打赏
  • 举报
回复
常规做法是对在数据库层面做 水平切割。

最极端的例子是:
北京-上海 一个数据库
北京-广州 一个数据库

不要那么极端的是:
北京-全国各地 一个数据库
北京-上海 一张表
北京-广州 一张表

再不极端的是:
北京-全国各地 一张表
北京-上海 一个分区
北京-广州 一个分区

anhy 2012-02-02
  • 打赏
  • 举报
回复
难道是12306?

81,095

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧