什么是交易?事务是一组原子SQL操作。所有操作都必须成功完成。如果由于崩溃或其他原因导致任何操作无法执行,则不会执行所有操作。也就是说,事务内的所有操作要么成功,要么失败。有两种方法可以结束交易。当事务中的所有操作都成功执行后,事务就被提交了。如果其中一个操作失败,将发生回滚操作,撤消事务开始之前的所有先前操作。事务的特性一个运行良好的事务处理系统还需要具备四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。这四个属性称为ACID属性。原子性(Atomicity)一个事务必须被看作是一个不可分割的最小逻辑工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚。对于一个事务来说,不可能只执行一部分操作而不执行另一部分操作,这就是事务的原子性。一致性(Consistency)事务执行的结果一定是从一种一致状态转换到另一种一致状态。当数据库仅包含成功事务提交的结果时,就称其处于一致状态。如果事务因崩溃或其他原因没有完成,则强制中断,最终事务不提交,事务中所做的修改也不会保存到数据库中。隔离(Isolation)一般来说,一个事务的执行不能干扰其他事务。也就是说,一个事务内使用的操作和数据与其他并发事务是隔离的,并发执行的事务之间不能相互干扰。等到我们后面解释隔离级别(IsolationLevel)的时候,我们就会发现为什么说“一般来说”是隔离的。一旦持久性事务被提交,它对数据库中数据的修改应该是永久性的。这时,即使系统崩溃,修改的数据也不会丢失。然而,实际上,坚持有很多不同的层次。一些持久性策略可以提供非常强大的安全保证,而另一些则不能。事务隔离级别在SQL标准中定义了四种隔离级别,每一种都定义了一个事务所做的修改,在另一个事务内和事务之间是可见的,哪些是不可见的。低级别隔离级别通常支持更高的并发处理并且具有更低的系统开销。未提交读(ReadUncommitted)在未提交读级别,事务中的修改即使没有提交,对其他事务也是可见的。读取未被事务提交的数据称为脏读(DirtyRead)。事务未提交的数据非常“脏”,如果读取会导致很多问题。从性能上看,uncommittedreadlevel并不比其他level好多少,但是缺乏其他level带来的好处,所以在实际应用中很少使用。为了加深对未提交读级别的理解,我们来看一个脏读的例子,首先设置事务隔离级别为未提交读:mysql>setsessiontransactionisolationlevelreaduncommitted;QueryOK,0rowsaffected(0.00sec)再次检查事务隔离级别:mysql>select@@tx_isolation;+----------------+|@@tx_isolation|+------------------+|READ-UNCOMMITTED|+----------------+1rowinset,1warning(0.00sec)大约是两个A用户,用户A在左边,用户B在右边,时间线从上到下:#UserA:查询user表,有OneMoreStudy的记录↓mysql>select*fromuser;↓+----+------------+↓|编号|姓名|↓+----+------------+↓|1|一个学习|↓+----+------------+↓1rowinset(0.00sec)↓↓↓#UserB:starttransaction↓mysql>starttransaction;↓查询OK,0行受影响(0.00秒)↓↓#用户B:更新用户表中的一条记录↓mysql>updateusersetname='OMS'whereid=1;↓QueryOK,1rowaffected(0.01sec)↓Rowsmatched:1Changed:1Warnings:0↓#UserA:查询user表,有OMS记录,脏读↓mysql>select*fromuser;↓+----+------+↓|编号|姓名|↓+----+------+↓|1|管理系统|↓+----+------+↓一组中的1行(0.00秒)↓↓↓#用户B:提交事务↓mysql>commit;↓QueryOK,0rowsaffected(0.00sec)ReadCommitted(ReadCommitted)在ReadCommitted级别,当一个事务开始时,只能查询其他事务Committedmodification是指一个事务从开始到提交的任何修改都是对其他交易不可见。CommittedRead级别基本满足事务的隔离。但是,如果在同一个事务中的两个查询之间提交其他事务的修改,则两个查询的结果可能不同,这就是不可重复读。为了更好的理解不可重复读,我们来看一个例子,先设置事务隔离级别为commitread:mysql>setsessiontransactionisolationlevelreadcommitted;QueryOK,0rowsaffected(0.00sec)然后查看事务隔离级别:mysql>select@@tx_isolation;+----------------+|@@tx_isolation|+----------------+|READ-COMMITTED|+----------------+1rowinset,1warning(0.00sec)是关于两个用户,左边的用户A和右边的用户B,时间轴从上到下:#UserA:starttransactionmysql>starttransaction;QueryOK,0rowsaffected(0.00sec)#UserA:queryusertable,有OneMoreStudymysql的记录>select*fromuser;+----+----------------+|编号|名字|+----+------------+|1|一个学习|+----+------------+1rowinset(0.00sec)#UserB:updatearecordintheusertablemysql>updateusersetname='OMS'其中id=1;查询正常,1行受影响(0.00秒)行匹配:1更改:1警告ings:0#UserA:查询user表,有OMS记录,不能重复读取mysql>select*fromuser;+----+-----+|编号|姓名|+----+------+|1|OMS|+----+-----+1rowinset(0.00sec)#UserA:submittransactionmysql>commit;QueryOK,0rowsaffected(0.00sec)可重复读(RepeatableRead)中可重复读级别,保证在同一个事务中多次读取同一条记录的结果是一致的,即使多次读取之间有其他事务。修改后,同一个事务多次读的结果也是一致的。可重复读级别也是MySQL默认的事务隔离级别。但是,当一个事务读取一个范围内的记录时,其他事务会在这个范围内插入新的记录。之前的事务再次读取这个范围的记录时,不会读取新插入的记录。那个记录,这叫做幻读。为了更好的理解幻读,我们来看一个例子,首先设置事务隔离级别为可重复读:mysql>setsessiontransactionisolationlevelrepeatableread;查询OK,0行受影响(0.00秒),然后检查事务隔离级别:mysql>select@@tx_isolation;+----------------+|@@tx_isolation|+-----------------+|REPEATABLE-READ|+----------------+1rowinset,1warning(0.00sec)左边有两个用户,左边的用户A和用户A右边是用户B,时间轴从上到下:#UserA:starttransactionmysql>starttransaction;QueryOK,0rowsaffected(0.00sec)#UserA:queryusertable,有一条记录mysql>从用户中选择*;+----+----------------+|编号|名字|+----+------------+|1|OneMoreStudy|+----+------------+1rowinset(0.00sec)#UserB:插入一条数据mysql>insertintouser(name)value('OneMoreStudy');QueryOK,1rowaffected(0.01sec)#UserA:查询user表,还是一条记录,幻读mysql>select*fromuser;+----+---------------+|编号|姓名|+----+----------------+|1|OneMoreStudy|+----+------------+1rowinset(0.00sec)#UserA:submittransactionmysql>commit;QueryOK,0rowsaffected(0.00sec))#用户A:查询用户表,两条记录mysql>select*fromuser;+----+--------------+|编号|名字|+----+------------+|1|OneMoreStudy||2|OneMoreStudy|+----+------------+2rowsinset(0.00sec)可序列化(Serializable)在可序列化级别,事务被强制串行执行,是最高隔离级别。在这个层次上,虽然避免了上面提到的幻读,但是每次读行都会加一个锁,可能会造成很多超时和锁竞争问题,所以在实际应用中很少使用。用来。除非非常需要保证数据的一致性,对并发性要求不高,否则可以使用序列化级别。小结本文首先简单介绍了事务及其ACID特性,然后着重讲解了事务的四种隔离级别:未提交读:即使事务中的修改没有提交,其他事务仍然可见。提交读:事务启动时,只能查询其他事务已经提交的修改。可重复读:保证在同一个事务中多次读取同一条记录的结果是一致的。Serializable:强制事务串行执行。隔离级别脏读不可重复读幻读未提交读可能可能可能提交读不可能可能可能可重复读不可能不可能可能序列化不可能不可能不可能
