第9章 MySQL中的事务及并发控制
事务是多用户系统的一个数据操作基本单元,一个事务在执行过程中对资源的占用方式是动态的,同一时刻需要的资源是有限的。如果事务按串行的方式执行,那么系统资源会大量处于空闲状态,为了提高系统资源的利用率,充分实现数据资源的共享,应允许多个事务并行地执行。
因此,数据库管理系统必须对多事务的并发操作加以控制,提供一整套完善的并发控制机制,以防止多用户并发使用数据库时造成数据错误和程序运行错误,从而保证数据的完整性。
【学习目标】
●事务的概念及事务的ACID特性:原子性、持久性、隔离性和一致性
●事务SQL控制语句
●事务的可串行化调度
●并发操作的三种问题:丢失修改、读脏数据和不可重复读
●MySQL中的封锁机制及三个级别封锁协议
9.1 事务
9.1.1 事务的概念
如果一个业务逻辑中包含的若干操作,要么都成功执行要么不执行其中任何一个操作,是一个不可分割的工作单元,那么这组操作序列我们定义为事务。
9.1.2 事务的ACID特性
事务是用户定义的一组操作序列,这些操作要么全做要么全不做,事务的四个特性包括:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。
1. 原子性:事务里面的操作要么都执行,要么都不执行
2. 一致性:事务执行之前和执行之后数据库状态保持一致
3. 隔离性:一个事务的执行不被其他事务干扰
4. 持久性:事务对数据库的改变是永久性的
9.1.3 MySQL事务控制语句
random函数怎么限制范围MySQL中可以使用BEGIN开始事务,使用COMMIT结束事务,中间可以使用ROLLBACK回滚事务。COMMIT的作用是提交,即提交事务的所有操作,事务提交是将事务中所有对数据的更新写回到磁盘上的物理数据库中去,事务正常结束;ROLLBACK的作用是回滚,即在事务运行的过程中发生了某种故障,事务不能继续执行,系统将事务中对数据库的所有已完成的操作全部撤销,回滚到事务开始时的状态。
1. 事务 SQL 控制语句
• START TRANSACTION (或 BEGIN ):显式开始一个新事务
• SAVEPOINT :分配事务过程中的一个位置,以供将来引用
• COMMIT :永久记录当前事务所做的更改
• ROLLBACK :取消当前事务所做的更改
• ROLLBACK TO SAVEPOINT :取消在 savepoint 之后执行的更改
• RELEASE SAVEPOINT :删除 savepoint 标识符
• SET AUTOCOMMIT :为当前连接禁用或启用默认 autocommit 模式
2. AUTOCOMMIT 模式
MySQL默认操作模式就是autocommit自动提交模式,这表示除非显式地开始一个事务,否则每个查询都被当做一个单独的事务自动执行。我们可以通过设置autocommit的值改变是否是自动提交autocommit模式。应注意,在一个表上利用事务处理业务逻辑时,要确保你所操作的表是支持事务处理的,否则, autocommit的值对执行结果没有任何影响。
【例9-1】查看当前会话的autocommit值,往职工表中插入两条记录(职工号:w13,姓名:王小小)和(职工号:w14,姓名:张婷婷),输出职工表的数据,然后执行回滚操作,再次输出职工表的数据。
show variables like '%autocommit%';
insert into 职工(职工号,姓名) values('w13','王小小');
insert into 职工(职工号,姓名) values('w14','张婷婷');
select * from 职工;
rollback;
select * from 职工;
3. 事务的显示提交和隐式提交
事务的显示提交命令是COMMIT,在非autocommit模式下,要将一个事务包含的若干条语句执行结果永久写入到数据库中,可以使用COMMIT命令显示提交事务。
在MySQL中,下面两个事务控制语句具有隐式提交并进而终止当前事务的作用:BEGIN/START TRANSACTION和 SET AUTOCOMMIT=1。
4. 事务的定义和使用
【例9-3】在“银行系统”数据库中,有一张表“账户”,其中有A、B两个人的账户余额信息,表中的数据如图9-6所示。定义一个事务,包含两个操作:从A账户余额扣除1000;从B账户余额增加1000。
start transaction;
update 账户
set 余额=余额-1000
where 账户名='A';
update 账户
set 余额=余额+1000
where 账户名='B';
commit;
select * from 账户;
【例9-4】假设由于某种原因,A账户上的余额只扣除了1000而B账户上的余额却增加了1500,导致转账操作出错,则撤销回滚事务,A和B账户上的余额保持转账操作前的值。
start transaction;
update 账户
set 余额=余额-1000
where 账户名='A';
update 账户
set 余额=余额+1500
where 账户名='B';
rollback;
select * from 账户;
【例9-5】为了模拟A账户余额不足的情况,先将A账户的余额从现在的1000改为800,B账户上的余额是4000。定义一个事务,先将B账户的余额增加1000,然后再将A账户的余额扣除1000,此时由于账户表上的触发器(余额不能小于0)保护,导致A账户的扣款操作失败,最后用rollback命令撤销回滚事务,A和B账户上的余额保持转账操作前的值。
start transaction;
update 账户
set 余额=余额+1000
where 账户名='B';
update 账户
set 余额=余额-1000
where 账户名='A';
9.1.4 事务的调度
在数据库系统中,往往有多个事务同时提出处理请求,这时需要决定这些事务的执行顺序,这就是事务的调度。基本的事务调度方式有两种:串行和并行。
如果一组事务按并行调度的方式执行,不同事务的指令是交叉处理的,那么调度的策略比串行要多得多,但不能保证每种调度的执行结果都是正确的,当且仅当其结果与按某一次串行地执行它们时的结果相同,我们称这种调度策略为可串行化(serializable)的调度。
可串行化是并发事务正确性的准则,判断一个并发调度是否正确的充要条件是它是否是可串行化的。
php与mysql连接 表9-1 串行调度和并行调度
T1 T2 | T1 T2 | T1 T2 php兼职程序员 | T1 T2 | ||||
读A=2000 A=A-100 写A=1900 读B=2500 B=B+100 写B=2600 | 读A=1900 A=A*1.05 写A=1995 读B=2600 B=B*1.05 写B=2730 | 读A=2100 A=A-100 写A=2000 读B=2625 B=Btcp三次握手详细过程+100 写B=2725 | 读A=2000 A=A*1.05 写A=2100 读B=2500 B=B*1.05 写B=2625 | mysql语句顺序 读A=2000 A=A-100 写A=1900 读B=2500 B=B+100 写B=2600 | 读A=1900 A=A*1.05 写A=1995 读B=2600 B=B*1.05 写B=2730 | 读A=2000 A=A-100 写A=1900 读B=2500 B=B+100 写B=2600 | 读A=java运行时环境2000 A=A*1.05 写A=2100 读B=2500 B=B*1.05 写B=2625 |
串行调度1 | 串行调度2 | 并行调度1 | 并行调度2 | ||||
9.2 并发操作的可能问题
当多个用户并发地存取数据库时,就可能出现多个事务同时存取同一数据的情况,事务的并发操作可能带来以下三个问题:丢失修改、读脏数据和不可重复读。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论