Oracle for update [of column] | [nowait] 详解

1 Overview

  • Alone select 语句is not going to add any locks
  • By for update 语句locking data or row data table

2 Grammar

select * from table_name for update [of column1, columnN][wait n|nowait];

Syntax analysis:

1. 表级锁: 锁住表中所有的记录
	select * from table_name for update; -- 锁住表中所有的记录
	select * from table_name where column_name = 1 for update; -- 锁住表中列名为 1 的记录
	
2. 行级锁: 锁住某列的记录(单表时,加不加效果一样。多表时,锁定 of column 列对应的表)
	select * from table_name for update of column1;

3. wait n | nowait
	(1) wait 5: 当锁冲突时,等待 5s 后报错(资源正忙...(2) nowait: 当锁冲突时,立即报错(资源正忙...

3 Examples

3.1 for update of column

Overall conclusion:

Number of connected tables Explanation
Single table for update 和 for update of it's the same
Multi-table Lock only of columnthe corresponding table (same table to lock a column)

other:

  • Without the where condition, the entire table is locked
  • Added where condition is a row-level lock

Single table: there is no difference between for update and for update of column

Conclusion: All dml statements in session 2 must wait for session 1 commit or rollback

Please note:
1.scott.emp and scott.dept are built-in Oracle tables,
2.scott.emp used for testing is a data table, and scott.dept is a type table (foreign key)

Scenario 1: for update
session 1:

SELECT * FROM scott.dept t WHERE t.deptno = 10 FOR UPDATE;

session 2:

UPDATE scott.dept t SET t.loc = 'test_lock' WHERE t.deptno = 10;

场景2:for update of column
session 1:

SELECT * FROM scott.dept t WHERE t.deptno = 10 FOR UPDATE OF t.loc, t.dname; -- 仅多了 OF t.loc, t.dname

session 2:

UPDATE scott.dept t SET t.loc = 'test_lock' WHERE t.deptno = 10;

Insert picture description here


When multiple tables: lock only the table corresponding to of column (the same table can lock one column)

Conclusion: The table corresponding to the non-of column column in the dml statements in session 2 and 3 does not need to wait for session 1 commit or rollback

Scenario 1: for update
session 1:

SELECT e.empno, e.ename, d.deptno, d.dname
  FROM scott.emp e, scott.dept d
 WHERE d.deptno = e.deptno
   AND d.deptno = 10
   FOR UPDATE;

session 2:

UPDATE scott.emp e SET t.ename = 'test_ename' WHERE e.deptno = 10;

session 3:

UPDATE scott.dept d SET t.dname = 'test_dname' WHERE d.deptno = 10;

Insert picture description here

场景2:for update of column
session 1:

SELECT e.empno, e.ename, d.deptno, d.dname
  FROM scott.emp e, scott.dept d
 WHERE d.deptno = e.deptno
   AND d.deptno = 10
   FOR UPDATE OF d.dname; -- 仅多了 OF d.dname

session 2:

UPDATE scott.emp e SET t.ename = 'test_ename' WHERE e.deptno = 10;

session 3:

UPDATE scott.dept d SET t.dname = 'test_dname' WHERE d.deptno = 10;

Insert picture description here

3.2 wait n | nowait

in conclusion:

  • wait 5: When the lock conflicts, an error will be reported after waiting 5s (resources are busy...)
  • nowait: When the lock conflicts, an error is reported immediately (resources are busy...)

session 1:

SELECT * FROM scott.dept t WHERE t.deptno = 10 FOR UPDATE;

session 2:

SELECT * FROM scott.dept t WHERE t.deptno = 10 FOR UPDATE NOWAIT;

Insert picture description here

4 Extension: rowid

1. 通过 for update 的方式修改表记录会产生 锁
	SELECT * FROM scott.dept t WHERE t.deptno = 10 FOR UPDATE;
	
2. 通过 rowid 的方式修改表记录是不会产生 锁 的
	SELECT t.*, ROWID FROM scott.dept t WHERE t.deptno = 10;

Guess you like

Origin blog.csdn.net/qq_34745941/article/details/106903759