012、MySQL事务基础
本文最后更新于 393 天前,其中的信息可能已经过时,如有错误请发送邮件到 wuxianglongblog@163.com

MySQL 事务基础

一、事务简介

  事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有操作作为一个整体一起向系统提交或者撤销操作请求,即这些操作要么同时成功,要么同时失败。mysql 的事务默认是自动提交的,也就是说,当执行一条 DML 语句,Mysql 会立即隐式的提交事务

二、事务操作

  2.1 查看事务提交方式  

select@@autocommit;

  2.2 设置事务提交方式

 set @@autocommit=0;

    说明:如果值为 1,就是自动提交,为 0 就是手动提交

  2.3 提交事务 

commit;

  2.4 回滚事务   

rollback;

  2.5 开启事务  

start transaction 或者 begin

三、事务的四大特性

  • 原子性(Atomicity):事务是不可分割的最小单元,要么全部成功,要么全部失败
  • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态
  • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发影响的独立环境下运行
  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的

四、事务的并发问题

  • 脏读:一个事务读到另外一个还未提交的事务中修改的数据。
  • 不可重复读:一个事务读取到了另一个已经提交了事务中的修改的数据。即一个事务先后读取同一条记录,但两次读取的数据不同,第一次读取的是原始数据,第二次读取到了其他已经提交的事务中修改的数据,所以会出现两次读取到不一致的数据,这就叫不可重复读
  • 幻读:一个事务在未提交之前读取不到其他任何事务对数据的修改,包括提交和未提交的事务。即一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在了,好像出现了一个幻影。

五、事务隔离级别

  • read uncommitted: 脏读 (会出现)、不可重复读 (会出现)、幻读 (会出现)
  • read committed: 脏读 (不会出现)、不可重读读 (会出现)、幻读 (会出现)
  • repeatable read (mysql 默认):脏读 (不会出现)、不可重读度 (不会出现)、幻读 (会出现)
  • serializable:脏读 (不会出现)、不可重复读 (不会出现)、幻读 (不会出现)

  

  5.1 查看事务的隔离级别

select @@transaction_isolation;

  5.2 设置事务隔离级别

set [session|global] transaction isolation level {read uncimmitted | read committed | repeatable read | serializable};

  说明 1:session :设置仅对当前对话起作用

  说明 2:global :设置对全局都有用

六、事务的演示

  6.1 案例使用的 accout 表结构及数据

mysql> select * from account;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 2000 |
| 2 | 李四 | 2000 |
+----+--------+-------+
2 rows in set (0.00 sec)

  6.2 案例 1:

    需求 1:模拟转账业务创建一个 account 表,里面有张三、李四两个人,初始金额都有两千元,现在需求让张三转账 1000 元给李四

    第一步:张三的账户余额减 1000

mysql> update account set money = money - 1000 where name="张三";
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

    查询张三、李四的账户余额,验证现在余额的变化

mysql> select * from account;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 1000 |
| 2 | 李四 | 2000 |
+----+--------+-------+
2 rows in set (0.00 sec)

    说明:此时张三的账户已经减去 1000 了,但是李四的账户还没有增加 1000

    第二步:李四的账户余额加 1000

mysql> update account set money = money + 1000 where name="李四";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

    查询张三、李四的账户余额,验证现在余额的变化

mysql> select * from account;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 1000 |
| 2 | 李四 | 3000 |
+----+--------+-------+
2 rows in set (0.00 sec)

    说明:这个时候李四的账户上也已经增加了 1000 元,所以这个转账分为了两步实现。

  6.3 案例 2

    异常案例展示:异常说明,如果这个时候在执行完第一步,张三的账户已经减少了 1000 元,但是系统出问题了,李四的账户上并没有增加 1000, 这样就出现了异常。

    在进行异常展示之前,先把数据恢复成各自 2000 的余额

mysql> update account set money=2000;
Query OK, 2 rows affected (0.02 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> select * from account;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 2000 |
| 2 | 李四 | 2000 |
+----+--------+-------+
2 rows in set (0.00 sec)

    执行异常语句

    

img

   再来查询张三和李四的余额

mysql> select * from account;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 1000 |
| 2 | 李四 | 2000 |
+----+--------+-------+
2 rows in set (0.00 sec)

    说明:这时候张三的余额已经减去 1000, 但是李四的账户上却没有增加 1000, 这在显示中是绝对不允许的。

  6.4 案例 3

    使用事务完成,首先同样也是先还原数据,每个人的余额都是 2000 元

mysql> select * from account;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 2000 |
| 2 | 李四 | 2000 |
+----+--------+-------+
2 rows in set (0.02 sec)

    执行事务

    

img

   在验证这时张三和李四的余额

mysql> select * from account;
+----+--------+-------+
| id | name | money |
+----+--------+-------+
| 1 | 张三 | 2000 |
| 2 | 李四 | 2000 |
+----+--------+-------+
2 rows in set (0.00 sec)

    说明 1:在使用了事务后,会保证事务的原子性,即该事务内的语句要成功够成功,要失败在全部返回,不会存在部分 sql 执行成功的情况

七、脏读的案例    

  

img

  说明 1:首先将模拟客户端改为 read uncommitted 模式

  说明 2:客户端 1 和客户端 2 同时开启一个事务

  说明 3:在客户端 2 中修改 account 表中数据,但并不提交事务

  说明 4:在客户端 1 中读到了客户端 2 未提交的事务数据,即 read uncommitted 模式下会出现脏读。  

  

img

八、不可重复读的案例  

  

img

    说明 1:在 read committed 的隔离模式下

    说明 2:客户端 1 和客户端 2,同时开启一个事务

    说明 3:客户端 2 修改张三余额数据,客户端 1 未查询到客户端 2 未提交的修改,因为查询到就是脏读了

    说明 4:客户端 2 提交修改余额的事务,客户端 1 查询,此时查询到张三的余额数据已经修改,及在一个事务中可以查询到其他已经提交事务对数据的修改,而导致在一次事务中对不同数据查询到的值不一致这就是不可重复读。

    说明 5:在一个事务中查询到其他未提交的事务修改的数据叫脏读,查询到其他已经提交的事务修改的数据叫不可重复读

九、幻读的案例

  

img

 说明 1:多个事务并发时,一个事务新增了数据,并提交,在另外一个事务中查询不到,但是却也不能新增同样的数据,这就是幻读

谨此笔记,记录过往。凭君阅览,如能收益,莫大奢望。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