理解事务和事务隔离实验

本文详细介绍了数据库事务的概念、转账示例、事务分类(隐式和显式)、在MySQL中的使用方法、事务特性(原子性、一致性、隔离性、持久性)以及并发问题(脏读、不可重复读、幻读)及其解决方案,包括设置不同的隔离级别。
摘要由CSDN通过智能技术生成

1.什么是是事务?

        1.1.概念:了解什么是事务

                事务是数据库提供的一个特性。     

                事务:组成各个数据的执行的单元,要么都成功,要么都不成功。

        1.2.转账例子

                转账的功能,冠希给美美转1000元钱。

                使用事务

                                先给冠希扣除掉1000元                

                                再给美美加上1000元            

                  事务结束了

2.事务的分类

        事务分为隐式事务和显式事务两种。我们的DML语句(insert、update、delete)就是隐式事务。

        2.1隐式事务:该事务没有明显的开启和结束标记,它们都具有自动提交事务的功能;不妨思考一下,update语句修改数据时,是不是对表中数据进行改变了,它的本质其实就相当于一个事务。

        2.2显示事务:该事务具有明显的开启和结束标记;也是本文重点要讲的东西。使用显式事务的前提是你得先把自动提交事务的功能给禁用。禁用自动提交功能就是设置autocommit变量值为0(0或off:禁用 1:开启)set autocommit = off;

3.事务的使用方式

       首先创建一个表

create table t_account(
        id int primary key auto_increment,
        username varchar(20),
        money double
    );
    
    insert into t_account values (null,'美美',10000);
    insert into t_account values (null,'冠希',10000);
    insert into t_account values (null,'小凤',10000);
    insert into t_account values (null,'熊大',10000);
    insert into t_account values (null,'熊二',10000);
2.在MySQL数据库中使用事务,提供两种方式(重点)
    * 模拟转账的例子,冠希给美美转钱
    
    * 第一种方式(使用命令的方式)
        * start transaction;        ‐‐ 开启事务
        * update t_account set money = money ‐ 1000 where username = '冠希';
        * update t_account set money = money + 1000 where username = '美美';
        * commit;                   ‐‐ 提供事务(事务已经结束了,数据永久的保存到数据库中了)
        * rollback;                 ‐‐ 回滚事务(事务已经结束了,数据回滚到最初始化的状态)
        
    * 第二种方式(设置MySQL事务不默认提交的方式)
        * MySQL数据库的事务是默认提交的。
* update t_account set money = money ‐ 1000 where username = '冠希'; ‐‐ 这一条语句在JDBC中操作事务(掌握) 
 
事务的特性(理解) 
* update t_account set money = money ‐ 1000 where username = '冠希'; ‐‐ 这一条语句
默认使用了一个事务。
               
 
        * 设置让MySQL的数据库的事务不默认提交
            * set autocommit = off或者0           ‐‐ 设置MySQL事务的事务不默认提交
        * 编写SQL语句(执行完,都没有提交)
            * sql1
            * sql2
        * 需要手动的提交或者回顾
            * commit;
            * rollback;         
 
    * 演示第二种方式
        * show variables like '%commit%';       ‐‐ 查看事务的是事务是否是默认提交
        * set autocommit = off;                 ‐‐ 设置不默认提交
        * update t_account set money = money ‐ 1000 where username = '冠希';
        * update t_account set money = money + 1000 where username = '美美';
        * commit;或者rollback;

4.事务的特性

        事务的特性:  

原子性:原子性对应的英文是Atomicity,即表示事务中所有操作是不可再分割的原子单位。事务中所有操作要么全 部执行成功,要么全部执行失败;   

一致性:一致性对应的英文是Consistency,事务执行后,数据库状态与其它业务规则保持一致。例如转账业务,无 论事务执行成功与否,参与转账的两个账号余额之和应该是不变的;   

隔离性:隔离性对应的英文是Isolation,是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不 会相互干扰;   

持久性:持久性对应的英文是Durability,指的是一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据 库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据  

1.事务的特性     * 原子性       ‐‐ 强调的是事务的不可分割的特性     

                          * 一致性       ‐‐ 强调的是事务执行前后数据需要保证一致     

                          * 隔离性       ‐‐ 强调的是多个事务同时操作一条记录,事务之间不能互相干扰     

                          * 持久性       ‐‐ 强调的是事务一旦结束了,数据将永久的保存到数据库中

