从SQL语言的分类谈COMMIT和ROLLBACK的用法

来源:互联网 发布:手机二次元壁纸软件 编辑:程序博客网 时间:2024/05/21 15:47

从SQL语言的分类谈COMMIT和ROLLBACK的用法


mysql的autocommit(自动提交)默认是开启,其对mysql的性能有一定影响,举个例子来说,如果你插入了1000条数据,mysql会commit1000次的,如果我们把autocommit关闭掉,通过程序来控制,只要一次commit就可以了。

1,我们可以通过set来设置autocommit

查看复制打印?
  1. mysql> set global init_connect="set autocommit=0";  //提示你用权限更高的财户来设置  
  2. ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER privilege(s) for this operation  
  3. mysql> set autocommit=0;  
  4. Query OK, 0 rows affected (0.00 sec)  
  5.   
  6. mysql> select @@autocommit;   //查看一下autocommit的设置  
  7. +--------------+  
  8. | @@autocommit |  
  9. +--------------+  
  10. |            0 |  
  11. +--------------+  
  12. 1 row in set (0.00 sec)  

2,我们可以修改mysql的配置文件my.cnf来关闭autocommit

查看复制打印?
  1. [mysqld]  
  2. init_connect='SET autocommit=0'  //在mysqld里面加上这些内容  

用第二种方法关,有一点要注意,连接mysql用户的权限不能大于启动mysql的用户的权限,不然init_connect='SET autocommit=0'根本不会启作用,也不会报任何错误,汗一个先。看以下实例

查看复制打印?
  1. zhangy@ubuntu:~$ mysql -umysql  
  2. Welcome to the MySQL monitor.  Commands end with ; or \g.  
  3. Your MySQL connection id is 1  
  4. Server version: 5.5.2-m2-log Source distribution  
  5.   
  6. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.  
  7.   
  8. mysql> select @@autocommit;     //mysql是启动用户,关闭autocommit成功  
  9. +--------------+  
  10. | @@autocommit |  
  11. +--------------+  
  12. |            0 |  
  13. +--------------+  
  14. 1 row in set (0.00 sec)  
  15.   
  16. mysql> Ctrl-C -- exit!  
  17. Aborted  
  18. zhangy@ubuntu:~$ mysql -uroot  
  19. Welcome to the MySQL monitor.  Commands end with ; or \g.  
  20. Your MySQL connection id is 2  
  21. Server version: 5.5.2-m2-log Source distribution  
  22.   
  23. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.  
  24.   
  25. mysql> select @@autocommit;    //用root财户启动,不成功。  
  26. +--------------+  
  27. | @@autocommit |  
  28. +--------------+  
  29. |            1 |  
  30. +--------------+  
  31. 1 row in set (0.00 sec)  

这个会不会是mysql的bug呢?我在网上找了找这方面的问题,还真有。部分内容如下:
If a user has SUPER privilege, init_connect will not execute
(otherwise if init_connect will a wrong query no one can connect to server).

Note, if init_connect is a wrong query, the connection is closing without any errors
and next command will clause 'lost connection' error.

里面有一点说的很清楚If a user has SUPER privilege, init_connect will not execute,如果用户有更高级的权限,init_connect根本不会执行。




2013-08-08 16:55:21


大家都知道SQL Server事务是单个的工作单元。如果某一事务成功,则在该事务中进行的所有数据修改均会提交,成为数据库中的永久组成部分。如果事务遇到错误且必须取消或回滚,则所有数据修改均被清除。

所以是不是说事务出错一定会回滚整个事物呢? 先看几个个例子: 

--create table

createtabletestrollback(id intprimarykey, name varchar(10))

 

SETXACT_ABORTOFF--Default Settings 

begintran

insertinto testrollback values (1,'kevin')

insertinto testrollback values (2,'kevin')

insertinto testrollback values (1,'kevin')

insertinto testrollback values (3,'kevin')

committran

三条成功插入只有第三条语句出错回滚

--use SET XACT_ABORT ON

SETXACT_ABORTON;

begintran

insertinto testrollback values (1,'kevin')

insertinto testrollback values (2,'kevin')

insertinto testrollback values (1,'kevin')

insertinto testrollback values (3,'kevin')

committran

 

select*from testrollback 

全部回滚没有数据插入

 

---use try catch to catch error and rollback whole transcation 

begintran

begintry

insertinto testrollback values (1,'kevin')

insertinto testrollback values (2,'kevin')

insertinto testrollback values (1,'kevin')

insertinto testrollback values (3,'kevin')

committran

endtry

begincatch

rollback

endcatch

 

全部回滚没有数据插入

对于上面的测试可以看到默认情况下SQL Server只是Rollback出错的语句而不是整个事物。所以如果想Rollback整个事物的话可以通过SET XACT_ABORT选项设置或者使用Try Catch之类的捕获错误进行Rollback. 

对于出现网络问题会跟上面的结果有点不一样。在执行事务的过程中,如果Client断开,那么SQL Server会自动Rollback整个事物。

SSMS客户端执行第一条语句,去掉commit Tran 

SETXACT_ABORTOFF--Default Settings 

begintran

insertinto testrollback values (1,'kevin')

insertinto testrollback values (2,'kevin')

insertinto testrollback values (1,'kevin')

insertinto testrollback values (3,'kevin')

之后断开连接,在服务器上用DBCC OPENTRAN查看open的事务:

间隔一段时间再执行发现DBCC OPENTRAN已经没有了,而且查询表数据也没有,说明整个事物回滚了。所以在客户端断开且事务没有完成的情况下整个事物回滚。

对于上面的测试微软有详细的解释:

If an error prevents the successful completion of a transaction, SQL Server automatically rolls back the transaction and frees all resources held by the transaction. If the client's network connection to an instance of the Database Engine is broken, any outstanding transactions for the connection are rolled back when the network notifies the instance of the break. If the client application fails or if the client computer goes down or is restarted, this also breaks the connection, and the instance of the Database Engine rolls back any outstanding connections when the network notifies it of the break. If the client logs off the application, any outstanding transactions are rolled back.

