Transaction
Table of Contents
1. 事务简介
数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
参考:
Nuts and Bolts of Transaction Processing
事务处理——概念与技术, by Jim Gray
1.1. 事务的 ACID
ACID,是指数据库管理系统(DBMS)在修改数据的过程中,为保证事务(transaction)是正确可靠的,所必须具备的四个特性。
- Atomicity 原子性
- 同一事务的所有操作要么都完成,要么都没有完成。
- Consistency 一致性
- 数据库在事务的开始和结束时将处于一致的状态(不管在任何给定的时间并发事务有多少)。比如,A向 B 转账,不会出现 A 扣了钱,B却没收到。
- Isolation 隔离性
- 一个事务不应该知道由任何其他的事务对数据所做的修改,除非那些修改已提交到数据库。可以设定不同的隔离级以修改默认行为。
- Durability 持久性
- 已成功提交数据库的事务结果要能够维持(只要事务提交,系统将保证数据不会丢失,如系统突然 crash)。
参考:SQL 宝典,原书第二版,7.2.1 什么是事务
2. 事务的 Isolation Level(隔离级别)
The SQL92 standard defines four levels of transaction isolation with differing degrees of impact on transaction processing.
These isolation levels are defined in terms of the following three read types.
2.1. Three read types
- Dirty reads
- A transaction reads data that has been written by another transaction that has not been committed yet.
- Fuzzy reads
- A transaction rereads data it has previously read and finds that another committed transaction has modified or deleted the data.
- Phantom reads
- A transaction re-runs a query returning a set of rows that satisfies a search condition and finds that another committed transaction has inserted additional rows that satisfy the condition.
参考:http://www.ibm.com/developerworks/data/zones/informix/library/techarticle/db_isolevels.html
2.1.1. Dirty Read
This occurs if one transaction can see the results of the actions of another transaction before it commits. Consider the following example:
Transaction | Action 1 | Action 2 | Action 3 |
---|---|---|---|
Transaction 1 | Write(a) | - | Rollback |
Transaction 2 | - | Read(a) | - |
If Transaction 2 reads the value written by Transaction 1, then a DIRTY READ has occurred.
2.1.2. Non-Repeatable Read (also called Fuzzy Read)
This occurs if the results of one transactions can be modified or deleted by another transaction before it commits. This is illustrated below:
Transaction | Action 1 | Action 2 | Action 3 | Action 4 |
---|---|---|---|---|
Transaction 1 | Read(a) | - | - | Read(a) |
Transaction 2 | - | Write/Delete(a) | Commit | - |
If Transaction 1 gets a different result from the each Read, then a NON-REPEATABLE READ has occurred.
对于“Transaction 1”来说,两次读的结果不一样,所以这称为“不可重复读(Non-Repeatable Read)”。
2.1.3. Phantom Read (幻读)
This occurs if the results of a query in one transaction can be changed by another transaction before it commits. This is illustrated below:
Transaction | Action 1 | Action 2 | Action 3 | Action 4 |
---|---|---|---|---|
Transaction 1 | Select(criteria) | - | - | Select(criteria) |
Transaction 2 | - | Update/Create(match to criteria) | Commit | - |
If Transaction 1 gets a different result from each Select, then a PHANTOM READ has occurred.
2.1.4. “脏读、不可重复读、幻读”的通俗例子
脏读(dirty read):A改后还未提交,B读,A又改并提交。例:
1.Mary 的原工资为 1000,财务人员将 Mary 的工资改为了 8000(但未提交事务)
2.Mary 读取自己的工资,发现自己的工资变为了 8000,欢天喜地!
3.而财务发现操作有误,回滚了事务,Mary 的工资又变为了 1000,像这样 Mary 记取的工资数 8000 是一个脏数据。
不可重复读(nonrepeatable read):A先读,B再改,A再读。例:
1.在事务 A 中,Mary 读取了自己的工资为 1000,操作并没有完成
2.在事务 B 中,这时财务人员修改了 Mary 的工资为 2000,并提交了事务
3.在事务 A 中,Mary 再次读取自己的工资时,工资变为了 2000
注:如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题。
幻读(phantom read):A改后还未提交,B改其他的,A再查。例:
1.A 把所有的“黑色”改为“白色”
2.B 把所有的“红色”改为“黑色”
3.A 再查询“黑色”,却发现还有“黑色”,这对 A 来说就好像发生了幻觉一样。
参考:
http://hi.baidu.com/zhushidan100/item/8937ad28a56960fc51fd8724
http://www.cnblogs.com/hollen/archive/2012/05/13/2498309.html
2.2. Four levels of isolation in SQL92
SQL92 defines four levels of isolation based on the read permissions above:
Isolation Level | Dirty Read | Nonrepeatable Read | Phantom Read |
---|---|---|---|
读未提交(Read Uncommitted) | Possible | Possible | Possible |
读提交(Read Committed) | Not Possible | Possible | Possible |
可重复读(Repeatable Read) | Not Possible | Not Possible | Possible |
串行化(Serializable) | Not Possible | Not Possible | Not Possible |
2.3. DB2 isolation levels
ANSI SQL Isolation Level | DB2 equivalent | Note |
---|---|---|
Read Uncommitted | UR (Uncommitted read) | |
Read Committed (default) | CS (Cursor stability) | |
Repeatable Read | RS (Read stability) | 对所读记录要加锁 |
Serializable | RR (Repeatable read) | 整个表可能要加锁 |
UR 是“最危险”的用法(性能相对好)。
RR 是“最安全”的用法(性能相对差)。
2.4. Oracle isolation levels
Oracle 中隔离级别最低对应 DB2 中的 CS 级别,若要把 DB2 代码迁移到 Oracle 中,其中的“WITH UR”和“WITH CS”语句可以安全地删除。但如果 DB2 代码中有“WITH RS”和“WITH RR”怎么办呢?可以在 Oracle 中通过下面语句来设置,但这些语句必须是当前事务的第一条语句:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET TRANSACTION READ ONLY;
参考:http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_10005.htm#SQLRF01705
Oracle does not allow reading uncommitted rows and WITH UR clause should be removed from the SELECT statement. Often it is not a problem as WITH UR is mostly used to prevent any read locks in DB2, while in Oracle readers are never blocked anyway.
WITH CS means to read committed rows, and this is the default in Oracle, so this clause can be also removed.
3. Distributed Transaction(分布式事务)
涉及一个以上数据库的事务称为分布式事务(又称全局事务)。
分布式事务必须在网络失败时最小化丢失数据的风险。分布式事务处理的困难源于两个方面:concurrency 和 failures。
3.1. 两阶段提交
分布式事务中使用两阶段提交协议(Two-Phase Commit protocol):
第 1 阶段:Commit request phase(准备阶段)
事务管理器(即处理协调器)接收到一个 COMMIT 请求后将这个请求传达到该事务涉及的所有资源管理器(即数据库),然后这些资源管理器执行准备工作,如锁定资源(获取锁等操作)。如果准备工作可以顺利完成,则回复“可以提交”,否则回复“拒绝提交”。
第 2 阶段:Commit phase(提交阶段)
如果所有资源管理器都回复“可以提交”,则处理协调器发送正式提交命令。在此阶段,这些资源管理器真正发出 COMMIT 并报告给处理协调器;当所有的 COMMIT 都成功后,处理协调器发通知给客户端应用程序。如果有任何资源管理器没有通知处理协调器,则处理协调器发送 ROLLBACK 命令给所有资源管理器。这个过程中可能需要在 COMMIT 执行后再执行 ROLLBACK,通常需要使用日志文件。
参考:
Concurrency Control and Recovery in Database Systems, by Philip A. Bernstein, Section 7.4 The Two Phase Commit Protocol
SQL 宝典,原书第二版,7.2.2 事务的 COMMIT 和 ROLLBACK
3.2. 分布式事务典型应用场景
Moving data between databases -- An application moving data from one database to another requires a distributed transaction. Otherwise, the data may be duplicated (if the insert completes and the delete fails) or lost (if the delete completes and the insert fails).
参考:
http://www.ibm.com/developerworks/websphere/library/techarticles/0407_woolf/0407_woolf.html
3.3. 分布式事务最大缺点是性能不高
The greatest disadvantage of the two-phase commit protocol is that it is a blocking protocol. If the coordinator fails permanently, some cohorts will never resolve their transactions: After a cohort has sent an agreement message to the coordinator, it will block until a commit or rollback is received.
参考:
https://en.wikipedia.org/wiki/Two-phase_commit_protocol#Disadvantages
https://docs.oracle.com/database/121/ADFNS/adfns_xa.htm#ADFNS017
3.4. TPC-C benchmark
The TPC-C benchmark continues to be a popular yardstick for comparing OLTP performance on various hardware and software configurations.
4. 事务处理标准
参考:事务处理——概念与技术, by Jim Gray, 2.7 节
4.1. LU6.2 事实标准
4.2. OSI-TP 标准
继 IBM 的 SNA 标准之后,ISO (国际标准化组织)定义了 OSI (开放系统互连)的网络体系结构,其中包含有事务处理相关标准 (OSI-TP)。
OSI-TP 和 LU6.2 非常相似,从某种程序上可以认为 OSI-TP 是 LU6.2 在 OSI 体系下的重定义。
参考:
http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=27614
4.3. X/Open DTP 标准
OSI-TP 仅定义了消息传递和格式和所使用的协议,没有标准化具体的 API。 这样,它们允许事务处理系统的互操作,但却没有提供编写可移植事务处理应用程序或服务器的方法。
另一个标准化组织 X/Open 意识到这个问题,它定义了分布事务处理标准(X/Open DTP)来解决这个问题。
在 X/Open DTP 模型中定义了资源管理器(RM),事务管理器(TM)等重要概念。在 TM 和 TM 之间的接口采用的还是 OSI-TP 标准。
5. X/Open DTP
X/Open DTP 模型的功能模块和接口如图 1 所示。
Figure 1: Functional Components and Interfaces
在简单场景下,模型可简化为图 2 所示。
Figure 2: X/Open distributed transaction processing (DTP) model
The resource manager (RM) manages a defined part of the computer’s shared resources. These may be accessed using services that the RM provides. Examples for RMs are database management systems (DBMSs), a file access method such as X/Open ISAM, and a print server.
The transaction manager (TM) manages global transactions and coordinates the decision to start them, and commit them or roll them back. This ensures atomic transaction completion. The TM also coordinates recovery activities of the resource managers when necessary, such as after a component fails.
说明:在分布式事务处理环境中,RM 必须依赖于 TM 来管理分布式事务。在分布式事务处理环境中,AP 不应该直接使用 RM 提供的事务 API,如 EXEC SQL COMMIT WORK 和 EXEC SQL ROLLBACK WORK 等。
参考:
Distributed Transaction Processing: Reference Model
Distributed Transaction Processing: The XA Specification
Distributed Transaction Processing: The TX (Transaction Demarcation) Specification
5.1. TX 接口(应用程序和 TM 之间的接口)
TX 接口是应用程序(AP)和事务管理器(TM)之间的接口。
Name | Description |
---|---|
tx_begin | Begin a global transaction. |
tx_close | Close a set of resource managers. |
tx_commit | Commit a global transaction. |
tx_info | Return global transaction information. |
tx_open | Open a set of resource managers. |
tx_rollback | Roll back a global transaction. |
tx_set_transaction_control | Set transaction_control characteristic. |
tx_set_transaction_timeout | Set transaction_timeout characteristic. |
这些函数的原型定义在头文件 tx.h 中。
参考:Oracle Tuxedo ATMI (Application-to-Transaction Monitor Interface) C Function Reference
5.2. XA 接口(TM 和 RM 之间的接口)
XA 接口是事务管理器(TM)和资源管理器(RM)之间接口。
XA uses a two-phase commit to ensure that all resources either commit or rollback any particular transaction consistently (all do the same).
Name | Description |
---|---|
ax_reg | Register an RM with a TM. |
ax_unreg | Unregister an RM with a TM. |
xa_close | Terminate the AP's use of an RM. |
xa_commit | Tell the RM to commit a transaction branch. |
xa_complete | Test an asynchronous xa_ operation for completion. |
xa_end | Dissociate the thread from a transaction branch. |
xa_forget | Permit the RM to discard its knowledge of a heuristically-completed transaction branch. |
xa_open | Initialise an RM for use by an AP. |
xa_prepare | Ask the RM to prepare to commit a transaction branch. |
xa_recover | Get a list of XIDs the RM has prepared or heuristically completed. |
xa_rollback | Tell the RM to roll back a transaction branch. |
xa_start | Start or resume a transaction branch - associate an XID with future work that the thread requests of the RM. |
ax_开头的 API 由 TM 提供,被 RM 调用。xa_开头的 API 由 RM 提供,被 TM 调用。
这些函数的原型定义在头文件 xa.h 中。
说明 1:RM 可以自由定义 xa_开头 API 的名字,TM 通过结构体 xa_switch_t 找到它们。
The XA interface describes a structure called the switch table, which lists the names of the xa_ routines implemented in the resource manager. This structure is called xa_switch_t, and is defined in the xa.h header file. The switch table helps build servers that are truly independent of the database vendor being used.
struct xa_switch_t { char name[RMNAMESZ]; /* name of resource manager */ long flags; /* resource manager specific options */ long version; /* must be 0 */ int (*xa_open_entry)(char *, int, long); /* xa_open function pointer */ int (*xa_close_entry)(char *, int, long); /* xa_close function pointer*/ int (*xa_start_entry)(XID *, int, long); /* xa_start function pointer */ int (*xa_end_entry)(XID *, int, long); /* xa_end function pointer */ int (*xa_rollback_entry)(XID *, int, long); /* xa_rollback function pointer */ int (*xa_prepare_entry)(XID *, int, long); /* xa_prepare function pointer */ int (*xa_commit_entry)(XID *, int, long); /* xa_commit function pointer */ int (*xa_recover_entry)(XID *, long, int, long); /* xa_recover function pointer*/ int (*xa_forget_entry)(XID *, int, long); /* xa_forget function pointer */ int (*xa_complete_entry)(int *, int *, int, long); }; /* xa_complete function pointer */
说明 2:Some database vendors, such as Oracle, typically have the xa.h header file in their default include directory. Other database vendors, such as Sybase and DB2, generally do not have the xa.h file in the include directory. If the database vendor does not supply xa.h, this file should be located in the include directory of the TM vendor.
下面给出一个新进程的简单控制流程。该进程执行的事务仅涉及一个资源管理器,它静态地注册和参加所有的事务。
Figure 3: DTP 中,新进程的简单控制流程
注:tm 开头的函数就是 TX 接口中那些 tx 开关的函数。
参考:事务处理——概念与技术,16.6 节
5.3. 常见 RMs
主流的数据库都可以作为 RM。
5.3.1. DB2
DB2, Designing for XA-compliant transaction managers
http://www-01.ibm.com/support/knowledgecenter/?lang=en#!/SSEPGG_10.1.0/com.ibm.db2.luw.admin.2pc.doc/doc/c0004558.html
5.3.2. Oracle Database
Oracle XA FAQ: http://www.orafaq.com/wiki/XA_FAQ
Developing Applications with Oracle XA: http://docs.oracle.com/database/121/ADFNS/adfns_xa.htm#ADFNS017
5.3.3. MySQL
XA Transactions in MySQL: http://dev.mysql.com/doc/refman/5.7/en/xa.html
5.4. 常见 TMs
IBM TXSeries(CICS): https://en.wikipedia.org/wiki/IBM_TXSeries
Oracle Tuxedo: https://en.wikipedia.org/wiki/Tuxedo_(software)
Microsoft Transaction Server(MTS): https://en.wikipedia.org/wiki/Microsoft_Transaction_Server
LIXA, LIbre XA, is a free and open source XA transaction manager: http://sourceforge.net/p/lixa/wiki/Home/