.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特性

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

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

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

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

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

Isolation Level 事务隔离层级

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

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

原文地址:https://www.cnblogs.com/zhurong/p/10453700.html

时间: 2024-11-14 11:28:06

.Net系列 Transaction 事务的相关文章

Innodb 锁系列2 事务锁

上一篇介绍了Innodb的同步机制锁:Innodb锁系列1 这一篇介绍一下Innodb的事务锁,只所以称为事务锁,是因为Innodb为实现事务的ACID特性,而添加的表锁或者行级锁. 这一部分分两篇来介绍,先来介绍下事务锁相关的数据结构 事务锁数据结构 1. 锁模式 /* Basic lock modes */ enum lock_mode { LOCK_IS = 0, /* intention shared */ LOCK_IX, /* intention exclusive */ LOCK_

Transaction事务注解和DynamicDataSource动态数据源切换问题解决

问题描述: 写主库开事务的情况下会导致时不时的将更新/插入操作写入到从库上, 导致mysqlException 问题原因: jetty的工作队列会重用处理线程, 导致threadLocal被重用, 然而transaction注解在service层, 他会在DynamicDataSourceSwitch被设置之前直接去threadlocal拿数据, 本应拿到null, 但是拿到了之前线程的值 一般代码调用链: [email protected](AOP)-->DefaultSqlSession--

Spring Transaction 事务模拟

事务,是描述一组操作的抽象,比如对数据库的一组操作,要么全部成功,要么全部失败. 事务有四个特性: Atomicity(原子性),Consistency(一致性),Isolation(隔离性),Durability(持久性) Spring对事务的支持很强大,但是从本质上来说,事务是否生效取决于数据库底层是否支持(MySQL的MyISAM引擎不支持事务), 同时,一个事务的多个操作需要在同一个connection上.下面手写一个Demo分析Spring事务底层实现. 工程结构 connection

Spring transaction事务之roll back回滚

转自:http://blog.csdn.net/lovejavaydj/article/details/7635848 试验方法: 写一个单元测试,调用一个service层方法(发生对数据库进行写操作的方法--insert.update.delete)即可. 试验过程: 定义一个service方法如下: public SMSTiming createSMSTiming(SMSTiming smsTiming){ SMSTiming s= this.getSmsTimingDAO().create

MSSQL Transaction[事务] and Procedure[存储过程]

1 --事务分三种 2 --1.显示事务 3 --我们手动begin transaction ...... commit transaction/rollback transaction 4 --上面这种写法叫做“显示事务” 5 6 --2.隐式事务 7 SET IMPLICIT_TRANSACTIONS { ON | OFF }隐式事务 8 9 10 --3.自动提交事务,SQL Server默认使用的是自动提交事务. 11 --我们每次执行一条sql语句的时候,sql server都会自动帮

[mybatis-spring] Transaction 事务/事务处理/事务管理器

使用mybatis-spring的主要原因之一就是: mybatis-spring允许mybatis参与到spring 事务中. mybatis-spring leverage[use (something) to maximum advantage)] 存在的DataSourceTransactionManager , 而无需为mybatis特意新建一个新的事务管理. 一旦Spring tansaction manager被配置,你可以像配置Spring中的transactions as yo

transaction事务案例--银行转账

1)dao层 package cn.spring.transaction.dao; public interface MoneyDao { //加钱的方法 void addMoney(double money); //减钱的方法 void subMoney(double money); } 代码实现 (2)daoImpl层 package cn.spring.transaction.dao.impl; import cn.spring.transaction.dao.MoneyDao; impo

C# MVC Transaction 事务

目前MVC有默认事务,在一个using块中dbContext.saveChanges()就是一个默认事务.但是有时候,业务上需要自己写事务. 下面代码块中,使用了MVC默认的事务,我们如果需要获取到student的自增id,需要先savechange:但是有时候多表操作的时候,可能需要获取到自增id后,将id插入别的表中,等多表操作结束后,再一起提交事务. using (DbContext context = new DbContext()) { context.Student.Add(stud

sql事务(Transaction)用法介绍及回滚实例

事务是将一系列操作作为一个单元执行,要么成功,要么失败,回滚到最初状态.在事务处理术语中,事务要么提交,要么中止.若要提交事务,所有参与者都必须保证对数据的任何更改是永久的.不论系统崩溃或是发生其他无法预料的事件,更改都必须是持久的.只要有一个参与者无法做出此保证,整个事务就会失败.事务范围内的所有数据更改将回滚到特定设置点. Begin TRANSACTION 语句1; If @@error<>0 Goto error 语句2; If @@error<>0 Goto error