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) 

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    微信自动回复
    pyqt5生成的APP制作DMG
    win10 安装MySQL过程和遇到的坑
    CentOS7 虚拟机设置文件共享 VMWareTools安装遇到的坑
    阿里云配置ssl证书服务遇到的几个问题和解决方法
    Linux基于libmemcached,php扩展memcached的安装
    PHP框架CodeIgniter--URL去除index.php
    javascript新窗口打开链接window.open()被阻拦的解决办法
    Centos6.5源码编译安装nginx
    MySQL批量修改数据库的字符集
  • 原文地址:https://www.cnblogs.com/wade-luffy/p/6297836.html
Copyright © 2011-2022 走看看