什么是事务
是一种机制、一个操作序列、它包含了一组数据库操作命令,并且所有的命令作为一个整体,一起向系统提交或撤销操作请求。由一个或多个完成一种相关行为的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的事务隔离级别:1、ReadCommitted。2、Serializable;
3、Read Only是Serialzable的子集,但事务中不能有任何修改数据库中数据的语句(DML),以及修改数据库结构的语句(DDL);
Oracle中不需要专门的语句来开始事务。隐含的,事务会在修改数据的第一条鱼具处开始。
结束事务:1、COMMIT语句显式终止一个事务。当执行COMMIT语句时,在事务中对数据的修改都会保存到数据库中。2、R