5.事务并发是出现的问题:

        5.1 脏读:一个事务读取到了另一个事务未提交的数据!

        5.2不可重复读:一个事务读取到了另一个事务提交的数据,导致了多次查询的结果不一致。强调的是update,修改记录 的数据。

        5.3虚度(幻读):一个事务读取到了另一个事务提交的数据,导致了多次查询的结果不一致。强调是insert,向表中添 加一条数据。

6.设置事务的隔离级别(解决读的问题)

6.1事务的隔离级别(设置数据库的隔离级别,根据级别的不同,解决上述的读的问题)
    * Read uncommitted      ‐‐ 什么都解决不了
    * Read committed        ‐‐ 避免脏读,但是不可重复读和虚读有可能产生
    * Repeatable read       ‐‐ 避免脏读和不可重复读,虚度有可能产生的
    * Serializable          ‐‐ 避免各种读
 
6.2 4种隔离级别有安全性和效率
    * 安全    Serializable > Repeatable read > Read committed > Read uncommitted
    * 效率    Serializable < Repeatable read < Read committed < Read uncommitted
 
6.3.数据库都有自己默认的隔离级别
    * MySQL的数据库,默认的隔离级别是Repeatable read,避免脏读和不可重复读。

       7.读问题实验

       7.1演示脏读

        

1.脏读:一个事务读取到了另一个事物未提交的数据。
2.进行测试
    * 开启两个窗口,一个A窗口(左),一个B窗口(右)。
    * 在A窗口中,查询A窗口的隔离级别:select @@tx_isolation;
* 设置A窗口的隔离级别为最低级别: set session transaction isolation level read uncommitted;
    * 在两个窗口中,都开启事物
        * start transaction;
    * 在B窗口中完成转账的工作。(冠希给美美转1千钱)
        * update t_account set money = money ‐ 1000 where username = '冠希';
        * update t_account set money = money + 1000 where username = '美美';
        * 注意:B窗口的事物未提交。
    * 在A窗口中,查询的结果(美美)
        * select * from t_account;
    * 在B窗口中,回滚的是事物
        * rollback;

7.2 避免脏读和演示不可重复读

        

1.避免脏读的发生,提高的隔离级别。
    * set session  transaction isolation level  read committed;
    
    * 在两个窗口中,都开启事物
        * start transaction;
    * 在B窗口中完成转账的工作。(冠希给美美转1千钱)
        * update t_account set money = money ‐ 1000 where username = '冠希';
        * update t_account set money = money + 1000 where username = '美美';
        * 注意:事物还是没有提交,但是你需要观察A窗口中是否能读取到B创建未提交的数据。
    * 在A窗口中,查询的结果(美美)
        * select * from t_account;
        
    * 在B窗口中把事物提交了
        * commit;
    
    * 在A窗口中,再查询一次钱。
        * 两次查询的结果不一致,发生了不可重复读。

        7.3 避免不可重复读

        

1.设置隔离级别:set session  transaction isolation level  repeatable read;
* 在两个窗口中,都开启事物
        * start transaction;
    * 在B窗口中完成转账的工作。(冠希给美美转1千钱)
        * update t_account set money = money ‐ 1000 where username = '冠希';
        * update t_account set money = money + 1000 where username = '美美';
        * 注意:事物还是没有提交,但是你需要观察A窗口中是否能读取到B创建未提交的数据。
    * 在A窗口中,查询的结果(美美)
        * select * from t_account;
        
    * 在B窗口中把事物提交了
        * commit;
    
    * 在A窗口中,再查询一次钱。
        * 两次查询的结果一致。

7.4演示幻读

1.设置隔离级别:set session  transaction isolation level  repeatable read;
* 在两个窗口中,都开启事物
        * start transaction;
    * 在A窗口中,查询的结果(美美)
        * select * from t_account;
     *在B窗口中,插入新数据
        * insert t_account values(10,"sdsd",1000)
      *提交
        * commit
    
        
 
    * 在A窗口中,再查询一次钱。
        * select * from t_account;
        * 两次查询的结果不一致,发生了发现出现了插入的新数据,发生幻读问题
    *还有可能出现不了,因为innodb引擎在可重复读下可能避免幻读,可以多试几遍。

7.5 避免各种读

1.设置隔离级别:set session transaction isolation level serializable;
* 在两个窗口中,都开启事物
    * start transaction;
* 在B窗口中添加一条数据
    * insert into t_account values (null,'小苍',10000);
    * 注意:没有提交事物
* 在A窗口中查询数据库
    * select * from t_account;

  • 21
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值