Hintergrund : Ich arbeite an http://sqlfiddle.com (meiner Website) und versuche, einen möglichen Missbrauch zu verhindern. Ich hoffe, dass ich durch die Frage nach einem Problem, das ich gerade anspreche, den potenziellen Missbrauch nicht versehentlich verschlimmere, aber was können Sie tun? Ich vertraue euch Leuten.
Ich möchte verhindern, dass ein Benutzer innerhalb eines bestimmten Transaktionsblocks explizite Festschreibungsaufrufe ausgibt. Aus dem Kontext von SQL Fiddle ist der Transaktionsblock der Code, der auf der rechten Seite ausgeführt wird. Grundsätzlich durchlaufe ich eine Liste von Klartext-SQL-Befehlen und führe sie aus. Außerdem möchte ich sicherstellen, dass alle vorgenommenen Änderungen am Ende des Stapels rückgängig gemacht werden. Normalerweise werden ihre Änderungen zurückgesetzt, aber manchmal gibt es eine explizite Festschreibungsanweisung im Text, und so funktioniert mein Rollback natürlich nicht. Diese explizite Festschreibung stammt höchstwahrscheinlich von einem Benutzer, der versucht, das Schema in SQL Fiddle zu unterbrechen, sodass andere Personen, die daran arbeiten, Fehler sehen.
Gewünschtes Hauptergebnis : Ich möchte explizite Festschreibungen auf JDBC-Ebene deaktivieren, sofern dies möglich ist. Das liegt daran, dass ich mehrere Datenbank-Backend-Anbieter unterstützen muss, und natürlich hat jeder seine Macken auf der niedrigen Ebene.
Fallback-Option : Wenn es nicht möglich ist, JDBC so zu konfigurieren, dass explizite Commits deaktiviert werden, sind Lösungen zum Erkennen expliziter Commits während der Stapelverarbeitung für jedes der folgenden Backends verfügbar: SQL Server, Oracle, MySQL und PostgreSQL.
Bei SQL Server dachte ich an diese Lösung: Analysieren Sie den XML-Abfrageplan für die Anweisung, bevor Sie sie ausführen, und überprüfen Sie, ob ein Eintrag vorhanden ist, der diesem XPath entspricht:
//*[@StatementType="COMMIT TRANSACTION"]
Ich denke, das würde für SQL Server ziemlich gut funktionieren. Dieser Ansatz funktioniert jedoch nicht für die anderen DB-Typen. Die XML-Ausführungsplanausgabe von Oracle für explizite Festschreibungen enthält keinen Hinweis darauf, dass Sie eine Festschreibungsanweisung ausführen (sondern wiederholt einfach die Ausführungsplanausgabe der festgeschriebenen Abfragen). PostgreSQL und MySQL bieten überhaupt keine Ausgabe von Ausführungsplänen (XML oder anderweitig) für explizite Commits.
Das lässt mich die eigentliche Anweisung auf das Wort "commit" überprüfen. Dies würde funktionieren, es sei denn, es sind alle Arten von Variationen möglich:
declare @sql varchar(50)
set @sql = 'com' + 'mit'
exec(@sql);
Das Obige ist ein Beispiel für SQL Server (den ich umgehen könnte), aber ich würde annehmen, dass ähnliche Dinge für Oracle, MySQL und PostgreSQL möglich wären. Liege ich mit dieser Annahme falsch? Vielleicht würden sie keine "dynamischen" Festschreibungsanweisungen zulassen? Sie können auch SQL Fiddle verwenden (vorzugsweise nicht das Beispielschema oder eines, an dem wahrscheinlich jemand anderes arbeitet), um zu prüfen, ob in Oracle, MySQL und PostgreSQL etwas Ähnliches möglich ist. Andernfalls funktioniert möglicherweise die einfache Erkennung von Zeichenfolgen.
Noch eine andere Möglichkeit
Eine andere Option ist mir eingefallen - wenn Sie wissen, wie Sie eine dieser Datenbanken in einen schreibgeschützten Modus versetzen können, kann dies auch funktionieren, wenn Sie sich in diesem Modus befinden. Ich müsste weiterhin zulassen, dass Transaktionen gestartet und Code in ihnen ausgeführt werden, nur solange in diesem Modus nichts festgeschrieben werden kann. Ist das möglich?
Aktualisieren
Was ich kürzlich gelernt habe - das ist eigentlich kein Problem mit PostgreSQL. Offensichtlich werden innerhalb eines Transaktionsblocks ausgegebene Commits nicht angewendet, wenn derselbe Block schließlich zurückgesetzt wird (in Postgres). Also Hurra für Postgres!
Dank Phils Link zum SO-Post kann ich den DEFERRABLE INITIALLY DEFERRED-Hack für Oracle verwenden, um das zu erreichen, wonach ich gesucht habe (ein Fehler wird ausgegeben, wenn ein Commit ausgegeben wird, aber ich kann das umgehen). Dies sollte sich an Oracle richten. (Ich dachte für einen Moment, dass verschachtelte Transaktionen hier funktionieren könnten, aber es sieht nicht so aus, als würde Oracle verschachtelte Transaktionen unterstützen? Trotzdem konnte ich nichts finden, was auf diese Weise funktionierte.)
Ich habe noch keine Lösung für MySQL. Versucht mit verschachtelten Transaktionen, aber das scheint nicht zu funktionieren. Ich denke ernsthaft über drastischere Ansätze für MySQL nach, z. B. entweder nichts anderes als SELECTs auf der rechten Seite zuzulassen oder die Datenbank nach jeder Abfrage zu löschen / neu zu erstellen. Weder klingt aber gut.
Auflösung
Daher habe ich jetzt die beschriebenen Lösungen für SQL Server und Oracle implementiert, und wie ich bereits erwähnt habe, ist dies für PostgreSQL eigentlich kein Problem. Für MySQL habe ich den etwas unglücklichen Schritt unternommen, den Abfrageeditor nur auf ausgewählte Anweisungen zu beschränken. DDL und DML für MySQL müssen einfach im Schemabereich (auf der linken Seite) eingegeben werden. Ich hoffe, dass dies nicht zu viele alte Probleme auflöst, aber ich denke, es ist einfach das, was getan werden muss, um die Datenkonsistenz sicherzustellen. Vielen Dank!
quelle
Antworten:
Für Oracle scheint dies eine gute versteckte Methode zu sein, um COMMITs abzufangen:
/programming//a/6463800/790702
Was er nicht erwähnt, ist, dass Sie in der Lage sein sollten, die Einschränkungsverletzung auch in Ihrem Code zu erfassen, um das Auftreten der zweiten Situation zu stoppen.
quelle