MySQL-事务

本文涉及的产品
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: MySQL-事务

什么是事务

       多条sql语句,要么全部成功,要么全部失败。MySQL的事务是在存储引擎层实现。 MySQL的事务分别为ACID。

1. A 原子性(atomicity):一个事务必须被视为一个不可分割的单元。2. C 一致性(consistency):数据库是从一种状态切换到另一种状态。3. I 隔离性(isolation):事务在提交之前,对于其他事务不可见。4. D 持久性(durablity):一旦事务提交,所修改的将永久保存到数据库。
1. mysql> create table bank(
2.     -> name varchar(24),
3.     -> money float);
4. Query OK, 0 rows affected (0.03 sec)
5. 
6. mysql> insert into bank values('z3',1000),('l4',5000);
7. Query OK, 2 rows affected (0.00 sec)
8. Records: 2  Duplicates: 0  Warnings: 0
9. Begin 或 start transaction开启事务
10. mysql> BEGIN;
11. Query OK, 0 rows affected (0.00 sec)
12. mysql> UPDATE bank SET MONEY=MONEY-1000 WHERE name='l4';
13. Query OK, 1 row affected (0.06 sec)
14. Rows matched: 1 Changed: 1 Warnings: 0
15. mysql> UPDATE bank SET MONEY=MONEY+1000 WHERE name='z3';
16. Query OK, 1 row affected (0.01 sec)
17. Rows matched: 1  Changed: 1  Warnings: 0
18. mysql> select * from bank;
19. +------+-------+
20. | name | money |
21. +------+-------+
22. | z3   |  2000 |
23. | l4   |  4000 |
24. +------+-------+
25. 2 rows in set (0.01 sec)
26. mysql> rollback;
27. Query OK, 0 rows affected (0.00 sec)
28. 
29. mysql> select * from bank;
30. +------+-------+
31. | name | money |
32. +------+-------+
33. | z3   |  1000 |
34. | l4   |  5000 |
35. +------+-------+
36. 2 rows in set (0.01 sec)
37. 
38. mysql> commit;
39. Query OK, 0 rows affected (0.00 sec)
40. 
41. mysql> select * from bank;
42. +------+-------+
43. | name | money |
44. +------+-------+
45. | z3   |  1000 |
46. | l4   |  5000 |
47. +------+-------+
48. 2 rows in set (0.00 sec)

【总结事务命令】

事务开始: start transaction事务开始: begin事务提交: commit回 滚: rollback

查看自动提交模式是自动还是手动

1. mysql> show variables like 'autocommit';
2. +---------------+-------+
3. | Variable_name | Value |
4. +---------------+-------+
5. | autocommit    | ON    |
6. +---------------+-------+
7. 1 row in set (0.02 sec)
8. 
9. mysql> set autocommit=0;            #关闭自动提交
10. Query OK, 0 rows affected (0.00 sec)
11. 
12. mysql> show variables like 'autocommit';
13. +---------------+-------+
14. | Variable_name | Value |
15. +---------------+-------+
16. | autocommit    | OFF   |
17. +---------------+-------+
18. 1 row in set (0.00 sec)

隔离级别


事务有4种隔离级别 事务在提交之前对其他事务可不可见

read unaommitted(未提交读)read committed(已提交读)Repeatable read(可重复读)serializable(可串行化)

详细解释:

未提交读

事务中修改没有提交对其他事务也是可见的,俗称脏读

1. mysql> create table student(
2.     -> id int not null auto_increment,
3.     -> name varchar(30) not null default '',
4.     -> primary key (id)
5.     -> )engine=innodb auto_increment=2 default charset=utf8;
6.     Query OK, 0 rows affected (0.01 sec)

两端的客户端都设置成未提交读

1. mysql> set session tx_isolation='read-uncommitted';         #两台客户端都设置
2. Query OK, 0 rows affected, 1 warning (0.00 sec)

客户端A:

1. mysql> begin;
2. Query OK, 0 rows affected (0.00 sec)
3. 
4. mysql> select * from student;
5. Empty set (0.00 sec)
6. 
7. mysql> insert into student(name) values('zhangsan');
8. Query OK, 1 row affected (0.00 sec)
9. mysql> //注意:此时事务未提交!!!

