I'm working on a web service that will need to handle many concurrent requests. While executing a long-running process that makes use of a transaction, I tested running separate requests against the server. I found that occasionally I would get an sql error claiming that the connection being used to prepare/execute a query was already occupied preparing/executing a query. I turned up the logging to finest and discovered that both requests were using connection 0, which caused the two processes to conflict when the timing was right. I put a break point on the connection object's release function, and found that it was being called in the long-running process when a call to a query's executeMulti function was called. It appears that executeMulti releases the connection when it's done, without regard to whether it's in a transaction or not:
Future<List<Results>> executeMulti(List<List> parameters) {
return _prepare(true)
.then((preparedQuery) {
var c = new Completer<List<Results>>();
_log.fine("Prepared query for multi execution. Number of values: ${parameters.length}");
var resultList = new List<Results>();
executeQuery(int i) {
_log.fine("Executing query, loop $i");
_execute(preparedQuery, parameters[i], retainConnection: true)
.then((Results results) {
_log.fine("Got results, loop $i");
resultList.add(results);
if (i < parameters.length - 1) {
executeQuery(i + 1);
} else {
preparedQuery.cnx.release();
c.complete(resultList);
}
})
.catchError((e) {
_releaseReuseCompleteError(preparedQuery.cnx, c, e);
});
}
executeQuery(0);
return c.future;
});
}
I switched my code to just loop the args over the regular query.execute, and I started seeing the second process use a connection 1 instead of 0, so that took care of it for me. Not a huge deal to work around, but this should probably be addressed.
I'm working on a web service that will need to handle many concurrent requests. While executing a long-running process that makes use of a transaction, I tested running separate requests against the server. I found that occasionally I would get an sql error claiming that the connection being used to prepare/execute a query was already occupied preparing/executing a query. I turned up the logging to finest and discovered that both requests were using connection 0, which caused the two processes to conflict when the timing was right. I put a break point on the connection object's release function, and found that it was being called in the long-running process when a call to a query's executeMulti function was called. It appears that executeMulti releases the connection when it's done, without regard to whether it's in a transaction or not:
I switched my code to just loop the args over the regular query.execute, and I started seeing the second process use a connection 1 instead of 0, so that took care of it for me. Not a huge deal to work around, but this should probably be addressed.