数据库事务隔离本质

提到事务, 你肯定不陌生, 和数据库打交道的时候, 我们总是会用到事务, 最经典的例子就是转账, 你要给朋友小王转100块钱, 而此时你的银行卡只有100块钱.
转账过程具体到程序里会有一系列的操作, 比如余额查询, 做加减法, 更新余额等, 这些操作必须保证是一体的, 不然等程序查完之后, 还没做减法之前, 你这100块钱, 完全可以借着这个时间差再查一次, 然后再给另外一个朋友转账, 如果银行这么整, 不久乱了么?, 这是就要用到”事务”这个概念了.

简单来说, 事务就是要保证一组数据库操作, 要么全部成功, 要么全部失败. 再mysql中, 事务支持是在引擎层实现的.你现在知道, mysql是一个支持多引擎的系统, 但并不是所有的引擎都支持事务.比如mysql原生的myiSAM引擎就不支持事务, 这也是MyISAM被InnoDB取代的重要原因之一.

隔离性和隔离级别
提到事务, 你肯定会想到ACID(Atomicity, Consistency, isolation, DURability, 即原子性, 一致性, 隔离性, 持久化).

当数据库上游多个事务同时执行的时候, 就可能出现脏读(dirty read), 不可重复读(non-repeatable read), 幻读(phantom read)的问题, 为了解决这些问题, 就有了”隔离级别”的概念.

在谈隔离级别之前, 你首先要知道, 你隔离得越严实, 效率就会越低.因此很多时候, 我们都要在二者之间寻找一个平衡点.sql标准的事务隔离级别包括: 都未提交(read uncommitted), 读提交(read committed), 可重复读(repeatable read)和串行化(seriazable).

  • 读未提交是指, 一个事务还没提交时, 他做的变更就能被别的事务看到.
  • 读提交是指, 一个事务执行过程中看到的数据, 总是跟这个事务在启动时看到的数据是一致的,当然在可重复读隔离级别下, 未提交变更对其他事务也是不可见.
  • 串行化, 顾名思义是对于同一行记录, “写”会加”写锁”, “读”会加”读锁”. 当出现读写锁冲突的时候, 后访问的事务必须等前一个事务执行完成, 才能继续执行.

其中”读提交”和”可重复读”比较难理解, 所以我用一个例子说明这几种隔离级别.假设数据表T中只有一列, 其中一行的值为1, 下面是按照时间顺序执行两个事务的行为.

1
2
mysql> create table T(c int) engine=InnoDB;
insert into T(c) values(1);

我们来看看在不同的隔离级别下, 事务A会有那些不同的返回结果, 也就是图里面V1, V2,V3的返回值分别是什么.

在mysql里, 有两个”视图”的概念:

  • 一个是view.它是一个用查询语句定义的虚拟表, 在调用的时候执行查询语句并生成结果,创建视图的语法是create view…, 而他的查询方法与表一样.

  • 另一个是InnoDB在实现mvcc时用到的一致性读视图, 即consistent readview, 用于支持RC(read committed, 读提交)和RR(Repeatable Read, 可重复读)隔离级别的实现.

感谢支持 !
0%