36-40 Weiss.indd

Werbung
36
Datenbanken
SQL Server 2008 FileStreams
Das Ende von NTFS?
Der neue SQL Server 2008 bietet mit den FileStreams eine
neue Möglichkeit zur Speicherung von BLOB-Daten
von Meinrad Weiss
Die Artikelüberschrift ist natürlich absichtlich provokativ: Obwohl es der neue Filestream-Datentyp von SQL Server 2008 erlaubt, Dateien effizient „im“ SQL Server 2008 zu speichern und er zudem noch diverse Managementvorteile bietet, gilt auch bei NTFS: Totgesagte leben länger. Denn
der Filestream-Datentyp benötigt für seine Existenz natürlich ein NTFS-Verzeichnis.
Sehr oft benötigt eine Applikation neben
relationalen Daten auch unstrukturierte Informationen in Form von Dateien,
z.B. Dokumenten, Musikdateien, Videos
kurz & bündig
Inhalt
Ein Überblick über die mit SQL Server 2008
eingeführten FileStreams
Zusammenfassung
Der neue FileStream-Typ ist ideal für die
Speicherung von typischen BLOB-Daten.
Auch wenn die Daten extern gelagert werden,
gehören sie zur Datenbank. Der Zugriff erfolgt
via SQL oder einer Win32-API, die am besten
in einer .NET-Klasse gekapselt wird. Es gibt
aber auch Nachteile. Insbesondere im Bereich von Backup und Restore
usw., also allgemein BLOBs. Bei den bisherigen Versionen war es schwierig, beide
Informationstypen effizient und sicher
zu verwalten. Grundsätzlich boten sich
zwei Varianten an: Entweder wurden die
unterschiedlichen Typen unterschiedlich
gespeichert, sprich die relationalen Daten in der Datenbank und die Dateien auf
dem Dateisystem, oder es wurde alles in
der Datenbank abgelegt.
Im gemischten Ansatz werden die
relationalen Daten in der Datenbank gespeichert. Zusätzlich zu den realen Daten
muss ein Link (Dateiname) zur Datei auf
dem Dateisystem verwaltet werden. Die
Datei selbst befindet sich, getrennt von
den strukturierten Daten, auf dem Datei-
system. Damit wird die Datenbank zwar
nur minimal belastet und dem Entwickler
steht ein sehr effizientes ProgrammierInterface zur Verfügung, aber dafür ist
das Management extrem schwierig und
aufwändig. So ist es zum Beispiel nahezu unmöglich, ein konsistentes Backup von Datenbank und Dateisystem zu
erstellen, ohne das System zu stoppen.
Der Datenbankansatz ist viel einfacher
aufgebaut und bietet entsprechende Managementvorteile. Es ist zum Beispiel trivial, ein konsistentes Backup zu erstellen,
und auch die Zugriffsrechte müssen nur
einmal definiert werden. Dafür müssen
aber auch gravierende Nachteile in Kauf
genommen werden. In den „Large Data
Quellcode (C#)
SQLServer2008FileStream.sln
Quellcode auf CD
4.08
Abb. 1: Das
Ergebnis einer
Abfrage
www.dotnet-magazin.de
SQL Server 2008 FileStreams
Types“ (varbinary(max)) können maximal zwei GB Daten gespeichert werden.
Zudem kann nur via SQL auf die Daten
zugegriffen werden und damit steht kein
einfach umzusetzendes Streaming-Interface zur Verfügung. Erschwerend kommt
noch hinzu, dass alle Manipulationen
durch den Datenbank-Kernel abgearbeitet werden müssen. Dies kann zu einer
enormen Belastung des TransaktionsLogfiles führen und wirkt sich negativ
auf die Cache-Hit-Ratio aus, da sehr viele
Data-Pages von den großen Objekten angesprochen werden.
Der goldene Mittelweg:
„Varbinary(max) Filestream“
Mit dem neuen Datentyp Varbinary(max)
Filestream bietet SQL Server 2008 den
goldenen Mittelweg. Aus Administrationssicht befindet sich alles in der Datenbank, dadurch vereinfacht sich der Betrieb
erheblich. Wer etwa Rechte auf die strukturierte Information besitzt, hat auch automatisch Zugriff auf die BLOB-Daten,
und ein Datenbank-Backup beinhaltet
alle „in“ der Datenbank gespeicherten
Informationen. In Wahrheit befindet sich
der Inhalt der Filestream-Attribute aber in
einzelnen Dateien auf dem Dateisystem.
Die so entstehenden Dateien werden aber
vom SQL Server selbständig verwaltet.
Ein Datentyp, zwei
Programmiermodelle
Auf Filestream-Daten kann entweder via
SQL oder mithilfe der Win32-API zugegriffen werden. Aus SQL-Sicht verhält
sich ein Filestream-Attribut wie ein normales varbinary(max)-Attribut. Der Unterschied zwischen einem varbinary(max)
und einem Filestream ist nur beim Erstellen der Tabelle sichtbar. Datenmanipulationen werden mit den bekannten Insert-,
Update- und Delete-Befehlen durchgeführt. Das Beispiel in Listing 1 zeigt den
Filestream-Datentyp im Einsatz. Damit
die Funktionsweise einfach sichtbar ist,
wird in das Filestream-Attribut ein Varchar-Wert: ‚Simple CV ...‘ geschrieben
und gelesen. Aus diesem Grund sind die
beiden Convert-Befehle notwendig. Normalerweise befinden sich in den BLOBAttributen binäre Objekte und dann entfallen diese Operationen.
Ein Drop Database bedeutet für eine
Datenbank nicht nur das Löschen der
www.dotnet-magazin.de
Daetnbanken
Abb. 2: Die
Sicht auf
das Dateisystem
Datenbank und Logfiles, sondern auch
das Löschen aller via Filestream erstellten Dateien. Deshalb kann ein „Drop
Database“ bei einer Datenbank mit vielen Filestream Datensätzen relativ lange
dauern. Einer der großen Vorteile des
Filestream-Datentyps ist die Tatsache,
dass neben dem normalen SQL-Interface auch direkt mit dem Win32-API auf
Filestream-Attribute zugegriffen werden
kann. Beim Zugriff via Win32 verhält
sich ein Filestream-Objekt wie eine normale Datei.
Den Zugriffspfad auf die „FilestreamDatei“ liefert die Methode PathName des
Filestream-Types. Zusätzlich zum Pfad ist
ebenfalls ein Transaktionskontext notwendig. Dieser Transaktionskontext kann
mit der Funktion Get_filestream_transaction_context() ermittelt werden. Das
einzige kleine Hindernis ist zurzeit noch
das Fehlen einer .NET-Klasse, welche das
Win32-Interface kapselt. Microsoft hat
allerdings angekündigt, eine entsprechende Klasse kurz nach der Fertigstellung des
SQL Server 2008 zu liefern. Zurzeit muss
man sich daher noch mit einer „WrapperAssembly“ begnügen. Weil aber lediglich
die eine Methode OpenSqlFilestream für
den Zugriff notwendig ist, ist eine solche
Assembly schnell erstellt – nachzulesen in
Listing 2.
Die Methode OpenSqlFilestream liefert eine Stream-Klasse zurück. Nach einem Aufruf von OpenSqlFilestream entspricht die .NET-Programmierung dem
Zugriff auf eine reguläre Datei. Das einzige, was hier speziell betrachtet werden
Listing 2
Ein Wrapper-Assembly erspart den direkten
Aufruf der Win32-API
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
namespace Trivadis.Training.SqlFilestream
{
public class SqlNativeClient
{
public const UInt32 DESIRED_ACCESS_READ =
0x00000000;
public const UInt32 DESIRED_ACCESS_WRITE =
0x00000001;
public const UInt32 DESIRED_ACCESS_READWRITE =
0x00000002;
Listing 1
[DllImport(“sqlncli10.dll“, SetLastError = true,
Das Anlegen einer Tabelle
mit FileStream-Attribut
public static extern SafeFileHandle OpenSqlFilestream(
CharSet = CharSet.Unicode)]
string FilestreamPath,
Create Table Person
UInt32 DesiredAccess,
(PERS_ID uniqueidentifier rowguidcol not null primary key
UInt32 OpenOptions,
,PERS_Name varchar(50)
byte[] FilestreamTransactionContext,
,PERS_CV varbinary(max) Filestream
UInt32 FilestreamTransactionContextLength,
)
LARGE_INTEGER_SQL AllocationSize);
insert Person(PERS_ID ,PERS_Name ,PERS_CV)
values
[StructLayout(LayoutKind.Sequential)]
(‘DF307D1E-7BDB-4CE0-9401-1BE15E14CE6A’
public struct LARGE_INTEGER_SQL
,’Muster Hans’
{
,Convert(Varbinary(max), ‘Simple CV ....’)
public Int64 QuadPart;
)
public LARGE_INTEGER_SQL(Int64 quadPart)
{ QuadPart = quadPart; }
select PERS_ID
,PERS_Name
}
,Convert(varchar, PERS_CV) as PERS_CV
}
from Person
}
4.08
37
38
Datenbanken
SQL Server 2008 FileStreams
Abb. 4: Der FileStreamZugriff muss administrativ
geregelt werden
Abb. 3: Ein Filestream kann via SQL oder Win32 angesprochen werden
muss, ist die Tatsache, dass während des
gesamten Zugriffs eine SQL-Transaktion
bestehen muss, damit der SQL-Server die
Multi-User-Zugriffsfragen regeln kann –
wie in Listing 3 dargestellt ist.
Ohne DBA läuft gar nichts
Bevor der Filestream-Datentyp verwendet werden kann, muss der Datenbankadministrator den Filestream-Service
zulassen. Dabei kann festgelegt werden,
ob nur mit SQL gearbeitet werden kann
oder ob auch das Win32-Interface lokal
beziehungsweise auch Remote verfügbar ist.
Anschließend kann beim Erstellen
der Datenbank festgelegt werden, auf
welchen Laufwerken die FilestreamDaten gespeichert werden. Zu diesem
Zweck können die Filestream-Dateigruppen mit Contains FileStream
gekennzeichnet werden. Der SQL Server
alloziert zu diesem Zeitpunkt keinen
Platz für die Filestream-Filegruppe(n).
Dieser wird erst später von den darin angelegten Dateien beansprucht. Die Größe der Dateien ist nicht mehr durch den
SQL Server auf zwei Gigabyte limitiert,
wie das bei normalen varbinary(max)Attributen der Fall ist. Die Größe wird
ausschließlich durch den auf dem Dateisystem verfügbaren Platz limitiert. Mit
Listing 3
Beim FileStream-Zugriff muss eine SQL-Transaktion eingerichtet werden
private void btnReadContent_Click(
object sender, EventArgs e)
{
// Open file handle to media stored in SQL Server.
SafeFileHandle safeFileHandle = SqlNativeClient
OpenDBConnection();
.OpenSqlFilestream(
sqlFilePath.Value,
SqlNativeClient.DESIRED_ACCESS_READ,
// Start a transaction
0,
SqlTransaction sqlTransaction = sqlConnection
transactionToken.Value,
.BeginTransaction();
(UInt32)transactionToken.Value.Length,
// Build select statment and pass params.
new SqlNativeClient.LARGE_INTEGER_SQL(0));
SqlCommand cmd
= new SqlCommand(“SELECT PERS_CV.PathName() “
+ “,GET_FILESTREAM_TRANSACTION_CONTEXT() “
// Back to traditional Filestream world
FileStream fileStream = new FileStream(safeFileHandle
,FileAccess.Read);
+ “ FROM Person “
+ “ WHERE PERS_ID = @PERS_ID;“
,sqlConnection
// Simplified Version. I know the content for my demo is
,sqlTransaction);
cmd.Parameters.Add(“@PERS_ID“, SqlDbType
.UniqueIdentifier).Value
= new Guid(txtPERS_ID.Text);
// Execute query and read results.
SqlDataReader rdr = cmd.ExecuteReader(
CommandBehavior.SingleRow);
rdr.Read();
SqlString sqlFilePath = rdr.GetSqlString(0);
SqlBinary transactionToken = rdr.GetSqlBinary(1);
rdr.Close();
4.08
TextReader textReader = new StreamReader(fileStream);
// very small
txtContent.Text = textReader.ReadToEnd();
// Close the reader, stream and handle
textReader.Close();
fileStream.Close();
safeFileHandle.Close();
// Commit Transaction and close connection
sqlTransaction.Commit();
sqlConnection.Close();
}
SQL Server 2008 müssen die FilestreamDaten auf einem lokalen Drive des Datenbankservers gespeichert werden. Die
Filestreams einer Tabelle können mittels
Partitionierung der Tabelle auf mehrere
Dateigruppen verteilt werden.
Eine Transaktion ist
der Schlüssel zu den Daten
Bei der Verwendung von Filestream-Daten muss der SQL Server 2008 in der Lage
sein, Zugriffe parallel von SQL-Interface
wie auch via Win32-API zuverlässig zu
verwalten. Damit keine Concurreny-Probleme auftreten, ist es ebenfalls notwendig, auch bei der Win32-Programmierung eine offene Transaktion zu besitzen.
So kann der SQL Server den Zugriff auf
seine Objekte in gewohnter Manier mit
Locks in der Datenbank regeln. Wenn
versucht werden sollte, ohne eine laufende Transaktion auf Filestream-Daten
zuzugreifen, quittiert der SQL Server die
Anfrage mit „Invalid Handle“. Mit dem
SQL Server 2008 wird lediglich der Isolation Level „Read Commited“ für den
Datenzugriff via Win32 unterstützt. Die
Filestream-Daten verhalten sich bezüglich Transaktionen wie normale Attribute in der Datenbank. Das bedeutet, dass
Insert-, Update- und Delete-Operationen mit einem Rollback rückgängig gemacht werden können. Die gilt sowohl
für Zugriffe via SQL wie auch für das
Win32-Interface.
Architektur
Für die Integration des Win32-Zugriffs
in die Datenbank-Transaktionslogik
wird mit der Installation von SQL Server 2008 ein neuer Dateisystemtreiber
(FS Driver) installiert. Dieser prüft vor
jedem Zugriff auf die Daten die SecurityDefinitionen innerhalb der Datenbank
und auch die Existenz einer gültigen
Transaktion.
Innerhalb der Datenbank steht dem
FS-Driver der FS-Agent zur Verfügung.
Dieser kommuniziert mit dem Datenbank-Kernel und überprüft die Gültigkeit
www.dotnet-magazin.de
SQL Server 2008 FileStreams
des Tokens und der Transaktion wie auch
das Zugriffsrecht auf das BLOB-Attribut.
Die Filestream-Daten werden von den
Clients durch einen speziellen FS-DriverShare angesprochen, der vom SQL Server
selbständig verwaltet wird.
SQL Server-Failover-Cluster können
auch mit Filestream-Daten aufgebaut
werden. Dabei ist es allerdings notwendig,
dass sich alle Filestream-Dateien auf einem
Shared-Drive des Clusters befinden, damit
diese bei einem Failover auf dem RemoteNode auch zur Verfügung stehen.
Daetnbanken
Abb. 5: Das
Zusammenspiel
zwischen Client
und Datenbank
läuft über einen
eigenen Dateisystemtreiber
Auch Filestreams haben ihren Preis
Ganz spurlos geht der Einsatz von Filestream nicht an der Datenbank vorbei.
Die größten Auswirkungen werden im
Bereich von Backup und Restore spürbar. Über das Win32-Interface können
Daten sehr effizient in die Datenbank gebracht werden. Der Schreibvorgang der
Filestream-Daten hat dabei nur minimalen Einfluss auf das Transaktions-Log, da
nur die Tatsache, dass geschrieben wird,
im Log vermerkt wird. Beim Backup des
Transaktion-Logs müssen aber alle Veränderungen aufgezeichnet werden. Damit
werden die Log-Backups entsprechend
größer und dauern länger. Das muss bei
der Planung des Backup Konzeptes mit
berücksichtig werden.
Die Auswirkungen im Restore Fall
sind noch größer: Wenn bei einer Datenbank mit Filestream-Attributen die
Festplatte mit den Filestream-Daten
ausfällt, kann ein Datenverlust, selbst im
„Full Recovery Model“, nicht vermieden werden. Da das Transaktions-Log
nur die Tatsache von Updates, nicht aber
die konkreten Update-Daten beinhaltet,
können alle Änderungen an FilestreamDaten nach dem letzten TransaktionsLog-Backup nicht mehr wiederhergestellt werden. Verloren gehen aber nur die
Änderungen der Filestream-Attribute.
Dies kann aber zu einer „inkonsistenten“
Datenbank führen. Aus diesem Grund
Abb. 6: Für den FS-Driver wird ein eigener Share angelegt
müssen die Filestream-Daten auf einer
möglichst ausfallsicheren Disk (RaidArray) gespeichert werden. Mit sehr regelmäßigen Transaktions-Log-Backups
können die Auswirkungen eines trotzdem auftretenden Laufwerksverlusts minimiert werden. Zudem werden diverse
Datenbankfeatures im Zusammenhang
mit Filestreams nicht unterstützt.
Es ist zum Beispiel nicht möglich, einen kompletten Snapshot einer Datenbank mit Filestream-Dateigruppen zu
erstellen. Die Snapshot-Datenbank darf
nur die Nicht-Snapshot-Dateigruppen
beinhalten, und Abfragen auf dem Snapshot müssen die Filestream-Attribute ausklammern. Database Mirroring wird zusammen mit Filestreams überhaupt nicht
unterstützt. Interessanterweise ist dafür
Log-Shipping möglich, wenn beide Server mit SQL Server 2008 betrieben werden und Filestream auf beiden Systemen
erlaubt ist. Es ist auch nicht möglich, eine Transparent Database Encryption im
Zusammenhang mit Filestream zu verwenden. Ebenso wenig können die neuen
SQL Server 2008 Table-Parametertabellen mit Filestream-Attributen definiert
werden.
Filestreams sind ideal
für BLOB-Daten
Mit dem neuen Filestream steht bei SQL
Server 2008 ein für BLOB-Daten extrem
praktischer Datentyp zur Verfügung.
Dieser erleichtert das Erstellen von Applikationen, die sowohl strukturierte wie
nicht strukturierte Informationen verwalten müssen, erheblich. Der Datentyp
stellt via das Win32-API ein effizientes,
streamingfähiges Programmiermodell
für den Zugriff auf die BLOB-Daten
zur Verfügung. Da alle Daten logisch in
der Datenbank gespeichert sind, können die Zugriffsrechte elegant an einem
Ort verwaltet werden. Grundsätzlich
vereinfacht sich dadurch das Management des Systems bis hin zu Backup- und
Restore-Fragen. Einige Details, wie eingeschränkte Isolation-Level und Replikations-Möglichkeiten oder fehlender
Mirroring- und Encryption-Support
müssen allerdings bei der Verwendung
schon berücksichtigt werden. Da Filestreams im Hintergrund auf dem NTFSDateisystem aufbauen, wird NTFS die
Anwender noch für lange Zeit begleiten
und zusammen mit Filestream noch viele
gute Dienste leisten.
Meinrad Weiss ist Principal Consultant bei
Trivadis und Microsoft Regional Director für die
Schweiz. Seine Erfahrungen reichen von DBATätigkeiten über Applikations-Entwicklung bis zum
Design von verteilten Datenbanken. In den letzten
Jahren hat er sich vor allem mit den Bereichen
Data Warehousing, OLAP/Analysis Services und
.NET beschäftigt.
39
Herunterladen