Archive for the ‘Computer’ Category

Heute habe ich wieder ein Highlight beim SQL-Server gefunden, was die Arbeit mit dieser Datenbank erheblich erleichtert. Ich hatte ein Problem und zwar mußte ich eine Hirachie und den entsprechenden Pfad aus der Datenbank ziehen.

Mein erster Gedanke war eine recursive Table-Valued-Funktion, die mir das Ergebnis zurückliefert. Das geht nun einfacher (leider erst im SQL-Server 2005):


declare @trenner nvarchar

set @trenner = '~';

WITH StructReports ( STRUKTURELEMENT_ID, VATER_STRUKTURELEMENT_ID, NAME , Level, path)
AS
(
-- Anchor member definition
SELECT
STRUKTURELEMENT_ID,
VATER_STRUKTURELEMENT_ID,
NAME ,
0 AS Level,
se.NAME as path
FROM dbo.Strukturelement as se
WHERE VATER_STRUKTURELEMENT_ID is null

UNION ALL

-- Recursive member definition

SELECT
se.STRUKTURELEMENT_ID,
se.VATER_STRUKTURELEMENT_ID,
se.NAME ,
Level +1,
sv.path + @trenner + se.Name as path
FROM dbo.Strukturelement as se
inner join StructReports as sv
on se.VATER_STRUKTURELEMENT_ID = sv.STRUKTURELEMENT_ID
)

Select * from StructReports r
order by path

Es ist zwar nicht eine so elegante Lösung, wie es Oracle mit dem Befehl “connect by” geschaft hat, aber es ist auch nicht schlecht.

Die hier gezeigt Möglichkeit gibt recursive die alle Elemente der Tabelle “Strukturelemente” zurück. Ein Struktur kann eine Verzeichnisstruktur oder eine Katalog sein, wie jeder mag. Hier hat sich Microsoft doch eine gute Methode einfallen lassen wie man endlich in der 9. Version des SQL-Servers Baumstrukturen per Select abrufen kann.

Habe mal wieder versucht unter Windows 2000 die üblichen Updates Microsoft-Update herunterzuladen. Habe dabei eine Fehlernummer bekommen (0x80072EE2) natürlich ohne Hinweis was zutun ist. Also mußte man wieder eine Suchmaschine bemühen, um annähernd einen Hinweis darauf zu bekommen was los ist.

Habe auch einen Microsoft Knowledge Base gefunden, der mir bei dem Problem helfen sollte, 836941, nach dem durchlesen stellte ich aber fest, das ich keine dieser beschrieben Probleme hatte. Also habe ich auf den bewärten Trick aus meinem Blogeintrag Window-Update – Fehler 0×8DDD0009 zurückgeriefen. Ich brauchte nur das SoftwareDistributionsverzeichnis zu löschen, dann ging es.

Es lag wohl daran, das nach einem Update des Software-Update-Active-X-Controls (man ist das ein langes Wort) der Verzeichnisinhalt nicht ganz paßt.

Auf alles Fälle geht alles wieder …. hoffe damit auch anderen geholfen zu haben …

Die Sicherung des Transaktionslogs ist eines der wichtigsten Dinge, die ein DBA einer Datenbank verstehen sollte. Den nur mit dem Transaktionslog können Datenbanken wieder bis zum Zeitpunkt des Crashs vollständig wiederhergestellt werden.

Zu diesem Thema habe ich unter http://www.insidesql.de/beitraege/administration/best_practice_fuer_log_files.html einen schönen Beitrag von Jonathan van Houtte gefunden, den ich hier nicht vorenthalten möchte.

Empfehlungen für Log Files für OLTP Datenbanken:

1: OLTP Produktionsdatenbanken sollten so gut wie nie die Datenbankoption “trunc. log on chkpt.” verwenden.

