• 深入理解mysql的隔离级别


    建表插入测试数据
    A> create table test(id int ,num int) ;
    Query OK, 0 rows affected (0.53 sec)

    A> insert into test values(1,1);
    Query OK, 1 row affected (0.01 sec)

    A> insert into test values(2,2);
    Query OK, 1 row affected (0.00 sec)

    A> insert into test values(3,3);
    Query OK, 1 row affected (0.01 sec)


    A> select * from test ;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 1 |
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    3 rows in set (0.00 sec)

    A> show create table test ;
    +-------+----------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table |
    +-------+----------------------------------------------------------------------------------------------------------------------+
    | test | CREATE TABLE `test` (
    `id` int(11) DEFAULT NULL,
    `num` int(11) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
    +-------+----------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)


    一。隔离级别read uncommitted,事物A可以读到事物B的未提交数据,未提交数据称为脏数据,因此叫脏读。
    A> set session transaction isolation level read uncommitted ;
    Query OK, 0 rows affected (0.00 sec)

    A> SELECT @@tx_isolation ;
    +------------------+
    | @@tx_isolation |
    +------------------+
    | READ-UNCOMMITTED |
    +------------------+
    1 row in set (0.00 sec)

    A> start transaction ;
    Query OK, 0 rows affected (0.00 sec)

    A> select * from test ;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 1 |
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    3 rows in set (0.00 sec)

    B> start transaction ;
    Query OK, 0 rows affected (0.00 sec)

    B> update test set num=10 where id=1 ;
    Query OK, 1 row affected (0.01 sec)
    Rows matched: 1 Changed: 1 Warnings: 0


    B> select * from test ;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 10 |
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    3 rows in set (0.00 sec)

    A> select * from test ;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 10 |
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    3 rows in set (0.01 sec)

    B> rollback ;
    Query OK, 0 rows affected (0.01 sec)

    B> select * from test ;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 1 |
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    3 rows in set (0.00 sec)

    A> select * from test ;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 1 |
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    3 rows in set (0.00 sec)


    二。隔离级别read committed ,
    对于事物B未提交的DML操作,事物A是看不到的
    但是事物A在本身事物操作的过程中(未做commit or rollback),可以读到事物B的已提交数据,这就是不可重复读
    下面测试下:
    A> set session transaction isolation level read committed ;
    Query OK, 0 rows affected (0.00 sec)

    A> start transaction ;
    Query OK, 0 rows affected (0.00 sec)

    A> select * from test ;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 1 |
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    3 rows in set (0.00 sec)

    B>start transaction ;
    Query OK, 0 rows affected (0.00 sec)


    B>update test set num=20 where id=1 ;
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1 Changed: 1 Warnings: 0


    B>rollback ;
    Query OK, 0 rows affected (0.01 sec)


    B>start transaction ;
    Query OK, 0 rows affected (0.00 sec)


    B>insert into test values(4,4) ;
    Query OK, 1 row affected (0.00 sec)

    B>select * from test;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 1 |
    | 2 | 2 |
    | 3 | 3 |
    | 4 | 4 |
    +------+------+
    4 rows in set (0.00 sec)

    B>rollback ;
    Query OK, 0 rows affected (0.01 sec)

    B>start transaction ;
    Query OK, 0 rows affected (0.00 sec)


    B>delete from test where id =1 ;
    Query OK, 1 row affected (0.01 sec)

    B>select * from test;
    +------+------+
    | id | num |
    +------+------+
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    2 rows in set (0.00 sec)


    B>rollback ;
    Query OK, 0 rows affected (0.01 sec)


    在事物B做这些DML操作的时候,事物A的查询结果一直没变,此时事物A尚未结束
    A> select * from test ;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 1 |
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    3 rows in set (0.00 sec)


    提交事物B的某个操作,事物A里面的对表test的查询结果就变了,因此事物A里面对test表的查询是不可重复的,所以叫不可重复读

    三。隔离级别repeatable read
    mysql的默认事物隔离级别,防止了脏读和不可重复读,但可能出现幻读
    该隔离级别解决了不重复读,保证了同一个事务里,查询的结果都是事务开始时的状态(一致性)。
    但是,如果另一个事务同时提交了新数据,本事务再更新时,就会“惊奇的”发现了这些新数据,貌似之前读到的数据是“鬼影”一样的幻觉。

    A> set session transaction isolation level repeatable read ;
    Query OK, 0 rows affected (0.00 sec)

    A> select @@session.tx_isolation ;
    +------------------------+
    | @@session.tx_isolation |
    +------------------------+
    | REPEATABLE-READ |
    +------------------------+
    1 row in set (0.00 sec)

    A> start transaction ;
    Query OK, 0 rows affected (0.00 sec)

    A> select * from test ;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 1 |
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    3 rows in set (0.00 sec)

    B> start transaction ;
    Query OK, 0 rows affected (0.00 sec)


    B> update test set num=10 where id=1 ;
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1 Changed: 1 Warnings: 0

    B> select * from test ;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 10 |
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    3 rows in set (0.00 sec)

    B> commit ;
    Query OK, 0 rows affected (0.01 sec)

    此处A的修改应该是num=3才对,但是因为幻读,事物B虽然提交了,但事物A读到的还是旧记录,
    如同幻影一般,事物A修改后,发现结果是30,而不是想要的结果3
    A> update test set num=num*3 where id=1 ;
    Query OK, 1 row affected (0.03 sec)
    Rows matched: 1 Changed: 1 Warnings: 0


    A> select * from test ;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 30 |
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    3 rows in set (0.00 sec)


    A> commit ;
    Query OK, 0 rows affected (0.01 sec)

    四。隔离级别SERIALIZABLE
    SERIALIZABLE事务隔离级别最严厉,在进行查询时就会对表或行加上共享锁,其他事务对该表将只能进行读操作,而不能进行写操作。

    A> set session transaction isolation level serializable ;
    Query OK, 0 rows affected (0.00 sec)

    A> select @@session.tx_isolation ;
    +------------------------+
    | @@session.tx_isolation |
    +------------------------+
    | SERIALIZABLE |
    +------------------------+
    1 row in set (0.00 sec)


    A> start transaction ;
    Query OK, 0 rows affected (0.00 sec)

    A> select * from test ;
    +------+------+
    | id | num |
    +------+------+
    | 1 | 1 |
    | 2 | 2 |
    | 3 | 3 |
    +------+------+
    3 rows in set (0.00 sec)


    B> start transaction ;
    Query OK, 0 rows affected (0.00 sec)

    B> update test set num=3 where id=1 ;
    ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

    控制超时的参数
    innodb_lock_wait_timeout | 120

  • 相关阅读:
    消息队列技术
    NET Core中使用Apworks
    TCP基础
    Oracle停止一个JOB
    如何在Java 8中愉快地处理日期和时间
    mysql字符串区分大小写的问题
    【已解决】javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint
    spring boot 1.4默认使用 hibernate validator
    mysql shell
    android:background="@drawable/home_tab_bg"
  • 原文地址:https://www.cnblogs.com/caibird2005/p/4555177.html
Copyright © 2020-2023  润新知