Sql server 将MSSQL bcp负载隔离到临时表中

Sql server 将MSSQL bcp负载隔离到临时表中,sql-server,ado,Sql Server,Ado,我想清空一个临时表,通过bcp加载它,然后在移动到生产表之前修改它的行。这些命令看起来像这样: 截断表temp1 import1.txt中的bcp db.schema1.temp1-h“TABLOCK” exec sp_修改_temp1_行_移动_到_生产_表 我的问题是如何将所有这些作为一个事务执行,不一定是为了回滚它,而是为了提供隔离 这是想象中的情景。User1转到load import1.txt(用户不知道如何完成此操作的实现细节,步骤1-3)。在User1的步骤2完成之前,User2启

我想清空一个临时表,通过bcp加载它,然后在移动到生产表之前修改它的行。这些命令看起来像这样:

  • 截断表temp1
  • import1.txt中的bcp db.schema1.temp1-h“TABLOCK”

  • exec sp_修改_temp1_行_移动_到_生产_表
  • 我的问题是如何将所有这些作为一个事务执行,不一定是为了回滚它,而是为了提供隔离

    这是想象中的情景。User1转到load import1.txt(用户不知道如何完成此操作的实现细节,步骤1-3)。在User1的步骤2完成之前,User2启动自己的导入。锁定机制阻止它们立即开始导入。主要的问题是User2的步骤1将在User2的步骤2完成后立即开始,从而在User1的步骤3和流程完成之前清除表

    三个补充说明:

  • 这里通过ADO执行客户端(不要与ADO.NET混淆)
  • 批量插入不是一个选项
  • 更愿意通过ADO扩展一些锁机制来实现这一点,ADO可以包括过程的步骤1和步骤2中的步骤2——如果可能的话——知道这是不可能的,在这里也会有所帮助
  • 1) 第一种解决方案

    • 将SessionId字段添加到temp1表
    • 添加加载会话状态表PK sessionId,状态tinyint(流程步骤1,流程步骤2…完成…)

    • sp_modify_temp1_rows_move_to_production_表将只执行一些sessionId和State=Done的记录。(sp_modify_temp1_rows_move_to_production_table可通过使用sql代理作业异步执行)
    • truncate应替换为DELETE,其中SessionId=(速度较慢,但必须执行)。(它可以由同一个sql代理作业执行,但要在将记录移动到生产环境之后执行)
    • 应从bcp命令中删除TABLOCK
    2) 第二种解决方案

    • 创建表格temp\u XXX
    • import1.txt中的bcp db.schema1.临时文件
    • exec sp_modify_tempXXX_rows_move_to_production_table_ @table\u name='temp\u XXX'(使用带有@table\u name参数的动态sql)
    • 升降台温度XXX
    已添加


    3) 使用表load_session_状态作为进度视图并锁定进程。如果其中有任何记录,则通知用户等待。使用以前的解决方案而不做任何更改。只需将table load\u session\u state用作逻辑锁

    典型的解决方案是使用

    sp_getapplock 'importing-ABC', 'Exclusive', 'Session';
    

    通过这种方式,您可以锁定逻辑资源(任意字符串/名称),按照惯例,尝试执行相同操作的其他用户必须尝试获取相同的applock。按住applock时,
    bcp
    命令可以不受干扰地运行。请注意,这不会阻止另一个不遵守协议的用户/应用程序(因为无知、恶意或愚蠢)。

    我考虑了1和2,但更多的是使用网络登录而不是会话id和登录来代替XXX。我希望(希望很高),但是,有某种方法可以通过某种sp将表锁定扩展到User1,我可以用某种方式从客户端包装bcp。谢谢你的回答。我将拭目以待,如果这样的事情是不可能的,我将使用#2作为答案。sp_modify_temp1_rows_move_to_production_table可以通过使用sql代理作业异步执行。您的最后一条评论我听不懂。我不确定这对我有什么好处?我也可以从ADO执行sp异步。如何通过将其作为作业运行来避免隔离问题?尽管出于某种奇怪的原因,我想到了一个想法,我可以在一个而不是插入触发器中运行sp。通过BCP将数据加载到temp1,而不是从inserted执行实际插入,然后执行sql?这不应该保持孤立吗?不确定性能是否会受到影响?考虑到我的环境和时间安排,很难测试这些场景。请使用表load\u session\u状态作为进度视图并锁定进程。如果其中有任何记录,则通知用户等待。使用以前的解决方案而不做任何更改。只需使用table load_session_state作为逻辑锁。您的#2仍然非常突出,我正在权衡各种选项。我认为我的触发选项是一个性能问题,所以我也放弃了。这似乎比创建一个表来管理锁更简单。虽然锁定表很容易创建,但我不希望有这个额外的表。另外,我还必须编写EXISTS和insert以及DELETES来添加到现有代码中。所以它比#2更混乱,在这里我基本上得到了现有临时表的CREATE表,然后将其嵌入到TRUNCATE中。这似乎是一个有趣的选项。我可以通过ADO for User1从GUI调用sp_getapplock,在User1释放它之前再次调用它(从User2),这会阻止代码运行。我注意到关键词“会话”。我必须检查一下,但我正在通过给shell打电话来运行BCP。因此,BCP应该与调用TRUNCATE和sp_modify_temp1_*的ADO连接处于不同的会话中。你知道这是不是你脑子里想不到的一个因素吗?伊戈尔,同意作为选项1和选项3的替代品,而不是桌子。我将不得不测试,看看这是否如预期的工作。尽管所有选项都有效,但仍将其标记为“答案”。这只是一个“我今天学到了一些新东西”,我认为这对其他项目很有用,尽管我可能仍然支持#2。谢谢。applock的“会话”范围是长操作的合适范围,如BCP事务的作用域用于短操作。