Archiv der Kategorie: Computer

Tipps und Hilfe bei Computer-Problemen

MyISAM-Datenbank-Tabelle reparieren

Es darf eigentlich nicht vorkommen, doch es passiert: Ein unbedachter Wackler an einem Stromkabel beim Ein- oder Umbau im Serverschrank oder gar eine Stromschwankung oder Stromausfall: Der Server wird ohne ordentliche Abmeldung einfach stromlos und das Chaos ist perfekt. Sofort werden der Techniker und der zuständige Admin kreideweiß im Gesicht. Wird der Server wieder anlaufen? Wird die Festplatte einen Schaden haben? Und wird die MySQL-Datenbank korrupt sein?
Gehen wir einmal davon aus, dass der Server wieder anläuft, das Betriebsystem zwar das nicht ordnungsgemäße Ausschalten in den Statusmeldungen moniert, aber ansonsten klaglos seinen Dienst verrichtet, wird spätestens MySQL zur Bewährungsprobe. Denn wenn im Moment des Stromausfalles schreibend auf die Datenbank zugegriffen wurde, kann man davon ausgehen, dass die Datenbank nicht ohne Schaden genommen wieder anlaufen wird.

Warning: Table ist maked as crashed and last repair failed
Wenn MySQL ohne Fehlermeldung anläuft bedeutet dies leider nicht, dass auch alle Tabellen ohne Schaden den Stromausfall überstanden haben. Gerade MyISAM-Tabellen werden, wenn während des Stromausfalles darauf zugegriffen wurde, Schaden genommen haben.
Man muss nicht gleich in Panik verfallen, es gilt Ruhe zu bewahren und den Schaden zu minimieren. Die Reparatur wird jedoch, je nach Tabellengröße, längere Zeit in Anspruch nehmen. Es ist daher zuerst zu prüfen, ob es nicht vielleicht sinnvoll ist, ein Backup zurückzuspielen. Je nach Tabelle und Sicherungs-Infrastruktur kann dies der schnellste Weg der Wiederherstellung sein.

MyISAM-Tabelle überprüfen
MySQL: myisammchk Tabelle pruefenLoggen Sie sich auf der Konsole auf dem Server ein. Navigieren Sie zum MySQL-Server („var/lib/mysql“) und wechseln Sie in das Verzeichnis der Datenbank. Prüfen Sie nun die Tabellen mit

myisamchk tabellenname.MYI

Mit Spannung kann das Ende der Prüfung abgewartet werden. Wenn die Konsole „MyISAM-Table ‚TABLENAME’ is corruped“ meldet, ist einen Reparatur der MyISAM-Tabelle angesagt.

Die schnelle MyISAM-Reparatur
Die Konsolenausgabe schlägt vor, mit dem Schalter „-r“ die Reparatur durchzuführen. Mittels dieses „Wiederherstellungsmodus“ werden falsche und gelöschte Datensätze entfernt und die Indexdatei neu erstellt. Wer es schneller möchte, kann den Schalter „-q“ zusätzlich verwenden. Dann wird versucht, die Indexdatei zu reparieren, anstatt sie neu zu erstellen. Probieren Sie die Reparatur aus.
In jedem Fall wird die Reparatur Zeit in Anspruch nehmen. Da die Datenbank sowieso offline ist, können Sie auch über den Speicher des Datenbankservers verfügen. Man beschleunigt die Reparatur ungemein, wenn man zuvor die MySQL-Variablen „sort_buffer_size“ und „key_buffer_size“ jeweils auf 25 Prozent des verfügbaren Hauptspeichers setzt.

MyISAM-table ‚tablename’ is not fixed because of errors
MySQL: myisamchk safe recoverWenn die schnelle MyISAM-Reparatur fehlschlägt, müssen Sie den Modus „safe-recover“ („-0“) wählen:

myisamchk –r –o TABELLENNAME

Je nach Tabellengröße wird diese Wiederherstellung mehrere Stunden benötigen. Sie ist genauer, aber auch sehr langsam.
Bei allen bisher bei mir aufgetretenen MyISAM-Reparatur-Szenarien haben diese Schritte zum Erfolg geführt. Wenn trotzdem Fehler auftreten oder mysiamchk sogar abstürzt, müssen Sie folgende Schritte ausführen:

1.    Kopieren Sie die Datenbank per Filesystem in einen sicheren Bereich
2.    Führen Sie die folgenden Befehle aus:

shell> mysql DATENBANKNAME
mysql> SET AUTOCOMMIT=1;
mysql> TRUNCATE TABLE TABELLENNAME;
mysql> quit

3. Kopieren Sie die Datenbank-Datei aus dem sicheren Bereich wieder auf den Server.
4. Starten Sie „myisamchk -r -q“, also die schnelle Datenbankreparatur, erneut.

GD Star Rating
loading...

C#: Konvertierung von Zahlen in Dezimal

Es klingt banal, dennoch bereitet es oftmals Probleme: Die Konvertierung von Zahlen oder Strings nach Dezimal. Wobei die eigentliche Umrechnung nach Dezimal weniger spannend ist als das Abfangen von falschen Werten. Denn eine Exception auszulösen bei der Prüfung von Werten ist nicht immer wünschenswert. Gerade bei Jobs, die massenweise Daten importieren, kann eine solche Prüfung Zeit kosten. Und zwar massiv Zeit, die sich gewaltig in der Laufzeit des Jobs auswirkt.
Spätestens dann ist der Programmierer gezwungen, sich Gedanken über die beste Konvertierung zu machen. Untersuchen wir doch gemeinsam einmal die unterschiedlichen Methoden, um eine Zahl nach Dezimal zu Konvertieren und falsche Werte zu filtern.

Betrachten wir doch folgenden C#-Code:

string sWert = "5235.65";
decimal dErgebnis = Convert.ToDecimal(sWert);
Console.WriteLine(dErgebnis);

sWert = "falscher string";
dErgebnis = Convert.ToDecimal(sWert);
Console.WriteLine(dErgebnis);

