文章目录

  • 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事务与锁 mysql 事务sql_数据

  • MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务
  • 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
  • 只有DML(insert、update、delete)语句支持事务,因为这三个语句都是和数据库表中的“数据”相关,事务的存在为了保证数据的完整性、安全性。
  • MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作

2、事务原理

MYSQL事务与锁 mysql 事务sql_隔离级别_02

3、事务的四大特性(ACID)

  • 原子性:事务中所涉及的程序对数据库的修改操作要么全部成功,要么全部失败。
  • 一致性:事务执行前和执行后来源和去向保持平衡。
  • 隔离性:事务A与事务B之间具有隔离,一个事务不会影响其它事务的运行。
  • 持久性:一旦事务成功提交,应该保证数据的完整存在。

4、事务的隔离性级别

事务隔离性存在隔离级别,理论上隔离级别包括4个:

(1)读未提交(read uncommitted)

对方事务还未提交,我们当前事务可以读取到对方未提交的数据.

读未提交存在脏读现象:表示读到的数据及其不稳定

MYSQL事务与锁 mysql 事务sql_MySQL_03

(2)读已提交(read committed)

对方事务已经提交的数据我方可以读取到。这种隔离级别解决了脏读现象

读已提交存在的问题时:不可重复读(事务提交前后,两次读取的数据不一致)

MYSQL事务与锁 mysql 事务sql_数据_04

Sql Server , Oracle等数据库的默认隔离级别

(3)可重复读( repeatable read)

解决了不可重复读的问题,读到的数据永远是开启事务时刻的数据。

可重复读存在幻读现象

MYSQL事务与锁 mysql 事务sql_数据_05


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)显示

分别使用两个终端连接数据库,按照如下顺序分别执行。

MYSQL事务与锁 mysql 事务sql_MySQL_06

②读已提交(read committed)

分别使用两个终端连接数据库,按照如下顺序分别执行。

MYSQL事务与锁 mysql 事务sql_数据_07

③可重复读(repeatbles read)

分别使用两个终端连接数据库,按照如下顺序分别执行。

MYSQL事务与锁 mysql 事务sql_隔离级别_08

④串行化(serializable)

分别使用两个终端连接数据库,按照如下顺序分别执行。

MYSQL事务与锁 mysql 事务sql_MySQL_09


可以看到隔离级别使用串行化后,两个事务同时开启的情况下,其中一个事务中执行了DML(insert\update\delete)语句后,另个事务再执行其他SQL语句就会被阻塞,直到刚刚的事务提交或回滚后该事务的语句才能被执行。这大大提高了安全性,但是降低了执行效率。