我们有一个长时间运行的事务(使用嵌套的trans),它运行大约2分钟。在这段时间里,它会执行一系列插入,更新和选择。同时用户仍然需要能够使用该系统。使用的一些表与批处理程序中的表相同。
在下面的探查器跟踪中,我从一个不相关的表中获取一个块。有趣的是,阻塞我的事务的查询,第二个任务不使用该表。
以下是分析器输出,阻塞进程(CustomerOrderEntry)是快速进程,而阻塞进程是运行时间较长的进程。
我们正在使用MSDTC和MS SQL Server以及ADO.Net
<blocked-process-report monitorLoop="546369">
<blocked-process>
<process id="process9fbc51c28" taskpriority="0" logused="10464" waitresource="PAGE: 40:1:182902 " waittime="20839" ownerId="232311233" transactionname="user_transaction" lasttranstarted="2015-05-14T11:52:46.997" XDES="0x12838563b0" lockMode="S" schedulerid="1" kpid="7508" status="suspended" spid="118" sbid="2" ecid="0" priority="0" trancount="1" lastbatchstarted="2015-05-14T11:52:47.023" lastbatchcompleted="2015-05-14T11:52:47.023" lastattention="1900-01-01T00:00:00.023" clientapp="CustomerOrderEntry.exe" hostname="QIT-TS" hostpid="116616" loginname="QIT\tgower.admin" isolationlevel="read committed (2)" xactid="232311233" currentdb="40" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame line="1" stmtstart="52" stmtend="512" sqlhandle="0x02000000946ebc1dc9d4bf7eefd3826e6a744d9b92931d1a0000000000000000000000000000000000000000"/>
<frame line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"/>
</executionStack>
<inputbuf>
(@OrderNumber varchar(20))SELECT Id, OrderNumber, Line, Equipment, Site, Quantity, EngineHours, GPSLongitude, GPSLatitude, OffRoad, Route, Eta, Etd
FROM CustomerOrderEquipment
WHERE (OrderNumber = @OrderNumber)
ORDER BY Equipment </inputbuf>
</process>
</blocked-process>
<blocking-process>
<process status="suspended" waitresource="40:1:2670699" waittime="49" spid="95" sbid="2" ecid="0" priority="0" trancount="2" lastbatchstarted="2015-05-14T11:53:07.817" lastbatchcompleted="2015-05-14T11:53:07.817" lastattention="1900-01-01T00:00:00.817" clientapp="EzyserveImport.exe" hostname="QIT-TS" hostpid="25480" loginname="QIT\tgower.admin" isolationlevel="read committed (2)" xactid="232308068" currentdb="40" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame line="1" stmtstart="1050" stmtend="2498" sqlhandle="0x0200000050f50e11ba633c312db084db39d3e5c7ff5b8a2d0000000000000000000000000000000000000000"/>
<frame line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"/>
</executionStack>
<inputbuf>
(@Id uniqueidentifier,@Account varchar(12),@Date datetime,@Details varchar(39),@Amount decimal(18,2),@Quantity decimal(18,4),@Source int,@PostingBatch uniqueidentifier,@BASPosition varchar(3),@BASPosted bit,@BASPostedPeriodDate date,@Site int,@Financed bit,@FinancedDate date,@FinancedBatch varchar(8000),@BankRecReference varchar(8000),@BankRecType int,@BankRecPayMedium varchar(8000),@ExcludeFromFinancing bit,@Notes varchar(8000),@Reconciled bit,@ReconciledDate datetime,@FuelSubsidyClaimed bit,@FuelSubsidyClaimDate date)INSERT INTO [LedgerTransactions] ([Id], [Account], [Date], [Details], [Amount], [Quantity], [Source], [PostingBatch], [BASPosition], [BASPosted], [BASPostedPeriodDate], [Site], [Financed], [FinancedDate], [FinancedBatch], [BankRecReference], [BankRecType], [BankRecPayMedium], [ExcludeFromFinancing], [Notes], [Reconciled], [ReconciledDate], [FuelSubsidyClaimed], [FuelSubsidyClaimDate]) VALUES (@Id, @Account, @Date, @Details, @Amount, @Quantity, @Source, @PostingBatch, @BASPosition, @BASPosted, </inputbuf>
</process>
</blocking-process>
</blocked-process-report>
答案 0 :(得分:0)
通过它的声音,将这个大规模的交易分解成更易于管理的块将是一种选择。使用游标或while循环一次更新/插入/选择1000个参数并在一个事务中运行它。这样,其他事务可以读取中断之间的数据。当然,这假设所有这些更新并非必须一起阅读。 另一个选项是更改您用于此查询的隔离级别。取决于您需要的数据并发性。
(1000个参数,我的意思是,如果一个列正在更新,那么每个事务1000行,如果两个列正在更新,那么每个事务500行。对于大多数系统1000参数是速度的“最佳点”。)