SQL之事务处理

什么是事务(transaction)?
事务就是几条SQL语句序列,是一个逻辑单元,不可分割的逻辑单元,要么全部执行,要么都不执行。比如银行账户转账,A给B转100元,实际动作有,A的存款数据减少100,接着B的存款数据加100。如果中间发生故障,B没有收到钱,A的存款却减少了,这就产生了不一致性。事务处理就是为了防止这类情况的发生,遇到故障回滚,回滚到A转钱的操作之前。

事务的四大特性,经典知识点:ACID。即
原子性:即事务的每个元素是一个整体,不可分,一旦某个元素失败,就必须整体回滚。默认情况下一条SQL就是一个单独事务,事务是自动提交的。只有显式的使用start transaction开启一个事务,才能将一个代码块放在事务中执行。
一致性:就像A,B账户的钱,事务完成后存款总额数据保持一致
隔离性:不同并发事务之间是独立的,不依赖的,比如一个事务X修改数据,而其他事务Y需要使用这些数据,那么X可以在Y完成之前或之后进行,不会在中间状态进行。不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。
持久性:该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

事务最复杂问题都是由事务隔离性引起的。完全的隔离性是不现实的,完全的隔离性要求数据库同一时间只执行一条事务,这样会严重影响性能。
关于隔离性中的事务隔离等级:
1Read uncommitted(读未提交) :如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据,该隔离级别可以通过“排他写锁”,但是不排斥读线程实现。这样就避免了更新丢失,却可能出现脏读,也就是说事务B读取到了事务A未提交的数据。

2 Read committed(读提交):如果是写事务将会禁止其他事务访问该行数据,该隔离级别避免了更新丢失和脏读,但是可能出现不可重复读。事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。(读的时候,允许其他读写事务)

3 Repeatable read(可重复读取):可重复读取是指在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别。
解决了更新丢失、脏读、不可重复读、但是还会出现幻读
事务A 按照一定条件进行数据读取, 期间事务B 插入了相同搜索条件的新数据(注意,A只对某一行进行读写锁定,不影响B添加新行),事务A再次按照原先条件进行读取时,发现了事务B 新插入的数据 称为幻读

  1. Serializable(可序化)
    提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,效率很低。一般行级锁无法实现可序列化,要用表级锁。

脏读就是读了错误的信息,因为别人修改了,只是还没提交修改而已;不可重复读是在读的过程中,被别人修改了,第二次读不到了;幻读是读的时候,别人添加了相同的信息,虽然读到,但实际上不是原来的那一行数据了。

MySQL中支持事务地存储引擎有InnoDB ,InnoDB存储引擎管理事务主要通过UNDO日志和REDO 日志实现。
UNDO日志:复制事务执行前的数据,用于在事务发生异常时回滚数据。
REDO日志:记录在事务执行中,对数据进行的每条更新操作,当事务提交时,该内容将被刷新到磁盘。
也就是说,在MYsql中,先把数据的变化记录到日志中,如果事务完成提交,就把日志的更新刷新到磁盘上,回退就是将更新删除。这是一种用日志记录更新的方式。

-- 标识事务的开始
start transactionbegin

使用 ROLLBACK(回退:用来管理insert 、update、delete 语句)
ROLLBACK 只能在一个事务处理内使用,也就是在执行了一条start transaction之后,将start transaction 之后的所有语句回退。对于,create,drop,select无法回退。

-- 开启事务
start transaction;
-- 在事务中删除 ordertotals
 delete from ordertotals;
-- 查看一下还有没
select * from ordertotals;
-- 回退,反悔了不能删除
 rollback;

使用COMMIT(提交)
在事务处理块中,提交不会隐含地进行,为了进行明确的提交,要使用commit 语句。

start transaction;
-- 删除明细表中
 delete from orderitems where order_num = 20007;
-- 删除订单表中
delete from orders where order_num = 20007;
-- 提交
 commit

这个事务确保信息在两个表中都删除了才提交,如果第一个成功,第二个删除不成功则不会提交,而是回退到事务执行之前。

使用保留点(savepoint)
简单的rollback 和commit 语句就可以写入或撤销整个事务处理,但是更复杂事务处理可能会部分提交或回退,所以引入了保留点。
为了支持回退部分事务处理,必须能在事务处理块中合适的位置防止占位符,这样如果需要回退,就可以回退到某个占位符。而这些占位符就称为保留点(创建时可以使用 savepoint 声明)

-- 创建保留点
savepoint 保留点名

-- 回退到保留点
rollback to 保留点名

(每个保留点的名字必须要唯一而且要有意义,以便在回退时,MySQL知道回到哪,我们也知道回退到哪)

几个要点:
1、事务要尽可能简短、访问数据量尽可能少。因为满足事务的ACID特性,就必须牺牲一定的并发性能。
2、查询数据时不要使用事务。因为查询不更新表,回退是没用的。
3、在事务处理过程中尽量不要出现等待用户输入地操作,会造成阻塞。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值