.Net系列 Transaction 事务

Transactions

事务(Transaction),通常是指要作的或所作的事情。在计算机术语中是指访问并可能更新数据库中各类数据项的一个程序执行单元(unit)。在计算机术语中,事务一般就是指数据库事务。数据库

应用场景:

应用程序须要执行多个操做,包括一个或多个数据库命令
* 其中一个数据库命令失败或某些其余操做失败(例如注册表更新)
* 多项行动是为了一块儿工做。应用程序如今处于不一致的状态。
咱们使用 transaction 来解决这个问题,transaction 就是执行所需的一组命令原子操做
➢若是全部命令都成功完成,则 transaction 成功。
➢若是有任何命令失败,整个 transaction 将 rollback 到 pre-transaction 状态。
➢形成rollback的故障不必定与数据库相关。并发

ACID transaction properties 属性

All database management systems adhere to a set of properties known as the ACID properties:
并不是任意的对数据库的操做序列都是数据库事务。数据库事务拥有如下四个特性,习惯上被称之为ACID特性ui

Atomicity: “All or nothing.” No partial success. Either the transaction succeeds in its entirety or it fails.
原子性(Atomicity):事务做为一个总体被执行,包含在其中的对数据库的操做要么所有被执行,要么都不执行。this

Consistency: Integrity constraints are met. Acceptable for inconsistency to occur during the transaction, but must be completely consistent upon completion.
一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另外一个一致状态。一致状态的含义是数据库中的数据应知足完整性约束。spa

Isolation: The extent to which other transactions can “see” changes made by other transactions while they are executing.
隔离性(Isolation):多个事务并发执行时,一个事务的执行不该影响其余事务的执行。.net

Durability: Guarantees permanent survival of data after the commit is complete.
持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中3d

.NET 页、XML Web services方法或 .NET Framework 类一旦被标记为参与事务,它们将自动在事务范围内执行。您能够经过在页、XML Web services 方法或类中设置一个事务属性值来控制对象的事务行为。特性值反过来肯定实例化对象的事务性行为。所以,根据声明特性值的不一样,对象将自动参与现有事务或正在进行的事务,成为新事务的根或者根本不参与事务。声明事务属性的语法在 .NET Framework 类、.NET 页和 XML Web services 方法中稍有不一样。orm

Isolation Level 事务隔离层级

A property of the TransactionScope object, specifying the degree of transaction isolation.
隔离级别定义了事务与事务之间的隔离程度。
隔离级别与并发性是互为矛盾的:隔离程度越高,数据库的并发性越差;隔离程度越低,数据库的并发性越好。server

Serializable (highest): read, write, and range locks (if necessary) used until end of the transaction.
序列化:提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。仅仅经过“行级锁”是没法实现事务序列化的,必须经过其余机制保证新插入的数据不会被刚执行查询操做的事务访问到。对象

RepeatableRead: Same, except no range locks. Other transactions can delete/update resulting in phantom reads.
可重复读取:禁止不可重复读取和脏读取,可是有时可能出现幻读数据。这能够经过“共享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但容许读事务),写事务则禁止任何其余事务。

Snapshot: Instead of write-locking, “snapshot” of to-be-written data is taken and served to reading transactions.
“snapshot” 取代 write-locking写锁定,获取待写入数据的 snapshot 并将其送达
reading transactions。这个实际上是tradeoff,并无复制全部的数据,
搞清楚OS中的 readlock,writelock, rangelock。
读取数据时,能够保证读操做读取的行是事务开始时可用的最后提交版本。这意味着这种隔离级别能够保证读取的是已经提交过的数据,而且能够实现可重复读,也能确保不会幻读。

ReadCommitted: No dirty reads (not-yet-committed data from other transactions not visible), but non-repeatable reads may occur. (Default IL for SQL Server)
受权读取:在commit以前,不容许dirty read(还没有提交的其余交易数据不可见)。但可能会发生不可重复的读取,由于反复读取会有不同的结果。 (SQL Server的默认level)容许不可重复读取,但不容许脏读取。这能够经过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务容许其余事务继续访问该行数据,可是未提交的写事务将会禁止其余事务访问该行。

