SQL Server 会同时执行两条 SQL 语句吗?我指的是同一时间点上执行,而不是先后。

2014-11-13 18:03:04 +08:00
 huage
比如说在进销存管理系统里,业务上经常会同时发生以下两种情况:

仓管在录入入库单:原库存 + 入库 = 新库存

但在同时

销售部也在开销售单:原库存 - 出库 = 新库存

上面两个业务可以简单理解为两条SQL语句,请问两条语句会在同一时间点上执行吗? 就是说会不会两条语句都以“原库存”为基数进行加或者减呢?

sql server本身是否有机制防止这种情况的发生呢?
8202 次点击
所在节点    问与答
18 条回复
takwai
2014-11-13 18:17:13 +08:00
sql server 有并发控制类型 http://technet.microsoft.com/zh-cn/library/ms189132(v=sql.105).aspx

需要在 Transact-SQL 语句或通过数据库应用程序编程接口的属性和特性来定义。
msg7086
2014-11-13 18:19:51 +08:00
事务。
huage
2014-11-13 18:25:21 +08:00
@takwai 可以这样理解吗?如果不定义,SQL server本身是有可能发生这种情况的。一旦这个风险真的出现了,新的库存数量就不正确了。
huage
2014-11-13 18:26:02 +08:00
@msg7086 能否详细指点一下?谢谢!
incompatible
2014-11-13 18:32:09 +08:00
@huage 你需要了解的是事务隔离级别这个概念
http://en.wikipedia.org/wiki/Isolation_%28database_systems%29
http://msdn.microsoft.com/zh-cn/library/ms173763.aspx


具体到你的情况 入库和销售这两个业务在共同操作库存这个资源,这样需要一个锁来保证两个业务各自的原子性
通常的做法是在业务系统中使用乐观锁或悲观锁来解决这个问题,而不是依赖数据库的事务隔离
zts1993
2014-11-13 18:36:14 +08:00
锁和事物

如果是sql执行加减,数据库自动行锁或者表锁可以保证正确。一般是没有问题的,烦心的话就加锁。


上面说事务是不对的吧,事务保证多步操作正确,这里是单条记录。
huage
2014-11-13 19:09:07 +08:00
@zts1993 我刚才问了一位SQL MVP,他很耐心地回答了我的问题,大概如下:

在单核计算机上不会同时执行,都会排队,在多核计算机上,会有可能同时执行。四核处理器,会有四个队列,每个队列都有sql语句排队,如果两条sql语句不在同一个队列,那么可以认为是同时执行,当然,如果由于排队机制,两个sql语句在两个核心上同时执行的可能性太少了,但是宏观上可以认为是同时执行。

为了保证执行的先后顺序,你必须加锁WITH(UPDLOCK)

如果不加锁的话,可以考虑sql2008的新的merge关键字
不过实际上在内部都是加了锁的
要保证执行顺序的一致性,也就是保证所谓的串行,反正会造成更新丢失,库存不一致


他提到的一个问题是:更新丢失。
liprais
2014-11-13 19:27:45 +08:00
楼主你先要了解下SQL server的隔离机制,
随手一搜,这里就有:http://technet.microsoft.com/zh-cn/library/ms189122(v=sql.105).aspx
永远记住先搜索再提问
huage
2014-11-13 20:22:41 +08:00
@liprais 是的,我是应该先搜索,这种菜鸟问题确实麻烦了V2EX了各位大神了。

不过由于我对于SQL没有很多基础上,许多名词不知道,所以搜索出来的结果不是很满意,特来到这里向大家请教。
20150517
2014-11-13 20:32:27 +08:00
@zts1993 是啊,update行,肯定是锁行的,不需要事务这么麻烦,事务锁表了吧?
liprais
2014-11-13 21:12:59 +08:00
@huage 推荐ni翻一遍head first sql这本书
mengskysama
2014-11-13 23:19:16 +08:00
@20150517
也不一定,只有 InnoDB有行锁,其他都是锁表的比如SAM。

每一个数据库语句肯定是先取得锁再操作的,锁是线程之间共享的不管你几个核心,但是有些锁是共享的,多线程的时候必须要考虑到逻辑正确性(多个线程同时操作,某些线程更新了某条记录)可能就会出现数据不一致。

这个例子似乎两sql之间不能保证原子和互斥。这个问题我只知道可以用事务解决,既然能够保证多线程的正确性,又能保证顺序的完整性要么操作都成功要么失败。
mengskysama
2014-11-13 23:21:04 +08:00
@huage 哦哦是微软数据库啊,不过应该都一样,差不多就是MVP说的那个意思。
min
2014-11-13 23:43:47 +08:00
买本书看看吧
msg7086
2014-11-14 03:46:58 +08:00
有冲突的记录,数据库上会自动加锁保证操作的原子性。

如果是先读再写,为了防止两条记录前后分别执行,则需要加事务。
huage
2014-11-14 08:37:29 +08:00
@liprais head first系列的图书确实不错,适合我这些初学者,简单易懂很有趣味。
huage
2014-11-14 08:38:43 +08:00
@msg7086 像我所提及有这种业务情况,应该就是先select,后insert的吧。
msg7086
2014-11-14 08:56:37 +08:00
@huage 不一定的。你这种计算可以直接在服务器上执行,不需要2句的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/146269

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX