文章目录
- 1、概述
- 2、事务原理
- 3、事务的四大特性(ACID)
- 4、事务的隔离性级别
- (1)读未提交(read uncommitted)
- (2)读已提交(read committed)
- (3)可重复读( repeatable read)
- (4)序列化/串行化(serializable)
- 5、事务示例
- (1)提交事务与回滚示例
- (2)隔离级别演示
- ①读未提交(read uncommitted)显示
- ②读已提交(read committed)
- ③可重复读(repeatbles read)
- ④串行化(serializable)
1、概述
事务(Transaction)是访问和更新数据库的程序执行单元;事务中可能包含一个或多个sql语句,这些语句要么都执行,要么都不执行。
例如下面的例子:张三给李四转钱,SQL语句要操作张三的账户余额减少8000,还要操作李四的账户余额增加8000。这两个SQL操作要保证全执行或不执行,不能一个执行了一个没执行!这就要需要用到事务。
- MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务
- 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
- 只有DML(insert、update、delete)语句支持事务,因为这三个语句都是和数据库表中的“数据”相关,事务的存在为了保证数据的完整性、安全性。
- MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作
2、事务原理
3、事务的四大特性(ACID)
- 原子性:事务中所涉及的程序对数据库的修改操作要么全部成功,要么全部失败。
- 一致性:事务执行前和执行后来源和去向保持平衡。
- 隔离性:事务A与事务B之间具有隔离,一个事务不会影响其它事务的运行。
- 持久性:一旦事务成功提交,应该保证数据的完整存在。
4、事务的隔离性级别
事务隔离性存在隔离级别,理论上隔离级别包括4个:
(1)读未提交(read uncommitted)
对方事务还未提交,我们当前事务可以读取到对方未提交的数据.
读未提交
存在脏读现象:表示读到的数据及其不稳定
(2)读已提交(read committed)
对方事务已经提交的数据我方可以读取到。这种隔离级别解决了脏读现象
读已提交
存在的问题时:不可重复读(事务提交前后,两次读取的数据不一致)
Sql Server , Oracle等数据库的默认隔离级别
(3)可重复读( repeatable read)
解决了不可重复读的问题,读到的数据永远是开启事务时刻的数据。
可重复读
存在幻读现象
MySQL的默认隔离级别
(4)序列化/串行化(serializable)
解决了所有问题。但是效率低,需要事务排队。强制的进行排序,在每个读读据行上添加共享锁。会导致大量超时现象和锁竞争。这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻读。
5、事务示例
MySQL事务默认情况下是自动提交的,即执行任意一条DML(insert update delete)语句则会提交一次。关闭自动提交(显式地开启一个事务)start transaction;
准备表
drop table if exists t_user;
create table t_user(
id int primary key auto_increment, 主键自增
username varchar(255)
);
(1)提交事务与回滚示例
提交事务
start transaction; #开启事务
insert into t_user(username) values("zhangsan");
insert into t_user(username) values("sili");
commit; #提交事务
select * from t_user;
执行结果
+----+----------+
| id | username |
+----+----------+
| 1 | zhangsan |
| 2 | sili |
+----+----------+
回滚事务
start transaction;
insert into t_user(username) values("liuliu");
insert into t_user(username) values("qiqi");
rollback; # 回滚事务
select * from t_user;
执行结果
+----+----------+
| id | username |
+----+----------+
| 1 | zhangsan |
| 2 | sili |
+----+----------+
可以看到上述两条插入语句并没有将数据插入到表中,因为回滚了,清空了操作历史缓存,不会真正改变文件
(2)隔离级别演示
MySQL默认的事务隔离级别为3级可重复读(repeatbles read),首先手动设置MySQL的事务隔离级别
设置MySQL的全局事务隔离级别
set global transaction isolation level 隔离级别;
例如:设置MySQL的全局事务隔离级别为读未提交
set global transaction isolation level read uncommitted;
查询MySQL的全局事务隔离级别
select @@global.transaction_isolation;
①读未提交(read uncommitted)显示
分别使用两个终端连接数据库,按照如下顺序分别执行。
②读已提交(read committed)
分别使用两个终端连接数据库,按照如下顺序分别执行。
③可重复读(repeatbles read)
分别使用两个终端连接数据库,按照如下顺序分别执行。
④串行化(serializable)
分别使用两个终端连接数据库,按照如下顺序分别执行。
可以看到隔离级别使用串行化后,两个事务同时开启的情况下,其中一个事务中执行了DML(insert\update\delete)语句后,另个事务再执行其他SQL语句就会被阻塞,直到刚刚的事务提交或回滚后该事务的语句才能被执行。这大大提高了安全性,但是降低了执行效率。