Есть мегапроблема. Не уверен, что она вообще решаема, но всё же =)
Есть таблица, например
A | B
-------
1 | 4
1 | 2
Есть несколько потоков. Все они одинаковые.
1-й поток в Hibernate выполнил блокирующий select 1-й записи по условию where a=1.(maxResult(1),LockMode.UPGRADE)
Можно ли сделать так, чтобы второй поток не ждал 1-ю строку а искал дальше по a=1.
То есть, если привести на оракловом sql аналог (или посмотреть output хибернейта), то будет что-то вроде
1-й поток: select * from tab where a=1 and rownum<2 for update
2-й поток на тот же запрос должен не висеть и ждать и не падать, а искать следующую свободную запись.
То есть пролетать мимо блокировки вообще.
Или это только программно делается через LockMode.UPGRADE_NOWAIT и отлов эксепшнов? И не долго ли по времени будет получение ошибки из базы, кидание эксепшна по этому поводу итд?
Здравствуйте, and_hom, Вы писали:
_>То есть, если привести на оракловом sql аналог (или посмотреть output хибернейта), то будет что-то вроде _>1-й поток: select * from tab where a=1 and rownum<2 for update _>2-й поток на тот же запрос должен не висеть и ждать и не падать, а искать следующую свободную запись. _>То есть пролетать мимо блокировки вообще. _>Или это только программно делается через LockMode.UPGRADE_NOWAIT и отлов эксепшнов? И не долго ли по времени будет получение ошибки из базы, кидание эксепшна по этому поводу итд? _>Спасибо!
Хибернейт может использовать только средства целевой базы для подобных вещей. Попробуй использовать "... for update nowait" в нативном запросе к ораклу, с хибернейтом не пробовал, но в PRO*C "форапдейт ноу вейт" работает.
D>Хибернейт может использовать только средства целевой базы для подобных вещей. Попробуй использовать "... for update nowait" в нативном запросе к ораклу, с хибернейтом не пробовал, но в PRO*C "форапдейт ноу вейт" работает.
Хибернейт прекрасно умеет nowait на Oracle, MS SQL, на других не пробовал (query.setLockMode(...))
Но nowait — это значит "кидать эксепшн сразу же, если наткнулись на строчку, не удовлетворяющую условию". Тогда придётся тащить список id-шников и в цикле по ним
Что касается баз, то MS SQL, кажется, умеет. В оракле, говорят, надо костыли приделывать для этого.
Re[3]: Hibernate + пропуск залоченных строк
От:
Аноним
Дата:
26.01.08 11:41
Оценка:
_>Что касается баз, то MS SQL, кажется, умеет. В оракле, говорят, надо костыли приделывать для этого.
в точности наоборот
Здравствуйте, Аноним, Вы писали:
_>>Что касается баз, то MS SQL, кажется, умеет. В оракле, говорят, надо костыли приделывать для этого. А>в точности наоборот
Здравствуйте, and_hom, Вы писали:
D>>Хибернейт может использовать только средства целевой базы для подобных вещей. Попробуй использовать "... for update nowait" в нативном запросе к ораклу, с хибернейтом не пробовал, но в PRO*C "форапдейт ноу вейт" работает.
_>Хибернейт прекрасно умеет nowait на Oracle, MS SQL, на других не пробовал (query.setLockMode(...)) _>Но nowait — это значит "кидать эксепшн сразу же, если наткнулись на строчку, не удовлетворяющую условию". Тогда придётся тащить список id-шников и в цикле по ним
nowait означает пропускать строки залоченные другими транзакциями, т.е. если у нас есть 3 строки две из которых залочены другими транзакциями, то результирующий запрос вернет одну строку, при этом наложив на нее эксклюзивную блокировку на запись (TX). Последующий запрос не вернет ни одной строки, если они все еще залочены транзакциями.
Т.е. оракл никаких исключений не бросает, если они у вас возникают, то скорее всего вследствие не правильного конфигурирования хибернейта, поэтому я и предложил использовать нативный запрос к ораклу, дабы избежать подобных коллизий.
Здравствуйте, deepsky, Вы писали:
D>Здравствуйте, and_hom, Вы писали:
D>>>Хибернейт может использовать только средства целевой базы для подобных вещей. Попробуй использовать "... for update nowait" в нативном запросе к ораклу, с хибернейтом не пробовал, но в PRO*C "форапдейт ноу вейт" работает.
_>>Хибернейт прекрасно умеет nowait на Oracle, MS SQL, на других не пробовал (query.setLockMode(...)) _>>Но nowait — это значит "кидать эксепшн сразу же, если наткнулись на строчку, не удовлетворяющую условию". Тогда придётся тащить список id-шников и в цикле по ним
D>nowait означает пропускать строки залоченные другими транзакциями, т.е. если у нас есть 3 строки две из которых залочены другими транзакциями, то результирующий запрос вернет одну строку, при этом наложив на нее эксклюзивную блокировку на запись (TX). Последующий запрос не вернет ни одной строки, если они все еще залочены транзакциями. D>Т.е. оракл никаких исключений не бросает,
У меня в стектрейсе присутствуют ошибки ORA-xxxxx
D> если они у вас возникают, то скорее всего вследствие не правильного конфигурирования хибернейта, поэтому я и предложил использовать нативный запрос к ораклу, дабы избежать подобных коллизий.
Откройте два окна SQL Plus
set autocommit false
create table A(B integer);
insert into A values(1);
insert into A values(2);
insert into A values(3);
commit;
в 1-м окне
select * from A where B=1 for update
во втором
select * from A for update nowait
Второе окно выкинет оракловую ошибку — специально проверял.
Причём, ту же самую, что и в стектрейсе