If a run-time statement error (such as a constraint violation) occurs in a batch, the default behavior in the Database Engine is to roll back only the statement that generated the error. You can change this behavior using the SET XACT_ABORT statement. After SET XACT_ABORT ON is executed, any run-time statement error causes an automatic rollback of the current transaction. Compile errors, such as syntax errors, are not affected by SET XACT_ABORT. For more information, see SET XACT_ABORT (Transact-SQL)

更多信息参考 Controlling Transactions

mysql的autocommit(自动提交)默认是开启,其对mysql的性能有一定影响,举个例子来说,如果你插入了1000条数据,mysql会commit1000次的,如果我们把autocommit关闭掉,通过程序来控制,只要一次commit就可以了。

1,我们可以通过set来设置autocommit

查看复制打印?
  1. mysql> set global init_connect="set autocommit=0";  //提示你用权限更高的财户来设置  
  2. ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER privilege(s) for this operation  
  3. mysql> set autocommit=0;  
  4. Query OK, 0 rows affected (0.00 sec)  
  5.   
  6. mysql> select @@autocommit;   //查看一下autocommit的设置  
  7. +--------------+  
  8. | @@autocommit |  
  9. +--------------+  
  10. |            0 |  
  11. +--------------+  
  12. 1 row in set (0.00 sec)  

2,我们可以修改mysql的配置文件my.cnf来关闭autocommit

查看复制打印?
  1. [mysqld]  
  2. init_connect='SET autocommit=0'  //在mysqld里面加上这些内容  

用第二种方法关,有一点要注意,连接mysql用户的权限不能大于启动mysql的用户的权限,不然init_connect='SET autocommit=0'根本不会启作用,也不会报任何错误,汗一个先。看以下实例

查看复制打印?
  1. zhangy@ubuntu:~$ mysql -umysql  
  2. Welcome to the MySQL monitor.  Commands end with ; or \g.  
  3. Your MySQL connection id is 1  
  4. Server version: 5.5.2-m2-log Source distribution  
  5.   
  6. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.  
  7.   
  8. mysql> select @@autocommit;     //mysql是启动用户,关闭autocommit成功  
  9. +--------------+  
  10. | @@autocommit |  
  11. +--------------+  
  12. |            0 |  
  13. +--------------+  
  14. 1 row in set (0.00 sec)  
  15.   
  16. mysql> Ctrl-C -- exit!  
  17. Aborted  
  18. zhangy@ubuntu:~$ mysql -uroot  
  19. Welcome to the MySQL monitor.  Commands end with ; or \g.  
  20. Your MySQL connection id is 2  
  21. Server version: 5.5.2-m2-log Source distribution  
  22.   
  23. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.  
  24.   
  25. mysql> select @@autocommit;    //用root财户启动,不成功。  
  26. +--------------+  
  27. | @@autocommit |  
  28. +--------------+  
  29. |            1 |  
  30. +--------------+  
  31. 1 row in set (0.00 sec)  

个会不会是mysql的bug呢?我在网上找了找这方面的问题,还真有。部分内容如下:
If a user has SUPER privilege, init_connect will not execute
(otherwise if init_connect will a wrong query no one can connect to server).

Note, if init_connect is a wrong query, the connection is closing without any errors
and next command will clause 'lost connection' error.

里面有一点说的很清楚If a user has SUPER privilege, init_connect will not execute,如果用户有更高级的权限,init_connect根本不会执行。

 

事务定义:

事务是单个的工作单元。如果某一事务成功,则在该事务中进行的所有数据更改均会

提交,成为数据库中的永久组成部分。如果事务遇到错误且必须取消或回滚,则所有

数据更改均被清除。

事务三种运行模式:
自动提交事务
每条单独的语句都是一个事务。
显式事务
每个事务均以 BEGIN TRANSACTION 语句显式开始,
 COMMIT  ROLLBACK 语句显式结束。
隐性事务
在前一个事务完成时新事务隐式启动,但每个事务仍以 COMMIT  ROLLBACK 语句

显式完成。

事务操作的语法:

BEGIN TRANSACTION
BEGIN DISTRIBUTED TRANSACTION
COMMIT TRANSACTION
COMMIT WORK
ROLLBACK WORK
SAVE TRANSACTION
BEGIN TRANSACTION

BEGIN TRANSACTION
标记一个显式本地事务的起始点。

BEGIN TRANSACTION @@TRANCOUNT  1

BEGIN TRANSACTION 代表一点,由连接引用的数据在该点是逻辑和物理上都一致的。如果遇上错误,在 BEGIN TRANSACTION 之后的所有数据改动都能进行回滚,以将数据返回到已知的一致状态 。每个事务继续执行直到它无误地完成并且用 COMMIT TRANSACTION 对数据库作永久的改动,或者遇上错误并且用 ROLLBACK TRANSACTION 语句擦除所有改动

语法
BEGIN TRAN [ SACTION ] [ transaction_name | @tran_name_variable [ WITH MARK [ 'description' ] ] ]

例子:
BEGIN TRAN T1
UPDATE table1 ...
--nest transaction M2
BEGIN TRAN M2 WITH MARK
UPDATE table2 ...
SELECT * from table1
COMMIT TRAN M2
UPDATE table3 ...
COMMIT TRAN T1

BEGIN DISTRIBUTED TRANSACTION
指定一个由 Microsoft 分布式事务处理协调器 (MS DTC) 管理的 Transact-SQL 分布式事务的起始。

语法
BEGIN DISTRIBUTED TRAN [ SACTION ]
[ transaction_name | @tran_name_variable ]

参数
transaction_name
是用户定义的事务名,用于跟踪 MS DTC 实用工具中的分布式事务。 transaction_name 必须符合标识符规则,但是仅使用头 32 个字符

@tran_name_variable
是用户定义的一个变量名,它含有一个事务名,该事务名用于跟踪 MS DTC 实用工具中的分布式事务。必须用 charvarcharnchar nvarchar 数据类型声明该变量。

注释
执行BEGIN DISTRIBUTED TRANSACTION 语句的服务器是事务创建人,并且控制事务的完成

