事务的定义:事务是一个操作序列。要么同时成功要么同时失败,这一系列操作,是不可分割的工作单位
事务保证数据库的完整性
事务不能嵌套
4.在oracle中,没有事务开始的语句。一个Transaction起始于一条DML(Insert、Update和Delete )语句,结束于以下的几种情况:
- 用户显式执行Commit语句提交操作或Rollback语句回退。
- 当执行DDL(Create、Alter、Drop)语句事务自动提交。执行一个 DDL ,dcl语句或从 SQL*Plus正常退出,都会自动执行commit命令
3)用户正常断开连接时,Transaction自动提交。
4)系统崩溃或断电时事务自动回退。
- commit:表示事务成功的结束
- rollback:表示事务不成功的结束
- commit成功后,无法rollback
-- save point 保存点
-- 一个操作序列中包含多条sql语句,但只想部分成功,其他失败
select * from emp;
--保存点sp之前delete操作成功,sp之后回滚
delete from emp where empno = 1234;
delete from emp where empno = 1111;
savepoint sp;
delete from emp where empno = 3;
rollback to sp;
commit;
事务的四个特性:ACID
A(atomicity)原子性:强调不可分割
C(Consistency)一致性:事务开始的前后,随着状态转移,始终保证正确,比如A向B转账,不可能A扣了钱,B却没收到
数据不一致的3种情况(事务的并发问题):
1)脏读
2)不可重复读
4)幻读I(Isolation)隔离性: 事务不受干扰的特点,也就是事务没执行完,数据不受系统其他部分影响,比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
涉及到事务4种隔离级别的概念(3读一序列化):
1)读未提交(read-uncommitted)
2)读已提交(read-commited)
3)可重复读 (repeatable-read)
4)序列化 (serializable)
隔离级别越严格执行效率越低,所以根据需要设置不同隔离级别,并不是越严格越好D(Durability)持久性:事务执行完成后,会持久化至物理设备
数据库的特性都是为了保证数据的一致性
数据库锁机制:
为了解决数据库并发访问导致数据不一致的问题,就需要给数据库加锁,为了执行效率,注意选择锁的粒度:
1)锁库
2)锁表
3)锁行
粒度越大效率越低,实际开发中大部分是行级锁
为什么不用oracle,因为oracle
mysql事务测试:
-
将自动提交事务关闭
--首先查看事务是否是自动提交(默认是自动提交)
select @@autocommit;
--改为不自动提交
set autocommit = 0; 准备数据
--建库
create database tran;
--使用库
use tran;
--建表
create table psn(id int primary key,name varchar(10)) engine = innodb;
insert into psn values(1,'zhangsan');
insert into psn values(2,'lisi');
insert into psn values(3,'wangwu');
commit;事务隔离级别
读未提交:AB事务并发访问数据,B事务读到A未提交的事务数据,也就是出现脏读
读已提交:AB事务并发访问数据,A修改数据,但未commit,B事务此时读取不到A未提交数据,当A提交事务后,B事务再次读取,发现两次结果不一致,也就是出现不可重复读
可重复读:AB事务并发访问数据,不论A怎么修改数据,事务是否提交,B事务每次读取结果都一致。会出现数据库已被A更新,事务B却读不到,也就是会出现幻读
序列化:串行执行 脏读、不可重复读、幻读都不会出现
四种隔离级别产生数据不一致的3种现象:
脏读
不可重复读
幻读
--设置事务隔离级别为读未提交(两个窗口都要执行)
set session transaction isolation level read uncommitted;
测试事务
注意每次切换事务隔离级别之前先确保事务都commit了,表示事务结束,重置了上下文
窗口A: start transaction;
窗口B: start transaction;-
读未提交产生脏读的现象
--窗口A更新数据但没commit:
--窗口B却能查到,出现了脏读:
将A窗口数据回滚
此时B窗口数据同A窗口
-
读已提交,不会出现脏读了
首先将两窗口都设置事务隔离级别为读已提交并start transaction
A窗口执行更新,但没有commit:
B窗口执行:
发现已经不会脏读,但是出现了不可重复读
A窗口commit结束事务:
B窗口再次查询发现又变成zhangsan了:
在B窗口同一个事务中,两次读取不一致,出现了不可重复读
-
可重复读
将AB两窗口分别执行:
--查询当前会话的事务隔离级别
select @@tx_isolation;
--查询数据库系统的事务隔离级别
select @@global.tx_isolation;
A窗口修改记录:
A提交事务:
B窗口查询记录:
第一次A刚修改完记录,B查询一次,第二次A commit事务,B再查一次
可见B窗口同一个事务中,两次查询结果一致,消除了不可重读的现象,实际上数据库中已经是A提交事务后的数据,B的第二次查询却没有读出来
在AB会话事务隔离级别为repeatable read情况下:
A窗口向数据库中插入一条记录:
B会话在A插入之前查询一次,插入之后再查询一次,都显示如下结果:
然后B会话执行插入同样一条记录:
B会话在同一事务中,查询的时候没有该条记录,插入时出现了提示重复主键,出现幻读,删除也是如此,如果隔离级别为串行化,则不会出现
幻读只会在插入和删除记录会出现,查询在repeatable read隔离级别下,不可能出现幻读
数据库级别的事务隔离级别以及会出现的数据不一致的现象总结:
Oracle数据类型:
1). number(x,y) 数字类型 ,最长x位,y位小数
2). varchar2(maxlength):变长字符串,这个参数的上限是32767字节
▪ 声明方式如下VARCHAR2(L),L为字符串长度,没有缺省值,作为变量最大32767个字节
3). char(max_length) :定长字符串 最大2000字节
4). DATE:日期类型 (只能精确到秒。)
5). TIMESTAMP:时间戳 (精确到微秒)
6). long:长字符串,最长2GB
了解类型
① CLOB:最大长度4G -->大对象很少使用:如果存在大对象,一般的解决方案存入文件地址
(地址为程序所在应用服务器的相对路径)。
② BLOB:存二进制文件