`
txf2004
  • 浏览: 6877916 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

事务

 
阅读更多

从MySQL 4.1开始支持事务,事务是构成多用户使用数据库的基础。
在MySQL环境中,事务由作为一个单独单元的一个或多个SQL语句组成。这个单元中的每个SQL语句是互相依赖的,而且单元作为一个整体是不可分割的。如果单元中的一个语句不能完成,整个单元就会回滚(撤销),所有影响到的数据将返回到事务开始以前的状态。因而,只有事务中的所有语句都成功地执行才能说这个事务被成功地执行。

使用一个简单的例子来帮助理解事务:向公司添加一名新的雇员(见图10.1)。这里的过程由三个基本步骤组成:在雇员数据库中为雇员创建一条记录;为雇员分配部门;建立雇员的工资记录。如果这三步中的任何一步失败,如为新成员分配的雇员ID已经被其他人使用或者输入到工资系统中的值太大,系统就必须撤销在失败之前所有的变化,删除所有不完整记录的踪迹,避免以后的不一致和计算失误。
前面的三项任务构成了一个事务。任何一个任务的失败都会导致整个事务被撤销,系统返回到以前的状态。
并不是所有的存储引擎都支持事务,如InnoDB和BDB支持,但MyISAM和MEMORY不支持,本章假设使用了一个支持事务的存储引擎来创建表。
通过InnoDB和BDB表类型,MySQL 事务系统能够完全满足事务安全的ACID测试。旧的表类型,如MyISAM类型,不支持事务。因此,这种系统中的事务只能通过直接的表锁定实现。
术语“ACID”是一个简称,每个事务的处理必须满足ACID原则,即原子性(A)、一致性(C)、隔离性(I)和持久性(D)。
(1)原子性
原子性意味着每个事务都必须被认为是一个不可分割的单元。假设一个事务由两个或者多个任务组成,其中的语句必须同时成功才能认为事务是成功的。如果事务失败,系统将会返回到事务以前的状态。
在添加雇员这个例子中,原子性指如果没有创建雇员相应的工资表和部门记录,就不可能向雇员数据库添加雇员。
原子的执行是一个或者全部发生或者什么也没有发生的命题。在一个原子操作中,如果事务中的任何一个语句失败,前面执行的语句都将返回,以保证数据的整体性没有受到影响。这在一些关键系统中尤其重要,现实世界的应用程序(如金融系统)执行数据输入或更新,必须保证不出现数据丢失或数据错误,以保证数据安全性。(2)一致性
不管事务是完全成功完成还是中途失败,当事务使系统处于一致的状态时存在一致性。参照前面的例子,一致性是指如果从系统中删除了一个雇员,则所有和该雇员相关的数据,包括工资数据和组的成员资格也要被删除。
在MySQL中,一致性主要由MySQL的日志机制处理,它记录了数据库的所有变化,为事务恢复提供了跟踪记录。如果系统在事务处理中间发生错误,MySQL恢复过程将使用这些日志来发现事务是否已经完全成功地执行,是否需要返回。因而一致性属性保证了数据库从不返回一个未处理完的事务。
(3)隔离性
隔离性是指每个事务在它自己的空间发生,和其他发生在系统中的事务隔离,而且事务的结果只有在它完全被执行时才能看到。即使在这样的一个系统中同时发生了多个事务,隔离性原则保证某个特定事务在完全完成之前,其结果是看不见的。
当系统支持多个同时存在的用户和连接时(如MySQL),这就尤其重要。如果系统不遵循这个基本规则,就可能导致大量数据的破坏,如每个事务的各自空间的完整性很快地被其他冲突事务所侵犯。
获得绝对隔离性的唯一方法是保证在任意时刻只能有一个用户访问数据库。当处理像MySQL这样多用户的RDBMS时,这不是一个实际的解决方法。但是,大多数事务系统使用页级锁定或行级锁定隔离不同事务之间的变化,这是要以降低性能为代价的。例如,MySQL的BDB表处理程序使用页级锁定来保证处理多个同时发生的事务的安全,InnoDB表处理程序使用更好的行级锁定。
(4)持久性
持久性是指即使系统崩溃,一个提交的事务仍然存在。当一个事务完成,数据库的日志已经被更新时,持久性就开始发生作用。大多数RDBMS产品通过保存所有行为的日志来保证数据的持久性,这些行为是指在数据库中以任何方法更改数据。数据库日志记录了所有对于表的更新、查询、报表等。
如果系统崩溃或者数据存储介质被破坏,通过使用日志,系统能够恢复在重启前进行的最后一次成功的更新,反映了在崩溃时处于过程的事务的变化。
MySQL通过保存一条记录事务过程中系统变化的二进制事务日志文件来实现持久性。如果遇到硬件破坏或者突然的系统关机,在系统重启时,通过使用最后的备份和日志就可以很容易地恢复丢失的数据。
默认情况下,InnDB表是100%持久的(所有在崩溃前系统所进行的事务在恢复过程中都可以可靠地恢复)。MyISAM表提供部分持久性,所有在最后一个FLUSH TABLES命令前进行的变化都能保证被存盘。1. 开始事务
当一个应用程序的第一条SQL语句或者在COMMIT或ROLLBACK语句(后面介绍)后的第一条SQL执行后,一个新的事务也就开始了。另外还可以使用一条START TRANSACTION语句来显示地启动一个事务。
语法格式:
START TRANSACTION | BEGIN WORK
一条BEGIN WORK语句可以用来替代START TRANSACTION语句,但是START TRANSACTION更常用些。
2. 结束事务
COMMIT语句是提交语句,它使得自从事务开始以来所执行的所有数据修改成为数据库的永久部分,也标志一个事务的结束,其语法格式为:
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
说明:
可选的AND CHAIN子句会在当前事务结束时,立刻启动一个新事务,并且新事务与刚结束的事务有相同的隔离等级。RELEASE子句在终止了当前事务后,会让服务器断开与当前客户端的连接。包含NO关键词可以抑制CHAIN或RELEASE完成。
注意:MySQL使用的是平面事务模型,因此嵌套的事务是不允许的。在第一个事务里使用START TRANSACTION命令后,当第二个事务开始时,自动地提交第一个事务。同样,下面的这些MySQL语句运行时都会隐式地执行一个COMMIT命令:
● DROP DATABASE / DROP TABLE
● CREATE INDEX / DROP INDEX
● ALTER TABLE / RENAME TABLE
● LOCK TABLES / UNLOCK TABLES
● SET AUTOCOMMIT=1
3. 撤消事务
ROLLBACK语句是撤销语句,它撤销事务所做的修改,并结束当前这个事务。
语法格式:
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
在前面的举例中,若在最后加上以下这条语句:
ROLLBACK WORK;
执行完这条语句后,前面的删除动作将被撤销,可以使用SELECT语句查看该行数据是否还原。
4. 回滚事务
除了撤销整个事务,用户还可以使用ROLLBACK TO语句使事务回滚到某个点,在这之前需要使用SAVEPOINT语句来设置一个保存点。
SAVEPOINT语法格式为:
SAVEPOINT identifier
其中,identifier为保存点的名称。
ROLLBACK TO SAVEPOINT语句会向已命名的保存点回滚一个事务。如果在保存点被设置后,当前事务对数据进行了更改,则这些更改会在回滚中被撤销。语法格式为:
ROLLBACK [WORK] TO SAVEPOINT identifier
当事务回滚到某个保存点后,在该保存点之后设置的保存点将被删除。
RELEASE SAVEPOINT语句会从当前事务的一组保存点中删除已命名的保存点。不出现提交或回滚。如果保存点不存在,会出现错误。语法格式为:
RELEASE SAVEPOINT identifier
下面几个语句说明了有关事务的处理过程:
1. START TRANSACTION
2. UPDATE …
3. DELETE…
4. SAVEPOINT S1;
5. DELETE…
6. ROLLBACK WORK TO SAVEPOINT S1;
7. INSERT…
8. COMMIT WORK;
说明:在以上语句中,第一行语句开始了一个事务;第2、3行语句对数据进行了修改,但没有提交;第4行设置了一个保存点;第5行删除了数据,但没有提交;第6行将事务回滚到保存点S1,这时第5行所做修改被撤销了;第7行修改了数据;第8行结束了这个事务,这时第2、3、7行对数据库做的修改被持久化。
每一个事务都有一个所谓的隔离级,它定义了用户彼此之间隔离和交互的程度。前面曾提到,事务型RDBMS的一个最重要的属性就是它可以“隔离”在服务器上正在处理的不同的会话。在单用户的环境中,这个属性无关紧要:因为在任意时刻只有一个会话处于活动 状态。但是在多用户环境中,许多RDBMS会话在任一给定时刻都是活动的。在这种情况 下,RDBMS能够隔离事务是很重要的,这样它们不互相影响,同时保证数据库性能不受到 影响。
为了了解隔离的重要性,有必要花些时间来考虑如果不强加隔离会发生什么。如果没有事务的隔离性,不同的SELECT语句将会在同一个事务的环境中检索到不同的结果,因为在这期间,基本上数据已经被其他事务所修改。这将导致不一致性,同时很难相信结果集,从而不能利用查询结果作为计算的基础。因而隔离性强制对事务进行某种程度的隔离,保证应用程序在事务中看到一致的数据。
基于ANSI/ISO SQL规范,MySQL提供了下面4种隔离级:序列化(SERIALIZABLE)、可重复读(REPEATABLE READ)、提交读(READ COMMITTED)、未提交读(READ UNCOMMITTED)。
只有支持事务的存储引擎才可以定义一个隔离级。定义隔离级可以使用SET TRANSACTION语句。
语法格式:
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
SERIALIZABLE
| REPEATABLE READ
| READ COMMITTED
| READ UNCOMMITTED
说明:
如果指定GLOBAL,那么定义的隔离级将适用于所有的SQL用户;如果指定SESSION,则隔离级只适用于当前运行的会话和连接。MySQL默认为REPEATABLE READ隔离级。
(1)序列化
如果隔离级为序列化,用户之间通过一个接一个顺序地执行当前的事务提供了事务之间最大限度的隔离。
(2)可重复读
在这一级上,事务不会被看成是一个序列。不过,当前在执行事务的变化仍然不能看到,也就是说,如果用户在同一个事务中执行同条SELECT语句数次,结果总是相同的。
(3)提交读
READ COMMITTED隔离级的安全性比REPEATABLE READ隔离级的安全性要差。不仅处于这一级的事务可以看到其他事务添加的新记录,而且其他事务对现存记录做出的修改一旦被提交,也可以看到。也就是说,这意味着在事务处理期间,如果其他事务修改了相应的表,那么同一个事务的多个SELECT语句可能返回不同的结果。
(4)未提交读
提供了事务之间最小限度的隔离。除了容易产生虚幻的读操作和不能重复的读操作外,处于这个隔离级的事务可以读到其他事务还没有提交的数据,如果这个事务使用其他事务不提交的变化作为计算的基础,然后那些未提交的变化被它们的父事务撤销,这就导致了大量的数据变化。
系统变量TX_ISOLATION中存储了事务的隔离级,可以使用SELECT随时获得当前隔离级的值
默认情况下,这个系统变量的值是基于每个会话设置的,但是可以通过向SET命令行添加GLOBAL关键字修改该全局系统变量的值。
当用户从无保护的READ UNCOMMITTED隔离级转移到更安全的SERIALIZABLE级时,RDBMS的性能也要受到影响。原因很简单:用户要求系统提供越强的数据完整性,它就越需要做更多的工作,运行的速度也就越慢。因此,需要在RDBMS的隔离性需求和性能之间协调。
MySQL默认为REPEATABLE READ隔离级,这个隔离级适用于大多数应用程序,只有在应用程序有具体的对于更高或更低隔离级的要求时才需要改动。没有一个标准公式来决定哪个隔离级适用于应用程序——大多数情况下,这是一个主观的决定,它是基于应用程序的容错能力和应用程序开发者对于潜在数据错误的影响的判断。隔离级的选择对于每个应用程序也是没有标准的。例如,同一个应用程序的不同事务基于执行的任务需要不同的隔离级。图10.2中列出了事务隔离级和性能之间的关系。
当用户对数据库并发访问时,为了确保事务完整性和数据库一致性,需要使用锁定,它是实现数据库并发控制的主要手段。锁定可以防止用户读取正在由其他用户更改的数据,并可以防止多个用户同时更改相同数据。如果不使用锁定,则数据库中的数据可能在逻辑上不正确,并且对数据的查询可能会产生意想不到的结果。具体地说,锁定可以防止丢失更新、脏读、不可重复读和幻读。
丢失更新(lost update),指当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,因此最后的更新将重写由其他事务所做的更新,这将导致数据丢失。
脏读(dirty read)指一个事务正在访问数据,而其他事务正在更新该数据,但尚未提交,此时就会发生脏读问题,即第一个事务所读取的数据是“脏”(不正确)数据,它可能会引起错误。
当一个事务多次访问同一行而且每次读取不同的数据时,会发生不可重复读(unrepeatable read)问题。不可重复读与脏读有相似之处,因为该事务也是正在读取其他事务正在更改的数据。当一个事务访问数据时,另外的事务也访问该数据并对其进行修改,因此就发生了由于第二个事务对数据的修改而导致第一个事务两次读到的数据不一样的情况,这就是不可重复读。
当一个事务对某行执行插入或删除操作,而该行属于某个事务正在读取的行的范围时,会发生幻读(phantom read)问题。事务第一次读的行范围显示出其中一行已不复存在于第二次读或后续读中,因为该行已被其他事务删除。同样,由于其他事务的插入操作,事务的第二次读或后续读显示有一行已不存在于原始读中。


分享到:
评论

相关推荐

    深入理解分布式事务,高并发下分布式事务的解决方案

    本文来自于csdn,本文主要从分布式的原因,事务特性,和解决方案中深入理解了分布式事务,希望对您的学习有所帮助。 分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的...

    浅谈SQL Server中的事务日志(一)----事务日志的物理和逻辑构架 .docx

    SQL Server中的事务日志无疑是SQL Server中最重要的部分之一。因为SQL SERVER利用事务日志来确保持久性(Durability)和事务回滚(Rollback)。从而还部分确保了事务的ACID属性.在SQL Server崩溃时,DBA还可以通过事务...

    事务处理API分布式事务处理

    本文的目的是要提供一个关于的Java事务处理API(JTA)的高级的概述,以及与分布式事务相关的内容。一个事务处理定义了一个工作逻辑单元,要么彻底成功要么不产生任何结果。 一个分布式事务处理只是一个在两个或更多...

    Spring Boot多数据源(支持Spring声明式事务切换和回滚).pdf

    1. 基于Aspectj实现动态数据源...6. 实现事务内切换数据源(支持原生Spring声明式事务哟,仅此一家),并支持多数据源事务回滚(有了它除了跨服务的事务你需要考虑分布式事务,其他都不需要,极大的减少了系统的复杂程度)

    spring 自定义事务管理器,编程式事务,声明式事务@Transactional使用

    本代码使用H2内存数据库演示spring事务使用,包括编程式事务,声明式事务@Transactional使用,自定义事务事务注解实现自定义事务管理器

    基于springboot整理的分布式事务及动态数据源切换

    整理的分布式事务 及动态数据源切换 基于数据库XA协议 maven 包可直接使用 maven 引入路径: <groupId>com.maple</groupId> <artifactId>DCSDataSourcesServer <version>0.0.1-SNAPSHOT 事务及数据源标签...

    PHP事务处理实例 mysql事务处理的意义

    mysql事务处理的意义 事务处理机制在程序开发过程中有着非常重要的作用,它可以使整个系统更加安全,例如在银行处理转账业务时,如果A账户中的金额刚被发出,而B账户还没来得及接收就发生停电,这会给银行和个人带来...

    太极分布式事务处理框架moonwater

    结合目前事务处理的精华,我开发了太极分布式事务处理框架TJDTP,采用可靠消息服务和重试、补偿处理机制,使用事件驱动、最终一致的事务模型,巧妙地运用数据库的事务处理能力,对服务操作结果进行判断,调用应用...

    微服务架构的分布式事务解决方案(Dubbo分布式事务处理)

    为了解决大家在实施分布式服务化架构过程中关于分布式事务问题的困扰,本教程将基于支付系统真实业务中的经典场景来对“可靠消息的最终一致性方案”、“TCC两阶段型方案”和“最大努力通知型方案”这3种柔性事务解决...

    Java Web项目企业事务管理系统源码

    Java Web项目企业事务管理系统源码,详细的代码注释 本系统的开发工具具体如下。 ● 系统开发平台:MyEclipse 6.5。 ● 数据库管理系统软件:MySQL 5.0。 ● 运行平台:Windows 2000/Windows XP/Windows 2003/...

    分布式事务实践 解决数据一致性

    介绍分布式事务的定义、原则和实现原则,介绍使用Spring框架实现分布式事务的几种方式,包括使用JTA、Spring事务同步、链式事务等,并通过实战介绍其实现。除此以外还介绍了一些分布式事务相关的技术,如幂等性、...

    分布式事务系统DTS原理及使用

    分布式事务服务 (Distributed Transaction Service, DTS) 是一个分布式事务框架,用来保障在大规模分布式环境下事务的最终一致性。DTS 从架构上分为 dts-core 、dts-schedule、 dts-server 两部分,dts-core是一个...

    mySQL事务处理

    关于mysql的事务处理 public static void StartTransaction(Connection con, String[] sqls) throws Exception { if (sqls == null) { return; } Statement sm = null; try { // 事务开始 System....

    springboot mybatis多数据源加事务嵌套

    springboot mybatis多数据源加事务嵌套 事务之间的调用 回滚 亲测可用 定义2个库分别建立 CREATE TABLE `user` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户编号', `user_name` varchar(25) ...

    毕业设计—基于Java的Acme班级事务管理系统.zip

    毕业设计—基于Java的Acme班级事务管理系统,已获老师指导并通过的高分项目。 毕业设计—基于Java的Acme班级事务管理系统,已获老师指导并通过的高分项目。毕业设计—基于Java的Acme班级事务管理系统,已获老师指导...

    jta分布式事务完成例子,测试通过

    例子虽小,可覆盖面广,设计spring载入.properties文件,spring配置jta和jotm分布式事务,设置数据源连接池,注解事务驱动。功能是在mysql上建立了两个数据库分别为dbone和dbtwo,在dbone里有表tb1,表中只有一个字段...

    浅谈SQL Server中的事务日志(四)----在完整恢复模式下日志的角色.docx

    SQL Server中的事务日志无疑是SQL Server中最重要的部分之一。因为SQL SERVER利用事务日志来确保持久性(Durability)和事务回滚(Rollback)。从而还部分确保了事务的ACID属性.在SQL Server崩溃时,DBA还可以通过事务...

    Spring事务传播特性解析

    方法被调用时自动开启事务,在事务范围内使用则使用同一个事务,否则开启新事务。 2、Propagation.REQUIRES_NEW 无论何时自身都会开启事务 3、Propagation.SUPPORTS 自身不会开启事务,在事务范围内则...

    注入JdbcTemplate启用事务管理.docx

    例:a方法调用b方法,如果a方法有事务,则b加入a事务,如果a没有,则b新建一个事务 @see Propagation#SUPPORTS 支持当前事务,如果没有则以非事务运行 例:a方法调用b方法,如果a方法有事务,则b加入a事务,如果a...

    Java中事务的实现

    在JDBC中,打开一个连接对象Connection时,缺省是auto-commit模式,每个SQL语句都被当作一个事务,即每次执行一个语句,都会自动的得到事务确认。为了能将多个SQL语句组合成一个事务,要将auto-commit模式屏蔽掉。在...

Global site tag (gtag.js) - Google Analytics