一、事务的4个基本特?nbsp;
当事务处理系l创Z务时Q将保事务有某些特性。组件的开发者们假设事务的特性应该是一些不需要他们亲自管理的Ҏ。这些特性称为ACIDҎ?ACID是Q原子?Atomicity )、一致? Consistency )、隔L或独立? Isolation)和持久?Durabilily)?nbsp;
1、原子?(Atomicity )
原子性属性用于标识事务是否完全地完成Q一个事务的M更新要在pȝ上完全完成,如果׃某种原因出错Q事务不能完成它的全部Q务,pȝ返回到事务开始前的状态?nbsp;
让我们再看一下银行{帐的例子。如果在转帐的过E中出现错误Q整个事务将会回滚。只有当事务中的所有部分都成功执行了,才将事务写入盘q变化 怹化。ؓ了提供回滚或者撤消未提交的变化的能力Q许多数据源采用日志机制。例如,SQL Server使用一个预写事务日志,在将数据应用?或提交到)实际数据面前,先写在事务日志上。但是,其他一些数据源不是关系型数据库理pȝ (RDBMS)Q它们管理未提交事务的方式完全不同。只要事务回滚时Q数据源可以撤消所有未提交的改变,那么q种技术应该可用于理事务?nbsp;
2、一致? Consistency )
事务在系l完整性中实施一致性,q通过保证pȝ的Q何事务最后都处于有效状态来实现。如果事务成功地完成Q那么系l中所有变化将正确地应用,pȝ处于有效状态。如果在事务中出现错误,那么pȝ中的所有变化将自动地回滚,pȝq回到原始状态。因Z务开
始时pȝ处于一致状态,所以现在系l仍然处于一致状态?再让我们回头看一下银行{帐的例子Q在帐户转换和资金{UdQ帐户处于有效状态。如果事务成功地完成Qƈ且提交事务,则帐户处于新的有效的状态。如果事务出错,l止后,帐户q回到原先的有效状态?nbsp;
CQ事务不负责实施数据完整性,而仅仅负责在事务提交或终止以后确保数据返回到一致状态。理解数据完整性规则ƈ写代码实现完整性的重Q通常落在 开发者肩上,他们Ҏ业务要求q行设计?当许多用户同时用和修改同样的数据时Q事务必M持其数据的完整性和一致性。因此我们进一步研IA C I DҎ中的下一个特性:隔离性?nbsp;
3、隔L?( Isolation)
在隔ȝ态执行事务,使它们好像是pȝ在给定时间内执行的唯一操作。如果有两个事务Q运行在相同的时间内Q执行相同的功能Q事务的隔离性将保每一事务?pȝ中认为只有该事务在用系l?q种属性有时称Z行化Qؓ了防止事务操作间的淆,必须串行化或序列化请求,使得在同一旉仅有一个请求用于同一数据。重要的是,在隔ȝ态执行事务, pȝ的状态有可能是不一致的Q在l束事务前,应确保系l处于一致状态。但是在每个单独的事务中Q系l的状态可能会发生变化。如果事务不是在隔离状态运行, 它就可能从系l中讉K数据Q而系l可能处于不一致状态。通过提供事务隔离Q可以阻止这cM件的发生。在银行的示例中Q这意味着在这个系l内Q其他过E和?务在我们的事务完成前看不到我们的事务引v的Q何变化,q对于终止的情况非常重要。如果有另一个过E根据帐户余额进行相应处理,而它在我们的事务完成前就 能看到它造成的变化,那么q个q程的决{可?nbsp;
建立在错误的数据之上Q因为我们的事务可能l止。这是说明了ؓ什么事务生的变化Q直C务完成,才对pȝ的其他部分可见。隔L不仅仅?证多个事务不能同时修改相同数据,而且能够保证事务操作产生的变化直到变化被提交或终止时才能对另一个事务可见,q发的事务彼此之间毫无媄响。这意味着 所有要求修Ҏd的数据已l被锁定在事务中Q直C务完成才能释放。大多数数据库,例如SQL Server以及其他的RDBMSQ通过使用锁定来实现隔,事务中涉及的各个数据Ҏ数据集用锁定来防止q发讉K?nbsp;
4、持久?(Durabilily)
持久性意味着一旦事务执行成功,在系l中产生的所有变化将是永久的。应该存在一些检查点防止在系l失败时丢失信息。甚至硬件本w失败,pȝ的状态仍能通过在日志中记录事务完成的Q务进行重建。持久性的概念允许开发者认Z系l以后发生了什么变化,?nbsp;
成的事务是系l永久的部分?在银行的例子中,资金的{UL怹的,一直保持在pȝ中。这听v来似乎简单,但这Q依赖于数据写入磁盘,特别需要指出的是,在事务完全完成ƈ提交后才?入磁盘的?所有这些事务特性,不管其内部如何关联,仅仅是保证从事务开始到事务完成Q不事务成功与否,都能正确地管理事务涉及的数据 Q当事务处理pȝ创徏事务 Ӟ确保事务有某些Ҏ。组件的开发者们假设事务的特性应该是一些不需要他们亲自管理的Ҏ?nbsp;
二、ؓ什么需要对事务q发控制
如果不对事务q行q发控制Q我们看看数据库q发操作是会有那些异常情?nbsp;
1、丢失更?Lost update)
两个事务都同时更C行数据,但是W二个事务却中途失败退出,DҎ据的两个修改都失效了?nbsp;
2、脏?Dirty Reads)
一个事务开始读取了某行数据Q但是另外一个事务已l更C此数据但没有能够及时提交。这是相当危险的Q因为很可能所有的操作都被回滚?nbsp;
3、非重复?Non-repeatable Reads)
一个事务对同一行数据重复读取两ơ,但是却得C不同的结果。同一查询在同一事务中多ơ进行,׃其他提交事务所做的修改或删除,每次q回不同的结果集Q此时发生非重复诅R?nbsp;
4、二cM失更?Second lost updates problem)
无法重复d的特例。有两个q发事务同时d同一行数据,然后其中一个对它进行修Ҏ交,而另一个也q行了修Ҏ交。这׃造成W一ơ写操作失效?nbsp;
5、像读(Phantom Reads)
事务在操作过E中q行两次查询Q第二次查询的结果包含了W一ơ查
询中未出现的数据Q这里ƈ不要求两ơ查询的SQL语句相同Q。这是因为在两次查询q程中有另外一个事务插入数据造成的?nbsp;
三、数据库的隔ȝ?nbsp;
Z兼顾q发效率和异常控Ӟ在标准SQL规范中,定义?个事务隔ȝ别,QORACLE和SQLSERERҎ准隔ȝ别有不同的实?Q?nbsp;
1、未提交?Read Uncommitted)
直译是"L提交",意思就是即使一个更新语句没有提?但是?nbsp;
的事务可以读到这个改?q是很不安全的。允怓Q务读取数据库中未提交的数据更改,也称诅R?nbsp;
2、提交读(Read Committed)
直译是"L?,可防止脏读,意思就是语句提交以后即执行了COMMIT以后
别的事务pdq个改变. 只能d到已l提交的数据。Oracle{多数数据库默认都是该?nbsp;
3、可重复?Repeatable Read)Q?nbsp;
直译是"可以重复?,q是说在同一个事务里面先后执行同一个查询语句的时?得到的结果是一L.在同一个事务内的查询都是事务开始时M致的QInnoDB默认U别。在SQL标准中,该隔ȝ别消除了不可重复读,但是q存在象读
4、串行读(Serializable)
直译是"序列?,意思是说这个事务执行的时候不允许别的事务q发执行. 完全串行化的读,每次读都需要获得表U共享锁Q读写相互都会阻?/p>
四,隔离U别对ƈ发的控制
下表是各隔离U别对各U异常的控制能力?/p>
LU丢失更新 | DR脏读 | NRR非重复读 | SLU二类丢失更新 | PRqd?/td> | |
未提交读 RU | Y | Y | Y | Y | Y |
提交?RC | N | N | Y | Y | Y |
可重复读 RR | N | N | N | N | Y |
串行?S | N | N | N | N | N |
Z举一例?/p>
MS_SQL:
--事务一
set transaction isolation level serializable
begin tran
insert into test values('xxx')
--事务?nbsp;
set transaction isolation level read committed
begin tran
select * from test
--事务?nbsp;
set transaction isolation level read uncommitted
begin tran
select * from test
在查询分析器中执行事务一后,分别执行事务二,和三。结果是事务二会{待Q而事务三则会执行?/p>
ORACLEQ?nbsp;
--事务一
set transaction isolation level serializable;
insert into test values('xxx');
select * from test;
--事务?nbsp;
set transaction isolation level read committed--ORACLE默认U别
select * from test
执行事务一后,执行事务二。结果是事务二只d原有的数据,无视事务一的插入操作?/p>
MYSQL
查看InnoDBpȝU别的事务隔ȝ别:
以下为引用的内容Q?nbsp;
mysql> SELECT @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set (0.00 sec)
查看InnoDB会话U别的事务隔ȝ别:
以下为引用的内容Q?nbsp;
mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
修改事务隔离U别Q?nbsp;
以下为引用的内容Q?nbsp;
mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
mysql> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
InnoDB的可重复读隔ȝ别和其他数据库的可重复读是有区别的,不会造成q象读(phantom readQ,所谓象读Q就是同一个事务内Q多ơselectQ可以读取到其他session insertq已lcommit的数据。下面是一个小的测试,证明InnoDB的可重复读隔ȝ别不会造成q象诅R测试涉及两个sessionQ分别ؓ session 1和session 2Q隔ȝ别都是repeateable readQ关闭autocommit
以下为引用的内容Q?nbsp;
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> set autocommit=off;
Query OK, 0 rows affected (0.00 sec)
session 1 创徏表ƈ插入试数据
mysql> create table test(i int) engine=innodb;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test values(1);
Query OK, 1 row affected (0.00 sec)
session 2 查询Q没有数据,正常Qsession1没有提交Q不允许脏读
mysql> select * from test;
Empty set (0.00 sec)
session 1 提交事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
session 2 查询Q还是没有数据,没有产生q象?nbsp;
mysql> select * from test;
Empty set (0.00 sec)
以上试验版本Q?nbsp;
mysql> select version();
+-------------------------+
| version() |
+-------------------------+
| 5.0.37-community-nt-log |
+-------------------------+
1 row in set (0.00 sec)
五、ƈ发一致性问题的解决办法
1 锁QLockingQ?nbsp;
锁是实现ƈ发控制的一个非帔R要的技术。所谓封锁就是事务T在对某个数据对象例如表、记录等操作之前Q先向系l发求,对其加锁。加锁后事务T对?数据对象有了一定的控制Q在事务T释放它的锁之前,其它的事务不能更新此数据对象?基本的封锁类型有两种Q排它锁QExclusive locks CؓX锁)和共享锁QShare locks CؓS锁)?nbsp;
排它锁又UCؓ写锁。若事务TҎ据对象A加上X锁,则只允许Td和修改AQ其它Q何事务都不能再对A加Q何类型的锁,直到T释放A上的锁。这׃证了其它事务在T释放A上的锁之前不能再d和修改A?nbsp;
׃n锁又UCؓ读锁。若事务TҎ据对象A加上S锁,则其它事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这׃证了其它事务可以读AQ但在T释放A上的S锁之前不能对A做Q何修攏V?nbsp;
2 锁协议
?q用X锁和S锁这两种基本锁Q对数据对象加锁Ӟq需要约定一些规则,例如应何时申请X锁或S锁、持锁时间、何旉攄。我们称q些规则为封锁协?QLocking ProtocolQ。对锁方式规定不同的规则,Ş成了各种不同的封锁协议。下面介l三U封锁协议。三U封锁协议分别在不同E度上解决了丢失的修攏V不 可重复读和读"?数据{不一致性问题,为ƈ发操作的正确调度提供一定的保证。下面只l出三锁协议的定义,不再做过多探讨?nbsp;
1 U封锁协议是Q事务T在修Ҏ据R之前必须先对其加X锁,直到事务l束才释放。事务结束包括正常结束(COMMITQ和非正常结束(ROLLBACKQ?1U封锁协议可防止丢失修改Qƈ保证事务T是可恢复的。在1U封锁协议中Q如果仅仅是L据不对其q行修改Q是不需要加锁的Q所以它不能保证可重复读和不 ??数据?nbsp;
2U封锁协议是Q?U封锁协议加上事务T在读取数据R之前必须先对其加S锁,d后即可释放S锁?U封锁协议除防止了丢׃改,q可q一步防止读"?数据?nbsp;
3U封锁协议是Q?U封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务l束才释放?U封锁协议除防止了丢׃改和不读'?数据外,q进一步防止了不可重复诅R?nbsp;
六、一般处理ƈ发问题时的步骤:
1、开启事务?nbsp;
2、申请写权限Q也是l对?表或记录)加锁?nbsp;
3、假如失败,则结束事务,q一会重试?nbsp;
4、假如成功,也就是给对象加锁成功Q防止其他用户再用同L方式打开?nbsp;
5、进行编辑操作?nbsp;
6、写入所q行的编辑结果?nbsp;
7、假如写入成功,则提交事?完成操作?nbsp;
8、假如写入失败,则回滚事务,取消提交?nbsp;
9?7.8)两步操作已释放了锁定的对象,恢复到操作前的状态?br />
转自Q?a >http://www.cnblogs.com/tqsummer/archive/2010/07/11/1775209.html