Zur Navigation

Bewertungen von Beiträgen [3]

Umsetzung in SQL?

21 Jörg Kruse

Für TEXT ist UNIQUE wohl nicht geeignet. Ich habe es schon für Felder vom Typ VARCHAR verwendet, wie z.B. für Emailadressen und Usernamen - da waren die Indexe allerdings auch angebracht.

Kann man davon ausgehen, daß InnoDB immer zur Verfügung steht?

InnoDB ist seit MySQL 5.5 die Standard-Engine. Auch in älteren Versionen ist es wohl meist (?) enthalten. Beim Anlegen der Datenbanktabellen sollte zur Sicherheit auch die Datenbank-Engine definiert werden (mit dem Schlüsselwort ENGINE)

06.05.2015 20:06

22 Ranma (Gast)

Jetzt ist mir wieder eingefallen, wieso ich ein Problem mit Transaktionen hatte. Ich dachte fälschlicherweise erst, daß ich ein paar meiner Datenbanktabellen mit ALTER TABLE mißhandeln müßte. ALTER führt zu einem automatischem COMMIT und bricht dadurch die Transaktion ab. Also mußte ich eines von beiden loswerden. Glücklicherweise brauche ich ALTER TABLE garnicht. Also kann ich mich endlich an die Transaktionen wagen.

Mit Prepared Statements kombiniert ergeben die Transaktionen ganz schön langen Quelltext. Angeblich soll es eine Funktion mysqli_start_transaction() geben, aber die nicht weiter kommentiert sein. In keinem der Beispiele, die ich bisher gefunden habe, wird sie verwendet. Das Syntax-Highlighting meines Editors kennt sie auch nicht. Die Beispiele zu Erklärungen der Transaktionen senden entweder START TRANSACTION oder BEGIN per mysqli_query() oder lassen das ganz weg. Letztere Möglichkeit verwirrt mich allerdings etwas. Möglicherweise bedeutet das Abschalten des Autocommit bereits implizit, daß man nachfolgend Transaktionen macht? Aber mysqli_rollback() oder wie immer man den Befehl übermittelt, kann so doch nicht wissen, bis wohin rückabgewickelt werden soll? Sollte ich sicherheitshalber START TRANSACTION senden, dann sollte ich mir sicher sein (aber das ist nicht der Fall), daß eine Transaktion innerhalb einer anderen Transaktion einfach keine Auswirkung hat?
Ranma

14.05.2015 04:07

23 Jörg Kruse

Wenn autocommit deaktiviert ist, dann beginnt eine Transaktion nach einem COMMIT und endet mit einem COMMIT

Mit "START TRANSACTION" wird der Autocommit gewissermaßen temporär aufgehoben:

Zitat von MySQL Manual
To disable autocommit mode implicitly for a single series of statements, use the START TRANSACTION statement:

[...]

With START TRANSACTION, autocommit remains disabled until you end the transaction with COMMIT or ROLLBACK. The autocommit mode then reverts to its previous state.

14.05.2015 20:59

24 Ranma (Gast)

Im Sommer habe ich weniger Zeit dafür, darum geht es nur noch sehr langsam voran. Ich muß noch ein paar Datenbanktabellen umbauen. Vor allem die für die Lokalisierung. Da habe ich nämlich schon einige Tage Arbeit für die Einträge darin investiert und würde die darum nur ungern verlieren. Darum ist die Tabelle immer noch so aufgebaut, daß sie sich nur mit ALTER TABLE vervollständigen läßt.

Aber erstmal etwas wichtigeres. Bei der Verwendung von Transaktionen werden die einzelnen Aktionen tatsächlich ausgeführt, auch wenn man sie dann durch ein Rollback wieder rückgängig machen kann. Das wirft für mich zwei immernoch ungeklärte Probleme auf. Wenn die Aktionen tatsächlich ausgeführt werden, ohne (weil ich in der Variante das LOCK TABLES nicht verwende) daß die Tabelle gesperrt ist, dann können sich doch die Transaktionen aus unterschiedlichen Instanzen des Skripts (also Einträgen durch unterschiedliche User) in die Quere kommen? Aber gerade das wollte ich eigentlich verhindern...

