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

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


person nvunguyen    schedule 11.12.2008    source источник


Ответы (5)


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

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

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

person jmucchiello    schedule 11.12.2008

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

person ninesided    schedule 11.12.2008

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

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

person Loki    schedule 11.12.2008

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

person Loki    schedule 11.12.2008

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

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

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

person too much php    schedule 11.12.2008