Mysql是如何用每个隔离级别去解决对应的问题?

1.Mysql的innodb引擎,数据库表会自动增加三个字段(记录当前事务的版本号,记录删除时事务版本号,记录回滚指针地址)

2.数据库锁分为性质分为两类,悲观锁和乐观锁,共享锁(S锁)和排它锁(X锁)属于悲观锁,MVCC属于乐观锁(依靠事务的版本控制)

3.事务A对某行数据增加共享锁的时候,事务B可以继续增加共享锁,但是不能再增加排它锁,要等待所有共享锁都释放之后才能获加锁成功。当一个数据被加上排他锁之后,不能再加任何类型的锁,直到事务结束释放锁

4.read uncommitted级别下,数据库查询和更新数据库的时候都使用行级共享锁,所以就算没有提交,其他事务也能对当前数据加共享锁进行读取数据,导致脏读。

5. read committed级别下,数据库读取数据时使用共享锁,在更新数据时使用排它锁,提交完之后再释放排它锁,这样就解决了脏  读问题

6.reapetable read级别下用MVCC(多并发版本控制)解决了不可重复读问题,数据每次更新的时候,都会在数据行的隐藏字段中记录当前事务的版本号,当A事务第一次读取数据完之后未提交,此时版本号为1,期间事务B更新了该数据,并把版本号更改为2并提交,事务A再次读取时只会读取小于等于当前版本号的数据,不会读取到B事务的数据

7.Mysql的innodb引擎默认reapetable read级别,在该级别下MVCC能不能解决幻读呢?不能的话要如何解决幻读问题呢?

幻读是指多事务并发中一个事务读到了另一个事务insert的记录。

前提知识:

快照读:select操作(不包含select ...for update, select ..lock in share mode)

当前读:update,insert,delete,select ...for update, select ..lock in share mode

假设有如下场景:

# 表结构如下
CREATE TABLE hero (
    number INT,
    name VARCHAR(100),
    country varchar(100),
    PRIMARY KEY (number),
    KEY idx_name (name)
) Engine=InnoDB CHARSET=utf8;
# 事务T1,REPEATABLE READ隔离级别下
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM hero WHERE number = 30;
Empty set (0.01 sec)
# 此时事务T2执行了:INSERT INTO hero VALUES(30, 'g关羽', '魏'); 并提交
mysql> UPDATE hero SET country = '蜀' WHERE number = 30;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> SELECT * FROM hero WHERE number = 30;
+--------+---------+---------+
| number | name    | country |
+--------+---------+---------+
|     30 | g关羽   | 蜀      |
+--------+---------+---------+
1 row in set (0.01 sec)
在REPEATABLE READ隔离级别下,T1第一次执行普通的SELECT语句时生成了一个ReadView,之后T2向hero表中新插入了一条记录便提交了,ReadView并不能阻止T1执行UPDATE或者DELETE语句来对改动这个新插入的记录(因为T2已经提交,改动该记录并不会造成阻塞),但是这样一来这条新记录的trx_id隐藏列就变成了T1的事务id,之后T1中再使用普通的SELECT语句去查询这条记录时就可以看到这条记录了,也就把这条记录返回给客户端了。因为这个特殊现象的存在,你也可以认为InnoDB中的MVCC并不能完完全全的禁止幻读。

总结:在RR模式下,快照读是通过MVCC和undo log来实现的,当前读是通过行锁+间隙锁来实现的

解决方案:在该级别下只能用行锁+间隙锁=next-key锁去解决幻读,具体操作如下:

间隙锁:间隙锁主要用来防止幻读,用在repeatable-read隔离级别下,指的是当对数据进行条件,范围检索时,对其范围内也许并存在的值进行加锁!当查询的索引含有唯一属性(唯一索引,主键索引)时,Innodb存储引擎会对next-key lock进行优化,将其降为record lock,即仅锁住索引本身,而不是范围!若是普通辅助索引,则会使用传统的next-key lock进行范围锁定!

幻读案例:有个表 (id 字段为非唯一辅助索引)每次插入前需查询这字段的最大值,然后再取最大值+1插入!

事务1事务2
开启事务开启事务

select max(id) from e; 

result:10

insert into e values (11);

commit;

insert into e values (11);

commit;

报错:ERROR 1062 (23000): Duplicate entry '11' for key 'id'

 

 

在上述事务1中明明查询最大值为10,但插入最大值+1的时候却报错!

解决方案:利用mysql间隙锁

事务1事务2
开启事务开启事务

select max(id) from e lock in share mode; 

(此时会对id为10以上的所有不存在的值加间隙锁或共享锁)

result:10

insert into e values (11);

commit;

尝试加排他锁

此时提交会一处于等待状态

在运用间隙锁的过程中,(-00 +00为负正无穷大)

如果条件为where a=5这样的条件,则间隙锁锁住的范围为(-00,3),(3,5),(5,6),(6,9),(9,+00)  

如果条件为where a>5,则间隙锁锁住的范围为(5,+00)

如果为select max(id),则锁住的范围为(max(id),+00)

8.Serializable级别下,每个事务排队执行,可以解决四个问题

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MySQL 的事务隔离级别底层实现是通过锁机制来实现的。MySQL 支持四种隔离级别:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。不同隔离级别会采用不同的锁机制,以保证在并发事务执行时数据的一致性和正确性。 在读未提交隔离级别下,一个事务可以读取其他事务未提交的数据,因为这些数据还没有被提交到数据库中。在这个级别下,MySQL 并不使用任何锁机制来保证数据的一致性和正确性。 在读已提交隔离级别下,一个事务只能读取其他事务已经提交的数据。在这个级别下,MySQL 会使用读锁和写锁来保证数据的一致性和正确性。 在可重复读隔离级别下,一个事务在执行期间多次读取同一行数据时,会读取到同样的结果。在这个级别下,MySQL 会使用行级锁来保证数据的一致性和正确性。 在串行化隔离级别下,所有事务会被序列化执行,每个事务只能等待前一个事务完成后才能开始执行。在这个级别下,MySQL 会使用表级锁来保证数据的一致性和正确性。 ### 回答2: MySQL的事务隔离级别的底层实现主要涉及以下几个方面: 1. 锁机制:MySQL使用锁机制来实现事务隔离级别。当一个事务对数据库中的某个数据进行修改时,会对该数据的行或表进行加锁,其他事务需要访问该数据时,必须先获得相应的锁才能执行操作。不同隔离级别使用不同的锁机制,如读未提交级别使用行级锁,读已提交级别使用快照读和间隙锁,可重复读级别使用多版本并发控制(MVCC)等。 2. MVCC:MySQL中的可重复读和序列化隔离级别使用了MVCC机制。MVCC通过为每个事务分配唯一的事务ID,并在每次数据更新时创建一个对应的版本,并在读取数据时根据事务ID和版本号来确定读取的数据。这种机制可以保证读取到的数据是事务开始时的一致状态,避免了脏读、不可重复读和幻读等问题。 3. 读写和提交锁:MySQL使用读写锁和提交锁来实现不同隔离级别的并发控制。读写锁用于控制读取和修改数据的操作,它允许并发读取操作,但只允许在没有其他读取或写入操作时进行数据的修改。提交锁用于控制事务的提交顺序,只有在前一个事务提交后,下一个事务才能提交。 总而言之,MySQL的事务隔离级别的底层实现主要依赖于锁机制、MVCC机制和读写提交锁等技术,通过这些技术来实现对数据的并发控制和隔离,确保事务的一致性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值