08.事物

事物

事务执行是一个整体,所有的 SQL 语句都必须执行成功。如果其中有 1 条 SQL 语句出现异常,则所有的SQL 语句都要回滚,整个业务执行失败。

MySQL有两种方式进行事物操作

  1. 手动提交事物【Oracle默认】
  2. 自动提交事物【MySQL默认】

一、手动提交事物

  1. 开启事物: start transaction;
  2. 提交事物: commit;
  3. 回滚事物: rollback;

1.手动提交事物的使用过程

  • 成功执行的情况:开启事物--执行多条SQL语句--成功提交事物
start transaction;
update account set balance = balance - 500 where name = '张三';
update account set balance = balance + 500 where name = '李四';
commit;
  • 执行失败的情况:开启事物--执行多条SQL语句--事物的回滚【清空日志,数据没有被改!】
start transaction;
update account set balance = balance - 500 where name = '张三';
update account set balance = balance + 500 where name = '李四';
rollback ;

总结: 如果事务中 SQL 语句没有问题,commit 提交事务,会对数据库数据的数据进行改变。 如果事务中 SQL语句有问题,rollback 回滚事务,会回退到开启事务时的状态。

二、自动提交事物的过程

MySQL默认每一条DML(增删改)语句都是一个单独的事物,每条语句都会自动开启一个事物,语句执行完毕自动提交事物,MySQL默认开始自动提交事物

1. 取消自动提交事物

  • 查看MySQL是否开启自动提交事物
select @@autocommit;

@@var 表示全局变量,@@autocommit=1表示开启自动提交事务,0表示关闭

  • 取消自动提交事务【只针对于当前连接--日志!】【需要手动commit;才能提交申请】
set @@autocommit = 0;

当前连接查询会经过当前连接日志处理,并不一定代表数据库中数据的真正改变!

三、事务原理

事务开启之后, 所有的操作都会临时保存到事务日志中, 事务日志只有在得到 commit 命令才会同步到数据表中,其他任何情况都会清空事务日志(rollback,断开连接)

1.事务原理图


事务原理图.png

2.事务的步骤

  1. 客户端连接数据库服务器,创建连接是创建此用户临时日志文件
  2. 开启事物以后,所有的操作都会先写入到临时日志文件中
  3. 所有的查询操作从表中查询,但会经过日志文件加工后才返回
  4. 如果事物提交则将日志文件中的数据写到表中,否则清空日志文件。

四、回滚点

在某些成功的操作完成之后,后续的操作有可能成功也有可能失败,但是不管成功还是失败,前面的操作都已经成功,可以在当前成功的位置设置一个回滚点。可以供后续失败操作返回到该位置,而不是返回所有操作,这个点称之为回滚点。

1. 回滚点操作语句

回滚点的操作语句 语句
设置回滚点 savepoint 名字
回到回滚点 rollback to 名字
  • 操作流程【在@@autocommit=0的情况下操作,非自动提交事务的情况下】
# 开启事务
start transaction;

# 执行更新操作
...

# 设置回滚点
savepoint three_times;

# 继续操作
...

# 回退到回滚点
rollback to three_times;

# 提交事务
commit;

总结:设置回滚点可以让我们在失败的时候回到回滚点,而不是回到事务开启的时候。

五、事务的隔离级别

1.事务的四大特性

事务特性 含义
原子性(Atomicity ) 每个事务都是一个整体,不可再拆分,事务中所有的 SQL 语句要么都执行成功,要么都失败。
一致性(Consistency ) 事务在执行前数据库的状态与执行后数据库的状态保持一致。如:转账前2 个人的总金额是 2000 ,转账后 2 个人总金额也是 2000
隔离性(Isolation ) 事务与事务之间不应该相互影响,执行时保持隔离的状态。
持久性(Durability ) 一旦事务执行成功,对数据库的修改是持久的。就算关机,也是保存下来的。

2.事务的隔离级别

事务在操作时的理想状态: 所有的事务之间保持隔离,互不影响。因为并发操作,多个用户同时访问同一个数据。可能引发并发访问的问题:

并发访问的问题 含义
脏读 一个事务读取到了另一个事务中尚未提交的数据
不可重复读 事务update时引发的问题:一个事务中两次读取的数据内容不一致,要求的是一个事务中多次读取时数据是一致的
幻读 insert或delete时引发的问题,一个事务中两次读取的数据的数量不一致,要求在一个事务多次读取的数据的数量是一致的

3.MySQL数据可以四种隔离级别

隔离级别越高,性能越差,安全性越高。

上面的级别最低,下面的级别最高。“是”表示会出现这种问题,“否”表示不会出现这种问题。

级别 名字 隔离级别 脏读 不可重复读 幻读 数据库默认隔离级别
1 读未提交 read uncommitted
2 读已提交 read committed Oracle和SQL Server
3 可重复读 repeatable read 是(MySQL InnoDB引擎已经解决此问题-间歇锁)) MySQL【查询select @@tx_isolation】
4 串行化 serializable

4.MySQL事务隔离级别相关的命令

  • 查询全局事务隔离级别
select @@tx_isolation
  • 设置数据隔离级别,需要退出登录才能开到隔离级别的变化
set global transaction isolation level 级别字符串;

六、并发问题演示!

1.脏读演示

【级别最低时,commit前,数据已经写入数据库!】read uncommitted 脏读!

《后期更新...》

【事务开始时,commit前,先将未提交的数据放在日志中,commit后才将数据放入库中】结论:read committed 的方式可以避免脏读的发生

2.不可重读演示

《后期更新...》

【事务开始时,commit前,第一次查询的结果会保留在日志中,后续查询会使用这个值,直到commit后才会再次访问数据库】结论:同一个事务中为了保证多次查询数据一致,必须使用 repeatable read 隔离级别

3.幻读演示

呵呵,MySQL中无法看到幻读的效果!

《后期更新...》

【事务开始时,commit前,如果当前没有commit操作,访问本次涉及到的数据的其他线程或进程会被阻塞】结论:使用 serializable 隔离级别,一个事务没有执行完,其他事务的 SQL 执行不了,可以挡住幻读

你可能感兴趣的:(08.事物)