Die einzigen Vorteile dieser Einstellung sind:

  • daß man sich keine Gedanken über die Wartung (Backup) des Transaktionsprotokolls zu machen braucht
  • daß die “Gefahr”, kein Speicherplatz mehr zur Verfügung zu haben, weniger wahrscheinlich wird

Nachteile dieser Einstellung sind

  • Schlechtere Performance aufgrund des laufenden Truncate Prozesses
  • keine Point in time Wiederherstellungsmöglichkeit
  • keine Möglichkeit, den Zustand bis zum Zeitpunkt des Fehlers wiederherzustellen

Trifft man die Entscheidung, daß eine Wiederherstellung des letzten vollständigen oder differentiellen Backup’s ausreichend ist, dann gibt man Erfahrung zugunsten von Bequemlichkeit auf.

2: Wird das Transaktionsprotokoll nicht gesondert gesichert, kann es auch nicht verkleinert werden. Ein vollständiges oder differentielles Backup verkleinert nicht das Transaktionsprotokoll.

3: Transaktionsprotokoll Backup’s sind losgelöst von anderen Backup’s und können unabhängig davon wiederhergestellt werden. Angenommen, Sie führen ein vollständiges Backup jede Nacht durch und sichern das Transaktionsprotokoll zweimal im Laufe des Tages. Finden Sie jetzt heraus, daß das letzte nächtliche Backup korrupt ist, können Sie das aus der Nacht zuvor wiederherstellen (WITH NORECOVERY!) und anschliessend die Log Backup’s wiederherstellen, um einen möglichst aktuellen Stand zu erreichen.

4: Das erste, was Sie in einem Disaster Fall machen sollten, ist, versuchen das Transaktionsprotokoll zu sichern. DBA’s, die ich unterrichte, werden darauf gedrillt.

5: Verwenden Sie SQL Server 7 und setzen die Einstellung “select into/bulkcopy” auf Wahr, um beispielsweise Daten aus einer Textdatei schnell zu laden, sollten Sie direkt danach die Einstellung wieder auf Falsch setzen, das Transaktionsprotokoll und dann die Datenbank sichern. SQL Server 2000 and höher können die Änderungen mit ihrem Bulk-Logged Recovery Model wiederherstellen. Allerdings nicht auf der einzelnen Vorgangsebene. Die Verwendung dieses Modells und Durchführung einer Bulk-Logged Operation verhindert Point in time Wiederherstellung (mit der dafür notwendigen Transaktionsprotokollsicherung) und limitiert Ihre Möglichkeiten, auf eine Korrumpierung Ihrer Datenbankdateien zu reagieren. Speichern Sie in der Datenbank unternehmenskritische dynamische Daten, sollten Sie sich genau überlegen, ob Sie die Fehlertoleranz des Full Recovery Models aufgeben zugunsten der Performance des Bulk-Logged Modells. Bedenken Sie dabei auch, daß auch SELECT INTO, CREATE INDEX, WRITETEXT und UPDATETEXT minimal protokollierte Operationen sind, genauso wie die offensichtlicheren BULK COPY und bcp.

6: Führen Sie die Transaktionsprotokollsicherung vor einem vollständigen oder differentiellen Backup durch statt danach. Sichern Sie das Transaktionsprotokoll nach der Datenbank, müssen Sie dieses Log Backup zusätzlich wiederherstellen, wenn Sie das Datenbankbackup wiederherstellen.

7: Verkleinern Sie nicht das Transaktionsprotokoll nur um des Verkleinerns willen. Die Protokolldateien sollten so dimensioniert sein, daß sie die maximale Menge an protokollierten Informationen zwischen zwei Backup Vorgängen aufnehmen können. Bestehen Sie auf der Verkleinerung, werden die Dateien vergrößert, wenn dies notwendig ist. Dies wiederum geht auf die Performance des Gesamtsystems, da Prozessorleistung für den Autogrow Vorgang benötigt wird und führt ferner zu Dateifragmentierung. (Gleiches gilt übrigens auch für Datendateien. Erwarten Sie, daß die Datenbank auf eine Größe von 20 GB anwachsen wird, sollten Sie auch diesen Speicherplatz direkt bei Erstellung der Datenbank allokieren).

