dart-drivers / mysql

MySQL Connector for Dart
Other
99 stars 38 forks source link

query.executeMulti closes transaction connection #45

Open sanmadjack opened 10 years ago

sanmadjack commented 10 years ago

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.