MySQL-事务

目录

事务简介

事务操作

事务四大特性ACID

并发事务问题

1.脏读

2.不可重复读

3.幻读

事务隔离级别

1.读未提交Read uncommitted

2.读已提交Read committed

3.可重复读Repeatable Read(默认)

4.串行化Serializable

隔离级别与一致性的关系


事务简介

事务是一组操作的集合,它是一个不可分割的工作单元,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败

一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成

事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同

就比如用户1需要向用户2转账100元

actno  balance
 1       500
 2       100
进行转账操作:
update t_act set balance=400 where actno=1;
update t_act set balance=200 where actno=2;
  • 以上两台DML语句必须同时成功或者同时失败
  • 最小单元不可再分,当第一条DML语句执行成功后, 并不能将底层数据库中的第一个账户的数据修改,只是将操作记录了一下
  • 这个记录是在内存中完成的,当第二条DML语句执行成功后,和底层数据库文件中的数据完成同步
  • 若第二条DML语句执行失败,则清空所有的历史操作记录,要完成以上的功能必须借助事务

注意:默认MySQL的事务是自动提交的,也就是说,当执行完一条DML语句时,MySQL会立即隐式的提交事务

事务操作

1.查看/设置事务提交方式

SELECT @@autocommit ;

SET @@autocommit = 0 ;

2.开启事务

START TRANSACTION 或 BEGIN ;

3.提交事务

COMMIT;

4.回滚事务

ROLLBACK;

案例:

(1)提交操作---无事务成功

update t_act set balance=400 where actno=1;
update t_act set balance=200 where actno=2;

 

(2)提交操作---无事务失败

update t_act set balance=400 where actno=1;
update t_act set balance=200 where actno=2w;

(3)提交操作---事务成功

start transaction;#手动开启事务
update t_act set balance=400 where actno=1;
update t_act set balance=200 where actno=2;
commit;#commit之后即可改变底层数据库数据

(4)提交操作---事务失败

start transaction;#手动开启事务
update t_act set balance=400 where actno=1;
update t_act set balance=200 where actno=2w; #这个地方故意让第二个语句出错
commit;#commit之后即可改变底层数据库数据

 

(5)回滚操作---事务失败

start transaction; #开启事务
update act set money = 0 where name = '张三';
update act set money = 200 where name = '李四';
-- 假设这里出现了错误,可以回滚事务
ROLLBACK;
-- 如果没有错误,可以提交事务
COMMIT;

事务四大特性ACID

1.原子性Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败

当事务发现有些语句不能执行时,需要将数据恢复到事务执行前,通过undo log实现

undo log是mysql中比较重要的事务日志之一,顾名思义,undo log是一种用于撤销回退的日志, 在事务没提交之前,MySQL会先记录更新前的数据到 undo log日志文件里面, 当事务回滚时或者数据库崩溃时,可以利用 undo log来进行回退

2.一致性Consistency):事务完成时,必须使所有的数据都保持一致状态

原子性、持久性和隔离性,都是为了保证数据库状态的一致性

3.隔离性(Isolation):事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰

与原子性、持久性侧重于研究事务本身不同,隔离性研究的是不同事务之间的相互影响

4.持久性Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的

持久性问题的产生:

背景:Mysql为了保证存储效率,每次读写文件都是先对缓存池(Buffer Pool)操作, 缓冲池再定期刷新到磁盘中(这一过程称为刷脏)

产生:由于数据不是直接写到磁盘,那么如果主机断电,就会有一部分数据丢失

解决:通过重做日志(redo log)恢复数据。在每次修改数据之前, 都会将相应的语句写到redo log中,如果主机断电,那么再次启动时可通过redo log恢复

拓展:redo log也需要在事务提交时将日志写入磁盘,它比缓冲池写入快的原因有两点:redo log是追加文件写,属于顺序IO,缓冲池是属于随机IO,且刷脏是以页为单位, 有一点修改就要整页写入

并发事务问题

1.脏读

一个事务读到另外一个事务修改但还没有提交的数据

2.不可重复读

一个事务先后读取同一条记录,但两次读取的数据不同

3.幻读

在一个事务中,多次查询同一个范围的数据,却发现有新增或者减少的行。这是因为在这个事务进行的过程中,另一个事务插入或者删除了符合查询条件的数据,导致前后两次查询结果不一致

事务隔离级别

为了解决并发所产生的问题,在数据库中引入了事务的隔离级别,隔离级别越高,数据越安全,但是性能越低,解决并发产生的问题越多

1.读未提交Read uncommitted

  • 事物A和事物B,事物A未提交的数据,事物B可以读取到
  • 这种隔离级别最低,这种级别一般是在理论上存在,数据库隔离级别一般都高于该级别
  • 三种并发问题都没解决

演示:

MySQL8中隔离级别的变量跟之前的版本不一样,之前是tx_isolation,MySQL8改成了transaction_isolation

#创建表:
create table t_user(id int primary key auto_increment,username varchar(255));

#设置读未提交的隔离级别
set global transaction isolation level read uncommitted;
#查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;

2.读已提交Read committed

  • 事物A和事物B,事物A提交的数据,事物B才能读取到
  • 这种隔离级别高于读未提交
  • 换句话说,只有对方事务提交之后的数据,当前事务才能读取到
  • 这种级别可以避免“脏数据”
  • 这种隔离级别会导致“不可重复读取”
  • Oracle默认隔离级别
#设置读已提交的隔离级别
set global transaction isolation level read committed;
#查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;

插入但没有提交是读不出来的,提交之后才能读出来

不可重复读和脏读的区别:脏读读取到的是一个未提交的数据,而不可重复读读取到的是前一个事务已提交的数据。 而不可重复读在一些情况也并不影响数据的正确性,比如需要多次查询的数据也是要以最后一次查询到的数据为主

3.可重复读Repeatable Read(默认)

  • 事务A和事务B,事务A提交之后的数据,事务B读取不到,事务B是可重复读取数据
  • 这种隔离级别高于读已提交
  • 换句话说,对方提交之后的数据,还是读取不到
  • 这种隔离级别可以避免“不可重复读取”,达到可重复读取,比如1点和2点读到数据是同一个
  • MySQL默认级别
  • 解决了 “不可重复读” 和 “幻读”
#设置可重复读的隔离级别
set global transaction isolation level repeatable read;
#查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;

无论是删除还是添加,commit后都是成功的,但是另一边却还是读出原来的数据,这就是可重复读,读取的是备份数据,不是真正的数据

4.串行化Serializable

  • 事务A和事务B,事务A在操作数据库时,事务B只能排队等待
  • 这种隔离级别很少使用,吞吐量太低,用户体验差
  • 这种级别可以避免“幻读”,每一次读取的都是数据库中真实存在数据,事务A与事务B串行, 而不并发
#设置串行化的隔离级别
set global transaction isolation level serializable;
#查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;

隔离级别与一致性的关系

上一篇:Kmeans聚类算法简述


下一篇:为什么要生成python项目需要的最小requirements.txt文件?