事务处理和并发控制

什么是交易

它是一种机制、操作序列、它包括一组数据库操作命令,总体。一起向系统提交或撤销操作请求。

由一个或多个完毕一种相关行为的SQL语句组成。是一个不可切割的工作逻辑单元。

在事务处理中。一旦某个操作发生异常,则整个事务都会又一次開始。数据库也会返回到事务開始之前的状态,在事务中对数据库所做的一切操作都会取消。

事务要是成功的话,事务中全部的操作都会运行。

事务控制语句COMMIT:提交事务,即把事务中对数据库的改动进行永久保存。

ROLLBACK:回滚事务,即取消对数据库所做的不论什么改动。

事务的特性:1、原子性(Atomicity):事务是一个完整的操作。事务的各步操作是不可分的(原子的),要么都运行,要么都不运行。2、一致性(Consistency):在事务操作前后,数据必须处于一致状态。

3、隔离性(Isolation):对数据进行改动的全部并发事务彼此隔离的。这表明事务必须是独立的。他不应该以不论什么方式依赖于或影响其它事务。4、持久性(Durability):事务完毕后,他对数据的改动被永久保持。

演示样例:ACCOUNT_BALANCE表示用户剩余金额ACCOUTN_ID表示用户id

BEGIN
 UPDATE ACCOUNT SETACCOUNT_BALANCE=ACCOUNT_BALANCE-4000;
       WHERE ACCOUNT_ID=’1001’;
 UPDATE ACCOUNT SETACCOUNT_BALANCE=ACCOUNT_BALANCE+4000;
       WHERE ACCOUNT_ID=’1002’;
COMMIT;
EXCEPTION
       WHERE OTHERS THEN ROLLBACK;
DBMS_OUTPUT.PUT_LINE(‘转账异常,停止转账!

’); END;

事务一致性要求:在事务处理開始之前。数据库的全部数据都满足业务规则约束。当事务处理结束后,数据库中的全部数据仍然满足业务规则约束。

演示样例:

DECLARE
       account_a ACCOUNT.ACCOUNT_BALANCE%TYPE;
       account_b ACCOUNT.ACCOUNT_BALANCE%TYPE;
BEGIN
       SELECT ACCOUNT_BALANCE INTO account_aFROM ACCOUNT WHERE ACCOUNT_ID=’1001’;
       SELECT ACCOUNT_BALANCE INTO account_bFROM ACCOUNT WHERE ACCOUNT_ID=’1002’;
       dbms_output.put_line(‘转账前A金额:’);
       dbms_output.put_line(account_a);
       dbms_output.put_line(‘转账前B的金额:’);
       dbms_output.put_line(account_b);
       dbms_output.put_line(‘转账前总金额:’);
       dbms_output.put_line(account_a+account_b);
       UPDATE ACCOUNT SETACCOUNT_BALANCE=ACCOUNT_BALANCE-2000
WHERE ACCOUNT_ID=’1001’;
       UPDATE ACCOUNT SETACCOUNT_BALANCE=ACCOUNT_BALANCE+2000
WHERE ACCOUNT_ID=’1002’;
       COMMIT;
       dbms_output.put_line(‘成功转账。’);
       SELECT ACCOUNT_BALANCE INTO account_aFROM ACCOUNT WHERE ACCOUNT_ID=’1001’;
       SELECT ACCOUNT_BALANCE INTO account_bFROM ACCOUNT WHERE ACCOUNT_ID=’1002’;
       dbms_output.put_line(‘转账后A金额:’);
       dbms_output.put_line(account_a);
       dbms_output.put_line(‘转账后B金额:’);
       dbms_output.put_line(account_b);
       dbms_output.put_line(‘转账后总金额:’);
       dbms_output.put_line(account_a+account_b);
       EXCEPTION WHEN OTHERS THEN ROLLBACK;
       dbms_output.put_line(‘转账异常,停止转账!’);
       SELECT ACCOUNT_BALANCE INTO account_aFROM ACCOUNT WHERE ACCOUNT_ID=’1001’;
       SELECT ACCOUNT_BALANCE INTO account_bFROM ACCOUNT WHERE ACCOUNT_ID=’1002’;
       dbms_output.put_line(‘停止转账后A金额:’);
       dbms_output.put_line(account_a);
       dbms_output.put_line(‘停止转账后B金额:’);
       dbms_output.put_line(account_b);
       dbms_output.put_line(‘停止转账后总金额:’);
       dbms_output.put_line(account_a+account_b);
