如何使用Sql Profiler捕获在SqlBulkCopy中传递的数据?

mar*_*ark 9 sql-server bulkinsert sqlbulkcopy sql-server-profiler sql-server-2012

我一直在使用Sql Profiler捕获SQL语句并重新运行有问题的语句.很有用.

但是,有些代码使用SqlBulkCopy API,我不知道如何捕获它们.我看到临时表的创建,但没有任何填充它们.看起来像SqlBulkCopy绕过Sql Profiler或者我没有捕获正确的事件.

Sol*_*zky 11

可以捕获批量插入操作的事件信息(BCP.EXE,SqlBulkCopy我认为BULK INSERT,和OPENROWSET(BULK...),但是您将无法看到各个行和列.

批量插入操作显示为单个(好,每个批次一个,默认是在一个批次中执行所有行)DML语句:

INSERT BULK <destination_table_name> (
      <column1_name> <column1_datatype> [ COLLATE <column1_collation> ], ...
      ) [ WITH (<1 or more hints>) ]

<hints> := KEEP_NULLS, TABLOCK, ORDER(...), ROWS_PER_BATCH=, etc
Run Code Online (Sandbox Code Playgroud)

您可以在MSDN页面上找到BCP实用程序的"提示"的完整列表.请注意,使用SqlBulkCopy只支持这些提示的一个子集(例如KEEP_NULLS,TABLOCK和其他几个),但并没有支持ORDER(...)ROWS_PER_BATCH= **(这是很不幸的,实际上,由于ORDER()是必要的,以避免那种情况发生在tempdb提示为了允许最小程度地记录操作(假设已经满足这种操作的其他条件).

要查看此语句,您需要捕获SQL Server Profiler中的以下任何事件:

SQL:BatchStarting
SQL:BatchCompleted
SQL:StmtStarting
SQL:StmtCompleted

您还需要至少选择以下列(在SQL Server Profiler中):

TextData
CPU
读取
写入
持续时间
SPID
StartTime
EndTime
RowCounts

而且,由于用户无法INSERT BULK直接提交语句,如果您只想查看这些事件而不是其他任何内容,则可以在列过滤器中对其进行过滤.

如果要查看BULK INSERT操作开始和/或结束的正式通知,则需要捕获以下事件:

的SqlTransaction

然后添加以下Profiler列:

EventSubClass
ObjectName

因为ObjectName你总是得到显示"BULK INSERT"的事件,以及是开始还是结束是由值in确定的EventSubClass,这是"0 - 开始"或"1 - 提交"(我想如果它失败你应该看到" 2 - 回滚").

如果ORDER()没有指定提示是(再次,它不能被使用时指定SqlBulkCopy),那么你也将得到一个"的SqlTransaction"事件显示"sort_init"在ObjectName列.此事件还具有"0 - 开始"和"1 - 提交"事件(如列中所示EventSubClass).

最后,即使您看不到特定的行,如果捕获以下事件,仍然可以看到针对事务日志的操作(例如,插入行,修改IAM行,修改PFS行等):

TransactionLog

并添加以下Profiler列:

对象ID

感兴趣的主要信息将在EventSubClass列中,但遗憾的是它只是ID值,我在MSDN文档中找不到这些值的任何转换.但是,我确实找到了Jonathan Kehayias的以下博客文章:在SQL Server Denali CTP1中使用扩展事件来映射TransactionLog SQL跟踪事件EventSubClass值.

@RBarryYoung指出可以在sys.trace_subclass_values目录视图中找到EventSubClass值和名称,但查询该视图显示它没有该TransactionLog事件的行:

SELECT * FROM sys.trace_categories -- 12 = Transactions
SELECT * FROM sys.trace_events WHERE category_id = 12 -- 54 = TransactionLog
SELECT * FROM sys.trace_subclass_values WHERE trace_event_id = 54 -- nothing :(
Run Code Online (Sandbox Code Playgroud)

**请注意,该SqlBulkCopy.BatchSize属性相当于-bBCP.EXE设置选项,这是一个操作设置,用于控制每个命令如何将行分解为集合.这与ROWS_PER_BATCH=没有物理控制行如何分解成集的提示不同,而是允许SQL Server更好地规划它将如何分配页面,从而减少事务日志中的条目数(有时通过很多).我的测试仍显示:

  • 指定-b用于BCP.EXE没有设置ROWS_PER_BATCH=提示相同的值.
  • 指定SqlBulkCopy.BatchSize属性并没有设置ROWS_PER_BATCH=提示,但是,减少事务日志活动的利益在某种程度上确实存在(魔术?).事实上,净效应仍然可以获益,这就是为什么我没有提到它的原因,当我说不幸的是ORDER()提示没有得到支持时SqlBulkCopy.


Ily*_*kov 0

SqlBulkCopy您无法在 SQL Profiler 中捕获,因为SqlBulkCopy在 SQL Server 表中插入数据时根本不生成 SQL。SqlBulkCopy与实用程序类似bcp,将数据直接加载到 SQL Server 文件系统中。它甚至可以在插入行时忽略 FK 和触发器!

  • 关于“SqlBulkCopy 在 SQL Server 表中插入数据时根本不生成 SQL。”:这绝对不是真的。它确实生成一条 INSERT 语句,并且可以在 SQL Server Profiler 中看到。这是一个“批量插入”操作。无法绕过 SQL Server 将数据注入数据库。如果这是可能的,那么 ACID 合规性就会失效。您引用的 MSDN 论坛答案断章取义且具有误导性。该人说 SELECT 查询无法与所有其他查询区分开来,因为它_绝对_来自 BCP。 (4认同)