数据库之事务详解
文章目录
一、事务的概念
1、数据库事务
数据库事务通常指对数据库进行读或写的一个操作序列。它的存在包含有以下两个目的:
-
为数据库操作提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
-
当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。
2、系统事务
处理一系列业务处理的执行逻辑单元,该单元里的一系列类操作要不全部成功要不全部失败
二、事务的属性(ACID)
1、原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
【例子】:
A向B转账100元,需要执行两个操作:A账户减少100元,B账户增加100元。这两个操作要么都同时执行成功,要么都执行失败,否则一个成功,一个失败都是不合理的。
2、一致性(Consistency)
数据库从一个一致性状态变到另一个一致性状态 (经过一系列操作后,所有的操作和更新全部提交成功,数据库只包含全部成功后的数据就是数据的一致性)。
【例子】:
A向B转账100元,假设转账之前这两个用户的钱加起来总共是2000,那么A向B转账之后,不管这两个账户怎么转,A用户的钱和B用户的钱加起来的总额还是2000,这个就是事务的一致性。
3、隔离性(Isolation)
多个事务,事务的隔离性是指多个用户并发访问数据库时, 一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
4、持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
三、数据库事务并发存在的问题
如果我们在不考虑隔离性问题时,事务是存在三种并发访问问题的:
1、脏读
A事务读取B事务尚未提交的更改数据,并在这个数据的基础上进行操作,这时候如果事务B回滚,那么A事务读到的数据是不被承认的。
在这个例子中,A事务修改了用户名,但是回滚了,这时候B事务读数据时出现了脏读。
2、不可重复读
不可重复读是指A事务读取了B事务已经提交的更改数据(针对的是update或delete)。然后事务A在前后两次很短的时间内读取数据的时候,发现数据不匹配了。
在这个例子中,A事务修改了用户名并提交了,这时候B事务两次读数据时出现了不一致的现象。
3、幻读
A事务读取B事务提交的新增数据,会引发幻读问题(针对的是insert)。即事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。
在这个例子中,A事务首先读取数据,这时候B事务增加了一条数据,然后A事务再次修改数据时发现多了一条数据(像是产生了幻觉)。
四、事务的隔离级别
1、read uncommitted(读未提交的数据)
事务中的修改,即使没有提交,其他事务也可以看得到,会导致“脏读”、“幻读”和“不可重复读”。
2、read committed(读已提交的数据)
大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读”,但不能避免“幻读”和“不可重复读”。该级别适用于大多数系统。
3、repeatable read(重复读-MySQL默认隔离级别)
保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读”和“不可重复读”的情况,但不能避免“幻读”,但是带来了更多的性能损失。
4、serializable(串行化)
最严格的级别,事务串行执行,资源消耗最大。
五、事务的SQL相关操作
/**** 1、事务的创建 ****/
// 禁止自动提交功能(只针对当前事务)
SET autocommit=0;
// 开启事务
START TRANSACTION;
// 事务处理(只能是增删改查语句:select,update,insert,delete)
UPDATE t_account SET balance=balance-500 WHERE username="Eric";
UPDATE t_account SET balance=balance+500 WHERE username="Lx";
// 结束事务
COMMIT;
/**** 2、事务的并发和隔离级别 ****/
// 查看默认的隔离级别(可重复读)
SELECT @@tx_isolation;
// 修改隔离级别(未提交读-允许脏读)
set session transaction isolation level read uncommitted;
// 事务1
SET autocommit=0;
START TRANSACTION;
UPDATE t_account SET username="eric" WHERE id=1;
COMMIT;
// 事务2
SET autocommit=0;
START TRANSACTION;
SELECT * from t_account;
COMMIT;
// 修改隔离级别(已提交读-不允许脏读但允许可重复读)
set session transaction isolation level read committed;
// 修改隔离级别(重复读-不允许脏读、重复读但允许幻读,这是MySQL默认隔离级别)
set session transaction isolation level repeatable read;
// 修改隔离级别(串行化-不允许脏读、重复读、幻读,但性能十分低下)
set session transaction isolation level serializable;
/**** 3、保存回滚点 ****/
SET autocommit=0;
START TRANSACTION;
DELETE FROM t_account WHERE id=2; // 数据被删除
SAVEPOINT a; // 设置回滚点
DELETE FROM t_account WHERE id=3; // 这里的数据不会被删除
ROLLBACK TO a; // 回到回滚点
六、事务总结
事务是指一系列将要发生的连续的操作。事务安全是为了保证一系列操作的结果保持同步,保证数据的完整性。开启事务后,操作的结果会先保存到事务日志中,等操作完成提交事务后,才会修改表中的数据。
【Note】:
只有innodb存储引擎和bdb存储引擎才支持事务安全。
参考:https://blog.****.net/love_legain/article/details/54706272
https://blog.****.net/z646721826/article/details/79412459
https://blog.****.net/starlh35/article/details/76445267
https://www.cnblogs.com/fengdejiyixx/p/7988935.html
https://blog.****.net/Somhu/article/details/78775198