文章目录
- 事务在并发执行时遇到的问题
-
- 脏读【读取数据未提交】
- 不可重复读【前后多次读取,数据内容不一致】
- 幻读【前后多次读取,数据总量不一致】
- 数据库事务隔离级别
-
- 未提交读
- 读已提交 Read Committed
- 可重复读 Repeatable Read
- 可串行化 Serializable
- 锁
事务在并发执行时遇到的问题
我们需要舍弃一部分的来换取数据库的并发的性能,怎么个舍弃法呢看一下访问相同数据的事务在不保证串行执行(也就是执行完一个再执行另一个)的情况下可能会出现哪些问题:
脏读【读取数据未提交】
一个事务读取另外一个事务未提交的更新事务。
事务1 | 事务2 |
---|---|
select age from table1 where id = 1 – 结果是 20 | |
update table1 set age = 30 where id = 1 – 这里没有提交 | |
select age from table1 where id = 1 – 结果是 30 | |
事务2回滚 | |
备注 | 正常事务1 的结果应该是20 |
这里的事务1就读取了一条脏数据。 – 脏读
不可重复读【前后多次读取,数据内容不一致】
在一个事务范围内, 同样的两次查询得到不同的结果。这里是由于系统中其他的事务提交引起的。
事务1 | 事务2 |
---|---|
select age from table1 where id = 1 – 结果是 20 | |
update table1 set age = 30 where id = 1 – 这里提交了 | |
select age from table1 where id = 1 – 结果是 30 | |
备注 | 按照正确逻辑,事务A前后两次读取到的数据应该一致 |
幻读【前后多次读取,数据总量不一致】
幻读是不可重复读的一种特殊情况, 在同一个事务范围内, 查询两次结果得到条数不一样。
事务1 | 事务2 |
---|---|
select count(*) from table1 结果是 20 | |
insert into table1 value(9,…) – 这里提交了 | |
select count(*) from table1 – 结果是 21 | |
备注 | 按照正确逻辑,事务A前后两次读取到的数据总量应该一致 |
数据库事务隔离级别
事务的指的是什么:并发执行的时候,事务是相互隔离的,一个事务的执行不能被其他的事务干扰。
什么是数据库隔离级别
- 我们知道是一个架构的软件,对于同一个服务器来说,可以有若干个客户端与之连接,每个客户端与服务器连接上之后,就可以称之为一个会话()。
- 每个客户端都可以在自己的会话中向服务器发出请求语句,一个请求语句可能是某个事务的一部分,也就是对于服务器来说可能同时处理多个事务。
- 在事务简介的章节中我们说过事务有一个称之为的特性,理论上在某个事务对某个数据进行访问时,其他事务应该进行排队,当该事务提交之后,其他事务才可以继续访问这个数据。但是这样子的话对性能影响太大,我们既想保持事务的,又想让服务器在处理访问同一数据的多个事务时性能尽量高些,鱼和熊掌不可得兼,舍一部分而取性能者也。
未提交读
一个事务可以读取另外一个事务未提交的事务。
1.事务在读数据时候没有加锁。
2.在修改数据的时候只是对事务增加行级共享锁。产生现象:
事务1在读取的时候, 事务2也可以进行读取以及修改。(事务在读取的时候是不加锁的)
事务2在这条记录进行修改时候, 事务1可以进行读取。(因为事务在修改的时候只是加了共享锁),
所以,这样就会产生脏读。
当隔离级别设置为Read uncommitted 时,就可能出现脏读,如何避免脏读,请看下一个隔离级别。
读已提交 Read Committed
读已提交是PostgreSQL里的缺省隔离级别。
当一个事务运行在这个隔离级别时, SELECT查询(没有FOR UPDATE/SHARE子句)只能看到其它事务已提交的数据。
实际上,SELECT 查询看到一个在查询开始运行的瞬间该数据库的一个快照。 不过,SELECT看得见其自身所在事务中之前的更新的执行结果,即使它们尚未提交。
请注意, 在同一个事务里两个相邻的SELECT命令可能看到不同的快照,因为其它事务会坑你在两个SELECT执行期间提交。
不会出现可脏读,但是不可重复读
可重复读 Repeatable Read
即使数据被其他事物修改, 当前事务也不会读取到新的数据
重复读事务中的查询看到的是事务开始时的快照, 而不是该事务内部当前查询开始时的快照,这样, 同一个事务内部后面的SELECT命令总是看到同样的数据,
也就是说,它们看不到 它们自身事务开始之后提交的其他事务所做出的改变。
不会出现可脏读, 可重复读, 可以幻读
可串行化 Serializable
可串行化级别提供最严格的事务隔离。这个级别为所有已提交事务模拟串行的事务执行, 就好像事务将被一个接着一个那样串行(而不是并行)的执行。
不过,正如可重复读隔离级别一样, 使用这个级别的应用必须准备在串行化失败的时候重新启动事务。
事实上,该隔离级别和可重复读希望的完全一样, 它只是监视这些条件,以所有事务的可能的序列不一致的(一次一个)的方式执行并行的可串行化事务执行的行为。
这种监测不引入任何阻止可重复读出现的行为,但有一些开销的监测,检测条件这可能会导致串行化异常 将触发串行化失败。
锁
锁就是防止其他事务访问指定的资源的手段。锁是实现并发控制的主要方法,是多个用户能够同时操纵同一个数据库中的数据而不发生数据不一致现象的重要保障。 一般来说,锁可以防止脏读、不可重复读和幻觉读。
文章知识点与官方知识档案匹配,可进一步学习相关知识MySQL入门技能树数据库组成表33031 人正在系统学习中
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!