ReadUncommitted (lowest): Dirty reads permitted. One transaction can see another transaction’s changes before the commit.
未受权读取: 容许脏读,但不容许更新丢失。若是一个事务已经开始写数据,则另一个事务则不容许同时进行写操做,但容许其余事务读此行数据。该隔离级别能够经过“排他写锁”实现。无论事务B什么时候Commit,事务A中的SELECT语句2均可以读出数据(有多是脏数据,因事务B可能会ROLLBACK),且与语句1的数据不一样。

 

Isolation Levels Illustrated

这个图按照时间顺序,上至下操做。
1. UnCommitted level时,只要A作出了更改,B就会读取到这个更改,不存在Commit的考虑。

Committed level时,T1读取了数据A,T2获得同样数据A。T1把数据修改成数据B,T2再读取依然是数据A。commit以后,T2 就会获得数据B。不可重复读。

RepeatableRead和Serializable level时,区别在于Range Lock。T2 在commit以前,读取的都是未修改的数据A。

选择什么level不少程度上取决于咱们对数据变化的重视程度。

 

下面是个例子:

 

关于 三种 读

脏读 :脏读就是指当一个事务正在访问数据,而且对数据进行了修改,而这种修改尚未提交到数据库中,这时,另一个事务也访问这个数据,而后使用了这个数据。

不可重复读 :是指在一个事务内,屡次读同一数据。在这个事务尚未结束时,另一个事务也访问该同一数据。那么,在第一个事务中的两 次读数据之间,因为第二个事务的修改,那么第一个事务两次读到的的数据多是不同的。这样就发生了在一个事务内两次读到的数据是不同的,所以称为是不 可重复读。例如,一个编辑人员两次读取同一文档,但在两次读取之间,做者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。若是 只有在做者所有完成编写后编辑人员才能够读取文档,则能够避免该问题。

幻读 : 幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,好比这种修改涉及到表中的“所有数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,之后就会发生操做第一个事务的用户发现表中还存在没有修改的数据行,就好象发生了幻觉同样.通常解决幻读的方法是增长范围锁RangeS,锁定检索范围为只读,这样就避免了幻读。

最高隔离级别SERIALIZABLE_READ能够保证不出现幻读的问题。

 

Transactions in EF

在Entity Framework中使用 transaction 更容易:事务自动发生在同一个事务中上下文。

SaveChanges 就自动有了transaction,是readcommitted level。
* Transactions using this technique are limited to the scope of the context in the using clause
* Transactions spanning multiple contexts require heavier artillery: TransactionScope
- You must add the reference System.Transactions
* Connecting to multiple databases requires enabling MSDTC on the server.

 

在EF版本6中:


SaveChanges以后还要Commit。
Try block以后Catch,任何问题发生均可以rollback。

 

若是咱们但愿用其余level的isolation,则须要用TransactionScope object:
这里有 TransactionScope constructor。
须要两个参数,一个是new,一个是transaction option object 设置 isolation level,这里设置成最低的 Uncommitted。

下面的例子并未完成,由于没有rollback

 

Change tracking

当修改EF对象或从容器中添加/删除EF对象时…
* Changes are tracked locally by the context
* You can stop change tracking by detaching an entity from the context. (example to follow)

Calling SaveChanges does the following:
* Generates and executes SQL commands 生成并执行SQL命令
* Commits changes to the database in a single transaction 在单个事务中提交对数据库的更改
* Resets tracking information重置跟踪信息

改变跟踪 attaching/detaching 例子


c2 脱离了,改变再也不被记录。Savechanges时,只有c1 会被记载,c2仍是会被放在course的container里,在Course里仍是能够看见c1和c2,可是数据库里只有c1。

--------------------- 原文:https://blog.csdn.net/CheungKaiwei/article/details/79775156 做者:CheungKaiwei 

相关文章
相关标签/搜索