当连接发出后续 COMMIT TRANSACTION  ROLLBACK TRANSACTION 语句时,
主控服务器请求 MS DTC 在所涉及的服务器间管理分布式事务的完成。
有两个方法可将远程 SQL 服务器登记在一个分布式事务中:

分布式事务中已登记的连接执行一个远程存储过程调用,该调用引用一个远程服务器。 
分布式事务中已登记的连接执行一个分布式查询,该查询引用一个远程服务器。

示例
本例在本地和远程数据库上更新作者的姓。本地和远程数据库将同时提交或同时回滚本事务。

说明 
当前的SQL Server 上必须安装 MS DTC.

USE pubs
GO
BEGIN DISTRIBUTED TRANSACTION
UPDATE authors
SET au_lname = 'McDonald' WHERE au_id = '409-56-7008'
EXECUTE 
link_Server_T.pubs.dbo.changeauth_lname '409-56-7008','McDonald'
COMMIT TRAN
GO
Note:
如果需要连接远程DB,如果是linkServer 方式连接的话,一定要修该linkServer RPC 选项置为 True

SET XACT_ABORT
指定当 Transact-SQL 语句产生运行时错误时,Microsoft? SQL Server? 是否自动回滚当前事务。

可以比较简单的理解,如果中间有任何一句SQL 出错,所有SQL全部回滚.特别适用于 Procedure 中间调用Procedure ,如果第一个Procedure Ok,被调用的Procedure 中间有错误,如果SET XACT_ABORT=false,则出错的部分回滚,其他部分提交,当然外部Procedure 也提交。).

---在分布式Trans中一定要注意设置下面参数(XACT_ABORT)

语法SET XACT_ABORT { ON | OFF }

注释  SET XACT_ABORT  ON 时,如果 Transact-SQL 语句产生运行时错误,整个事务将终止并回滚。为 OFF 时,只回滚产生错误的Transact-SQL 语句,而事务将继续进行处理。编译错误(如语法错误)不受 SET XACT_ABORT 的影响。

对于大多数 OLE DB 提供程序(包括 SQL Server),隐性或显式事务中的数据修改语句必须将 XACT_ABORT 设置为 ON

SET XACT_ABORT 的设置是在执行或运行时设置,而不是在分析时设置。

示例 下例导致在含有其它 Transact-SQL 语句的事务中发生违反外键错误。在第一个语句集中产生错误,但其它语句均成功执行且事务成功
提交。在第二个语句集中,SET XACT_ABORT 设置为 ON。这导致语句错误使批处理终止,并使事务回滚。

CREATE TABLE t1 (a int PRIMARY KEY)
CREATE TABLE t2 (a int REFERENCES t1(a))
GO
INSERT INTO t1 VALUES (1)
INSERT INTO t1 VALUES (3)
INSERT INTO t1 VALUES (4)
INSERT INTO t1 VALUES (6)
GO
SET XACT_ABORT OFF
GO
BEGIN TRAN
INSERT INTO t2 VALUES (1)
INSERT INTO t2 VALUES (2) /* Foreign key error */
INSERT INTO t2 VALUES (3)
COMMIT TRAN
GO

SET XACT_ABORT ON
GO

BEGIN TRAN
INSERT INTO t2 VALUES (4)
INSERT INTO t2 VALUES (5) /* Foreign key error */
INSERT INTO t2 VALUES (6)
COMMIT TRAN
GO

SAVE TRANSACTION
在事务内设置保存点。

语法 SAVE TRAN [ SACTION ] { savepoint_name | @savepoint_variable }
参数 savepoint_name
是指派给保存点的名称。保存点名称必须符合标识符规则,但只使用前 32 个字符。
@savepoint_variable
是用户定义的、含有有效保存点名称的变量的名称。
必须用 charvarcharnchar  nvarchar 数据类型声明该变量。 注释
用户可以在事务内设置保存点或标记。保存点定义如果有条件地取消事务的一部分,事 务可以返回的位置。如果将事务回滚到保存点,则必须(如果需要,使用更多的 Transact-SQL 语句和 COMMIT TRANSACTION 语句)继续完成事务,或者必须(通过将事务回滚到其起始点)完全取消事务。若要取消整个事务,请使用 ROLLBACK TRANSACTION transaction_name 格式。这将撤消事务的所 有语句和过程。

Note:1: 在由 BEGIN DISTRIBUTED TRANSACTION 显式启动或从本地事务升级而来的分布式事务中,不支持 SAVE TRANSACTION

2:当事务开始时,将一直控制事务中所使用的资源直到事务完成(也就是锁定)。当将事务的一部分回滚到保存点时,将继续控制资源直到事务完成(或者回滚全部事务)。

例子:begin transaction
save transaction A
insert into demo values('BB','B term')
rollback TRANSACTION A
create table demo2(name varchar(10),age int)
insert into demo2(name,age) values('lis',1)
commit transaction

ROLLBACK TRANSACTION

将显式事务或隐性事务回滚到事务的起点或事务内的某个保存点。
语法
ROLLBACK [ TRAN [ SACTION ]
[ transaction_name | @tran_name_variable | savepoint_name | @savepoint_variable ] ]

参数
transaction_name
是给 BEGIN TRANSACTION 上的事务指派的名称。transaction_name 必须符合标识符规则,但只使用事务名称的前 32 个字符。嵌套
事务时,transaction_name 必须是来自最远的 BEGIN TRANSACTION 语句的名称。
@tran_name_variable
是用户定义的、含有有效事务名称的变量的名称。必须用 charvarcharnchar  nvarchar 数据类型声明该变量。
savepoint_name
是来自 SAVE TRANSACTION 语句的 savepoint_namesavepoint_name 必须符合标识符规则。当条件回滚只影响事务的一部分时使 savepoint_name
@savepoint_variable
是用户定义的、含有有效保存点名称的变量的名称。必须用 charvarcharnchar  nvarchar 数据类型声明该变量。

注释 ROLLBACK TRANSACTION 清除自事务的起点或到某个保存点所做的所有数据修改。ROLLBACK 还释放由事务控制的资源。
不带 savepoint_name  transaction_name  ROLLBACK TRANSACTION 回滚到事务的起点。嵌套事务时,该语句将所有内层事务回滚到 最远的 BEGIN TRANSACTION 语句。在这两种情况下,ROLLBACK TRANSACTION 均将 @@TRANCOUNT 系统函数减为 0ROLLBACK
TRANSACTION savepoint_name 
不减少 @@TRANCOUNT

