Mysql事务详解
一、什么是数据库事务?
事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行,因此事务是一个不可分割的工作逻辑单元。
事务具有 4 个特性吗,这 4 个特性通常简称为 ACID。
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
二、原子性
事务是一个完整的操作。事务的各元素是不可分的(原子的)。事务中的所有元素必须作为一个整体提交或回滚。如果事务中的任何元素失败,则整个事务将失败。
以支付宝转账为例,当转账这个事务提交后,两个账号内的数据将会得到更新,如果出于某些原因事务在更新之前终止了,那么不会对两个账号内的数据进行更新。
三、一致性
当事务成功完成时,数据必须再次回到已知的一致状态。通过事务对数据所做的修改不能损坏数据。
比如两个账号内一共200块钱,不管这两个账号之间如何转账,总的资金只能是200块。
四、隔离性
对数据进行修改的所有并发事务是彼此隔离的,这表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务。修改数据的事务可以在另一个使用相同数据的事务开始之前访问这些数据,或者在另一个使用相同数据的事务结束之后访问这些数据。
五、持久性
一个事务成功完成之后,它对数据库所作的改变是永久性的,即使系统出现故障也是如此。也就是说,一旦事务被提交,事务对数据所做的任何变动都会被永久地保留在数据库中。
六、执行事务
Mysql中只有InnoDB支持事务,而且事务是自动提交的。也可以通过BEGIN 或 START TRANSACTION 这个语句显式地标记一个事务的起始点。
使用COMMIT将事务中所有对数据库的更新都写到磁盘上的物理数据库中,事务正常结束。
当事务执行过程中遇到错误时,使用 ROLLBACK 语句使事务回滚到起点或指定的保持点处。同时,系统将清除自事务起点或到某个保存点所做的所有的数据修改,并且释放由事务控制的资源。
七、数据库事务的隔离级别
先看一下,因为隔离级别而可能引发的问题:
脏读:指一个事务读取了另外一个事务未提交的数据。
不可重复读:指在一个事务内读取表中的某一行数据,多次读取结果不同。
幻读:指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致
数据库标准提出了四类隔离级别:
未提交读 :允许一个事务读取到另一个事务未提交的数据。未提交读的有点在于并发能力高,适合对数据一致性没有要求而追求高并发的场景,但他最大的坏处就是会出现脏读。
读已提交:就是一个事务要等另一个事务提交后才能读取数据。可以解决脏读问题,但是会造成不可重复读。 举个例子,程序员卡里有1w块去买东西,刷卡时读卡器检测出卡中有1w,但是此时他媳妇用卡里的1w块补贴家用了,当读卡器扣款时发现卡里居然没钱了(第二次检测金额当然要等待媳妇转出金额事务提交完)。这里就出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。
可重复读 :就是在开始读取数据(事务开启)时,不再允许修改操作。可重复读可以解决不可重复读问题。写到这里,应该明白的一点就是,不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。
串行化:是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。
什么时候会出现幻读?
事例:程序员某一天去消费,花了2千元,然后他的妻子去查看他今天的消费记录(全表扫描FTS,妻子事务开启),看到确实是花了2千元,就在这个时候,程序员花了1万买了一部电脑,即新增INSERT了一条消费记录,并提交。当妻子打印程序员的消费记录清单时(妻子事务提交),发现花了1.2万元,似乎出现了幻觉,这就是幻读。
注意:
大多数数据库默认的事务隔离级别是Read committed,比如Sql Server , Oracle。Mysql的默认隔离级别是可重复读。
八、修改事务的隔离级别
MySQL 提供了 SET TRANSACTION 语句,该语句可以改变单个会话或全局的事务隔离级别。语法格式如下:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
其中,SESSION 和 GLOBAL 关键字用来指定修改的事务隔离级别的范围:
SESSION:表示修改的事务隔离级别将应用于当前 session(当前 cmd 窗口)内的所有事务;
GLOBAL:表示修改的事务隔离级别将应用于所有 session(全局)中的所有事务,且当前已经存在的 session 不受影响;
如果省略 SESSION 和 GLOBAL,表示修改的事务隔离级别将应用于当前 session 内的下一个还未开始的事务。
任何用户都能改变会话的事务隔离级别,但是只有拥有 SUPER 权限的用户才能改变全局的事务隔离级别。
- 点赞
- 收藏
- 关注作者
评论(0)