标签:假设 就是 version 应该 编程 二次 myisam oracle 共享锁
引言:
在写“事务”之前要说一点,对于 MySQL 而言 InnoDB 引擎支持事务,而 MyISAM 引擎是不支持事务的。下面会从事务的基本概念入手,对事务的特性以及其特性带来的一些问题进行详细介绍。
事务是指逻辑上的一组操作
事务是一个不可分割的工作单位,事务中的操作要么都成功,要么都失败。
事务发生前后数据的完整性必须保持一致。例:A:200,B:200,A、B之间无论怎么交换,最终都要保证和是 400。
多事务并发访问数据库时,一个事务不能被其他事务所干扰,多个并发事务之间数据要相互隔离。如果不考虑隔离性,会引发诸多安全问题,比如下:脏读、不可重复读、幻读(虚读),下面会对其展开介绍。
一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
不考虑隔离性会带来如下几个问题:脏读、不可重复读、幻读(虚读)
A 事务读取了 B 事务 update 但还未 commit 的数据,如果 B 事务回滚,那么 A 事务刚才读到的数据就会消失。
A 事务第一次查询到一条记录后,此时 B 事务更新了该条记录后进行 commit,A 事务接着进行第二次查询发现该记录数据变了,不可重复读就发生了。(强调的是读到了其他事务的已经提交的 update 的数据)
A 事务第一次查询到了两行记录,此时 B 事务插入(insert)一条记录后进行 commit, A 事务接着进行查询发现有三行记录,幻读就发生了。(强调的是读到了其他事务已经提交的 insert 的数据)
(4)针对不可重复读有以下几点思考:
????? ①:一个业务开启了一个事务(A),在 A 事务中首先查询某一条数据(时间点1),在此之后有另一个事务(B)对这条记录进行了修改(时间点2)并且修改完立即提交(提交的时候事务 A 还未提交),此时在事务 A 中如果有业务需要再进行查询该条数据就会发生不可重复读。这是写程序要考虑的,但是 Repeatedable Read 已经为我们防止了该问题。但是对于 Oracle 数据库是没有实现该隔离级别的,所以编程时还得注意。
????? ②:在 ① 中时间点2处默认是针对那一行获取排他锁的(假设在时间点1处,该 select 语句加了 FOR UPDATE 排他锁,那么 B 事务只能等待 A 事务结束,注意锁的释放不是根据该查询语句的结束而结束(所以并不是 select ... for update 查询结果出来了锁就释放了),而是根据该事务的结束而结束),因为 B 事务是 update 语句默认对操作的记录加排他锁的,而一条记录只能被加一个排他锁(共享锁可以加多个,排他锁只能加一个;对应的数据记录如果加了排他锁之后就不能够加任何锁了,包括共享锁。)
这里有一个点要提一下:隔离性具体是怎么实现的?(锁和 MVCC)这个在下一章
(3)MySQL 事务的四种隔离级别:
?????持久性(Durability):
?????SQL 标准定义了 4 类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。
Read Uncommitted(读取未提交内容)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
标签:假设 就是 version 应该 编程 二次 myisam oracle 共享锁
原文地址:https://www.cnblogs.com/tkzL/p/11259432.html