一、事务特性
要求事务具有4个特性:
原子性(Atomicity)、
一致性(Consistency)、
隔离性(Isolation)、
持久性(Durability)、
简称ACID准则。
注意:理解每个特性体现的实例。
二、 事务模式
(1)自动提交事务模式。每条单独的语句都是一个事务,是MySQL默认的事务管理模式。在此模式下,当一条语句成功执行后,它被自动提交(系统变量AUTOCOMMIT值为1),而当它执行过程中产生错误时,则被自动回滚。
(2)显式事务模式。该模式允许用户定义事务的启动和结束。事务以BEGIN WORK或START TRANSACTION语句显式开始,以COMMIT或ROLLBACK语句显式结束。显式事务内可定义多条语句作为一个事务,封装在START TRANSACTION与COMMIT中间。加保存点可以截取。
A、无保存点,整个事务通过rollback撤销
B、设置保存点
SAVEPOINT语句的语法形式如下:
SAVEPOINT 保存点名称;
回滚事务到保存点的ROLLBACK语句的语法形式如下:
ROLLBACK [WORK] TO SAVEPOINT 保存点名称;
【6-3】示例。下面创建的两个存储过程,分别对在同一个事务中创建两个账号相同的银行账户进行的不同处理。
创建save_p1_proc,仅仅撤消第二条insert语句,但提交了第一条insert语句。
DELIMITER @@
CREATE PROCEDURE save_p1_proc()
BEGIN
DECLARE CONTINUE HANDLER FOR 1062
BEGIN
ROLLBACK TO b; ##事务回滚到保存点b
END;
START TRANSACTION;
INSERT INTO account VALUES(null,'赵四',1000);
SAVEPOINT b; ##设置保存点
##last_insert_id()获取'赵四'账户的账号
INSERT INTO account VALUES(last_insert_id(),'钱六',1000);
COMMIT;
END@@
DELIMITER ;
CALL save_p1_proc();
SELECT * FROM account;
(3)隐性事务模式。在当前事务完成提交或回滚后,新事务自动启动。隐性事务不需要使用BEGIN WORK或START TRANSACTION语句标识事务的开始,但需要以COMMIT或ROLLBACK语句来提交或回滚事务。执行SET @@AUTOCOMMIT=0;语句可以使MySQL进入隐性事务模式。
三、并发控制
1、理解什么是并发控制
事务串行执行 : DBMS 按顺序一次执行一个事务 , 执行完一个事务后才开始另一事务的执行。
事务并发执行( concurrent execution ): DBMS 同时执行多个事务对同一数据的操作(并发操作),为此, DBMS 须对各事务中的操作顺序进行安排,以达到同时运行多个事务的目的。这里的“并发”是指在单处理器(一个 CPU )上,利用分时方法实现多个事务同时做。
2、并发执行可能引起的问题
事务中的操作归根结底就是读或写。两个事务之间的相互干扰就是其操作彼此冲突。因此,事务间的相互干扰问题可归纳为写 - 写、读 - 写和写 - 读三种冲突(读 - 读不冲突),分别称为“丢失更新”、“不可重读”、“读脏数据”问题。
1 .丢失更新( lost update )
丢失更新又称为覆盖未提交的数据 。
原因:由于两个(或多个)事务对同一数据并发地写入引起,称为写 — 写冲突。
结果:与串行地执行两个(或多个)事务的结果不一致。
2.不可重复读(unrepeatable read)
不可重复读也称为读值不可复现。
原因:该问题因读 — 写冲突引起。
结果:第二次读的值与前次读的值不同。
3 .读脏数据( dirty read )
读脏数据也称为读未提交的数据 。
原因:由于后一事务读了前一个事务写了但尚未提交的数据引起,称为写 — 读冲突。
结果:读到有可能要回退的更新数据。
3、事务隔离级别
隔离级别定义了一个事务与其他事务的隔离程度。
在并发事务中,总地来说会发生 4 种异常情况:
(1)丢失更新。
(2)读脏数据。
(3)不可重复读。
(4)幻影读。如果一个事务基于某个条件读取数据后,另一个事务则更新了同一个表中的数据,这时第一个事务再次读取数据时,根据搜索条件返回了不同的行,这就是幻影读。
4、MySQL事务隔离级别设置
1.MySQL隔离级别的设置
语法形式如下:
SET SESSION TRANSACTION ISOLATION LEVEL
SERIALIZABLE
REPEATABLE READ
READ COMMITED
READ UNCOMMITED;
级别由高到低:SERIALIZABLE>REPEATABLE READ>READ COMMITED>READ UNCOMMITED
SERIALIZABLE:事务最安全,事务按顺序一个接一个执行,一个事务完成开启新的事务。
【例6-10】避免幻影读现象示例。
(1)打开MySQL客户机A,执行下面语句。
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT @@transaction_isolation;
REPEATABLE READ:Mysql默认是REPEATABLE READ,在一个事务中对同一数据进行多次读取,内容不变,如果 其他事务在期间改了数据,可能读到脏数据。
【例6-9】幻影读现象示例。
(1)打开MySQL客户机A,执行下面语句。
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT @@transaction_isolation;
READ COMMITED:一个事务在过程中读取数据,另外有事务改了数据,可能出现前后读取数据不一致,不可重读问 题。
【例6-8】不可重复读现象示例。
(1)打开MySQL客户机A,执行下面语句。
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT @@transaction_isolation;
READ UNCOMMITED:一个事务在执行过程中读取数据,另一个事务在修改数据,并没有提交,第一个事务也能读 到。(很不安全,第一个事务能读到其他事务还没提交的数据)。
【例6-7】脏读现象示例。
(1)打开MySQL客户机A,执行下面语句。
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT @@transaction_isolation;
2. READ UNCOMMITED隔离级别
设置READ UNCOMMITED(读取未提交数据)隔离级别,所有事务都可以看到其他未提交事务的执行结果。该隔离 级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称为脏读(Dirty Read)。
3. READ COMMITED隔离级别
READ COMMITED(读取提交的数据)是大部分数据库系统(如SQL Server、Oracle)的默认隔离级别(但不是 MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已提交事务所做的改变。这种隔离级别可以避免脏读 现象,但可能出现不可重复读和幻影读,因为同一事务的其它实例在该实例处理期间可能会有新COMMIT,所以同一 查询可能返回不同结果。
4. REPEATABLE READ隔离级别
REPEATABLE READ(可重复读)是MySQL的默认事务隔离级别,它确保在同一事务内相同的查询语句的执行结果 一致。这种隔离级别可以避免脏读以及不可重复读的现象,但可能出现幻影读现象。
5. SERIALIZABLE隔离级别
SERIALIZAL是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突。简单来说,它是在每个读的数据行上 加上共享锁。在这个级别中,可能会导致大量的锁等待现象。该隔离级别主要用于分布式事务。
SERIALIZAL隔离级别可以有效的避免幻影读现象,但是会降低MySQL的并发访问性能,因此,不建议将事务的隔离 级别设置为SERIALIZAL。