`
北极的。鱼
  • 浏览: 159313 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【转】事务

 
阅读更多

转自:http://www.cnblogs.com/hoojo/archive/2011/07/19/2110325.html

 

Ø 事务

在数据库中有时候需要把多个步骤的指令当作一个整体来运行,这个整体要么全部成功,要么全部失败,这就需要用到事务。

    1、 事务的特点

        事务有若干条T-SQL指令组成,并且所有的指令作为一个整体提交给数据库系统,执行时,这组指令要么全部执行完成,要么全部取消。因此,事务是一个不可分割的逻辑单元。

 

        事务有4个属性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)以及持久性(Durability),也称作事务的ACID属性。

        原子性:事务内的所有工作要么全部完成,要么全部不完成,不存在只有一部分完成的情况。

        一致性:事务内的操作都不能违反数据库的约束或规则,事务完成时有内部数据结构都必须是正确的。(个人理解:事务运行后数据库前后的状态要是相等的,既5+2=7和5-2=3)

        隔离性:事务之间是相互隔离的,如果有两个事务对同一个数据库进行操作,比如读取表数据。任何一个事务看到的所有内容要么是其他事务完成之前的状态,要么是其他事务完成之后的状态。一个事务不可能遇到另一个事务的中间状态。

        持久性:事务完成之后,它对数据库系统的影响是持久的,即使是系统错误,重新启动系统后,该事务的结果依然存在。

 

    2、 事务的模式

        a、 显示事务

        显示事务就是用户使用T-SQL明确的定义事务的开始(begin transaction)和提交(commit transaction)或回滚事务(rollback transaction)

        b、 自动提交事务

        自动提交事务是一种能够自动执行并能自动回滚事务,这种方式是T-SQL的默认事务方式。例如在删除一个表记录的时候,如果这条记录有主外键关系的时候,删除就会受主外键约束的影响,那么这个删除就会取消。

        可以设置事务进入隐式方式:set implicit_transaction on;

        c、 隐式事务

        隐式事务是指当事务提交或回滚后,SQL Server自动开始事务。因此,隐式事务不需要使用begin transaction显示开始,只需直接失业提交事务或回滚事务的T-SQL语句即可。

        使用时,需要设置set implicit_transaction on语句,将隐式事务模式打开,下一个语句会启动一个新的事物,再下一个语句又将启动一个新事务。

 

    3、 事务处理

        常用T-SQL事务语句:

        a、 begin transaction语句

        开始事务,而@@trancount全局变量用来记录事务的数目值加1,可以用@@error全局变量记录执行过程中的错误信息,如果没有错误可以直接提交事务,有错误可以回滚。(BEGIN TRANSACTION 代表一个点,由连接引用的数据在该点是逻辑和物理上都一致的。如果遇上错误,在 BEGIN TRANSACTION 之后的所有数据改动都能进行回滚,以将数据返回到已知的一致状态 。每个事务继续执行直到它无误地完成并且用 COMMIT TRANSACTION 对数据库作永久的改动,或者遇上错误并且用 ROLLBACK TRANSACTION 语句擦除所有改动

        b、 commit transaction语句

        提交事务,表示一个隐式或显示的事务的结束,对数据库所做的修改正式生效。并将@@trancount的值减1;

        c、 rollback transaction语句

        回滚事务,执行rollback tran语句后,数据会回滚到begin tran的时候的状态

 

    4、 事务的示例

--开始事务
begin transaction tran_bank;
declare @tran_error int;
    set @tran_error = 0;
    begin try
        update bank set totalMoney = totalMoney - 10000 where userName = 'jack';        
        set @tran_error = @tran_error + @@error;
        update bank set totalMoney = totalMoney + 10000 where userName = 'jason';
        set @tran_error = @tran_error + @@error;
    end try
    begin catch        
        print '出现异常,错误编号:' + convert(varchar, error_number()) + ', 错误消息:' + error_message(); 
        set @tran_error = @tran_error + 1;
    end catch
if (@tran_error > 0)
    begin
        --执行出错,回滚事务
        rollback tran;
        print '转账失败,取消交易';
    end
else
    begin
        --没有异常,提交事务
        commit tran;
        print '转账成功';
    end
go

 Ø 异常

     在程序中,有时候完成一些Transact-SQL会出现错误、异常信息。如果我们想自己处理这些异常信息的话,需要手动捕捉这些信息。那么我们可以利用try catch完成。

TRY…CATCH 构造包括两部分:一个 TRY 块和一个 CATCH 块。如果在 TRY 块中所包含的 Transact-SQL 语句中检测到错误条件,控制将被传递到 CATCH 块(可在此块中处理该错误)。

     CATCH 块处理该异常错误后,控制将被传递到 END CATCH 语句后面的第一个 Transact-SQL 语句。如果 END CATCH 语句是存储过程或触发器中的最后一条语句,控制将返回到调用该存储过程或触发器的代码。将不执行 TRY 块中生成错误的语句后面的 Transact-SQL 语句。

     如果 TRY 块中没有错误,控制将传递到关联的 END CATCH 语句后紧跟的语句。如果 END CATCH 语句是存储过程或触发器中的最后一条语句,控制将传递到调用该存储过程或触发器的语句。

     TRY 块以 BEGIN TRY 语句开头,以 END TRY 语句结尾。在 BEGIN TRY 和 END TRY 语句之间可以指定一个或多个 Transact-SQL 语句。CATCH 块必须紧跟 TRY 块。CATCH 块以 BEGIN CATCH 语句开头,以 END CATCH 语句结尾。在 Transact-SQL 中,每个 TRY 块仅与一个 CATCH 块相关联。

     # 错误函数

TRY...CATCH 使用错误函数来捕获错误信息。
    ERROR_NUMBER() 返回错误号。
    ERROR_MESSAGE() 返回错误消息的完整文本。此文本包括为任何可替换参数(如长度、对象名称或时间)提供的值。
    ERROR_SEVERITY() 返回错误严重性。
    ERROR_STATE() 返回错误状态号。
    ERROR_LINE() 返回导致错误的例程中的行号。
    ERROR_PROCEDURE() 返回出现错误的存储过程或触发器的名称。

  示例

--错误消息存储过程
if (object_id('proc_error_info') is not null)
    drop procedure proc_error_info
go
create proc proc_error_info
as
    select 
        error_number() '错误编号',
        error_message() '错误消息',
        error_severity() '严重性',
        error_state() '状态好',
        error_line() '错误行号',
        error_procedure() '错误对象(存储过程或触发器)名称';
go

 # 示例:用异常处理错误信息

--简单try catch示例
begin try
    select 1 / 0;
end try
begin catch
    exec proc_error_info; --调用错误消息存储过程
end catch
go

 # 示例:异常能处理的错误信息

--
--简单try catch示例,无法处理错误
begin try
    select * * from student;
end try
begin catch
    exec proc_error_info;
end catch
go
--
--简单try catch示例,不处理错误(不存在的表对象)
begin try
    select * from st;
end try
begin catch
    exec proc_error_info;
end catch
go
--
--异常处理,能处理存储过程(触发器)中(不存在表对象)的错误信息
if (object_id('proc_select') is not null)
    drop procedure proc_select
go
create proc proc_select
as
    select * from st;
go
begin try
    exec proc_select;
end try
begin catch    
    exec proc_error_info;
end catch
go

 异常不能处理编译期的错误,如语法错误。以及重编译造成部分名称对象得不到正确解析的时候所出现的错误。

 

     # 示例:无法提交的事务

--创建临时用表
if (object_id('temp_tab', 'u') is not null)
    drop table temp_tab
go
create table temp_tab(
    id int primary key identity(100000, 1),
    name varchar(200)
)
go

begin try
    begin tran;
    --没有createTime字段
    alter table temp_tab drop column createTime;
    commit tran;
end try
begin catch
    exec proc_error_info;--显示异常信息
    if (xact_state() = -1)
    begin
        print '会话具有活动事务,但出现了致使事务被归类为无法提交的事务的错误。'
            + '会话无法提交事务或回滚到保存点;它只能请求完全回滚事务。'
            + '会话在回滚事务之前无法执行任何写操作。会话在回滚事务之前只能执行读操作。'
            + '事务回滚之后,会话便可执行读写操作并可开始新的事务。';
    end
    else if (xact_state() = 0)
    begin
        print '会话没有活动事务。';
    end
    else if (xact_state() = 1)
    begin
        print '会话具有活动事务。会话可以执行任何操作,包括写入数据和提交事务。';
    end
end catch
go

 # 示例:处理异常日志信息

--
---异常、错误信息表
if (object_id('errorLog', 'U') is not null)
    drop table errorLog
go
create table errorLog(
    errorLogID int primary key identity(100, 1),    --ErrorLog 行的主键。
    errorTime datetime default getDate(),            --发生错误的日期和时间。
    userName sysname default current_user,            --执行发生错误的批处理的用户。
    errorNumber int,                                --发生的错误的错误号。
    errorSeverity int,                                --发生的错误的严重性。
    errorState int,                                    --发生的错误的状态号。
    errorProcedure nvarchar(126),                    --发生错误的存储过程或触发器的名称。
    errorLine int,                                    --发生错误的行号。
    errorMessage nvarchar(4000)
)
go
--
--存储过程:添加异常日志信息
if (object_id('proc_add_exception_log', 'p') is not null)
    drop proc proc_add_exception_log
go
create proc proc_add_exception_log(@logId int = 0 output)
as
begin
    set nocount on;
    set @logId = 0;
    begin try
        if (error_number() is null)
            return;
        
        if (xact_state() = -1)
        begin
            print '会话具有活动事务,但出现了致使事务被归类为无法提交的事务的错误。'
                + '会话无法提交事务或回滚到保存点;它只能请求完全回滚事务。'
                + '会话在回滚事务之前无法执行任何写操作。会话在回滚事务之前只能执行读操作。'
                + '事务回滚之后,会话便可执行读写操作并可开始新的事务。';
        end
        else if (xact_state() = 0)
        begin
            print '会话没有活动事务。';
        end
        else if (xact_state() = 1)
        begin
            print '会话具有活动事务。会话可以执行任何操作,包括写入数据和提交事务。';
        end
        
        --添加日志信息
        insert into errorLog values(getDate(), 
            current_user, error_number(), 
            error_severity(), error_state(), 
            error_procedure(), 
            error_line(), error_message());
        --设置自增值
        select @logId = @@identity;
    end try
    begin catch
        print '添加异常日志信息出现错误';
        exec proc_error_info;--显示错误信息
        return -1;
    end catch
end
go
--
---处理异常信息示例
declare @id int;
begin try
    begin tran;
    --删除带有外键的记录信息
    delete classes where id = 1;
    commit tran;
end try
begin catch
    exec proc_error_info;--显示错误信息
    if (xact_state() <> 0)
    begin
        rollback tran;
    end
    exec proc_add_exception_log @id output
end catch
select * from errorLog where errorLogID = @id;
go

 

事务隔离级别




其实隔离级别就是提供锁机制来控制读者写者问题对临界资源的访问:

更新丢失:2个写者同时作业,其中一个失败导致回滚,但是另一个写者事务不知道。(read umcommitted)

脏读:读者读到了写者过程中的数据,这个被修改了,但是没提交到数据库,那么写者事务失败的话,这个数据就没意义。(read committed)

不可重复读:读者事务对相同数据两次读取的间隙,写者事务更新了数据,导致读者两次操作结果不同。(repeatable read)

幻读:读者事务两次读取的结果数目不同,因为两次读取的间隙,写者事务发生操作了。(serializable)

  • 大小: 59.7 KB
分享到:
评论

相关推荐

    kettle使用事务的转换

    kettle使用事务的转换

    事务所审计员年度个人工作总结(范文)..doc

    事务所审计员年度个人工作总结是对一年来工作的回顾与评估,对于审计行业的从业者来说,这是自我提升和改进的重要环节。在本文中,作者首先探讨了国内事务所行业的发展前景及建议,然后聚焦于事务所的质量控制。 ...

    个人股东股权转让个人所得税鉴证报告.docx

    这份报告由一家会计师事务所为公司提供,旨在确保股权转让过程中的税收合规性。报告的主要内容包括公司的基本情况、股权转让的具体情况以及相关股东的投资损益计算,最后提及其他审核事项和报告附件。 1. 公司基本...

    Java进阶-连接池&amp;amp;amp;amp;事务(九).zip

    在Java编程领域,连接池和事务管理是两个非常重要的概念,尤其对于开发高效、稳定的企业级应用程序至关重要。本文将深入探讨这两个主题,并结合Dbutils工具库进行讲解。 首先,我们来了解一下连接池。连接池是一种...

    A级税务师事务所执业信用等级考评具体标准.pdf

    【A级税务师事务所执业信用等级考评】是针对税务师事务所的一项重要评估标准,旨在确保事务所在提供专业服务时遵循法规、保持良好的职业道德,并具备一定的经营规模和执业质量。以下是该考评的具体内容: 首先,**...

    对中小事务所数字化转型的若干思考

    【标题】:“对中小事务所数字化转型的若干思考” 【描述】:文章探讨了中小事务所在面对数字化转型过程中的挑战和机遇,强调了数字化在疫情应对中的重要作用,并指出数字化已经深刻影响了政府、企业和个人的工作...

    android SQLite增删改查及事务处理

    SQLite是一个轻量级的数据库系统,它支持标准的关系型数据库特性,如SQL语法、事务处理等。这篇内容将深入讲解如何在Android中使用SQLite进行数据的增删改查(CRUD)操作以及事务处理。 首先,我们来了解SQLite在...

    2021-2022年收藏的精品资料银行2年到事务所就这样难被理解吗?.doc

    - 这种转变通常是因为银行工作虽然稳定,但可能不如事务所具有挑战性,同时事务所能够提供更多的专业成长机会,如注册会计师(CPA)的备考和实践经验。 2. **选择银行的原因**: - 作者在毕业后选择了银行,主要是...

    使用DateTimePicker程序, 当您进一步完善后,可以加入事务处理(C#源代码编写)

    这篇教程将深入探讨如何使用DateTimePicker控件,并讨论如何在您的应用程序中添加事务处理功能。 首先,让我们了解DateTimePicker的基本用法。在C#中,DateTimePicker是System.Windows.Forms命名空间下的一个类。要...

    对中小事务所数字化转型的若干思考.pdf

    【标题】:“对中小事务所数字化转型的若干思考” 【描述】:该文件探讨了中小事务所在面临数字化转型过程中的挑战和机遇,特别是在新冠疫情背景下,数字化的重要性愈发凸显。 【标签】:“新金融 金融行业 数据...

    【面试必备】Spring事务源码解析.txt

    本资源讲解的是Spring事务的相关技术,需要可自行下载。...2.埋坑,从深坑中玩转事务; 3.迷一般的事务?我数据验证为啥失效? 4.透过源码学习事务隔离级别; 5.源码解读,原来事务就那么回事; 6.互动答疑;

    事务与锁定的问题 自治事务

    ### 事务与锁定的问题:自治事务详解 #### 一、事务与锁定的基础 在数据库管理中,事务(Transaction)和锁定(Locking)是保证数据完整性和一致性的重要机制。事务被视为一系列操作的集合,这些操作要么全部成功...

    浅谈律师事务所经营模式的转型.pdf

    《浅谈律师事务所经营模式的转型》一文深入探讨了法律服务机构如何从传统的多元化经营模式向专业化模式转变的问题。文章首先强调了专业化在律所发展中的重要性,并指出多元化经营模式存在的问题。经营模式是由特定的...

    Java事务处理总结

    ### Java事务处理总结 #### 一、什么是Java事务 事务是指一组操作的集合,这些操作要么全部成功,要么全部失败,以确保数据的一致性和完整性。在Java开发中,事务处理主要关注的是如何管理和控制对数据库的操作,...

    事务的使用方法

    ### 事务的使用方法 #### 一、引言 在软件开发中,特别是在涉及数据库操作的应用程序中,事务处理是一项非常重要的技术。它确保了一系列的操作要么全部成功完成,要么全部失败回滚,从而保持了数据的一致性和完整...

    会计师事务所股权转让合同协议合同书.pdf

    1. **股权转让**:此文档详细阐述了会计师事务所的股权转让过程,其中转让方(甲方)将其持有的100%股权转给受让方(乙方)。股权转让是基于《公司法》和《合同法》的规定进行的。 2. **股权转让前提条件**:乙方在...

    JSP运用事务处理

    此外,JSP通常与Java后端框架(如Spring、Struts等)配合,这些框架提供了更高级的事务管理功能,如支持声明式事务、事务回滚规则、事务传播行为等。例如,Spring的PlatformTransactionManager接口和@Transactional...

    Java中的事务处理

    在Java编程领域,事务处理是确保数据一致性与完整性的关键机制。它主要用于数据库操作,确保一组操作要么全部成功,要么全部失败,遵循ACID(原子性、一致性、隔离性和持久性)原则。以下是对Java中事务处理的详细...

    java事务设计策略

    根据提供的文件信息,我们可以深入探讨“Java事务设计策略”这一主题。尽管提供的文件内容主要包含了出版信息而非具体的事务设计内容,但基于标题、描述及标签信息,我们可以推断出本书可能涉及的关键知识点,并据此...

    数据库事务应用

    ### 数据库事务应用详解 #### 事务处理的重要性与ACID特性 事务处理是现代数据库管理系统(DBMS)中不可或缺的一部分,尤其对于那些涉及复杂业务逻辑、需要确保数据一致性和完整性的应用来说更是如此。事务处理的...

Global site tag (gtag.js) - Google Analytics