Wir konvertieren den String „5235.65“ per Convert.ToDecimal nach Dezimal. Dies wird funktionieren. Nun nehmen wir beispielsweise eine Benutzereingabe entgegen, die einen Nicht-Dezimal-Wert enthält. C# wird bei „Convert“ eine Exception auslösen. Der Klassiker ist an dieser Stelle, die Konvertierung mit einen try-catch-Block zu umschließen. Wenn nur eine Eingabe so abgefangen werden soll, ist dies sicherlich akzeptabel. Elegant und schnell ist diese Variation jedoch nicht.

Auch die Möglichkeit, die Dezimal-Konvertierung mittels „System.Decimal.Parse“ durchzuführen, wird zum gleichen Ergebnis führen:

string sWert = "5235.65";
decimal dErgebnis = System.Decimal.Parse(sWert);
Console.WriteLine(dErgebnis);

sWert = "falscher string";
dErgebnis = System.Decimal.Parse(sWert);
Console.WriteLine(dErgebnis);

Eleganter ist es auf jeden Fall, mögliche Falscheingaben per „System.Decimal.TryParse“ abzufangen:

string sWert = "5235.65";
decimal dErgebnis = 0.0M;

if (System.Decimal.TryParse(sWert, out dErgebnis)) Console.WriteLine(dErgebnis);
Console.WriteLine(dErgebnis);

sWert = "falscher string";
if (System.Decimal.TryParse(sWert, out dErgebnis)) Console.WriteLine(dErgebnis);
Console.WriteLine(dErgebnis);

Die eben beschriebene Methode eignet sich in der Regel immer, um elegant und schnell Konvertierungen von Werten nach Dezimal vorzunehmen. Allerdings ist es immer noch einem Menge Text, die man angeben muss. Und da Programmieren von Natur aus faul sind, ist auch hier eine Verbesserung denkbar. Um es vorweg zu nehmen: Die folgende Methode erzeugt noch mehr Code. Die eigentliche Umwandlung ist jedoch elegant, schnell und ermöglicht auch einen Default-Wert mitzugeben, wenn die Umwandlung schiefgehen sollte. Wenn also in einem Projekt mehrfach eine Umwandlung nach Dezimal vorgenommen werden muss, sollte man über die folgende Methode nachdenken:

namespace ConsoleApplication1
{
    public static class StringExtensions
    {
        public static Decimal? ToDecimal(this string obj, Decimal? dBaseValue=null)
        {
            Decimal dValue;
            if (Decimal.TryParse(obj, out dValue)) return dValue;
            return dBaseValue;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

            string sWert = "5235.65";
            decimal dErgebnis = sWert.ToDecimal(0).Value;
            Console.WriteLine(dErgebnis);                     

            sWert = "falscher string";
            dErgebnis = sWert.ToDecimal(0).Value;
            Console.WriteLine(dErgebnis);
        }
     }
}
GD Star Rating
loading...

Amazon S3: Zugriff auf S3 per C#

Im Artikel „Amazon S3: Wie wir einen Image-Server realisiert haben“ habe ich bereits über die Vorteile der Amazon S3 berichtet. Nun folgt der Zugriff auf die S3 mittels C#.

Daten zu Amazon S3 hochladen
Amazon selbst stellt eine einfache Oberfläche zur Verfügung. Mit dieser kann man Daten verwalten, hochladen, löschen und auch Rechte und Metadaten verwalten. Da die Daten jedoch maschinell zu S3 hochgeladen werden sollten, musste die Dokumentation studiert werden. Leider bietet Amazon keinen FTP-Zugriff aus die S3. Von Sicherheitsbedenken mal abgesehen wäre dies für uns der einfachste Weg gewesen.

Erste Schritte mit S3
amazon-s3-management-consoleZuerst sollte man sich mit S3 über die Oberfläche vertraut machen. Man sieht sehr schnell, dass Amazon bewusste die S3 nur mit einem Minimum an Funktionen ausgestattet hat. Man sollte sich mit „Buckets“ (Eimer) auseinandersetzen. In diesem werden die Daten in der S3 gespeichert. Ein besonderes Augenmerk sollte auf die Rechtevergabe fallen, denn alle Daten, die von einem User hochgeladen werden, sind per Default auch nur für diesen zum Download zugänglich. Für einen Image-Server natürlich nicht sinnvoll.
Zudem sollten die Meta-Daten betrachtet werden. Bilder werden bereits mit dem richtigen Header ausgestattet. Um ein Expire-Date zu setzen, muss unter den Meta-Daten dies angegeben werden. Eine allgemeingültige Angabe wie im Apache-Header ist leider nicht möglich. Im Beispielcode unten wird beim Hochladen neben allgemeinen Lese-Rechten auch ein Expires-Date jedem Image vergeben.

Amazon .Net-DLL für .NET
Um die Amazon S3 mittels C# ansprechen zu können, benötigen wir die Amazon DLL „AWSSDK.dll“, die bereits stolze 2.995 KB groß ist. Sie beinhaltet jedoch alles, was man zur Kommunikation mit Amazon benötigt. Also auch weitere Schnittstellen, die über unsere C#-Kommunikation mit S3 hinaus geht. Eingebunden in ein .NET-Projekt, binden wir die DLL per „using Amazon.S3;“ ein. Je nach Anwendung erfolgen noch weitere Using-Anweisungen.

Die S3 ersetzt einen FTP-Server
Untenstehend folgt ein C#-Beispiel samt C#-Code, wie man einen S3-Bucket alternativ eines FTP-Servers nutzen kann. Wir prüfen hier, ob ein Ordner in einem Bucket exisitert und legen gegebenenfalls den Ordner in der Amazon S3 an.
Dann erfolgt der Upload einer Datei. Wir begnügen uns hier, Datei für Datei in die Amazon-Wolke hochzuladen. Die Amazon-DLL bietet auch die Möglichkeit, ganze Ordner in der S3 abzulegen. Hierzu einfach einmal die Amazon-Doku studieren.

