# 事务?
--模拟银行转账问题
create table bank( id number(6) primary key, money number(6)check(money>0) ) insert into bank values(1,100); insert into bank values(2,100);
--转账步骤
--1给2转账50元(一起执行多条sql语句,每句之间用;隔开,并F5执行)
update bank set money = money-50 where id=1;
update bank set money = money+50 where id=2;
--发生错误的原因
--update语句违反约束余额>=0 第一个sql发生错误;第二个sql还在增加
***事务:是作为单个逻辑工作单元执行一系列操作***
***多个操作作为一个整体向系统提交,要么都执行,要么都不执行***
***事务是一个不可分割的工作逻辑单位***
--使用事务解决转账
begin update bank set money = money-50 where id=1; update bank set money = money+50 where id=2; commit; --一起生 exception when others then rollback;--一起死 end;
***
# 事务四个特性:(ACID)
原子性:要么都成功,要么都失败。
一致性:当事务执行前后,总量保持一致。
隔离性:各个事务并发执行时,彼此独立。
持久性:持久化操作。
# 事务生命周期:
MySQL:自动提交(将每条DML语句自动提交)
Oracle:手动提交
事务的开始标识: 第一条DML
结束: 提交事务 撤销事务
a.提交
i:显示提交:commit;
ii:隐式提交:正常退出exit、DCL(grant...to..、revoke..from..)、DDL(create.../drop...)
b.撤销
i:显示回滚:rollback;
ii:隐式回滚:异常退出(宕机、断电)
保存点savepoint:
打游戏 10:1,2(savepoint),3,4,5,6,7,8,9
语法: x a b savepoint 保存点名字
create table xx( id number(10) primary key, name varchar2(10) ); insert into xx values(1,'zs'); insert into xx values(2,'ls'); savepoint initdate; insert into xx values(3,'ww'); select * from xx; rollback to savepoint initdate;
--事务的隔离级别:多个事务会产合适生很多并发问题:
1.脏读:当一个事务正在访问数据,并对此数据进行修改(1――>2),但是这种修改【还没有提交到数据库(commit)】
此时,另一个事务也在访问这个数据。本质:某个事务(客户端)读取的数据是过时的。
2.不可重复读:在一个事务内(客户端)内,多次读取同一个数据,但结果不同。
本质:就是事务A拿到了 被其他事务B修改并体交后的数据。
3.幻读(虚读):在一个事务内(客户端)内,多次读取同一批数据,但结果不同。
不可重复读和幻读的区别:
a.不可重复读指的是对于"同一条"数据的查询操作 a――>b
幻读对于"多条数据"的查询操作,数据量数:20条――>18条
b.不可重复读:update
幻读:insert|delete
SQL99标准隔离级别 依次递进(解决并发效果,越来越稳定),但是性能越来越低。
并发性、可用性本身就是矛盾的。
---Read uncommitted 读未提交
---Read comitted 读已提交
---Repeatable 可重复读
---Serializable 序列化/串行化
Oracle支持: Read comitted 读已提交(默认)、Serializable 序列化/串行化、
(Oracle自身扩充了read only,实际read only 隶属于Serializable 序列化/串行化级别。)
---切换隔离级别:
commit;--结束前面的操作 set transaction isolation level Read Comitted; set transaction isolation read only;
MySQL:全部支持
***
--事务三步走 (查询没有事务,只有DML有,增、删、改)
开始事务:从上一次事务结束之后,进行的第一次dml操作,就自动开启了事务
提交事务:commit;
回滚(撤销)事务:rollback;
insert into bank values(3,100); insert into bank values(4,100); insert into bank values(5,100); rollback; --白玩,打回原形
--例子:办理学生离校手续
select * from grade where gradename = '白银' select * from subject where gradeid=2 select * from result where subjectid in (5,6,7,8,9,10)
***查询result表中所有的”白银”阶段学生的考试成绩,保存到表HistoryResult中***
create table historyResult( Id number(4)primary key, StudentNo varchar2(50) not null, SubjectId number(2) not null, StudentResult number(4) null, ExamDate date not null ) --insert into tab1 select * from tab2; insert into historyResult select * from result where subjectid in (5,6,7,8,9,10); commit; select * from historyResult;
***删除Result表中所有的“白银”阶段学生的考试成绩***
delete from result where subjectid in (5,6,7,8,9,10); commit; select * from historyResult;