mysql事务概念简要(1)

并发控制

  • 读写锁

    • 共享锁(读锁):读锁是共享的,相互不阻塞,但会阻塞写锁;多个客户在同一时刻可以读取同一个资源,互不干扰。
    • 排他锁(写锁):写锁是排他的,一个写锁会阻塞其他的写锁和读锁;这是出于安全策略,确保只有一个客户能执行写入,并防止其他用户读取正在写入的资源。
  • 锁粒度

一种提高共享资源并发性的方式就是让锁定对象更有选择性。尽量只锁定需要修改的部分数据(最理想的方式),而不是所有的资源。锁定范围越小,并发性越高。大多数数据库都是在表上施加行级锁,并以各种复杂的方式来实现。

  • 表锁(table lock):MySQL中最基本的锁策略,并且是开销最小的策略(不涉及过多逻辑),会锁定整张表;eg:服务器会为诸如alter table之类的语句使用表锁,而忽略存储引擎的锁机制。【这么看来服务器层就实现了表锁】
    -行级锁(row lock):行级锁可以最大程度地支持并发处理(同时有带来了最大的锁开销)。行级锁只在储存引擎层实现,而MySQL服务器层没有实现;储存引擎Innodb就实现了行级锁。

事务

事务就是一组原子性的SQL执行,或者说一个独立的工作单元。事务内的语句,要么全部执行成功,要么全部执行失败。

严格意义上来说,一个运行良好的事务应该具备4个标准特性:ACID

  • 原子性(atomicity):最小工作单元,要么都成功,要么都失败回滚。
  • 一致性(consistency):数据库总是从一个一致性状态转换到另外一个一致性的状态,失败事务中的改动不会保存到数据库中
  • 隔离性(isolation):\color{red}{通常来说},一个事务的修改在最终提交前,对其他事务是不可见的。这里是考虑到下文会提及的隔离级别的,所以说通常来说,并不绝对。
  • 持久性(durability):一旦事务成功提交,其修改就会永久保存到数据库中。

隔离级别

  • read uncommitted(未提交读)
    • 事务中的修改尚未提交,对其他事务是可见的;一般不用这个隔离级别
    • 事务可以读取其他事务未提交的数据,这就叫\color{red}{脏读}
  • read committed(提交读/不可重复读)
    • 提交读就开始满足之前的隔离性定义了:一个事务从开始到提交之前,所做的修改对其他事务都是不可见的。
    • 也叫不可重复读,因为一个事务前后两次执行同样的SQL查询,可能会得到不一样的结果(两次查询间隙可能会有其他事务提交了改动,而第二次查询读取了其他事务的提交修改)
    • 大多数数据库系统的默认隔离级别
  • repeatable read(可重复读)
    • 在提交读的基础上,做到了可重复读:前后两次同样的SQL查询得到的结果一定相同。
    • 幻读(Phantom Read):指的是当某个事务在读取某个范围内的记录时,另外一个事务有在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。
    • 理论上,可重复读无法解决幻读的问题;但是Innodb存储引擎通过MVCC解决了幻读的问题;
    • MySQL的默认事务隔离级别
  • serializable(可串行化)
    • 最高的隔离级别,通过强制事务串行执行,避免了前面的幻读问题。
    • 会在\color{red}{读取}的每一行数据上都加上锁,所以可能导致大量的超时和锁争用的问题。
    • 实际应用很少用这个级别,只有在非常需要确保数据一致性并接受没有并发的情况下,才考虑使用

死锁

死锁是指两个或多个事务在同一资源上互相占用,并请求对方占用的资源。
Innodb目前处理死锁的方式是,将持有最少行级排他锁的事务进行回滚(这是相对简单的死锁回滚方法)。

多版本并发控制-MVCC(Multi-Version Concurrency Control)

  • MySQL的大多数事务型存储引擎实现的都不是简单的行级锁,基于提升并发性能的考虑,他们一般都实现了各自的MVCC。包括Oracle,PostgreSQL等其他数据库也都实现了MVCC,只是机制不尽相同,MVCC没有一个统一的实现标准。
  • 可以认为MVCC是行级锁的一个变种,很多情况下它可以避免加锁操作,因此开销更低。
  • MVCC的实现,是通过保存数据在某个时间点的快照来实现的。

\color{red}{PS}:下面仅仅是大意的说明,实际上行记录隐藏列是创建事务id、undo log指针,还有一个delete bit标记。

不同存储引擎的MVCC的实现是不同的,典型的有乐观并发控制和悲观并发控制。从下文可以看出innodb的MVCC实现属于乐观并发控制:

  • InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的。一个列保存了行的创建时间,另一个列保存行的过期时间(删除时间)。当然存储的并不是实际的时间值,而是系统版本号。事务开始时刻的系统版本号会作为事务的版本号,每开始一个新的事务,系统版本号都会自动递增。(类似自增主键概念,系统版本号始终比最大的事务版本号大1)下面是repeatable read的隔离级别下,MVCC的具体操作:
    • select
      • 只查找创建版本早于当前事务版本的数据行(create_system_version_number <= now_tx_id),从而确保读取的行是事务开始前就存在的,或者是事务本身插入(或修改)的数据行
      • 查找的数据行的删除版本号要么未定义(数据没被删除),要么大于当前事务版本号(del_system_version_number > now_tx_id),从而确保事务读取的行在事务开始之前未被删除,也就是说事务之后其他事务删除的话该事务不可见。
      • 说白了就是读取数据的时候只认now_tx_id之前的数据来处理,其他的忽略。
    • insert:
      • 事务给自己新插入的行的创建版本号标记为now_system_id(now_system_id即当前系统版本号)
    • delete:
      • 事务给自己删除的行的删除版本号标记为now_system_id
    • update:
      • 事务的修改实际上是删除老的行,新增一行。
      • 删除、新增的隐藏列处理逻辑与上面保持一致

保存这两个额外的系统版本号,使大多数的读操作都可以不用加锁。可以不加锁去做到安全的并发,这可不就是乐观并发控制嘛!不足之处是需要额外的存储空间,还有一些额外行检查工作、维护工作。
MVCC只是在可重复读和提交读这两个隔离级别下工作。其他两个隔离级别不兼容,因为未提交读总是读最新数据而不管隐藏列的事务版本,可串行化则对所有读取的行都会加锁。

PS:脏读 VS 幻读的理解

其实这两个概念没有什么联系,只是名称都带个读而已。就我的理解而言:

  • 脏读强调的是其他事务未提交的改动就会被读取,这里的改动包括update、insert、delete
  • 幻读从定义来看仅仅是强调其他事务提交的改动会被读取,但是这里的改动仅仅包含了insert、delete,没有涉及update。只要没有update,就可以认为两次查询的结果一致,这里说的一致应该是指特定数据行的内容一致,但是数据行的范围发生了变化,多出来的行就是幻行(我认为少了的行也可以认为一种变相的幻行,这里书籍没有明确指明)。
  • 总而言之,就是脏读是读取了未提交的update,幻读是读取了已提交的insert/delete。讨论两者的比较没啥意义,本身就是特定模式下的概念,都没啥相似之处
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342