Note: 
ROLLBACK TRANSACTION 
语句若指定 savepoint_name 则不释放任何锁。
在由 BEGIN DISTRIBUTED TRANSACTION 显式启动或从本地事务升级而来的分布式事务中,ROLLBACK TRANSACTION 不能
引用savepoint_name在执行 COMMIT TRANSACTION 语句后不能回滚事务

在事务内允许有重复的保存点名称,但 ROLLBACK TRANSACTION 若使用重复的保存点名称,则只回滚到最近的使用该保存点名称的SAVE TRANSACTION

在存储过程中,不带 savepoint_name  transaction_name  ROLLBACK TRANSACTION 语句将所有语句回滚到最远的BEGINTRANSACTION。在存储过程中,ROLLBACK TRANSACTION 语句使 @@TRANCOUNT 在触发器完成时的值不同于调用该存储过程时的@@TRANCOUNT 值,并且生成一个信息。该信息不影响后面的处理。

如果在触发器中发出 ROLLBACK TRANSACTION:将回滚对当前事务中的那一点所做的所有数据修改,包括触发器所做的修改。 
触发器继续执行 ROLLBACK 语句之后的所有其余语句。如果这些语句中的任意语句修改数据,则不回滚这些修改。执行其余的语句不会激发嵌套触发器。在批处理中,不执行所有位于激发触发器的语句之后的语句。每次进入触发器,@@TRANCOUNT 就增加 1,即使在自动提交模式下也是如此。(系统将触发器视作隐性嵌套事务。)

在存储过程中,ROLLBACK TRANSACTION 语句不影响调用该过程的批处理中的后续语句;
将执行批处理中的后续语句。在触发器中,ROLLBACK TRANSACTION 语句终止含有激发触发器的语句的批处理;
不执行批处理中的后续语句。

ROLLBACK TRANSACTION 语句不生成显示给用户的信息。如果在存储过程或触发器中需要警告,请使用 RAISERROR 或 PRINT 语句。RAISERROR 是用于指出错误的首选语句。

ROLLBACK 对游标的影响由下面三个规则定义: 
当 CURSOR_CLOSE_ON_COMMIT 设置为 ON 时,ROLLBACK 关闭但不释放所有打开的游标。 
当 CURSOR_CLOSE_ON_COMMIT 设置为 OFF 时,ROLLBACK 不影响任何打开的同步 STATIC 或 INSENSITIVE 游标不影响已完全填充的异步 STATIC 游标。将关闭但不释放任何其它类型的打开的游标。 
对于导致终止批处理并生成内部回滚的错误,将释放在含有该错误语句的批处理内声明的所有游标。
不论游标的类型或 CURSOR_CLOSE_ON_COMMIT 的设置,所有游标均将被释放,其中包括在该错误批处理所调用的存储过程内声明的游标。在该错误批处理之前的批处理内声明的游标以规则 1 和 2 为准。死锁错误就属于这类错误。在触发器中发出的 ROLLBACK 语句也 自动生成这类错误。

权限
ROLLBACK TRANSACTION 权限默认授予任何有效用户。
例子:

begin transaction
save transaction A
insert into demo values('BB','B term')
rollback TRANSACTION A

-- select * into demo2 from demo1

create table demo2(name varchar(10),age int)
insert into demo2(name,age) values('lis',1)
rollback transaction

COMMIT TRANSACTION
标志一个成功的隐性事务或用户定义事务的结束。如果 @@TRANCOUNT  1COMMIT

TRANSACTION 使得自从事务开始以来所执行的 所有数据修改成为数据库的永久部分,释放连接

占用的资源,并将 @@TRANCOUNT 减少到 0。如果@@TRANCOUNT 大于 1,则COMMIT

TRANSACTION 使 @@TRANCOUNT  1 递减。

只有当事务所引用的所有数据的逻辑都正确时,发出 COMMIT TRANSACTION 命令。
COMMIT WORK
标志事务的结束。
语法
COMMIT [ WORK ]

注释
此语句的功能与 COMMIT TRANSACTION 相同,但 COMMIT TRANSACTION 接受用户定义的事务

名称。这个指定或没有指定可选关键字WORK  COMMIT 语法与 SQL-92 兼容

例子
begin transaction a
insert into demo values('BB','B term')
commit TRANSACTION A

隐性事务
当连接以隐性事务模式进行操作时,SQL Server将在提交或回滚当前事务后自动启动新事务。无须描述事务的开始,只需提交或

回滚每个事务。隐性事务模式生成连续的事务链。

在为连接将隐性事务模式设置为打开之后,当 SQL Server 首次执行下列任何语句时,都会自动启动一个事务:

 

ALTER TABLE

INSERT

 

CREATE

OPEN

 

DELETE

REVOKE

 

DROP

SELECT

 

FETCH

TRUNCATE TABLE

 

GRANT

UPDATE

在发出 COMMIT  ROLLBACK 语句之前,该事务将一直保持有效。在第一个事务被提交或回滚之后,下次当连接执行这些语句

中的任何语句时,SQL Server 都将自动启动一个新事务。SQL Server 将不断地生成一个隐性事务链,

直到隐性事务模式关闭为止

例子:
begin transaction 
save transaction A

insert into demo values('BB','B term')
rollback TRANSACTION A

create table demo2(name varchar(10),age int)
insert into demo2(name,age) values('lis',1)
rollback transaction
-- 
 Create table demo2  SQL Server 已经隐式创建一个Trans,知道提交或回滚

嵌套事务处理:

1 Trans 嵌套,将内部的trans 合并到外部并形成一个Trans.

begin tran t1

----In the first trans .
Insert into demo2(name,age) values('lis',1)

---Second Trans begin transaction t2 
insert into demo values('BB','B term')
commit transaction t2

----In the first trans .
Insert into demo2(name,age) values('lis',2)
rollback transaction t1

Note:

