stefan: UPDATE / invertieren einer col in MYSQL

ich will in einer tabelle über ein PHP/javascript-interface einen wert invertieren [ col stat kann zwei werte haben 0 und 1 beim invertieren soll 0 1 werden und 1 0 die col ist CHAR]

meine Lösung wäre : UPDATE xyz set stat=if(stat='0','1','0) WHERE a='aaa',b='bbb' etc. LIMIT 22

soweit so gut. das problem, dass nun auftritt ist relativ eigenartig : bei etwa 4 von 10 versuchen funktioniert diese query komplett richtig und tut was sie tun soll. bei den restlichen 6 leider nicht - der wert wird nicht umgesetzt.

ich vermutete ein caching problem, da die server var have_query_cache YES ist und wollte dies durch das einfügen eines zusätzlichen wertes in die query - phptimestamp + dbfeld - umgehen, da ich leider keinen zugriff zum umsetzen der var habe -> nada... der timestamp wird richtig gesetzt und ist auch jedesmal unterschiedlich, das problem mit dem stat feld bleibt allerdings gleich.

falls jemand ne idee hat was noch der grund sein kann bzw. ob ich have_query_cache so wie oben beschrieben umgehn kann würd ich mich sehr über ne reply freun.

danke
stef

  1. hi,

    meine Lösung wäre : UPDATE xyz set stat=if(stat='0','1','0) WHERE a='aaa',b='bbb' etc. LIMIT 22

    meine wäre SET stat=MOD(stat+1,2) gewesen :-)

    das problem, dass nun auftritt ist relativ eigenartig : bei etwa 4 von 10 versuchen funktioniert diese query komplett richtig und tut was sie tun soll. bei den restlichen 6 leider nicht - der wert wird nicht umgesetzt.

    hast du überprüft, ob die DB ordentliche ausführung der query angibt, oder ob sie einen fehler meldet?

    ich vermutete ein caching problem, da die server var have_query_cache YES ist

    beeinflusst das wirklich auch UPDATE-queries?
    würde ich für ungünstig halten - bei SELECT-queries wäre es ja noch verständlich, aber bei UPDATE halte ich das für kontraproduktiv.

    falls jemand ne idee hat was noch der grund sein kann#

    wie gesagt, überprüfe erst mal, ob die DB fehlerfrei ausführung der query meldet.

    dazu wären z.b. wenn du PHP und mysql einsetzt, mysql_error() und mysql_affected_rows() nützlich.

    gruß,
    wahsaga

    --
    "Look, that's why there's rules, understand? So that you _think_ before you break 'em."
    1. die query läuft ohne fehler ab...
      auch dann wenn des resultat nicht "stimmt" :(

      die idee mim mod find ich allerdings nett
      hilft nur leider auch nix :)

      stef

      1. hi,

        die query läuft ohne fehler ab...
        auch dann wenn des resultat nicht "stimmt" :(

        bleiben wir mal bei meiner vermutung, dass das cachen sich nur auf SELECT-, nicht aber auf UPDATE-queries auswirkt:

        dann könnte es doch sein, dass das UPDATE zwar korrekt ausgeführt wurde - du das "richtige" ergebnis mit einem anschliessenden SELECT aber nicht angezeigt bekommst, weil eben diese SELECT-query noch gecached ist, und du "alte" daten präsentiert bekommst ...?

        gruß,
        wahsaga

        --
        "Look, that's why there's rules, understand? So that you _think_ before you break 'em."
        1. hi,

          dann könnte es doch sein, dass das UPDATE zwar korrekt ausgeführt wurde - du das "richtige" ergebnis mit einem anschliessenden SELECT aber nicht angezeigt bekommst, weil eben diese SELECT-query noch gecached ist, und du "alte" daten präsentiert bekommst ...?

          überprüf' das doch bitte mal - http://dev.mysql.com/doc/mysql/de/Query_Cache_in_SELECT.html beschreibt, wie du _in_ der SELECT-query selbst per parameter angeben kannst, ob die ergebnisse gecached werden dürfen oder nicht.

          gruß,
          wahsaga

          --
          "Look, that's why there's rules, understand? So that you _think_ before you break 'em."
        2. hi,

          dann könnte es doch sein, dass das UPDATE zwar korrekt ausgeführt wurde - du das "richtige" ergebnis mit einem anschliessenden SELECT aber nicht angezeigt bekommst, weil eben diese SELECT-query noch gecached ist, und du "alte" daten präsentiert bekommst ...?

          nein, sorry, scheint doch die falsche fährte zu sein - http://dev.mysql.com/doc/mysql/de/Query_Cache_How.html sagt explizit:

          "Wenn sich eine Tabelle ändert (INSERT, UPDATE, DELETE, TRUNCATE, ALTER oder DROP TABLE|DATABASE), werden alle gecacheten Anfragen, die diese Tabelle benutzten (möglicherweise über eine MRG_MyISAM-Tabelle!) ungültig und werden aus dem Cache entfernt."

          gruß,
          wahsaga

          --
          "Look, that's why there's rules, understand? So that you _think_ before you break 'em."
          1. hmmm also is mei idee mim cache auch mist...
            aber ich hab da grad von nem mysql bug gelesen.. der auf mei version (4.0.18) noch zutreffen könnte.

            da wird beschrieben dass mysql probleme hat wenn in (VAR)CHAR feldern zahlen stehn. komisch. ich überprüf dass mal... danke auf jedenfall mal für deine hilfe

            stef

            1. feld typ ist auch nicht schuld. ob char oder tinyint - problem besteht weiterhin.

              *seufz*

              1. hi,

                feld typ ist auch nicht schuld. ob char oder tinyint - problem besteht weiterhin.

                wenn nur die werte 0 und 1 in dem feld vorkommen können, solltest du sowieso überlegen, einen ENUM dafür zu verwenden.

                gruß,
                wahsaga

                --
                "Look, that's why there's rules, understand? So that you _think_ before you break 'em."
                1. schon klar. nur wie gesagt... der feld typ ist leider nicht schuld
                  und im bugreport stand nur was von (VAR)CHAR felder bei denens zu problemen kommen kann. ist also jacke wie hose ob des jetzt CHAR, TINYINT, ENUM oder sonst etwas ist :P

                  stef

        3. wäre zu schön um wahr zu sein. ich hab so zirka alles probiert was möglich ist. auch dass was du anführst erschien mir anfangs sehr plausibel. auf die waghalsige idee mit dem query_cache kam ich erst als ich 2 tage alles mögliche probiert hab.

          was ich so alles gemacht habe :

          werte asgelesen, via php invertiert dann upgedatet etc.
          -> nada

          abgleiche gemacht von dem was php liefert und dem was ein graphical db manager so tut (ems mysql manage 2)
          -> im manager gleiche werte wie in php vor dem UPDATE
          -> nach dem update auch die gleichen werte nur halt die falschen (0 immer noch 0)
          -> nada

          das update komplett ohne select davor danach oder sonstwo ausgeführt
          -> nada

          hab selbst schon 22 querys in php generiert und jeden wert einzeln geändert - das geht sogar allerdings, oh wunder, auf kosten der performance.
          -> hurra... allerdings ist die wartezeit für den zweck ungeeignet
          -> nada

          bin irgntwie komplett mim latein am ende...

          der aufbau der tabelle ist wie folgt von relevanz :

          sektor
          reihe
          platz

          stat

          sektion+reihe+platz ergeben einen unique key.
          solange ich alle 3 angebe um den stat eines platzes zu ändern ist alles bestens.

          wenn ich wie in meiner frage beschrieben versuche eine ganze "reihe" (22 plätze)-> 22 rows in der db, einfach zu invertiern funktionierts nicht mehr - ich spreche auch sicher die richtige "reihe" an - es geht ja 4 von 10 mal :P

          es liegt auch garantiert kein fehler im frontend vor.

          stef

  2. yo,

    meine Lösung wäre : UPDATE xyz set stat=if(stat='0','1','0) WHERE a='aaa',b='bbb' etc. LIMIT 22

    versuch mal anstelle des vergleich operators '=' einen strcmp durchzuführen.

    Ilja

    1. hmmm... danke für die reply

      aber

      1. ist die von mir angegebene updatelösung zwar nicht die beste doch nicht verursacher des problems - funktioniert ja eigentlich korrekt - halt nur 4 von 10 mal, aber die query als solches ist nicht schuld daran.

      2. hilft strcmp hier nur bedingt nachdem ja 3 werte als ergbnis in frage kommen 1, 0, -1 ich brauch aber nur 0 oder 1 :) die lösung vom wahsaga mit mod fand ich da schon recht nett... hat allerdings auch nicht geholfen.

      danke trotzdem
      stef

      1. yo,

        solange du noch keine lösung hast, wäre ich vorsichtig, den verursacher auszuschließen. ich kenne solche stringvergleiche mit der 0 von php her und dort ist es problematisch und zwar in nur ganz bestimmten fällen. versuch es einfach mal.

        Ilja

        1. ich habe das selbstverständlich versucht.
          wäre ja sonst ne frechheit .)

          natürlich ist ne implementierung deines vorschlages - wenn auch bedingt - (3 werte) möglich... allerdings failen nichts desto trotz die updates bei etwa 4 von 10 versuchen.

          auch ich kenne die string vergleiche von php her - in dem fall hier ist es jedoch wie gesagt komplett egal, hab auch tinyint bzw enum als field type probiert hilft ebensowenig.
          wodurch sich mir der schluss aufzwingt dass es an der query an sich -immerhin nun bereits 12 verschiede für das selbe problem probiert - die auch allesamt keine mysql_errors liefern - garantiert nicht liegt.

          nachdem ich jetzt mal das ganze update problemchen mit meinem ursprünglichen syntax in nem mysqlmanager probiert habe und dort NICHT die gleichen probleme auftauchen - wohlgemerkt unter verwendung der selben query und eingangsdaten - verstehe ich ohnehin nichts mehr.

          ich glaube mittlerweile dass die db anbingung übers php spinnt - kann aber eigentlich auch nicht sein weil ja andere querys die übers selbe system rennen gehn. pff...

          stef

          1. yo,

            ich glaube mittlerweile dass die db anbingung übers php spinnt - kann aber eigentlich auch nicht sein weil ja andere querys die übers selbe system rennen gehn. pff...

            schon mal einen geister-austreiber versucht. nicht das ich daran glauben würde, aber es hilft vielleicht der verzweifelung etwas entgegen zu setzen.. ;-)

            Ilja

            1. eigentlich noch nicht aber danke für den tipp .)

              so ein schei..hmm..benkleister :)
              i sitz da jetzt scho 3 tag davor und nix geht

              *heul*

  3. Hallo stefan,

    meine Lösung wäre : UPDATE xyz set stat=if(stat='0','1','0) WHERE a='aaa',b='bbb' etc. LIMIT 22

    nach Konvertiern der Spalte stat in z.B. int, teste doch mal folgenden Query:
    UPDATE xyz set stat=1-stat WHERE ....
    Vermutlich wird das aber auch nichts bringen.
    Ist stat sicher kein Bestandteil eines Indexes, der zum Ausführen des Update-Queries benutzt wird?
    Ein möglicher workaround wäre, das Update auf 3 Queries aufzuteilen.
    1. set 0 -> 2
    2. set 1 -> 0
    3. set 2 -> 1
    Funktioniert dieser Weg?

    danke
    stef

    tschau,
    ziegenmelker

    1. es liegt wie gesagt nicht an der query.
      auch diesen weg habe ich bereits in gewisser
      weise implementiert - mit den selben problemen.

      danke trotzdem
      stef

      1. Gib uns doch bitte mal die genaue Spezifikation der Tabelle. Das macht mich langsam wirklich neugierig *gg*

        cu, ziegenmelker

        1. CREATE TABLE plaetze (
            id bigint(20) NOT NULL auto_increment,
            sektor tinyint(3) default NULL,
            reihe tinyint(3) default NULL,
            platz tinyint(3) default NULL,
            stat char(1) NOT NULL default '0',
            datum datetime default NULL,
            event varchar(255) default NULL,
            PRIMARY KEY  (id)
          ) TYPE=MyISAM ROW_FORMAT=DYNAMIC

          wie sich erkennen lässt ne kontingentgschichte... die query invertiert den stat - der angibt ob ein platz frei ist oder nicht. ich habs auch schon mit anderen indizes versucht - auch ohne auto_increment. hilft alles nix. sobald ich für mein gegenwertiges beispiel eine ganze "reihe" (22 Plätze - deswegn auch des limit) invertiern will macht er dies nicht immer. die steuerung der querys funktioniert über ein php/javascript frontend in dem auch die einzelplatzfreigabe erfolgt - die ohne jedes problem abläuft.

          stef

          1. CREATE TABLE plaetze (
              id bigint(20) NOT NULL auto_increment,
              sektor tinyint(3) default NULL,
              reihe tinyint(3) default NULL,
              platz tinyint(3) default NULL,
              stat char(1) NOT NULL default '0',
              datum datetime default NULL,
              event varchar(255) default NULL,
              PRIMARY KEY  (id)
            ) TYPE=MyISAM ROW_FORMAT=DYNAMIC

            wie sich erkennen lässt ne kontingentgschichte... die query invertiert den stat - der angibt ob ein platz frei ist oder nicht. ich habs auch schon mit anderen indizes versucht - auch ohne auto_increment. hilft alles nix. sobald ich für mein gegenwertiges beispiel eine ganze "reihe" (22 Plätze - deswegn auch des limit) invertiern will macht er dies nicht immer. die steuerung der querys funktioniert über ein php/javascript frontend in dem auch die einzelplatzfreigabe erfolgt - die ohne jedes problem abläuft.

            stef

            Also ich habe hier eine fast identische Tabelle angelegt:
            CREATE TABLE sektors (
              sektor\_id bigint(20) unsigned NOT NULL auto_increment,
              sektor int(10) unsigned NOT NULL default '0',
              reihe int(10) unsigned NOT NULL default '0',
              platz int(10) unsigned NOT NULL default '0',
              stat tinyint(3) unsigned NOT NULL default '0',
              timestamp timestamp(14) NOT NULL,
              PRIMARY KEY  (sektor\_id),
              UNIQUE KEY sektor\_idx (sektor,reihe,platz)
            ) TYPE=MyISAM ROW_FORMAT=DYNAMIC;

            Ein Update mittels
            update sektors set stat=1-stat limit 22
            funktioniert völlig problemlos, wäre auch schlimm, wenn nicht. Irgendwo muß da bei Dir an einer anderen Stelle ein Fehler sein.
            Wie gesagt, das _muß_ funktionieren, sonst könnte man mySQL komplett in die Tonne treten.
            Ausprobieren kannst Du es zur Zeit hier:
            http://217.226.195.163/test/stev/stev.php
            (die IP wechselt um ca 19:14 Uhr, wenn Du sie später noch mal brauchst kann ich dir gerne die neue mitteilen)

            cu, ziegenmelker

            1. Das ganze noch mal mit
              "update sektors set stat=1-stat where sektor=1 and reihe=2 limit 22"
              null problemo

              http://217.226.195.163/test/stev/stev2.php

              cu, ziegenmelker

              1. kewle sache... so wars auch gedacht

                allerdings gehts bei mir nicht :) selber source ...
                sogar selbe felder - welche mysql version hast du ?

                danke vielmals für die grosse hilfe
                stef

                1. sogar selbe felder - welche mysql version hast du ?

                  mySQL 3.23.52
                  apache 1.3.26
                  php 4.2.2

                  danke vielmals für die grosse hilfe
                  stef

                  danke, freut mich, wenn ich helfen konnte, aber der Fehler ist damit ja immer noch nicht gefunden. :(
                  Vielleicht solltest Du nach meinem Muster auch mal eine ganz einfache Seite machen, und das Update da testen.

                  cu, ziegenmelker

                  1. ich kapier gar nix mehr... hab hier mysql 4.0.18... allerdings habe ich gerade des rätsels lösung gefunden. der server cached tatsächlich auch updates - wie idiotisch - du wirst vermutlich den timestamp via mysql einfügen, ich hingegen habe dies via php getan. seit ich ein timestamp feld den wert via mysql einfüge geht alles wie es soll... was für ein dreck. updates cachen *sigh* sogar wenn die query OFFENSICHTLICH unterschiedlich ist. kA was das soll aber ich wers mal als mysql-bug reporten.

                    danke für die grosse hilfe :)
                    stefan

                    1. ich kapier gar nix mehr... hab hier mysql 4.0.18... allerdings habe ich gerade des rätsels lösung gefunden. der server cached tatsächlich auch updates - wie idiotisch - du wirst vermutlich den timestamp via mysql einfügen, ...

                      Selbstverständlich! Das lasse ich immer den db-Server machen, alles Andere kann ins Chaos führen ;)

                      ... ich hingegen habe dies via php getan. seit ich ein timestamp feld den wert via mysql einfüge geht alles wie es soll... was für ein dreck. updates cachen *sigh* sogar wenn die query OFFENSICHTLICH unterschiedlich ist. kA was das soll aber ich wers mal als mysql-bug reporten.

                      Also ich freu' mich ja für Dich, das es jetzt klappt, aber das cachen von updates (+inserts?) halte ich doch für irgendwie unwahrscheinlich. Und wenn denn da ein Fehler ist/wäre, sollte das ja auch schon früher aufgefallen sein.
                      Hast Du es eigentlich auch mal nach dem update mit
                      $query = "flush tables";
                      versucht?
                      http://dev.mysql.com/doc/mysql/en/FLUSH.html

                      danke für die grosse hilfe :)
                      stefan

                      Das hört man doch gerne :)
                      cu,
                      ziegenmelker

                      1. pff... sorry dass ich nicht vorher schreibe aber ich habe bis jetzt getestet... so wies aussieht hat er doch kein cache problem ...
                        im gegenteil... auch dass mit dem timestamp als lösung bei meiner anwendung war wohl eher glück. die updates werden offensichtlich einfach zu langsam durchgeführt.

                        egal welche "redunante" definition ich in einem update verwende - updates mit einer wert definition alla stat = blahblbah + stat oder if blahblah etc. brauchen länger als 5 sekunden um tatsächliche auswirkungen auf die daten innerhalb der tbl zu haben bzw um vom mysql korrekt interpretiert zu werden (dazu untn mehr). da mein system eine anwendung darstellt die "onklick" funktionieren soll geht dies meines derzeitigen wissens nach offensichtlich doch nur mit konstanten werten für die updates.

                        dieselbe query gesendet mit einem stat='0' oder stat='1' statt einer if stat, mod stat oder anderen "rekursiven" definition benötigt <1sec um änderungen an den daten hervorzurufen.

                        des pudels kern allerdings ist, dass die "alten" querys, obwohl die seite die die querys sendet offensichtlich fertig geladen hat und diese auch beim server korrekt ankommen [affected rows 22, true für mysql_query(), "konstante" werte wie etwa php timestamps werden korrekt eingefügt etc.], bei "rekursiven" definitionen "nachträglich" falsch ausgeführt werden.

                        das heisst der stat in einer kurz auf die vorherige query folgende query wird definiert durch den stat wert in der vorherigen query obwohl angegeben werte bereits korrekt eingefügt wurden. darf zwar eigentlich nicht sein da ja updates von links nach rechts abgearbeitet werden aber naja.

                        z.B:
                        ich setze den stat einer reihe von 1 auf 0 die "alte" 1 wird allerdings für den stat-wert der folgenden query genommen die allerdings bereits 0 als tatsächlichen stat-wert hat und diese bleibt daher 0 statt dass sie 1 wird und dass obwohl werte die danach in der selben query gesendet werden korrekt geändert werden.

                        mir fällt leider kein workaround für dieses problem ein bzw wodurch es tatsächlich zu stande kommt. nichtsdestotrotz irgentwie doof von mir dass ich nicht früher draufgekommen bin - wohl zuviel vertrauen auf die geschwindigkeit und funktionstüchtigkeit lt. manual von mysql - aber was solls. mir wird nun jedoch wohl nichts anderes übrig bleiben als das ursprünglich geplante frontend umzucoden... bzw die werte die stat innerhalb der tabelle hat zu erraten :)

                        fallst lust hast dieses mysql interne problem bei dir am server nachzuvollziehn mach dir eine seite mit 2 iframes. in einem iframe wird ne datei geladen in der die darstellung und des abschicken der daten wobei per klick jeweils eine "reihe" invertiert wird vorgenommen, ans 2te werden via javascript die querys vom ersten andn server geschickt und in der "haupt"-datei machst da an refresh button fürs erste iframe. dann klickst nacheinander ein paar reihen durch - und siehe da - egal wast machst - er macht fehler bei der stat row. diest dann beim refreshen leicht siehst. mit glück packst so wie ich mitm timestamp 10 reihen hintereinander. mit pech nicht mal 2.

                        dank dir trotzdem nochmal für deine hilfe... nachdem ich nach absenden meiner letzten nachricht ans forum gesehn hab dass dein lösungsweg nun doch ned geht bini auszuckt und hab vor lauter wut mei tastatur zertrümmert und musste dann erst mal ne neue kaufn :P
                        danach hab ich mich nochmal 6 stund hingsetzt und bin alles durchgegangen...auch so kommt man zu lösungen und ner neuen tastatur :)

                        stef

                        1. Hi stef,

                          .............. _jede_ Menge Text ..................

                          ja, mach das mal mit der Testseite, ich hab da schon einen Verdacht ;)

                          tschau,
                          ziegenmelker

                          p.s. ich hoffe, Du hast Dir eine anständige Cherry Tastatur gekauft :)

  4. ich will in einer tabelle über ein PHP/javascript-interface einen wert invertieren [ col stat kann zwei werte haben 0 und 1 beim invertieren soll 0 1 werden und 1 0 die col ist CHAR]

    meine Lösung wäre : UPDATE xyz set stat=if(stat='0','1','0) WHERE a='aaa',b='bbb' etc. LIMIT 22

    die lösung von wahsaga mit mod ist doch astrein.

    soweit so gut. das problem, dass nun auftritt ist relativ eigenartig : bei etwa 4 von 10 versuchen funktioniert diese query komplett richtig und tut was sie tun soll. bei den restlichen 6 leider nicht - der wert wird nicht umgesetzt.

    das ist wirklich eigenartig!

    aber was soll LIMIT 22 ?

    mach doch einfach mal einen test mit einer neuen tabelle, und probiere den update mal ohne WHERE und LIMIT aus.
    dann gehe sukzessive weiter, erst mit WHERE, dann zusätzlich LIMIT.

    so läßt sich der fehler leichter eingrenzen.

    1. ohne where eingrenzung ist die sache nicht mehr nützlich für mich
      das limit 22 habe ich nur eingefügt weil ich dachte es macht das ganze vielleicht schneller - es werden maximal 22 rows geändert - auch diese angabe ist völlig korrekt. lies bitten den nachrichten baum den ich mim wahsaga gschriebn hab durch, vielleicht verstehst du worans wirklich liegt :)

      danke
      stef

      1. ohne where eingrenzung ist die sache nicht mehr nützlich für mich
        das limit 22 habe ich nur eingefügt weil ich dachte es macht das ganze vielleicht schneller - es werden maximal 22 rows geändert - auch diese angabe ist völlig korrekt. lies bitten den nachrichten baum den ich mim wahsaga gschriebn hab durch, vielleicht verstehst du worans wirklich liegt :)

        es liegt wirklich an deinem LIMIT 22!!!!

        was soll der quatsch. die anzahl der ergebnismenge wird durch die WHERE bedingung bestimmt. hier ist ein LIMIT  bei einem UPDATE völlig sinnlos, es sei denn, es soll nur ein TEIL der ergenismenge geändert werden. dann hast du dein ergebnis.

        es ist ein typischer anfägerfehler, die schuld bei dem anderen zu suchen. und dann noch in einem von xxxx usern benutzen system.
        du glaubst doch nicht wirklich einen bug entdeckt zu haben.