数据库村的旺财和小强

通过旺财和小强的故事,讲述了数据库中常见的事务隔离级别问题,包括丢失修改、脏读、不可重复读及幻读等问题,并介绍了如何通过X锁和S锁解决这些问题。

丢失的数据

旺财是数据库村的一个程序,小强也是。

数据库村有个特点,很多数据支持共享操作,多个程序可以同时读写,他们俩经常会为了读写同一个数据,争夺的不可开交。

这一天,当旺财和小强对同一个银行账户A进行写操作时候, 出现了这么一个错误:

看看, 本来旺财要加上的20元就丢掉了。

同样的事情发生的多了, 他俩给这种情况起了一个名字,叫“丢失修改”, 其实说白了就是俩人都去写一个数据, 一个人的数据把另外一个给覆盖了。

村里的Mysql说: “你们两个小家伙,写数据的时候连加锁都不做,肯定会出大乱子!"

旺财说:“加什么锁?”

“来来来, 我教你们一个排他锁(Exclusive Lock) , 简称X锁, 旺财你要写数据了, 就把它用X锁锁住, 锁住后,除非你释放, 否则小强无法获得X锁。 这不就解决你们的问题了? ”

小强想了想, 就把上面的操作过程用X锁改了一下:

旺财说:“果然不错, 确实可以解决两个人同时修改导致的问题。”

脏数据

小强说:“旺财, 我们约定,写数据的时候都用X锁吧?”

旺财说: “这没问题, 可是X锁只在写数据的时候用, 我们读数据是不用加锁的, 我想起了一种情况, 你看看怎么办?”

小强在旺财执行的途中读了A的值, 但是旺财把对A的修改给回滚(Rollback)了, 这下小强尴尬了, 他读到了脏数据

“要不我们在读取数据的时候也加个X锁 ? ” 小强说。

“那样太严格了, 就是读一个数据啊, 值得吗?”

“这样吧, 我们再搞一个新的锁出来, 专门用于共享数据的读取, 就叫共享锁(Share lock) ,简称S锁, 这个锁和之前的排他锁X锁有区别, 主要用于读取数据, 如果一个数据加了X锁, 就没法加S锁, 同样加了S锁, 就没法加X锁” 小强想出了一个点子。

“那如果我加了S锁, 你还能加S锁吗? ” 旺财问。

“应该可以吧, 咱们俩都是读数据, 互不影响啊。 还有为了防止长时间的锁住, 我们可以约定一下,不管我们要做的事情有多少, 读一个数据之前加S锁, 读完之后立刻释放该S锁! ”

果然,这样一来“脏数据”的问题就解决了 !

没法重复读?

旺财和小强两个程序相安无事了很久, 但是S锁在读完数据后立刻释放的约定, 导致出了一个新问题。

旺财在一次数据处理中, 先读取了A和B的值, 相加得到了150 , 然后小强把B改成了30

旺财再次读取A和B, 发现求和以后是130 , 刚才的不一样了!

(码农翻身注: 假定旺财的处理是在一个事务当中)

旺财说: “小强, 我在读取数据的时候你不能改啊 , 要不然我这里会出现不一致, 你看刚开始是A+B是 150, 现在变成130了”

小强说: “我们之前的约定是读数据时加S锁, 读完立马释放, 问题就出现在这里了。”

“看来在读数据的时候, 也需要一直锁定了, 直到事务提交。”

幻觉出现

旺财和小强现在已经能灵活的使用X锁和S锁了。

他们俩总结了一下, 分为了这么几种情况:

1. 写数据时加上X锁,直到事务结束, 读的时候不加锁。

虽然能够避免丢失数据, 但是可以读到没有提交或者回滚的内容 (脏数据), 这其实就是数据库最低的事务隔离级别 --- Read uncommitted

2. 写数据的时候加上X锁, 直到事务结束, 读的时候加上S锁, 读完数据立刻释放。

