事务

事务概念

一个事务是由一条或者多条对数据库操作的SQL语句所组成的一个不可分割的单元,只有当事务中的所有操作都正常执行完了,整个事务才会被提交给数据库;如果有部分事务处理失败,那么事务就要回退到最初状态,因此,事务要么全部执行成功,要么全部失败。

事务的几个概念如下:

  1. 事务是一组SQL语句的执行,要么全部成功,要么全部失败,不能出现部分成功,部分失败的结果,保证事务执行的原子操作。
  2. 事务的所有SQL语句全部执行成功,才能提交(commit)事务,把结果写回磁盘上。
  3. 事务执行过程中,有的SQL出现错误,那么事务必须要回滚(rollback)到最初的状态。

MyISAM:不支持事务
InnoDB:支持事务、支持行锁

比如银行转账就要用到事务。总不能让钱越转越少吧hhh。

ACID特征

原子性(Atomic):不允许事务部分完成。
一致性(Consistency):一个事务执行之前和执行之后,数据库数据必须保持一致性的状态。数据库的一致性必须由用户来负责,由并发控制机实现。维持总状态不变。
隔离性(Isolation):当两个或多个事务并发执行时,为了保证数据的安全性,将一个事务内部的操作与其它事务的操作隔离起来,不被其它正在执行的事务所看到,使得并发执行的各个事务之间不能互相影响。
持久性(Durability):事务完成后,DBMS保证它对数据库中的数据的修改是永久的,即使数据库因为故障出错,也应该能够恢复数据。

db写数据 =》cache缓存 =》磁盘I/O 有日志做保障。

事务并发存在的问题

事务处理不经隔离,并发执行通常会有以下问题:
脏读(Dirty Read):事务B读取了事务A尚未提交的数据。
不可重复读(NonRepeatable Read):事务B两次读之间事务A更新了数据。B读取了A已提交的数据。
虚读(Phantom Read)幻读:事务B先查询,A新增或删除了一条满足B查询条件的记录,B再查询。(B读了A新增的;或没读到A删除的)

事务处理命令

SELECT @@AUTOCOMMIT; 查看MySQL是否自动提交事务

0表示手动提交事务,1表示自动提交事务,设置事务提交方式为手动提交方式:

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
BEGIN; 开启一个事务
COMMIT; 提交一个事务
ROLLBACK; 回滚一个事务到初始的位置
SAVEPOINT point1; 设置一个名字为point1的保存点
ROLLBACK TO point1; 事务回滚到保存点point1,而不是回滚到初始状态
SET TX_ISOLATION='REPEATABLE-READ'; 设置事务的隔离级别
SELECT @@ TX_ISOLATION; 查询事务的隔离级别

事务的隔离级别

简要概述

TRANSACTION_READ_UNCOMMITTED 未提交读
TRANSACTION_READ_COMMITTED 已提交读
TRANSACTION_REPEATABLE_READ 可重复读
TRANSACTION_SERIALIZABLE 串行化

隔离级别 脏读 不可重复读 幻读
未提交读 可以 可以 可以
已提交读 不可以 可以 可以
可重复读 不可以 不可以 可以
串行化 不可以 不可以 不可以

把手动提交事务的设置打开:

set autocommit=0;

查询事务的隔离级别,看到MySQL默认是在可重复读级别(只允许幻读)

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)

实验

未提交读

开两个窗口,同时使用user表。都设置成最低级别:

set tx_isolation='READ-UNCOMMITTED';

A 回滚了

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update user set age=21 where name='zhang san';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user where name='zhang san';
+----+-----------+-----+-----+
| id | name      | age | sex |
+----+-----------+-----+-----+
|  4 | zhang san |  20 | M   |
+----+-----------+-----+-----+
1 row in set (0.00 sec)

B 读到了A未提交的数据,并把其拿去做业务了 脏读

mysql> select * from user where name='zhang san';
+----+-----------+-----+-----+
| id | name      | age | sex |
+----+-----------+-----+-----+
|  4 | zhang san |  21 | M   |
+----+-----------+-----+-----+
1 row in set (0.00 sec)

已提交读

set tx_isolation='READ-COMMITTED';

禁止了脏读
A 的过程

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update user set age=20 where name='zhang san';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

B在A未提交时不会产生脏读,会产生可重复读

mysql> select * from user where name='zhang san';
+----+-----------+-----+-----+
| id | name      | age | sex |
+----+-----------+-----+-----+
|  4 | zhang san |  21 | M   |
+----+-----------+-----+-----+
1 row in set (0.00 sec)

A提交后,B查询到了新的数据

mysql> select * from user where name='zhang san';
+----+-----------+-----+-----+
| id | name      | age | sex |
+----+-----------+-----+-----+
|  4 | zhang san |  20 | M   |
+----+-----------+-----+-----+
1 row in set (0.00 sec)

可重复读

A

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update user set age=21 where name='zhang san';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

B 在A commit后任然查不到更新的数据,禁止了不可重复读

mysql> select * from user where name='zhang san';
+----+-----------+-----+-----+
| id | name      | age | sex |
+----+-----------+-----+-----+
|  4 | zhang san |  20 | M   |
+----+-----------+-----+-----+
1 row in set (0.00 sec)

幻读

表面上幻读不存在,但是有幻读
A 往表里插入一条数据

mysql> insert into user(name,age,sex) values('tt',21,'W');
Query OK, 1 row affected (0.00 sec)

B 表面上查询不到

mysql> select * from user where age=21;
+----+-----------+-----+-----+
| id | name      | age | sex |
+----+-----------+-----+-----+
|  4 | zhang san |  21 | M   |
|  5 | li si     |  21 | W   |
|  7 | zhang ai  |  21 | W   |
|  8 | wu liu    |  21 | M   |
+----+-----------+-----+-----+
4 rows in set (0.00 sec)

但是 B 能够修改这条数据

mysql> update user set age=22 where name='tt';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
暂无评论

发送评论 编辑评论


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