mysql事务详解-4种事务隔离级别该怎么选择

mysql事务详解-4种事务隔离级别该怎么选择

事务要保证ACID,其中就有隔离性。

当我们有多个事务在执行的时候,如果保证每个事务都是隔离的,而不是数据混乱的呢?sql标准的四种隔离级别如下:

  • 读未提交 RU(Read Uncommitted),在这个级别下,是所有数据共享的,A事务在执行的任何操作,B事务都能看见,不管有没有提交。
  • 读已提交 RC(Read Committed),在这个级别下,只有A事务提交的数据,B事务才能看见。提交前的数据对其他事务是不可见的。
  • 可重复读 RR(Repeatable Read),在这个级别下,一个事务内读取的数据都是重复的,也就是都是一致的,就算别的事务提交了数据,你读取的还是原来的数据。
  • 串行化 (serializable), 对于同一行记录,写会加写锁,读会加读锁。

事务隔离的原理

这些是怎么做到的呢?因为事务是具备回滚功能的,如果一旦事务出错就会回滚整个事务。

用过github的应该都知道,github上的代码是具备回滚功能的,如果上线之后发现bug,会回滚到上一个版本,github就是基于版本控制的。

事务同样是基于版本控制的。有一个undo log回滚日志来记录这些版本。比如对于一行用户数据:

{id: 1, name: 张三, mobile:13245678976, pwd: 123456}

事务1进行了修改手机号操作,这时候还没有提交。数据库就会有两个版本的数据。这些都记录在undo log里面,这也就是所谓的MVCC的概念。

{id: 1, name: 张三, mobile:13245678976, pwd: 123456} 原始版本
{id: 1, name: 张三, mobile:12322223333, pwd: 123456} 事务1版本

事务2同时启动,但是稍后进行查询操作,获取用户信息,如果你是读未提交级别,那么读取的是事务1版本数据:

{id: 1, name: 张三, mobile:12322223333, pwd: 123456} 事务1版本

如果你是其他级别,那么你读取的是原始版本数据:

{id: 1, name: 张三, mobile:13245678976, pwd: 123456} 原始版本

如果事务1已经提交了修改,那么事务2在读已提交级别下获取的也是事务1版本数据。

这个是怎么判断的呢?

每个事务有自己的事务id,这个id是单调递增的。在每行数据的版本上会记录事务id。在事务启动的时候,会维护一个已经启动但没有提交的事务的有序数组。有序也就是从小到大,排好序了。如果事务id小于这个数组中第一个id,那么这个事务一定是一个已经提交的事务。如果事务id大于这个数组,那么这个事务是在我之后启动的事务。如果事务id在这个数组中,那么他在我启动的时候一定是未提交的。

拿上面的数据举例,原始版本的事务id为100,事务1的事务id为101,事务2的事务id为102。

{id: 1, name: 张三, mobile:13245678976, pwd: 123456} 原始版本 100
{id: 1, name: 张三, mobile:12322223333, pwd: 123456} 事务1版本 101

当事务2启动后,事务数组为[101],假设这时候事务1未提交。

如果是可重复读级别下,那么当查询到最新版本事务id=101,在数组中,那么不可见,接着查询上一个版本,上一个版本事务id = 100,发现小于数组最小值,那么这个值是正确的,取出这个版本的数据。

这样就算后面有事务提交,但是它提交后的版本的事务id不满足要求,那么查看到的数据永远都是同一个版本的数据,这也就是一致性读

但是如果你在事务2中先更新了密码再执行查询,那么就会有三个版本的数据

{id: 1, name: 张三, mobile:13245678976, pwd: 123456} 原始版本 100
{id: 1, name: 张三, mobile:12322223333, pwd: 123456} 事务1版本 101
{id: 1, name: 张三, mobile:12322223333, pwd: 123456789} 事务2版本 102

这时候查询,事务数组为[101,102]。

再可重复读级别下,查询到最新数据事务id=102,发现和自己的一样,那么是可见的。因为是自己修改的,自己修改的不能不让自己看到啊,所以这时候查询到的数据会是最新数据。这也就是当前读

可重复读级别和读已提交级别的区别如下:

  • 可重复读是再事务开始时候创建一致性视图,数组,这些东西,它只认事务启动前提交的数据。
  • 读已提交级别则是每次执行sql语句的时候创建一致性视图,数组,这些东西,它认的是语句启动前提交的数据。

这四个隔离级别,常用的就是读已提交和可重复读两个级别。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章