在一系列嵌套的事务中用一个事务名给多个事务命名对该事务没有什么影响。系统仅登记第一个(最外部的)事务名。回滚

到其它任何名字(有效的保存点名除外)都会产生错误

事实上,任何在回滚之前执行的语句都没有在错误发生时回滚。这语句仅当外层的事务回滚时才会进行回滚。

例:内部事务回滚SQL server 报错。

begin tran t1 
Insert into demo2(name,age) values('lis',1)
---Second Trans

--Server: Msg 6401, Level 16, State 1, Line 6
---Cannot roll back t2. No transaction or savepoint of that name was found.
begin transaction t2 
insert into demo values('BB','B term')
rollback transaction t2

----In the first trans .
Insert into demo2(name,age) values('lis',2)
commit transaction t1

例: 内部事务提交SQL server 不会报错。

begin tran t1 
Insert into demo2(name,age) values('lis',1)
---Second Trans no error
begin transaction t2 
insert into demo values('BB','B term')
commit transaction t2

----In the first trans .
Insert into demo2(name,age) values('lis',2)
commit transaction t1

SQL Server 的隔离级别:

1: 设置TimeOut 参数

Set Lock_TimeOut 5000

被锁超时5秒将自动解锁

Set Lock_TimeOut 0

产立即解锁,返回Error 默认为-1,无限等待

2

(SET TRANSACTION ISOLATION LEVEL
{ READ COMMITTED
| READ UNCOMMITTED
| REPEATABLE READ | SERIALIZABLE
}

READ COMMITTED

指定在读取数据时控制共享锁以避免脏读,但数据可在事务结束前更改,从而产生不可重复读取或

幻像数据。该选项是SQL Server 的默认值。

避免脏读,并在其他session 在事务中不能对已有数据进行修改。共享锁。

READ UNCOMMITTED

执行脏读或 0 级隔离锁定,这表示不发出共享锁,也不接受排它锁。当设置该选项时,可以对数

据执行未提交读或脏读;在事务结束前可以更改数据内的数值,行也可以出现在数据集中或从数据

集消失。该选项的作用与在事务内所有语句中的所有表上设置 NOLOCK 相同。这是四个隔离级别中

限制最小的级别。

REPEATABLE READ

锁定查询中使用的所有数据以防止其他用户更新数据,但是其他用户可以将新的幻像行插入数据

集,且幻像行包括在当前事务的后续读取中。因为并发低于默认隔离级别,所以应只在必要时才使

用该选项。

SERIALIZABLE

在数据集上放置一个范围锁,以防止其他用户在事务完成之前更新数据集或将行插入数据集内。这

是四个隔离级别中限制最大的级别。因为并发级别较低,所以应只在必要时才使用该选项。该选项

的作用与在事务内所有 SELECT 语句中的所有表上设置 HOLDLOCK 相同。



mysql禁用autocommit,以及遇到的问题

张映 发表于 2011-03-15

分类目录: mysql

mysql的autocommit(自动提交)默认是开启,其对mysql的性能有一定影响,举个例子来说,如果你插入了1000条数据,mysql会commit1000次的,如果我们把autocommit关闭掉,通过程序来控制,只要一次commit就可以了。

1,我们可以通过set来设置autocommit

查看复制打印?
  1. mysql> set global init_connect="set autocommit=0";  //提示你用权限更高的财户来设置  
  2. ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER privilege(s) for this operation  
  3. mysql> set autocommit=0;  
  4. Query OK, 0 rows affected (0.00 sec)  
  5.   
  6. mysql> select @@autocommit;   //查看一下autocommit的设置  
  7. +--------------+  
  8. | @@autocommit |  
  9. +--------------+  
  10. |            0 |  
  11. +--------------+  
  12. 1 row in set (0.00 sec)  

2,我们可以修改mysql的配置文件my.cnf来关闭autocommit

查看复制打印?
  1. [mysqld]  
  2. init_connect='SET autocommit=0'  //在mysqld里面加上这些内容  

用第二种方法关,有一点要注意,连接mysql用户的权限不能大于启动mysql的用户的权限,不然init_connect='SET autocommit=0'根本不会启作用,也不会报任何错误,汗一个先。看以下实例

查看复制打印?
  1. zhangy@ubuntu:~$ mysql -umysql  
  2. Welcome to the MySQL monitor.  Commands end with ; or \g.  
  3. Your MySQL connection id is 1  
  4. Server version: 5.5.2-m2-log Source distribution  
  5.   
  6. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.  
  7.   
  8. mysql> select @@autocommit;     //mysql是启动用户,关闭autocommit成功  
  9. +--------------+  
  10. | @@autocommit |  
  11. +--------------+  
  12. |            0 |  
  13. +--------------+  
  14. 1 row in set (0.00 sec)  
  15.   
  16. mysql> Ctrl-C -- exit!  
  17. Aborted  
  18. zhangy@ubuntu:~$ mysql -uroot  
  19. Welcome to the MySQL monitor.  Commands end with ; or \g.  
  20. Your MySQL connection id is 2  
  21. Server version: 5.5.2-m2-log Source distribution  
  22.   
  23. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.  
  24.   
  25. mysql> select @@autocommit;    //用root财户启动,不成功。  
  26. +--------------+  
  27. | @@autocommit |  
  28. +--------------+  
  29. |            1 |  
  30. +--------------+  
  31. 1 row in set (0.00 sec)  

这个会不会是mysql的bug呢?我在网上找了找这方面的问题,还真有。部分内容如下:
If a user has SUPER privilege, init_connect will not execute
(otherwise if init_connect will a wrong query no one can connect to server).

Note, if init_connect is a wrong query, the connection is closing without any errors
and next command will clause 'lost connection' error.

里面有一点说的很清楚If a user has SUPER privilege, init_connect will not execute,如果用户有更高级的权限,init_connect根本不会执行。




 3SET QUOTED_IDENTIFIER ON    

 4sql事务处理 - ManJuSaka - ManJuSaka 4GO   
 5sql事务处理 - ManJuSaka - ManJuSaka 5SET ANSI_NULLS ON    
 6sql事务处理 - ManJuSaka - ManJuSaka 6GO   
 7sql事务处理 - ManJuSaka - ManJuSaka 7  
 8sql事务处理 - ManJuSaka - ManJuSaka 8ALTER    procedure myInsertTest   
 9sql事务处理 - ManJuSaka - ManJuSaka 9  
10sql事务处理 - ManJuSaka - ManJuSaka10@job_desc varchar(50),   
11sql事务处理 - ManJuSaka - ManJuSaka11@min_lvl tinyint,   
12sql事务处理 - ManJuSaka - ManJuSaka12@max_lvl tinyint,   
13sql事务处理 - ManJuSaka - ManJuSaka13@id int,   
14sql事务处理 - ManJuSaka - ManJuSaka14@name varchar(40)   
15sql事务处理 - ManJuSaka - ManJuSaka15  
16sql事务处理 - ManJuSaka - ManJuSaka16as  
17sql事务处理 - ManJuSaka - ManJuSaka17    
18sql事务处理 - ManJuSaka - ManJuSaka18 begin tran   
19sql事务处理 - ManJuSaka - ManJuSaka19  
20sql事务处理 - ManJuSaka - ManJuSaka20--第一张表的插入语句    
21sql事务处理 - ManJuSaka - ManJuSaka21INSERT INTO dbo.jobs  (job_desc, min_lvl,max_lvl)      VALUES(@job_desc,@min_lvl,@max_lvl)     
22sql事务处理 - ManJuSaka - ManJuSaka22  
23sql事务处理 - ManJuSaka - ManJuSaka23 --第二张表的插入语句     
24sql事务处理 - ManJuSaka - ManJuSaka24 INSERT INTO test (id,name)  values@id,@name)   
25sql事务处理 - ManJuSaka - ManJuSaka25    
26sql事务处理 - ManJuSaka - ManJuSaka26--如果有一张表插入失败就回滚   
27sql事务处理 - ManJuSaka - ManJuSaka27 IF @@ERROR <> 0     
28sql事务处理 - ManJuSaka - ManJuSaka28     BEGIN    
29sql事务处理 - ManJuSaka - ManJuSaka29      ROLLBACK  TRAN      
30sql事务处理 - ManJuSaka - ManJuSaka30         
31sql事务处理 - ManJuSaka - ManJuSaka31      RETURN  0   
32sql事务处理 - ManJuSaka - ManJuSaka32     END    
33sql事务处理 - ManJuSaka - ManJuSaka33    
34sql事务处理 - ManJuSaka - ManJuSaka34 else     
35sql事务处理 - ManJuSaka - ManJuSaka35     BEGIN    
36sql事务处理 - ManJuSaka - ManJuSaka36      COMMIT TRANSACTION  
37sql事务处理 - ManJuSaka - ManJuSaka37      RETURN 1   
38sql事务处理 - ManJuSaka - ManJuSaka38     END    
39sql事务处理 - ManJuSaka - ManJuSaka39  
40sql事务处理 - ManJuSaka - ManJuSaka40  
41sql事务处理 - ManJuSaka - ManJuSaka41GO   
42sql事务处理 - ManJuSaka - ManJuSaka42SET QUOTED_IDENTIFIER OFF    
43sql事务处理 - ManJuSaka - ManJuSaka43GO   
44sql事务处理 - ManJuSaka - ManJuSaka44SET ANSI_NULLS ON    
45sql事务处理 - ManJuSaka - ManJuSaka45GO  
46sql事务处理 - ManJuSaka - ManJuSaka46

