zoukankan      html  css  js  c++  java
  • 事务控制语句,begin,rollback,savepoint,隐式提交的SQL语句

    事务控制语句

    在MySQL命令行的默认设置下,事务都是自动提交的,即执行SQL语句后就会马上执行COMMIT操作。因此开始一个事务,必须使用BEGIN、START TRANSACTION,或者执行SET AUTOCOMMIT=0,以禁用当前会话的自动提交。这和Microsoft SQL Server数据库的方式一致,需要显式地开始一个事务。而Oracle数据库不需要专门的语句来开始事务,事务会在修改数据的第一条语句处隐式地开始。

    在具体介绍其含义之前,先来看看我们可以使用哪些事务控制语句:

    1. START TRANSACTION|BEGIN:显式地开启一个事务。
    2. COMMIT:要想使用这个语句的最简形式,只需发出COMMIT。也可以更详细一些,写为COMMIT WORK,不过这二者几乎是等价的。COMMIT会提交你的事务,并使得已对数据库做的所有修改成为永久性的。
    3. ROLLBACK:要想使用这个语句的最简形式,只需发出ROLLBACK。同样,你也可以写为ROLLBACK WORK,但是二者几乎是等价的。回滚会结束你的事务,并撤销正在进行的所有未提交的修改。
    4. SAVEPOINT identifier:SAVEPOINT允许你在事务中创建一个保存点,一个事务中可以有多个SAVEPOINT。
    5. RELEASE SAVEPOINT identifier:删除一个事务的保存点,当没有一个保存点执行这句语句时,会抛出一个异常。
    6. ROLLBACK TO[SAVEPOINT]identifier:这个语句与SAVEPOINT命令一起使用。可以把事务回滚到标记点,而不回滚在此标记点之前的任何工作。例如可以发出两条UPDATE语句,后面跟一个SAVEPOINT,然后又是两条DELETE语句。如果执行DELETE语句期间出现了某种异常情况,而且你捕获到这个异常,并发出ROLLBACK TO SAVEPOINT命令,事务就会回滚到指定的SAVEPOINT,撤销DELETE完成的所有工作,而UPDATE语句完成的工作不受影响。
    7. SET TRANSACTION:这个语句用来设置事务的隔离级别。InnoDB存储引擎提供的事务隔离级别有:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE。

    START TRANSACTION、BEGIN语句都可以在mysql命令行下显式地开启一个事务。但是在存储过程中,MySQL分析会自动将BEGIN识别为BEGIN……END。因此在存储过程中,只能使用START TRANSACTION语句来开启一个事务。

    COMMIT和COMMIT WORK语句基本是上一致的,都是用来提交事务。不同之处在于,COMMIT WORK用来控制事务结束后的行为,是CHAIN还是RELEASE的。可以通过参数completion_type来进行控制,默认情况下该参数为0,表示没有任何操作。在这种设置下,COMMIT和COMMIT WORK是完全等价的。

    当参数completion_type的值为1时,COMMIT WORK等同于COMMIT AND CHAIN,表示马上自动开启一个相同隔离级别的事务,如:

    create table t(a int,primary key(a))engine=innodb;

    select @@autocommitG

    @@autocommit:1

    set @@completion_type=1;

    begin;

    insert into t select 1;

    commit work;

    insert into t select 2;

    insert into t select 2;

    ERROR 1062(23000):Duplicate entry '2' for key'PRIMARY'

    rollback;

    #注意回滚之后只有1这个记录,而没有2这个记录

    select * from tG

    我们将completion_type设置为1,第一次通过COMMIT WORK来插入1这个记录。之后插入记录2时我们并没有用BEGIN(或者START TRANSACTION)来开启一个事务,之后再插入一条重复的记录2,这时会抛出异常。我们执行ROLLBACK操作,最后发现只有1这一个记录,2并没有被插入。因为completion_type为1时,COMMIT WORK会自动开启一个事务,因此两个INSERT语句是在同一个事务内的,因此回滚后就没有进行插入。

    参数completion_type为2时,COMMIT WORK等同于COMMIT AND RELEASE。当事务提交后会自动断开与服务器的连接,如:

    set @@completion_type=2;

    begin;

    insert into t select 3;

    commit work;

    select @@versionG

    ERROR 2006(HY000):MySQL server has gone away

    No connection.Trying to reconnect……

    Connection id:54

    Current database:test

    ***************************1.row***************************

    @@version:5.1.45-log

    1 row in set(0.00 sec)

    通过上面的实验可以发现,当参数completion_type设置为2时,COMMIT WORK后,我们再执行select @@version,会出现ERROR 2006(HY000):MySQL server has gone away的错误,这其实就是因为当前会话已经在上次执行COMMIT WORK语句后与服务器断开了连接。

    ROLLBACK和ROLLBACK WORK与COMMIT和COMMIT WORK的工作一样,不再赘述。

    SAVEPOINT记录了一个保存点,可以通过ROLLBACK TO SAVEPOINT回滚到某个保存点,但是如果回滚到一个不存在的保存点,会抛出异常:

    begin;

    rollback to savepoint t1;

    ERROR 1305(42000):SAVEPOINT t1 does not exist

    InnoDB存储引擎中的事务都是原子的,这说明下述两种情况:或者构成事务的每条语句都会提交(成为永久),或者所有语句都回滚。这种保护还延伸到单个的语句。一条语句要么完全成功,要么完全回滚(注意,我说的是语句回滚)。如果一条语句失败,并不会导致先前已经执行的语句自动回滚。它们的工作会保留,必须由你来决定是否对其进行提交或回滚操作。如:

    create table t(a int,primary key(a))engine=innodb;

    begin;

    insert into t select 1;

    insert into t select 1;

    ERROR 1062(23000):Duplicate entry'1'for key'PRIMARY'

    select * from tG

    可以看到,插入第二记录1时,因为重复的关系抛出了1062的错误,但是数据库并没有进行自动回滚,这时事务仍需要我们显式地运行COMMIT或者ROLLBACK。

    另一个容易犯的错误是ROLLBACK TO SAVEPOINT,虽然有ROLLBACK,但是它并不是真正地结束一个事务,因此即使执行了ROLLBACK TO SAVEPOINT,之后也需要显式地运行COMMIT或者ROLLBACK命令。

    create table t(a int,primary key(a))engine=innodb;

    begin;

    insert into t select 1;

    savepoint t1;

    insert into t select 2;

    savepoint t2;

    release savepoint t1;

    insert into t select 2;

    ERROR 1062(23000):Duplicate entry'2'for key'PRIMARY'

    rollback to savepoint t2;

    select * from t;

    rollback;

    select * from t;

    Empty set(0.00 sec)

    在上面的例子中可以看到,虽然我们在发生重复错误后,通过ROLLBACK TO SAVEPOINT t2命令回滚到了保存点t2,但是事务此时并没有结束,我们再接着运行ROLLBACK后,事务才完整回滚。需要再次提醒的是,ROLLBACK TO SAVEPOINT命令并不真正地结束事务。

    隐式提交的SQL语句

    以下这些SQL语句会产生一个隐式的提交操作,即执行完这些语句后,会有一个隐式的COMMIT操作。

    1. DDL语句:ALTER DATABASE……UPGRADE DATA DIRECTORY NAME、ALTER EVENT、ALTER PROCEDURE、ALTER TABLE、ALTER VIEW、CREATE DATABASE、CREATE EVENT、CREATE INDEX、CREATE PROCEDURE、CREATE TABLE、CREATE TRIGGER、CREATE VIEW、DROP DATABASE、DROP EVENT、DROP INDEX、DROP PROCEDURE、DROP TABLE、DROP TRIGGER、DROP VIEW、RENAME TABLE、TRUNCATE TABLE。
    2. 用来隐式地修改mysql架构的操作:CREATE USER、DROP USER、GRANT、RENAME USER、REVOKE、SET PASSWORD。
    3. 管理语句:ANALYZE TABLE、CACHE INDEX、CHECK TABLE、LOAD INDEX INTO CACHE、OPTIMIZE TABLE、REPAIR TABLE。

    注意:我发现Microsoft SQL Server的数据库管理员或者开发人员往往忽视对于DDL语句的隐式提交操作,因为在Microsoft SQL Server数据库中,即使是DDL也是可以回滚的。这和InnoDB存储引擎、Oracle数据库都不同。

    TRUNCATE TABLE语句是DDL,因此虽然和DELETE整张表的结果是一样的,但它是不能被回滚(这又是和Microsoft SQL Server数据不同的地方):

    select * from tG

    begin;

    truncate table t;

    rollback;

    select * from t;

    Empty set(0.00 sec) 

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    CodeForces 785D Anton and School
    CodeForces 785C Anton and Fairy Tale
    CodeForces 785B Anton and Classes
    CodeForces 785A Anton and Polyhedrons
    爱奇艺全国高校算法大赛初赛C
    爱奇艺全国高校算法大赛初赛B
    爱奇艺全国高校算法大赛初赛A
    EOJ 3265 七巧板
    EOJ 3256 拼音魔法
    EOJ 3262 黑心啤酒厂
  • 原文地址:https://www.cnblogs.com/wade-luffy/p/6297836.html
Copyright © 2011-2022 走看看