# SQL inserts bringen Router zum Absturz



## m0rf (10. Apr 2010)

Hallo zusammen,

ich habe bisher noch nie mit Datenbanken in Verbindung mit Java gearbeitet, daher fehlen mir hier die Erfahrungswerte und ich bitte um Hilfe.

Ich parse relativ große Files und schreibe diese in die Datenbank, wodurch je nach File ungefähr 15mio INSERTs anfallen. Die INSERTs werden mit prepareStatement "vorbereitet" und dann an die DB geschickt. Das klappt auch alles absolut problemlos, allerdings zerlegt es dabei kurioserweise regelmäßig meinen Router (Speedport W721V).

Da ich bei der Telekom relativ wenig Hoffnung darauf habe, eine ordentliche Antwort zu bekommen, frage ich hier: Ist das normal, oder sollte ich das Ding lieber mal reklamieren?

Vielen Dank.


----------



## Jay_030 (10. Apr 2010)

Also normal ist das sicherlich nicht. :noe:

Die Menge von 15 Mio Insert ist zwar schon eine gewissen Anzahl an Bytes, aber das sind große Downloads auch und ich denke mal, da rebootet dein Router nicht spontan, oder?

Wie ist denn dein Code? Was ich mir vorstellen könnte, ist, dass du für jedes Insert immer ne neue Connection aufbaust, was dann durchaus zu Überlastungen des Routers führen kann.

Ermöglicht dir das Web-Interface des Routers die aktuell aufgebauten Verbindungen zu beobachten in Form eines Counters? Dann einfach mal das Programm laufen lassen und schauen, ob diese signifikant ansteigen.


----------



## m0rf (10. Apr 2010)

Also am Code sollte es eigentlich liegen, ich baue zu Anfang eine Connection auf, die dann für alle INSERTs Verwendung findet.


Hier mal eine vereinfachte Darstellung. Es wird ein Objekt der Klasse erstellt und dann immerwieder addElements() aufgerufen um in die DB zu schreiben.

```
protected DataBaseConnection(String username, String pass, String url,
			String database) throws SQLException, InstantiationException,
			IllegalAccessException, ClassNotFoundException {
		this.username = username;
		this.pass = pass;
		this.url = "jdbc:mysql://" + url + "/";
		this.database = database;
	}

	protected boolean connectMySQL() throws InstantiationException,
			IllegalAccessException, ClassNotFoundException, SQLException {
		Class.forName("com.mysql.jdbc.Driver").newInstance();
		conn = DriverManager.getConnection(this.url + this.database,
				this.username, this.pass);
		isConnected = true;
		return true;
	}

private void addElements(Object arg){
		ArrayList<Item> items = (ArrayList<Item>) arg;
		String st;
		st = //Stringerstellung für das PreparedStatement
		
		
		
		Iterator<Item> listIter = items.iterator();
		try{
		PreparedStatement ps = conn.prepareStatement(st);
		
		
	while (listIter.hasNext()) {
		count=1;
		ps.setString(count++,Long.toString(id++));
		Iterator<String> itemIter = listIter.next().iterator();
		while(itemIter.hasNext()){
			String s = itemIter.next();
			ps.setString(count++, s);
			
		}
		ps.addBatch();
       }
	
	ps.executeBatch();
		}catch(Exception e){System.err.println(e.getMessage());};
	}
```

Leider habe ich bei dem Router keine Möglichkeit irgendwelche Sachen zu beobachten. Die Logfiles zeigen leider nur, ob eine Verbindung ins Internet aufgebaut werden konnte und welche Geräte per WLAN verbunden sind.


----------



## XHelp (10. Apr 2010)

Du könntest während dein Programm läuft mit
"netstat -o 1"
dir die Verbindungen anzeigen lassen.


----------



## m0rf (10. Apr 2010)

Danke für den Tipp. Es wird tatsächlich nur eine Verbindung angezeigt.


----------



## XHelp (10. Apr 2010)

Kann zwar unmittelbar zu deinem Problem nichts sagen. Allerdings hatte ich selber mal einen Fall, dass der Router grundlos rumgesponnen hat. Geholfen hat mir ein Firmware-Update. Du könntest dir deine Firmware ziehen und auf gut Glück probieren.


----------



## m0rf (10. Apr 2010)

Das war das erste was ich gemacht habe, leider hat es auch nicht geholfen. Ich denke ich muss das Ganze dann mal mit einem anderen Router testen.


----------



## Thief (11. Apr 2010)

Ich hab zwar irgendwie Probleme deinen Code (leicht) lesen zu können, aber ich hab gesehen dass du nirgends setAutocommit(false) gesetzt hast. Weiss jetzt nicht ob das unbedingt nötig ist wenn man mit Batch arbeitet, aber zumindest mach ich das immer, und schicke dann manuell ab wenn alles fertig ist.


----------



## m0rf (12. Apr 2010)

Ja, der Code ist wirklich schrecklich, da aus mehreren Klassen zusammenkopiert. Den Tipp mit setAutocommit werde ich mal ausprobieren.

Gibt es eigentlich eine Möglichkeit bei PreparedStatement einzelne Spalten auf NULL zu setzen, sofern keine Parameter über .setXXX(zahl, eintrag) gesetzt werden?

Wenn ich jetzt z.B ein PreparedStatement mit: 


```
String sql = "INSERT INTO foo (id, random, bar, hans) VALUES (?,?,?,?)"
```

habe, und ich den String dann über:


```
PreparedStatement ps = conn.prepareStatement(sql);
```

setze, kann ich die einzelnen Fragezeichen über:


```
ps.setString(1,"boo");
ps.setString(2,"schmuh");
ps.setString(3,"foo");
ps.setString(4,"foobar");
```

setzen und diese dann abschicken.

Wenn ich nun allerdings einen Wert nicht setze, also beispielsweise ps.setString(2,"schmuh"); weglasse, wird verständlicherweise eine Exception geworfen, weil kein Eintrag vorhanden ist.

Gibt es eine komfortable Möglichkeit diese Werte von PreparedStatement automatisch auf NULL setzen zu lassen, oder muss ich das selbst irgendwie implementieren?


----------

