欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SQL学习笔记08-- 事务

程序员文章站 2024-01-13 20:05:40
...

事务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');--报错,无法插入数据
--此时发现读取不到插入的数据,但是在插入的时候不允许插入,出现了幻读,设置更高级别的隔离级别即可解决

总结:

现在学习的是数据库级别的事务,需要掌握的就是事务的隔离级别和产生的数据不一致的情况

后续会学习声明式事务及事务的传播特性以及分布式事务

相关标签: transaction