我们的客户端代码检测到死锁,等待一段时间,然后重试请求最多5次.重试逻辑基于错误号1205检测死锁.
我的目标是在各种存储过程中测试死锁重试逻辑和死锁处理.我可以使用两个不同的连接创建死锁.但是,我想在单个存储过程本身内部模拟死锁.
死锁引发以下错误消息:
消息1205,第13级,状态51,第1行
事务(进程ID 66)在锁资源上与另一个进程发生死锁,并被选为死锁受害者.重新运行该交易.
我看到此错误消息在sys.messages
:
select * from sys.messages where message_id = 1205 and language_id = 1033
message_id language_id severity is_event_logged text
1205 1033 13 0 Transaction (Process ID %d) was deadlocked on %.*ls resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
Run Code Online (Sandbox Code Playgroud)
我不能使用RAISERROR
以下方法引发此错误:
raiserror(1205, 13, 51)
Run Code Online (Sandbox Code Playgroud)
消息2732,级别16,状态1,行1
错误号1205无效.号码必须是13000到2147483647,不能是50000.
我们的死锁重试逻辑检查错误号是否为1205.死锁需要具有与正常死锁相同的消息ID,级别和状态.
有没有办法模拟死锁(使用RAISERROR或任何其他方法)并只用一个进程获取相同的消息号?
我们的数据库使用SQL 2005兼容性,但我们的服务器在2005年到2008年之间有所不同.
我有一个C#.NET 2.0 WinForms应用程序.我的应用程序有一个控件,它是两个子控件的容器:标签和某种编辑控件.您可以这样想,外框是父控件:
+---------------------------------+ | [Label Control] [Edit Control] | +---------------------------------+
我试图在鼠标进入或离开父控件时执行某些操作,但我不在乎鼠标是否移动到其中一个子控件中.我想要一个标志来表示"鼠标在父或子的内部"和"鼠标移动到父控件边界之外".
我已尝试在父控件和两个子控件上处理MouseEnter和MouseLeave,但这意味着当鼠标在控件上移动时,操作会多次开始和结束.换句话说,我明白了:
Parent.OnMouseEnter (start doing something) Parent.OnMouseLeave (stop) Child.OnMouseEnter (start doing something) Child.OnMouseLeave (stop) Parent.OnMouseEnter (start doing something) Parent.OnMouseLeave (stop)
中间的OnMouseLeave事件会导致一些不良影响,因为我正在做的事情开始然后停止.我想避免这种情况.
我不想捕获鼠标,因为父控件需要鼠标移动,因为子控件需要鼠标事件,我想要菜单和其他快捷键才能工作.
有没有办法在.NET框架内执行此操作?或者我需要使用Windows鼠标挂钩?
我有一个来自生产服务器的崩溃转储,显示OutOfMemoryException.例外本身与此无关.
我碰巧运行了一个!dso来查看堆栈对象:
0:042> !dso
OS Thread Id: 0x1014 (42)
ESP/REG Object Name
246eeb24 109a21bc System.UnhandledExceptionEventHandler
246eeb2c 39083998 System.Runtime.Remoting.Proxies.__TransparentProxy
246eeb34 39083b5c System.UnhandledExceptionEventArgs
246eeb48 39073280 System.Byte[]
246eec10 2e720050 System.OutOfMemoryException
[snip]
246ef250 0ac1c4d0 System.IO.MemoryStream <-- interesting
Run Code Online (Sandbox Code Playgroud)
我以为MemoryStream可能与错误有关,所以我把它丢弃了:
0:042> !do 0ac1c4d0
Name: System.IO.MemoryStream
MethodTable: 7932d5e4
EEClass: 790ec318
Size: 52(0x34) bytes
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
MT Field Offset Type VT Attr Value Name
7933061c 400018a 4 System.Object 0 instance 00000000 __identity
7992cbcc 4001b6c 8 ...ream+ReadDelegate 0 instance 00000000 _readDelegate
7992cc58 4001b6d c ...eam+WriteDelegate 0 instance 00000000 _writeDelegate …
Run Code Online (Sandbox Code Playgroud) 我们其中一个产品的架构是典型的3层解决方案:
客户端从Web服务请求信息.Web服务命中数据库以获取信息并将其返回给客户端.
这是问题所在.其中一些查询可能需要很长时间,而且我们不知道哪些查询会很慢.我们知道一些通常比其他人慢,但即使最简单的请求也可能因为足够的数据而变慢.有时使用查询或运行大量数据的报告.只有在大量数据减慢之前,才能优化查询.
如果数据库中的查询在SQL Server中达到最大查询超时,则数据库查询将终止,并且Web服务会向客户端返回错误.这是理解的.我们可以处理这些错误.
客户端正在等待Web服务调用完成.如果数据库调用需要很长时间,则客户端可能会在调用Web服务时超时.客户端放弃,但数据库请求继续处理.此时,客户端与数据库不同步.数据库调用可能成功也可能不成功.可能有错误.客户永远不会知道.在某些情况下,我们不希望我们的用户发起另一个请求,如果完成上一个请求,可能会导致无效状态.
我很想知道其他人是如何处理这个问题的.您使用了哪些策略来防止Web服务超时影响数据库调用?
我能提出的最好的想法涉及在某个地方建立一个实际的数据库层 - 在Web服务内部,附加到消息队列 - 某些东西.将每个查询卸载到另一个进程似乎过多.(然后,我们并不总是知道给定的请求是快还是慢.)
如果我们能够将发出HTTP请求的行为与启动和运行数据库进程的行为分开,那就太好了.我已经在之前的公司看到过使用自定义服务器,但它使用的是直接套接字通信,我宁愿避免使用某些自定义应用程序替换Web服务.
请注意,考虑到我们处理的数据量,我们都在进行查询优化.查询优化,索引等只会在数据量很大时才将您带到目前为止.有时事情需要很长时间.
我正在测试一次删除许多记录的进程.它不能TRUNCATE TABLE
,因为那里有记录需要留下来.
由于音量,我已将删除分解为类似于此的循环:
-- Do not block if records are locked.
SET LOCK_TIMEOUT 0
-- This process should be chosen as a deadlock victim in the case of a deadlock.
SET DEADLOCK_PRIORITY LOW
SET NOCOUNT ON
DECLARE @Count
SET @Count = 1
WHILE @Count > 0
BEGIN TRY
BEGIN TRANSACTION -- added per comment below
DELETE TOP (1000) FROM MyTable WITH (ROWLOCK, READPAST) WHERE MyField = SomeValue
SET @Count == @@ROWCOUNT
COMMIT
END TRY
BEGIN CATCH
exec sp_lock …
Run Code Online (Sandbox Code Playgroud) 在我的整个职业生涯中,我在QA方面取得了不同程度的成功.我承认我可以亲自接受错误报告,但通常当它们以自由形式制作时,其措辞更像是投诉:"这个过程仍然无效!",没有足够的信息来重现缺陷.
我愿意研究我对批评的敏感性,但我也对将质量保证流程去个性化并鼓励提供信息性错误报告的工具和技术感兴趣.目前,通过电子邮件或有时通过走路和语言表达错误来报告错误.
任何工具应该是:啤酒中的免费和易于安装/低管理.我也对博客文章,书籍或有关如何使自己对错误报告不敏感的文章持开放态度.
我正在编写一些代码来查询某些DMV。根据SQL版本,DMV中某些列可能存在也可能不存在。我在网上找到了一个有趣的建议,如何跳过使用的特定检查CROSS APPLY
。
以下查询是用于读取可能缺少的列的DMV的代码示例。该代码为该列创建默认值,并用于CROSS APPLY
从DMV中提取实际列(如果存在)。
代码尝试提取的列BogusColumn不存在。我希望下面的查询会生成有关无效列名的错误...但事实并非如此。它返回NULL且没有错误。
为什么下面的CROSS APPLY子句不会导致“无效的列名”错误?
declare @x int
select @x = b.BogusColumn
from
(
select cast(null as int) as BogusColumn
) a
cross apply
(
select BogusColumn from sys.dm_exec_sessions
) b;
select @x;
Run Code Online (Sandbox Code Playgroud)
如果我分别运行查询CROSS APPLY
:
select BogusColumn from sys.dm_exec_sessions;
Run Code Online (Sandbox Code Playgroud)
我收到有关无效列名的预期错误:
Msg 207, Level 16, State 1, Line 9
Invalid column name 'BogusColumn'.
Run Code Online (Sandbox Code Playgroud)
如果我将DMV列名更改为BogusColumn2以使其唯一,则会出现预期的列名错误:
select a.BogusColumn1, b.BogusColumn2
from
(
select cast(null as int) as BogusColumn1
) a
cross apply
(
select BogusColumn2 from …
Run Code Online (Sandbox Code Playgroud) 我们有一个带有C#客户端,C#WCF Web服务层和SQL Server数据库的3层应用程序.Web服务使用ADO.NET连接到数据库.我们所有的C#代码都使用.NET Framework 2.0.
最近,客户对我们的应用程序进行了压力测试.在测试期间,Web服务器生成了许多错误,如下所示:
无法连接到数据库以获取连接字符串'...'.超时已过期.操作完成之前经过的超时时间或服务器没有响应.
我知道有些方法可以在连接池已满时捕获连接错误并尝试获取连接池外部的连接.我们还发现了一些需要调整的查询,但它们并不能解释Web服务器连接超时.
我们试图弄清楚为什么Web服务器超时连接到数据库.我已经设置了Web服务器以启用所有ADO.NET性能计数器.但是,我没有看到任何与连接或连接超时等所需时间相关的内容.理想情况下,我们可以perfmon
在其他ADO.NET计数器旁边绘制连接时间图.
有没有办法监控ADO.NET在获取连接时的性能?
我想我们可以通过尝试打开连接来创建我们自己的"平均连接开放时间"性能计数器,但我宁愿使用已经存在的东西.
背景
我们有一个用C#编写的.NET WinForms应用程序,它通过控制台应用程序连接到手持式商店扫描仪.控制台应用程序是用很好的'VB6编写的 - 那里没有托管代码.VB6应用程序由几个COM对象组成.
.NET WinForms应用程序通过使用正确的参数调用控制台应用程序来刷新扫描程序中的数据.当控制台应用程序启动时,它会弹出一个模态表单,提醒用户将手持设备放入其底座中.
问题
客户有一种奇怪的情况,即启动控制台应用程序的调用在显示提醒表单之前似乎已挂起.如果用户按下任何键 - 即使是像Shift或Alt这样无辜的东西 - 应用程序也会解冻,并显示提醒表单.挂起时,控制台应用程序的CPU使用率非常高.
我们使用ProcDump从命令行应用程序获取了内存转储.我有一些调试托管转储文件的经验,但这个VB 6转储对我来说很奇怪.
我们连续捕获了几个完整的内存转储.在其中一些中,似乎有COM胶水堆.例如,几个转储文件显示如下调用堆栈:
msvbm60!BASIC_DISPINTERFACE_GetTICount
msvbm60!_vbaStrToAnsi
msvbm60!IIDIVbaHost
msvbm60!rtcDoEvents
msvbm60!IIDIVbaHost
msvbm60!BASICCLASS_QueryInterface
[our code which I think is trying to create and invoke a COM object]
Run Code Online (Sandbox Code Playgroud)
我所拥有的唯一符号来自我们的代码并没有帮助.Microsoft符号服务器没有msvbm60.dll的PDB文件(或至少不是他们的版本6.0.98.2).
问题
我怀疑可能有一些COM线程问题只发生在他们的系统上.
1)如何确定转储文件中每个线程的线程状态?如果这是一个托管转储文件,我会查看!threads
然后!threadstate
找出线程状态.没有托管代码,所以我不能使用sos.dll.我没有看到任何提示使用~
和!teb
.
2)有没有办法看到在转储文件中创建了什么COM对象?同样,在托管转储中,我可以执行a !dumpheap
以获取托管对象的列表.有没有类似我可以找到的COM对象?
3)我可以在转储文件中确定COM对象的线程模型吗?
我一直在努力解决我们在生产中遇到的各种僵局.我们启用了死锁跟踪.跟踪显示KEYLOCK上有很多阻塞,如下所示:
01/15/2010 08:25:07,spid15s,Unknown,keylock hobtid=72057594047758336 dbid=2
objectname=tempdb.dbo.MyTable indexname=IX_MyTable id=lock36977900 mode=X
associatedObjectId=72057594047758336
Run Code Online (Sandbox Code Playgroud)
据我所知,键锁锁定索引,以防止在事务执行自己的插入,更新和删除时插入,更新或删除记录.
我猜测有错误的查询计划会导致请求坏锁.我可以在我的开发系统上运行相同的查询并运行sp_lock来检查查询所需的锁,我在列表中看到一些KEYLOCK.如何检查KEYLOCK锁定的键范围?
sql-server ×5
c# ×3
sql ×3
deadlock ×2
locking ×2
windbg ×2
.net ×1
ado.net ×1
architecture ×1
com ×1
cross-apply ×1
events ×1
minidump ×1
mouse ×1
perfmon ×1
qa ×1
raiserror ×1
sos ×1
t-sql ×1
timeout ×1
unit-testing ×1
vb6 ×1
wcf ×1
web-services ×1
winforms ×1