BEGIN TRANSACTION--开始事务

DECLARE @errorSun INT --定义错误计数器
SET @errorSun=0 --没错为0

UPDATE a SET id=232 WHERE a=1 --事务操作SQL语句
SET @errorSun=@errorSun+@@ERROR --累计是否有错

UPDATE aa SET id=2 WHERE a=1 --事务操作SQL语句
SET @errorSun=@errorSun+@@ERROR --累计是否有错

IF @errorSun<>0
BEGIN
PRINT '有错误,回滚'
ROLLBACK TRANSACTION--事务回滚语句
END
ELSE
BEGIN
PRINT '成功,提交'
COMMIT TRANSACTION--事务提交语句
END

1.什么是事务事务是一个不可分割的工作逻辑单元,在数据库系统上执行并发操作时事务是做为最小的控制单元来使用的。他包含的所有数据库操作命令作为一个整体一起向系提交或撤消,这一组数据库操作命令要么都执行,要么都不执行。
2.事务的语句
 
开始事物:BEGIN TRANSACTION
 提交事物:COMMIT TRANSACTION
 回滚事务:ROLLBACK TRANSACTION
3.事务的4个属性
     ①原子性(Atomicity):
事务中的所有元素作为一个整体提交或回滚,事务的个元素是不可分的,事务是一个完整操作。
  ②一致性(Consistemcy):事物完成时,数据必须是一致的,也就是说,和事物开始之前,数据存储中的数据处于一致状态。保证数据的无损。
  ③隔离性(Isolation):对数据进行修改的多个事务是彼此隔离的。这表明事务必须是独立的,不应该以任何方式以来于或影响其他事务。
  ④持久性(Durability):事务完成之后,它对于系统的影响是永久的,该修改即使出现系统故障也将一直保留,真实的修改了数据库
4.事务的保存点
     SAVE TRANSACTION 保存点名称 --自定义保存点的名称和位置
     ROLLBACK TRANSACTION 保存点名称 
--回滚到自定义的保存点

 

 

                                                  二事例

所谓事务是指一组逻辑操作单元,它使数据从一种状态变换到另一种状态。
包括四个特性:
1、原子性              就是事务应作为一个工作单元,事务处理完成,所有的工作要么都在数据库中保存下来,要么完全回滚,全部不保留
2、一致性             事务完成或者撤销后,都应该处于一致的状态
3、隔离性             多个事务同时进行,它们之间应该互不干扰.应该防止一个事务处理其他事务也要修改的数据时, 
不合理的存取和不完整的读取数据  
4、持久性             事务提交以后,所做的工作就被永久的保存下来

