У меня есть вопрос, касающийся транзакций базы данных, когда я не уверен, правильно ли я понимаю.Я хочу реализовать логин пользователя в Java-приложении.Поскольку в одной и той же базе данных может быть несколько серверов, и каждый пользователь может войти в систему только на одном из этих серверов, база данных должна сохранять флаг, если пользователь уже вошел в систему.
Итак, предположим следующую структуру таблицы:
ID | User | PWD | Server
, где Server
- это ссылка на сервер, на котором пользователь вошел в систему, или NULL
, если он не вошел в систему.
Когда пользователь входит в систему,Я должен сначала проверить, является ли значение сервера NULL, и если нет, установить его в соответствующее ссылочное значение.Но что происходит, когда между этими двумя утверждениями пользователь входит в систему на другом сервере?Может ли такое состояние быть обнаружено транзакциями?например (псевдо)
conn.setAutoCommit(false);
ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM users WHERE user = 'usr' AND password = 'pwd'");
if (rs.next()) {
rs.getInt("Server");
if (rs.wasNull()) {
// Not logged in
conn.createStatement().execute("UPDATE users SET server = 123 WHERE user = 'usr' AND password = 'pwd'");
conn.commit();
}
} else {
// Usr/Pwd wrong
}
conn.rollback();
Что произойдет, если пользователь войдет в систему между операторами выбора и обновления на другом сервере?происходит ли сбой фиксации, поскольку таблица была изменена кем-то другим во время транзакции, или она все же выполняется?
Должен ли я лучше использовать подход, подобный
UPDATE users SET server = 123 WHERE user = 'usr' AND pwd = 'pwd' AND server IS NULL
, и проверить, были ли 0 строкзатронуты?Если это так, я должен проверить, существует ли пользователь в запросе.
Проблемы с Simmilar возникают при регистрации нового пользователя с помощью INSERT.Должен ли я использовать транзакционный подход или объявить пользовательский столбец как UNIQUE и перехватить исключения SQL?