我的一个客户有一个基于预订的系统。类似于航空公司。在MS SQL 2005上运行。
上一家公司设计它的方式是将分配创建为一组行。
简单的例子是:
AllocationId | SeatNumber | IsSold
1234 | A01 | 0
1234 | A02 | 0在出售座位的过程中,系统会在桌子上建立一个更新锁。
目前我们有一个问题,锁定过程运行缓慢,我们正在寻找加速它的方法。
表已经被有效地索引,所以我们正在寻找一种硬件解决方案来加速这一过程。该表大约有500万个活动行,位于RAID 50 SAS阵列上。
我假设当你有5百万行并且一次更新2-5行时,硬盘寻道时间将是加速更新锁的限制因素(我可能是错的)。
我听说有人在几个磁盘阵列上使用索引分区,有没有人有过类似的加速锁定的经历?谁能给我一些建议,关于哪些硬件可以升级,或者我们可以利用哪些技术来加快更新锁定(而不移动到集群)的可能解决方案?
发布于 2009-10-12 09:05:54
最后一次尝试…
很明显,有太多的锁持有的时间太长。
一旦系统由于太多的锁而开始变慢,启动更多事务就没有意义了。
因此,您应该对系统进行基准测试,以找出最优的并发事务数量,然后使用一些队列系统(或其他方式)来限制并发事务的数量。Sql Server可能有一些设置(活动连接数等)可供帮助,否则您将不得不在应用程序代码中编写此设置。
Oracle在允许reads to bypass writes方面做得很好,但是SqlServer并不是很标准...
因此,我会将存储的proc拆分为使用两个事务,第一个事务应该是:
读取未提交(or
并使用第二个(希望非常短)事务
行最有可能是读提交的(或者可能对每一行进行更新(使用在此期间尚未售出的locking hint)
上设置“IsSold”标志
(您可以使用“in”在一条update语句中执行上述操作,然后检查预期的行数是否已更新)
对不起,有时你确实需要理解事务的每一次都做了什么,以及锁是如何工作的细节。
如果表较小,则更新时间较短,锁持有的时间也较短。
因此,请考虑拆分表:
发布于 2009-09-22 14:38:24
我认为您不会从表分区中获得任何好处--唯一的改进是从较小(较短)的索引树中读取较少的磁盘(每次读取将至少命中索引的每个级别一次,因此级别越少,读取速度越快)。但是,我得到了一个带有4M+行分区的表,它在4列上进行索引,键长度净为10字节。它适用于三个索引级别,最高级别为42.6%。假设您有类似的东西,分区可能只从树中删除一个级别,这似乎是合理的,我怀疑这是一个很大的改进。
一些即兴的强硬想法:
由于奇偶校验计算,Raid 5(和50)的写入速度可能会较慢。如果磁盘I/O缓存足够大,可以处理工作负载,这不是问题(或者我是这么被告知的),但是如果磁盘I/O缓存被淹没,您可能需要考虑raid 10。
跨多个驱动器阵列对表进行分区。使用两个(或更多) Raid阵列,将表分布在卷文件/文件组中,无论是否使用表分区或分区视图,您都可以获得两倍的磁盘I/O速度,这取决于数据相对于检索数据的查询所在的位置。(如果数组#1和数组#2上的所有内容都是空闲的,那么您什么也得不到。)
最坏的情况是,可能有尖端或尖端的技术会让你大吃一惊。如果它对你的业务至关重要,而且你有预算,那么可能值得认真研究一下。
发布于 2009-09-22 14:57:30
long是持有的更新锁的长度
为什么“table”上的锁而不仅仅是“rows”上的锁被出售?
如果锁被持有超过一小部分秒,这很可能是你的问题。SqlServer不喜欢你在用户填写网页表单时手持锁,等等。
使用SqlServer,您必须自己实现“购物车”,通过临时预订座位,直到用户支付为止。例如,添加“IsReserved”和“ReservedAt”列,则任何已预订超过n分钟的座位都应自动取消预订。
这是一个很难解决的问题,因为购物者不会期望库存中的座位会被卖给他结账的其他人。然而,你不知道购物者是否会完成结账。那么如何在UI上显示它呢?考虑一下其他预订网站做了什么,然后复制一个你的用户已经知道如何使用的网站。
(Oracle有时可以处理长时间保存的锁,但如果保持短时间的锁定,即使是Oracle也比快得多,也更好。)
https://stackoverflow.com/questions/1460294
复制相似问题