• 2021-04-24

    数据库事务的原子性与隔离级别

    Views: 2781 | No Comments

    数据库事务的原子性并不仅仅是指写操作, 还包括读操作. 对于写操作, 众所周知, 原子性是指操作序列中的所有操作要么全部成功, 要么全部失败. 但多次读操作未必是指要么全部读到要么全部读不到. 如果不是 Snapshot Isolation, 那么两次读操作, 可能有其中一次读到旧值, 另一次读到新值. 但是, 读操作的原子性要求必须满足因果性. 当读到新值之后, 就说明事务中的所有写操作都已完成, 显然, 后续的读操作必须读到新值, 不能读到旧值.

    Snapshot Isolation 有一个最大的问题, 那便是在创建快照的时候(可能隐式创建), 如何处理 pending 状态的资源, 如果不处理, 那么同一个事务的两个资源, 在快照中可能处于不同的状态(一个已提交, 另一个未提交), 也显然违反了原子性.

    对于隔离级别来说, 只有 Serializable 才是符合原子性的. Read Committed 违反了原子性, 因为大部分的数据库实现, 只判断资源的状态是否为 committed, 并没有向上追查资源所关联的事务对象(commit point)的状态, 所以会出现先读到新值, 再读到旧值的情况(见后面的例子). 这种情况违反了因果关系, 也违反了一致性.
    Continue reading »

    Posted by ideawu at 2021-04-24 10:25:29
  • 2021-04-24

    数据库的并发操作与一致性

    Views: 3596 | No Comments

    作为分布式强一致数据库的开发者, 被多次问到:

    如果我在新加坡和欧洲同时修改一条记录, 如在新加坡 set a=1, 在欧洲 set a=2, 结果 a 是多少?

    我的回答是:

    可能是 a=1, 也可能是 a=2.

    然后提问者会非常困惑和不满:

    你不是说数据库是强一致的吗? 为什么结果不确定呢?

    我非常理解他的困惑, 但是, 他所提到的"并发操作"和"一致性"并没有必然的联系.

    并发

    Martin Kleppmann 提到并发(Concurrency)的定义:

    For defining concurrency, exact time doesn’t matter: we simply call two operations concurrent if they are both unaware of each other, regardless of the physical time at which they occurred.

    要定义并发, 时间并不是一个影响因素: 如果两个操作不知道对方(的开始和结束以及结果), 无论物理时间上他们何时发生, 我们都称这两个操作是并发的.

    有这样的例子:
    Continue reading »

    Posted by ideawu at 10:08:22
  • 2021-04-17

    并发编程的核心技术 – 多版本(Multi Version)

    Views: 10955 | No Comments

    在单机编程时代, 每一项数据只有唯一的一份, 对数据的修改也是 in-place 的. 但是, 在并发编程领域, 包括分布式系统, 数据多版本(Multi Version, Versioning)是核心.

    我们先从单机编程的内存操作出发. 对于内存的操作, 都是原地(in-place)更新的. 对象和内存空间强绑定, 当更新对象时, 是将对象的内存空间擦除然后用新数据写覆盖. 到了多线程编程时代, 就引入了锁机制, 因为擦除和写操作过程不是原子性的, 可能擦除到一半时, 就被其它线程读取了, 因此要加锁.

    单机的硬盘操作, 基本也是借鉴内存操作, 也是对象和硬盘空间强绑定. 至少大部分程序员的思想是这样的, 这样比较直观. 跟内存操作一样, in-place 也遇到了操作的原子性挑战. 内存本来就是易失的(掉电后丢失), 但硬盘不一样, 数据需要持久化(掉电不丢失), 即使靠加锁解决了访问原子性问题, 但解决不了数据丢失问题. 所以, 硬盘操作是最先引入多版本技术的. 当需要修改某个对象时, 在另外的地方保存对象的新数据, 然后在另外的地方原子性地修改指向新数据的"指针". 事实上, 指针的修改也是多版本的, 不是 in-place 的, 后面会细说.
    Continue reading »

    Posted by ideawu at 2021-04-17 18:20:34
  • 2021-04-11

    大型互联网企业需要什么样的数据库系统?

    Views: 4247 | No Comments

    我们先看看, 早期小型公司是如何使用数据库系统的. 找来几台运行 Linux 操作系统的虚拟机, 部署几个 MySQL 进程, 配置一下主从同步.

    当公司业务发展壮大, 一是业务的深度加深, 也即同样的业务数据量增加, 二是业务的广度增加, 也即做了更多的功能和产品. 为了适应业务发展, 不得不部署更多的 MySQL 进程. 管理这些进程本身就是一项繁杂的工作, 这时, 就需要引入所谓的运维系统了. 运维系统首先是信息系统(MIS), 其次是操作平台(管理后台).

    运维系统本身的开发, 就是一个软件工程. 业务发展得越大, 运维系统就会越庞大. 这时, 所谓的公有云平台出场了. 国内比较有名的云平台有阿里云, 腾讯云, 国外有 AWS.

    那么, 是不是所有的企业都会使用公有云服务呢? 公有云服务确实越来越流行, 但至少对于大型互联网企业, 甚至是中型的互联网企业, 依然不会选择公有云. 有功能覆盖上的考虑, 有成本的考虑, 更重要的是商业上独立自主的发展权的考虑.
    Continue reading »

    Posted by ideawu at 2021-04-11 23:25:53
  • 2021-04-09

    全球分布式数据库遇到的经典问题

    Views: 4619 | 2 Comments

    全球分布式数据库因为地理距离较远(上万公里), 网络通信延迟一般在 100ms 级别, 所以只能采取异步复制的方案. 采取异步复制方案, 那就决定了最终数据被复制的时效性无法得到保证, 例如正常情况仅仅比网络延迟多几毫秒(100ms+). 但坏情况时, 例如, 因为网络线路不好, 数据可能要花费数秒甚至数分钟才能同步. 这就导致了非常恼人的用户体验.

    考虑这样的场景:

    某网络游戏平台的用户 A 在中国, 而用户 B 是他曾经的邻居, 目前在美国. 某日, 用户 A 将游戏中的道具转给了用户 B, A 在游戏中看到了明确的操作成功的提示, 而且刷新也确认道具已经转交.

    A 在私下用微信告知了这个操作, 然后让 B 在游戏中查看自己的道具背包.

    该游戏平台在中国有一个数据库, 在美国也有一个数据库, 两地的数据库是异步复制(最终一致性)的. 因为游戏平台自己的网络线路问题, 这个操作的数据一直没有同步到美国. 但是, 微信所使用的网络线路没有问题, B 收到了 A 的微信消息.

    B 在美国不断地刷新, 一直看不到道具, 这让他非常疑惑. 明明 A 说道具已经转交了呀, 而且还发截图了.

    这就是经典的异步复制(最终一致性)导致的问题. 要怎么解决呢? 有很多方案, 但是, 正如”没有银弹”一样, 每一种方案都有缺陷. 我们一种一种地分析.

    Continue reading »

    Posted by ideawu at 2021-04-09 22:03:57
  • 2021-04-01

    数据库的持久化等级

    Views: 3256 | No Comments

    数据持久化(Durability)是数据库系统的最基础功能之一. 我们把数据写入数据库, 期望未来能从数据库中再读出来, 即使中间经过了数据库进程重启或者计算机掉电重启, 数据依然在. 但是, 持久化被划分为许多等级, 每个等级所能承受的外界变化程度(容灾能力)不同. 之所以划分持久化等级, 直接原因是因为性能(单请求的处理耗时, Response Time), 间接原因是成本.

    磁盘持久化

    掉电重启级别的容灾能力, 是单机系统最低限度的持久化, 所以, 把数据写入磁盘, 才能称为持久化.

    如果数据只写入内存, 无论是用户进程管理的内存, 还是操作系统内核管理的内存, 都不算是持久化, 特别的, 即使写入磁盘驱动器自身的缓冲区, 也不算是持久化. 只要数据没有真正到达磁盘的硬件本体, 那么就无法容忍掉电故障, 也即所谓的断电丢数据.

    Continue reading »

    Posted by ideawu at 2021-04-01 23:09:56
|<<<1234>>>| 4/4 Pages, 24 Results.