关于事务的简单介绍

 

一、概述

1、什么是事务?
事务(Transation),是一个“最小”的“不可再分”的工作单元。 通常一个事务对应一个完整的业务,例如:一个银行的账户转账业务就是一个最小的工作单元。而一个完整的业务需要一个批量的DML语句共同联合完成。

事务只和DML语句有关系,或者说DML语句才有事务。以上所描述的“批量的DML语句”共有多少条DML语句,和业务逻辑有关系。业务逻辑不同DML语句的个数不同。


2、关于银行账户转账操作,账户转账是一个完整的业务,最小的单元,不可再分。也就是说银行账户转账是一个事务。

t_act 账户表

actno balance
-------------------------------
act-001 30000.0
act-002 10000.0

执行转账操作(10000):
update t_act set balance=20000.0 where actno='act-001';
update t_act set balance=20000.0 where actno='act-002';


以上的两条DML语句要求必须同时成功或者同时失败,最小单元,不可再分。当第一条DML语句执行成功之后,并不能将底层数据库中第一个账户的数据修改,只是将操作记录了一下,这个记录是在内存中完成的,当第二条DML语句执行成功之后,和底层数据库文件中的数据完成同步。若第二条DML语句执行失败,清空所有历史操作记录。

要完成以上的功能,必须借助事务。事务只和数据文件有关系。


3、事务的四个特性:
  原子性(A)
* 事务是最小的工作单元,不可再分。

一致性(C)
* 事务要求所有的DML语句操作的时候,必须保证同时成功或者同时失败。

隔离性(I)

* 事务A和事务B之间具有隔离性。

 持久性(D)
* 是事务的保证,事务终结的标志。【内存中的数据持久到硬盘文件中】


 4、关于事务的术语

- -开启事务:start Transaction

- -事务结束:End Transaction

- -提交事务:Commit Transaction

-- 回滚事务:Rollback Transaction


 5、和事务有关的两条重要的SQL语句【TCL】

commit:提交  rollback:回滚  savepoint :保存点
 


6、事务开启和结束的标志

- 开启的标志:
任何一条DML语句(insert update delete)执行,标志事务的开始。

- 结束的标志:
提交或回滚
提交:成功的结束,将所有的DML语句操作历史记录和底层硬盘文件中的数据来一次同步。
回滚:失败的结束,将所有的DML语句操作历史记录全部清空。
 


 7、重点:
在事务进行过程中,未结束之前,DML语句是不会更改底层数据库文件中的数据。只是将历史操作记录一下,在内存中完成记录。只有在事务结束的时候,而且是成功的结束的时候才会修改底层硬盘中文件中的数据。


二、事务的提交和回滚演示


1、在MYSQL数据库管理系统中,事务的提交和回滚演示

在MYSQL数据库管理系统中,默认情况下,事务是自动提交的,也就是说,只要执行一条DML语句,开启了事务,并且提交了事务。

这种自动提交机制是可以关闭的:【以下关闭自动提交,方式之一】

start transaction; -- 手动开启事务
DML语句 ...
DML语句 ...
DML语句 ...
DML语句 ...
DML语句 ...
DML语句 ...
commit; -- 手动提交事务【事务成功的结束】

start transaction; -- 手动开启事务
DML语句 ...
DML语句 ...
DML语句 ...
DML语句 ...
DML语句 ...
DML语句 ...
rollback; -- 手动回滚事务【事务失败的结束】

- 关闭自动提交的第二种方式:
set autocommit = off;
或者
set session autocommit = off;

- 打开自动提交:
set autocommit = on;
或者
set session autocommit = on;
注:以上操作只对当前会话有效。

---------------------------------------------------------------------------------------------------

操作演示:

set autocommit=off;
mysql> show variables like '%commit%';


 2、事物的四个特性之一:隔离性(isolation)

 事物A和事务B之间具有一定的隔离性,隔离性有隔离级别(4个):

- read uncommitted 读未提交
- read committed 读已提交
- repeatable read 可重复提交
- serializeble 串行化

2.1 read uncommitted 读未提交

事务A和事务B,事务A未提交的数据,事务B可以读取到。这里读取到的数据叫做’脏数据‘或者叫做’Dirty Read‘。这种隔离级别是最低级别的,这种级别一般都是在理论上存在的,数据库默认的隔离级别。一般都是高于该隔离级别的。

