SQLServer之事务简介
事务定义
事务是单个的工作单元。事务是在数据库上按照一定的逻辑顺序执行的任务序列,既可以由用户手动执行,也可以由某种数据库程序自动执行。
事务分类
自动提交事务
每条单独的语句都是一个事务。
显式事务
每个事务均以 begin transaction 语句显式开始,以 commit 或 rollback 语句显式结束。
隐式事务
在前一个事务完成时新事务隐式启动,但每个事务仍以 commit 或 rollback 语句显式完成。
批处理级事务
只能应用于多个活动结果集 (mars),在 mars 会话中启动的 transact-sql 显式或隐式事务变为批处理级事务。当批处理完成时没有提交或回滚的批处理级事务自动由 sql server 进行回滚。
事务特性
事务是作为单个逻辑工作单元执行的一系列操作。一个逻辑工作单元必须有四个属性,称为原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)属性,只有这样才能成为一个事务。
原子性
事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。
一致性
事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如 b 树索引或双向链表)都必须是正确的。
隔离性
由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务识别数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是第二个事务修改它之后的状态,事务不会识别中间状态的数据。这称为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。
持久性
事务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。
事务隔离
隔离级别用于决定如何控制并发用户读写数据的操作。
读操作默认使用共享锁;写操作需要使用排它锁。
读操作能够控制他的处理的方式,写操作不能控制它的处理方式。
可序列化性
理想情况下,事务应可序列化。 事务被视为可用作按顺序运行它们的结果的同时运行的事务的结果是相同的情况下序列化 — 即,另一个。 它并不重要的事务,则首先执行,仅的结果不会反映任何混合的事务。
事务隔离级别
事务隔离级别隔离成功事务的范围内的一种度量值。 具体而言,事务隔离级别定义由存在以下现象:
-
脏读a脏读事务读取尚未提交的数据时发生。 例如,假设事务 1 更新行。 事务 2 在事务 1 提交更新之前读取更新的行。 如果事务 1 回滚更改,将具有事务 2 读取永远不会视为已存在于数据。
-
不可重复读取a不可重复读事务两次读取同一行,但每次获取不同的数据时发生。 例如,假设事务 1 读取某行。 事务 2 更新或删除该行并提交 update 或 delete。 如果事务 1 重新读取行,它将检索不同的行值或发现该行已被删除。
-
幻影a幻像是与搜索条件匹配,但是最初未检测到的行。 例如,假设事务 1 读取一组满足某些搜索条件的行。 事务 2 生成一个新行 (通过更新或插入) 事务 1 搜索条件相匹配。 如果事务 1 reexecutes 读取这些行的语句,它获取一组不同的行。
- 更新丢失,两个事务同时更新,但由于某一个事务更新失败发生回滚操作,这样有可能的结果就是第二个事务已更新的数据因为第一个事务发生回滚而导致数据最终没有发生更新,因此两个事务的更新都失败了。
根据这些现象定义四个事务隔离级别 (如 sql-92 所定义)。 下表中"x"将标记每个可能发生的现象。
事务隔离级别可能的实现
未提交读
事务不是相互隔离的。 如果 dbms 支持其他事务隔离级别,它会忽略它使用来实现这两种级别的任何机制。 以便它们不产生不利影响其他事务,在 read uncommitted 级别运行的事务是通常是只读的。
已提交读
在事务等待,直到由其他事务写入锁定的行不会被锁定;这可以防止它读取任何"更新"的数据。
事务持有读取的锁 (如果它仅读取行) 或写入锁定 (如果它更新或删除的行) 的当前行,以防止其他事务更新或删除它。 事务释放读的锁时即会关闭当前行。 它保留写锁,直到提交或回滚。
可重复读
在事务等待,直到由其他事务写入锁定的行不会被锁定;这可以防止它读取任何"更新"的数据。
事务持有读取的锁,它返回到的应用程序和写锁,它插入、 更新或删除的所有行的所有行。 例如,如果事务包含的 sql 语句选择*从订单,如应用程序读取它们的事务读取锁定行。 如果在事务中包含的 sql 语句删除从订单的状态 = 已关闭,如将其删除的行事务写入锁。
由于其他事务不能更新或删除这些行,当前事务可以避免任何不可重复读取。 事务提交或回滚时释放其锁。
可序列化
在事务等待,直到由其他事务写入锁定的行不会被锁定;这可以防止它读取任何"更新"的数据。
事务持有读取的锁 (如果它仅读取的行) 或写入锁 (如果它可以更新或删除行) 的范围上它的行影响。 例如,如果事务包含的 sql 语句选择*从订单,范围是整个 orders 表; 事务读取锁定表而不会允许任何新行插入到它。 如果在事务中包含的 sql 语句删除从订单的状态 = 已关闭,范围为"已关闭"状态的所有行; 事务写入锁订单中的所有行具有都表状态为"closed"而不会不允许任何行要插入或更新,以便得到的行的状态为"已关闭"。
由于其他事务不能更新或删除范围中的行,当前事务可以避免任何不可重复读取。 由于其他事务不能在范围中插入任何行,当前事务可以避免任何幻影。 事务提交或回滚时释放其锁定。
设置事务隔离级别
若要设置事务隔离级别,应用程序,请使用 sql_attr_txn_isolation 连接属性。 如果数据源不支持所请求的隔离级别,则驱动程序或数据源可以设置更高的级别。 若要确定哪些事务隔离级别的数据源支持和默认隔离级别是,应用程序调用sqlgetinfosql_txn_isolation_option 和 sql_default_txn_isolation 选项分别。
更高版本的事务隔离级别提供数据库数据的大多数完整性的保护。 可序列化事务都保证是不受其他事务的影响,因此保证维护数据库的完整性。
但是,更高版本的事务隔离级别可能导致性能下降,因为它增加了应用程序必须等待锁释放的数据的可能性。 应用程序可以指定较低级别的隔离,以提高性能,在以下情况下:
-
当它可以保证其他任何事务存在,可能会影响应用程序的事务。 这种情况仅在有限的情况下,如小型公司中的某个人时维护 dbase 文件包含一台计算机上的人员数据中发生,不会共享这些文件。
-
当速度比准确性和任何错误很可能是小型更为重要。 例如,假设一家公司,使得许多小型销售和大单销售很少。 估计总销售额值中所有打开的事务可以安全地使用 read uncommitted 隔离级别。 尽管该事务将包含订单是得到打开或关闭,随后可以回滚,这些将通常相互抵消,事务会快得多,因为它不会阻止每次它遇到这种订单。
可滚动游标和事务隔离
下表列出了用于管理更改的可见性的因素。
所做的更改: | 可见性取决于: |
---|---|
游标 | 游标类型,游标实现 |
同一个事务中的其他语句 | 游标类型 |
在其他事务中的语句 | 游标类型,事务隔离级别 |
下表总结了每种游标类型能够检测所本身、 其自己的事务中的其他操作和其他事务所做的更改。 后一种更改的可见性取决于游标类型和包含光标的事务的隔离级别。
[a] 中括号的字母指示包含游标的事务的隔离级别(在其中进行了更改) 的其他事务的隔离级别是不相关。
ru: 未提交的读
rc: 已提交读
rr: 可重复读
s: 可序列化
[b] 依赖于如何实现游标。 光标是否可以检测此类更改通过中的 sql_static_sensitivity 选项将报告sqlgetinfo。
事务支持
sql server 的 ole db 驱动程序实现本地事务的支持。 使用者可借助 microsoft 分布式事务处理协调器 (ms dtc) 来使用分布式事务或协调事务。 对于需要跨多个会话的事务控制权的使用者,适用于 sql server 的 ole db 驱动程序可以加入由 ms dtc 启动和维护的事务。
默认情况下,适用于 sql server 的 ole db 驱动程序使用自动提交事务模式,其中对使用者会话执行的每次离散操作均包含一个针对 sql server 实例的完整事务。 适用于 sql server 的 ole db 驱动程序的自动提交模式是本地的,并且自动提交事务从不会跨多个会话。
适用于 sql server 的 ole db 驱动程序公开 itransactionlocal 接口,并允许使用者在 sql server 实例的单个连接上使用显式和隐式启动事务。 sql server 的 ole db 驱动程序不支持嵌套本地事务。
事务应用场景
确保数据完整、安全、一致性。
确保线程之间操作不会相互影响。
事务优点
原子性、一致性、持久性通过数据库日志实现。
批处理数据库操作。
保证数据库级联操作的正确性。
事务缺点
执行较慢。
需要较多的磁盘空间保存事务日志。
执行更新需要内存较多。
上一篇: 简单的php中文转拼音的实现代码