SQL学习笔记08-- 事务
事务transaction:
表示操作集合,不可分割,要么全部成功,要么全部失败
事务的开始取决于一个DML语句
事务的结束:
1、正常的commit(使数据修改生效)或者rollback(将数据恢复到上一个状态)
2、自动提交,但是一般情况下要将自动提交进行关闭,效率太低
3、用户关闭会话之后,会自动提交事务
4、系统崩溃或者断电的时候回回滚事务,也就是将数据恢复到上一个状态
▪ Commit: 表示事务成功地结束,此时告诉系统,数据库要进入一个新的正确状态,
该事务对数据库的所有更新都以交付实施。每个Commit语句都可以看成是一个事
务成功的结束,同时也是另一个事务的开始。
▪ Rollback表示事务不成功的结束,此时告诉系统,已发生错误,数据库可能处在
不正确的状态,该事务对数据库的更新必须被撤销,数据库应恢复该事务到初始
状态。每个Rollback语句同时也是另一个事务的开始。
一旦执行了commit语句,将目前对数据库的操作提交给数据库(实际写入DB),
以后就不能用rollback进行撤销。
insert into emp(empno,ename) values(7777,'asss');
commit;
select * from emp;
insert into emp(empno,ename) values(1234,'ghjn');
rollback;
select * from emp;
▪savepoint 保存点
--当一个操作集合中包含多条SQL语句,但是只想让其中某部分成功,某部分失败,此时可以使用保存点
--此时如果需要回滚到某一个状态的话使用 rollback to sp1;
--savepoint 保存点
--当一个操作集合中包含多条SQL语句,但是只想让其中某部分成功,某部分失败,此时可以使用保存点
--此时如果需要回滚到某一个状态的话使用 rollback to sp1;
delete from emp where empno = 1111;
delete from emp where empno = 2222;
savepoint sp1;
delete from emp where empno = 1234;
rollback to sp1;
commit;
事务的四个特性:ACID
1 原子性 Automicity:表示不可分割,一个操作集合要么全部成功,要么全部失败,不可以从中间做切分
2 一致性 consistency:最终是为了保证数据的一致性,当经过N多个操作之后,数据的状态不会改变(转账case)
从一个一致性状态到另一个一致性状态,也就是数据不可以发生错乱
3 隔离性 lsolation:各个事务之间相关不会产生影响,(隔离级别)
严格的隔离性会导致效率降低,在某些情况下为了提高程序的执行效率,需要降低隔离的级别
隔离级别:
读未提交
读已提交
可重复读
序列化
数据不一致的问题:
脏读
不可重复读
幻读
4 持久性 Durability:所有数据的修改都必须要持久化到存储介质中,不会因为应用程序的关闭而导致数据丢失
四个特性中,哪个是最关键的?
所有的特性中都是为了保证数据的一致性,所以一致性是最终的追求
事务中的一致性是通过原子性、隔离性、持久性来保证的
锁的机制:
为了解决在并发访问的时候,数据不一致的问题,需要给数据加锁
加锁的同时需要考虑《粒度》的问题:
操作的对象
数据库
表
行
一般情况下,锁的粒度越小,效率越高,粒度越大,效率越低 .
在实际的工作环境中,大部分的操作都是行级锁 .
mysql事务测试
1、打开mysql的命令行,将自动提交事务给关闭
--查看是否是自动提交 1表示开启,0表示关闭
select @@autocommit;
--设置关闭
set autocommit = 0;
2、数据准备
--创建数据库
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;
3、测试事务
--事务包含四个隔离级别:从上往下,隔离级别越来越高,意味着数据越来越安全 read uncommitted; --读未提交 read commited; --读已提交 repeatable read; --可重复读 (seariable) --序列化执行,串行执行 --产生数据不一致的情况: 脏读 不可重复读 幻读
隔离级别 | 异常情况 | 异常情况 | 异常情况 |
---|---|---|---|
读未提交 | 脏读 | 不可重复读 | 幻读 |
读已提交 | 不可重复读 | 幻读 | |
可重复读 | 幻读 | ||
序列化 |
4、测试1:脏读 read uncommitted
set session transaction isolation level read uncommitted;
A:start transaction;
A:select * from psn;
B:start transaction;
B:select * from psn;
A:update psn set name='msb';
A:selecet * from psn
B:select * from psn; --读取的结果msb。产生脏读,因为A事务并没有commit,读取到了不存在的数据
A:commit;
B:select * from psn; --读取的数据是msb,因为A事务已经commit,数据永久的被修改
5、测试2:当使用read committed的时候,就不会出现脏读的情况了,当时会出现不可重复读的问题
set session transaction isolation level read committed;
A:start transaction;
A:select * from psn;
B:start transaction;
B:select * from psn;
--执行到此处的时候发现,两个窗口读取的数据是一致的
A:update psn set name ='zhangsan' where id = 1;
A:select * from psn;
B:select * from psn;
--执行到此处发现两个窗口读取的数据不一致,B窗口中读取不到更新的数据
A:commit;
A:select * from psn;--读取到更新的数据
B:select * from psn;--也读取到更新的数据
--发现B在同一个事务中多次读取数据出现不一致的情况
6、测试3:当使用repeatable read的时候(按照上面的步骤操作),就不会出现不可重复读的问题,但是会出现幻读的问题
set session transaction isolation level repeatable read;
A:start transaction;
A:select * from psn;
B:start transaction;
B:select * from psn;
--此时两个窗口读取的数据是一致的
A:insert into psn values(4,'sisi');
A:commit;
A:select * from psn;--读取到添加的数据
B:select * from psn;--读取不到添加的数据
B:insert into psn values(4,'sisi');--报错,无法插入数据
--此时发现读取不到插入的数据,但是在插入的时候不允许插入,出现了幻读,设置更高级别的隔离级别即可解决
总结:
现在学习的是数据库级别的事务,需要掌握的就是事务的隔离级别和产生的数据不一致的情况
后续会学习声明式事务及事务的传播特性以及分布式事务