Hello All,I thought I'd share my solution to this problem after numerous searches on Google and not finding a solution to fit my particular needs.Summary: We are not using contained databases (haven't even dug into this topic). We have two SQL servers, I'll call SQLA (Primary) and SQLB (Secondary) in an AlwaysOnAvailability Group cluster, called SQLCluster1. As we add databases to the cluster, we have SQL logins that need to be maintained between the two SQL servers. When we add our customer databases, I have a powershell script that automatically provisions the database and adds it to my SQLCluster1 availability group.Problem: If you create a SQL login on SQLA, let's call it "sqluser", and then also create the same SQL login on SQLB, they will not be the same (they may appear to be). When we perform a failover to SQLB, the failed over database(s) that uses our "sqluser" SQL login would have permission issues when trying to authenticate. Why? Remember when I said they weren't the same, even though they appear to be?If you run [code="sql"] use master;select * from syslogins [/code]against both SQLA and SQLB, and search for our "sqluser" under the [b]name[/b] column, you'll notice that their [b]sid[/b] values are completely different.This problem is explained in more details in the links below:https://www.sqlskills.com/blogs/jonathan/synchronize-availability-group-logins-and-jobs/http://dba.stackexchange.com/questions/29903/logins-arent-syncing-across-availability-groupsMy Resolution to this issue:I used the solution provided by Microsoft in this article https://support.microsoft.com/en-us/kb/918992. It works nicely, because it iterates through all the SQL logins on SQLA and generates the CREATE statements I can run on SQLB to create the exact same SQL login with the exact same SID and Password . This is nice, but I wanted to make this somewhat automatic, so I simply modified some of the logic in the sp_help_revlogin.Here's what I did:As a prerequisite, I went to each SQL server and added the other SQL replica as a linked server named "PARTNER", which makes it easier to reuse code that referenced the other SQL instance.I replaced the logic in sp_help_revlogin where it starts the [b]IF (@login_name IS NULL)[/b]. I commented out the original code and then put my own code in it's place. What this does is filters down the SQL logins I'm looking for to [b] ONLY [/b] SQL logins. The original code also included Windows Logins and disabled logins, but I wasn't concerned with those, so I wanted to filter things down.First, you'll want to make sure to declare a variable to hold some dynamic SQL, which will be used towards the end when we execute dynamic SQL against our [b]PARTNER[/b][code="sql"] DECLARE @SqlStmt varchar (MAX)[/code] [code="sql"]/*********************************************Added the logic for the PARTNER linked server**********************************************/DECLARE login_curs CURSOR FORSELECT p.sid, p.name, p.type, p.is_disabled, p.default_database_name, l.hasaccess, l.denylogin FROM sys.syslogins as l LEFT JOIN sys.server_principals as p ON( l.name = p.name ) LEFT JOIN PARTNER.master.sys.syslogins as rON l.name=r.name WHEREp.type = 'S' AND p.name <> 'sa' AND is_disabled <> 1 AND r.name IS NULL AND r.sid IS NULL AND l.isntuser <> 1 AND l.isntgroup <> 1 [/code]At the very end of the script, where it performs the last [b]PRINT @tmpstr[/b] r, I changed the code to build dynamic SQL into a variable, and then executed that dynamnic SQL, targeted towards my "PARTNER" linked server. [code="sql"] SET @SqlStmt= 'USE master;' + @tmpstr --execute the CREATE statement against our PARTNER, which is the secondary replica server. exec (@SqlStmt) AT PARTNER [/code]The end result?What this does is allows me to execute the sp_help_revlogin stored procedure during my powershell provisioning script. The stored procedure has been modified to search for SQL logins that exist on SQLA but don't have an exact match on SQLB (based on name AND/OR SID), generate the CREATE T-SQL, and then execute the T-SQL against SQLB (our [b] PARTNER [/b] from SQLA's perspective). At the end we would have our SQL logins on both SQLA and SQLB, and when we have a failover, we won't have any issues with permissions because the EXACT same SQL login now exists on both SQL servers (identical Names, SIDs, and Passwords).What this doesn't do: Unfortunately I haven't added the logic to check first to see if the SQL login may already exist (by [b] name [/b]) before I run my CREATE T-SQL. So this solution assumes that the SQL login simply just doesn't exist on SQLB.
↧