MySQL数据库学习笔记——事务

事务

概述:在实际的开发过程中,一个业务操作如:转账,往往是要多次访问数据库才能完成的。转账是一个用户扣 钱,另一个用户加钱。如果其中有一条 SQL 语句出现异常,这条 SQL 就可能执行失败。事务执行是一个整体,所 有的 SQL 语句都必须执行成功。如果其中有 1 SQL 语句出现异常,则所有的 SQL 语句都要回滚,整个业务执行 失败。
模拟银行转账:
创建表
CREATE TABLE account (
  id INT ( 10 ) AUTO_INCREMENT PRIMARY KEY ,
  name VARCHAR ( 10 ),
  balance DOUBLE
) engine=innodb default charset=utf8;
# 添加数据
INSERT INTO account (name, balance) VALUES ( ' 张三 ' , 1000 ), ( ' 李四 ' , 1000
假设,张三给李四转账200元
张三账号+200
update account set balance = balance ­ -  200 where name= ' 张三 ' ;
李四账号+200
update account set balance = balance + 200 where name= ' 李四 ' ;
数据正常情况下,完成两条语句不会发生任何问题,但是,假设当张三账号上 -200 , 服务器崩溃了。李四的账号并没有+200 元,数据就出现问题了。我们需要保证其中一条 SQL 语句出现问题,整个转账就算失败。只有两条
SQL 都成功了转账才算成功。这个时候就需要用到事务。

MySQL中事物的提交方式

原理:事务开启之后 , 所有的操作都会临时保存到事务日志中 , 事务日志只有在得到 commit 命令才会同步到数据表中,其他任何情况都会清空事务日志(rollback ,断开连接 )
①手动提交
SQL 语句:
 
功能SQL语句
开启事务start transaction;
提交事务commit;
回滚事务rollback;

②手动提交

手动提交事务

执行过程:开启事务 --> 执行多条 SQL 语句 --> 成功提交事务 ( 失败事务的回滚 )
如下图所示:
代码展示:
数据库内容

 提交事务步骤:

①使用 DOS 控制台进入 MySQL;
②执行以下 SQL 语句: 1. 开启事务, 2. 张三账号 -200 3. 李四账号 +200;
③ 使用 Navicat 查看数据库:发现数据并没有改变 ;
④在控制台执行 commit 提交事务 ;
⑤使用 Navicat 查看数据库:发现数据改变 .
过程截图:
Win+R 进入 cmd ,输入如下命令进入数据库

 

 ②开启事务

③选择数据库并执行SQL语句

 ④查询数据库中数据

⑤通过Navicat工具查看表中数据 

上述内容可以发现,两条语句还没有提交,只是执行完成了

⑥提交之后查看数据

 

⑦通过navicat工具查看表中数据 

回滚事务步骤:
①在控制台执行以下 SQL 语句: 1. 开启事务, 2. 张三账号 -200 ,李四账号 +200;
②使用 Navicat 查看数据库:发现数据并没有改变 ;
③在控制台执行 rollback 回滚事务 ;
④在 dos 界面查看数据库:发现数据回滚到开启事务时的状态;使用 Navicat 查看数据库:发现数据没有改变 .
过程截图:
数据库内容

 

执行过程 

navicat结果展示

 回滚事务

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

事务回滚点

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

设置回滚点  savepoint 名字

回到回滚点 rollback to 名字

代码演示:
①将数据还原到 1000 ,开启事务
②让张三账号减 3 次钱,每次 10
③设置回滚点: savepoint three_times;
④让张三账号减 3 次钱,每次 10
⑤回到回滚点: rollback to three_times;

 

事务的四大特征(ACID)

 

特征

含义

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

事务的隔离级别

事务在操作时的理想状态:所有的事务之间保持隔离,互不影响。因为并发操作,多个用户同时访问同一个数据。可能引发并发访问 的问题:
并发的访问问题含义
脏读
一个事务读取到了另一个事务中尚未提交的数据
不可重复读
一个事务先后执行同一条 SQL ,但两次读取到的数据不同,就是不可重复读,这是事务 update 时引发的问题
幻读
在一个事务中明明没有查到主键为 X 的数据,但主键为 X 的数据就是插入不进去,这是insert 或 delete 时引发的问题

不可重复读和脏读的区别

脏读可以读到其他事务中未提交的数据,而不可重复读是读取到了其他事务已经提交的数据,但前后两次读取的结果不同。

不可重复读和幻读的区别:

二者描述的侧重点不同,不可重复读描述的侧重点是修改操作,而幻读描述的侧重点是添加或删除操作 MySQL 中隔
离级别可能引发的问题。
MySQL 中事务的隔离级别有以下 4 种:
1. 读未提交( READ UNCOMMITTED
2. 读已提交( READ COMMITTED
3. 可重复读( REPEATABLE READ
4. 序列化(SERIALIZABLE)
READ UNCOMMITTED
读未提交,也叫未提交读,该隔离级别的事务可以看到其他事务中未提交的数据。该隔离级别因为可以读取到其他事务中未提交的数据,而未提交的数据可能会发生回滚,因此我们把该级别读取到的数据称之为脏数据,把这个问题称之为脏读。
READ COMMITTED
读已提交,也叫提交读,该隔离级别的事务能读取到已经提交事务的数据,因此它不会有脏读问题。但由于在事务的执行中可以读取到其他事务提交的结果,所以在不同时间的相同 SQL 查询中,可能会得到不同的结果,这种现象叫做不可重复读。
REPEATABLE READ
可重复读,是 MySQL 的默认事务隔离级别,它能确保同一事务多次查询的结果一致。但也会有新的问题,比如此级别的事务正在执行时,另一个事务成功的插入了某条数据,但因为它每次查询的结果都是一样的,所以会导致查询不到这条数据,自己重复插入时又失败(因为唯一约束的原因)。明明在事务中查询不到这条信息,但自己就是插入不进去,这就叫幻读。
SERIALIZABLE
序列化,事务最高隔离级别,它会强制事务排序,使之不会发生冲突,从而解决了脏读、不可重复读和幻读问题,但因为执行效率低,所以真正使用的场景并不多

事务隔离级别
脏读不可重复读幻读
读未提交(read-uncommitted)
读已提交(read-committed)
可重复读(repeatable-read)
串行化(serializable)
测试:
查看事务隔离级别:
SELECT @@GLOBAL .tx_isolation , @@tx_isolation;
设置事务隔离级别:
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
读未提交:
删除 account 数据表并重建:
drop table account;
CREATE TABLE account (
id INT ( 10 ) AUTO_INCREMENT PRIMARY KEY ,
name VARCHAR ( 10 ),
balance DOUBLE
) engine=innodb default charset=utf8;
初始化两条数据:
INSERT INTO account (name, balance) VALUES ( ' 张三 ' , 1000 ), ( ' 李四 ' , 1000
两个人的账户各有 1000 人民币,现在模拟这两个用户之间的一个转账操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值