Nach all den Big-Data-Beiträgen nun etwas über traditionelles SQL, das mit DB2 9 läuft. Wir hatten eine Web-Anwendung erstellt, die im Grunde eine Ansicht für eine Datenbank war. Die Anwendung zeigte den Inhalt einer Datenbank an, nachdem der Benutzer Suchparameter eingegeben hatte, oder alles, wenn kein Parameter eingegeben wurde. Die Datenbank enthielt ein paar hunderttausend Datensätze. Alles in allem sehr einfach. Die Software funktionierte in unserer Testumgebung einwandfrei. Aber als wir die Software in der Produktion einsetzten, zeigte sie kaum noch Daten an. In den Protokollen fanden wir häufige Sperrfehler wie folgt: 15:23 ERROR (org.hibernate.engine.jdbc.spi.SqlExceptionHelper) - DB2 SQL Error: SQLCODE=-911, SQLSTATE=40001, SQLERRMC=68, DRIVER=4.1 Eine Suche im Internet ergab, was dieser Fehler bedeutete: ein Deadlock oder Timeout ist aufgetreten. Wir wussten, dass auf dieselbe Datenbank auch eine andere Anwendung zugriff, nämlich Activiti, die in BPMN geschriebene Prozesse ausführt. Die Prozesse in der Activiti-Engine fügten nur ein paar Datensätze pro Minute ein, so dass wir nicht davon ausgingen, dass diese Anwendung einen großen Einfluss hatte. Doch wie können ein paar Einfügungen pro Minute einen so großen Einfluss haben? Nach einigen Gesprächen mit einem DBA und eigenen Experimenten fanden wir das Problem heraus, das wir hier beschreiben werden.
Wie gesagt, die andere Anwendung war eine Activiti, die Prozesse ausführte (um genau zu sein: Prozessdefinitionen in BPMN). Bei mehreren Prozessschritten wurde Java-Code durch den| Zeit | Prozess a(ctiviti) | Prozess c(onsole) | |
|---|---|---|---|
| 1 | INSERT etwas INTO mytable | Prozess a ist einsatzbereit | |
| 2 | SELECT * FROM mytable | Prozess c muss auf Prozess a warten | |
| 3 | INSERT etwas INTO myothertable | Prozess c muss noch warten | |
| 4 | Übertragen | Prozess a überträgt, schließlich kann Prozess c fortfahren | |
| 5 | übertragen | Prozess c ist nun auch beendet |
EntityManagerFactoryImpl entityManagerFactory = (EntityManagerFactoryImpl) Persistence.
createEntityManagerFactory(properties.getProperty("meinEinheitsname");
sessionFactory = entityManagerFactory.getSessionFactory();
Session session = sessionFactory.openSession();
session.getTransaction().begin();
...
session.getTransaction().commit();
session.close();
Hinweis: Wenn Sie Spring-Transaktionen verwenden, übernimmt Spring den obigen Textbaustein für Sie.
Die Sperren wurden nun für eine viel kürzere Zeit gehalten. Nach dieser Änderung verhielt sich unsere Konsole normal.
Das Verhalten des Prozesses, wie oben aufgeführt, war in der Tat von vornherein erwünscht. Nach allen Schreibvorgängen gab es im ursprünglichen Code eine Flush-Anweisung. Bei DB2 würde diese Anweisung tatsächlich dazu führen, dass die Daten auf die Festplatte geschrieben werden, aber die Daten wären erst sichtbar, wenn der Commit durchgeführt wird. Verfasst von
Gerard van de Glind
Unsere Ideen
Weitere Blogs
Contact



