当前位置:   article > 正文

[MySQL][事务管理][中][事务常见操作方式]详细讲解

[MySQL][事务管理][中][事务常见操作方式]详细讲解


0.准备工作

# 为了便于演示,将mysql的默认隔离级别设置成读未提交。
mysql> set global transaction isolation level READ UNCOMMITTED;

# 需要重启终端,进行查看
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 简单银行用户表
    create table if not exists account(
    	id int primary key,
    	name varchar(50) not null default '',
    	blance decimal(10,2) not null default 0.0
    )ENGINE=InnoDB DEFAULT CHARSET=UTF8;
    
    • 1
    • 2
    • 3
    • 4
    • 5

1.操作演示

  • 正常演示 - 证明事务的开始与回滚
    -- 查看事务是否自动提交。故意设置成自动提交,看看该选项是否影响begin
    mysql> show variables like 'autocommit'; 
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | autocommit    | ON    |
    +---------------+-------+
    
    mysql> start transaction; -- 开始一个事务begin也可以,推荐begin
    mysql> savepoint save1; -- 创建一个保存点save1
    
    mysql> insert into account values (1, '张三', 100); -- 插入一条记录
    mysql> savepoint save2; -- 创建一个保存点save2
    
    mysql> insert into account values (2, '李四', 10000); -- 再插入一条记录
    mysql> select * from account; -- 两条记录都在了
    +----+--------+----------+
    | id | name   | blance   |
    +----+--------+----------+
    | 1  | 张三   | 100.00   |
    | 2  | 李四   | 10000.00 |
    +----+--------+----------+
    
    mysql> rollback to save2; -- 回滚到保存点save2
    mysql> select * from account; -- 一条记录没有了
    +----+--------+--------+
    | id | name   | blance |
    +----+--------+--------+
    | 1  | 张三   | 100.00 |
    +----+--------+--------+
    
    mysql> rollback; -- 直接rollback,回滚在最开始
    mysql> select * from account; -- 所有刚刚的记录没有了
    Empty 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
  • 非正常演示1 - 证明未commit,客户端崩溃,MySQL自动会回滚(隔离级别设置为读未提交)
    -- 终端A
    mysql> select * from account; -- 当前表内无数据
    Empty set (0.00 sec)
    
    mysql> show variables like 'autocommit'; -- 依旧自动提交
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | autocommit    | ON    |
    +---------------+-------+
    
    mysql> begin; --开启事务
    mysql> insert into account values (1, '张三', 100); -- 插入记录
    mysql> select * from account; --数据已经存在,但没有commit,此时同时查看终端B
    +----+--------+--------+
    | id | name   | blance |
    +----+--------+--------+
    | 1  | 张三   | 100.00 |
    +----+--------+--------+
    
    mysql> Aborted -- ctrl + \ 异常终止MySQL
    
    --终端B
    mysql> select * from account; --终端A崩溃前
    +----+--------+--------+
    | id | name   | blance |
    +----+--------+--------+
    | 1  | 张三   | 100.00 |
    +----+--------+--------+
    
    mysql> select * from account; --数据自动回滚
    Empty 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
  • 非正常演示2 - 证明commit了,客户端崩溃,MySQL数据不会在受影响,已经持久化
    --终端 A
    mysql> show variables like 'autocommit'; -- 依旧自动提交
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | autocommit    | ON    |
    +---------------+-------+
    
    mysql> select * from account; -- 当前表内无数据
    Empty set (0.00 sec)
    
    mysql> begin; -- 开启事务
    mysql> insert into account values (1, '张三', 100); -- 插入记录
    mysql> commit; --提交事务
    
    mysql> Aborted -- ctrl + \ 异常终止MySQL
    
    --终端 B
    mysql> select * from account; --数据存在了,所以commit的作用是将数据持久化到MySQL中
    +----+--------+--------+
    | id | name   | blance |
    +----+--------+--------+
    | 1  | 张三   | 100.00 |
    +----+--------+--------+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 非正常演示3 - 对比试验,证明begin操作会自动更改提交方式,不会受MySQL是否自动提交影响
    -- 终端 A
    mysql> select *from account; --查看历史数据
    +----+--------+--------+
    | id | name   | blance |
    +----+--------+--------+
    | 1  | 张三   | 100.00 |
    +----+--------+--------+
    
    mysql> show variables like 'autocommit'; --查看事务提交方式
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | autocommit    | ON    |
    +---------------+-------+
    
    mysql> set autocommit=0; --关闭自动提交
    mysql> show variables like 'autocommit'; --查看关闭之后结果
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | autocommit    | OFF   |
    +---------------+-------+
    
    mysql> begin; --开启事务
    mysql> insert into account values (2, '李四', 10000); --插入记录
    mysql> select *from account; --查看插入记录,同时查看终端B
    +----+--------+----------+
    | id | name   | blance   |
    +----+--------+----------+
    | 1  | 张三   | 100.00   |
    | 2  | 李四   | 10000.00 |
    +----+--------+----------+
    
    mysql> Aborted --再次异常终止
    
    -- 终端B
    mysql> select * from account; --终端A崩溃前
    +----+--------+----------+
    | id | name   | blance   |
    +----+--------+----------+
    | 1  | 张三   | 100.00   |
    | 2  | 李四   | 10000.00 |
    +----+--------+----------+
    
    mysql> select * from account; --终端A崩溃后,自动回滚
    +----+--------+--------+
    | id | name   | blance |
    +----+--------+--------+
    | 1  | 张三   | 100.00 |
    +----+--------+--------+
    
    • 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
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
  • 非正常演示4 - 证明单条 SQL 与事务的关系
    -- 实验一
    -- 终端A
    mysql> select * from account;
    +----+--------+--------+
    | id | name   | blance |
    +----+--------+--------+
    | 1  | 张三   | 100.00 |
    +----+--------+--------+
    
    mysql> show variables like 'autocommit';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | autocommit    | ON    |
    +---------------+-------+
    
    mysql> set autocommit=0; --关闭自动提交
    
    mysql> insert into account values (2, '李四', 10000); --插入记录
    mysql> select *from account; --查看结果,已经插入。此时可以在查看终端B
    +----+--------+----------+
    | id | name   | blance   |
    +----+--------+----------+
    | 1  | 张三   | 100.00   |
    | 2  | 李四   | 10000.00 |
    +----+--------+----------+
    mysql> ^DBye --ctrl + \ or ctrl + d,终止终端
    
    -- 终端B
    mysql> select * from account; --终端A崩溃前
    +----+--------+----------+
    | id | name   | blance   |
    +----+--------+----------+
    | 1  | 张三   | 100.00   |
    | 2  | 李四   | 10000.00 |
    +----+--------+----------+
    
    mysql> select * from account; --终端A崩溃后
    +----+--------+--------+
    | id | name   | blance |
    +----+--------+--------+
    | 1  | 张三   | 100.00 |
    +----+--------+--------+
    
    -- 实验二
    -- 终端A
    mysql> show variables like 'autocommit'; --开启默认提交
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | autocommit    | ON    |
    +---------------+-------+
    
    mysql> select * from account;
    +----+--------+--------+
    | id | name   | blance |
    +----+--------+--------+
    | 1  | 张三   | 100.00 |
    +----+--------+--------+
    
    mysql> insert into account values (2, '李四', 10000);
    mysql> select *from account; --数据已经插入
    +----+--------+----------+
    | id | name   | blance   |
    +----+--------+----------+
    | 1  | 张三   | 100.00   |
    | 2  | 李四   | 10000.00 |
    +----+--------+----------+
    
    mysql> Aborted --异常终止
    
    -- 终端B
    mysql> select * from account; --终端A崩溃前
    +----+--------+----------+
    | id | name   | blance   |
    +----+--------+----------+
    | 1  | 张三   | 100.00   |
    | 2  | 李四   | 10000.00 |
    +----+--------+----------+
    
    mysql> select * from account; --终端A崩溃后,并不影响,已经持久化。autocommit起作用
    +----+--------+----------+
    | id | name   | blance   |
    +----+--------+----------+
    | 1  | 张三   | 100.00   |
    | 2  | 李四   | 10000.00 |
    +----+--------+----------+
    
    • 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
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87

2.总结

  • 只要输入begin或者start transaction,事务便必须要通过commit提交,才会持久化,与是否设置set autocommit无关
  • 事务可以手动回滚,同时,当操作异常,MySQL会自动回滚
  • 对于 InnoDB 每一条 SQL 语言都默认封装成事务,自动提交(select有特殊情况,因为 MySQL 有 MVCC)
  • 从上面的例子,能看到事务本身的原子性(回滚),持久性(commit)

3.事务操作注意事项

  • 如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用 rollback(前提是事务还没有提交)
  • 如果一个事务被提交了(commit),则不可以回退(rollback)
  • 可以选择回退到哪个保存点
  • InnoDB 支持事务, MyISAM 不支持事务
  • 开始事务可以使 start transaction 或者 begin

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/882566
推荐阅读
相关标签
  

闽ICP备14008679号