数据库事务(datebase transaction),是指作为独立的逻辑工作单元执行的一系列操作,要么完全的执行,要么完全不执行。事务处理可以保证除非事务性单元内的所有操作完全成功执行,否则不会永久更新面向数据的资源。
事务的四大特性:
1、原子性:事务必须是原子工作单元,是不可分割的;对于其数据的修改,要么全都执行,要么全都不执行;
2、隔离性:由并发事务所做的修改必须与其它并发事务所做的修改相互隔离。事务查看数据状态,要么是另一并发事务修改前,要么是修改后,事务不会查看中间状态的数据(事务间是不透明的);
3、一致性:数据要保持一致性,如银行汇款转账,必须保证数据一致;
4、持久性:事务在执行完成后,对于系统的影响是永久的,事务的任何修改及时出现致命的系统故障也将一致保持。
事务的执行控制:
1、commit 提交事务处理
2、rollback 撤销/回滚事务处理
3、savepoint 事务保存点
4、rollback to savepoint 回滚到事务保存点
模拟银行转账事务处理:
1、创建测试序列
CREATE SEQUENCE seq_test
START WITH 1
INCREMENT BY 1
MAXVALUE 99
2、创建余额表
CREATE TABLE acc_bal(
ID NUMBER PRIMARY KEY,
cardnum NUMBER NOT NULL,
balance NUMBER NOT NULL CHECK (balance>= 1),
owner VARCHAR2(32) NOT NULL,
timepoint TIMESTAMP DEFAULT systimestamp
)
插入两条用户记录
INSERT INTO acc_bal VALUES(99, 123456789321654,20000,'陈坤',DEFAULT);
INSERT INTO acc_bal VALUES(100, 987654321123456,40000,'吴山',DEFAULT);
commit;--记得提交事务,否则回滚不到此节点数据状态
3、创建交易表
CREATE TABLE bus_tab(
ID NUMBER PRIMARY KEY,
amount NUMBER NOT NULL,
biztype NUMBER NOT NULL,
biztime TIMESTAMP DEFAULT systimestamp,
cardid NUMBER REFERENCES acc_bal (ID)
)
4、创建plsql语句块,模拟银行转账(由于增加了余额的check约束,导致余额小于1会违反约束,借此模拟转账的成功和失败)
DECLARE
mess1 STRING(32) := '交易成功';
mess2 STRING(32) := '交易失败';
err_che EXCEPTION;--定义异常变量
PRAGMA EXCEPTION_INIT(err_che,-2290);--用错误号注册异常
BEGIN
--转出账户增加一条记录
INSERT INTO bus_tab VALUES(seq_test.nextval,20000,1,DEFAULT,99);
--转入账户增加一条记录
INSERT INTO bus_tab VALUES(seq_test.nextval,20000,0,DEFAULT,100);
--转入账号加上10000
UPDATE acc_bal SET balance = balance - 20000 WHERE ID = 99;
--转出账号减少10000
UPDATE acc_bal SET balance = balance + 20000 WHERE ID = 100;
COMMIT;
dbms_output.put_line(mess1);
EXCEPTION WHEN err_che THEN--处理异常
ROLLBACK;
dbms_output.put_line(mess2);
END;
由于执行过程中id=99的用户余额小于1,违反check约束,触发异常,进行事务回滚,保持了原有的数据状态;
当转账金额改为18000时,没有触发异常,所以交易成功,保持数据的一致性。