数据库事务 Transaction

Transaction 就是把一些读写操作组成一个逻辑单元,这些操作要么全部执行成功,要么全都不执行,不存在执行一半的情况(造成数据不一致)。数据库完善的事务机制保证了数据的一致性,如事务执行到一半系统宕机,数据库崩溃等各种异常情况下都可以保证数据的一致性,减少了应用程序开发的困难。

begin transaction
read()
write()
。。。
write()
commit (or rollback)

事务的4大特性:

Atomicity(原子性):

这个很好理解,事务是作为一个整体要么全部执行要么回滚,不存在中间状态。跟多线程中的原子操作是一样的。

Consistency(一致性):

这个不是很好理解,可以简单理解为事务可以保证数据的一致性。A给B转账,中间系统崩溃了,A和B的钱都不会丢失。

Isolation(隔离性):

隔离是指在多个事务并发的读写同一数据时各个事务之间要有隔离机制,并发控制不好很容易造成脏读,脏写,更新丢失等各种不一致的情况。主要有 4 种隔离级别。

Durability(持久性):

也很好理解,指事务提交成功后可以保证数据持久化到磁盘,即使事务执行中间数据库崩溃也可以保证。

事务隔离级别:

Read Committed(只能读已提交的数据):
  1. 当读取时只能读取已经提交的数据。(no dirty reads 防止了脏读 )一个事务不会读取到另外一个未提交事务更新到一半的数据。
  2. 当写入时只能复写已经提交的数据。(no dirty writes 防止了脏写)一个事务不能复写另外一个未提交事务更新到一半的数据。

实现:
防止脏写一般通过添加行锁来实现,一个事务要更新一行数据时先加行锁,这时其它事务要写时获取不到行锁只能等待。

防止脏读也可以通过锁来实现,读之前必须先获取锁,如果另外一个事务正在写这时读的事务获取不到锁必须等待。但这种方式存在性能问题,因为一个比较耗时的写事务会阻止所有的读事务。所以通常通过同时保存要更新值的旧值和新值来实现,在一个写事务未提交之前,可以读,但只能读取到旧值(在事务开始之前某一时刻照一张照片保存旧值)。

Snapshot Isolation and Repeatable Read (可重复读)

Read Committed 并不能解决所有并发问题。如会出现两次读取不一致的情况,事务1先读取一个值, 之后事务2修改了该值后 commit, 之后事务1再次读取该值发现读取的值改变了,这种不可重复读(两次读取数据不一样)的情况经常会给用户造成困扰。 但这并不违背 Read Committed 的原则, Repeatable Read 可以防止这种情况。

Snapshot Isolation 会存在 Lost update 的情况,两个事务并发的对同一值先读后写,最后写入的结果存在不确定的情况。

一:可以通过显示锁解决更新丢失
BEGIN TRANSACTION;
SELECT * FROM figures
WHERE name = 'robot' AND game_id = 222 FOR UPDATE;
-- Check whether move is valid, then update the position -- of the piece that was returned by the previous SELECT. UPDATE figures 
SET position = 'c4' WHERE id = 1234;
COMMIT;

FOR UPDATE 对读取出来的数据上显示锁,这时其它事务不能读也不能写这些查询出来的数据。 这是一种悲观锁,只要认为有可能有并发问题就提前加锁。

二:通过 Compare-and-set 解决更新丢失
UPDATE wiki_pages SET content = 'new content' , version = version + 1 WHERE id = 1234 AND version = 1;

给每一行数据设置一个版本号,先读取,之后提交事务时如果发现版本号变了,说明期间其它事务修改了这个数据,则回滚事务重试。版本号不变则说明没有修改则版本号加1 ,提交成功。
这是一种乐观锁,读取时并不加锁,到提交的时候再判断是否需要重试。适合读比较多的事务,如果写比较多不加锁很容易造成冲突和死锁。

实现: Repeatable Read 一般也通过保存事务执行期间的多个版本的值来实现的,在各个时刻照一张相(所以也叫做 Snapshot Isolation ),在写事务提交前,另外一个事务只能读取到 Snapshot 中的旧值, 防止了两次读取不一致的情况。

Snapshot Isolation 实现较为复杂,不是一两句就能说清楚的。

Serializability(串行化)

之前说 Repeatable Read 不能解决 Lost update (更新丢失) 和 Phantoms (幻读)等情况。 只有 Serializability (串行化)能解决所有问题。 如果让每一个事务一个挨着一个按顺序执行,可以彻底避免并发,这样就不会有任何问题了。(实际上并不是真正的串行执行,但结果和串行执行的结果是一样的)。

既然串行执行这么好,为什么用的较少呢,主要还是效率问题。 串行化一般可以通过加排它锁实现, 读之前对读出来的数据加锁,然后修改, 修改提交后释放锁。这期间其它事务既不能读,也不能写。解决了所有问题。

实际实现一般是 2PL (two-phase locking )已经存在了30 多年。

mysql 默认隔离级别是 Repeatable Read , 所以高并发情况下会出现 Lost update, 幻读, 死锁等各种问题。事务执行时间越长,发生不一致和死锁的概率越高。

本想多写一点,发现很难组织表达清楚,事务这块真不是一两篇文章能说的清楚的,这还不涉及分布式。

推荐阅读: Designing Data-Intensive Applications

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,576评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,515评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,017评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,626评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,625评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,255评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,825评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,729评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,271评论 1 320
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,363评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,498评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,183评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,867评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,338评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,458评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,906评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,507评论 2 359

推荐阅读更多精彩内容