Das andere Problem, das vielleicht keines ist, tritt nur beim Rollback auf. Dazu habe ich nämlich gelesen, daß zwar die in einer Tabelle gemachten Einträge wieder entfernt werden, aber der Rollback keinen Einfluß auf ein AUTO INCREMENT hat. Wenn also die Datenbank beim Eintragen eine neue ID-Nummer dem Eintrag hinzufügt, dann bleibt die auch nach einem Rollback erhalten. Die meisten Tabellen lassen keine Einträge mit ausschließlich leeren Spalten zu, also wird der Eintrag komplett gelöscht, aber die AUTOINCREMENT-Funktion zählt erst nach dem gelöschten ID-Wert weiter und es entsteht eine Lücke in der Zählung. Zumindest falls ich das richtig verstanden habe. Möglicherweise stören sich andere SQL-Funktionen, vor allem für Sortierung, nicht an solchen Lücken. Dann ist das kein Problem. Diese Möglichkeit wäre sogar besonders erfreulich, weil dann solche Lücken zum Beispiel auch durch Moderationsmaßnahmen entstehen dürfen und toleriert werden können. Aber wäre da noch die Möglichkeit, daß so eine Lücke nicht ignoriert wird. Das wäre dann doch ein Problem.
Ranma

01.06.2015 03:05

25 Jörg Kruse

Wenn die Aktionen tatsächlich ausgeführt werden, ohne (weil ich in der Variante das LOCK TABLES nicht verwende) daß die Tabelle gesperrt ist, dann können sich doch die Transaktionen aus unterschiedlichen Instanzen des Skripts (also Einträgen durch unterschiedliche User) in die Quere kommen?

Kannst du da mal ein konkretes Beispiel geben, auf welche Weise sie sich in die Quere kommen? möglicherweise lässt sich dies auch anders lösen.

Wenn man z.B. einen Zähler hochzählen möchte, dann macht man dies direkt in SQL (`SET zaehler = zaehler + 1`), statt ihn erst abzufragen und ihn dann addiert zurückzuschreiben. Damit vermeidet man Race Conditions bei parallelen Zugriffen auf das Script.

Wenn also die Datenbank beim Eintragen eine neue ID-Nummer dem Eintrag hinzufügt, dann bleibt die auch nach einem Rollback erhalten. Die meisten Tabellen lassen keine Einträge mit ausschließlich leeren Spalten zu, also wird der Eintrag komplett gelöscht, aber die AUTOINCREMENT-Funktion zählt erst nach dem gelöschten ID-Wert weiter und es entsteht eine Lücke in der Zählung. Zumindest falls ich das richtig verstanden habe. Möglicherweise stören sich andere SQL-Funktionen, vor allem für Sortierung, nicht an solchen Lücken. Dann ist das kein Problem.

Diese Lücken sind unproblematisch, andernfalls könnte man ja keine Daten löschen.

01.06.2015 17:37

26 Ranma (Gast)

Ich brauche die Transaktionen (oder LOCK TABLES), um Beiträge im Nested-Set-System speichern zu können. Das heißt vor jedem INSERT müssen zwei UPDATE erfolgen, die "Platz" für das INSERT schaffen. Wenn ich Lücken in der Zählung nicht schließen muß, dann wird natürlich jeder Eintrag irgendwo eingehängt, aber vielleicht an der falschen Stelle.

Vielleicht wird es sogar noch komplizierter, weil ich erst noch eine Sprachweiche baue, die dann noch berücksichtigt werden muß.
Ranma

02.06.2015 04:44

27 Ranma (Gast)

Übrigens könnte man auch dann Daten löschen, wenn die Lücken problematisch wären. Man hätte dann alle nachfolgenden Einträge mittels weiterer Anweisungen wieder dekrementieren müssen. Aber ich will die Datenbankhersteller nicht auf blöde Ideen bringen....
Ranma

02.06.2015 04:46

Beitrag schreiben (als Gast)

Die Antwort wird nach der Überprüfung durch einen Moderator freigeschaltet.





[BBCode-Hilfe]