目录
1.概念:
事务通常由 高级数据库 操纵语言或 编程语言 (如SQL,C++或 Java )书写的 用户程序 的执行所引起,并用形如 begin transaction 和 end transaction 语句(或 函数调用 )来界定。 事务由事务开始 (begin transaction)和事务结束 (end transaction)之间执行的全体操作组成
基本概念:
如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。如下A给B转钱的例子很形象的说明了事务的概念:
2.事务的操作
- 开启事务:start transaction;
- 回滚:rollback;
- 提交:commit;
例: 还是用这个A给B转账的例子,在SQLyog中进行模拟开启事务、回滚、提交
-- 创建表
CREATE TABLE account (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
balance DOUBLE
);
-- 添加数据
INSERT INTO account (NAME, balance) VALUES ('zhangsan', 1000), ('lisi', 1000);
UPDATE account SET balance = 1000;
SELECT * FROM account;
-- 0. 开启事务
START TRANSACTION;
-- 1. 张三账户 -500
UPDATE account SET balance = balance - 500 WHERE NAME = 'zhangsan';
-- 2. 李四账户 +500
-- 出错了...
UPDATE account SET balance = balance + 500 WHERE NAME = 'lisi';
-- 发现执行没有问题,提交事务
COMMIT;
-- 发现出问题了,回滚事务
ROLLBACK;
解释: 指要做的或所做的事情
3.事务的四大特征:
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
4.事务的隔离级别
多个事务之间是隔离的,相互独立的,但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别,就可以解决这些问题。
5. 存在的问题
1)脏读:一个事务读取到另一个事务中没有提交的数据; 【举例】:A给B发1000块钱,手一抖打了10000,这个钱已经打到B的户口,但是事务还没有提交,这时B查下卡,发现多了9000,兴奋坏了,但是A及时发现,马上回滚差点提交的事务,将数字改回1000再提交。
2)不可重复读(虚读):在同一个事务中两次读取到的数据不一样; 【举例】:A拿着卡去购物,卡里有1000块钱,当A买单时(事务开启),收费系统事先检测到他的卡里有1000,就在这个时候,A的妻子要把钱全部拿出来买首饰,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待A的妻子转出金额事务提交完),A就会很郁闷,钱哪去了。。。
3)幻读:一个事务操作(DML)数据表中所有的记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改; 【举例】:A去消费,花了1千元,A的妻子去查看他今天的消费记录(全表扫描FTS,妻子事务开启),看到确实是花了1千元,就在这时,A又花了1千元买了一个机械键盘,即新增INSERT了一条消费记录,并提交。当妻子打印消费记录清单时(妻子事务提交),发现花了2千元,似乎出现了幻觉,这就是幻读。
6. 隔离级别
1)read uncommitted:读未提交 【会产生的问题】:脏读、不可重复读、幻读
2)read committed:读已提交(Oracle默认) 【会产生的问题】:不可重复读、幻读
3)repeatable read:可重复读(MySQL默认) 【会产生的问题】:幻读
4)serializable:串行化 【会产生的问题】:可以解决所有问题
7.事务类型
编辑 播报
(1)手动事务
手动事务允许显式处理若干过程,这些过程包括:开始事务、控制事务边界内的每个连接和资源登记、确定事务结果(提交或中止)以及结束事务。尽管此模型提供了对事务的标准控制,但它缺少一些内置于自动事务模型的简化操作。例如,在手动事务中数据存储区之间没有自动登记和协调。此外,与自动事务不同,手动事务中事务不在对象间流动。
如果选择手动控制分布式事务,则必须管理恢复、并发、安全性和完整性。也就是说,必须应用维护与事务处理关联的 ACID 属性所需的所有编程方法。
(2)自动事务
.NET 页、XML Web services方法或 .NET Framework 类一旦被标记为参与事务,它们将自动在事务范围内执行。您可以通过在页、XML Web services 方法或类中设置一个事务属性值来控制对象的事务行为。特性值反过来确定实例化对象的事务性行为。因此,根据声明特性值的不同,对象将自动参与现有事务或正在进行的事务,成为新事务的根或者根本不参与事务。声明事务属性的语法在 .NET Framework 类、.NET 页和 XML Web services 方法中稍有不同。
声明性事务特性指定对象如何参与事务,如何以编程方式被配置。尽管此声明性级别表示事务的逻辑,但它是一个已从物理事务中移除的步骤。物理事务在事务性对象访问数据库或消息队列这样的数据资源时发生。与对象关联的事务自动流向合适的资源管理器,诸如 OLE DB、开放式数据库连接 (ODBC) 或 ActiveX 数据对象 (ADO) 的关联驱动程序在对象的上下文中查找事务,并通过分布式事务处理协调器 (DTC) 在此事务中登记。整个物理事务自动发生。
案例:
例:
……关键语句讲解………
BEGIN TRANSACTION
/*--定义变量,用于累计事务执行过程中的错误--*/
DECLARE @errorSum INT
SET @errorSum=0 --初始化为0,即无错误
/*--转账:张三的账户少1000元,李四的账户多1000元*/
UPDATEbankSET currentMoney=currentMoney-1000
WHERE customerName='张三'
SET @errorSum=@errorSum+@@error
UPDATE bank SET currentMoney=currentMoney+1000
WHERE customerName='李四'
SET @errorSum=@errorSum+@@error --累计是否有错误
IF @errorSum<>0 --如果有错误
BEGIN
print '交易失败,回滚事务'
ROLLBACK TRANSACTION
END?
ELSE
BEGIN
print '交易成功,提交事务,写入硬盘,永久的保存'
COMMIT TRANSACTION
END
GO
print '查看转账事务后的余额'
SELECT * FROM bank?
GO
【注意】:隔离级别从小到大,安全性越来越高,但是效率越来越低。但是一般情况下不会修改数据库默认的隔离级别,只有在极特殊情况下才会做出修改已解决一些特殊问题。