MVCC:修订间差异
imported>Soleverlee 以“=MVCC简述= Multi-Version Concurrency Control 多版本并发控制 在并发读写数据库时,读操作可能会不一致的数据(脏读)。为了避免...”为内容创建页面 |
|||
(未显示2个用户的3个中间版本) | |||
第2行: | 第2行: | ||
Multi-Version Concurrency Control 多版本并发控制 | Multi-Version Concurrency Control 多版本并发控制 | ||
在并发读写数据库时,读操作可能会不一致的数据(脏读)。为了避免这种情况,需要实现数据库的并发访问控制,最简单的方式就是加锁访问。由于,加锁会将读写操作串行化,所以不会出现不一致的状态。但是,读操作会被写操作阻塞,大幅降低读性能。在Java | 在并发读写数据库时,读操作可能会不一致的数据(脏读)。为了避免这种情况,需要实现数据库的并发访问控制,最简单的方式就是加锁访问。由于,加锁会将读写操作串行化,所以不会出现不一致的状态。但是,读操作会被写操作阻塞,大幅降低读性能。在Java concurrent包中,有<span class="article-label">copyonwrite</span>系列的类,专门用于优化读远大于写的情况。而其优化的手段就是,在进行写操作时,将数据copy一份,不会影响原有数据,然后进行修改,修改完成后原子替换掉旧的数据,而读操作只会读取原有数据。通过这种方式实现写操作不会阻塞读操作,从而优化读效率。而写操作之间是要互斥的,并且每次写操作都会有一次copy,所以只适合读大于写的情况。 | ||
MVCC的原理与copyonwrite类似,全称是Multi-Version Concurrent Control,即多版本并发控制。在MVCC协议下,每个读操作会看到一个一致性的snapshot,并且可以实现非阻塞的读。MVCC允许数据具有多个版本,这个版本可以是时间戳或者是全局递增的事务ID,在同一个时间点,不同的事务看到的数据是不同的。 | MVCC的原理与copyonwrite类似,全称是Multi-Version Concurrent Control,即多版本并发控制。在MVCC协议下,每个读操作会看到一个一致性的snapshot,并且可以实现非阻塞的读。MVCC允许数据具有多个版本,这个版本可以是时间戳或者是全局递增的事务ID,在同一个时间点,不同的事务看到的数据是不同的。 | ||
=MySQL MVCC= | =MySQL MVCC= | ||
mysql的innodb采用的是行锁,而且采用了多版本并发控制来提高读操作的性能。在每一行记录的后面增加两个隐藏列,记录创建版本号和删除版本号,而每一个事务在启动的时候,都有一个唯一的递增的版本号。 | mysql的innodb采用的是行锁,而且采用了多版本并发控制来提高读操作的性能。在每一行记录的后面增加两个隐藏列,记录创建版本号和删除版本号,而每一个事务在启动的时候,都有一个唯一的递增的版本号。 | ||
==插入== | |||
在插入操作时 : 记录的创建版本号就是事务版本号。 | |||
比如我插入一条记录, 事务id 假设是1 ,那么记录如下:也就是说,创建版本号就是事务版本号。 | 比如我插入一条记录, 事务id 假设是1 ,那么记录如下:也就是说,创建版本号就是事务版本号。 | ||
{| class="wikitable" border="1" | |||
|- | |||
1 | | id | ||
| name | |||
| create version | |||
| delete version | |||
|- | |||
| 1 | |||
| test | |||
| 1 | |||
| | |||
|} | |||
==更新== | |||
在更新操作的时候,采用的是先标记旧的那行记录为已删除,并且删除版本号是事务版本号,然后插入一行新的记录的方式。 | |||
比如,针对上面那行记录,事务Id为2 要把name字段更新 | 比如,针对上面那行记录,事务Id为2 要把name字段更新 | ||
<source lang="sql"> | |||
update table set name= 'new_value' where id=1; | update table set name= 'new_value' where id=1; | ||
</source> | |||
{| class="wikitable" border="1" | |||
|- | |||
| id | |||
| name | |||
| create version | |||
| delete version | |||
|- | |||
| 1 | |||
| test | |||
| 2 | |||
| 2 | |||
|- | |||
| 1 | |||
| xxxx | |||
| 2 | |||
| | |||
|} | |||
==删除== | |||
删除操作的时候,就把事务版本号作为删除版本号。比如 | |||
<source lang="sql"> | |||
delete from table where id=1; | delete from table where id=1; | ||
</source> | |||
{| class="wikitable" border="1" | |||
|- | |||
| id | |||
| name | |||
| create version | |||
| delete version | |||
|- | |||
| 1 | |||
| xxxx | |||
| 2 | |||
| 3 | |||
|} | |||
[[Category:MySQL]] | |||
[[Category:Database]] | |||
[[Category: |
2023年12月19日 (二) 09:14的最新版本
MVCC简述
Multi-Version Concurrency Control 多版本并发控制
在并发读写数据库时,读操作可能会不一致的数据(脏读)。为了避免这种情况,需要实现数据库的并发访问控制,最简单的方式就是加锁访问。由于,加锁会将读写操作串行化,所以不会出现不一致的状态。但是,读操作会被写操作阻塞,大幅降低读性能。在Java concurrent包中,有copyonwrite系列的类,专门用于优化读远大于写的情况。而其优化的手段就是,在进行写操作时,将数据copy一份,不会影响原有数据,然后进行修改,修改完成后原子替换掉旧的数据,而读操作只会读取原有数据。通过这种方式实现写操作不会阻塞读操作,从而优化读效率。而写操作之间是要互斥的,并且每次写操作都会有一次copy,所以只适合读大于写的情况。
MVCC的原理与copyonwrite类似,全称是Multi-Version Concurrent Control,即多版本并发控制。在MVCC协议下,每个读操作会看到一个一致性的snapshot,并且可以实现非阻塞的读。MVCC允许数据具有多个版本,这个版本可以是时间戳或者是全局递增的事务ID,在同一个时间点,不同的事务看到的数据是不同的。
MySQL MVCC
mysql的innodb采用的是行锁,而且采用了多版本并发控制来提高读操作的性能。在每一行记录的后面增加两个隐藏列,记录创建版本号和删除版本号,而每一个事务在启动的时候,都有一个唯一的递增的版本号。
插入
在插入操作时 : 记录的创建版本号就是事务版本号。
比如我插入一条记录, 事务id 假设是1 ,那么记录如下:也就是说,创建版本号就是事务版本号。
id | name | create version | delete version |
1 | test | 1 |
更新
在更新操作的时候,采用的是先标记旧的那行记录为已删除,并且删除版本号是事务版本号,然后插入一行新的记录的方式。
比如,针对上面那行记录,事务Id为2 要把name字段更新
update table set name= 'new_value' where id=1;
id | name | create version | delete version |
1 | test | 2 | 2 |
1 | xxxx | 2 |
删除
删除操作的时候,就把事务版本号作为删除版本号。比如
delete from table where id=1;
id | name | create version | delete version |
1 | xxxx | 2 | 3 |