数据库隔离级别

串行化(Serializable,SQLite默认模式):最高级别的隔离。两个同时发生的事务100%隔离,每个事务有自己的『世界』。

可重复读(Repeatable read,MySQL默认模式):每个事务有自己的『世界』,除了一种情况。如果一个事务成功执行并且添加了新数据,这些数据对其他正在执行的事务是可见的。但是如果事务成功修改了一条数据,修改结果对正在运行的事务不可见。所以,事务之间只是在新数据方面突破了隔离,对已存在的数据仍旧隔离。

举个例子,如果事务A运行”SELECT count(1) from TABLE_X” ,然后事务B在 TABLE_X 加入一条新数据并提交,当事务A再运行一次 count(1)结果不会是一样的。
这叫幻读(phantom read)。

读取已提交(Read committed,Oracle、PostgreSQL、SQL Server默认模式):可重复读+新的隔离突破。如果事务A读取了数据D,然后数据D被事务B修改(或删除)并提交,事务A再次读取数据D时数据的变化(或删除)是可见的。
这叫不可重复读(non-repeatable read)。
读未提交(Read uncommitted):最低级别的隔离,是读取已提交+新的隔离突破。如果事务A读取了数据D,然后数据D被事务B修改(但并未提交,事务B仍在运行中),事务A再次读取数据D时,数据修改是可见的。如果事务B回滚,那么事务A第二次读取的数据D是无意义的,因为那是事务B所做的从未发生的修改(已经回滚了嘛)。
这叫脏读(dirty read)。

#什么是当前读,快照读:
当前读
select lock in share mode( 共享锁),select for update ; update, insert ,delete( 排他锁) 这些操作都是⼀种当前读,为什么叫当前读? 就是它读取的是 记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进⾏加锁。

快照读
像不加锁的select 操作就是快照读,即不加锁的⾮阻塞读;

快照读的前提是隔离级别不是未提交读和串⾏化级别,因为未提交读总是读取最新的数据⾏,⽽不是符合当前事务版本的数据⾏。⽽串⾏化则会对所有读取的⾏都加锁

RC、RR级别下的INNODB的非阻塞读如何实现
我们在存储一条数据时,除了我们能看到的字段,其实mysql还给我们添加了许多的隐藏字段,比如与我们题目有关的字段:DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID字段,看他们的名字就能够大致知道是什么意思。

DB_TRX_ID:事务ID,每开启一个新事务,当前的事务id就自动加一,事务id越大,表明当前启动事务时间离当前时间越近。
DB_ROLL_PTR:回滚指针,比如当前事务去更新一条数据的时候,这条数据的回滚指针会指向undo log里最大的事务id的地址,也就是最新的undo日志
undo log是在一个事务中每进行一次增删改操作就形成的一条undo日志,它是用于在事务回滚是回到事务开启之前的版本。它也分为insert undo log和update undo log
DB_ROW_ID:行号,新行插入,对应行号,如果一个InnoDB表中的字段没有唯一索引和主键索引,InnoDB会自动生成隐藏自增主键字段(6个字节),也就是这个字段。
实现快照读除了用到上面的三个隐藏字段和undo日志,还需要一个read view,当我们去执行快照读的时候,针对我们读的数据会创建一个read view来决定我们读到的是哪个版本的数据,有可能是最新版本的数据,也有可能是undo日志里的某个版本的数据。read view遵循一个可见性算法,主要是将要修改的数据的DB_TRX_ID取出来与系统其它活跃事务ID作比较,如果大于等于这些ID,就通过DB_ROLL_PTR指针去取出undolog中的数据直到小于这些活跃事务ID为止,这样就能保证获取到的数据是当前事务可见的最稳定的版本。

在RR级别下,session在开启事务后的第一条快照读会创建一个快照,也就是read view,将当前系统中活跃的其他事务记录起来,此后,再调用这个read view,在RC级别下,在开启事务后每次调用快照读的情况下都会创建一个快照,这就是之前RC级别下快照读每次都能看到其他事务进行的最新的增删改,而在RR级别下如果首次使用快照读是在别的事务进行增删改之前调用的,此后即便别的事务做了增删改还是得不到最新数据的原因。所以在RR级别下,首次进行快照读的时机是很重要的。

DUPLICATE KEY UPDATE
语法如下:

INSERT INTO tablename(field1,field2, field3, ...) VALUES(value1, value2, value3, ...) ON DUPLICATE KEY UPDATE field1=value1,field2=value2, field3=value3, ...; 

这个语法的目的是为了解决重复性,当数据库中存在某个记录时,执行这条语句会更新它,而不存在这条记录时,会插入它。
该语句规则如下:如果你插入的记录导致一个UNIQUE索引或者primary key(主键)出现重复,那么就会认为该条记录存在,则执行update语句而不是insert语句,反之,则执行insert语句而不是更新语句。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值