END;

读取异常的情况:1、脏读:一个事务读取了还有一个事务未提交的数据。

2、不可反复读。一个事务在次读取之前曾读取过的数据时。发现该数据已经被还有一个已提交的事务改动。

3、幻读:一个事务依据同样的查询条件,又一次运行查询,返回的记录中包括与前一次运行查询返回的记录不同的行。

ANSISQL-92标准中定义的事务隔离级别:

ReadUncommitted最低等的事务隔离,它只保证了读取过程中不会读取到非法数据。

ReadCommitted,此级别的书屋隔离保证了一个事务不会读到还有一个并行事务已改动但未提交的数据。也就是说此级别的事务级别避免了“脏读”。

RepeatableRead。此级别的事务隔离避免了“脏读”和“不可反复读”异常现象的出现。

这也意味着。一个事务不可能更新已经由还有一个事务读取但未提交的数据。

可能引发幻读。

Serializable,最高等级的隔离级别,提供了最高等级的隔离机制,三种异常情况都能避免。

隔离等级

脏读

不可反复读

幻读

Read  Uncommitted

可能

可能

可能

Read  Committde

不可能

可能

可能

Repeatable  Read

不可能

不可能

可能

Serializable

不可能

不可能

不可能

Oracle的事务隔离级别:1ReadCommitted

2Serializable;

3Read OnlySerialzable的子集,但事务中不能有不论什么改动数据库中数据的语句(DML),以及改动数据库结构的语句(DDL);

 

 

 

Oracle中不须要专门的语句来開始事务。

隐含的,事务会在改动数据的第一条鱼具处開始。

结束事务:1COMMIT语句显式终止一个事务。当运行COMMIT语句时,在事务中对数据的改动都会保存到数据库中。2ROLLBACK语句回滚事务。当运行ROLLBACK语句时,将取消在事务中对数据库所做的不论什么改动。

3、运行一条DDL语句,假设DDL语句前已经有DML语句,则Oracle会把前面的DML语句作为一个事务提交。

4、用户断开与Oracle的链接。用户当前事务将被自己主动提交。5、用户进程意外被终止。这时用户当前的事务被回滚。

事务控制语句:1COMMIT:提交事务,即把事务中对数据库的改动进行永久保存。

2ROLLBACK:回滚事务。即取消对数据库所做的不论什么改动。

3SAVEPOINT:在事务中创建存储点。

4ROLLBACKTO<SAVEPOINT_NAME>:将事务回滚到存储点。5SET TRANSACTION:设置事务的属性。

SAVEPOINT:在事务中创建存储点。

语法:SAVEPOINT[SavePoint_Name];

ROLLBACKTO<SavePoint_Name>:将事务回滚到存储点。语法:ROLLBACK TO[SavePoint_Name];

演示样例:

BEGIN
	UPDATE ACCOUNT SETACCOUNT_BALANCE=ACCOUNT_BALANCE+2000 WHEN ACCOUNT_ID=’1001’;
	SAVEPOINT Add_Account_A;
	UPDATE ACCOUNT SET ACCOUNT_BALANCE= ACCOUNT_BALANCE-6000 WHEN ACCOUNT_ID=’1001’;
	UPDATE ACCOUNT SETACCOUNT_BALANCE=ACCOUNT_BALANCE+6000 WHEN ACCOUNT_ID=’1002’;
	COMMIT;
	EXCEPTION
	     WHENOTHERS THEN dbms_output.put_line(‘转账异常!

’); ROLLBACK TO Add_Account_A; END;

