AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 29903
Accepted
John
John
Asked: 2012-12-06 15:41:42 +0800 CST2012-12-06 15:41:42 +0800 CST 2012-12-06 15:41:42 +0800 CST

登录未跨可用性组同步

  • 772

我们在 AlwaysOn 组中有 2 台服务器。

虽然每个同步数据库中的用户帐户都存在于两台服务器上,但数据库实例级登录仅存在于其中一台服务器上。即 DBINSTANCE->Security->Logins 在一台服务器上丢失。

因此,当发生故障转移时,我会在第二台服务器(没有相应的实例级别登录)上登录失败。

我该如何克服这个问题?我应该以特殊方式设置用户帐户吗?

sql-server sql-server-2012
  • 4 4 个回答
  • 27171 Views

4 个回答

  • Voted
  1. Mark Storey-Smith
    2012-12-06T16:01:21+08:002012-12-06T16:01:21+08:00

    我的理解是,如果您不使用Contained Databases,则必须确保在其他实例上手动创建登录。

    类似于SQLSoldier的脚本(最初发布在将登录名转移到数据库镜像一文中)应该可以解决问题。

    • 15
  2. Best Answer
    John
    2012-12-07T07:46:14+08:002012-12-07T07:46:14+08:00

    您必须使用包含的数据库,或者必须在其他服务器上使用相同的密码哈希和 SID 重新创建用户。

    Microsoft 提供了执行此操作的脚本: How to transfer logins and passwords between SQL Server instances

    Mark 的解决方案部分正确,但他推荐的解决方案是针对镜像数据库,而不是问题所要求的 AlwaysOn。

    • 7
  3. Muhammad
    2018-04-20T09:43:37+08:002018-04-20T09:43:37+08:00

    我在很长一段时间后回复了这个帖子,但它可能会帮助其他人解决类似的问题。PowerShell 可用于将登录信息从主副本复制到辅助副本。详细信息可以在这里找到https://maq.guru/synchronizing-sql-server-logins-in-an-always-on-availability-group/。

    全面披露:我拥有上述网站。

    PowerShell 脚本:

    $Conn=New-Object System.Data.SqlClient.SQLConnection
    $QueryTimeout = 120
    $ConnectionTimeout = 30
    
    ###########################################################
    # Execute Query function 
    ###########################################################
    Function executequery($Query, $QueryTimeout, $ServerName)
    {
        $Datatable = New-Object System.Data.DataTable
        $ConnectionString = "Server={0};Database={1};Integrated Security=True;Connect Timeout={2}" -f $ServerName,$Database,$ConnectionTimeout
        $Conn.ConnectionString=$ConnectionString
        $Cmd=New-Object system.Data.SqlClient.SqlCommand($Query,$Conn)
        $Cmd.CommandTimeout=$QueryTimeout
    
                do
                    {   
                        $Conn.Open()
                        Start-Sleep -Seconds 2
                    }while ($Conn.State -ne 'Open')
    
                $Reader = $cmd.ExecuteReader()
                $Datatable.Load($Reader)
                $Conn.Close()
                return $Datatable    
    }
    
    
    ###########################################################
    # Create spHexaDecimal Stored Procedure
    ###########################################################
    
    Function CreatespHexaDecimal ($ServerName)
        {
        $Query='USE [master];
                    GO
                    SET ANSI_NULLS ON;
                    GO
                    SET QUOTED_IDENTIFIER ON;
                    GO
                    CREATE PROCEDURE [dbo].[spHexaDecimal]
                    (
                        @BinValue VARBINARY(256)
                        , @HexValue VARCHAR(514) OUTPUT
                    )
                    AS
    
                    DECLARE @CharValue VARCHAR(514)
                    DECLARE @i INT
                    DECLARE @Length INT
                    DECLARE @HexString CHAR(16)
    
                    SET @CharValue = ''0x''
                    SET @i = 1
                    SET @Length = DATALENGTH(@BinValue)
                    SET @HexString = ''0123456789ABCDEF''
    
                    WHILE (@i <= @Length)
                    BEGIN
    
                        DECLARE @TempInt INT
                        DECLARE @FirstInt INT
                        DECLARE @SecondInt INT
    
                        SET @TempInt = CONVERT(INT, SUBSTRING(@BinValue, @i, 1))
                        SET @FirstInt = FLOOR(@TempInt/16)
                        SET @SecondInt = @TempInt - (@FirstInt * 16)
                        SET @CharValue = @CharValue 
                                            + SUBSTRING(@HexString, @FirstInt + 1, 1)
                                            + SUBSTRING(@HexString, @SecondInt + 1, 1)
    
                        SET @i = @i + 1
    
                    END --WHILE (@i <= @Length)
    
                    SET @HexValue = @CharValue'
    
                    Invoke-Sqlcmd -Query $Query -ServerInstance $ServerName
        }
    
    
    ###########################################################
    # CheckStroedProc 
    ###########################################################
    
    Function CheckStoredProc ($Server)
    {
        $Query= 'SELECT 1 AS ExistCheck
                 FROM   sysobjects 
                 WHERE  id = object_id(N''[dbo].[spHexaDecimal]'') 
                     AND OBJECTPROPERTY(id, N''IsProcedure'') = 1 '
    
        $Result=executequery $Query $QueryTimeout $Server
        $Exist=$Result | SELECT -ExpandProperty ExistCheck
        IF ($Exist -ne 1)
            {
                CreatespHexaDecimal -ServerName $Server
            }
    }
    
    ###########################################################
    # Get Login Script
    ###########################################################
    
    Function Get-Script ($Server)
    {
    
    $Query='DECLARE @TempTable TABLE
    (Script NVARCHAR(MAX))
    DECLARE @Login NVARCHAR (MAX)
    DECLARE CURLOGIN CURSOR FOR
    SELECT name 
    FROM sys.server_principals
    WHERE CONVERT(VARCHAR(24),create_date,103) = CONVERT(VARCHAR(24),GETDATE(),103)
        OR CONVERT(VARCHAR(24),modify_date,103) = CONVERT(VARCHAR(24),GETDATE(),103)
    
    OPEN CURLOGIN
        FETCH NEXT FROM CURLOGIN INTO @Login
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET NOCOUNT ON
        DECLARE @Script NVARCHAR (MAX)
        DECLARE @LoginName VARCHAR(500)= @Login
        DECLARE @LoginSID VARBINARY(85)
        DECLARE @SID_String VARCHAR(514)
        DECLARE @LoginPWD VARBINARY(256)
        DECLARE @PWD_String VARCHAR(514)
        DECLARE @LoginType CHAR(1)
        DECLARE @is_disabled BIT
        DECLARE @default_database_name SYSNAME
        DECLARE @default_language_name SYSNAME
        DECLARE @is_policy_checked BIT
        DECLARE @is_expiration_checked BIT
        DECLARE @createdDateTime DATETIME
    
    
    
        SELECT @LoginSID = P.[sid]
            , @LoginType = P.[type]
            , @is_disabled = P.is_disabled 
            , @default_database_name = P.default_database_name 
            , @default_language_name = P.default_language_name 
            , @createdDateTime = P.create_date 
        FROM sys.server_principals P
        WHERE P.name = @LoginName
    
        /** Some Output **/
        SET @Script = ''''
    
    
    
    
        --If the login is a SQL Login, then do a lot of stuff...
        IF @LoginType = ''S''
        BEGIN
    
            SET @LoginPWD = CAST(LOGINPROPERTY(@LoginName, ''PasswordHash'') AS VARBINARY(256))
    
            EXEC spHexaDecimal @LoginPWD, @PWD_String OUT   
            EXEC spHexaDecimal @LoginSID, @SID_String OUT
    
            SELECT @is_policy_checked = S.is_policy_checked
                , @is_expiration_checked = S.is_expiration_checked
            FROM sys.sql_logins S
    
            /** Create Script **/
            SET @Script = @Script + CHAR(13) + CHAR(13)
                            + ''IF EXISTS (SELECT name FROM sys.server_principals WHERE name= ''''''+ @LoginName + '''''') '' 
                            + CHAR(13) + '' BEGIN ''
                            + CHAR(13) + CHAR(9) + '' ALTER LOGIN '' + QUOTENAME(@LoginName)
                            + CHAR(13) + CHAR(9) + ''WITH PASSWORD = '' + @PWD_String + '' HASHED''
                            + CHAR(13) + CHAR(9) + '', DEFAULT_DATABASE = ['' + @default_database_name + '']''
                            + CHAR(13) + CHAR(9) + '', DEFAULT_LANGUAGE = ['' + @default_language_name + '']''
                            + CHAR(13) + CHAR(9) + '', CHECK_POLICY '' + CASE WHEN @is_policy_checked = 0 THEN ''=OFF'' ELSE ''=ON'' END
                            + CHAR(13) + CHAR(9) + '', CHECK_EXPIRATION '' + CASE WHEN @is_expiration_checked = 0 THEN ''=OFF'' ELSE ''=ON'' END
                            + CHAR(13) + '' END ''
                            + CHAR(13) + ''ELSE''
                            + CHAR(13) + '' BEGIN ''
                            + CHAR(13) + CHAR(9) + '' CREATE LOGIN '' + QUOTENAME(@LoginName)
                            + CHAR(13) + CHAR(9) + ''WITH PASSWORD = '' + @PWD_String + '' HASHED''
                            + CHAR(13) + CHAR(9) + '', SID = '' + @SID_String
                            + CHAR(13) + CHAR(9) + '', DEFAULT_DATABASE = ['' + @default_database_name + '']''
                            + CHAR(13) + CHAR(9) + '', DEFAULT_LANGUAGE = ['' + @default_language_name + '']''
                            + CHAR(13) + CHAR(9) + '', CHECK_POLICY '' + CASE WHEN @is_policy_checked = 0 THEN ''=OFF'' ELSE ''=ON'' END
                            + CHAR(13) + CHAR(9) + '', CHECK_EXPIRATION '' + CASE WHEN @is_expiration_checked = 0 THEN ''=OFF'' ELSE ''=ON'' END
                            + CHAR(13) + '' END ''
    
            SET @Script = @Script + CHAR(13) + CHAR(13)
                            + '' ALTER LOGIN ['' + @LoginName + '']''
                            + CHAR(13) + CHAR(9) + ''WITH DEFAULT_DATABASE = ['' + @default_database_name + '']''
                            + CHAR(13) + CHAR(9) + '', DEFAULT_LANGUAGE = ['' + @default_language_name + '']''
    
        END
        ELSE
        BEGIN
    
            --The login is a NT login (or group).
            SET @Script = @Script + CHAR(13) + CHAR(13)
                            + ''IF NOT EXISTS (SELECT name FROM sys.server_principals WHERE name= ''''''+ @LoginName + '''''') '' 
                            + CHAR(13) + '' BEGIN ''
                            + CHAR(13) + CHAR(9) + '' CREATE LOGIN '' + QUOTENAME(@LoginName) + '' FROM WINDOWS''
                            + CHAR(13) + CHAR(9) + ''WITH DEFAULT_DATABASE = ['' + @default_database_name + '']''
                            + CHAR(13) + '' END ''
        END
    
        /******************************************************************************************/
        --This section deals with the Server Roles that belong to that login...
        /******************************************************************************************/
    
        DECLARE @ServerRoles TABLE
            (
            ServerRole SYSNAME
            , MemberName SYSNAME
            , MemberSID VARBINARY(85)
            )
    
        INSERT INTO @ServerRoles EXEC sp_helpsrvrolemember
    
        --Remove all Roles
        SET @Script = @Script + CHAR(13)
        SET @Script = @Script 
                                + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''sysadmin''''''
                                + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''securityadmin''''''
                                + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''serveradmin'''''' 
                                + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''setupadmin'''''' 
                                + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''processadmin''''''
                                + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''diskadmin'''''' 
                                + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''dbcreator'''''' 
                                + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''bulkadmin'''''' 
    
        /** Output to script... **/
        --SET @Script = @Script + CHAR(13) + CHAR(13)
    
        --Test if there are any server roles for this login...
        IF EXISTS(SELECT 1 FROM @ServerRoles WHERE MemberName = @LoginName)
        BEGIN
    
            SET @Script = @Script + CHAR(13)
    
            DECLARE @ServerRole SYSNAME
            DECLARE curRoles CURSOR LOCAL STATIC FORWARD_ONLY
    
            FOR SELECT ServerRole 
                FROM @ServerRoles
                WHERE MemberName = @LoginName
    
            OPEN curRoles
    
            FETCH NEXT FROM curRoles
            INTO @ServerRole
    
            WHILE @@FETCH_STATUS = 0
            BEGIN
    
                /** Output to Script **/
                SET @Script = @Script 
                                + CHAR(13) + ''EXEC sp_addsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + QUOTENAME(@ServerRole, '''''''')
    
                FETCH NEXT FROM curRoles
                INTO @ServerRole
    
            END
    
            --Cleanup.
            CLOSE curRoles
            DEALLOCATE curRoles
    
        END
        INSERT INTO @TempTable
        VALUES(@Script)
    
        FETCH NEXT FROM CURLOGIN INTO @Login
    END
    CLOSE CURLOGIN;
    DEALLOCATE CURLOGIN;
    SELECT Script FROM @TempTable'
    
    $Result=executequery $Query $QueryTimeout $Server
    
    If($Result -eq $null)
        {
            break
        }
    Else
        {
            [Void][System.IO.Directory]::CreateDirectory("C:\temp")
            $Path = "C:\temp"
            $Acl = (Get-Item $Path).GetAccessControl('Access')
            $Username = Get-WmiObject win32_service | Where name -EQ 'SQLSERVERAGENT' | Select -ExpandProperty StartName
            $Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($Username, 'Full', 'ContainerInherit,ObjectInherit', 'None', 'Allow')
            $Acl.SetAccessRule($Ar)
            Set-Acl -path $Path -AclObject $Acl
            $Result | select -ExpandProperty Script | Out-File C:\temp\Script.txt
        }
    }
    
    
    ###########################################################
    # SCRIPT BODY 
    ###########################################################
    
    $Query= "SELECT ISNULL(SERVERPROPERTY ('InstanceName'), 'DEFAULT') InstanceName 
                , name AGName
                , replica_server_name Replica
                , role_desc 
                FROM sys.dm_hadr_availability_replica_states hars 
                INNER JOIN sys.availability_groups ag ON ag.group_id = hars.group_id 
                INNER JOIN sys.availability_replicas ar ON ar.replica_id = hars.replica_id
                WHERE role_desc = 'PRIMARY'
                ORDER BY role_desc asc"
    Write-Host "Is this Primary Replica?"
    $Result=executequery $Query $QueryTimeout $PrimaryReplica
    If ($Result -eq $null)
        {
            Write-Host "No, it's not."
            break
        }
    Else
        {
            Write-Host "Yes, it is."
            $PrimaryReplica= $Result | select -ExpandProperty Replica
            Write-Host "Check for prerequisite, if not present deploy it."
            CheckStoredProc -Server $PrimaryReplica
            Write-Host "Get script for new/modifies login(s)."
            Get-Script -Server $PrimaryReplica
    
            $Query= "SELECT ISNULL(SERVERPROPERTY ('InstanceName'), 'DEFAULT') InstanceName 
                        , name AGName
                        , replica_server_name Replica
                        , role_desc 
                        FROM sys.dm_hadr_availability_replica_states hars 
                        INNER JOIN sys.availability_groups ag ON ag.group_id = hars.group_id 
                        INNER JOIN sys.availability_replicas ar ON ar.replica_id = hars.replica_id
                        WHERE role_desc = 'SECONDARY'
                        ORDER BY role_desc asc"
    
            $Result=executequery $Query $QueryTimeout $PrimaryReplica
            $SecondaryReplicas= $Result | select -ExpandProperty Replica
            $Query= Get-Content -Path 'C:\temp\Script.txt' | Out-String
            ForEach($SecondaryReplica in $SecondaryReplicas)
                {
                    Invoke-Sqlcmd -Query $Query -ServerInstance $SecondaryReplica
                    Write-Host "Successfully copied login(s) to $SecondaryReplica"
                }
            Remove-Item C:\temp\Script.txt
        }
    
    • 1
  4. user70509
    2015-07-14T10:52:48+08:002015-07-14T10:52:48+08:00

    您必须使用 Windows 域登录并在每个实例中创建它们,由于 SID 由活动目录管理,如果登录存在于主副本中,您将能够访问可用性组的所有副本成员。另一种选择,您必须使用证书。

    • -1

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何查看 Oracle 中的数据库列表?

    • 8 个回答
  • Marko Smith

    mysql innodb_buffer_pool_size 应该有多大?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    从 .frm 和 .ibd 文件恢复表?

    • 10 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve