参考来源:MySQL(二)|深入理解MySQL的四种隔离级别及加锁实现原理-腾讯云开发者社区-腾讯云 (tencent.com)
事务解释:
事务就是将对数据库的多个操作融合为一个整体,利用事务的特性来保证操作的安全一致性
(事务内要么全部执行 要么全部都不执行,执行过程中一旦出现错误那么回溯到执行前的数据)
事务:
一般指要做或所做的事情
计算机术语中指:访问并可能更新数据库中各种数据项的一个程序执行单元
个人理解2024/7/1:
将执行同一目的地原本并联分散调用数据库改为串联式执行,并且如果中途出现错误将数据库回溯到执行前的数据;
原子性(atomicity):
事务的原子性确保动作要么全部完成要么完全不起作用
一致性(consistency):
一个事务执行之前后都必须处于一致性状态(无论运行成功与否都不能改变数据的完整性)
隔离性(isolation):
每个事务之间相互隔离互不影响,防止数据损坏
持久性/永久性(durability):
一旦事务完成并提交,事务的结果永久写入数据库中,其它操作或故障都不应该使其受到影响
并发问题:
脏读:读取到其他事务未提交的数据
不可重复读:同一事务中多次读取的数据内容不同,重点在于update和delete
幻读:同一事务中多次读取的数据数量不同,幻读的重点在于insert
解决:
read uncommited(读取未提交内容):完全并联,性能最优但并不比其他好多少
任何操作都不会加锁
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。
读取未提交的数据,也被称之为脏读(Dirty Read):脏读幻读 不可重复都能发生
read committed(读取提交内容):并联+级串联,不会读取事务未提交的数据
数据的写入、修改和删除是加锁的
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。
它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。
可解决脏读,无法解决不可重复读和幻读。
repeatable read(可重读):并联+级串联,同一事务中多次读取的数据保持一致
乐观锁,Next-Key锁
这是MySQL的默认事务隔离级别,
同一事务的多个实例在并发读取数据时,会看到同样的数据。
不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。
可解决脏读、不可重复读
serializable(可串行化):完全串联,事务排队一个一个执行
读加共享锁,写加排他锁,读写互斥。使用的悲观锁的理论
这是最高的隔离级别,
它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。
简言之,它是在每个读的数据行上加上共享锁。
在这个级别,可能导致大量的超时现象和锁竞争(读锁写锁互斥等),
并且极大的降低数据库并发能力
可解决脏读、不可重复读、幻读。
关于锁:
在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。我们的数据库锁,也是为了构建这些隔离级别存在的。
个人理解2024/7/1:
:锁是为了保证当前事务影响的数据不被其他事务干涉而加锁.
:锁表不意味着其他事务无法添加行,所以会导致幻读的产生
-
表锁:
表锁是对一整张表加锁,虽然可分为读锁和写锁,但毕竟是锁住整张表,会导致并发能力下降,一般是做ddl处理时使用。
-
行锁:
行锁则是锁住数据行,这种加锁方法比较复杂,但是由于只锁住有限的数据,对于其它数据不加限制,所以并发能力强,MySQL一般都是用行锁来处理并发事务
-
悲观锁:
它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
-
乐观锁:
MVCC的实现没有固定的规范,每个数据库都会有不同的实现方式
通过MVCC机制,虽然让数据变得可重复读,但我们读到的数据可能是历史数据,是不及时的数据,不是数据库当前的数据!这在一些对于数据的时效特别敏感的业务中,就很可能出问题。
例如:历史读/快照读(select * from table ....)和当前读(where ? lock in share mode...)
InnoDB的MVCC:
乐观锁机制采取了更加宽松的加锁机制。大多是基于数据版本 (Version) 记录机制实现。即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
MVCC在MySQL的InnoDB中的实现:
在InnoDB中,会在每行数据后添加两个额外的隐藏的值(Version+版本迭代号)来实现MVCC,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时过期(或者被删除)。 在实际操作中,存储的并不是时间,而是事务的版本号,每开启一个新事务,事务的版本号就会递增。
在可重读Repeatable reads事务隔离级别下:
SELECT时:读取创建版本号<=当前事务版本号,删除版本号为空或>当前事务版本号。
INSERT时:保存当前事务版本号为行的创建版本号。
DELETE时:保存当前事务版本号为行的删除版本号。
UPDATE时:插入一条新纪录,保存当前事务版本号为行创建版本号,同时保存当前事务版本号到原来删除的行。
通过MVCC,虽然每行记录都需要额外的存储空间,更多的行检查工作以及一些额外的维护工作,但可以减少锁的使用,大多数读操作都不用加锁,读数据操作很简单,性能很好,并且也能保证只会读取到符合标准的行,也只锁住必要行。
-
间隙锁GAP:
GAP锁防止别的事务新增
-
Next-Key锁:
行锁防止别的事务修改或删除,GAP锁防止别的事务新增
行锁和GAP锁结合形成的的Next-Key锁共同解决了RR级别在写数据时的幻读问题。
----------其中多为自我理解进行总结,可能会有错误,仅供参考---------