Несколько транзакций базы данных на одном соединении

У меня многопоточная программа, тогда как каждый поток в начале выполнения получает одно соединение из класса пула соединений MySql. Затем поток использует ряд классов-оболочек таблиц базы данных для выполнения своей бизнес-логики, передавая соединение с базой данных классам-оболочкам. Операции над этими классами-обертками не обязательно являются последовательными, и я хочу, чтобы эти классы-обертки могли фиксировать или откатывать изменения в своей таблице базы данных независимо друг от друга, используя одно соединение с базой данных. Я знаю, что MySql не разрешает вложенные транзакции и не нашел способ сделать это. Любая помощь очень ценится. Спасибо!

11.12.2008 03:49:21
5 ОТВЕТОВ

Если я правильно понимаю проблему, я полагаю, что единственным вариантом является создание какой-либо очереди транзакций, которая позволяет нескольким потокам совместно использовать одно соединение. Каждый из ваших потоков может затем добавить «задачи» в очередь, которые требуют выполнения внутри транзакции. Затем у вас есть процесс, который выбирает эти задачи из очереди (вы могли бы даже реализовать какой-то приоритет здесь) и отправляет их в базу данных, прежде чем возвращать результаты в поток, который инициировал запрос. Вызывающие потоки будут блокироваться до тех пор, пока не получат свои результаты, что не идеально, но если вам действительно нужно иметь несколько потоков и несколько транзакций, я не вижу другого способа сделать это, не имея нескольких соединений.

1
11.12.2008 04:04:31

Ну, это классический пример использования одного ресурса несколькими потоками.

Решение заключается в использовании мьютексов в операциях соединения mysql.

1
11.12.2008 04:25:10

Похоже, вы должны связывать транзакции с обертками таблиц лучше, чем просто по потокам. IOW, вам нужно создать класс транзакции. Класс транзакции получает / освобождает соединения из / в пул соединений, когда транзакция открывается и закрывается.

Затем транзакция станет фабрикой для ваших оберток. Любая оболочка таблицы, созданная транзакцией, находится внутри транзакции, поскольку она не имеет доступа ни к какому соединению, кроме той, к которой относится транзакция.

Раздражающей частью этого является предотвращение доступа всех объектов к мертвым объектам. Некоторая форма SmartPtr потребуется для обработки того, что происходит, когда транзакция фиксируется, но что-то пытается снова использовать оболочку таблицы.

2
11.12.2008 04:26:17

Есть пул соединений, почему бы вам не приобрести больше соединений? И, возможно, использовать семафоры, чтобы ограничить количество одновременных подключений. Иначе, вам нужно заблокировать одно соединение или использовать клиентские транзакции (используйте каркас, это не просто, и вам все равно нужно заблокировать соединение, если оно есть, но время ожидания будет очень маленьким по сравнению с отсутствием транзакций на вашей стороне кода).

1
11.12.2008 04:45:50

Самое простое решение - просто создать новое соединение для каждого потока - так обычно это делается с Apache / PHP.

Если у вас гораздо меньше операций записи, чем операций чтения (для записи требуется только 1 из 10 потоков), вы можете использовать одно глобальное соединение для SELECT и создать новое соединение для каждого потока, который необходимо обновить.

После этого у вас может быть пул до 10 потоков, используемых для записи (так что вы можете иметь до 10 одновременных транзакций). В конце дня, если вы хотите параллелизма, вам нужно несколько соединений.

1
11.12.2008 04:55:23