SETTRANSACTION语句必须是事务的第一条语句,他能够指定事务的隔离级别、规定回滚事务时所使用的存储空间、对事务命名。

设置訪问级别的方法:SET TRANSACTION READ ONLY;   SET TRANSACTION ISOLATION LEVEL READCOMMITED;          SET TRANASCTION ISOLATION LEVEL SERIALIZABLE;

并发控制:指用正确的方式实现事务的并发操作,避免造成数据的不一致。

并发控制带来的问题:1、丢失更新。一个事务改动某行数据时,还有一个事务同一时候改动了该行数据,使第一个事务对数据的改动丢失。2、脏读。

3、不可反复读。4、幻读。

锁的基本概念:锁,用来共享资源控制并发訪问的一种机制。锁由Oracle自己主动管理,锁持续的时间等于被提交事务处理的时间。

锁的类型:1、共享锁(使用共享锁的数据对象能够被其它事务读取,但不能改动),也称s锁。2、排他锁,也称x锁。

按锁保护的内容分类:DML锁,用来保护数据的完整性和一致性;DDL锁,用来保护数据对象结构定义;内部锁和闩,用来保护数据库内部数据结构。

死锁:两个事务(会话)都进入了彼此等候对方锁定的资源时的一种停止状态。

解决死锁:“牺牲”一个会话。回滚一个会话事务。使还有一个会话的事务继续运行。

在发生死锁时Oracle数据库会在server上创建一个跟踪文件记录死锁。

注意:不要在开发过程中人为的提供条件使Oracle产生死锁。

堵塞:假设一个会话持有某个资源的锁,而还有一个会话在请求这个资源就造成了堵塞。

锁机制问题:1、悲观锁,是指在读取数据后立即锁定相关资源。语法:SELECT…………FORUPDATE[OF column_list][WAIT n|NOWAIT]    OF子句用于指定即将更新的列,即锁定行上的特定列;WAIT子句指定等待其它用户释放的秒数。防止无限期的等待,NOWAIT表示不等待。

演示样例:

SELECT * FROM ACCOUNT WHEREACCOUNT .ID=’1001’ FOR UPDATE;
UPDATE ACCOUNT SETBALANCE=BALANCE-500 WHERE ID=’1001’;

乐观锁:把全部锁定都延迟到即将运行更新之前。

语法:

UPDATE Table_Name SETColumn_Name1=NewValue1,Column_Name2=NewValue2……
WHERE Column_Name1=OldValue1 ANDColumn_Name2=OldValue2……

演示样例:

DECLARE 
 account_a ACCOUNT.BALANCE%TYPE;
BEGIN
       SELECT balance INTO account_a FROMACCOUNT WHERE ID=’1001’;
       UPDATE ACCOUNT SET balance=balance-500WHERE ID=’1001’ AND BALANCE=account_a;
END;

锁的分类:DML锁用于确保一次仅仅有一个用户能改动一行。并且正在处理一个表时,别人也不能删除这张表。

DML锁主要包含TX锁、TM锁。当中TX锁是事务锁或行级锁,TM锁成为表级锁。

TX锁:事务发起第一个改动数据的语句时会自己主动得到TX锁。并且会一直持有这个锁,知道事务提交或回滚。

TX锁用作一种排队机制,使得其它会话能够等待这个事务运行。

事务中改动或通过悲观锁定选择的每一行都会指向该事务的一个相关TX锁。

TM锁:用于确保在改动表的内容是。表的结构不会改变当一个会话開始更新一个表时,会自己主动获得这个表的TM锁,这样可以防止。另外一个在该表上运行DROP或者ALTER语句删除该表或更改该表的结构。

DDL锁:用来保护数据对象结构定义。DDL操作会自己主动为数据库对象加DDL锁。

注意:Oracle中,DDL包裹在提交一个隐含的声明(回滚)要运行操作。

版权声明:本文博主原创文章。博客,未经同意不得转载。

posted @ 2015-09-02 11:00  zfyouxi  阅读(376)  评论(0编辑  收藏  举报