a person updates a row and forgets the commit. later the update-service always wants to update this row and the service hangs, until the commit will be made or the session will be closed
В идеале читатели не блокируют писателей, а писатели не блокируют читателей.
Что вы описываете не a DEADLOCK сценарий. Когда сеанс выполняет обновление, он получает эксклюзивную блокировку на уровне строк и другую сессию, пытающуюся обновить эти строки, нужно дождаться, когда блокировка будет выпущена COMMIT/ROLLBACK.
Тупик случается, когда две или более сеансов ждут друг друга для блокировки.
Or can i configure the oracle server to send an error code after a defined time, if the lock on a row does not finish?
Для проверки блокировки сеанса и ждать класса, вы можете запросить V $ SESSION вид:
select sid,
status,
program,
sql_id,
state,
wait_class,
blocking_session_status,
event
from v$session;
Когда дело доходит до тупиков, Oracle обнаруживает тупиковый автоматически, бросает ORA -00060: обнаружен тупик, ожидающий ресурса, и откатывает одну из транзакций, вовлеченных в тупик, которые Oracle решил в качестве жертвы. Предыдущие успешные транзакции не откатываются. Даже после ошибки тупика, если вы совершили фиксацию, будет выполнена предыдущая успешная транзакция. В это время транзакция другого сеанса также будет успешной, и вы можете выполнить фиксацию. Нет ничего, что вам нужно явно здесь делать. Тупики автоматически очищаются - вам не нужно их очищать.
См аналогичный вопрос, который я ответил здесь https://stackoverflow.com/a/28455397/3989608
Для детальной демонстрации и примеры тупиков см Understanding Oracle Deadlock
Если вы используете FOR UPDATE NOWAIT, то Oracle не позволит вам обновить эти строки и бросить следующее сообщение об ошибке:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
Например,
Сессия 1:
SQL> SELECT empno, deptno
2 FROM emp WHERE
3 deptno = 10
4 FOR UPDATE NOWAIT;
EMPNO DEPTNO
---------- ----------
7782 10
7839 10
7934 10
SQL>
Сессия 2:
SQL> SELECT empno, deptno
2 FROM emp WHERE
3 deptno in (10, 20)
4 FOR UPDATE NOWAIT;
FROM emp WHERE
*
ERROR at line 2:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
Переход на шаг дальше, если вы хотите избежать обновления строки, которые уже заблокированы, вы можете использовать ДЛЯ ОБНОВЛЕНИЯ ПРОПУСКА ЗАБЛОКИРОВАТЬ, чтобы избежать других сеансов для извлечения строк для обновления, которые уже заблокированы.
Например,
Сессия 1:
SQL> SELECT empno, deptno
2 FROM emp WHERE
3 deptno = 10
4 FOR UPDATE NOWAIT;
EMPNO DEPTNO
---------- ----------
7782 10
7839 10
7934 10
SQL>
Сессия 2:
SQL> SELECT empno, deptno
2 FROM emp WHERE
3 deptno in (10, 20)
4 FOR UPDATE NOWAIT;
FROM emp WHERE
*
ERROR at line 2:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
Теперь давайте пропустить строки которые заблокированные сессии 1.
SQL> SELECT empno, deptno
2 FROM emp WHERE
3 deptno IN (10, 20)
4 FOR UPDATE SKIP LOCKED;
EMPNO DEPTNO
---------- ----------
7369 20
7566 20
7788 20
7876 20
7902 20
SQL>
Так, отдел = 10 были заблокированы сессии 1, а затем отдел = 20 блокированы сессии 2.
Смотрите этот же вопрос о избежать обновления на уже заблокированные строки Oracle deadlock keeps repeating on the same record
Вы описываете блокировку, а не тупик. Первое незафиксированное обновление блокирует второе, потому что строка заблокирована. –
Читатели не блокируют писателей, и авторы не блокируют читателей. –
Не только это не тупик, это страшный дизайн, чтобы оставить транзакции открытыми для людей, чтобы «забыть совершить». Если вы не можете исправить это, вы можете использовать предложение SELECT FOR UPDATE WAIT, чтобы выйти рано. – LoztInSpace