8: Vergewissern Sie sich, daß Sie in einem Disasterfall in der Lage sind, eine Datenbank auf den aktuellsten Stand wiederherzustellen. Erstellen Sie eine Testdatenbank und warten diese exakt so, wie Ihre Produktionsdatenbanken. Führen Sie dann eine Notfallübung durch, indem Sie simulieren, daß die Hardware mit den Datendateien mit einem Fehler ausfällt. (Was ist das Erste, was Sie in einem solchen Fall machen? Punkt 4!). Überprüfen Sie Ihre Bandsicherungen und Wiederherstellungpläne wenigstens vierteljährlich, bzw, immer dann, wenn sich etwas in Ihrem Backup Prozess verändert. Sie können sich nur dann sicher sein, daß Ihre Backup funktionieren, wenn Sie sie ausprobieren und weiderherstellen; und sicherlich wollen Sie das nicht erst auf die harte Tour herausfinden. Üben Sie ebenso die Point in time Wiederherstellung. Ich bin dafür bekannt, die WHERE Klausel im DELETE Statement anzugeben.

9: Festplatten und andere Hardware werden irgendwann ausfallen. Die Frage ist nicht, ob, sondern, wann.

10: Sichern Sie die Datenbankdateien (mdf, ndf und ldf) erst dann, wenn Sie vorher die Datenbank mit sp_detach offline genommen haben oder den SQL Server Dienst gestoppt haben. Diese “Backup’s” sind nicht verwendbar mit differentiellen oder Transaktionsprotokollbackup’s. Auch wenn Sie später SQL Server verwenden, um sie zu sichern und mit No RECOVERY wiederherzustellen. Müssen Sie ein Backup Utility ohne nativen SQL Server Support verwenden, verwenden Sie SQL Server, um die Datenbanken und Transaktionsprotokolle auf Festplatte zu sichern (aber bitte auf einer separaten physikalischen Platte!) und verwenden anschließend Ihr Backup Utility, um diese Backup Dateien zu sichern. Sichern Sie auf einen anderen Server, beachten Sie bitte, daß der Service Account mit dem SQL Server oder der SQL Server Agent gestartet wird, ein Domänen User sein muß, der auch auf dem Remote Server angelegt sein muß. Zusätzlich sollte ein RESTORE VERFIYONLY angewendet werden, wenn auf einen Remote Server gesichert wird.

11: Löschen oder überschreiben Sie kein Backup, solange Sie nicht wenigstens zwei voneinander unabhängige Wiederherstellungsalternativen haben (siehe Punkt 3:).

12: Logging läßt sich nicht abschalten. Es ist ein integraler Bestandteil von SQL Server und garantiert die ACID Eigenschaften des Systems.

13: Verwenden Sie einen Write-Cache Disk Controller, stellen Sie sicher, daß sein Speicher redundant ist und batteriebetrieben. Lernen Sie, wie man seinen Speicher im Falle eines Disasters wiederherstellt. Deaktivieren Sie Caching auf den Platten selbst.

14: Stellen Sie sicher, daß die Transaktionsprotokolle auf redundanten physikalischen Platten sind und nicht auf dem gleichen Array wie die Daten. RAID 1 ist ideal für Transaktionsprotokolle, da ihr typischer I/O (im Gegensatz zu den Datendateien) sequentiell ist. Haben Sie mehrere Datenbanken gleichzeitig in Benutzung, kann es sinnvoll sein, jedes Transaktionsprotokoll auf einem eigenen RAID1 Platten Paar zu haben; anderenfalls könnte auf dem sequentiellen I/O ein random I/O werden.

Ja, gestern wollte ich einfach nur dividieren. Einen Dividenden durch einen Divisor, das ergibt ja einen Quotienten … :-)

