事务

事务

概念

一个事务是由一条或者多条sql语句构成,这一条或者多条sql语句要么全部执行成功,要么全部执行失败。

默认情况下,每条单独的sql语句就是一个单独的事务。

事务属于 Transaction Control Language 事务控制语言(TCL


举例:

银行转账,侠奢转20块到猪猪的账户,这其实需要两条SQL语句:

  • 给侠奢三的账户减去20元;
  • 给猪猪的账户加上20元。

如果在第一条SQL语句执行成功后,在执行第二条SQL语句之前,程序被中断了(可能是抛出了某个异常,也可能是其他什么原因),那么李四的账户没有加上20元,而张三却减去了20元。这是不允许的。

所以说:事务中的多个操作,要么完全成功,要么完全失败,不可能存在成功一半的情况。也就是说给张三的账户减去20元如果成功了,那么给李四的账户加上20元的操作也必须是成功的;否则给张三减去20元,以及给李四加上20元都是失败的。

四大特性:ACID

  • 原子性(Atomicity):事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。
  • 一致性(Consistency):事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。
  • 隔离性(Isolation):隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰,即一个事务的执行不能杯其他事务干扰。(与隔离级别有关)
  • 持久性(Durability):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。

MySql中的事务

在默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务。如果需要在一个事务中包含多条SQL语句,那么需要开启事务和结束事务。

l 开启事务:start transaction;

l 结束事务:commitrollback

在执行SQL语句之前,先执行strat transaction,这就开启了一个事务(事务的起点),然后可以去执行多条SQL语句,最后要结束事务,commit表示提交,即事务中的多条SQL语句所做出的影响会持久化到数据库中。或者rollback,表示回滚,即回滚到事务的起点,之前做的所有操作都被撤消。

实例一:

# 事务

/*
概念:由一条或多条sql语句组成,要么都成功,要么都失败
mysql 中 innodb 存储引擎支持事务

分类:
1.隐式事务:没有明显的开启和结束标记
	比如DML语句中的insert、update、delete语句本身就是一条事务
	例如,insert中只要有一个数据插入失败,则整条语句不能执行:
	insert into students values(1, '侠奢', '男’, 'xxx@163.com')

2.显式事务:具有明显的开启和结束标记
	一般由多条sql语句组成,必须具有明显的开启和结束标记


步骤:
	0. 取消隐式事务自动开启的功能
		set autocommit=0;

	1. 开启事务
		start transaction;
		
	2. 编写事务需要的sql语句(1条或多条)
		(select insert update delete)
		
	savepoint 节点名;设置保存点

	
	3. 结束事务:
		commit;提交事务
		rollback;回滚事务
*/


-- 查看事务是否自动开启
SHOW VARIABLES LIKE '%auto%'

# 事务使用步骤

-- 0. 取消事务自动开启
SET autocommit = 0;

-- 1. 开启事务
START TRANSACTION;

-- 2. 编写事务的sql语句,侠奢转给猪猪500块钱
# 侠奢的钱-500
UPDATE person SET money=money-500 WHERE id=1;
# 猪猪的钱+500
UPDATE person SET money=money+500 WHERE id=2;

-- 3. 提交事务
# 提交
# commit;
# 回滚
ROLLBACK;

事务隔离级别

对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:

-- 脏读: 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段。之后, 若 T2 回滚, T1读取的内容就是临时且无效的. 

-- 不可重复读: 对于两个事务T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段。之后, T1再次读取同一个字段, 值就不同了. 

-- 幻读: 对于两个事务T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行。之后, 如果 T1 再次读取同一个表, 就会多出几行

一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好, 但并发性越弱。四个隔离级别如下图所示:

-- 事务的隔离级别:
		  			脏读	 不可重复读	幻读
read uncommitted:	√		√		 √
read committed:  	×		√		 √
repeatable read:    × 	    ×		 √
serializable:       ×       ×        ×


mysql中默认 第三个隔离级别 repeatable read
oracle中默认第二个隔离级别 read committed
查看隔离级别
select @@tx_isolation;
设置隔离级别
set session|global transaction isolation level 隔离级别;

实例二:

-- 1. 演示事务对于delete和truncate的处理的区别
SET autocommit=0;
START TRANSACTION;
TRUNCATE TABLE account;
DELETE FROM account;
ROLLBACK;



-- 2. 演示savepoint 的使用,即id为25的数据删掉,id为28的没有删掉
SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=25;
SAVEPOINT a; #设置保存点
DELETE FROM account WHERE id=28;
ROLLBACK TO a; #回滚到保存点


SELECT * FROM account;

posted @ 2020-07-17 17:12  侠奢  阅读(136)  评论(0)    收藏  举报