S3: Dateien öffentlich lesbar machen
Dateien, die von einem Benutzer hochgeladen werden, sind per default auch nur von diesem lesbar. In unserem Falle möchten wir jedoch, dass alle Besucher die Dateien lesen können. Die Rechte können per Hand über die S3-Oberfläche gesetzt werden. Wenn wir jedoch per C# die Dateien hochladen, können wir den entsprechenden Header-Eintrag gleich setzen:
req.AddHeader(„x-amz-acl“, „public-read“);

S3: Dateien mit einem Expire Date versehen
Um Bandbreite zu sparen und Zugriffe zu minimieren, ist es sinnvoll, Dateien mit einem Expire Date zu versehen. Der lokale Browser wird dadurch angewiesen, bei einem zweiten Aufruf die Datei aus seinem lokalen Cache dem Kunden auszuliefern. Der Vorteil liegt auf der Hand: Die Datei muss nicht erneut angefordert werden und die Kosten für den Webbetreiber werden minimiert, da keine erneute Auslieferung der Datei aus der Cloud erfolgt.
Gerade bei Bildern, die sich selten bis nie ändern, macht es Sinn, das Expire-Date zu setzen. Welches Datum bzw. welchen Zeitraum man wählt, ist Ansichtssache. Es gibt Webmaster, die den Zeitraum nahezu bis ins unendliche ausdehnen. In unserem Beispiel erhöhen wir das aktuelle Datum (Upload-Datum) um fünf Jahre. Eine lange Zeit; die wenigsten Rechner bleiben so lange aktiv bzw. die wenigsten Besucher werden ihren lokalen Internet-Cache in diesem Zeitraum nicht leeren. Doch so haben wir auch genügend Zeit, das Bild irgendwann auszutauschen.

Mit folgendem C#-Beispiel-Code setzen Sie das Expire Date für die Amazon S3-Cloud:

//Optional: Expire Date setzen - für Images sinnvoll
CultureInfo ci = new CultureInfo("en-US");
string sExpire = DateTime.Now.AddYears(5).ToString("ddd, dd MMM yyyy hh:mm:ss", ci) + " GTM";
req.AddHeader("Expires", sExpire);

Der gesamte C#-Beispielcode mit entsprechenden Kommentare:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.Transfer; //Upload
using Amazon.S3.Util;//Upload
using System.Web; //Header
using System.Globalization;

namespace ConsoleApplication1
{
    class Program
    {

        //Amazon S3
        private const string AWS_ACCESS_KEY = "<mein AWS_ACCESS_KEY>";
        private const string AWS_SECRET_KEY = "<mein AWS_SECRET_KEY>";
        private const string BUCKET_NAME = "<mein BUCKET_NAME>";
        private const string S3_KEY = "<mein S3_KEY>";

        public static AmazonS3Client client = new AmazonS3Client(AWS_ACCESS_KEY, AWS_SECRET_KEY);

        static void Main(string[] args)
        {

            //Prüfen, ob ein Ordner in S3 exitiert, ansonsten Ordner anlegen
            if (!DoesFolderExist("mein Ordner")) CreateFolder("mein Ordner");

            //Hochladen von Dateien in die S3
            if (Upload("<Zukünftiger Dateiname in der S3>", "<ordner>", "<lokaler Filepfad>")) Console.WriteLine("Upload in die S3 erfolgreich.");
            else Console.WriteLine("Datei-Upload leider nicht erfolgreich!");

        }

        private static bool Upload(string filename, string ordner, string sFilepfad)
        {
            //Upload - Hochladen von Dateien zu Amazon S3
            bool bRes = false;

            //Ordnerstuktur: Basisornder/unterordner_ordner1
            string basisverzeichnis = "basisordner/" + ordner;

            //Existiert der Ordner in S3?
            if (!DoesFolderExist(basisverzeichnis)) CreateFolder(basisverzeichnis);

            try
            {
                //Upload Datei in Folder
                string key = string.Format("{0}/{1}", basisverzeichnis, filename);

                Amazon.S3.Model.PutObjectRequest req = new Amazon.S3.Model.PutObjectRequest().WithBucketName(BUCKET_NAME);
                req.FilePath = sFilepfad; // Lokaler vollqualifizierter Pfad inkl. Dateiname zur lokalen Quelldatei
                req.Key = key;
                req.Timeout = int.MaxValue; //Timeout nach Wunsch
                req.AddHeader("x-amz-acl", "public-read"); //Optional: Hier werden öffentliche Leserechte gesetzt

                //Optional: Expire Date setzen - für Images sinnvoll
                CultureInfo ci = new CultureInfo("en-US");
                string sExpire = DateTime.Now.AddYears(5).ToString("ddd, dd MMM yyyy hh:mm:ss", ci) + " GTM";
                req.AddHeader("Expires", sExpire);

                client.PutObject(req);

                bRes = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message, "Upload Error. File: " + filename);

            }
            return bRes;
        }

