一.数据库事务
1.DML语句执行的时候,如果当前有事务,那么就使用这个事务,如果当前没有事务,这个执行的DML语句就会产生一个新的事务。
2.只有DML语句才会产生事务,其他语句不会产生事务。insert updata delete
3.commit/rollback/DDL语句都可以把当前事务给结束掉
4.commit和DDL语句结束事务的方式是把这个事务给提交了
5.rollback结束事务的方式是把这个事务给回滚了
注:
提交事务是指让这个事务里面的所有操作都生效到数据库中commit
回滚事务是指让这个事务里面的所有操作都撤销rollback
例如1:
insert ....产生事务A
update ... 这个操作是事务A中的操作
insert .. 这个操作是事务A中的操作
commit; 让事务A里面的三个操作生效、事务A结束
delete ... 产生新的事务B
insert .. 这个操作是事务B中的操作
insert .. 这个操作是事务B中的操作
insert .. 这个操作是事务B中的操作
rollback; 让事务B中的四个操作都撤销,事务B结束
例如2:
insert ....产生事务A
update ... 这个操作是事务A中的操作
insert .. 这个操作是事务A中的操作
DDL语句; 事务A会被提交,事务A结束
rollback; 这时候回滚已经对事务A不起作用,因为事务A以及被提交了,当前已经没有事务了
注:CREATE, ALTER, DROP, RENAME, TRUNCATE 等都属于DDL语句
二.事务特征ACID:
原子性:Atomicity
同时成功或者同时失败
一致性:Consistency
事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
隔离性:Isolation
事务操作应该相互独立
持久性:Durability
事务所做的影响 ,在事务结束之后应该能够是持久的。
三.isolation 事务隔离级别
事务中产生的问题:
1.脏读 主要针对update操作。
一个事务A读到另一个事务B中修改过但是还没有提交的数据
2.不可重复读 主要针对update操作。(修改了数据的值)
一个事务A在第一次读数据和第二次读数据之间,有另一个事务B把这个数据更改并提交了,所以就出现了事务A里面读一个数据俩次,但是读到的结果是不同的。
3.幻读 主要针对的是insert/delete操作。(修改了数据的数量)
事务A第一次用where条件筛选出了10条数据,事务A第二次用通样的where条件筛选出的却是11条数据,
因为事务B在事务A的第一次和第二次查询之间进行了插入操作,并且插入的这个数据满足事务A的where筛选条件.
事务隔离级别有:
read-uncommitted 不提交也能读
read-committed 提交之后才能读 解决了脏读
repeatable-read 解决了脏读和不可重复读
serializable 三个问题都解决了
级别越高解决的问题越多但是效率越低。
注意:并不是所有数据库都支持这四种事务隔离级别,比如oracle就只支持第二种和第四种这俩种,比如mysql就四种全支持.
oracle里面默认的事务隔离级别是第二种:read-committed
oralce里面设置事务隔离级别:
Set Transaction Isolation Level Read Uncommitted
Set Transaction Isolation Level Read Committed
Set Transaction Isolation Level Read Repeatable
Set Transaction Isolation Level Serializable
四.回滚点/保存点 savepoint
例如:
DML语句1
savepoint A
DML语句2
savepoint B
DML语句3
rollback to A/B
这个时候可以通过这个回滚点让事务回滚到指定的位置,如果不指定回滚点而是直接rollback,那么事务会一下子回滚完.
【特别注意】:rollback到回滚点之后,这个事务并没结束,这个时候还可以接着回滚或者commit提交事务。
create table t_user(
id number primary key,
name varchar2(100),
salary number
);
drop table t_user;
例如:
insert into t_user values(1,'tom',1000);
savepoint A;
insert into t_user(id,name) values(2,'zs');
savepoint B;
delete from t_user;
rollback to B;
然后查询看结果
select * from t_user;