2015-12-16 4 views
1

У меня есть общий вопрос о том, как Slick/база данных управляет асинхронными операциями. Когда я составляю запрос, или действие, скажемБезопасность потока в Slick

(for { 
    users <- UserDAO.findUsersAction(usersInput.map(_.email)) 
    addToInventoriesResult <- insertOrUpdate(inventoryInput, user) 
    deleteInventoryToUsersResult <- inventoresToUsers.filter(_.inventoryUuid === inventoryInput.uuid).delete if addToInventoriesResult == 1 
    addToInventoryToUsersResult <- inventoresToUsers ++= users.map(u => DBInventoryToUser(inventoryInput.uuid, u.uuid)) if addToInventoriesResult == 1 
} yield(addToInventoriesResult)).transactionally 

Есть ли вероятность того, что другой пользователь может, например, удалить пользователей сразу после первого действия UserDAO.findUsersAction(usersInput.map(_.email)) выполняется, но перед остальными, так что вставка будет fail (из-за ошибки внешнего ключа)? Или сценарий, который может привести к потерянному обновлению, например: транзакция A считывает данные, затем транзакция B обновляет эти данные, а затем транзакция A обновляет данные на основе того, что она читала, она не увидит обновление B, чтобы перезаписать его.

Я думаю, что это, вероятно, зависит от реализации базы данных или, возможно, от JDBC, поскольку это отправляется в базу данных как блок SQL, но, возможно, Slick играет роль в этом. Я использую MySQL.

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

ответ

1

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

Были разговоры о внедрении неблокирующих драйверов для Oracle и SQL Server (под платной подпиской на регистрацию), но это не происходит в ближайшее время AFAICT. Есть couple of projects, которые предоставляют неблокирующие драйверы для Postegres и MySQL, но YMMV, еще рано.

С этой целью, когда вы звоните transactionally Слик принимает партию запросов для выполнения и обертывает их в блок try-catch с флагом autocommit базового соединения, установленным в false. После успешного выполнения запросов транзакция выполняется, установив для autocommit значение по умолчанию true. В случае, если выбрано исключение, вызывается метод rollback соединения. Просто стандартный JDBC-сессионный шаблон, который Slick удобно абстрагирует.

Что касается вашего сценария пользователя, который удаляет среднюю транзакцию и правильно ее обрабатывает, это задание базовой базы данных/драйвера.

+0

* поток будет потреблен и заблокирован * это означает, что все еще могут быть n потоков, обращающихся к базе данных одновременно (где max n, вероятно, мой размер пула потоков)? Я беспокоюсь только о переписывании обновлений, которые, я думаю, не могут быть решены только с помощью транзакций. Если транзакция A считывает некоторые данные, тогда транзакция B обновляет эти данные, тогда транзакция A выполняет обновление на основе того, что она прочитала, но не увидит обновление B, чтобы перезаписать его. Может ли это случиться? Если да, то как это относится к Slick? – Ixx

+0

Слайк поддерживает собственный собственный пул потоков (поверх пула по умолчанию, HikariCP), который, например, «DBIO» зависит от выполнения операций потоковой передачи/пакетной обработки. Сам Слик не препятствует возникновению сценария transactionA/transactionB, поскольку они (предположительно) являются отдельными не вложенными транзакциями. Пока базовая база данных является потокобезопасной, она должна иметь возможность правильно управлять сценарием transactionA/transactionB (т. Е. Сбой transactionB) – virtualeyes

+0

Знаете ли вы, что MySQL является потокобезопасным? Я читал, что для этого иногда требуется блокировка таблицы, поэтому не уверен в этом. Если это не безопасно для потоков, я правильно понимаю, что я ничего не могу сделать со стороны Slick? Спасибо за всю информацию до сих пор. – Ixx

Смежные вопросы