【61-70】事务
2022-02-14 11:06:00 # MySQL

概述

什么是事务

  1. 一个事务时一个完整的业务逻辑单元,不可再分
  2. 比如转账一方+100,另一方-100,两个update操作不可分,所以这两条DML语句同时成功或者同时失败,使用事务来实现

事务作用

  1. 和事务相关的语句只有:DML语句(insert delete update)
  2. 保证数据完整性,安全性

事务特性

  1. ACID 四大特性
  2. A 原子性:事务时最小的工作单元,不可再分
  3. C 一致性:事务必须保证多条DML语句同时成功或者同时失败
  4. I 隔离性:事务A与事务B之间具有隔离
  5. D 持久性:最终数据必须持久化到硬盘文件中

事务的隔离性

  • 事务隔离性存在隔离级别,理论上隔离级别包括4个
  1. 第一级别:读未提交(read uncommitted)
    对方事务未提交,当前事务可以读取到对方未提交的数据
    读未提交存在脏读(Dirty Read)现象:读到脏数据
  2. 第二级别:读已提交(read committed)
    对方事务提交之后的数据我方可以读到
    这种级别解决了脏读现象
    读已提交存在的问题是:不可重复读
    不可重复读就是读表的结果不确定,可能在不同时间读到的结果不同
  3. 第三级别:可重复读(repeatable read)
    解决了不可重复读问题
    这种级别存在的问题:读取到的数据是幻象
  4. 第四级别:序列化读/串行化读(serializable)
    解决了所有问题,但效率低,需要事务排队
  5. Oracle默认是:读已提交
  6. MySQL默认是:可重复读

演示事务

  • MySQL默认情况下是自动提交的,自动提交就是执行任意一条DML语句就提交一次
  • start transaction 关闭自动提交

未关闭自动提交

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
drop table if exists t_user;
create table t_user(
id int primary key auto_increment,
name varchar(255)
);
insert into t_user(name) values('zs');
select * from t_user;
rollback;
select * from t_user;

mysql> drop table if exists t_user;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> create table t_user(
-> id int primary key auto_increment,
-> name varchar(255)
-> );
Query OK, 0 rows affected (0.03 sec)

mysql> insert into t_user(name) values('zs');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t_user;
+----+------+
| id | name |
+----+------+
| 1 | zs |
+----+------+
1 row in set (0.00 sec)

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

mysql> select * from t_user;
+----+------+
| id | name |
+----+------+
| 1 | zs |
+----+------+
1 row in set (0.00 sec)

关闭自动提交

  • rollback 后事务结束,要再次开启需要重新 start transaction
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    start transaction;
    insert into t_user(name) values('li');
    select * from t_user;
    rollback;
    select * from t_user;

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

    mysql> insert into t_user(name) values('li');
    Query OK, 1 row affected (0.00 sec)

    mysql> select * from t_user;
    +----+------+
    | id | name |
    +----+------+
    | 1 | zs |
    | 2 | li |
    +----+------+
    2 rows in set (0.00 sec)

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

    mysql> select * from t_user;
    +----+------+
    | id | name |
    +----+------+
    | 1 | zs |
    +----+------+
    1 row in set (0.00 sec)

手动提交

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
start transaction;
insert into t_user(name) values('xx');
insert into t_user(name) values('yy');
select * from t_user;
commit;
rollback;
select * from t_user;

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

mysql> insert into t_user(name) values('xx');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_user(name) values('yy');
Query OK, 1 row affected (0.00 sec)

mysql> select * from t_user;
+----+------+
| id | name |
+----+------+
| 1 | zs |
| 3 | xx |
| 4 | yy |
+----+------+
3 rows in set (0.00 sec)

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

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

mysql> select * from t_user;
+----+------+
| id | name |
+----+------+
| 1 | zs |
| 3 | xx |
| 4 | yy |
+----+------+
3 rows in set (0.00 sec)

相关命令

1
2
3
4
-- 设置 全局 事务 隔离 级别 读未提交  
set global transaction isolation level read uncommitted;
-- 查看全局事务隔离级别
select @@global.transaction_isolation;
Prev
2022-02-14 11:06:00 # MySQL
Next