事务的四大特性(ACID):
- 原子性(Atomicity):
多个操作要么全部成功,要么全部失败
- 一致性(Consistency):
保证数据的一致性,不允许出现数据不一致的情况。事务结束时,所有内部结构(如B树索引或双向链表)都必须正确
- 隔离性(Isolation):
并发执行的事务不会相互影响。由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态,要么另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。这为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执的状态相同。
- 持久性(Durability):
事务一旦提交,对数据库的更新就是持久的
事务的最终目的就是为了保证数据的一致性,所以一致性是事务最重要的特性
事务并发可能产生的问题:(在不考虑事务隔离的情况下)
- 脏读:
脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
- 不可重复读:
不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。
- 幻读/虚读:
是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
不可重复读与幻读的区别:
不可重复读的重点是修改,同样的条件,你读取过的数据,再次读取出来发现值不一样;(主要在于update和delete)
幻读的重点在于新增或者删除,同样的条件,第 1 次和第 2 次读出来的记录数不一样。(主要在于insert)
事务的隔离级别:(为了解决上面说的并发所导致的问题,就需要设置数据的隔离级别)
- Read uncommitted:读未提交,最低级别,以上情况都无法保证
- Read committed:读已提交,防止数据脏读
实现机制:修改时加排他锁,直到事务提交后才释放,读取时加共享锁,读取完释放。事务1读取数据时加上共享锁后(这 样在事务1读取数据的过程中,其他事务就不会修改该数据),不允许任何事物操作该数据,只能读取,之后1如果有更新操作,那么会转换为排他锁,其他事务更 无权参与进来读写,这样就防止了脏读问题。 但是当事务1读取数据过程中,有可能其他事务也读取了该数据,读取完毕后共享锁释放,此时事务1修改数据,修改 完毕提交事务,其他事务再次读取数据时候发现数据不一致,就会出现不可重复读问题,所以这样不能够避免不可重复读问题。
- Repeatable read:
实现机制:读取数据时加共享锁,写数据时加排他锁,都是事务提交才释放锁。读取时候不允许其他事物修改该数据,不管数据在事务过程中读取多少次,数据都是一致的,避免了不可重复读问题。
- Serializable:
实现机制:所有的读操作均为当前读,读加读锁 (S锁),写加写锁 (X锁)。采用的是范围锁RangeS RangeS_S模式,锁定检索范围为只读,这样就避免了幻影读问题。
Serializable隔离级别下,读写冲突,因此并发度急剧下降,在MySQL/InnoDB下不建议使用。
MySQL数据库设置事务隔离级别:(设置数据库的隔离级别要在开启事务之前)
set [global | session] transaction isolation level 隔离级别名称; 或 set tx_isolation='隔离级别名称'
set transaction isolation level repeatable read;
ADO.NET设置事务隔离级别:
var tran = conn.BeginTransaction(IsolationLevel.ReadUncommitted)
参考:https://www.cnblogs.com/jieerma666/p/10805578.html