-
getprivateprofilestring读不到数据_MySQL是怎么读数据的——多版本并发控制
2020-11-22 05:42:20求关注求转发 我在之前的文章中(【MySQL入门】之MySQL数据库的锁机制(一),【MySQL入门】之MySQL数据库的锁机制(二))介绍了MySQL的全局锁、表锁和行锁,今天我在来介绍下MySQL的一致性非锁定读、一致性锁定读。...求关注
求转发
我在之前的文章中(【MySQL入门】之MySQL数据库的锁机制(一),【MySQL入门】之MySQL数据库的锁机制(二))介绍了MySQL的全局锁、表锁和行锁,今天我在来介绍下MySQL的一致性非锁定读、一致性锁定读。再说之前我们先思考个问题,当我们用mysqldump进行逻辑备份时,如果有事务对表进行修改操作,那么我们备份出来的数据是否包含修改后的数据呢?如果mysqldump备份出的数据不包含之后修改的数据,那么他又是怎么保存之前的数据的呢?
一致性非锁定读(Consistent nonlocking reads)
一致性非锁定读也叫快照(snapshot read),是指当事务进行查询时,innodb存储引擎利用MVCC技术可以查看过去某个时间点的快照数据。查询可以看到别的事务在生成快照前提交的数据,而查看不到别的事务在生成快照之后提交或者未提交的数据。但是有一个例外,就是查询可以看到同一个事务中之前提交的数据,比如说事务开始时我做了一个查询id=1,紧接着我在当前事务中将id修改为2,那么当前事务再次查询时查到的id=2,也就是说我自己做的修改我还是要认的。
MVCC英文Multiversion Concurrency Control,翻译成中文是多版本并发控制,它的出现是为了提高数据库的并发能力,解决读-写冲突的无锁并发控制,它不需要等待要访问的行上的X锁的释放,可以读到数据之前的版本,实现了写不阻塞读以及可重复读。
MVCC主要是通过数据行的三个隐藏字段(DB_TRX_ID,DB_ROLL_PTR, DB_ROW_ID)、undo log和Read View来实现的。
三个隐藏字段InnoDB为数据库中存储的每一行增加了三个字段。
DB_TRX_ID:6字节,表示插入或者更新该行的最后一个事务的事务标识符。此外删除也被认为是一次更新,在行的一个特殊位置添加一个删除标记。
DB_ROLL_PTR:7字节,回滚指针指向被写在回滚段的undo log记录,如果数据行被修改,会将该行修改前的内容记录到undo log上。
DB_ROW_ID:6字节,我们在之前关于索引的文章中说过,如果表中没有显式的主键或者唯一索引,innodb会用DB_ROW_ID生成聚簇索引。
比如下图包含三个显式字段的一行数据:
UNDO 日志Undo log主要分为insert和update两种情况的日志,MVCC主要依赖的是update undo log(包含delete)。
首先我们要知道,每个事务都有一个唯一的事务ID,叫transaction id,它是在事务开始的时候向 InnoDB 的事务系统申请的,是按申请顺序严格递增的。每行数据也有自己的id,就是上面提到的DB_TRX_ID,每次事务更新数据的时候,都会生成一个新的数据版本,并且把 transaction id 赋值给这个数据版本的DB_TRX_ID,同时将上一版本的数据拷贝至undo log中,用DB_ROLL_PTR指针指向Undo log中的上一个版本数据。
还是上图的例子,我们假设事务1将name改为tom,接着事务2将age改为32,事务3将addr改为BeiJing,它的状态图如下:
从图中可以看出同一行数据总共有4个版本,当前最新的版本V4是被事务3修改的,所以他的DB_TRX_ID中存的是3,它的ROLL_PTR指针指向它上一个版本的数据,上一个版本是事务2修改,存放在undo log中的回滚段。这样就形成了一个版本链表,链首就是当前事务,链尾就是最早的记录,如果想找V2,就可以通过V4->V3->V2计算出V2来。
从这里也可以看出来,我们一定要消灭大事务,如果一个事务里有大事务,会导致undo log暴增而无法被purge。
Read ViewRead View 就是事务在使用MVCC机制进行快照读操作时产生的读视图(Read View),当事务启动时,会生成数据库系统当前的一个快照,InnoDB 为每个事务构造了一个数组,用来记录并维护系统当前活跃事务的ID(“活跃”指的就是,启动了但还没提交)。当该事务要读取某行记录时,innodb会将该行的当前版本号与数组中保存的版本号进行比较,来判断当前事务应该读取的行数据版本。
具体的算法规则如下(可RR隔离级别下):
假设当前事务要访问的数据行的版本T0,数组里面事务 ID 的最小值是T_min,当前系统里面已经创建过的事务 ID 的最大值记为T_max。
1. 当T0
2. 当T0>T_max时,表示这个版本是未来的某个事务生成的,数据肯定是不可见的。
3. 当T_min <= T0 <= T_max时,先看T0是否在read view数组中,
如果在数组中表示这个版本是由还没提交的事务生成的,数据不可见(自己更新的还是能看到的)。
如果不在数组中表示这个版本是由已经提交的事务生成的,数据可见。
再回到一开始我们说的问题,关于mysqldump工具的使用,其中有个参数—single-transaction,在RR隔离级别下,它表示在备份开始前,执行start transaction,把整个备份当成一个事务,直到备份结束,都不会读取到本事务开始之后提交的任何数据,在结合上面讲到的MVCC机制可以知道,它保存的并不是当前数据库的数据备份,而是当前事务的一致性视图(Read View)。
注意:以上是在RR隔离级别下的场景,在RC隔离级别下,对于一致性快照,总是读取被锁定行的最新一份快照数据,即只要数据被修改并且提交了,我就能看到最新的数据版本。
一致性锁定读(Locking Reads)
在同一个事务中如果你先查询然后再更新数据时,由于InnoDB引擎的select操作使用一致性非锁定读,其他事务可以修改或者删除刚才查询的行数据,这样就无法保证数据的一致性了。用户需要显式的对数据库读取操作进行加锁以保证数据逻辑的一致性。
InnoDB引擎对select语句支持两种一致性锁定读的操作:
1. SELECT ... LOCK IN SHARE MODE在要读取的行上加共享锁,在事务结束前其他事务可以读取这些行,但是不能修改。如果这些数据正在被其他事务修改,需要等待其他事务提交或者结束,然后获取最新的值。
2. SELECT ... FOR UPDATE对读取的行记录上加上X锁,其他事务不能在已锁定的行上加任何锁。
以上两种加锁模式必须在事务中,加锁前加上begin、start transaction或者set autocommit=0,当事务提交了,锁也就释放了。不管是在RC还是RR隔离级别下,普通的select操作使用的是快照读,不会对数据加锁,也不会被事务阻塞。
同时以上两种模式都是当前读(current read),它们读取到的是最新的数据,就是它们能看到其他事务提交后的数据。update、insert、delete也都是采用的当前读,会读取最新的记录,我们可以拿update来举个例子
对于t表,有两条数据,id为主键。
mysql> select * from t;+----+------+| id | k |+----+------+| 1 | 1 || 2 | 2 |+----+------+2 rows in set (0.00 sec)
我们开启一个会话A,查询下t表:
mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from t;+----+------+| id | k |+----+------+| 1 | 1 || 2 | 2 |+----+------+2 rows in set (0.00 sec)
开启会话B,对id=1的行执行k=k+1并提交,此时k=2
mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from t;+----+------+| id | k |+----+------+| 1 | 1 || 2 | 2 |+----+------+2 rows in set (0.00 sec)mysql> update t set k=k+1 where id=1;Query OK, 1 row affected (0.02 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql> select * from t;+----+------+| id | k |+----+------+| 1 | 2 || 2 | 2 |+----+------+2 rows in set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)
接着我们在会话A再执行update t set k=k+1 where id=1,大家觉得此时k等于多少呢?
mysql> update t set k=k+1 where id=1;Query OK, 1 row affected (0.00 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql> select * from t;+----+------+| id | k |+----+------+| 1 | 3 || 2 | 2 |+----+------+2 rows in set (0.00 sec)
从结果看k=3,这个例子也证明了update是当前读模式,它需要先拿到最新的数据然后再进行修改,如果会话B未提交的话,会话A只能等待会话B释放锁了。
悲观锁和乐观锁
悲观锁和乐观锁人们根据并发时对资源加锁的设计思路总结出来的概念,是一种加锁思想,不是真实存在的锁,是处理并发资源的常用手段。
悲观锁(Pessimistic Lock)悲观锁的特点是先获取锁,在进行业务操作,即悲观的认为我要修改的数据很有可能被其他事务锁住或者修改,因此我必须先确保锁成功之后再进行业务。
悲观锁主要是依靠数据库自身的锁机制实现,比如上面我们提到的一致性锁定读,其实就是用了悲观锁的思想。
MySQL的悲观锁通常用Select … for update和SELECT ... LOCK IN SHARE MODE来实现。在使用以上两种方式时所有扫描到的行都会被锁上,因此如果MySQL使用悲观锁时务必走索引,不然的话就会进行全表扫描,把整个表都锁住了。
乐观锁(Optimistic Lock)乐观锁认为数据一般情况下不会造成冲突,所以在提交更新的时候,才会对数据的冲突进行检测,如果发生锁冲突,则返回错误信息,由应用决定下一步如何去做。乐观锁需要应用自己去实现,不需要数据底层的支持,一般通过增加Version字段或者时间戳字段来实现。
----------------------------------------
原创不易,每篇文章都是作者工作之余熬夜整理与创作,如果觉得文章对您有帮助的话,关注、转发、分享、点在看都是对作者的一种鼓励,您的鼓励将是我持续发表高质量文章的最大动力。
关注MySQL
数据库技术栈
MySQL
往期推荐
【MySQL入门】之MySQL数据库的锁机制(一)
【MySQL入门】之MySQL数据库的锁机制(二)
MySQL是如何保证不丢数据的(一)
MySQL是如何保证不丢数据的(二)
-
datatables中的修改數據保存至mysql實例_MySQL是怎么读数据的——多版本并发控制...
2021-01-18 18:03:59求关注求转发 我在之前的文章中(【MySQL入门】之MySQL数据库的锁机制(一),【MySQL入门】之MySQL数据库的锁机制(二))介绍了MySQL的全局锁、表锁和行锁,今天我在来介绍下MySQL的一致性非锁定读、一致性锁定读。...求关注
求转发
我在之前的文章中(【MySQL入门】之MySQL数据库的锁机制(一),【MySQL入门】之MySQL数据库的锁机制(二))介绍了MySQL的全局锁、表锁和行锁,今天我在来介绍下MySQL的一致性非锁定读、一致性锁定读。再说之前我们先思考个问题,当我们用mysqldump进行逻辑备份时,如果有事务对表进行修改操作,那么我们备份出来的数据是否包含修改后的数据呢?如果mysqldump备份出的数据不包含之后修改的数据,那么他又是怎么保存之前的数据的呢?
一致性非锁定读(Consistent nonlocking reads)
一致性非锁定读也叫快照(snapshot read),是指当事务进行查询时,innodb存储引擎利用MVCC技术可以查看过去某个时间点的快照数据。查询可以看到别的事务在生成快照前提交的数据,而查看不到别的事务在生成快照之后提交或者未提交的数据。但是有一个例外,就是查询可以看到同一个事务中之前提交的数据,比如说事务开始时我做了一个查询id=1,紧接着我在当前事务中将id修改为2,那么当前事务再次查询时查到的id=2,也就是说我自己做的修改我还是要认的。
MVCC英文Multiversion Concurrency Control,翻译成中文是多版本并发控制,它的出现是为了提高数据库的并发能力,解决读-写冲突的无锁并发控制,它不需要等待要访问的行上的X锁的释放,可以读到数据之前的版本,实现了写不阻塞读以及可重复读。
MVCC主要是通过数据行的三个隐藏字段(DB_TRX_ID,DB_ROLL_PTR, DB_ROW_ID)、undo log和Read View来实现的。
三个隐藏字段InnoDB为数据库中存储的每一行增加了三个字段。
DB_TRX_ID:6字节,表示插入或者更新该行的最后一个事务的事务标识符。此外删除也被认为是一次更新,在行的一个特殊位置添加一个删除标记。
DB_ROLL_PTR:7字节,回滚指针指向被写在回滚段的undo log记录,如果数据行被修改,会将该行修改前的内容记录到undo log上。
DB_ROW_ID:6字节,我们在之前关于索引的文章中说过,如果表中没有显式的主键或者唯一索引,innodb会用DB_ROW_ID生成聚簇索引。
比如下图包含三个显式字段的一行数据:
UNDO 日志Undo log主要分为insert和update两种情况的日志,MVCC主要依赖的是update undo log(包含delete)。
首先我们要知道,每个事务都有一个唯一的事务ID,叫transaction id,它是在事务开始的时候向 InnoDB 的事务系统申请的,是按申请顺序严格递增的。每行数据也有自己的id,就是上面提到的DB_TRX_ID,每次事务更新数据的时候,都会生成一个新的数据版本,并且把 transaction id 赋值给这个数据版本的DB_TRX_ID,同时将上一版本的数据拷贝至undo log中,用DB_ROLL_PTR指针指向Undo log中的上一个版本数据。
还是上图的例子,我们假设事务1将name改为tom,接着事务2将age改为32,事务3将addr改为BeiJing,它的状态图如下:
从图中可以看出同一行数据总共有4个版本,当前最新的版本V4是被事务3修改的,所以他的DB_TRX_ID中存的是3,它的ROLL_PTR指针指向它上一个版本的数据,上一个版本是事务2修改,存放在undo log中的回滚段。这样就形成了一个版本链表,链首就是当前事务,链尾就是最早的记录,如果想找V2,就可以通过V4->V3->V2计算出V2来。
从这里也可以看出来,我们一定要消灭大事务,如果一个事务里有大事务,会导致undo log暴增而无法被purge。
Read ViewRead View 就是事务在使用MVCC机制进行快照读操作时产生的读视图(Read View),当事务启动时,会生成数据库系统当前的一个快照,InnoDB 为每个事务构造了一个数组,用来记录并维护系统当前活跃事务的ID(“活跃”指的就是,启动了但还没提交)。当该事务要读取某行记录时,innodb会将该行的当前版本号与数组中保存的版本号进行比较,来判断当前事务应该读取的行数据版本。
具体的算法规则如下(可RR隔离级别下):
假设当前事务要访问的数据行的版本T0,数组里面事务 ID 的最小值是T_min,当前系统里面已经创建过的事务 ID 的最大值记为T_max。
1. 当T0
2. 当T0>T_max时,表示这个版本是未来的某个事务生成的,数据肯定是不可见的。
3. 当T_min <= T0 <= T_max时,先看T0是否在read view数组中,
如果在数组中表示这个版本是由还没提交的事务生成的,数据不可见(自己更新的还是能看到的)。
如果不在数组中表示这个版本是由已经提交的事务生成的,数据可见。
再回到一开始我们说的问题,关于mysqldump工具的使用,其中有个参数—single-transaction,在RR隔离级别下,它表示在备份开始前,执行start transaction,把整个备份当成一个事务,直到备份结束,都不会读取到本事务开始之后提交的任何数据,在结合上面讲到的MVCC机制可以知道,它保存的并不是当前数据库的数据备份,而是当前事务的一致性视图(Read View)。
注意:以上是在RR隔离级别下的场景,在RC隔离级别下,对于一致性快照,总是读取被锁定行的最新一份快照数据,即只要数据被修改并且提交了,我就能看到最新的数据版本。
一致性锁定读(Locking Reads)
在同一个事务中如果你先查询然后再更新数据时,由于InnoDB引擎的select操作使用一致性非锁定读,其他事务可以修改或者删除刚才查询的行数据,这样就无法保证数据的一致性了。用户需要显式的对数据库读取操作进行加锁以保证数据逻辑的一致性。
InnoDB引擎对select语句支持两种一致性锁定读的操作:
1. SELECT ... LOCK IN SHARE MODE在要读取的行上加共享锁,在事务结束前其他事务可以读取这些行,但是不能修改。如果这些数据正在被其他事务修改,需要等待其他事务提交或者结束,然后获取最新的值。
2. SELECT ... FOR UPDATE对读取的行记录上加上X锁,其他事务不能在已锁定的行上加任何锁。
以上两种加锁模式必须在事务中,加锁前加上begin、start transaction或者set autocommit=0,当事务提交了,锁也就释放了。不管是在RC还是RR隔离级别下,普通的select操作使用的是快照读,不会对数据加锁,也不会被事务阻塞。
同时以上两种模式都是当前读(current read),它们读取到的是最新的数据,就是它们能看到其他事务提交后的数据。update、insert、delete也都是采用的当前读,会读取最新的记录,我们可以拿update来举个例子
对于t表,有两条数据,id为主键。
mysql> select * from t;+----+------+| id | k |+----+------+| 1 | 1 || 2 | 2 |+----+------+2 rows in set (0.00 sec)
我们开启一个会话A,查询下t表:
mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from t;+----+------+| id | k |+----+------+| 1 | 1 || 2 | 2 |+----+------+2 rows in set (0.00 sec)
开启会话B,对id=1的行执行k=k+1并提交,此时k=2
mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from t;+----+------+| id | k |+----+------+| 1 | 1 || 2 | 2 |+----+------+2 rows in set (0.00 sec)mysql> update t set k=k+1 where id=1;Query OK, 1 row affected (0.02 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql> select * from t;+----+------+| id | k |+----+------+| 1 | 2 || 2 | 2 |+----+------+2 rows in set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)
接着我们在会话A再执行update t set k=k+1 where id=1,大家觉得此时k等于多少呢?
mysql> update t set k=k+1 where id=1;Query OK, 1 row affected (0.00 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql> select * from t;+----+------+| id | k |+----+------+| 1 | 3 || 2 | 2 |+----+------+2 rows in set (0.00 sec)
从结果看k=3,这个例子也证明了update是当前读模式,它需要先拿到最新的数据然后再进行修改,如果会话B未提交的话,会话A只能等待会话B释放锁了。
悲观锁和乐观锁
悲观锁和乐观锁人们根据并发时对资源加锁的设计思路总结出来的概念,是一种加锁思想,不是真实存在的锁,是处理并发资源的常用手段。
悲观锁(Pessimistic Lock)悲观锁的特点是先获取锁,在进行业务操作,即悲观的认为我要修改的数据很有可能被其他事务锁住或者修改,因此我必须先确保锁成功之后再进行业务。
悲观锁主要是依靠数据库自身的锁机制实现,比如上面我们提到的一致性锁定读,其实就是用了悲观锁的思想。
MySQL的悲观锁通常用Select … for update和SELECT ... LOCK IN SHARE MODE来实现。在使用以上两种方式时所有扫描到的行都会被锁上,因此如果MySQL使用悲观锁时务必走索引,不然的话就会进行全表扫描,把整个表都锁住了。
乐观锁(Optimistic Lock)乐观锁认为数据一般情况下不会造成冲突,所以在提交更新的时候,才会对数据的冲突进行检测,如果发生锁冲突,则返回错误信息,由应用决定下一步如何去做。乐观锁需要应用自己去实现,不需要数据底层的支持,一般通过增加Version字段或者时间戳字段来实现。
----------------------------------------
原创不易,每篇文章都是作者工作之余熬夜整理与创作,如果觉得文章对您有帮助的话,关注、转发、分享、点在看都是对作者的一种鼓励,您的鼓励将是我持续发表高质量文章的最大动力。
关注MySQL
数据库技术栈
MySQL
往期推荐
【MySQL入门】之MySQL数据库的锁机制(一)
【MySQL入门】之MySQL数据库的锁机制(二)
MySQL是如何保证不丢数据的(一)
MySQL是如何保证不丢数据的(二)
-
mysql 快照读 当前读_mysql并发控制之快照读和当前读
2021-01-27 08:37:48上一篇简单的介绍了下MVCC(多版本并发控制)的原理,MVCC会对事物内操作的数据做多版本控制,从而实现并发环境下事物对数据写操作的阻塞不影响读操作的性能。而这个多版本控制的实现是由undo log来实现的,下面的内容...上一篇简单的介绍了下MVCC(多版本并发控制)的原理,MVCC会对事物内操作的数据做多版本控制,从而实现并发环境下事物对数据写操作的阻塞不影响读操作的性能。而这个多版本控制的实现是由undo log来实现的,下面的内容将会简单的介绍下undo log的内容。
mysql在事物开始操作数据之前,会先将原始数据备份到一个undo log的地方,这样做的目的有两个。第一是为了保证事物的原子性,如果事物在执行的过程中出现了某些错误,或者是用户执行了rollback的操作,mysql可以利用undo log中的备份将数据恢复到事物开始之前的状态。第二是为了实现多版本的并发控制,事物在提交之前,undo log中保存了未提交之前的数据版本,undo log可以作为旧版数据的快照供其他并发访问的事物实现快照读。
快照读:SQL读取的数据是快照版本,也就是历史版本,普通的select查询的就是快照。innodb存储引擎的快照读,读取的数据将由cache(原始数据)+undo(事物修改过的数据)两部分组成。
当前读:SQL读取的数据是最新版本,可以通过锁的机制来保证读取的数据无法被其它的事物修改。update,delete,insert,select ... lock in share mode,select ... for update都是当前读。
除了undo log,Mysql数据库还有一个redo log的概念,mysql在事物开始之后,事物中操作的任何数据,会将最新的数据备份到一个地方(redo log),就是在事物执行的过程中,开始将数据写入redo buffer中,最后写入redo log中,具体的落盘策略可以自行配置。这样做的目的是:为了实现事物的持久性,防止在发生故障的时间点,尚有脏页未写入磁盘,在mysql重启的时候,根据redo log重做,从而使事物未入磁盘的数据达到持久化这一特定。
说明:指定的redo log是记录在{datadir}/ib_logfile1&ib_logfile2,可以通过innodb_log_group_home_dir配置指定的目录存储。一旦事物提交成功,并且数据持久化落盘之后,redo log中的数据也就失去了意义,所以redo log中的写入是日志文件循环写入的。可以配置下列参数:
指定redo log日志文件组中的数量 innodb_log_files_in_group 默认为2
指定redo log每一个日志文件最大存储量innodb_log_file_size 默认48M
指定redo log在cache/buffer中的buffer池大小innodb_log_buffer_size 默认16M
redo log的落盘策略,即将数据从redo buffer持久化到磁盘的redo log文件中,可配置Innodb_flush_log_at_trx_commit参数,这个参数的取值有以下几种情况。
取值0,每秒提交redo buffer -> redo log os cache -> flush cache to disk,这种情况可能丢失一秒内的事物数据。
取值1,该参数的默认值,每次事物提交执行redo buffer -> redo log os cache -> flush cache to disk,这种情况可能丢失一个事物的数据,最安全,但同时性能最差。
取值2,每次事物提交执行redo buffer -> redo log os cache,在每一秒执行 -> flush cache to disk操作。
关于undo log和redo log,有下面的图可以参考。
说明:undo log和redo log可以理解为都是对数据的备份,其中undo log是对旧数据(原始数据)的备份,redo log是对新数据(事物所要提交的数据)的备份。对数据的备份首先是会存储在各自的buffer中,即undo buffer和redo buffer,至于如何持久化到磁盘,即写入到undo log和redo log文件中,要根据设置的具体落盘策略而定。
MySQL Transaction--快照读和当前读
在MySQL读取数据时可以按照是否使用一致性非锁定读来分为快照读和当前读:1.快照读:MySQL使用MVCC (Multiversion Concurrency Control)机制来保证被读取到数据 ...
MySQL 笔记整理(20) --幻读是什么,幻读有什么问题?
笔记记录自林晓斌(丁奇)老师的 (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 20) --幻读是什么,幻读有什么问题? 我们先来看看表结构和初始化数据 ...
InnoDB在MySQL默认隔离级别下解决幻读
1.结论 在RR的隔离级别下,Innodb使用MVVC和next-key locks解决幻读,MVVC解决的是普通读(快照读)的幻读,next-key locks解决的是当前读情况下的幻读. 2.幻读 ...
MYSQL事件隔离级别以及复读,幻读,脏读的理解
一.mysql事件隔离级别 1未提交读(READUNCOMMITTED) 另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据(脏读)( 隔离级别最低,并发性能高 ) 2 ...
五分钟详解MySQL并发控制及事务原理
在如今互联网业务中使用范围最广的数据库无疑还是关系型数据库MySQL,之所以用"还是"这个词,是因为最近几年国内数据库领域也取得了一些长足进步,例如以TIDB.OceanBase等 ...
SQL Server中STATISTICS IO物理读和逻辑读的误区
SQL Server中STATISTICS IO物理读和逻辑读的误区 大家知道,SQL Server中可以利用下面命令查看某个语句读写IO的情况 SET STATISTICS IO ON 那么这个命令 ...
初谈SQL Server逻辑读、物理读、预读
前言 本文涉及的内容均不是原创,是记录自己在学习IO.执行计划的过程中学习其他大牛的博客和心得并记录下来,之所以想写下来是为了记录自己在追溯的过程遇到的几个问题,并把这些问题弄清楚. 本章最后已贴出原 ...
ORACLE 物理读 逻辑读 一致性读 当前模式读总结浅析
在ORACLE数据库中有物理读(Physical Reads).逻辑读(Logical Reads).一致性读(Consistant Get).当前模式读(DB Block Gets)等诸多概念,如果 ...
SQL Server逻辑读、预读和物理读
SQL Server数据存储的形式 预读:用估计信息,去硬盘读取数据到缓存.预读100次,也就是估计将要从硬盘中读取了100页数据到缓存. 物理读:查询计划生成好以后,如果缓存缺少所需要的数据,让缓存 ...
随机推荐
Bootstrap_Datatable Ajax请求两次问题的解决
最近一个项目中使用JQuery Datatable,用起来比较方便,但在测试过程中,发现当条件改变时,有时查询结果中的数据不正确. 使用FireBug跟踪时,发现在使用Ajax请求时,点击一次搜索按钮 ...
BarManager.ContextMenu
onkeyup,onkeydown和onkeypress
如下一段代码:
js 比较日期大小
//1获取当前时间 var curTime = new Date(); //2把字符串格式转换为日期类 var startTime = new Date(Date.parse(kc.begintime ...
openStack centos6.4
http://repos.fedorapeople.org/repos/openstack/openstack-icehouse/epel-6/repodata/repomd.xml: [Errno ...
浅析node.js
大家好,今天来给大家讨论node.js这个东西,说起这个东西啊,可能大家已经很熟悉了,因为现在市场上运用的越来越广泛,毕竟它的优点还是有目共睹的! 那么,什么是node.js呢?官方给出了这样的定义: ...
Python之Django rest_Framework
Django Rest Framework 一.rest api a.api就是接口 如: - http://www.oldboyedu.com/get_user/ ...
Centos环境下给PHP7.0安装yaf扩展
首先要知道PHP的安装目录在哪里,以我当前的路径为例,在/usr/local/php目录下. 下一步需要下载扩展包,进入http://pecl.php.net/package/yaf寻找符合版本要求的 ...
[Swift]LeetCode917. 仅仅反转字母 | Reverse Only Letters
Given a string S, return the "reversed" string where all characters that are not a letter ...
Android总结篇系列:Activity中几个主要函数详解
Activity作为Android系统中四大基本组件之一,包含大量的与其他的各大组件.intent.widget以及系统各项服务等之间的交互的函数.在此,本文主要选取实际项目开发中常用的,但完全理解又 ...
-
多版本并发控制
2019-01-15 08:30:15多版本并发控制,讨论的不是指的一个软件同时发行多个版本怎么进行管理的问题,而是MySQL中的MVCC。 MVCC,multiple version concurrent control,多版本并发控制。 可以认为MVCC是行级锁的一个变种,但它在很多...多版本并发控制,讨论的不是指的一个软件同时发行多个版本怎么进行管理的问题,而是MySQL中的MVCC。
MVCC,multiple version concurrent control,多版本并发控制。
可以认为MVCC是行级锁的一个变种,但它在很多情况下避免了加锁操作,因此开销更低。虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行。
MVCC的实现,是通过保存数据在某个时间点的快照来实现的。也就是说,不管需要执行多长时间,每个事务看到的数据都是一致的。根据事务开始时间的不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。
前面说到了不同存储引擎的MVCC的实现是不同的,典型的有乐观并发控制和悲观并发控制。下面我们通过简化版行为来说明MVCC是如何工作的。
InnoDB的MVCC,是通过在每行后面保存两个隐藏的列来实现的。这两个列,一个保存了行的的创建时间,一个保存了行的过期时间(或删除时间)。当然,存储的并不是实际的时间,而是系统版本号。每开始一个新的事务,系统版本号会自动递增。事务开始时刻的系统版本号作为该事务的版本号,用来和查询到的行的版本号进行比较。
下面看一下在可重复读隔离级别下,MCVV的具体实现过程。
1,select
InnoDB会根据两个条件来检查每行记录。
a,InnoDB只查找版本早于当前事务版本号的行(也就是说,行的系统版本号,小于或等于当前事务的系统版本号),这样可以保证事务读取的行,要么是在事务开始之前已经存在的,要么是事务自身或者修改过的。
b,行的删除版本号要么未定义,要么大于当前事务版本号。这样可以保证,事务读取到的行,在事务开始之前未删除。
只有符合以上两个条件的数据,才会返回。
2,insert
InnoDB为插入的每一行数据保存当前的系统版本号作为行版本号。
3,delete
InnoDB为删除的每一行保存当前的系统版本号作为行的删除标志。
4,update
InnoDB插入一行新的数据,并保存当前的系统版本号作为新插入行的版本号,并且保存当前系统版本号到原来的行作为它的删除标志。
保存两个额外的系统版本号,使得大多数读操作都不用加锁。
MVCC只在可重复读和读已提交两个隔离级别下工作。其他两个隔离级别都与MVCC不兼容,因为读未提交总是读取最新的数据行,而不是符合当前事务版本的数据行。而串行化则会对所有读取的行进行加锁。
-
Java多线程编程核心技术读书笔记(2)-并发控制
2017-04-25 20:37:00并发编程其实解决的就是“非线程安全”的问题,是指多个线程对同一个对象中的实例变量进行并发访问时产生的“脏读”的情况,也就是取到的数据是被其他线程更改过的。Java对于解决并发问题提供了两个关键字供开发者... -
mysql 快照读隐藏列_mysql并发控制之快照读和当前读
2021-02-01 22:29:46上一篇简单的介绍了下MVCC(多版本并发控制)的原理,MVCC会对事物内操作的数据做多版本控制,从而实现并发环境下事物对数据写操作的阻塞不影响读操作的性能。而这个多版本控制的实现是由undo log来实现的,下面的内容... -
mysql并发控制之快照读和当前读
2019-04-11 23:37:00上一篇简单的介绍了下MVCC(多版本并发控制)的原理,MVCC会对事物内操作的数据做多版本控制,从而实现并发环境下事物对数据写操作的阻塞不影响读操作的性能。而这个多版本控制的实现是由undo log来实现的,下面的内容... -
mysql快照配置_mysql并发控制之快照读和当前读
2021-01-19 03:06:36上一篇简单的介绍了下MVCC(多版本并发控制)的原理,MVCC会对事物内操作的数据做多版本控制,从而实现并发环境下事物对数据写操作的阻塞不影响读操作的性能。而这个多版本控制的实现是由undo log来实现的,下面的内容... -
mysql事务多版本并发控制_[MySQL] MVCC多版本并发控制实现的事务
2021-01-20 03:36:381.没有一个统一的实现标准,实现了非阻塞的读操作,写操作也只锁定必要的行2.通过保存数据在某个时间点的快照实现的3.典型的有乐观并发控制和悲观并发控制4.innodb的mvcc是每次事务都有递增的版本号,通过在... -
mysql MVCC 多版本并发控制
2020-08-30 11:39:20MVCC是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。大多数的MVCC都实现了非阻塞的读操作,写操作也只锁定必要的行。 MVCC 多版本并发控制 概念 Multiversion concurrency control 多版本... -
并发控制
2013-06-20 20:54:26(1)事务是并发控制的基本单元。 (2)数据库中多个事务并发执行时,事务的隔离性和一致性可能会遭到破坏,DBMS需要对并发事务相互作用加以控制,即并发控制机制。 (3)并发操作带来的数据不一致性包括(T1和T2为事务): ... -
MySQL并发控制的类型_MySQL并发控制
2021-01-19 13:17:07并发即指在同一时刻,多个操作并行执行。...为了防止多个写操作共同执行破坏数据,写锁是排他的,一个写锁会阻塞其它的写锁和读锁,进而保证同一资源在任何时刻只有一个写操作在执行,并防止其它用户读取正在写... -
并发控制习题
2020-06-22 18:42:49数据库的一个明显的特点就是多个用户共享数据库资源,尤其是多用户可以同时存取相同的数据。在这样的系统中,在同一时刻并发运行的事务数可达数百个。若对事务的并发操作不加以控制,就会造成数据存、取得错误,破坏... -
MVCC 多版本并发控制【MySQL 篇】
2020-08-01 04:02:34假设事务 A 对表中的指定行数据进行更新,事务 B 对该表中的这几行数据进行读,这个时候为了保证并发控制事务 A 的更新操作会阻塞事务 B 的读操作,为了达到并发控制的目的,MySQL 使用了两种方案去实现:一种是基于... -
Mysql MVCC多版本并发控制
2019-02-06 17:34:00Multi-Version Concurrency Control,多版本并发控制,每次操作,copy一份所要改的数据作为副本,副本之间通过一个版本号字段区分,并将副本的版本号+1,如果是更新操作,数据在副本上修改完后,要更新时候查看原... -
PostgreSQL中的多版本并发控制
2018-01-24 22:46:43多版本并发控制的原理 在并发操作中,当正在写时,如果用户在读,可能会产生数据不一致的问题。比如一行的前半部分刚写入,后半部分还没有写入,这时读的人可能读取到的数据行,其前半部分数据是新的,后半部分数据... -
MVCC多版本并发控制机制详解
2020-08-30 22:45:55MVCC多版本并发控制机制 上节我们说到了事务的ACID特性和四种隔离级别,其中在可重复读级别下是如何保证事务较高的隔离性的?对,就是靠MVCC(Multi-Version ...undo日志版本链是指一行数据被多个事务依次修改过后, -
MySQL并发控制
2018-08-21 14:43:00并发即指在同一时刻,多个操作并行执行。...为了防止多个写操作共同执行破坏数据,写锁是排他的,一个写锁会阻塞其它的写锁和读锁,进而保证同一资源在任何时刻只有一个写操作在执行,并防止其它用... -
Mysql -(innodb)多版本多版本并发控制
2020-09-15 20:51:09MVCC是行级锁的一个变种,在很多情况下避免了加锁的操作,实现了非阻塞的读操作,写操作也只锁定必要的行。MVCC的实现,是通过保存数据在某个时间点的快照来实现的。 InnoDB的MVCC,是通过在每行记录后面保存两个... -
InnoDB多版本并发控制(MVCC)
2020-01-29 12:25:26可以认为MVVC是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低,虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只是锁定必要的行 MVCC的实现是通过保存数据在某个时间点的快照... -
MySQL 高级 —— MVCC 多版本并发控制
2020-06-27 18:42:00基于提升并发性能的考虑,它们一般都同时实现了多版本并发控制——MVCC。包括其他数据库如Oracle等,由于MVCC并没有一个统一的实现标准,因此它们的实现原理都不尽相同。 MVCC简介 可以认为MVCC是行级锁的一个变种... -
MySQL多事务并发控制
2017-12-28 17:12:54若两个事务A和B操作同一资源,A和B都通过begin开启事务后,若A只存在读操作,则B可以对数据进行写操作,且B的写操作不会影响A的读,即A每次读到的内容都是一致的(就算B已经提交)。 若A进行了写操作,则B的读操作不... -
数据库原理第十一章---并发控制
2020-05-28 10:37:56事务是并发控制的基本单位,保证事务的ACID特性是事务处理的重要任务,而事务的ACID破坏的可能原因之一是多个数据对事务的并发控制造成的。所以为了保证事务的一致性和隔离性,数据库系统需要对并发操作进行正确的... -
多版本并发控制(MVCC)
2018-05-17 20:53:10可以认为MVCC是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行。 MVCC的实现 MVCC的实现是通过保存数据在某个... -
多版本并发控制协议(Multiversion concurrency control) 简介
2016-09-28 00:15:21在并发领域,如果一个操作正在从数据库中读数据,同时另一个操作正在往数据库更新这个数据,那么读操作可能读到写了一半的数据或者不一致的数据。 有很多被称之为并发控制的方法来解决这个问题,最简单的方式... -
mysql 多事务_MySQL多事务并发控制
2021-03-03 20:16:00若两个事务A和B操作同一资源,A和B都通过begin开启事务后,若A只存在读操作,则B可以对数据进行写操作,且B的写操作不会影响A的读,即A每次读到的内容都是一致的(就算B已经提交)。若A进行了写操作,则B的读操作不受... -
mysql并发书籍_MySQL并发控制
2021-01-27 12:06:53并发即指在同一时刻,多个操作并行执行。...为了防止多个写操作共同执行破坏数据,写锁是排他的,一个写锁会阻塞其它的写锁和读锁,进而保证同一资源在任何时刻只有一个写操作在执行,并防止其它用户读取正在写... -
mysql - 第11课 - MVCC多版本并发控制机制原理 看了就懂
2020-08-09 00:54:30导图(用于总结和复习) MVCC (Multi-Version Concurrency Control)(多版本并发控制机制) Mysql在可重复度事务隔离级别下,同样的sql在同一事务下...但是实现原理不大一样,在读已提交级别是每次select生成一个..