0
点赞
收藏
分享

微信扫一扫

【 React 】React JSX 转换成真实DOM的过程?

千白莫 03-20 07:00 阅读 2

MySQL的事务隔离级别及特性如下:

SERIALIZABLE(串行化):无问题,性能差;
REPEATABLE-READ(可重复读):幻读,默认隔离级别;
READ-COMMITTED(已提交读):不可重复读&幻读;
READ-UNCOMMITTED(未提交读):脏读&不可重复读&幻读。

串行化就是事务按顺序执行,没有并行,自然也就没有问题。但是性能就会比较差;
可重复读是MySQL默认的隔离级别,就是一个事务中多次读取数据,读到的数据都是一致的,不受其他事务修改的影响;
已提交读就是可以读到其他事务已经提交的数据,所以就没有了可重复读的特性;
未提交读能读到其他事务已执行但是未提交的数据,这就会产生脏读。

数据库事务隔离级别的查看和修改

-- 查看(5.7)
select @@global.tx_isolation;
select @@tx_isolation;
-- 查看(8)
select @@global.transaction_isolation;
select @@transaction_isolation;
-- 修改
set session transaction isolation level serialiable/repeatable read/……

可重复读出现幻读的情况

A事务:

start transaction;
select * from table where id = 2; //此时表中无id为2的数据

B事务:

start transaction;
insert into table(id, name) values(2, 'Wang');
commit;

A事务:

select * from table where id = 2; // 此时虽然表中已经有了,但是由于可重复读的特性,同一事务读到的数据是一致的,所以还是读不到
insert into table(id, name) values(2, 'Wang'); //报错
commit;

已提交读出现不可重复读的情况

A事务:

start transaction;
select * from table where id = 2; // 此时可以看到2的name是'Wang'

B事务:

start transaction;
update table set name = 'Yan' where id = 2;
commit;

A事务:

select * from table where id = 2; // 此时2的name变成了'Yan',这样就出现了不可重复度的问题
commit;

已提交读出现幻读的情况

A事务:

start transaction;
select * from table where id = 3; // 此时没有id为3的数据,

B事务:

start transaction;
insert into table(id, name) values(3, 'Li'); // 只插入不提交

A事务:

select * from table where id = 3; // 此时还是读不到3的数据
insert into table(id, name) values(3, 'Li'); // 此时插入数据就会有问题,因为B事务还没提交,但是已经执行了,A事务只能等待,看B事务是回滚还是提交

未提交读出现不可重复读和脏读的情况

A事务:

start transaction;
select * from table where id = 2; // 此时读到2的name为'Yan'

B事务:

start transaction;
update table set name = 'Sun' where id = 2; // 只执行不提交

A事务:

select * from table where id = 2; // 此时读到2的name为'Sun',这就已经出现了不可重复读。假设B事务现在回滚了,那么这个数据就是错的,就出现了脏读。

为提交读出现幻读的情况

A事务:

start transaction;
select * from table; // 查出全表数据为[1-'Wu'], [2-'Sun'], [3-'Li']

B事务:

delete from table where id = 3; // 删除了但是没提交

A事务:

select * from table; // 查出全表数据为[1-'Wu'], [2-'Sun'],查到3被删除了。此时B事务回滚,数据3又出来了,一会有一会没有,就出现了幻读。

MVCC

MVCC即多版本并发控制(Multi-Version Concurrent Control)。
使用可重复读和已提交读这两种隔离级别时,SELECT操作版本链的过程。

MySQL数据行中存在隐藏的3个列:row_id、trx_id、roll_pointer
row_id如果表中有主键,或者有非NULL唯一键,就不需要row_id。没有则会自动生成6个字节的row_id。
trx_id为事务id,每次开启事务都会生成,记录在数据行中。
roll_pointer则是会指向undo_log中的上一次更新的数据。更新多次就会形成版本链。

SELECT操作会生成ReadView,已提交读同一个事务中对相同数据的查询每次SELECT都会生成一个,而可重复读一个事务多个SELECT只会生成一个ReadView。
ReadView中有m_ids、min_trx_id、max_trx_id、creator_trx_id。
m_ids:生成ReadView时所有未提交的事务id。
min_trx_id:m_ids的最小值。
max_trx_id:生成ReadView时,系统应该分配给下一个事务的事务id。
creator_trx_id:生成ReadView的事务的事务id,如果只有SELECT则为0。

当SELECT生成ReadView后,从当前B+树中的数据开始查,顺着版本链从上往下查,知道找到ReadView生成前提交的最新记录,返回即可。有以下几种情况:

  1. 被访问数据的事务id小于min_trx_id,返回。
  2. 被访问数据的事务id大于等于max_trx_id,不返回。
  3. 被访问数据的事务id在m_ids中,不返回。
  4. 被访问数据的事务id在min_trx_id和max_trx_id之间,且不在m_ids中,返回。

已提交读举例

有数据[1-Wang], [2-Yan], [3-Li],插入事务id均为80。
A事务id为100更新1 = Sun,不提交。
B事务id为200更新其他表,不提交。
C事务读id为1的数据,生成ReadView,m_ids=[100, 200],min_trx_id=100, max_trx_id=201,creator_trx_id=0。
这时就该从版本链中开始寻找数据:

A事务提交。
B事务更新1 = Liu,不提交。
C事务读id为1的数据,再次生成ReadView,m_ids=[200],min_trx_id=200,max_trx_id=201,creator_trx_id=0。
从版本链中开始寻找数据:

可重复读举例

有数据[1-Wang], [2-Yan], [3-Li],插入事务id均为80。
A事务id为100更新1 = Sun,不提交。
B事务id为200更新其他表,不提交。
C事务读id为1的数据,生成ReadView,m_ids=[100, 200],min_trx_id=100, max_trx_id=201,creator_trx_id=0。
这时就该从版本链中开始寻找数据:

A事务提交。
B事务更新1 = Liu,不提交。
C事务读id为1的数据,由于是可重复读隔离级别,所以不再生成新的ReadView,还是用之前的,m_ids=[100, 200],min_trx_id=100, max_trx_id=201,creator_trx_id=0。
从版本链中开始寻找数据:

举报

相关推荐

0 条评论