什么是事务?
事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。数据库事务通常包含了一个序列的对数据库的读/写操作。包含有以下两个目的:
- 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
- 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。
隔离性与隔离级别
提到事务,你肯定会想到acid(atomicity、consistency、isolation、durability,即原子性、一致性、隔离性、持久性),今 天我们就来说说其中i,也就是“隔离性”。当数据库上有多个事务同时执行的时候,就可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读 (phantom read)的问题,为了解决这些问题,就有了“隔离级别”的概念。隔离级别做的越强则性能就越不好,所以要在性能与隔离级别中取一个平衡点。sql标准的事务隔离级别包括:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交 | 可以出现 | 可以出现 | 可以出现 |
读提交 | 不允许出现 | 可以出现 | 可以出现 |
可重复读 | 不允许出现 | 不允许出现 | 可以出现 |
序列化 | 不允许出现 | 不允许出现 | 不允许出现 |
主要是读已提交和可重复读比较难区分,所以我们看个小例子。先创建一张表,并插入数据1
create database test; use test; create table test(id int primary key); insert into test(id) values(1);
事务a | 事务b |
启动事务查询得到1 | 启动事务 |
查询得到1 | |
将1改为2 | |
查询得到v1 | |
提交事务b | |
查询得到v2 | |
提交事务a | |
查询得到v3 |
我们来看看在不同的隔离级别下,事务a会有哪些不同的返回结果,也就是图里面v1、v2、v3的返回值分别是什么。
数据库里面会创建一个视图,访问的时候以视图的逻辑结果为准。在“可重复读”隔离级别下,这个视图是在事务启 动时创建的,整个事务存在期间都用这个视图。在“读提交”隔离级别下,这个视图是在每个sql语句开始执行的时候创建的。 这里需要注意的是,“读未提交”隔离级别下直接返回记录上的最新值,没有视图概念;而“串行化”隔离级别下直接用加锁的方式来避免并行访问。
那什么时候需 要**“可重复读”**的场景呢?
假设你在管理一个个人银行账户表。一个表存了每个月月底的余额,一个表存了账单明细。这时候你要做数据校对,也就是判断上个月的余额和当前余额的差额,是否与本月的账单明细一致。你一定希望在校对过程中,即使有用户发生了一笔新的交 易,也不影响你的校对结果。
事务隔离的实现
在mysql中,实际上每条记录在更新的时候都会同时记录一条回滚操作。记录上的最新值,通过回滚操作,都可以得到前一个状态的值。假设一个值从1被按顺序改成了2、3、4,在回滚日志里面就会有类似下面的记录。
当前值是4,但是在查询这条记录的时候,不同时刻启动的事务会有不同的read-view。如图中看到的,在视图a、b、c里面, 这一个记录的值分别是1、2、4,同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(mvcc)。对于 read-view a,要得到1,就必须将当前值依次执行图中所有的回滚操作得到。即使现在有另外一个事务正在将4改成5,这个事务跟read-view a、b、c对应的事务是不会冲突的。
回滚日志总不能一直保留吧,什么时候删除呢?
在不需要的时候才删除。也就是说,系统会判断,当没有事务再需要用到这些回滚日志时,回滚日志会被删除。
什么时候才不需要了呢?
就是当系统里没有比这个回滚日志更早的read-view的时候。
为什么尽量不要使用事务?
事务意味着系统里面会存在很老的事务视图,在这个事务提交之前,回滚记录都要保留, 这会导致大量占用存储空间。除此之外,事务还占用锁资源,可能会拖垮库。
以上就是关于msyql事务隔离你要知道的详细内容,更多关于mysql事务隔离的资料请关注移动技术网其它相关文章!
如对本文有疑问, 点击进行留言回复!!
SqlServer2008实例35排名搜索之根据权值返回排名搜索结果
com.alibaba.druid.sql.parser.ParserException: syntax error, error in :‘xx)
PLSQL Developer 13 报错“数据库字符集(AL32UTF8)和客户端字符集(2%)是不同的。字符集转化可能会造成不可预期的后果“
SQL注入--利用floor(rand(0)*2)报错返回信息
Oracle SQL nvl(),listagg() within group(),TO_CHAR(),CASE WHEN THEN ELSE END
SqlServer2008实例32全文索引和全文目录之从全文索引中去掉普通字符串
网友评论