Oracle锁1:DML锁
时间:2022-03-14 04:45
DML锁,也叫做数据锁(data lock),用于保证在多用户操作数据时数据的完整。DML锁防止相互冲突的DML和DDL操作同时发生。
DML锁有行锁(Row Locks,TX)和表锁(Table Locks,TM),不同的DML操作会自动请求对应的锁。
行锁(Row Locks,TX)
行锁也叫TX锁,用于锁表的一行数据。当一个事务对一行数据做INSERT、UPDATE、DELETE、MERGE或SELECT ... FOR UPDATE操作时,数据将为行添加行锁,直到事务执行了commit或roll back操作后,行锁才释放。行锁防止两个事务修改同一行数据,当一个事务修改一行数据时,数据库总是为修改的行加一个排它锁以至于其它事务无法修改该行,只有当事务执行了commit或者roll back操作后,数据库才会释放对应的锁。行锁是小粒度的锁,为应用提供了最大限度的并行修改数据的能力。
当一个事务获取了一个行锁,那么这个事务也需要获取这行数据所在表的表锁,表锁阻止有冲突的DDL操作,即数据库会自动的为更新的行添加一个排它锁,并为行所在的表添加一个子排它锁。
行锁和并发
下面通过一个例子来理解行锁和并发的关系。首先创建下面的表格,并初始化数据:
create table employees(employee_id number(10),salary number(10)); insert into employees(employee_id,salary) values(100,512); insert into employees(employee_id,salary) values(101,600); ......步骤一:三个Session同时查询ID为100和101的雇员,查询结果一致
Session 1: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 600 Session 2: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 600 Session 3: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 600步骤二:Session 1执行更新操作,更新id为100的雇员,在这个更新中,写者将请求一个行锁,阻止其它写者更新这行数据,如果其它写者更新该行数据将被阻塞,直到Session 1提交或者回滚数据
Session 1: update employees set salary = 612 where employee_id = 100步骤三:再次执行步骤一的操作
Session 1: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 612 101 600 Session 2: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 600 Session 3: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 600Session 1的结果是它更新后的数据,而其他两个session任然是旧数据。
步骤四:Session 2更新101雇员的薪水,并且不提交数据,这样Session 2获取了对雇员101的行锁
UPDATE hr.employees SET salary = salary + 100 WHERE employee_id = 101;步骤五:再次执行步骤1的查询
Session 1: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 612 101 600 Session 2: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 700 Session 3: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 600
行锁的存储
Oracle将锁信息存储在data block中。数据库用一个队列机制处理行锁请求,如果一个事务请求一个未锁定的行,那么事务将放一个锁到data block,被事务修改的每一行都指向存储在block header中的事务ID的一个拷贝。当一个事务结束时,事务ID保留在block header中,如果另一个事务想修改一行数据,那么它用这个事务ID判定这个锁是否是激活的。如果锁是激活的,那么当锁被释放时,该事务的session将被通知,否则,事务获取这个锁。
表锁(Table Locks,TM)
表锁,也叫TM锁,当对表执行以下操作时将被请求:INSERT、UPDATE、DELETE、MERGE、SELECT ... FOR UPDATE和LOCK TABLE。请求表锁的DML操作将阻止其它冲突的DDL操作。表锁有以下的模式: