Помогите с Java потоками или исполнителями: выполнение нескольких выборов MySQL, вкладывает и обновляется однократно

StackOverflow https://stackoverflow.com/questions/2953955

Вопрос

Я пишу приложение для анализа базы данных MySQL, и мне нужно выполнить несколько DMLS с однократным образом; Например:

// In ResultSet rsA: Select * from A;
rsA.beforeFirst();
while (rsA.next()) {
   id = rsA.getInt("id");
   // Retrieve data from table B: Select * from B where B.Id=" + id;
   // Crunch some numbers using the data from B
   // Close resultset B
}

Я объявляю множество объектов данных, каждый со своим собственным соединением с базой данных, которая, в свою очередь, вызывает несколько методов для анализа данных. Проблема состоит в том, что все потоки используют одно и то же соединение, поэтому все задачи бросают, кроме: «Заблокировать тайм -аут ожидания превышен; попробуйте перезапустить транзакцию»

Я полагаю, что есть способ написать код таким образом, чтобы любой заданный объект имел свое собственное соединение и выполняет необходимые задачи, независимые от любого другого объекта. Например:

DataObject dataObject[0] = new DataObject(id[0]);
DataObject dataObject[1] = new DataObject(id[1]);
DataObject dataObject[2] = new DataObject(id[2]);
...
DataObject dataObject[N] = new DataObject(id[N]);
// The 'DataObject' class has its own connection to the database, 
// so each instance of the object should use its own connection. 
// It also has a "run" method, which contains all the tasks required.
Executor ex = Executors.newFixedThreadPool(10);

for(i=0;i<=N;i++) {
   ex.execute(dataObject[i]);
}
// Here where the problem is: Each instance creates a new connection,
// but every DML from any of the objects is cluttered in just one connection
// (in MySQL command line, "SHOW PROCESSLIST;" throws every connection, and all but
// one are idle).

Можете ли вы указать мне правильное направление?

Спасибо

Это было полезно?

Решение 2

После некоторого времени разрыва мозга я понял свои собственные ошибки ... Я хочу поставить эти новые знания, так что ... вот я иду

Я сделал очень большая ошибка Объявив подключение objet как статический объект в моем коде ... так что, очевидно, несмотря на то, что я создал новое соединение для каждого нового объекта данных, который я создал, каждая транзакция прошла через одно статическое соединение.

С этой первой проблемой исправлена, я вернулся к дизайнерскому столу и понял, что мой процесс был:

  1. Прочитайте идентификатор из таблицы ввода
  2. Возьмите блок данных, связанных с идентификатором, прочитанным на шаге 1, хранятся в других входных таблицах
  3. Числа хруста: прочитайте связанные входные таблицы и обрабатывайте данные, хранящиеся в них
  4. Сохранить результаты в одной или нескольких выходных таблицах
  5. Повторите процесс, пока у меня есть идентификаторы в таблице ввода

Просто используя выделенное соединение для чтения ввода и выделенное соединение для написания вывода, производительность моей программы увеличилась ... но мне нужно было намного больше!

Мой первоначальный подход к шагам 3 и 4 заключался в том, чтобы сохранить в выводе каждый из результатов, как только они у меня были ... но я нашел лучший подход:

  • Прочитайте входные данные
  • Хрустят числа и поместите результаты в кучу очередей (по одному для каждой выводной таблицы)
  • Отдельный поток проверяется каждую секунду, если есть данные в любой из очередей. Если в очереди есть данные, напишите их в таблицы.

Таким образом, разделив входные и выходные задачи, используя различные соединения, и перенаправляя выходной вывод процесса на очередь, и, используя выделенный поток для задач вывода хранилища, я наконец достиг того, что хотел: многопоточное выполнение DML!


Я знаю, что есть лучшие подходы к этой конкретной проблеме, но эта работает довольно хорошо.

Так что ... если кто -то застрял с такой проблемой ... Я надеюсь, что это поможет.

Другие советы

Я думаю, что проблема в том, что вы смешали много среднего уровня, транзакции и постоянной логики в одном классе.

Если вы имеете дело напрямую с результатами, вы не думаете о вещах очень ориентированным на объект.

Вы умны, если вы можете выяснить, как заставить базу данных сделать некоторые из ваших вычислений.

Если нет, я бы порекомендовал поддерживать открытые соединения в течение минимального времени. Откройте соединение, получите результаты, сочините его в объект или структуру данных, закройте результаты и соединение в локальном объеме и верните сопоставленную структуру объекта/данных для обработки.

Вы сохраняете настойчивость и логику обработки отдельно. Вы спасаете себя большим горем, сохраняя недолгие связи.

Если хранимое решение для процедуры медленное, оно может быть связано с плохой индексацией. Другое решение будет работать одинаково плохо, если не хуже. Попробуйте запустить план объяснения и посмотрите, используют ли какие -либо из ваших запросов сканирование таблицы. Если да, у вас есть несколько индексов, которые нужно добавить. Это также может быть связано с большими откатами в журналах, если ваши транзакции будут продолжительными. Есть многое, что вы могли бы и должны сделать, чтобы убедиться, что вы сделали все возможное с решением, которое у вас есть перед переключением. Вы можете пойти на большие усилия и при этом не учитывать основную причину.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top