Klingt ganz einfach … denkste … auf dem SQL-Server ist es das nicht, wie ich spüren musste. Eigentlich wollte ich eine ganz einfache Rechnung durchführen. In einer Tabelle A gibt es zwei Integerspalten X und Y diese beiden Spalten sollten gegeneinander verrechnet werden.

Folgendes SQL-Stament habe ich verwendet:

select X/Y as Quotient from A

die ersten Tests sahen auch vielversprechend aus.

Hier eine kleine Übersicht:

4 / 2 = 2
64 / 4 = 16

Beim weiteren Test ergab sich folgende Situation:

50 / 4 = 12
5 / 3 = 1

Das machte mich dann doch etwas stutzig, da ich das vom SQL-Server nicht gewohnt war. Ein Blick in die Dokumentation bestätigt, der SQL-Server macht eine Integerdivision.

Ich hätte nie gedacht, dass der SQL-Server eine Integer-Division durchführt, nach dem gesunden Menschenverstand erwartet man, das hier eine Gleitkommazahl herauskommt.

Hier verhält sich der SQL-Server nicht so wie es andere Datenbanken tun. Oracle, Access und MySQL tun dies richtig. Das ist sehr ärgerlich, denn jetzt muss ich bei einer normalen Division noch eine Typenbetrachtung durchführen.

Ist zwar einfach, aber ärgerlich, das Statment würde jetzt zum Beispiel so aussehen:

select X/cast(Y as float) as Quotient from A

Dann gibst das richte Ergebnis:

50 / 4 = 12,5
5 / 3 = 1,6667

Ich frage mich nur, muss das sein … Microsoft macht es den Entwicklern wieder besonders schwer. Einen Entwickler kann man das ja noch zutrauen, aber viele meiner Kunden, verwenden den SQL-Server für Abfragen. Ob denen das Problem so bewusst ist? Ich werde sie darauf hinweisen, aber was ist mit dem Rest der Welt ….

Die Gründe von Microsoft werde ich wahrscheinlich nie verstehen … wie so manches anderes

Man lernt ja nie aus, nach jahrelanger SQL-Erfahrung stand ich nun vor dem Problem aus einer Textspalte einer SQL-Server-Datenbank alle Werte mit einem ‘%’-Zeichen zu extrahieren. Einfacher gesagt als getan, den das ‘%’-Zeichen ist ein Platzhalter für beliebige Zeichen. Da mußte ich also doch Dokumentation wälzen und habe dann den Befehl gefunden, der hilfreich ist.

Man erweitert den LIKE Operator um den die Answeisung ESCAPE, dann klappt es.

match_expression [NOT] LIKE pattern [ESCAPE escape_character]

Im Beispiel sieht das so aus:

SELECT foo FROM batz WHERE txt LIKE '% 19!%' ESCAPE '!'

Hier ist das !-Zeichen das Escapezeichen für Prozent. Das tolle dabei ist, das der Escapecharakter seperat definiert werden kann, den man weis ja nie wie eine Bedingung aussehen kann und der SQL-Server kann nicht raten.

Das tolle bei dem SQL-Befehl ist, das er auch bei Oracle-Datenbanken funktioniert, und kann so in datenbankunabhänigigen Prgrammen verwendet werden.

Heute wollte ich in Word eine Seite im Querformat in eine Dokument Einschieben das eigentlich im Hochformat eingerichtet war. Nach einiger Sucherei hab ich es dann gefunden, war einfacher als ich dachte. Da hat Microsoft doch gut mitgedacht.

Wer das so etwas auch in Word lösen möchte geht wie folgt vor:

  1. Am Ende der letzten Seite die hochformtig ist, fügst Du einen manuellen Abschnittwechsel ein (Einfügen -> Wechsel -> Abschnittwechsel (nächste Seite))
  2. Jetzt setzt Du den Cursor auf die neue erste Seite nach dem Abschnittwechsel und wählst als Format Querformat aus (Datei -> Seite einrichten -> Ausrichtung Quer)

