暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Mysql事务的隔离机制(一)

氷泠之路 2021-05-11
166

首先说一下什么是ACID


1 ACID

事务的四大特性是ACID(不是"酸"......)

(1) A:原子性(Atomicity)

原子性指的是事务要么完全执行,要么完全不执行.


(2) C:一致性(Consistency)

事务完成时,数据必须处于一致的状态.若事务执行途中出错,会回滚到之前的事务没有执行前的状态,这样数据就处于一致的状态.若事务出错后没有回滚,部分修改的内容写入到了数据库中,这时数据就是不一致的状态.


(3) I:隔离性(Isolation)

同时处理多个事务时,一个事务的执行不能被另一个事务所干扰,事务的内部操作与其他并发事务隔离.


(4) D:持久性(Durability)

事务提交后,对数据的修改是永久性的.

2 Mysql的锁

Mysql的锁其实可以按很多种形式分类

- 按加锁机制分,可以分为乐观锁与悲观锁

- 按数据库系统角度来分,可分为X锁与S锁

- 按锁粒度分,可以分为表锁,行锁,页锁

- 按锁模式分,可以分为记录锁,gap锁,next-key锁,意向锁,插入意向锁


这里主要讨论S锁,X锁,乐观锁与悲观锁.

(1) S锁与X锁

S锁与X锁是InnoDB引擎实现的两种标准行锁机制.查看引擎可使用
    show variables like '%storage_engine%';
    复制
    作者的mysql版本为8.0.17,结果如下:
    先建好测试库与测试表,很简单,表就两个字段.
      create database test;
      use test;
      create table a
      (
      id int primary key auto_increment,
      money int
      );
      复制

      S锁

      S锁也叫共享锁,读锁,数据只能被读取不能被修改.
      玩一下,上锁!
        lock table a read;
        复制


        然后.....



        只能读不能改,删,也不能改.


        X锁

        X锁也叫排他锁,写锁,一个事务对表加锁后,其他事务就不能对其进行加锁与增删查改操作.


        先开启一个事务并上X锁.
          set autocmmmit=0;
          start transaction;
          lock table a write;
          复制

          然后再开启另一个事务,使用select.
            set autocommit=0;
            start transaction;
            select * from a;
            复制

            这里是等待操作,因为一直都没释放X锁.


              

            同样也不能再加锁,也是等待中.


            回到原来那个加锁的事务,嗯,什么事也没有,正常读写.


            释放锁后:

              unlock table;
              复制



              可以看到中断时间.

              (2) 乐观锁与悲观锁
              乐观锁
              乐观锁就是总是假设是最好的情况,每次去操作的时候都不会上锁,但在更新时会判断有没有其他操作去更新这个数据,是一种宽松的加锁机制.

              mysql本身没有提供乐观锁的支持,需要自己来实现,常用的方法有版本控制和时间戳控制两种.

              - 版本控制

              版本控制就是为表增加一个version字段,读取数据时连同这个version字段一起读出来,之后进行更新操作,版本号加1,再将提交的数据的版本号与数据库中的版本号进行比较,若提交的数据的版本号大于数据库中的版本号才会进行更新.

              举个例子,假设此时version=1,A进行操作,更新数据后version=2,与此同时B也进行操作,更新数据后version=2,A先完成操作,率先将数据库中的version设置为2,此时B提交,B的version与数据库中的version一样,不接受B的提交.

              - 时间戳控制

              时间戳控制与版本控制差不多,把version字段改为timestamp字段

              还有一种实现方法叫CAS算法,这个作者不怎么了解,有兴趣可以自行搜索.


              悲观锁

              悲观锁就是总是假设最坏的情况,在整个数据处理状态中数据处于锁定状态,悲观锁的实现往往依靠数据库的锁机制.每次在拿到数据前都会上锁.
              mysql在调用一些语句时会上悲观锁,如(先关闭自动提交,开启事务):
                set autocommit=0;
                start transaction;
                复制

                两个事务都这样操作,然后其中一个事务输入:

                  select * from a where xxx for update;
                  复制



                  在另一事务也这样输入:

                  这时语句会被阻塞,直到上锁的那个事务commit(解开悲观锁).

                  在另一事务中可以看到这个事务被阻塞了2.81s.

                  以下这条语句:

                    *** lock in share mode.
                    复制

                    也会加上悲观锁.

                    文章转载自氷泠之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                    评论