客户端B:

1. mysql> select * from student;
2. +----+----------+
3. | id | name     |
4. +----+----------+
5. |  2 | zhangsan |
6. +----+----------+
7. 1 row in set (0.00 sec)

客户端B可以查看到信息

       总结:以上可以看出未提交读隔离级别非常危险,对于一个没有提交事务所做修改对另一个事务是可见状态,出现了脏读!非特殊情况不建议使用此级别。

已提交读

多数数据库系统默认为此级别(MySQL不是)。已提交读级别为一个事务只能已提交事务所做的修改,也就是解决了未提交读的问题

1. mysql> set session tx_isolation='read-committed';       #两台客户端都设置
2. Query OK, 0 rows affected, 1 warning (0.00 sec)

客户端A

1. mysql> begin;
2. Query OK, 0 rows affected (0.00 sec)
3. 
4. mysql> select * from student;
5. +----+----------+
6. | id | name     |
7. +----+----------+
8. |  2 | zhangsan |
9. +----+----------+
10. 1 row in set (0.00 sec)
11. 
12. mysql> insert into student(name) values('lisi');
13. Query OK, 1 row affected (0.01 sec)

#此时去客户端B查看表,查看后在执行下面命令提交事务

1. mysql> commit;
2. Query OK, 0 rows affected (0.00 sec

客户端B:

1. mysql> select * from student;           #未提交事务前查看
2. +----+----------+
3. | id | name     |
4. +----+----------+
5. |  2 | zhangsan |
6. +----+----------+
7. 1 row in set (0.00 sec) 
8. mysql> select * from student;           #提交事务后查看
9. +----+----------+
10. | id | name     |
11. +----+----------+
12. |  2 | zhangsan |
13. |  3 | lisi     |
14. +----+----------+
15. 2 rows in set (0.00 sec)

       总结:从上面的例子可以看出,提交读没有了未提交读的问题,但是我们可以看到客户端A的一个事务中执行了两次同样的SELECT语句,,得到不同的结果,因此已提交读又被称为不可重复读。同样的筛选条件可能得到不同的结果。

可重复读

解决了不可重复读的问题,数据库级别没有解决幻读的问题。

1. mysql> set session tx_isolation='repeatable-read';          #两个客户端均设置为可重复读,然后两边一起开启一个事务
2. Query OK, 0 rows affected, 1 warning (0.00 sec)

客户端A:

1. mysql> begin;
2. Query OK, 0 rows affected (0.00 sec)
3. 
4. mysql> select * from student;
5. +----+----------+
6. | id | name     |
7. +----+----------+
8. |  2 | zhangsan |
9. |  3 | lisi     |
10. +----+----------+
11. 2 rows in set (0.00 sec)
12. 
13. mysql> update student set name='zhang3' where id=2;
14. Query OK, 1 row affected (0.01 sec)
15. Rows matched: 1  Changed: 1  Warnings: 0
16. 
17. mysql> commit;
18. Query OK, 0 rows affected (0.00 sec)

客户端B:

1. mysql> begin;
2. Query OK, 0 rows affected (0.00 sec)
3. 
4. mysql> select * from student;
5. +----+----------+
6. | id | name     |
7. +----+----------+
8. |  2 | zhangsan |
9. |  3 | lisi     |
10. +----+----------+
11. 2 rows in set (0.00 sec)
12. 
13. mysql> select * from student;
14. +----+----------+
15. | id | name     |
16. +----+----------+
17. |  2 | zhangsan |
18. |  3 | lisi     |
19. +----+----------+
20. 2 rows in set (0.00 sec)
21. mysql> commit;
22. Query OK, 0 rows affected (0.00 sec)
23. 
24. mysql> select * from student;
25. +----+--------+
26. | id | name   |
27. +----+--------+
28. |  2 | zhang3 |
29. |  3 | lisi   |
30. +----+--------+
31. 2 rows in set (0.00 sec)

       总结:上面的例子我们得知,可重复读两次读取的内容不一样。数据库的幻读问题并没有得到解决。幻读只读锁定里面的数据,不能读锁定外的数据,解决幻读出了mvcc机制Mvcc机制。

可串行化

是最高隔离级别,强制事务串行执行,执行串行了也就解决问题了,这个I别只有在对数据一致性要求非常严格并且没有并发的情况下使用

1. mysql> set session tx_isolation='serializable';             #两个客户端均设置为串读,然后两边一起开启一个事务
2. Query OK, 0 rows affected, 1 warning (0.00 sec)

客户端A:

1. mysql> begin;
2. Query OK, 0 rows affected (0.00 sec)
3. 
4. mysql> select * from student whereid < 10;
5. +----+--------+
6. | id | name   |
7. +----+--------+
8. |  2 | zhang3 |
9. |  3 | lisi   |
10. +----+--------+
11. 2 rows in set (0.00 sec)

客户端B:

客户端B执行插入命令,发现卡顿,稍等一会就会返回ERROR。

1. mysql> insert into student(name) values('wangwu');
2. ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

总结:我们发现INSERT 语句被阻塞执行,原因是A执行了查询表student同时满足id<10,已被锁定。如果查询表student同时满足id<5,则新增语句可以正常执行。

隔离级别

脏读

不可重复

幻读

加锁读

未提交读

提交读

可重复读

串行读


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
SQL 存储 关系型数据库
MySQL----事务
MySQL----事务
22 3
|
9天前
|
SQL 关系型数据库 MySQL
MySQL 事务回滚。在执行删除、更新等操作时,防止误操作
MySQL 事务回滚。在执行删除、更新等操作时,防止误操作
22 2
|
2月前
|
存储 关系型数据库 MySQL
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
|
4天前
|
存储 SQL 关系型数据库
深入解析MySQL事务机制和锁机制
深入解析MySQL事务机制和锁机制
|
6天前
|
算法 关系型数据库 MySQL
一天五道Java面试题----第七天(mysql索引结构,各自的优劣--------->事务的基本特性和隔离级别)
这篇文章是关于MySQL的面试题总结,包括索引结构的优劣、索引设计原则、MySQL锁的类型、执行计划的解读以及事务的基本特性和隔离级别。
|
20天前
|
SQL 关系型数据库 MySQL
(七)MySQL事务篇:ACID原则、事务隔离级别及事务机制原理剖析
众所周知,MySQL数据库的核心功能就是存储数据,通常是整个业务系统中最重要的一层,可谓是整个系统的“大本营”,因此只要MySQL存在些许隐患问题,对于整个系统而言都是致命的。
|
20天前
|
SQL 算法 关系型数据库
(十)全解MySQL之死锁问题分析、事务隔离与锁机制的底层原理剖析
经过《MySQL锁机制》、《MySQL-MVCC机制》两篇后,咱们已经大致了解MySQL中处理并发事务的手段,不过对于锁机制、MVCC机制都并未与之前说到的《MySQL事务机制》产生关联关系,同时对于MySQL锁机制的实现原理也未曾剖析,因此本篇作为事务、锁、MVCC这三者的汇总篇,会在本章中补全之前空缺的一些细节,同时也会将锁、MVCC机制与事务机制之间的关系彻底理清楚。
|
5天前
|
算法 关系型数据库 MySQL
一天五道Java面试题----第七天(mysql索引结构,各自的优劣--------->事务的基本特性和隔离级别)
这篇文章是关于MySQL的面试题总结,包括索引结构的优劣、索引设计原则、MySQL锁的类型、执行计划的解读以及事务的基本特性和隔离级别。
|
7天前
|
SQL 安全 关系型数据库
Go 语言中的 MySQL 事务操作
在现代应用中,确保数据完整与一致至关重要。MySQL的事务机制提供了可靠保障。本文首先解释了事务的概念及其ACID特性,随后介绍了如何在Go语言中使用`database/sql`包进行MySQL事务操作。通过一个银行转账的例子,演示了如何通过Go开启事务、执行操作并在必要时回滚或提交,确保数据一致性。最后,还讨论了不同事务隔离级别的含义及如何在Go中设置这些级别。通过本文的学习,开发者能更好地掌握MySQL事务的应用。
12 0