        public static bool DoesFolderExist(string folderName)
        {
            //Amazon S3: Prüft, ob ein Ordner vorhanden ist
            try
            {
                ListObjectsRequest request = new ListObjectsRequest();
                request.BucketName = BUCKET_NAME;
                request.WithPrefix(folderName + "/");
                request.MaxKeys = 1;

                using (ListObjectsResponse response = client.ListObjects(request))
                {
                    if (response.S3Objects.Count > 0) return true;
                }
            }
            catch (Amazon.S3.AmazonS3Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return false;
        }

        public static void CreateFolder(string folderName)
        {
            //Neuanlage eines Ordners in S3
            try
            {
                Console.WriteLine("Lege Ordner an: " + folderName);

                //Amazon S3: Anlegen eines Ordners
                var key = string.Format(@"{0}/", folderName);
                var request = new PutObjectRequest().WithBucketName(BUCKET_NAME).WithKey(key);
                request.InputStream = new MemoryStream();
                client.PutObject(request);
            }
            catch (Amazon.S3.AmazonS3Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

UPDATE 22.08.2012: Danke an den Leser „Andreas“, der festgestellt hat, dass der hier angelegte „S3-Key“ im Beispielprojekt nicht verwendet wird. Somit wird der Key auch nicht benötigt.

GD Star Rating
loading...

Amazon S3: Wie wir einen Image-Server realisiert haben

“Cloud” ist in aller Munde. Amazon S3 (Amazon Simple Storage Service) ist im Prinzip eine Cloud. Amazon selbst beschreibt diesen Dienst als “Speicher für das Intranet”. Ich kann also schnell und einfach Dateien dort ablegen und von überall zugreifen. Die Daten werden gespiegelt dort abgelegt, die Datenanbindung ist vorbildlich. Soweit so gut. Nichts wirklich spannendes. Clouds gibt es inzwischen wie Sand am Meer und die meisten Nerds können sich bei der Vorstellung eines neuen Cloud-Anbieters das Gähnen nicht verkneifen. Auch Amazons „Ausführungsanforderungen“ lesen sich wie klassisches Bullshit-Bingo: „Sicher“, „Zuverlässig“, „Skalierbar“, „Geschwindigkeit“, „Günstiger Preis“ und Einfachheit“. Und trotzdem möchte ich den Dienst samt Zugriff per C# vorstellen.

amazon s3 kontoübersichtIm vorliegenden Projekt hatten wir das Problem, eine große Shopping-Seite zu beschleunigen. Alleine die Bilddateien belegten über 50 GB und wurden rege von den Kunden aufgerufen. Schon recht früh erkannte man, dass die Bilder auf einen separaten Server ausgelagert werden mussten, um den Zugriff auf den eigentlichen Webserver zu entlasten. Doch man erkannte, dass ein Server, der die Bilder hostet, nicht mehr ausreicht. Zu groß war die Last, die nur das Ausliefern der Bilder verursachte. Des Weiteren waren die Bilder nicht gespiegelt. Bei einem Servercrash wären die Bilder zwar nicht unwiederbringlich verloren gewesen, doch der Ausfall hätte einiges an Zeit benötigt. Und ein Shopping-Portal ohne Produkt-Bilder ist ein Portal ohne Umsätze. Also überlegte man, wie der/die zukünftigen Server beschaffen sein mussten, damit der Zugriff auf die Bilder schnell erfolgte und diese gleichzeitig zuverlässig gespeichert wurden.
Um alle Anforderungen zu erfüllen mussten also mindestens zwei Server angeschafft werden. Neben den Hardwarekosten, den laufenden Betriebskosten sind die Server-Administrationskosten nicht zu unterschätzen. Dem gegenüber wurden die Kosten für die Amazon S3 gestellt. Für Neueinsteiger bietet Amazon ein AWS Gratisangebot an, was für erste Tests durchaus akzeptabel ist. Dies genutzt, konnte der Dienst ein paar Wochen gestestet werden. Zugriffe und deren Geschwindigkeit wurden getestet, die (produktiv anfallenden) Kosten der Eigenlösung gegenübergestellt.
Aktuell halte ich die Amazon Webserver-Angebote nicht unbedingt für finanziell Vorteilhaft (einige Spezial-Angebote ausgenommen). Auch kleinere Webseiten sind sicherlich besser damit bedient, Teile ihres Webs auf eine andere virtuelle Maschine bei einem Hosten auszulagern, als die Daten in einer S3 zu speichern, denn bei jedem Zugriff eines Users tickt der Amazon-Zähler. Und da kann schon ein „Sümmchen“ zusammenkommen.
Doch bei dem oben beschriebenen Projekt ergab sich ein Kostenvorteil. Zudem überzeugte die Zugriffszeit der S3. Genutzt wird der Standort EU (Irland).

Weiter: Amazon S3: Zugriff auf S3 per C#

GD Star Rating
loading...

Suchmaschinen-Besucher und Search-Keys aus Apache-Logfile ermitteln

Es interessiert einem brennend: Wie viel Besucher habe ich durch Suchmaschinen erhalten und vor allem, nach was haben die Besucher über die Suchmaschine gesucht? Die Antwort gibt das Server-Logfile, welches detailliert die Besucher protokolliert. Die gängigste Methode ist, das Logfile in einem Texteditor zu öffnen und manuell nach den Zugriffen zu schauen. Dies macht man eine Weile, dann hat man keine Lust mehr. Denn man möchte schnell eine Übersicht über die Suchmaschinen-Besucher und ihre Suchbegriffe.
Dann sucht man im Internet nach Logfile-Parser und wird schnell fündig. Neben online-Webstatistiken wie AWStats oder Freeware für das Offline-Parsen findet man eine ganze Reihe an Parsern; die meisten jedoch viel zu kompliziert oder eben nicht speziell für diesen Zweck zugeschnitten, so dass die Handhabung zu umständlich ist.

Logfile-Parser speziell für das Ermitteln von Suchmaschinen-Benutzer
Irgendwann war ich es leid und habe den Sirmark-Suchmaschinen-Pareser geschrieben, den ich hier zum Download anbiete. Das Programm ist Freeware, Ihr könnt es kostenlos downloaden und benutzen. Einen Support biete ich jedoch NICHT!

DOWNLOAD: Logfile-Parser SLP V1.2

Systemvoraussetzungen für den Suchmaschinen-Parser
Der Parser ist für Windows .NET geschrieben. Er läuft ab Windows XP und benötigt mindestens das .NET-Framewerk 2.0. Er besteht aus einer einfachen EXE, benötigt keine Installation oder Registry-Einträge. Also einfach downloaden und starten.

Benutzung von Sirmarks-Suchmaschinen-Parser

Apache Logfile auswerten

Logfile Parser: Apache Logfile öffnen

Die Handhabung des Suchmaschinen-Parsers ist sehr einfach. Nach dem Starten der Anwendung klickt man auf den Button „Logfile laden“. Es öffnet sich ein Dialog, über den man das Logfile auswählt. Dies bedeutet, dass das Logfile also auf der lokalen Windows-Maschine oder per Datenfreigabe über Windows erreichbar sein muss. Also gegebenenfalls das Logfile via FTP vom Webserver herunterladen.
Gezippte Logfiles: Der Logfile-Parser entpackt das Logfile NICHT automatisch. Wenn es sich um ein gezipptes Logfile handelt („.gz“), das Logfile vorher beispielsweise mit 7.zip entpacken!

Logfile nach Suchbegriffen analysieren

Logfile nach Suchbegriffen analysieren

Alle Besucher von Suchmaschinen werden mit dem Suchbegriff ermittelt

Wenn ein Logfile ausgewählt wurde, beginnt der Parser sofort mit seiner Arbeit. Er geht das Logfile zeilenweise durch und zeigt die gefundenen Zeilen in der Box „Zeilen“ zur Laufzeit an. Die Anzahl der Zeilen sowie der Fundstellen wird in einem Label angezeigt.
Wenn das Logfile komplett analysiert wurde, werden die Suchstellen aufbereitet. In der unteren Tabelle erscheinen alle Suchstellen aufbereitet nach Datum, Suchmaschine, Search-Key, Ziel-URL und die IP-Adresse des Besuchers.

Tipps für die Nutzung des Suchmaschinen-Parsers
Beide Tabellen sind durch einen horizontalen Slider miteinander verbunden. Wenn man mit der Maus in den Bereich zwischen der Anzeige „Zeilen“ und der Tabelle fährt, ändert sich der Mauszeiger und man kann die Größe der Elemente ändern.
Die Datenzeilen in der aufbereiteten Tabelle sind markierbar und können so per Copy and Paste schnell in eine Textdatei oder Excel kopiert werden. Um beispielsweise die gesamte aufbereitete Tabelle nach Excel zu kopieren, klickt man am einfachsten (1) in der Tabelle an; die gesamte Tabelle wird markiert. Nun wählt man auf der Tatstatur „Strg“ + „c“ für „Copy“, wechselt dann nach Excel oder einem Texteditor und wählt dort einfügen (oder „Strg“+ „p“ („Paste“).

Change-Log
Version 1.1:

  1. Suchanfragen werden nun per URL Decode umgeschlüsselt.
  2. BUG in Suchanfrage (String-Länge) bereinigt.
  3. Bot, Spider und Crawler-Tab hinzugefügt: Ab dieser Version werden auch alle Crawler-Zugriffe aus dem Logfile extrahiert und aufbereitet in einem eigenen Tab aufgelistet. Durch die Möglichkeit, die Tabelle zu sortieren (Klick in den Tabellen-Spaltenkopf), kann schnell eine Übersicht über die Crawler-Tätigkeit einzelner Bots (Googleboot, Bing etc) erhalten werden.

Version 1.2

  1. Tool kommt nun mit weiteren verschiedenen Apache-Logfiles zurecht (Logfile Aufbau-Erkennung)
  2. Beschleunigung der Verarbeitungsgeschwindigkeit: Durch C#-Optimierung konnte die Abarbeitungsdauer eines Referenz-Logfiles von 1:37 min auf 1:13 min minimiert werden.
  3. Ausführungsdauer wird nun im Fenstertitel mit angezeigt
  4. Um die Verarbeitungsgeschwindigkeit zu beeinflussen, kann nun der Analysemodus (alles, nur Suchanfragen, nur Bots) beeinflusst werden
  5. BUG: Aufgrund der optimierten Abfragegeschwindigkeit kann es vorkommen, dass normale Besuchereinträge fälschlicherweise als Bot erkannt werden.
GD Star Rating
loading...

Alternativer PHP Cache (APC) installieren

Installation Alternativer PHP Cache APC Linux Ubuntu Plesk

Die Installation des „Alternativer PHP Cache“ (APC)  ist eigentlich schnell erledigt. Da jedoch nicht jede im Internet verfügbare Lösung oder jedes HowTo zum Ziel führt, möchte ich hier einige Wege aufzeigen. Gerade unter Ubuntu/Plesk kann die Installation zu Problemen führen. Wie diese Probleme umgangen werden, zeige ich hier.

APC bzw. der Alterative PHP Cache ist ein freies PHP Modul, welches eine robuste Möglichkeit bietet, PHP Zwischencode zu cachen und somit die Zugriffszeiten einer dynamischen PHP-Seite massiv zu optimieren. Gerade Google scheint immer mehr darauf zu achten, dass eine Webseite möglichst schnell geladen wird. Das Stichwort hierzu lautet Page Speed.  Da offensichtlich die Ladezeit einer Webseite sich auch auf den Google-Suchindex auswirken, müssen Webmaster inzwischen auch die Ladezeit im Auge behalten. Im Prinzip auch ein richtiger Ansatz. Kaum ein Leser möchte bei jedem Klick mehrere Sekunden auf den Aufbau der folgenden Seite warten. Im Zeitalter von Breitband-Anschlüssen und DSL verliert der Leser bei langen Wartezeiten schnell das Interesse an einer Seite.

Über die PHP.ini ist schnell ersichtlich, ob APC installiert wurde

Das PHP-Modul APC ist aktuell noch nicht im Basis-Umfang von PHP enthalten. Dies wird wohl – wie man im Internet lesen kann – sich in einer der folgenden Versionen ändern. Wohl aus diesem Grund ist das Interesse an diesem Cache sprunghaft gestiegen, ist es doch ein Garant, dass der Code dieses Caches von den Machern von PHP als valide angesehen wird. Aktuell müssen wir APC noch per Hand nachinstallieren. Prüfen Sie zuerst über eine PHPINFO(), ob das Modul APC auf Ihrem Server installiert ist.

Je nach Linux-Webserver-Installation führen unterschiedliche Wege zur Installation von APC Bytecode Cache. Im einfachsten Fall genügen die folgenden Zeilen:

# sudo aptitude install php-apc
# sudo /etc/init.d/apache2 restart

Leider wird gerade unter Plesk der Versuch wie folgt enden:

root@XXX:/usr/local/src/APC-3.1.8# apt-get install php-apc
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Couldn't find package php-apc

Wenn APC nicht als Paket vorhanden ist, müssen wir es manuell installieren. Zuerst besuchen wir die Seite http://pecl.php.net/package/APC und ermitteln die aktuellste Version sowie den Download-Link der aktuellen TGZ-Version. Hier in diesem Beispiel ist es die Version „APC-3.1.9.tgz”.

cd /usr/local/src
wget http://pecl.php.net/get/APC-3.1.9.tgz
tar xf APC-3.1.9.tgz
cd APC-3.1.9/
phpize

Fehlermöglichkeit PHP: pecl install liefert „ERROR: ‚phpize‘ failed“
Wenn nach der Eingabe von „phpize“ die Fehlermeldung „ERROR: ‚phpize‘ failed“ erscheint, deutet dies darauf hin, das PECL nicht auf dem Server installiert wurde. Holen Sie dies nach:

apt-get install apache2-threaded-dev php5-dev php-pear make

Wenn der Befehl “phpize” keinen Fehler mehr liefert, können Sie wie folgt weitermachen:

./configure
make
make install

Nun ist APC erfolgreich installiert. Damit PHP dieses Modul auch läd und nutzen kann, muss es in der php.ini auch eingefügt werden. Hierzu können Sie folgenden Befehl nutzen:

echo „extension=apc.so“ >>/etc/php.ini

Status des APC-Cache

Je nach Installation hat PHP auch einen Ordner mit dynamischen Inhalten. Prüfen Sie, ob der Ordner
/etc/php5/apache2/conf.d
vorhanden ist. Wenn ja, kopieren Sie ein vorhandenes Ini-File und ändern den darin vorhandenen Dateipfad wie folgt ab:
extension=apc.so

Nach dieser Änderung müssen Sie den Apache Webserver neu starten:
/etc/init.d/apache2 restart
Plesk-Nutzer sollten den Neustart des Apache Webserver über die Weboberfläche von Plesk erledigen.

Prüfen Sie über eine PHPINFO(), ob PHP APC erfolgreich läd.

GD Star Rating
loading...

Daten unter Linux zippen und schnell übertragen

Wenn man beispielsweise eine MySQL-Tabelle von einem Master Server zum Slave übertragen muss und diese Tabelle schon eine stattliche Größe angenommen hat, macht man sich durchaus Gedanken, wie man den Datenübertrag am sinnvollsten bewerkstelligt.

Datenübertrag per WinSCP
Wer sich zwischen der Windows und der Linux-Welt bewegt, kennst sicherlich das Windows-Tool WinSCP. Mit diesem Tool kann von einem Windows-Rechner per grafischer Benutzeroberfläche auf einen Linux-Server zugegriffen werden. Auch der Datenaustausch zwischen beiden Rechnern ist möglich. Wenn allerdings von einem Linux-Recher zum Anderen die Verbindung erfolgen soll, müsste man die Daten zuerst auf Windows-Rechner zwischengespeichert werden, was in den meisten Fällen weniger sinnvoll ist. Positiv anzumerken ist, dass WinSCP auch ein abgebrochener Upload selbstständig wieder aufnimmt.

Datenaustausch mittels SCP (Secure Copy)
Der direkte Weg zur Datenübertragung zwischen zwei Linux-Rechnern sollte per SCP (Secure Copy) erfolgen. Die Übertragung erfolgt verschlüsselt vom Quell- zum Zielserver. Beginnend vom Quellserver gilt folgende Befehlskette:

scp -r orig_directory USERNAME@machine2:destination_directory

Der Parameter “-r” veranlasst SCP das angegebene Directory rekursiv zu übertragen. Wenn man nur eine einzelne Datei übertragen möchte, kann dieser Parameter weggelassen werden.

Nach Absetzen des Befehles nimmt SCP Kontakt zum Zielserver auf. Danach erfolgt die Abfrage des Passwortes (von USERNAME) und der Übertrag beginnt.
NACHTEIL: Leider kann ein abgebrochener Upload mittels SCP nicht wieder aufgenommen werden. Da gemäß Murphys Gesetz der stundenlange Upload meist bei 99 Prozent abbricht, ist dies ein sehr ärgerlicher Nachteil. Wie man den Abbruch eines Uploads umgehen kann, kann im Artikel „Upload mit SCP abgebrochen, was nun?“ nachgelesen werden.

Dateien unter Linux zippen (komprimieren)
Die bekannteste Komprimierungsform unter Windows ist sicherlich ZIP. Auch unter Linux ist ZIP erhältlich, wenn auch nicht in jeder Distribution vorhanden. In den Linux-Paketen ist der Zipper jedoch meist integriert, so dass die Installation schnell und einfach erledigt ist.

Um ein Directory zu zippen, genügt folgender Befehl:

zip -r archive_name.zip directory_to_compress

Um eine Datei zu entpacken, genügt:

unzip archive_name.zip

Dateien packen mittels TAR.GZ
Verbreiteter als der Zipper ist in der Linux-Welt sicherlich tar.gz. Glaubt man einigen Meinungen im Internet (die ich nicht in Frage stelle), erreicht dieser Zipper wesentlich bessere Komprimierungsraten und schon die CPU beim zippen im Gegensatz zum Zipper.
Um ein Verzeichnis zu zippen, wählt man:
tar -zcvf archive_name.tar.gz directory_to_compress

Zum Entpacken im aktuelle Verzeichnis wählt man
tar -zxvf archive_name.tar.gz

Will man seine Daten in einem bestimmten Verzeichnis entpacken, gibt man das Zielverzeichnis explizit an:
tar -zxvf archive_name.tar.gz -C /tmp/extract_here/

GD Star Rating
loading...

Upload mit SCP abgebrochen, was nun?

Da ich aktuell meine Server-Cluster mit den Replikations-Datenbanken bestücke, schaufel ich gigabyteweise Daten durch das Netz. Die Dateien sind gepackt bzw. gezippt größer als zwei Gigabyte, also ein nennenswerter Brocken, bei einer normalen DSL-Leitung, deren magerer Upstream an alte ISDN-Zeiten erinnert. Umso ärgerlicher, wenn der Upload der Datei abbricht, denn wie es das Schicksal will, bricht der Upload nicht nach wenigen Minuten, sondern kurz vor Schluss, nach Stunden, bei 97, 98 oder 99 Prozent ab. Es ist nicht leicht, hier ruhig vor der Konsole sitzen zu bleiben.

Bisher habe ich das Replikationsverzeichnis gezippt und dann per SCP (LINK) zum Zielserver geschickt. Leider gibt es keine Möglichkeit, einen abgebrochenen Upload per SCP wieder aufzunehmen. Abhilfe schafft der Befehl rsync. Mit diesem Befehl kann man den abgebrochenen Upload einer Datei „reparieren“. Der Syntax des Befehls lautet wie folgt:

rsync -e ssh –partial –progress quelle [benutzer@]zielrechner:zielverzeichnis/

RSync: Daten und Datenverzeichnisse unter Linux synchronisieren
RSync ist eigentlich dafür gedacht, Daten und ganze Datenverzeichnisse über ein Netzwerk zu synchronisieren. RSync prüft hierzu die Unterschiede zwischen dem Quell- und dem Zielrechner und überträgt nur die Änderungen. Dadurch, dass Rsync auch einzelne Dateien in Teilen ersetzen kann, eignet sich das Programm auch zur Wiederaufnahme abgebrochener Transfers.

Was bedeuten die Parameter von rsync?
-e ssh: Diesen Parameter sollte man aus Sicherheitsgründen beim Transfer über das Internet immer verwenden, da so eine Verschlüsselung der übertragenen Daten erreicht wird.

partial: Der Parameter „partial“ verhindert bei einem Abbruch, dass Rsync die bereits übertragenen Daten nicht einfach löscht.

Progress: Dieser Parameter ermöglicht es, den Fortschritt des Downloads zu überwachen. Für eine ausführliche Darstellung der Synchronisation kann der Parameter „-v“ hinzugezogen werden.

-P: Die Parameter Partial und Progress können mit dem Parameter „P“ zusammengefasst werden.

Komprimierung einschalten
Wenn man nicht gerade eine zip-Datei überträgt, bietet sich eine Komprimierung der übertragenen Daten an. Hierfür eignet sich der Parameter „-z“.

Eine detaillierte Beschreibung der Parameter von Rsync kann auf der Ubuntu-Seite nachgelesen werden.

rsync -Pvze ssh /home/benutzer benutzer@example.com:/backups

Trockentest: Übertragung von Daten nur Testen
Da rsync je nach Konfiguration auch Daten löschen kann, ist ein Datenverlust bei falscher Parameterübergabe nicht ausgeschlossen. Hier bietet es sich an, zuerst einen Test („dry run“) durchzuführen um zu schauen, ob die Parameter richtig gesetzt sind. Eine Simulation kann mit dem Parameter „-n“ gestartet werden.

GD Star Rating
loading...

Excel-Tabelle lesen: Auslesen einer Excel-Tabelle mit C#

Während CSV-Dateien quasi zum Standard für den Datenaustausch definierter Listen erklärt haben, sind Excel-Tabellen für den Datenaustausch eher das letzte Mittel von Privatanwendern. Zu Recht, denn zu groß ist die Gefahr, dass die verwendete Version von Excel nicht kompatibel mit der Version von Excel ist, die der Anwender nutzt. Und kann ich überhaupt voraussetzen, dass der Empfänger zahlender Kunde von Microsoft ist und Excel nutzt?
Trotz dieser Bedenken stößt man immer wieder, wenn auch selten, auf Excel-Listen, die Firmen zum Datenaustausch bereitstellen. Und da wir alle Freunde von Automationen sind, möchten wir natürlich auch automatisiert auf die Excel-Tabellen zugreifen.

Selbstredend kann C# den Zugriff auf Excel-Tabellen gewähren, schließlich nutzen wir das .NET-Framework und es ist nur eine Frage, wie man dies am schnellsten erledigt. Zuerst binden wir in unserem Visual Studio-Projekt unter VERWEISE/COM die „Microsoft Excel 11.0 Object Library“ (oder eine andere Version) ein. Als Using-Direktive nutzen wir „using Excel = Microsoft.Office.Interop.Excel;“. Schon haben wir das nötige Rüstzeug, um automatisiert auf die Excel-Tabelle zuzugreifen.

Wie wir im folgenden Code stehen können, können wir durch die Interop.Excell.dll relativ schnell Zugriff auf die Tabelle erhalten. Der Zugriff auf die Tabelle erfolgt mittels „xlApp.Workbooks.Open“. Es ist von Vorteil, zuvor das vorhandensein der Excel-Tabelle mittels „if (File.Exists(sFile))“ zu prüfen.
Neben einigen Definitionen wird der Code erst mit der Zeile „xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);“ interessant. Wir erhalten hier Zugriff auf das erste Excel-Tabellenblatt. Dann ermitteln wir die Größe/Range der Tabelle und gehen die Zeilen mittels for-Schleife durch. Um eine Zelle in einer bestimmten Spalte auszulesen, nutzen wir einfach „string sZelleSpalte1 = (string)(range.Cells[rCnt, 1] as Excel.Range).Value2;“

 

static private void ReadExcel(string sFile)
{
try
       {
       	Excel.Application xlApp;
        Excel.Workbook xlWorkBook;
        Excel.Worksheet xlWorkSheet;
        Excel.Range range;

        int rCnt = 0;
        xlApp = new Excel.ApplicationClass();
        xlWorkBook = xlApp.Workbooks.Open(sFile, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "t", false, false, 0, true, 1, 0);
        xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
        range = xlWorkSheet.UsedRange;

        //Gehe das ganze Zabellenblatt durch
        for (rCnt = 1; rCnt <= range.Rows.Count; rCnt++)
        {
            //Hier haben wir Zugriff auf jede Zeile
            if ((range.Cells[rCnt, 1] as Excel.Range).Value2 != null)
            {
                try
                {
                   string sZelleSpalte1 = (string)(range.Cells[rCnt, 1] as Excel.Range).Value2;
                   string sZelleSpalte2 = (string)(range.Cells[rCnt, 2] as Excel.Range).Value2;
                  }
                 catch { }
              }
         }

          xlWorkBook.Close(true, null, null);
          xlApp.Quit();
      }
      catch (Exception ex)
      {
         Console.WriteLine("Fehler in ReadExcel: " + ex.Message);
       }
}
GD Star Rating
loading...

Incoming search terms:

  • c# excel tabelle auslesen
  • c# excel auslesen
  • c# tabelle
  • c# excel lesen
  • interop excel auslesen
  • xlsx einlesen c#

MySQL Tabellen-Optimierung: Der optimale Datentyp

Hand aufs Herz: Wieviel Zeit invenstieren Sie vor dem Anlegen der ersten Datenbank-Tabelle in das optimale Tabellendesign? Ich hoffe viel, denn durch das richtige Design, die richtig gewählten Dateitypen und letztlich die richtigen Indizes lassen sich die Größe einer Datenbank minimieren und die Abfragen massiv beschleunigen.

Doch meistens ist das folgende Bild eher an der Tagesordnung. Man legt die erste Tabelle an, füllt die mit Testdaten und programmiert die Anwendung. Es kommen Spalten hinzu, manche werden gelöscht, umbenannt und viele schlichtweg vergessen. Später scheut man sich, das Datenbankdesign noch einmal zu überarbeiten, da man froh ist, dass die Anwendung läuft und man keine Zeit mehr investieren möchte.

Doch wenn die Größe der Datenbanktabelle wächst, wird man von der Realität eingeholt. Es rächt sich mit steigender Datenbankgröße, wenn man das Design vernachlässigt hat. Wer nicht ständig die programminternen Datenbankabfragen auf das Vorhandensein eines optimalen Index prüft, wird schnell Schiffbruch erleiden. Und wer zu großzügig mit Datentypen umgeht, wir schnell unnötigen Plattenplatz belegen und seine Datenbank aufgrund der Größe der Tabellen verlangsamen.

Gerade bei den numerischen Datentypen ist es unumgänglich, den „besten“ Datentyp für ein Feld zu wählen. Es gilt immer: Man wählen den kleinsten Datentyp, der für das Feld ausreicht. Wählt man einen zu großen Datentyp, belegt dieser nur unnötiger Weise Speicherplatz. Bremst unter Umständen sogar die Datenbank. Daher ist es wichtig zu wissen, welche maximale Werte ein numerischer Datentyp unter MySQL annehmen kann.

Unten aufgeführt habe ich die gängigen Datentypen (nicht vollständig!) aufgeführt und gebe Tipps für die Verwendung. Eine detaillierte Aufstellung kann in der MySQL-Doku nachgelesen werden.

  • TINYINT: Nimmt Werte zwischen 0 bis255 oder -128 bis 127 auf. Optimal für die ID von kleinen Tabellen (maximal 255 Einträge) oder Status-Felder.
  • SMALLINT: Nimmt Werte zwischen 0 bis 65.535 oder -32.768 bis 32.767 auf. Langt bereits als Datentyp für die ID-Spalte vieler Tabellen.
  • MEDIUMINT: Nimmt Werte zwischen 0 bis 16.777.215 oder -8.388.608 bis 8.838.607 auf. Optimaler Wert für ID-Felder im „kleinen“ Millionenbereich.
  • INT: Nimmt Werte zwischen 0 und 4.294.967.295 oder -2.147.438.648 und 2.147.483.647 auf. Im Gegensatz zu anderen Datenbanken ist der Integer bei MySQL schon sehr, sehr mächtig. Für viele Felder ist dieser bereits schon überdimensioniert und sollte durch einen kleineren Datentyp ersetzt werden.
  • BIGINT: Nimmt Werte zwischen 0 und 18.446.744.073.709.551.615 oder -9.223.372.036.854.775.808 und 9.223.372.036.854.775.807 auf. Gerade Umsteiger von anderen Datenbanksystemen wählen gerne das „große INT“ für die ID einer stark wachsenden Tabelle. Doch unter MySQL ist der der Integer bereits groß genug für die meisten Tabellen.

Speicherplatzbedarf von nummerischen Daten-Typen
Warum wir nur den kleinsten Datensatztyp wählen sollten, der wirklich benötigt wird, zeigt die folgende Tabelle. In dieser ist der erforderliche Speicherplatz eines Datentyp aufgeführt. Wenn wir beispielsweise für eine Spalte großzügig BIGINT (8 Byte) deklariert haben, aber ein SMALLINT (2 Byte) als Spaltentyp reichen würde, verschenken wir 6 Bytes. Pro Datensatz, wohlgemerkt! Wer als Datensatz-ID BIGINT gewählt hat und nun den Spaltentyp auf INT reduziert, spart 4 Bytes (50 Prozent) an Speicherplatz, bezogen auf das ID-Feld. Es lohnt sich also, auch laufende Tabellen zu gegebener Zeit auf die Datentypen hin zu prüfen.

  • TINYINT: 1 Byte
  • SMALLINT: 2 Byte
  • MEDIUMINT: 3 Byte
  • INTEGER: 4 Byte
  • BIGINT: 8 Byte

Update: Noch weniger Gedanken macht man sich um TEXT …

Schon mal Gedanken gemacht, wieviel Text in ein MySQL-Text-Feld passt? Viel. Sehr viel, sollte man meinen. Dem ist aber nicht so. Rund 65.000 Zeichen passen in ein Text-Feld. Nachfolgend der Speicherplatz und die maximale Textlänge von MySQL Text Feldern:

TINYTEXT 256 bytes
TEXT 65,535 bytes ~64kb
MEDIUMTEXT  16,777,215 bytes ~16MB
LONGTEXT 4,294,967,295 bytes ~4GB
GD Star Rating
loading...