前言
mysql学习-day05 事务MySQL事务
1.定义
指的是一组操作对数据库的数据真正的影响,这一组操作中有一个操作失败了 这一组事务就全失败了
2.事务的开启与提交
开启事务:
执行第一条dml语句,接下来所有的dml语句都会放到事物中。
也可以执行: start transaction;
手动开启事务
mysql中默认自动提交事务.
事务的提交:commit和DDL语句都会提交事务
禁用mysql自动提交事务.
set autocommit=0;
3. 事务的特点:ACID
A原子性、C一致性、I隔离性和D持久性
- 原子性:事物同时成功或者同时失败
- 一致性:是指事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
- 隔离性:事务操作应该相互独立
- 持久性:事务提交之后,它对于系统的影响是永久性的:对数据库产生真正的影响。
4. 事务控制语句
egin 或 start transaction;显式地开启一个事务;
commit;也可以使用 : commit work,不过二者是等价的。commit 会提交事务,并使已对数据库进行的所有修改称为永久性的;
rollback;也可以使用 : rollback work,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
savepoint 记录点名字 : savepoint 允许在事务中创建一个保存点,一个事务中可以有多个 savepoint;
release savepoint 记录点名字 : 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
rollback to identifier;把事务回滚到标记点;
set transaction;用来设置事务的隔离级别
commit;提交事物,对数据库产生永久的影响。没有提交前的数据在当前的session缓存中可以被查询。
commit;ddl ; exit;(退出);
exit; 退出sqlplus控制台,会提交事物,点击关闭 也会提交事务(有的版本会)
rollback; 回滚全部事务,当前的一组操作失败了,把这一组操作都返回到原始状态.
savepoint 保存点; 标记保存点,可以回滚到标记点。
rollback to 保存点名; 回滚到某标记点
5. 事务测试
1,设置事务手动提交:
set autocommit=0;
2,手动开启事务:
start transaction;
create table c(name varchar(20));
提交:
insert into c values('tom1') 产生一个事务A
insert into c values('tom2') 把这个操作放进已经存在的事务A里面
updete c set name = 'jary'; 把这个操作放进已经存在的事务A里面
delete c where name ='tom1' 把这个操作放进已经存在的事务A里面
commit; 提交事务:让前面的DML操作都生效
回滚:
insert into c values('tom1') 产生一个事务A
insert into c values('tom2') 把这个操作放进已经存在的事务A里面
updete c set name = 'jary'; 把这个操作放进已经存在的事务A里面
delete c where name ='tom1' 把这个操作放进已经存在的事务A里面
rollback; 回滚事务:让前面的DML操作都撤销
保存点:
insert into c values('tom1'); 产生一个事务A
insert into c values('tom2'); 把这个操作放进已经存在的事务A里面
insert into c values('tom3'); 把这个操作放进已经存在的事务A里面
insert into c values('tom4'); 把这个操作放进已经存在的事务A里面
savepoint a_point;
update c set name='jary'
where name='tom3'; 把这个操作放进已经存在的事务A里面
delete c where name ='tom1'; 把这个操作放进已经存在的事务A里面
savepoint b_point;
insert into c values('tom5'); 把这个操作放进已经存在的事务A里面
insert into c values('tom6'); 把这个操作放进已经存在的事务A里面
回滚到:
rollback to 保存点;
eg: rollback to a_point;
MYSQL 事务处理主要有两种方法:
用 begin,rollback,commit 来实现
begin; 开始一个事务
rollback; 事务回滚
commit; 事务确认
直接用 set 来改变 mYsql 的自动提交模式
set autocommit=0; 禁止自动提交
set autocommit=1; 开启自动提交
6. 事务隔离级别
事务并发访问中产生的问题:
1.脏读 主要针对update操作。 一个事务A读到另一个事务B中修改过但是还没有提交的数据
测试:
产生脏读:没有效果可以重开两个控制台.
A控制台 :
1set autocommit=0;
2set session transaction isolation level read uncommitted;
3start transaction;
7update s_emp set last_name ='V1' where id = 1;
B控制台 :
4set session transaction isolation level read uncommitted;
5start transaction;
6select id,last_name from s_emp;
8select id,last_name from s_emp;
在B控制台看到了A控制台修改但是没有提交的数据
避免脏读:没有效果可以重开两个控制台.
A控制台 :
1set autocommit=0;
2set session transaction isolation level read committed;
3start transaction;
7update s_emp set last_name ='V2' where id = 1;
B控制台 :
4set session transaction isolation level read committed;
5start transaction;
6select id,last_name from s_emp;
8select id,last_name from s_emp;
在B控制台没有看到了A控制台修改但是没有提交的数据
2.不可重复读 主要针对update操作。
一个事务A在第一次读数据和第二次读数据之间,有另一个事务B把这个数据更改并提交了,
所以就出现了事务A里面读一个数据俩次,但是读到的结果是不同的。
测试:
产生不可重复读:没有效果可以重开两个控制台.
A控制台 :
1set autocommit=0;
2set session transaction isolation level read uncommitted;
4start transaction;
7update s_emp set last_name ='V3' where id = 1;
8commit;
B控制台 :
3set session transaction isolation level read uncommitted;
5start transaction;
6select id,last_name from s_emp where id < 3;
9select id,last_name from s_emp where id < 3;
在B控制台看到了A控制台修改并且提交的数据.
避免不可重复读:没有效果可以重开两个控制台.
A控制台 :
1set autocommit=0;
2set session transaction isolation level repeatable read;
4start transaction;
7update s_emp set last_name ='V4' where id = 1;
8commit;
B控制台 :
3set session transaction isolation level repeatable read;
5start transaction;
6select id,last_name from s_emp where id < 3;
9select id,last_name from s_emp where id < 3;
在B控制台看到了还是和步骤6查询数据一样,并没有看到步骤7的更新数据,成功避免了不可重复读
3.幻读 主要针对的是insert/delete操作。
事务A第一次用where条件筛选出了10条数据,
事务A第二次用通样的where条件筛选出的却是11条数据,
因为事务B在事务A的第一次和第二次查询直接进行了插入操作,
并且插入的这个数据满足事务A的where筛选条件.
测试:
产生幻读:没有效果可以重开两个控制台.
A控制台 :
1set autocommit=0;
2set session transaction isolation level read uncommitted;
4start transaction;
7insert into s_emp(id,last_name) values(140,'t140');
8commit;
B控制台 :
3set session transaction isolation level read uncommitted;
5start transaction;
6select id,last_name from s_emp where id >100 3;
9select id,last_name from s_emp where id >100 3;
在B控制台看到了A控制台insert并且提交的数据.发生了幻影读
避免幻读:没有效果可以重开两个控制台.
A控制台 :
1set autocommit=0;
2set session transaction isolation level serializable;
4start transaction;
7insert into s_emp(id,last_name) values(141,'t141');
当执行该步骤的时候,A控制台会一直卡着不动了.成功避免了幻读问题.
B控制台 :
3set session transaction isolation level serializable;
5start transaction;
6select id,last_name from s_emp where id >100;
MySQL 数据库提供的四种隔离级别:InnoDB 存储引擎提供事务的隔离级别有 read uncommitted、read committed、repeatable read和 serializable。
Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
Repeatable read (可重复读):可避免脏读、不可重复读的发生。
Read committed (读已提交):可避免脏读的发生。
Read uncommitted (读未提交):最低级别,任何情况都无法保证。
以上四种隔离级别最高的是 Serializable 级别,最低的是 Read uncommitted 级别,当然级别越高,执行效率就越低。像 Serializable 这样的级别,就是以锁表的方式(类似于 Java 多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。在 MySQL 数据库中默认的隔离级别为 Repeatable read (可重复读)。
在 MySQL 数据库中,支持上面四种隔离级别,默认的为 Repeatable read (可重复读);而在 Oracle 数据库中,只支持 Serializable (串行化)级别和 Read committed (读已提交)这两种级别,其中默认的为 Read committed 级别。
Repeatable-read 是 MySQL 的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。
不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB 和 Falcon 存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
在 MySQL 数据库中查看当前事务的隔离级别:select @@tx_isolation;
在 MySQL 数据库中设置事务的隔离级别:
set [glogal|session] transaction isolation level 隔离级别名称;
set tx_isolation=’隔离级别名称’;
总结
以上就是mysql学习day05啦,希望能够帮到大家