这能避免“丢失数据”和“脏数据”, 但是会出现“不可重复读”的问题 , 这是第二级的事务隔离级别 -- Read committed

3. 写数据的时候加上X锁, 直到事务结束, 读数据的时候加S锁, 也是直到事务结束。

这能避免“丢失数据”和“脏数据”, “不可重复读”三个问题 , 这是数据库常用的隔离级别 --

Repeatable read

整个世界似乎清净了。

有一次旺财对一个“学生表”进行操作,选取了年龄是18岁的所有行, 用X锁锁住, 并且做了修改。

改完以后旺财再次选择所有年龄是18岁的行, 想做一个确认, 没想到有一行竟然没有修改!

这是怎么回事? 出了幻觉吗?

原来就在旺财查询并修改的的时候, 小强也对学生表进行操作, 他插入了一个新的行,其中的年龄也是18岁! 虽然两个人的修改都没有问题, 互不影响, 但从最终效果看, 还是出了事。

(码农翻身注: 正是小强的操作, 让旺财出现了“幻读”)

旺财说: “没辙了, 我们俩非得串行执行不可, 你必须得等我执行完。 ”

这就是数据库事务隔离级别的终极大招:Serializable

最后, 为了方便记忆, 他们俩倒腾了半天, 整出了一张表, 用于记录各种情况:

(点击看大图)

两个人看着这张表, 感慨的说:“唉, 这数据库村的事务隔离级别可真是不容易啊!”

Mysql 不屑一顾的说: “这都嫌麻烦了, 你们还没遇到死锁呢....”

CockroachDB (蟑螂数据库)是一个可伸缩的、支持地理位置处理、支持事务处理的数据存储系统,谷歌的F1系统类似,支持分布式事务等特性。。CockroachDB 提供两种不同的的事务特性,包括快照隔离(snapshot isolation,简称SI)顺序的快照隔离(SSI)语义,后者是默认的隔离级别。        为了保证在线的百万兆字节流量业务的质量,Google开发了Spanner系统,这是一个可扩展的,稳定的,支持事务的系统。许多参与开发CockroachDB的团队现在都服务于开源社区。就像真正的蟑螂(cockroach)一样,CockroachDB可以在没有数据头、任意节点失效的情况下正常运行。这个开源项目有很多富有经验的贡献者,创始人们通过社交媒体、Github、网络、会议聚会结识他们并鼓励他们参与其中    蟑螂是一个分布式的K/V数据仓库,支持ACID事务,多版本值存储是其首要特性。主要的设计目标是全球一致性可靠性,从蟑螂的命名上是就能看出这点。蟑螂数据库能处理磁盘、物理机器、机架甚至数据中心失效情况下最小延迟的服务中断;整个失效过程无需人工干预。蟑螂的节点是均衡的,其设计目标是同质部署(只有一个二进制包)且最小配置。    蟑螂数据库实现了单一的、巨大的有序映射,键值都是字节串形式(不是unicode),支持线性扩展,理论上支持4EB的逻辑数据)。映射有一个或者多个Range组成,每一个Range对应一个把数据存储在RocksDB(LevelDB的一个变种,Facebook贡献)上的K/V数据库,并且复制到三个或者更多蟑螂服务器上,Range定义为有开始结束键值的区间。Range可以合并及分裂来维持总大小在一个全局配置的最大最小范围之间。Range的大小默认是64M,目的是便于快速分裂合并,在一个热点键值区间快速分配负载。Range的复制确定为分离的数据中心来达到可靠性(比如如下分组:{ US-East, US-West, Japan }, { Ireland, US-East, US-West}, { Ireland, US-East, US-West, Japan, Australia })    Range有一种变化,通过分布式一致性算法实例来调节确保一致性,蟑螂所选择使用Raft一致性算法。所有的一致性状态存在于RocksDB中。项目官网地址:http://www.cockroachdb.cn/ 标签:蟑螂数据库  国人开源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值