一、什么是事务
数据库事务就是一组sql语句,这组sql语句是一个逻辑工作单元。我们可以认为事务就是一组不可分割的sql语句。在执行时,应该作为一个整体永久性地修改数据库的内容,或者作为一个整体取消对数据库的修改。
e.g. 事务的一个例子是银行转账:将钱从一个银行账号中转到另外一个银行账号中。此时通常包含两步操作:一条是update语句负责从一个银行账号的总额中减去一定的钱数,另一条update语句负责向另外一个银行账号中增加相应的钱数。这2个减少和增加的操作应该要么同时永久地保存到数据库中,要么全部取消——否则就
会有一部分钱丢失了。这个简单的例子只使用了2个update语句,然后实际中的事务要比这复杂很多:通常包含多个insert、update、delete等。
二、事务的回滚和提交
要永久地记录事务中sql语句的结果,需要执行commit语句,从而提交事务。要取消sql语句的结果,需要执行rollback语句,从而回滚(rollback)事务。rollback语句可以将行重新设置为原始状态。在执行回滚操作之前对数据库进行的任何修改操作都会被取消。条件是此前没有断开与数据库的连接。
配置config:
create user Ruying identified by miyake87
default tablespace users
temporary tablespace temp
/
GRANT connect, resource TO Ruying;
/
GRANT CREATE SESSION TO Ruying;
/
grant create table to Ruying;
/
create table product(
product_id number(10) primary key,
product_name varchar2(100) not null
)
/
insert into product
values(1,'花卉');
/
insert into product
values(2,'鬼脸嘟嘟')
/
insert into product
values(3,'pocky')
commit;
/
update product
set product_name='好时巧克力'
where product_id=3
/
rollback;
SQL> select
2 *
3 from product;
PRODUCT_ID PRODUCT_NAME
3 pocky
1 花卉
2 鬼脸嘟嘟
三、事务的开始与结束
如前所述,事务是用来分隔数据库活动的逻辑工作单元。事务既有起点,也有终点:
当下列事件之一发生时,事务就开始了:
①连接到数据库上,并执行第一条DML语句;
②前一个事务结束后,又输入另一个DML语句;
当下列事件之一发生时,事务就结束了:
①执行commit或rollback语句;
②执行一条DDL语句。例如create table 语句;这种情况会自动commit;
③执行一条DCL语句,例如grant语句,也会自动commit;
④断开与数据连接:在退出sql*plus时候,通常会输入exit命令,此时会自动执行commit;
如果sql*plus被意外终止了,那么会自动执行rollback。这适用于任何会访问数据的程序。例如,
如果编写了一个可以访问数据库的java程序,而这个程序崩溃了,那么就会自动rollback。
⑤执行一条DML语句,该语句却失败了;会自动rolback.
Tips:每个事务之后,都显式的执行rollback或者commit是很好的习惯;
四、事务保存点
在事务中的任何地方都可以设置一个savepoint,这样可以将修改回滚到保存点处。如果有一个很大的事务,这将非常实用,譬如如果在保存点后进行了误操作,并不需要将整个事务一直回滚到最开头.saveponit不能乱用:调整一下事务的结构,将其转换为较小的事务。
例如:
select *
from product
where product_id in(1,2)
PRODUCT_ID PRODUCT_NAME PRICE
1 花卉 1
2 鬼脸嘟嘟 1
SQL> update product
set price=99
where product_id=1
SQL> savepoint save1;
SQL> update product
set price=66
where product_id=2;
SQL> select *
from product
where product_id in(1,2)
PRODUCT_ID PRODUCT_NAME PRICE
1 花卉 99
2 鬼脸嘟嘟 66
rollback to savepoint save1;
select *
from product
where product_id in(1,2)
PRODUCT_ID PRODUCT_NAME PRICE
1 花卉 99
2 鬼脸嘟嘟 1
----------------------由此可见名为save1的savepoint之前的修改没有被回滚。