zoukankan      html  css  js  c++  java
  • 一步步走进Sql中的事务及事务隔离级别

     1.事务定义

    事务是按照逻辑执行的一组任务序列,这一组任务序列要么都执行,要么都不执行。

    事务是优先基于会话配置的的(session),其次是基于全局配置的(global)。

    2.事务的提交和回滚

    提交commited,即一组任务序列,正常执行后,提交给数据库。

    回滚rollback,即一组任务序列中,无论哪一个任务环节出现异常,都会把所有的任务序列全部恢复到原始状态。

    事务的提交可以分为手动提交和自动提交。

    3.查看和设置提交方式

    session和global中都有变量autocommit,

    autocommit为1的时候自动提交,

    autocommit为0的时候手动提交。

    select @@session.autocommit;

    查看全局配置中的默认提交方式

    select @@global.autocommit;

    关闭当前会话的自动提交,改为手动提交。

    set @@session.autocommit=0;

     4.创建数据库,测试提交方式。

    设计一个简单的数据库,往数据库中加一个表格。

    表格中分别是,id(自增),用户名,用户余额。

    USE transdemo;
    
    DROP TABLE IF EXISTS users;
    
    CREATE TABLE users (
      uid INT(11) AUTO_INCREMENT,
      uname VARCHAR(10) DEFAULT NULL,
      money INT(11) DEFAULT NULL,
      PRIMARY KEY (uid)
    )

    插入一条数据

    INSERT INTO users VALUES(NULL,'zhanghao',1000)

    mysql自增字段(id)插入时,用null即可。

    结果:

    自动提交:

     手动提交:

     为了测试手动提交,打开另外一个命令窗口并连接mysql,即开启了另外一个会话窗口B(Windows PowerShell)

    这是原本的会话窗口A(Windows PowerShell),关闭自动提交,改为手动提交。

    此时A中会话看似一切正常。

    在B中,再次读取users表。

    问题出来了,zhanghao用户的money还是900,表格数据并没有被更新。

    此时,我们在A会话(原本会话)中,提交commit;

     

    此时,我们在B会话(新开的会话窗口)再次查询,

    数据被更新。

    总结:自动提交时,无需commit即可自动更新改变数据;手动提交时,必须要commit,才能更新改变数据库中的数据。

    5.事务隔离级别

    事务中的隔离级别共有四种:

    1.读未提交 read uncommited

    2.读已提交 read commited

    3.可重复读 repeatable read

    4.串行化 serializable

    首先查看当前会话的事务隔离级别

    select @@session.transaction_isolation;
    
    
    -- 8.0以下版本
    -- select @@session.tx_isolation;

     再看一下全局的

    select @@global.transaction_isolation;
    
    
    -- 8.0以下版本
    -- select @@global.tx_isolation;

    从上面测试可以看出,mysql的事务隔离级别,默认是repeatable-read,即可重复读。

    我们可以修改mysql的事务隔离级别,仍然基于当前会话(session)

    -- 将当前会话的事务隔离级别设置为 : read uncommitted,即读未提交
    set session transaction isolation level read uncommitted;
    
    -- 查看当前会话的事务隔离级别
    select @@session.transaction_isolation;

     此时,事务的隔离级别变为的read uncommitted即读未提交。

    5.1 读未提交

    两个连接窗口AB(Windows PowerShell),测试读未提交。

    按上文方法,将A连接设置为读未提交。B连接不设置隔离级别,采用默认。

    首先在B连接中,开始事务,并将zhanghao用户的money减100。

    此时,在事务中,可以正常的显示zhanghao的money为900,成功被减去100。

    但是在数据库中查看

    zhanghao的money仍为1000。

    这也不奇怪,因为B连接的事务并没有被提交。

    但是,在B连接中的事务没有提交,数据库users表中zhanghao的money为1000的时候,

    在A会话窗口中(已被设置为读未提交),开始事务并读取zhanghao的money时,却读到了未提交的900。

    这就是读未提交。

    导致的问题:脏读。即另外一个事务尚未提交的时候(数据库中的数据没被改变的时候),在A窗口事务中,已经读到了未提交的数据。

    5.2 读已提交

    仍然开始两个Windows PowerShell窗口分别连接mysql,实现两个会话。

    首先在A窗口中,设置事务隔离级别为读已提交。

    set session transaction isolation level read committed;

    B窗口采用默认的隔离级别,不做任何改动即可。

    数据库初始值

    在B窗口中,开启事务,并把money减去100,不提交。

    然后,在A窗口中,开始事务并查询users表,不提交

     然后,在B窗口中,提交。

    然后,在A窗口中,再次查询users表。

    本次流程A窗口的完整运行结果如下

    第一次查询的时候,由于B窗口的update未提交,所以为money1000,

    B窗口提交之后,A窗口再次查询的时候,money变为了900。

    这就是读已提交。

    导致的问题:不可重复读。从上图可以明显看出,在一个事务中,两次读到的结果不相同。

    5.3 可重复读

    仍然开始两个Windows PowerShell窗口分别连接mysql,实现两个会话。

    首先在A窗口中,设置事务隔离级别为可重复读。

    B窗口采用默认的隔离级别,不做任何改动即可。

    数据库初始值

    首先在B窗口中,开启事务。并将zhanghao的money减去100,不提交。

    然后,在A窗口中,开启事务并查看users表,不提交。

    然后B窗口提交。

    然后再次在A窗口中查看users表。

     发现,两次查询的结果,是一致的。即使B窗口已经将money改为900并提交,

    但是在A窗口的一个事务中,两次查询结果是一致的

    这就是可重复读,即在一个事务中,重复读数据时不会变的。

    但是这就完美了吗?

    此时A窗口仍未提交,B窗口已提交。

    在B窗口,再次开启一个事务,并且添加一条用户,lisi,500。

    此时,A窗口再次查询users表时,诡异的多了一条lisi的数据,

    也就是像魅影一样的出现了,这就是幻读。

    mysql8中,已经对幻读增加了防范措施,低版本mysql仍存在幻读问题。

    可重复读导致的问题:幻读

    5.4 串行化

    同上,开启A、B两个Windows PowerShell窗口连接mysql,

    在AB窗口中,都设置事务隔离方式为串行化

    set session transaction isolation level seriable;

    首先在A窗口中开启事务,并查询users表

    然后再B窗口中开启事务,并将zhanghao的money减去100,却发现窗口卡住了。

    回到A窗口,提交事务

    此时B窗口,更新操作顺利完成

    这就是串行化,

    即当A连接中的事务访问一个表的时候,

    B连接中的事务想要修改表中的数据,

    B连接就会卡住,等待A连接中的事务提交或回滚后,才继续执行B连接中的修改事务。

    即谁先执行的事务,必须等这个事务执行完,才能执行另一个事务。

    缺点:性能非常低。

  • 相关阅读:
    原型和原型链的理解
    vue2.0 购物车小球的实现
    canvas 实现规则多边形
    ES6全套教程
    利用canvas实现雪花的飘动
    前端 原型对象中this的认识
    JavaScript——创建对象
    javaScript——原型继承四步曲
    AltiumDesigner使用小窍门 (转)
    C指针理解(转)
  • 原文地址:https://www.cnblogs.com/zh1996/p/10361793.html
Copyright © 2011-2022 走看看