Contained Database–die Eigenständige Datenbank

Erst letzte Woche habe ich in meinem Blog nach Contained Databases gesucht .. und nichts gefunden. Wirklich peinlich! Gerade dieses kleine neue Gimmick des SQL Server 2012 ist für  mich eines des praktischsten und häufigst verwendeten neuen Features ab SQL Server 2012.

Zweck der Contained Database

Datenbanken können nicht ohne Systemdatenbanken leben. So werden beispielsweise Logins in der Master Datenbank gespeichert, temporäre Tabellen in der TempDB, Aufträge in der msdb. Dagegen ist überhaupt nichts einzuwenden. Aber sbald man ein Backup einer Datenbank auf einen anderen Server restored fehlen logischerweise wieder diese Dinge. Nicht – zumindest nicht ganz – bei einer Contained Database. Hier werden bspw. Logins in der Contained Database gespeichert und temporäre Tabellen ebenfalls dort erstellt. (zugegebenermaßen: Vor- und Nachteil).

Wie gehts?

Konfiguration des Servers

Bevor Contained Databases erstellt werden können muss auf dem Server die Option Einschlusstyp auf True gesetzt sein:

Das geht natürlich auch per Script:

EXEC sys.sp_configure N’contained database authentication‘, N’1′
GO
RECONFIGURE WITH OVERRIDE
GO

 

Anlegen einer Contained Database

Das Anlegen ist kurz und schmerzlos:

oder per Script natürlich:

USE [master]
GO
ALTER DATABASE [ContDB] SET CONTAINMENT = PARTIAL WITH NO_WAIT
GO

Interessanter ist schon die Tatsache, dass der Einschlusstyp entweder:

  1. Keine
  2. Teilweise

Nein es ist kein Fehler! Eine vollständige Kapselung einer Datenbank existiert auch nicht unter SQL Server 2014. In der Onlinedokumentation liest man zu folgendes:

Eine teilweise enthaltene Datenbank ist eine enthaltene Datenbank, die die Verwendung nicht enthaltener Funktionen zulässt.

Alles klar, oder?

Letztendlich bedeutet dies, dass es immer noch Dinge gibt, die nicht in der Contained Database vorgehalten werden, sondern immer noch ausserhalb aufgehoben werden. (Jobs, etc.)

Sehen wir uns mal ein paar Beispiele an.

Keine verwaisten User mehr

Legen wir mal einen User an, der nicht wi üblich einem Login (master Datenbank) zugeordnet wird.

 

USE [ContDB]
GO
CREATE USER [Seppl] WITH PASSWORD=N’123@zauberei‘
GO

Natürlich funktioniert das auch mit einem Windows Login

USE ContDB
CREATE USER [FBIss1]

Das Login – auf herkömmliche Art und Weise wird nun natürlich scheitern, da in der master kein Login enthalten ist.

Damit der Login gegenüber der Datenbank funktioniert muss diese explizit angegeben werden:

Das Schöne an der Geschichte ist, dass nicht nur Datenbanken inkl Logins nun leicht von Server zu Server gebracht werden können. (Das Backup selbst reicht ja schon aus), sondern auch Sicht der Administration. Die Benutzer ohne Login haben effektiv keine Zugriffsmöglichkeit auf anderen Datenbanken und noch besser sehen diese nicht einmal:

Allerdings sollte nicht unerwähnt blieben, dass per T-SQL immer noch ein wenig mehr gesehen werden kann.  Zumindest die master und die tempdb sind sichtbar und auch der Zugriff auf Systemsichten ist ebenso möglich. Allerdings ist das nur halb so schlimm, wie man nun denken würde, denn es werden nur Ergebisse zu sehen sein, die den jeweiligen Benutzer der Contained Database betreffen

Datenbankübergreifende Zugriffe?

Ja, das ist möglich. Notwendig dazu ist, dass die Contained Database auf vertrauenswürdig gesetzt ist:

ALTER DATABASE ContDB SET TRUSTWORTHY ON

Anschliessend muss die aktuelle Verbindung des Benutzer zurückgesetzt werden, damit die Änderung aktiv werden kann.

Entweder man schaltet den guest Account aktiv (nicht unbedingt das, was man gerne macht) oder man legt den Benutzer in der anderen Datenbank ebenfalls an.  Das funktioniert allerdings auch nur bei Windows Usern, da SQL Server intern immer SIDs verwendet. Im Falle eines SQL Users werden eigene SID generiert, im Falle von Windows Konten werden die Windows SID verwendet. Wenn man also einen weiteren SQL Benutzer in der Datenbank anlegt, wird dieser bei SQL Konten, defintiv eine andere SID besitzen.

Temporäre Tabellen

