Ключевое слово synchronized
- это разные чтения и записи различных потоков, объектов и ресурсов. Это не тривиальная тема в Java, но вот цитата из методов Sun:
blockquote>
synchronized
позволяет простую стратегию предотвращения помех потоков и ошибок согласованности памяти: если объект видим более одного потока, все чтения или записи в переменные этого объекта выполняются с помощью синхронизированных методов.В очень, очень малой части: Когда у вас есть два потока которые читают и записывают один и тот же «ресурс», скажем, переменную с именем
foo
, вам необходимо обеспечить, чтобы эти потоки обращались к переменной по-атомному. Без ключевого словаsynchronized
ваш поток 1 может не увидеть поток изменений 2, сделанный вfoo
, или, что еще хуже, его можно изменить только наполовину. Это не то, что вы логически ожидаете.Опять же, это нетривиальная тема в Java. Чтобы узнать больше, изучите здесь темы SO и Interwebs о:
Продолжайте исследовать эти темы, пока имя «Брайан Гетц» не будет постоянно связано с термином «параллелизм» в вашем мозгу.
Необходимо принять последовательный подход. Знайте, что откат транзакции в рамках хранимой процедуры будет откатывать любую вложенную область транзакций, включая любой внешний объем.
я советовал бы Вам сохранять свои транзакции вне процедур. Тем путем Вы сохраняете полный контроль.
В хранимой процедуре самое соответствующее местоположение, по-моему.
Одно из фундаментальных правил хорошего дизайна транзакции состоит в том, чтобы сохранить жизнь транзакции максимально короткой и таким образом, фиксация должна сразу произойти после того, как логика формирования транзакций была завершена. Управление транзакцией за пределами хранимой процедуры приведет к ненужному расширению жизни транзакции.
необходимо также полагать, что определение транзакции в рамках процедуры также предоставит больше ясности коду. Иначе, если другой кодер должен изменить данную хранимую процедуру, они должны были бы полагаться на то, что вызывающая сторона действительно обертывает процедуру в транзакцию. Включая транзакцию в рамках процедуры явно определяет Вашу обработку транзакции.
Так же, как к вашему сведению, Oracle не делает поддерживаемых вложенных транзакций, и если Вы начнете транзакцию на внешнем уровне и затем назовете ряд хранимых процедур, кто-либо сохраненный-proc, который выходит, то фиксация будет фиксировать всю транзакцию до сих пор, не только транзакцию, которую она спровоцировала. Поэтому необходимо управлять транзакцией вне сохраненного-proc, когда вызов с языков как C#
Просто думал, что Вам могло бы быть интересно для сравнения.
Снаружи, или по крайней мере, во внешнем слое Вашей базы данных API.
, Если Вы фиксируете в каждой хранимой процедуре, тогда Вы могли бы также иметь включенную автоматическую фиксацию, отобразить следующие хранимые процедуры
create_user_with_email_address
calls -> create_user
calls -> create_email_address
, если Вы фиксируете в любом, какой create_user/create_email_address тогда create_user_with_email_address больше не может быть транзакционным, если create_email_address перестал работать, create_user уже фиксировался, и Вы повредили данные.
Помещенный транзакция как высоко по мере необходимости для хранения всего в нем.
Это зависит от бизнес-логики, если SP является атомарным, это должно реализовать свою собственную транзакцию. Если Вы не делаете этого, Вы рискуете ошибочным кодом в будущем не создание переносящейся транзакции. таким образом в ответе на Ваш вопрос я думаю, что транзакция должна войти в SP.
, Конечно, нет ничего для остановки Вас делающий обоих, атомарный SPS реализуют их собственные транзакции, и за пределами того объема могут уже существовать другие более широкие транзакции.
В целом при создании использования транзакций в SPS можно уже быть в области транзакций, необходимо кодировать для этого экземпляра при выполнении Фиксации/Отката.
Мы делаем следующее в Sproc, потому что, если мы просто откатываем его, пачкает количество транзакции во внешнем SProcs, который может генерировать предупреждение назад приложению - и если он не ожидает / обработка, он может вызвать ошибку приложения.
Однако этот метод только откатывает "локальную" транзакцию, таким образом, внешние "вызывающие стороны" должны интерпретировать Возвращаемое значение соответственно; альтернативно используйте RAISERROR или подобный.
BEGIN TRANSACTION MySprocName_01
SAVE TRANSACTION MySprocName_02
...
IF @ErrorFlag = 0
BEGIN
COMMIT TRANSACTION MySprocName_01
END
ELSE
BEGIN
ROLLBACK TRANSACTION MySprocName_02
COMMIT TRANSACTION MySprocName_01
END