• Mysql事务


    @[TOC]Mysql事务

    简介

    事务四大特征(ACID)

    推荐: https://blog.csdn.net/lianghecai52171314/article/details/102782804

    原子性:事务是最小单位,不可再分,例如:update … insert … delete …

    一致性:所有的DML语句操作,必须同时成功或者同时失败

    隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read
    committed)、可重复读(repeatable read)和串行化(Serializable)。

    持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

    事务的4个级别

    隔离级别:

    隔离级别脏读(Dirty Read)不可重复读(NonRepeatable Read)幻读(Phantom Read)
    未提交读(READ-UNCOMMITTED)
    已提交读(READ-COMMITTED)
    可重复读(REPEATABLE-READ)[默认级别]
    串行化(SERIALIZABLE )

    脏读,幻读,不可重复读

    脏读[脏数据](Dirty Read): 两个事务,一个事务未提交的数据(commit),另一个事务可以读取到.

    不可重复读(NonRepeatable Read):事务A在修改数据,事务B在事务A 数据(修改前)和(修改后),未提交(commit)前,两次读取的数据不一致。

    幻读(Phantom Read):是指多个事务执行时发生的一种现象。事务A新增或删除了数据,但是未提交(commit),事务B发现新增或删除的数据,就像幻觉一样。

    备注

    不可重复读的重点是修改:

    同样的条件,你读取过的数据,再次读取出来发现值不一样了

    幻读的重点在于新增或者删除:

    同样的条件,第 1 次和第 2 次读出来的记录数不一样

    查询与设置隔离级别

    查询会话事务级别

    # mysql 查询会话级别
    select @@transaction_isolation; # 查询当前的会话事务级别 
    select @@global.transaction_isolation; # 查询全局的事务隔离级别
    show variables like 'transaction_isolation';
    
    
    # 8.0以下版本,8.0之后版本废弃
    select @@tx_isolation;  # 查询当前的会话事务级别 
    select @@global.tx_isolation; # 查询全局的事务隔离级别
    
    +-----------------+
    | @@tx_isolation  |
    +-----------------+
    | REPEATABLE-READ |
    +-----------------+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    设置事务级别

    # 未提交读  read uncommitted级别:
    set session transaction isolation level read uncommitted;
    
    # 已提交读 read committed级别:
    set session transaction isolation level read committed;
    
    # 可重复读 repeatable read级别:
    set session transaction isolation level repeatable read;
    
    # 可串行化 serializable级别:
    set session transaction isolation level serializable;
    
    # 开始事务
    begin; 
    start transaction; 
    # 提交事务
    commit; 
    # 回滚
    rollback;   
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    示例测试数据

    初始化数据表

    -- 登录mysql
    -- mysql -u root -h 127.0.0.1 -p
    
    -- 创建数据库
    -- create database testdb;
    
    use testdb;
    drop table if exists user;
    CREATE TABLE `user`(
        `id`   int(11) unsigned NOT NULL AUTO_INCREMENT,
        `name` varchar(255) NOT NULL DEFAULT '' COMMENT '名字',
        `num`  int(11) NOT NULL DEFAULT 0 COMMENT '数量',
        PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    
    -- 初始数据
    INSERT INTO `user` (`name`,`num`) VALUES ('one',0),('two',0),('three',0);
    
    select * from user;
    +----+-------+-----+
    | id | name  | num |
    +----+-------+-----+
    |  1 | one   |   0 |
    |  2 | two   |   0 |
    |  3 | three |   0 |
    +----+-------+-----+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    未提交读

    事务A事务B
    无事务
    备注
    set session transaction isolation level read uncommitted;

    begin;


    设置事务级别
    开启事务

    set session transaction isolation level read uncommitted;
    
    begin;
    set session transaction isolation level read uncommitted;

    select * from user; 

    idnamenum
    1one0
    2two0
    3three0



    原始数据

    INSERT INTO `user` (`name`,`num`) VALUES ('four',0);


    UPDATE user SET num=10 where id=1;


    DELETE FROM user where id=3;


    select * from user;

    idnamenum
    1one10
    2two0
    4four0






    select * from user; 

    idnamenum
    1one10
    2two0
    4four0

    脏读

    事务A数据未提交但是事务B可以读取




    select * from user; 

    idnamenum
    1one10
    2two0
    4four0


    虽然未启用事务,但是依然课读取到脏数据

    commit; (事物提交)

    idnamenum
    1one10
    2two0
    4four0




    rollback; (事物回滚,无操作)

    idnamenum
    1one10
    2two0
    4four0




    select * from tb;

    idnamenum
    1one10
    2two0
    4four0

    已提交读

    事务A事务B
    无事务
    备注
    set session transaction isolation level read committed;

    begin;
    set session transaction isolation level read committed;
    
    begin;
    set session transaction isolation level read committed;设置事物级别
    开启事物

    select * from user; 

    idnamenum
    1one0
    2two0
    3three0


    INSERT INTO `user` (`name`,`num`) VALUES ('four',0);


    UPDATE user SET num=10 where id=1;


    DELETE FROM user where id=3;


    select * from user;

    idnamenum
    1one10
    2two0
    4four0






    select * from user; 

    idnamenum
    1one0
    2two0
    3three
    0

    看不见事务A数据修改



    select * from user; 

    idnamenum
    1one0
    2two0
    3three0



    commit; (事物提交)


    idnamenum
    1one10
    2two0
    4four0


    事物A提交

    select * from user; 

    idnamenum
    1one10
    2two0
    4four0



    不可重复读,

    数据被修改,读取到已提交的数据。


    幻读(一种现象),

    第一次查询可以看见3,第二次查询3被删除,查询到了4,行不一样了


    rollback; (事物回滚,无操作)





    select * from user; 

    idnamenum
    1one10
    2two0
    4four0

    可重复读

    事务A事务B
    无事务
    备注
    set session transaction isolation level repeatable read;

    start transaction;
    set session transaction isolation level repeatable read;

    start transaction;
    set session transaction isolation level repeatable read;设置事物级别
    开启事物


    select * from user; 

    idnamenum
    1one0
    2two0
    4four0


    INSERT INTO `user` (`name`,`num`) VALUES ('four',0);


    UPDATE user SET num=10 where id=1;


    DELETE FROM user where id=3;


    select * from user;

    idnamenum
    1one10
    2two0
    4four0






    select * from user; 

    idnamenum
    1one0
    2two0
    3three
    0

    看不见数据修改



    select * from user; 

    idnamenum
    1one0
    2two0
    3three0



    commit; (事物提交)


    idnamenum
    1one10
    2two0
    4four0




    select * from user; 

    idnamenum
    1one0
    2two0
    3three0



    未查询到修改,避免 不可重复读取 ,


    UPDATE user SET num=num+20 where id=1;


    select * from user; 

    idnamenum
    1one30
    2two0
    3three0



    更新后id=1的值为30,


    在可重复读的隔离级别下,MySQL采用的是MVCC机制,select 操作不会更新版本号,是快照读(历史版本);而insert、update和delete会更新版本号,是当前读(当前版本)


    commit; (事务提交)

    idnamenum
    1one30
    2two0
    4four0

    结束后发现最新数据


    select * from user; 

    idnamenum
    1one30
    2two0
    4four0

    串行化

    事务A事务B
    无事务
    备注
    set session transaction isolation level serializable;

    start transaction;
    set session transaction isolation level serializable;
    
    start transaction;
    set session transaction isolation level serializable;设置事物级别
    开启事物

    INSERT INTO `user` (`name`,`num`) VALUES ('four',0);


    UPDATE user SET num=10 where id=1;


    DELETE FROM user where id=3;


    select * from user;

    idnamenum
    1one10
    2two0
    4four0






    select * from user; 


    等待 事物A 执行。。。






    select * from user; 

    idnamenum
    1one0
    2two0
    3three0



    commit; (事物提交)


    idnamenum
    1one10
    2two0
    4four0




    事物A 等待结束,开始执行语句。。。

    idnamenum
    1one10
    2two0
    4four0



    最新数据


    rollback; (事物回滚,无操作)

    idnamenum
    1one10
    2two0
    4four0




    select * from user; 

    idnamenum
    1one10
    2two0
    4four0

  • 相关阅读:
    我的为人处事真的有问题吗?
    SuperMap iServer 机器学习服务配置及使用
    16-Linux磁盘管理
    创建vue3工程
    React编写CSS方式
    蓝桥等考Python组别六级003
    算法优化,最短路径。
    PMP备考|通关宝典
    【yosys】基础的综合操作(更新中)
    【工作中遇到的性能优化问题】
  • 原文地址:https://blog.csdn.net/u010861514/article/details/125897981