–======================
–SQL基础–>数据库事务
–======================
一、数据库事务
数据库事务是指作为单个逻辑工作单元执行的一系列操作,可以认为事务就是一组不可分割的SQL语句
二、数据库事务的ACID属性
原子性(atomic)
事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。
一致性(consistent)
事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务
的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如B 树索引或双向链
表)都必须是正确的。
隔离性(Isolation)
由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状
态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中
间状态的数据。(注:更正@20131218)
持久性(Duration)
事务完成之后,它对于系统的影响是永久性的。
三、事务的组成
一个数据库事务可由:
一个或多个DML语句组成
一个DDL语句组成
一个DCL语句组成
一个数据事务由:
以第一个DML语句的执行作为开始
以下面的其中之一作为结束
commit (提交)
rollback (回滚)
ddl或dcl语句 (自动提交)
用户会话正常结束(自动提交)
系统异常终止 (自动回滚)
系统崩溃 (自动回滚)
四、事务的提交或回滚(COMMIT、ROLLBACK)
—使用COMMIT事务,robinson记录被插入到表
SQL> INSERT INTO scott.emp(empno,ename,job,salary)
2 VALUES(9999,‘Robinson’,‘DBA’,3500);
1 row created.
SQL> COMMIT;
Commit complete.
SQL> UPDATE scott.emp SET salary = 4000 WHERE ename = ‘Robinson’;
1 row updated.
—使用ROLLBACK回滚,更新将失效,最终结果如下面的查询
SQL> ROLLBACK;
Rollback complete.
SQL> SELECT * FROM scott.emp WHERE ename = ‘Robinson’;
EMPNO ENAME JOB MGR HIREDATE SALARY DEPTNO
———- —————————— ——— ———- ——— ———- ———-
9999 Robinson DBA 3500
五、保存点
设置保存点:
SAVEPOINT NAME
恢复至保存点:
ROLLBACK TO NAME
—查看empno为,的记录
SQL> SELECT * FROM scott.emp WHERE empno IN (1235,1236);
EMPNO ENAME JOB MGR HIREDATE SALARY DEPTNO
———- —————————— ——— ———- ——— ———- ———-
1235 Tony boy 28–JUN–10 7100
1236 Ben IT 28–JUN–10 3100 20
—首先更新empno 为的salary ,并设置了一个保存点tran1
SQL> UPDATE scott.emp SET salary = salary * 1.5 WHERE empno = 1236;
1 row updated.
SQL> SAVEPOINT tran1;
Savepoint created.
—更新empno 为的salary
SQL> UPDATE scott.emp SET salary = salary * 0.8 WHERE empno = 1235;
1 row updated.
—查看刚刚更新的两条记录
SQL> SELECT * FROM scott.emp WHERE empno IN (1235,1236);
EMPNO ENAME JOB MGR HIREDATE SALARY DEPTNO
———- —————————— ——— ———- ——— ———- ———-
1235 Tony boy 28–JUN–10 5680
1236 Ben IT 28–JUN–10 4650 20
—将事务回滚到保存点tran1
SQL> ROLLBACK TO SAVEPOINT tran1;
Rollback complete.
—可以看到保存点之后的修改被回滚,而保存点之前的修改则不受影响
SQL> SELECT * FROM scott.emp WHERE empno IN (1235,1236);
EMPNO ENAME JOB MGR HIREDATE SALARY DEPTNO
———- —————————— ——— ———- ——— ———- ———-
1235 Tony boy 28–JUN–10 7100
1236 Ben IT 28–JUN–10 4650 20
—对所作的修改全部ROLLBACK,此时仅仅包含了empno 为的记录,因为已经被回滚
SQL> ROLLBACK;
Rollback complete.
SQL> SELECT * FROM scott.emp WHERE empno IN (1235,1236);
EMPNO ENAME JOB MGR HIREDATE SALARY DEPTNO
———- —————————— ——— ———- ——— ———- ———-
1235 Tony boy 28–JUN–10 7100
1236 Ben IT 28–JUN–10 3100 20
六、事务的开始与结束及不同时刻的状态
事务的开始
连接到数据并执行了一条DML语句(INSERT ,UPDATE,DELETE)
前一条事务结束后,又执行了另外一条DML语句
事务的结束
执行COMMIT 或ROLLBACK
执行DDL语句,则自动提交并结束事务
执行DCL语句,则自动提交并结束事务
断开与数据库的连接,如退出SQL Plus。
Windows下SQL Plus正常退出将执行COMMIT,如点击关闭窗口直接关闭则回滚
X–Window下SQL Plus正常退出将执行COMMIT,如点击关闭窗口直接关闭则回滚(笔者在RHEL5下测试如此)
DML语句执行失败则自动回滚
提交或回滚前的数据状态
改变前的数据状态是可以恢复的
执行DML 操作的用户可以通过SELECT 语句查询之前的修正
其他用户不能看到当前用户所做的改变,直到当前用户结束事务。
DML语句所涉及到的行被锁定,其他用户不能操作
提交后的数据状态
数据的改变已经被保存到数据库中。
改变前的数据已经丢失。
所有用户可以看到结果。
锁被释放,其他用户可以操作涉及到的数据。
所有保存点被释放。
七、并发事务
多个用户同时与数据库交互,且每个用户都可以同时访问自己的事物,这种事务称为并发事务
对于同一个对象上运行的多个事务,仅当执行commit时才对彼此的查询产生影响
下表中演示了并发事务的处理:
| Trans1 | Trans2 |
T1 | SQL> SELECT COUNT(1) FROM emp;
COUNT(1) ———- 16 | SQL> SELECT COUNT(1) FROM scott.emp;
COUNT(1) ———- 16 |
T2 | SQL> INSERT INTO emp(empno,ename,salary) 2 SELECT 6666,’Jenney’,3000 FROM DUAL; |
|
T3 | SQL> UPDATE emp 2 SET salary = salary + 200 WHERE ename = ‘SCOTT’; |
|
T4 | SQL> SELECT COUNT(1) FROM emp;
COUNT(1) ———- 17 | SQL> SELECT COUNT(1) FROM scott.emp;
COUNT(1) ———- 16 |
T5 | SQL> COMMIT; |
|
T6 |
| SQL> SELECT COUNT(1) FROM scott.emp;
COUNT(1) ———- 17 |
示例中显示了两个不同的事务交叉执行的顺序,可以看出,仅当事务执行COMMIT后,相关事务才产生影响
八、利用AUTOCOMMIT进行事务控制
SET AUTOCOMMIT ON
设置自动提交,每执行一条语句,就提交。将autocommit设成ON时,在进行DML操作时似乎很方便,
但在实际应用中有时可能会出现问题,如,在有些应用中要同时对几个表进行操作,对于这些表建立
了外键联系,如果一旦操作失败另一个表,就很麻烦了。
关于锁及事物的隔离级别请关注后续文章
九、更多
SQL基础–>层次化查询(START BY … CONNECT BY PRIOR)
SQL 基础–> 集合运算(UNION 与UNION ALL)