… jetzt müßte der neue Abschnitt quer sein, während die Seiten davor weiter hochformatig sind. Dieses Spielchen läßt sich beliebig oft wieder holen.

Heute hatte ich wieder ein interessantes Problem im SQL-Server 2005. Ich musste eine Prozedure schreiben die Transactionssicher war, das heißt die Veränderungen im Fehlerfalle richtig zurücknimmt, aber auch ein Rollback durch äußere Transaktionen zuläßt.

Hier die Lösung die ich gefunden habe:


CREATE PROCEDURE [dbo].[UpdateOrInsertValue]

@Key int, --Primary Key
@Value money = 0 --Value

AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

DECLARE @TranCounter INT;
SET @TranCounter = @@TRANCOUNT;
IF @TranCounter > 0
SAVE TRANSACTION VerteilungNachMonatenSpeichern;
ELSE
-- Procedure must start its own
-- transaction.
BEGIN TRANSACTION;

BEGIN TRY

-- Monat 1
UPDATE table1 SET Wert = @Value WHERE (ID = @Key)
if @@ROWCOUNT <1
Insert into Table1 (ID, Wert) values (@Key, @Value)

IF @TranCounter = 0
COMMIT TRANSACTION;

END TRY
BEGIN CATCH
IF @TranCounter = 0
-- Transaction started in procedure.
-- Roll back complete transaction.
ROLLBACK TRANSACTION;
ELSE
-- Transaction started before procedure
-- called, do not roll back modifications
-- made before the procedure was called.
IF XACT_STATE() <> -1
-- If the transaction is still valid, just
-- roll back to the savepoint set at the
-- start of the stored procedure.
ROLLBACK TRANSACTION VerteilungNachMonatenSpeichern;
-- If the transaction is uncommitable, a
-- rollback to the savepoint is not allowed
-- because the savepoint rollback writes to
-- the log. Just return to the caller, which
-- should roll back the outer transaction.

-- After the appropriate rollback, echo error
-- information to the caller.
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;

SELECT @ErrorMessage = ERROR_MESSAGE();
SELECT @ErrorSeverity = ERROR_SEVERITY();
SELECT @ErrorState = ERROR_STATE();

RAISERROR (@ErrorMessage, -- Message text.
@ErrorSeverity, -- Severity.
@ErrorState -- State.
);
END CATCH

END
GO

Heute hatte ich ein ziemlich heftiges Problem mit einer ASP.Net-Installtion auf meiner Workstation, kann aber sicher auch auf Windows-Servern auftreten. Ich hatte eine funktionierende ASP.Net-Installation in meinem IIS, alles tat wunderbar. Eigentlich hatte ich nichts daran verändert, außer die üblichen Microsoft-Updates, diese müssen sich auf den IIS so ausgewirkt haben, das nix mehr ging. Ich würde es auf ein SP1 des Visual-Studio2005 schieben, das hat ja einige Änderungen am .Net-Framework vorgenommen. Möglicherweise ist beim Update was nicht korrekt aktualisiert worden.

Auf alle Fälle war aus die Maus, alle Webs meldeten folgenden Fehler:

Der Pfad /LISgoogleEarth/App_GlobalResources/ konnte nicht zugeordnet werden.
Beschreibung: Unbehandelte Ausnahme beim Ausführen der aktuellen Webanforderung. Überprüfen Sie die Stapelüberwachung, um weitere Informationen über diesen Fehler anzuzeigen und festzustellen, wo der Fehler im Code verursacht wurde.

Ausnahmedetails: System.InvalidOperationException: Der Pfad /LISgoogleEarth/App_GlobalResources/ konnte nicht zugeordnet werden.

Quellfehler:

