数据库理论之并发下的错误和隔离级别

可能出现的问题

丢失更新:两个事务同时修改一个数据,一个覆盖另一个。

  • 比如事务T1:10 - 1 和 T2:10 - 2 并发执行,T2的结果覆盖T1,得到8,或者T1覆盖T2,得到9。

污读:事务T1更新了数据R,T2读了R,T1回滚,T2得到的数据和数据库不一致了

不可重读:事务T1读取了数据R,T2读取并更新了数据R,T1再次读取R发现两次读取不一致。

幻读:事务T1在读取某个范围的记录时,T2在该范围内插入了一条记录,T1再次读取到这一范围时,产生幻行。

锁类型

X锁(排他型封锁Exclusive Lock,写封锁)

  • 禁止一切并发操作,其他事务需要等解锁之后在执行

S锁(共享型封锁Share Lock, 读封锁)

  • 允许其他事务对同一对象查询,但不能对该数据对象修改

封锁协议

一级封锁协议:在事务修改数据对象时加X锁,直到事务结束。 解决丢失更新的问题。

二级封锁协议:一级封锁协议 + 事务在读时加S锁,读完释放S锁。防止污读

三级封锁协议:一级封锁协议 + 事务在读时加S锁,读完不释放S锁,事务结束后才释放。防止污读不可重读

四种隔离级别

Read Uncommitted(未提交读):事务中的修改,即使没有提交,对别的事务也是可见的。

Read Committed(提交读):只能看到已经提交的事务做出的修改。

Repeatable Read(可重复读):解决污读和不可重读,理论上无法解决幻读的问题,但实际上InnoDB使用了多版本并发控制(MVCC multi version concurrency control)解决了幻读的问题。是MySQL的默认隔离级别。

Serializable(可串行):强制使事务串行执行。

隔离级别可能污读可能不可重读可能幻读加锁读
Read Uncommitted
Read Committed
Repeatable Read
Serializable

MVCC是通过保存数据在某个时间点的快照实现的,也就是说,不管一个事务执行多长时间,该事务看到的数据都是一致的,而开始时间不同的事务,同一时刻看到的同一张表可能不同。

InnoBD的MVCC是通过每行记录后面隐藏的两个列实现的,这两个列一个是创建时间,一个是过期时间(或删除时间),储存的不是实际的时间,而是系统版本号,每开始一个新事务,系统版本号就会自动递增。

具体实现:

  • select:只查找版本号小于当前事务版本的数据行,且过期时间为空或大于当前事务版本。
  • insert:为插入的每一行都保存当前版本号作为行版本号
  • delete:为删除的每一行都保存当前版本号作为行删除标识
  • update:插入一条新记录,保存当前版本号为行版本号,保存当前版本号为原来行的删除标识(相当于insert + delete)

加了这两列(这两个版本号)使得大多数读操作都不需要加锁!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值