事务
事务简介
事务就是一系列操作的集合,它们之间不可分割。
事务会将一系列操作当做一个整体执行,要么全部成功,要么全部失败。
比较典型的例子就是银行转账系统,A给B转账,A账号减少一定金额,则B账号会增加一定金额。
注:在MySQL中事物的提交是自动的。也就是当我们执行一条语句后就直接提交了事务
事务操作
注:对于每一条SQL语句都可以看做是一个事务
#查看事务提交方式
#默认查询的结果为1,也就是自动提交事务
select @@autocommit;
#设置事务提交方式
##方式一
##将事务设置为手动提交
set @@autocommit = 0;
##方式二
###出现以下关键字就意味着需要手动提交事务
start transation;
#提交事务
commit;
#回滚事务
rollback;
#方式一实现
将MySQL中的事务设置为手动提交
set @@autocommit = 0;
#转账操作
#begin
##查询张三的余额
select * from account where name = '张三';
## 将张三的余额-1000
update account set money = money - 1000 where name = '张三';
...
##将李四的余额+1000
update account set money = money + 1000 where name = '李四';
#end
commit ;
#如果整个事务发生错误,执行回滚即可返回此次异常的事务操作,但前提是需要将事务的提交模式改为手动
rollback ;
注:
- 在编写错误的SQL语句时,最好设置为…,此时可视化工具才可判断出此语句有误。
- 在执行整个事务时,需要选中整个完整的事务代码执行
#方式二实现
start transaction;
-- 转账操作 (张三给李四转账1000)
-- 1. 查询张三账户余额
select * from account where name = '张三';
-- 2. 将张三账户余额-1000
update account set money = money - 1000 where name = '张三';
...
-- 3. 将李四账户余额+1000
update account set money = money + 1000 where name = '李四';
commit;
rollback ;
事务的四大特性(acid特性)
- 原子性(A):要么全部成功,要么全部失败
- 一致性(C):无论事务正常还是异常执行,所有的数据都会保持一致。如上述的张三和李四的金额加起来是一个恒定的值。
- 隔离性(I):可以在并发操作数据库的情况下独立运行。即两个事务之间的操作不互相影响,都可以独立运行。
- 持久性(D):事务一旦提交或回滚,对数据库的操作都是不可逆的。因为数据库中的数据最终存储在磁盘中
数据库中的数据存储的数据存储在电脑磁盘中,以下是test数据库中的四张表
事务隔离级别
隔离级别概述
查看和设置隔离级别
#查看事务隔离级别,默认情况下为 Repeatable Read
select @@transaction_isolation;
#设置隔离级别,session是仅设置当前会话的事务,global是设置全局会话的事务
set [session | gloabl] transaction isolation level [ read uncommitted | read committed | repeatable read | serializable]
注:
- 事务的隔离级别越高,安全性就越高,但性能越低
- 事务的隔离级别是为了解决并发事务引起的问题
- MySQL的默认事务隔离级别是Repeatable Read
并发事务问题
脏读
事务A读取到事务B修改了但还未提交的数据。如下图中 右边的事务修改但未提交数据,而左边事务能访问到未提交的数据。
#事务的默认隔离级别是Repeatable Read,此级别不允许 脏读 问题
#所以需要将当前会话的事务隔离级别设置为 read uncommitted
set session transaction isolation level read uncommitted;
注:如果想用使用某一数据库,一定要先使用
use 数据库
定位到需要使用的数据库上
#将事务隔离等级设置为read committed则不可再读取为提交的数据。只有B事务提交了事务,A事务才能查看到修改后的事务。
set session transaction isolation level read committed;
不可重复读
默认情况下,MySQL的事务隔离等级设置为repeatable read,所以此时不需要设置事务的隔离等级。从下图可看出,即使事务B提交了修改的数据,但在A事务中的第二次查询仍和第一次的查询结果相同。故repeatable read隔离等级可以解决不可重复读问题。
幻读
默认情况的事务隔离等级不能解决幻读问题,如下图所示。事务A在第一次查询数据时没有id = 3的数据,而此时B事务插入 id = 3的记录并提交,当A事务也想插入 id = 3的记录时,则提示主键重复,但在进行第二次查询时还是查询不到 id = 3的数据。在A事务中的数据库中不能插入此条重复记录但又查询不到该记录。
此时就需要将事务隔离等级设置为serializable 。
set session transaction isolation level serializable ;
此时B事务执行插入语句时就会被阻塞(执行插入语句后一直出现光标闪烁),直到A事务提交事务后B事务才可操作。
注:串行化就是指在并发环境下,一次只允许一个事务操作数据库