Beim Ausführen der aktuellen Webanforderung wurde einen unbehandelte Ausnahme generiert. Informationen über den Ursprung und die Position der Ausnahme können mit der Ausnahmestapelüberwachung angezeigt werden.

Stapelüberwachung:

[InvalidOperationException: Der Pfad /LISgoogleEarth/App_GlobalResources/ konnte nicht zugeordnet werden.]
System.Web.Hosting.HostingEnvironment.MapPathActual(VirtualPath virtualPath, Boolean permitNull) +3530188
System.Web.Compilation.BuildManager.CheckTopLevelFilesUpToDate2(StandardDiskBuildResultCache diskCache) +306
System.Web.Compilation.BuildManager.CheckTopLevelFilesUpToDate(StandardDiskBuildResultCache diskCache) +46
System.Web.Compilation.BuildManager.RegularAppRuntimeModeInitialize() +419
System.Web.Compilation.BuildManager.Initialize() +235
System.Web.Compilation.BuildManager.InitializeBuildManager() +228
System.Web.HttpRuntime.HostingInit(HostingEnvironmentFlags hostingFlags) +310

[HttpException (0x80004005): Der Pfad /LISgoogleEarth/App_GlobalResources/ konnte nicht zugeordnet werden.]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +3435023
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +88
System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr) +252

——————————————————————————–
Versionsinformationen: Microsoft .NET Framework-Version:2.0.50727.42; ASP.NET-Version:2.0.50727.210

Ich habe im Netz gesucht und habe einige Hinweise gefunde woran es liegen könnte. Hauptsächlich ging es um den Zugriffschutz in der Registry. Bei mir lag es daran, das der Benutzer ASP (der Benutzer der im IIS ASP.Net-Anwendungen ausführt) hatte nicht genügend Rechte in der Registry auf folgenden Pfad: HKEY_CLASSES_ROOT\Interface\{70B51430-B6CA-11D0-B9B9-00A0C922E750}.

Bei anderen Benutzern fehleten Rechte auf das Verzeichnis C:\WINNT\Profiles\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys.

Sollte das nicht ausreichen empfiehlt es sich mit FileMon oder RegMon das Filesystem oder die Registry zu monitoren, ich denke so wird man schnell das Probelm finden.

P.S: Auf diese Tip gibt es keine Garantie das es das Problem auch bei Ihnen löst.

Heute gab es wieder Spaß mit Windows. Diesmal war der Windows-Update-Service betroffen, nach dem letzten Patch-Day der Windows-Update-Service über den Internet-Explorer nicht mehr ausgeführt werden. Es kam zu einem Fehler mit der Fehlernummer: 0x8DDD0009

Der Internet-Explorer schlug eine Lösung vor: Internet-Explorer schließen (mußte ich erst abschießen), temporäre Dateien löschen und nochmal probieren.

Hat aber nicht geholfen. Nach etwas googlen und im Forenlesen ab ich dann die Lösung gefunden die bei mir funktioniert hat.

Als erstes habe ich die msxml3.dll neu registriert. Das geht ganz einfach. Unter “Start/Ausführen” (oder Windows-Taste + R) gibt man “regsvr32 msxml.dll” ein.

Als nächstes stoppt man den Dienst Automatisches Update im Dienstmanager. (zu finden in der Computerverwaltung/dienste in der Systemsteuerung) Nachdem das passiert ist, muß man das Verzeichnung {Windows}\SoftwareDistribution löschen oder umbenennen. Ich habe es erstmal umbenannt. Wenn man das getan hat, startet man den Dienst wieder und öffnet den Internet-Explorer.

Im Internet-Explorer löscht man alle temporären Dateien, und auch die Offline-Inhalte und startet das Windows-Update, was dann sauber funktionieren sollte.

Ich hoffe allen Betroffenen damit geholfen zu haben.

Wer deutsche Infromationen zum Thema Word-press sucht ist hier bei wordpress-deutschland.org gut aufgehoben. Dort findet ihr auch deutsche Ressourcen und Themen.