示例:创建一个存储过程,向两个表中同时插入数据
Create proc RegisterUser 
(@usrName varchar(30), @usrPasswd varchar(30),@age int,@sex varchar(10), @PhoneNum varchar(20), @Address varchar(50) ) 
as begin 
begin tran 
insert into userinfo(userName,userPasswd) values(@usrName,@usrPasswd) 
if @@error<>0 
begin

rollback tran

return -1 
end 
insert into userdoc(userName,age,sex,PhoneNumber,Address)values(@Usrname,@age,@sex,@PhoneNum,@Address) 
if @@error<>0 
begin

rollback tran 
return -1  
end

commit tran 
return 0 
end 

事务的分类
按事务的启动与执行方式,可以将事务分为3类:
显示事务  
也称之为用户定义或用户指定的事务,即可以显式地定义启动和结束的事务。分布式事务属于显示事务
自动提交事务
默认事务管理模式。如果一个语句成功地完成,则提交该语句;如果遇到错误,则回滚该语句。
隐性事务
当连接以此模式进行操作时,sql将在提交或回滚当前事务后自动启动新事务。无须描述事务的开始,只需提交或回滚每个事务。它生成连续的事务链。

一、显示事务
通过begin transacton、commit transaction、commit work、rollback transaction或rollback work等语句完成。
1、启动事务
格式:begin tran 事务名或变量 with mark 描述
2、结束事务
格式:commit tran 事务名或变量 (事务名与begin tran中的事务名一致
或commit work 但此没有参数
3、回滚事务
rollback tran 事务名或变量 | savepoint_name | savepoint_variable  
或rollback work
说明:清除自事务的起点或到某个保存点所做的所有数据修改
4、在事务内设置保存点
格式:save tran savepoint_name | savepoint_variable  
示例:
use bookdb
go
begin tran mytran
insert into book
values(9,"windows2000',1,22,'出版社')
save tran mysave
delete book where book_id=9
rollback tran mysave
commit tran
go
select * from book
go
可以知道,上面的语句执行后,在book中插入了一笔记录,而并没有删除。因为使用rollback tran mysave 语句将操作回滚到了删除前的保存点处。
5、标记事务
格式:with mark
例:使用数据库标记将日志恢复到预定义时间点的语句 
在事务日志中置入一个标记。请注意,被标记的事务至少须提交一个更新,以标记该日志。 

BEGIN TRAN MyMark WITH MARK 
UPDATE pubs.dbo.LastLogMark SET MarkTime = GETDATE() 
COMMIT TRAN MyMark 

按照您常用的方法备份事务日志。 

BACKUP LOG pubs TO DISK='C:\Backups\Fullbackup.bak' WITH INIT 

现在您可以将数据库恢复至日志标记点。首先恢复数据库,并使其为接受日志恢复做好准备。 

RESTORE DATABASE pubs FROM DISK=N'C:\Backups\Fullbackup.bak' WITH NORECOVERY 

现在将日志恢复至包含该标记的时间点,并使其可供使用。请注意,STOPAT在数据库正在执行大容量日志时禁止执行。 

RESTORE LOG pubs FROM DISK=N'C:\Backups\Logbackup.bak' WITH RECOVERY, 
STOPAT='02/11/2002 17:35:00'

5、不能用于事务的操作
创建数据库 create database
修改数据库 alter database
删除数据库 drop database
恢复数据库 restore database
加载数据库 load database
备份日志文件 backup log
恢复日志文件 restore log
更新统计数据 update statitics
授权操作              grant
复制事务日志 dump tran
磁盘初始化           disk init
更新使用sp_configure后的系统配置           reconfigure

二、自动提交事务
sql连接在begin tran 语句启动显式事务,或隐性事务模式设置为打开之前,将以自动提交模式进行操作。当提交或回滚显式事务,或者关闭隐性事务模式时,将返回到自动提交模式。
示例:
由于编译错误,使得三个insert都没执行
use test
go
create table testback(cola int primary key ,colb char(3))
go
insert into testback values(1,'aaa')
insert into testback values(2,'bbb')
insert into testback value(3,'ccc') /*符号错误*/
go 
select * from testback
go
没有任何结果返回

三、隐式事务
通过 API 函数或 Transact-SQL SET IMPLICIT_TRANSACTIONS ON 语句,将隐性事务模式设置为打开。下一个语句自动启动一个新事务。当该事务完成时,再下一个 Transact-SQL 语句又将启动一个新事务。
当有大量的DDL 和DML命令执行时会自动开始,并一直保持到用户明确提交为止,切换隐式事务可以用SET IMPLICIT_TRANSACTIONS 
为连接设置隐性事务模式.当设置为 ON 时,SET IMPLICIT_TRANSACTIONS 将连接设置为隐性事务模式。当设置为 OFF 时,则使连接返回到自动提交事务模式 
语句包括:
alter table          insert           open          create             delete            revoke          drop
select                fetch            truncate table                grant             update
示例:
下面使用显式与隐式事务。它使用@@tracount函数演示打开的事务与关闭的事务:
use test 
go
set nocount on
create table t1(a int)
go 
insert into t1 values(1)
go 

print '使用显式事务'
begin tran
insert into t1 values(2)
print '事务外的事务数目:'+cast(@@trancount as char(5))
commint tran
print '事务外的事务数目:'+cast(@@trancount as char(5))
go

print 
go
set implicit_transactions on
go

print '使用隐式事务'
go
insert into t1 values*4)
print'事务内的事务数目:'+cast(@@trancount as char(5))
commint tran
print'事务外的事务数目:'+cast(@@trancount as char(5))
go
执行结果:
使用显示事务
事务内的事务数目:2
事务外的事务数目:1
使用隐式事务
事务内的事务数目:1
事务外的事务数目:0

四、分布式事务
跨越两个或多个数据库的单个sql server中的事务就是分布式事务。
与本地事务区别:必须由事务管理器管理,以尽量避免出现因网络故障而导致一个事务由某些资源管理器成功提交,但由另一些资源管理器回滚的情况。

sql server 可以由DTc microsoft distributed transaction coordinator 来支持处理分布式事务,可以使用 BEgin distributed transaction 命令启动一个分布式事务处理 


分二阶段:
A 准备阶段
B 提交阶段

执行教程:
1、sql 脚本或应用程序连接执行启动分布式事务的sql语句
2、执行该语句的sql在为事务中的主控服务器
3、脚本或应用程序对链接的服务器执行分布式查询,或对远程服务器执行远程存储过程。
4、当执行了分布式查询或远程过程调用后,主控服务器将自动调用msdtc以便登记分布式事务中链接的服务器和远程服务器
5、当脚本或应用程序发出commit或rollback语句时,主控sql将调用msdtc管理两阶段提交过程,或者通知链接的服务器和远程服务器回滚其事务。

 

转载自:http://lhsblog01.blog.163.com/blog/static/102004519200811301349181/

更多0


SQL脚本 


从功能上划分,SQL语言可以分为DDL,DML和DCL三大类。

    1. DDL(Data Definition Language) 
    数据定义语言,用于定义和管理 SQL 数据库中的所有对象的语言 ;
    CREATE---创建表
    ALTER---修改表
    DROP---删除表

    2. DML(Data Manipulation Language) 
    数据操纵语言,SQL中处理数据等操作统称为数据操纵语言 ; 
    INSERT---数据的插入
    DELETE---数据的删除
    UPDATE---数据的修改
    SELECT---数据的查询

    DCL(Data Control Language) 
    数据控制语言,用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等;
    GRANT---授权。
    ROLLBACK---回滚
    COMMIT---提交。

     提交数据有三种类型:显式提交、隐式提交及自动提交。下面分别说明这三种类型。

    (1) 显式提交

    用COMMIT命令直接完成的提交为显式提交。

    (2) 隐式提交

    用SQL命令间接完成的提交为隐式提交。这些命令是:

    ALTER,AUDIT,COMMENT,CONNECT,CREATE,DISCONNECT,DROP,

EXIT,GRANT,NOAUDIT,QUIT,REVOKE,RENAME。

    (3) 自动提交

    若把AUTOCOMMIT设置为ON,则在插入、修改、删除语句执行后,

系统将自动进行提交,这就是自动提交。其格式为: SQL>SET AUTOCOMMIT ON; 

    COMMIT / ROLLBACK这两个命令用的时候要小心。 COMMIT / ROLLBACK 都是用在执行 DML语句(INSERT / DELETE / UPDATE / SELECT )之后的。DML 语句,执行完之后,处理的数据,都会放在回滚段中(除了 SELECT 语句),等待用户进行提交(COMMIT)或者回滚 (ROLLBACK),当用户执行 COMMIT / ROLLBACK后,放在回滚段中的数据就会被删除。

    (SELECT 语句执行后,数据都存在共享池。提供给其他人查询相同的数据时,直接在共享池中提取,不用再去数据库中提取,提高了数据查询的速度。)

    所有的 DML 语句都是要显式提交的,也就是说要在执行完DML语句之后,执行 COMMIT 。而其他的诸如 DDL 语句的,都是隐式提交的。也就是说,在运行那些非 DML 语句后,数据库已经进行了隐式提交,例如 CREATE TABLE,在运行脚本后,表已经建好了,并不在需要你再进行显式提交。




mysql禁用autocommit,以及遇到的问题


mysql的autocommit(自动提交)默认是开启,其对mysql的性能有一定影响,举个例子来说,如果你插入了1000条数据,mysql会commit1000次的,如果我们把autocommit关闭掉,通过程序来控制,只要一次commit就可以了。

1,我们可以通过set来设置autocommit

查看复制打印?
  1. mysql> set global init_connect="set autocommit=0";  //提示你用权限更高的财户来设置  
  2. ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER privilege(s) for this operation  
  3. mysql> set autocommit=0;  
  4. Query OK, 0 rows affected (0.00 sec)  
  5.   
  6. mysql> select @@autocommit;   //查看一下autocommit的设置  
  7. +--------------+  
  8. | @@autocommit |  
  9. +--------------+  
  10. |            0 |  
  11. +--------------+  
  12. 1 row in set (0.00 sec)  

2,我们可以修改mysql的配置文件my.cnf来关闭autocommit

查看复制打印?
  1. [mysqld]  
  2. init_connect='SET autocommit=0'  //在mysqld里面加上这些内容  

用第二种方法关,有一点要注意,连接mysql用户的权限不能大于启动mysql的用户的权限,不然init_connect='SET autocommit=0'根本不会启作用,也不会报任何错误,汗一个先。看以下实例

查看复制打印?
  1. zhangy@ubuntu:~$ mysql -umysql  
  2. Welcome to the MySQL monitor.  Commands end with ; or \g.  
  3. Your MySQL connection id is 1  
  4. Server version: 5.5.2-m2-log Source distribution  
  5.   
  6. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.  
  7.   
  8. mysql> select @@autocommit;     //mysql是启动用户,关闭autocommit成功  
  9. +--------------+  
  10. | @@autocommit |  
  11. +--------------+  
  12. |            0 |  
  13. +--------------+  
  14. 1 row in set (0.00 sec)  
  15.   
  16. mysql> Ctrl-C -- exit!  
  17. Aborted  
  18. zhangy@ubuntu:~$ mysql -uroot  
  19. Welcome to the MySQL monitor.  Commands end with ; or \g.  
  20. Your MySQL connection id is 2  
  21. Server version: 5.5.2-m2-log Source distribution  
  22.   
  23. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.  
  24.   
  25. mysql> select @@autocommit;    //用root财户启动,不成功。  
  26. +--------------+  
  27. | @@autocommit |  
  28. +--------------+  
  29. |            1 |  
  30. +--------------+  
  31. 1 row in set (0.00 sec)  

这个会不会是mysql的bug呢?我在网上找了找这方面的问题,还真有。部分内容如下:
If a user has SUPER privilege, init_connect will not execute
(otherwise if init_connect will a wrong query no one can connect to server).

Note, if init_connect is a wrong query, the connection is closing without any errors
and next command will clause 'lost connection' error.

里面有一点说的很清楚If a user has SUPER privilege, init_connect will not execute,如果用户有更高级的权限,init_connect根本不会执行。




0 0
原创粉丝点击