多线程操作数据库时为了防止数据的增删改的混乱该在数据库层还是程序层面上进行同步?

水上冰石 2014-11-28 05:04:20
假设两张表中各有一个字段,是由约束关系的,比如一张表是已经卖出的票的数目,另一张表是还剩余的票的数目。为了操作两张表时保证数据的原子性,应该在数据库层设置还是在程序层做设置?两种方式各有什么优缺点?
...全文
4324 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
lin182508 2017-08-18
  • 打赏
  • 举报
回复
事物+乐观离线锁,,更新剩余数量时,验证一下,剩余数量大于1时才能更新,,更新失败,页面可提示,票已卖完,,足够友好 建议楼主查看 企业应用架构模式 第十六章离线并发模式
uuuiiiooo099 2017-06-05
  • 打赏
  • 举报
回复
引用 12 楼 sp1234 的回复:
[quote=引用 6 楼 hqshaozhu 的回复:] 举例,现剩余数量是1,有一个线程去读取剩余数据,并进行出票操作,由于这个线程还未提交事务,这时有另一个线程来读取剩余数量,读取到的还是1,所以也进行出票操作,这样就出错了。
这个事务描述是错误的!一般默认的隔离级别,通常是可以避免幻象读问题的。(更何况还可以自定义更严格级别) 当一个事务读取剩余数量1、而并没有结束出票操作时,另外一个线程启动的事务就不能读取到剩余数量(也就是不能读取到1)。所以这里所谓的“出错”不成立! [/quote]是吗?
showjim 2015-06-23
  • 打赏
  • 举报
回复
在数据库层还是程序层,一般情况下取决于你当前框架的支持。 如果没有任何支持,数据库事务是最佳选择,虽然可能存在性能问题。 如果有成熟的缓存架构支持,那么程序层面的处理优势是绝对毋庸置疑的。
jdmake 2015-06-20
  • 打赏
  • 举报
回复
引用 5 楼 atgso 的回复:
两个字:事务 多几个字:不管你在哪个层面,都要对数据库进行事务处理 锁数据是基本的。
事务 提交 回滚
  • 打赏
  • 举报
回复
引用 6 楼 hqshaozhu 的回复:
举例,现剩余数量是1,有一个线程去读取剩余数据,并进行出票操作,由于这个线程还未提交事务,这时有另一个线程来读取剩余数量,读取到的还是1,所以也进行出票操作,这样就出错了。
这个事务描述是错误的!一般默认的隔离级别,通常是可以避免幻象读问题的。(更何况还可以自定义更严格级别) 当一个事务读取剩余数量1、而并没有结束出票操作时,另外一个线程启动的事务就不能读取到剩余数量(也就是不能读取到1)。所以这里所谓的“出错”不成立!
  • 打赏
  • 举报
回复
将很关键、很简单的原则操作放在多步业务流程的“最开头” -> 将很关键、很简单的原子操作放在多步业务流程的“最开头” 如果你说“程序层做设置”,它不是还是得修改数据库嘛! 正因为此,有些人很懒,觉得既然一切最终都要记录到数据库,那么干脆就用存储过程写业务逻辑程序就得了。而人家用程序显式地声明事务(将两条update语句封装在一个事务的begin/commit之间),就被他看作是非要辨出个是非曲直的多大事儿出来。 实际上如果不考虑效率,那么程序员随便折腾程序。谁跟老板是亲戚,谁说的就是对的。但是考虑性能需求,用较少的成本产生足以打败竞争对手的高性能、高并发处理能力的需求,这就能分出哪种设计才是更加值得鼓励的了!
  • 打赏
  • 举报
回复
数据库事务是一种层次,而且这也是需要应用程序显式声明两个sql操作在同一个事务中的。(不知道在应用程序中事务的,就不提了)。 但是能够在内存操作中考虑到需要“原子”操作的,(假设能够用在大系统中的话)是另外一个层次。因为内存操作毕竟会比数据库操作快100倍速度的! 将很关键、很简单的原则操作放在多步业务流程的“最开头”,然后后边的操作就可以尽量异步处理(并且也尽量不加锁)了。而如果你把“修改库存票数”这个操作放在多步业务流程的最后,那么你就会写出一个冗长、严重阻塞整体性能的程序。
Java_er 2015-05-23
  • 打赏
  • 举报
回复
数据库事务,怎可能会在程序中控制呢
_Nick_ 2015-04-01
  • 打赏
  • 举报
回复
数据层做悲观锁效率太差,且承载资源有限。 1.简单方案:使用cache实例做同步锁 2.复杂方案:使用zookeeper的分布式锁实现(尽量使用锁分段) 假如操作这2张表库存的方法是 abc(int lessStock) getLock(); abc(1); returnLock();
少主无翼 2014-12-16
  • 打赏
  • 举报
回复
在数据库层面的话就需要通过加锁来控制原子性,事务是无法控制的,因为事务具有隔离性。 举例,现剩余数量是1,有一个线程去读取剩余数据,并进行出票操作,由于这个线程还未提交事务,这时有另一个线程来读取剩余数量,读取到的还是1,所以也进行出票操作,这样就出错了。 如果在应用层面控制的话解决方法可以使用队列,或者加锁并发操作
Knight.Dj 2014-12-10
  • 打赏
  • 举报
回复
两个字:事务 多几个字:不管你在哪个层面,都要对数据库进行事务处理 锁数据是基本的。
Knight.Dj 2014-12-10
  • 打赏
  • 举报
回复
两个字:事务 多几个字:不管你在哪个层面,都要对数据库进行事务处理 锁数据是基本的。
Knight.Dj 2014-12-10
  • 打赏
  • 举报
回复
两个字:事务 多几个字:不管你在哪个层面,都要对数据库进行事务处理 锁数据是基本的。
MiceRice 2014-11-29
  • 打赏
  • 举报
回复
基本上是数据库层面为主;程序层面的话因为涉及到要如何解决集群问题,所以比较麻烦。 但如果是12306之类的这种压力规模系统,直接把所有事物管控下推数据库可能将数据库变为瓶颈,所以需要特殊设计。
周某某_1112 2014-11-29
  • 打赏
  • 举报
回复
用售票系统来举例 不错 这种问题说明你操作数据层是面向对象的 这样在多线程下会出现剩余票数不一致 这是由于你取数据对象后 还没进行数据操作 其他线程就对数据该条数据操作了 导致你现在纠结的问题 解决方法大致分为两种: 1、利用存储过程,对售票逻辑编写存储过程来保证数据操作的唯一性 2、利用纯SQL语句对售票逻辑进行处理 如: update ticket set restTicket=(restTicket-1) where......... 上面任何一种方法都适用,不过存储过程编写需要一定的基本功,建议使用第二种,简单明了又能有效解决问题

25,985

社区成员

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

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