2.2 read committed 读已提交

事务A和事务B,事务A提交的数据,事务B才能读取到。这种隔离级别高于上面的读未提交。换句话说:对事务提交之后的数据,当前事务才能读取到。这种隔离级别可以避免脏数据。这种隔离级别会导致:“不可重复读取”,Oracle数据库管理系统默认的隔离级别就是读已提交。


2.3 repeatable read 可重复读

事务A和事务B,事务A提交之后的数据,事务B读取不到。事务B是可重复读取数据的。 这种隔离级别高于读已提交。换句话说:对方提交之后的数据我还是读取不到。这种隔离级别可以避免“脏读和不可重复读取”,达到可重复读取。MYSQL数据库管理系统默认的隔离级别就是 可重复读虽然可以达到“可重复读”的效果,但是会导致:”幻象读“。


2.4  serializeble 串行化

事务A和事务B,事务A在操作数据库表中数据的时候,事务B只能排队等待。这种事务隔离级别一般很少使用,吞吐量太低。用户体验不好。这种隔离级别可以避免“幻象读”,每一次读取的都是数据库表中的真实记录。事务A和事务B是串行执行,不再并发。最高的隔离级别。

隔离级别一致性问题的关系:

隔离级别   脏读取   不可重复读   幻象读。

---------------------------------------------------------------------------
读未提交   可能      可能     可能
读已提交   不可能     可能     可能
可重复读   不可能    不可能    对InnoDB不可能
串行化    不可能       不可能     不可能
----------------------------------------------------------------------------

3、设置事务的隔离级别

3.1 第一种方式:

修改my.ini配置文件,可选值:

- READ-UNCOMMITTED
- READ-COMMITTED
- REPEATABLE-READ
- SERIALIZABLE

具体操作:

-----------------my.ini---------------------------------
[mysql]
transaction-isolution = READ-COMMITTED
-----------------my.ini---------------------------------

3.2  第二种方式:

使用命令方式,设置事务的隔离级别。可选值:

- READ-UNCOMMITTED
- READ-COMMITTED
- REPEATABLE-READ
- SERIALIZABLE

命令格式:
set [无/session/global] transaction isolution level<isolution-level>;
<isolution-level>的可选值:
- READ-UNCOMMITTED
- READ-COMMITTED
- REPEATABLE-READ
- SERIALIZABLE

3.3  事务的作用范围设置

-设置事务的隔离级别作用于全局:
set global transaction isolution level<level>;

-设置事务的隔离级别作用于当前会话:
set transaction isolution level<level>;
或者
set session transaction isolution level<level>;

3.4 查看隔离级别

-查看当前会话事务的隔离级别:
select @@tx_isolation;
select @@seeeion.tx_isolation;

-查看全局的事物隔离级别:
select @@global.tx_isolation;



4、并发事务与隔离级别示例:

4.1 读未提交 read uncommitted

会话1 会话2
-------------------------------------------------------------------------------
set global transaction isolation level read uncommitted;
退出DOS窗口
use bjpowernode;
use bjpowernode;
start transaction;
start transaction;
insert into t_user(name) values('king');
select * from t_user;

4.2 读已提交 read committed

会话1 会话2
-------------------------------------------------------------------------------
set global transaction isolation level read uncommitted;
退出DOS窗口
use bjpowernode;
use bjpowernode;
start transaction;
start transaction;
insert into t_user(name) values('ford');
select * from t_user;
commit;
select * from t_user;

4.3 可重复读 repeatable read

会话1 会话2
-------------------------------------------------------------------------------
set global transaction isolation level repeatable read;
退出DOS窗口
mysql> select @@tx_isolation;
+-----------------------------+
| @@tx_isolation     |
+-----------------------------+
| REPEATABLE-READ |
+-----------------------------+
................................................................................
use bjpowernode;
use bjpowernode;
start transaction;
start transaction;
select * from t_user;
select * from t_user;
insert into t_user(name) values('luzhishen');
commit;
select * from t_user;
-------------------------------------------------------------------------------------------

4.4  串行化 

由于隔离级别太高,一般不用。
     
  
 

猜你喜欢

转载自www.cnblogs.com/feizhao/p/9427966.html