Pit: Umstieg mysql_ auf PDO oder mysqli?

Hi,

ich wollte eigentlich sukkzessive von mysql_ auf PDO umstellen.

Leider habe ich unterschätzt, wieviele Scripte ich geschrieben habe. Es sind mehrere Hundert Scripte und das schaffe ich arbeitstechnisch gar nicht.

Frage: Ist es nicht viel schneller, anstelle auf PDO auf mysqli umzusteigen?

Worauf müßte ich hier achten? ist das wirklich einfach nur das "i", was angehängt wird? (prozedural)

Pit

  1. hallo

    Leider habe ich unterschätzt, wieviele Scripte ich geschrieben habe. Es sind mehrere Hundert Scripte und das schaffe ich arbeitstechnisch gar nicht.

    Meine Welt bricht gerade zusammen.

    -- https://beat-stoecklin.ch/pub/index.html
  2. Tach!

    Frage: Ist es nicht viel schneller, anstelle auf PDO auf mysqli umzusteigen?

    Ja, es ist nicht viel schneller.

    Worauf müßte ich hier achten? ist das wirklich einfach nur das "i", was angehängt wird? (prozedural)

    Nein, das reicht nicht. Wenn du mysqli prozedural verwenden möchtest, musst du überall die Verbindungskennung übergeben, was bei mysql nicht der Fall war. Du musst also sowieso alles anfassen, da kannst du auch auf objektorientiert und PDO umstellen. Das bedient sich auch leichter als mysqli.

    Eine grobe Vergleichsübersicht gibts im PHP-Handbuch.

    dedlfix.

    1. Hi dedlfix,

      Nein, das reicht nicht. Wenn du mysqli prozedural verwenden möchtest, musst du überall die Verbindungskennung übergeben, was bei mysql nicht der Fall war. Du musst also sowieso alles anfassen, da kannst du auch auf objektorientiert und PDO umstellen. Das bedient sich auch leichter als mysqli.

      Es geht nicht nur ums "anfassen", es geht auch darum, was ich weniger fehleranfällig iun kurzer zeit schaffen kann. Oder was ich, viellciht auch nur teilweise, automatisieren kann.

      Eine grobe Vergleichsübersicht gibts im PHP-Handbuch.

      Habe ich auch schon gelesen.

      Im Selfwiki steht aber z.b:

      In der Planungsphase muss eigentlich nur die Entscheidung getroffen werden, welche API zukünftig verwendet werden soll. Soll der Umstieg möglichst einfach sein und im Projekt spielt Objektorientierung keine Rolle? Dann wäre wahrscheinlich MySQLi in der prozeduralen Variante am geeignetsten.

      Ist das falsch?

      Pit

      Folgende Nachrichten verweisen auf diesen Beitrag:

      1. Tach!

        Es geht nicht nur ums "anfassen", es geht auch darum, was ich weniger fehleranfällig iun kurzer zeit schaffen kann. Oder was ich, viellciht auch nur teilweise, automatisieren kann.

        Wenn du nur mysql ablösen möchtest, dann ist mysqli wohl ein wenig schneller, aber es geht nicht nur um das i, sondern auch die Übergabe der Verbindungkennung. Wenn du dann allerdings auch die modernen Eigenschaften, wie Prepared Statements, nutzen möchtest, dann ist das zwar mit mysqli möglich, aber deutlich unschöner realisiert als mit PDO. In Hinblick auf die Zukunft sehe ich das nicht als die bessere Variante.

        dedlfix.

        1. Hi dedlfix,

          Wenn du nur mysql ablösen möchtest, dann ist mysqli wohl ein wenig schneller, aber es geht nicht nur um das i, sondern auch die Übergabe der Verbindungkennung.

          Ok, das stimmt natürlich.

          Wenn du dann allerdings auch die modernen Eigenschaften, wie Prepared Statements, nutzen möchtest, dann ist das zwar mit mysqli möglich, aber deutlich unschöner realisiert als mit PDO. In Hinblick auf die Zukunft sehe ich das nicht als die bessere Variante.

          Ich auch, weshalb ich eigentlich auf PDO umsteoigen möchte. Hinzu kommt auch noch, dass PDO nicht an mysql/mariadb gebunden ist (siehe auch Reginas Post)

          Ich überlege, ob ich es schaffen kann, den Umstieg (wenigstens teilweise) zu automatisieren. Diese Frage kann ich mir aber nur selber beantworten, weil natürlich keiner wissen kann, wie meine Datenbankaktkionen organisiert und notiert sind.

          Pit

      2. Ich fasse mal zusammen:

        • Du bist Dir GANZ sicher, dass es bei mysql oder mariadb bleibt und willst wenig Arbeit haben:→ mysqli funktional
        • Du bist Dir GANZ sicher, dass es bei mysql oder mariadb bleibt und willst es gleich besser machen:→ mysqli objektorientiert
        • Du bist Dir NICHT wirklich sicher, dass es bei mysql oder mariadb bleibt:→ PDO
        1. Tach!

          • Du bist Dir GANZ sicher, dass es bei mysql oder mariadb bleibt und willst wenig Arbeit haben:→ mysqli funktional
          • Du bist Dir GANZ sicher, dass es bei mysql oder mariadb bleibt und willst es gleich besser machen:→ mysqli objektorientiert
          • Du bist Dir NICHT wirklich sicher, dass es bei mysql oder mariadb bleibt:→ PDO
          • Du bist Dir GANZ sicher, dass es bei mysql oder mariadb bleibt und willst es gleich besser machen und angenehmer haben:→ PDO

          Übrigens, das Wechseln auf ein anderes DBMS ist auch mit PDO nicht so einfach, wie man sich das vielleicht vorstellen mag. Die SQL-Dialekte sind unterschiedlich und man muss zumindest über alles drüberschauen und Syntax- und gegebenenfalls weitere Anpassungen prüfen.

          dedlfix.

          1. und angenehmer haben:→ PDO

            Angenehmer

            Hm. Definiere mal "angenehmer". Für den, der mal eben hunderte Skripte umschreiben muss, kann es durchaus "angenehmer" sein, dass er einiges davon mit "suchen und ersetzen" (womöglich tools wie sed...) erledigen kann. Nach dieser Definition wäre mysqli-* "angenehmer".

            Zukunftsaussichten

            Andererseits hat PDO natürlich den sonnenklaren Vorteil, dass es mehr Datenbanken unterstützt. Da nur der Teufel weiß, wie lange MariaDB und MySQL aus Sicht des Interfaces noch kompatibel sind und nur ein anderer Teufel weiß, was davon $HOSTER den Kunden installiert, würde ich jedenfalls bei neuen Projekten unbedingt auf PDO setzen. Einer der Gründe ist übrigens SQLite. Wenn ich sehe, wie oft projektgebundene Minitabellen im MySQL-"Monster"-Server gehalten werden...

            Performance

            Ich dachte eigentlich, mysqli müsste deutlich performanter sein, weil es sich auf eine Datenbank konzentriert und also gegenüber PDO eine Abstraktionsschicht einspart. Doch das ist offenbar nicht so. Ich habe mal ein wenig nach Performance-Tests gesucht und bin fündig geworden. Da gibt es einige, die dann teilweise - auch in Abhängigkeit von der PHP-Version - widersprüchliche Ergebnisse lieferten. Aber Summa-Summarum sieht es so aus, dass die Performance von PDO und mysqli recht ähnlich ist und dass es eigentlich erst dann interessant wird, wenn zig-tausend oder Millionen Datensätze "durchgeschaufelt" werden müssen. Was im Hinblick auf die Anwendungsfälle, für die PHP gemacht und gedacht ist, eher weniger oft vorkommt.

            1. Tach!

              und angenehmer haben:→ PDO

              Angenehmer

              Hm. Definiere mal "angenehmer".

              Das angenehmer bezieht sich auf das Handling von Prepared Statements.

              Für den, der mal eben hunderte Skripte umschreiben muss, kann es durchaus "angenehmer" sein, dass er einiges davon mit "suchen und ersetzen" (womöglich tools wie sed...) erledigen kann. Nach dieser Definition wäre mysqli-* "angenehmer".

              Kurzfristig. Die Umstellung ist das eine, aber wenn man schon auf ein modernes System umstellt, kann man auch möchten, dessen Möglichkeiten zu nutzen. Eine wesentliche davon sind die Prepared Statements. Und da kommt ein entscheidender Unterschied zwischen mysqli und PDO ins Spiel.

              Wenn man mit mysqli Prepared Statements verwenden möchte, muss man bind_param und bind_result verwenden. Dazu muss man aber Variablen binden. Einfach so einen Wert zu übergeben geht nicht, man muss ihn erst in die gebundene Variable legen. Auch das Ergebnis kann man nicht einfach so als Array oder Objekt entgegennehmen, man hat es nur in den gebundenen Variablen zur Verfügung und muss es sich dann in eine andere Struktur übersetzen, wenn man es nicht gleich an Ort und Stelle ausgibt. Für kleine Scripts ist diese Vorgehensweise nicht weiter tragisch, aber für größere Anwendungen, die mit Datenobjekten arbeiten, ist das unvorteilhaft.

              Auch wenn man anfängt, Universalhandler zu erstellen, die mit Querys mit beliebiger Anzahl Parameter und beliebiger Anzahl Ergebnisfelder umgehen können soll, dann muss man sich was ausdenken, wie man die Parameter und Ergebnisfelder in bindbare Variablen oder gleichwertigen Ersatz übertragen kann. Da kommt man dann an solche Konstrukte wie call_user_func_array() und Referenzen-Handling.

              Wie schön einfach geht das doch bei PDO. Man kann da genauso umständlich binden, aber man kann auch ohne Binden sehr einfach dem Execute ein Array mit Parametern übergeben und fertig ist. Auch die Ergebnisse kann man sich wie bei herkömmlichen Query-Handling als Objekt oder Array liefern lassen, ohne selbst irgendwelche Übertragungen vornehmen zu müssen. Das ist verwenderfreundlich und nicht die viel zu technische Implementierung von mysqli.

              Performance

              Ich dachte eigentlich, mysqli müsste deutlich performanter sein, weil es sich auf eine Datenbank konzentriert und also gegenüber PDO eine Abstraktionsschicht einspart. Doch das ist offenbar nicht so.

              Da verstehe ich deinen Gedankengang nicht so ganz. PDO ist ja kein ORM, was einen Haufen zusätzliche Arbeit erledigt, sondern erstmal nur eine Übersetzung von einem generellen Funktionsnamen in den jeweiligen der DBMS-API. Das macht eine native Schnittstelle nicht prinzipiell anders. Sie übersetzt den spezifischen PHP-Funktionsnamen in den Funktionsnamen der DBMS-API. Die Unterschiede kommen dann zum Vorschein, wenn der eine oder der andere Layer Zusatzfunktionen anbieten und mehr eigene Arbeit als eine solche 1:1 Übersetzung hat. Alles in allem, denke ich, sind die Unterschiede der Übersetzungsarbeit eher im Bereich Mikrooptimierung anzusiedeln. Das eigentliche Datenschaufeln im DBMS ist in der Regel der Hauptanteil an einer Abfrage.

              dedlfix.

        2. Ich fasse mal zusammen:

          • Du bist Dir GANZ sicher, dass es bei mysql oder mariadb bleibt und willst wenig Arbeit haben:→ mysqli funktional
          • Du bist Dir GANZ sicher, dass es bei mysql oder mariadb bleibt und willst es gleich besser machen:→ mysqli objektorientiert
          • Du bist Dir NICHT wirklich sicher, dass es bei mysql oder mariadb bleibt:→ PDO

          Ich füge eine 4. Variante an: Ich bin ein wenig unter Zeitdruck, will entsrechden Zeit gewinnen und (zumindest teilweise) automatisieren. Auch dann käme ggf. temporär mysqli funktional in Frage?

          Pit

          1. temporär

            Wie hießen doch gleich die Lösungen, die nicht dauerhaft sein sollten, aber wegen des Aufwandes der richtigen Lösung - mit allen Nachteilen - bis zum Zusammenbruch bleiben und dann also erst in der peinlichsten Not durch die nächste Lösung, die nicht dauerhaft sein soll, ersetzt werden?

            1. Hello,

              temporär

              Wie hießen doch gleich die Lösungen, die nicht dauerhaft sein sollten, aber wegen des Aufwandes der richtigen Lösung - mit allen Nachteilen - bis zum Zusammenbruch bleiben und dann also erst in der peinlichsten Not durch die nächste Lösung, die nicht dauerhaft sein soll, ersetzt werden?

              Das sind die Profi-Sorien, oder?

              Ich habe nie herausgefunden, was Sorien eigentlich sind ;-P

              Liebe Grüße
              Tom S.

              -- Es gibt nichts Gutes, außer man tut es!
              Das Leben selbst ist der Sinn.
          2. Hello,

            Meine Meinung:

            MySQLi() funktional benutzt reicht vollkommen für alle normalen Webanwendungen. Letztlich sollte man nicht vergessen, dass jedes PHP-Skript bereits ein Objekt des Runtimesystems darstellt. Warum sollte ich OOP²-programmieren, wenn es mit OOP (embedded) doch auch schon geht?

            Allerdings sind einige wichtige Features der PHP-OOP-Programmierung in der prozuduralen nicht darstellbar, weil sie vom Runtime nicht unterstützt werden. "Units", wie man sie aus Turbopascal kennt, gibt es nicht. Funktionen kann man also nicht mehrfach deklarieren in unterschiedlichen Gültigkeitsbereichen...

            Aber man sollte in der prozeduralen PHP-Programmierung nicht das "Array of Functions" unterschätzen!

            Liebe Grüße
            Tom S.

            -- Es gibt nichts Gutes, außer man tut es!
            Das Leben selbst ist der Sinn.
            1. Funktionen kann man also nicht mehrfach deklarieren in unterschiedlichen Gültigkeitsbereichen...

              Das geht wohl:

              <?php namespace Kuh; function says() { echo "Muh!\n"; } namespace Hund; function says() { echo "Wuff!\n"; } namespace Kuh; says(); namespace Hund; says(); ~> php test.php Muh! Wuff!
              1. Hello,

                Funktionen kann man also nicht mehrfach deklarieren in unterschiedlichen Gültigkeitsbereichen...

                Das geht wohl:

                <?php namespace Kuh; function says() {echo "Muh!\n";} namespace Hund; function says() {echo "Wuff!\n";} namespace Kuh; says(); namespace Hund; says(); ~> php test.php Muh! Wuff!

                Nun habe ich endlich in wenigen Zeilen beantwortet bekommen, was ich schon mehrfach in ganz vielen nachgefragt hatte und nie mehr erwartet hatte, wissen zu dürfen ...

                tztz

                Wie ist das mit dem includen innerhalb untgerschiedlicher Namespaces?
                Ok, probiere ich garantiert selber noch aus, aber vielleicht kann ich ja schon mal einen Vorschuss bekommen? Wenn es so funktioniert, wie erhofft, bin ich zufrieden.

                Liebe Grüße
                Tom S.

                -- Es gibt nichts Gutes, außer man tut es!
                Das Leben selbst ist der Sinn.
                1. Wie ist das mit dem includen innerhalb untgerschiedlicher Namespaces?

                  Eigentlich dürfte der Spaß dafür gedacht sein, dass gerade die includierten Libs eigene Namespaces setzen.

                  1. Hello,

                    Wie ist das mit dem includen innerhalb untgerschiedlicher Namespaces?

                    Eigentlich dürfte der Spaß dafür gedacht sein, dass gerade die includierten Libs eigene Namespaces setzen.

                    als ich mir das zuletzt angeschaut habe, war es leider noch grottig.
                    Es kommt mir allerdings immer noch leicht "GOTO-mäßig" vor.

                    Man sollte also jedes Hauptscript mit "namespace main" beginnen?

                    Mir würde sie Syntax "system.crt.goto()" oder eine äquivalente eben besser gefallen, so dass man auch in sequenziellen Funktionsaufrufen jeweils ganz einfach das passende Include ansprechen könnte.

                    Liebe Grüße
                    Tom S.

                    -- Es gibt nichts Gutes, außer man tut es!
                    Das Leben selbst ist der Sinn.
    2. Im Wiki hast Du schon nachgesehen?

      16:15. Mist! Viel zu früh vom schwimmen zurück...

      1. Im Wiki hast Du schon nachgesehen?

        Hi Regina,

        ja, ich habe sogar schon daraus zitiert 😉

        Pit

  3. Hallo,

    Du kannst mit einem geeigneten Editor, welcher auch in Verzeichnissen sucht und ersetzt, die "mysql_"-Funktionen durch das "mysqli_"-Pendant ersetzen - ggf. auch mit Verbindungskennung, z.B.

    $connection = mysqli_connect(…

    suche nach "mysql_query(" ersetze mit "mysqli_query($connection, "

    Das Ganze natürlich für jede verwendete "mysql_"-Funktion - aber so viele sind das ja nicht.

    Viele Grüße Basti

    1. Hi Basti,

      Du kannst mit einem geeigneten Editor, welcher auch in Verzeichnissen sucht und ersetzt, die "mysql_"-Funktionen durch das "mysqli_"-Pendant ersetzen - ggf. auch mit Verbindungskennung, z.B.

      Das habe ich bereits über ein eigenes php-script erledigt.

      suche nach "mysql_query(" ersetze mit "mysqli_query($connection, "

      Genau so habe ich es gemacht.

      Das Ganze natürlich für jede verwendete "mysql_"-Funktion - aber so viele sind das ja nicht.

      Ich bae es für:

      • mysql_connect
      • mysql_select_db
      • mysql_set_charset
      • mysql_query
      • mysql_real_escape_string
      • mysql_fetch_row
      • mysql_fetch_assoc
      • mysql_affected_rows
      • mysql_num_rows

      gemacht.

      Habe ich was vergessen??

      Vorteil eines scripts ist natürlich, dass ich alles in einem Rutsch machen kann und somit auch immmer wieder neu ansetzen, dann testen und ggf. das Script anpassen kann. In einem editor müßte ich alles nacheinander machen. Das wäre aufwändiger.

      Eines fehlt mir noch, aber dafür werde ich einen neuen Thread aufmachen, weil das mit diesem thema wirklich nichts mehr zu tun hat.

      Pit

      Folgende Nachrichten verweisen auf diesen Beitrag:

  4. Hallo,

    der Umstieg auf mysqli hat bis hierher schon ganz gut funktioniert. Ich bin nun dabei, Fehler zu debuggen, die aufgetreten sind.

    Ein Fehler entsteht bei einem Script, welches ich irgendwann mal auf PDO umgestellt hatte.

    Die Zeile

    while ($row = $result->fetch()){

    bringt folgenden Fehler hervor:

    Fatal error: Call to undefined method mysqli_result::fetch()

    Eine PDO-DB-Verbindung besteht bereits, trotzdem versucht die fetch-Methode in obigem Aufruf auf eine msqli-Methode zuzugreifen.

    Ok, ich könnte das script von PDO auf mysqli umschreiben, aber sollten nicht mysqli und PDO parallel nebeneinander laufen können?

    Pit

    1. Tach!

      Eine PDO-DB-Verbindung besteht bereits, trotzdem versucht die fetch-Methode in obigem Aufruf auf eine msqli-Methode zuzugreifen.

      Von einem Objekt ausgehend kann man immer nur auf die Mitglieder zugreifen, die zum Objekt und dessen Klasse gehören.

      Ok, ich könnte das script von PDO auf mysqli umschreiben, aber sollten nicht mysqli und PDO parallel nebeneinander laufen können?

      Parallel ja, aber nicht gemischt. Ein PDO-Objekt hat keine mysqli-spezifischen Mitglieder und umgekehrt.

      dedlfix.

      1. Hi dedlfix,

        Parallel ja, aber nicht gemischt. Ein PDO-Objekt hat keine mysqli-spezifischen Mitglieder und umgekehrt.

        Ich dachte aber, ich nutze sie (nur) parallel und nicht gemischt. Hast Du einen Tip, wie ich die beiden strikt trennen kann?

        Ich habe in allen scripten (nun) mysqli und in diesem Script ausschließlich PDO, inkl. eigenem Verbindungsaufbau, usw.

        Ich verstehe gar nicht, warum die Zeile while ($row = $result->fetch()){ auf mysqli zugreift???

        Pit

        1. Tach!

          Hast Du einen Tip, wie ich die beiden strikt trennen kann?

          Grundlagen objektorientierter Programmierung. Wenn du ein PDO-Objekt erstellst, kannst du damit nur im PDO-Stil arbeiten. Du kannst nicht mit diesem PDO-Objekt auf mysqli wechseln. Auch nicht andersrum.

          Ich verstehe gar nicht, warum die Zeile while ($row = $result->fetch()){ auf mysqli zugreift???

          Weil $result ein mysqli_result-Objekt ist. Das hast du vermutlich von einem vorhergehenden mysqli_query() bekommen. Oder es war ein $ein_objekt->query(), wobei das $ein_objekt ein mysqli-Objekt gewesen ist.

          dedlfix.

          1. Hi,

            Weil $result ein mysqli_result-Objekt ist. Das hast du vermutlich von einem vorhergehenden mysqli_query() bekommen. Oder es war ein $ein_objekt->query(), wobei das $ein_objekt ein mysqli-Objekt gewesen ist.

            Seltsamerweise mußte ich die query einfach neu ausführen… Im Mix mit mysql_ mußte ich das aber nciht.

            $result ist in diesem Script aber irgendwie verloren gegangen... woraufhin sich das Script ein bereits aus mysqli vorhandenes Objekt gekrallt hat.

            Naja, so jedenfalls erkläre ich es mir.

            Danke, dedlfix,

            Pit

            1. Hallo Pit,

              wenn $result ein älteres $mysqli_result enthielt, dann hast Du ein Problem mit dem Gültigkeitsbereich deiner Variablen. Wenn man die gleiche Variable an verschiedenen, voneinander unabhängigen Stellen für den gleichen Zweck benutzt (nämlich Speichern eines Query-Results), ist das Chaos vorprogrammiert.

              Ich finde es aber schon merkwürdig, dass das passiert. Oben hast Du doch geschrieben, dass dein Code in Funktionen gegliedert ist. D.h. eigentlich solltest Du doch Funktionen haben, die eine gewisse Datenmenge X beschaffen und dieses X dann zurückgeben. Die DB-Spezifika dazu sollten außerhalb der Funktion nicht sichtbar werden, bis auf das globale Objekt mit der PDO- oder mysqli-Connection. Ist deine Funktionengliederung möglicherweise zu grob?

              Bei mysql gibt es kein Result-Objekt, deswegen trat das da nicht auf.

              Rolf

              -- sumpsi - posui - clusi