2014-08-27 22 views
1

有一种情况可以在不同的地方创建表。 所以,我有〜10个工作应用程序,可以同时尝试创建一个相同的表。 问题。我如何同步它们?所以我没有任何例外或错误?并发表创建

当一天结束时,应用程序的所有实例都试图创建一个新表,所以当有类似00:00:00的时候,他们都会尝试创建它。

对不起,对于可能的“愚蠢的问题”,一直在谷歌搜索一段时间,没有结果。 谢谢。

+1

为什么不确定不会发生。也许根据应用程序试图创建表的方式,在表名前面附加一些独特的东西。即app1MyTable,app2MyTable,app3MyTable等。 – Linger 2014-08-27 12:54:49

+0

您会看到,它们全部10个都是一个应用程序的实例,并且它们都在该表中写入日志,所以在一个地方查看来自所有服务器的所有日志将很高兴 – Eramir 2014-08-27 12:56:54

+0

或在创建表之前先进行检查以确保它不存在... – Darren 2014-08-27 12:57:07

回答

2

您可以使用sp_getapplock进行任意锁定。在创建表之前,您可以让您的应用程序使用此锁。像这样:

exec sp_getapplock 
if tabledoesnotexist 
create table ... 
-1

您可以请通过以下代码...并发执行使用ISOLATION LEVEL SERIALIZABLE处理。

 CREATE PROCEDURE [dbo].[GetNextID](
      @IDName nvarchar(255) 
     ) 
     AS 
     BEGIN 
      /* 
       Description: Increments and returns the LastID value from tblIDs 
       for a given IDName 
       Author:   Max Vernon 
       Date:   2012-07-19 
      */ 

      DECLARE @Retry int; 
      DECLARE @EN int, @ES int, @ET int; 
      SET @Retry = 5; 
      DECLARE @NewID int; 
      SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
      SET NOCOUNT ON; 
      WHILE @Retry > 0 
      BEGIN 
       BEGIN TRY 
        BEGIN TRANSACTION; 
        SET @NewID = COALESCE((SELECT LastID FROM tblIDs WHERE IDName = @IDName),0)+1; 
        IF (SELECT COUNT(IDName) FROM tblIDs WHERE IDName = @IDName) = 0 
         INSERT INTO tblIDs (IDName, LastID) VALUES (@IDName, @NewID) 
        ELSE 
         UPDATE tblIDs SET LastID = @NewID WHERE IDName = @IDName; 
        COMMIT TRANSACTION; 
        SET @Retry = -2; /* no need to retry since the operation completed */ 
       END TRY 
       BEGIN CATCH 
        IF (ERROR_NUMBER() = 1205) /* DEADLOCK */ 
         SET @Retry = @Retry - 1; 
        ELSE 
         BEGIN 
         SET @Retry = -1; 
         SET @EN = ERROR_NUMBER(); 
         SET @ES = ERROR_SEVERITY(); 
         SET @ET = ERROR_STATE() 
         RAISERROR (@EN,@ES,@ET); 
         END 
        ROLLBACK TRANSACTION; 
       END CATCH 
      END 
      IF @Retry = 0 /* must have deadlock'd 5 times. */ 
      BEGIN 
       SET @EN = 1205; 
       SET @ES = 13; 
       SET @ET = 1 
       RAISERROR (@EN,@ES,@ET); 
      END 
      ELSE 
       SELECT @NewID AS NewID; 
     END 
     GO 
0

正如评论中提到的那样,您的第一步是执行存在检查。然后,如果有两个同时创作的机会,您可以使用TRY...CATCH

IF Object_ID('test', 'U') IS NULL 
    BEGIN 
    BEGIN TRY 
     CREATE TABLE test (a int) 
    END TRY 
     BEGIN CATCH 
     SELECT Error_Message() 
     END CATCH 
    END 

UPDATE

每天都想创建一个表。认真。这是非常差的数据库设计。

相反,您希望将datetime列添加到您的表中,以指示每条记录何时创建。