OCA读书笔记(9) - 管理数据同步

时间:2023-03-09 20:51:24
OCA读书笔记(9) - 管理数据同步

9.Managing Data Concurrency

描述锁机制以及oracle如何管理数据一致性
监控和解决锁冲突

管理数据的并发--管理锁
数据的不一致:
脏读
更改丢失
幻影读

脏读:
数据是指事务T2修改某一数据,并将其写回磁盘,事务T1读取同一数据后,T2由于某种原因被撤消,这时T2已修改过的数据恢复原值,T1读到的数据就与数据库中的数据不一致,则T1读到的数据就为"脏"数据,即不正确的数据。

幻影读:事务1按一定条件从数据库中读取某些数据记录后,事务2插入了一些符合事务1检索条件的新记录,当事务1再次按相同条件读取数据时,发现多了一些记录。

阻止多个会话在相同时间对相同数据进行更改。
在最低可能级别自动获取,在行上加锁,不会在块上加锁。Rac分布锁可以锁定数据块。

DML语句
行上加排他锁
表上加行级排他锁(共享锁)
排他锁不兼容,共享锁兼容。
共享锁保护表结构,不能被删除或者增加列。

session 1
conn scott/tiger;
update emp set sal=sal+100 where empno=7788;

session 2
conn scott/tiger;
update emp set sal=sal+100 where empno=7566;
update emp set sal=sal+100 where empno=7788;等到session1 commit后才能执行。
drop table emp; --也不能执行,由于共享锁

手动加锁
lock table emp in exclusive mode;

session 2
conn scott/tiger;
update emp set sal=sal+100 where empno=7566;--不能进行

session 1
rollback;

发现和解决锁冲突:
SQL> select SID, SERIAL#, USERNAME
from V$SESSION where SID in
(select BLOCKING_SESSION from V$SESSION)
SQL> alter system kill session '144,8982' immediate;

死锁
conn scott/tiger;
create table d as select * from dept;
create table e as select * from emp;

update e set sal=sal+100;
update d set

session 2;
delete e;
delete d;

锁被持有直到事务结束(通常为COMMIT和ROLLBACK操作)
Transaction 1:
SQL> update emp set sal=sal+100
2 where empno=7369;

Transaction 2:
SQL> update emp set sal=sal*1.1
2 where empno=7369;

锁机制默认为细粒度,行级锁定模式。不同事务可以更新同一表中的不同行,彼此不会干扰。
如果必要,oracle数据库支持在更高级别进行手动锁定。
SQL> LOCK TABLE emp IN EXCLUSIVE MODE;

锁定模式
EXCLUSIVE:最严格的锁定模式
ROW SHARE:允许同步访问锁定的表,但是禁止其他会话锁定表以排他访问。
ROW EXCLUSIVE:与ROW SHARE相同,但是同样禁止以SHARE模式锁定。该锁定模式允许多个读会话但是近允许一个写会话。DML默认获取该模式的锁。
SHARE:允许同步查询,但是禁止更新锁定的表。创建索引时自动获取该模式的锁。允许多个读会话但是不允许写会话。
SHARE ROW EXCLUSIVE:允许查询整个表,同时允许其它会话查询表中的行,但是不允许更新或以SHARE模式锁定表。

手动锁定需要等待所有会话释放锁。可以使用NOWAIT选项强制立即获取控制权
SQL> LOCK TABLE hr.employees IN SHARE MODE NOWAIT

入队机制
锁定请求自动入队,前一个会话完成之后,下一个会话获取锁。已经获取锁的会话可以改变会话模式而不用重新排队。

锁冲突的可能原因
1.不提交的改变
2.长时间运行的事务
3.不必要的高级别的锁定

解决锁冲突
1.提交或者回滚持有锁的会话
2.终止持有锁的会话
SQL> select SID, SERIAL#, USERNAME from V$SESSION where SID in (select BLOCKING_SESSION from V$SESSION)
SQL> alter system kill session '144,8982' immediate; ('SID,SERIAL#')

死锁
Transaction 1:
setp1. SQL> update emp set sal=sal+100 where empno=7369;
step3. SQL> update emp set sal=sal+100 where empno=7499;

Transaction 2:
step2. SQL> update emp set sal=sal+100 where empno=7499;
step4. SQL> update emp set sal=sal*1.1 where empno=7369;