Ein weiterer Klassiker der Contained Database sind temporäre Tabellen. Verwendet man temporäre Tabellen, dann landen diese in der tempdb und nehmen dort auch die Sortierung der tempdb an. Weist jedoch aktuelle Datenbank eine andere Sortierung auf, kommt es zu einem Konflikt:

Ändert man die Datenbank auf eine Contained Database, funktioniert das plötzlich wieder:

Die temporäre Tabellen liegen aber nun nicht wirklich in der Contained Database, wie man immer wieder gerne mal liest, sondern nach wie vor in der tempdb, bekommt allerdings die Sortierung der Ursprungsdatenbank verpasst.

Das ist gut so, da die tempDB nach wie vor die Leistung von Auslagerungsvorgangängen übernehmen sollte.

Migration von Datenbanken und Benutzern in Contained Databases

Gelinde gesagt, ist die Migration einer Datenbank in eine Contained Database nichts anderes als das Aktvieren der Contained Database (siehe Einschlusstyp = True s.o.)

Für die Migration eines Benutzers steht explizit eine Prozedur zur Verfügung

sp_migrate_user_to_contained [ @username = ] N'user' ,     [ @rename = ] { N'copy_login_name' | N'keep_name' } ,     [ @disablelogin = ] { N'disable_login' | N'do_not_disable_login' }

Also beispielsweise:

sp_migrate_user_to_contained 
@username = N'Hias',@rename = N'keep_name',@disablelogin = N'do_not_disable_login' ;

Wobei keep_name den Benutzername des Benutzers in der Datenbank übernimmt, dagegen übernimmt copy_login_name den Loginnamen des Benutzers für die Contained Database.

Microsoft stellt dazu sogar ein Codesnippet zur Verfügung mit dem man alle Benutzer auf einen Schlag migrieren könnte.

http://technet.microsoft.com/de-de/library/ff929275.aspx

DECLARE @username sysname ;
DECLARE user_cursor CURSOR     FOR         SELECT dp.name         FROM sys.database_principals AS dp         JOIN sys.server_principals AS sp         ON dp.sid = sp.sid         WHERE dp.authentication_type = 1 AND sp.is_disabled = 0;
OPEN user_cursor
FETCH NEXT FROM user_cursor INTO @username     WHILE @@FETCH_STATUS = 0     BEGIN         EXECUTE sp_migrate_user_to_contained         @username = @username,         @rename = N'keep_name',         @disablelogin = N'disable_login';     FETCH NEXT FROM user_cursor INTO @username     END
CLOSE user_cursor ;
DEALLOCATE user_cursor ;
Einschränkungen und Tipps
  • Vermeiden Sie Logins mit gleichen Namen wie der Contained DB Benutzer. Falls doch, dann ändern sie beim Login die Standarddatenbank so, dass nicht gleich auf die ContDB zugegriffen wird. Sonst gibts Fehler bei der Anmeldung.
  • keine Kerberos Authentifizierung möglich
  • beim Anfügen einer Datenbank den Zugriff auf Restricted User stellen, um nicht unegwollte zugriffe auf dem SQL Server zu haben.
  • keine Replikation
  • kein CDT und CDC
  • keine temporären Prozeduren

PS: Die Contained Database nicht auf AUTO_CLOSE stellen. Ausnahme wäre 1.April Sobald die Datenbank geschlossen ist, gibts auch keine Anmeldung mehr.

 

Coole Sache.. und warten mal auf Einschlusstyp FULL

Fumus

View Comments

Share
Published by
Fumus

Recent Posts

SQL Server 2019 – static data masking – Du Opfer!

In SQL Server 2016 wurde das sog. dynamic data masking eingeführt. Eine Möglichkeit Daten bei…

5 Jahren ago

MinRole – Oder wie alles etwas einfacher wird

Seit Sharepoint Server 2007 präsentiert sich die Installation immer auf die gleiche Weise. Gerade mal,…

8 Jahren ago

Schritt für Schritt: SQL 2016 – Dynamic Data Masking

Es weihnachtet! Gerade bekam ich von einer Kollegin Plätzchen angeboten mit der Größe eines Diskus…

8 Jahren ago

Schritt für Schritt: SQL Server 2016 – temporal tables

Nein, bitte nicht verwechseln: temporal tables haben nichts zu tun mit temporary tables table variables…

9 Jahren ago

SQL Server 2016 Schritt für Schritt–Installation und First Look

SQL Server 2016.. habe ich schon erwähnt, dass ich den ziemlich cool finde? Wollen wir…

9 Jahren ago

SQL Server 2016 – CTP2

Nach langer Zeit wieder mal eine Artikel von mir.. der mich besonders erfreut. SQL Server…

9 Jahren ago