MySQL笔记-锁、事务与并发控制

MySQL服务器逻辑架构

每个连接都会在mysql服务端产生一个线程(内部通过线程池管理线程),比如一个
select语句进入,mysql首先会在查询缓存中查找是否缓存了这个select的结果集,如
果没有则继续执行 解析、优化、执行的过程;否则会之间从缓存中获取结果集。

MySQL并发控制

共享锁
共享锁也称为读锁,读锁允许多个连接可以同一时刻并发的读取同一资源,互不干扰;
排他锁
排他锁也称为写锁,一个写锁会阻塞其他的写锁或读锁,保证同一时刻只有一个连接可以写入数据,同时防止其他用户对这个数据的读写。

锁策略
锁的开销是较为昂贵的,锁策略其实就是保证了线程安全的同时获取最大的性能之间的平衡策略。

Mysql锁策略:talbe lock(表锁)
表锁是Mysql最基本的锁策略,也是开销最小的策略,它会锁定整个表;具体情况是:若一个用户正在执行写操作,会获取排他的“写锁”,这是会锁定整个表,阻塞其他用户的读、写操作;
若一个用户正在执行读操作,会先获取共享锁“读锁”,这个锁运行其他读锁并发的对这个表进行读取,互不干扰。只要没有写锁的进入,读锁可以是并发读取统一资源的。

Mysql锁策略:row lock(行锁)
行锁可以最大限度的支持并发处理,当然也带来了最大开销,顾名思义,行锁的粒度实在每一条行数据。

事务

事务就是一组原子性的sql,或者说一个独立的工作单元。就是说要么mysql引擎会全部执行这一组sql语句,要么全部都不执行(比如其中一条语句失败的话)。

比如,tim要给bill转账100块钱: 
1.检查tim的账户余额是否大于100块; 
2.tim的账户减少100块; 
3.bill的账户增加100块; 
这三个操作就是一个事务,必须打包执行,要么全部成功,要么全部不执行,其中任何一个操作的失败都会导致所有三个操作“不执行”——回滚。


一个良好的事务系统,必须满足ACID特点:
ACID
A:atomiciy原子性 一个事务必须保证其中的操作要么全部执行,要么全部回滚,不可能存在只执行了一部分这种情况出现。

C:consistency一致性  数据必须保证从一种一致性的状态转换为另一种一致性状态;比如上一个事务中执行了第二步时系统崩溃了,数据也不会出现bill的账户少了100块,但是 tim的账户没变的情况。要么维持原装(全部回滚),要么bill少了100块同时tim多了100块,只有这两种一致性状态的

I:isolation隔离性
在一个事务未执行完毕时,通常会保证其他事务无法看到这个事务的执行结果

D:durability持久性事务一旦commit,则数据不会保存下来,即使提交完之后系统崩溃,数据也不会丢失。

隔离级别
1. READ UNCOMMITTED(未提交读)

事务中的修改,即使没有提交,对其他事务也是可见的。事务可以读取未提交的数据——脏读。脏读会导致很多问题,一般不适用这个隔离级别。

2. READ COMMITTED(提交读)
一般数据库都默认使用这个隔离级别(Mysql不是),这个隔离级别保证了一个事务如果没有完全成功(commit执行完),事务中的操作对其他事务是不可见的。-   

3. REPEATABLE READ(可重复读) 这个隔离级别解决了脏读的问题,但会产生幻读,问题。
脏读与幻读与不可重复读
3.1) 脏读:一个事务读取到另一事务未提交的更新新据。当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据, 那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作也可能是不正确的。
3.2) 不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同。换句话说就是,后续读取可以读到另一事务已提交的更新数据。相反,“可重复读”在同一事务中多次读取数据时,能够保证所读数据一样,也就是,后续读取不能读到另一事务已提交的更新数据。
3.3) 幻读:事务T1执行一次查询,然后事务T2新插入一行记录,这行记录恰好可以满足T1所使用的查询的条件。然后T1又使用相同的查询再次对表进行检索,但是此时却看到了事务T2刚才插入的新行。这个新行就称为“幻像”,因为对T1来说这一行就像突然出现的一样。
4. SERIALIZABLE(可串行化) 最强的隔离级别,通过给事务中每次读取的行加锁(行锁),保证不产生幻读问题,但是会导致大量超时以及锁争用问题。

MySQL死锁问题

死锁,就是产生了循环等待链条,我等待你的资源,你却等待我的资源,我们都相互等待,谁也不释放自己占有的资源,导致无线等待下去。 

比如:
//Thread A
START TRANSACTION;
UPDATE account SET p_money=p_money-100 WHERE p_name="tim";
UPDATE account SET p_money=p_money-100 WHERE p_name="bill";
COMMIT;

//Thread B
START TRANSACTION;
UPDATE account SET p_money=p_money-100 WHERE p_name="bill";
UPDATE account SET p_money=p_money-100 WHERE p_name="tim";
COMMIT;


当线程A执行到第一条语句UPDATE account SET p_money=p_money-100 WHERE p_name=”tim”;锁定了p_name=”tim”的行数据;并且试图获取p_name=”bill”的数据;

,此时,恰好,线程B也执行到第一条语句:UPDATE account SET p_money=p_money+100 WHERE p_name=”bill”;

锁定了 p_name=”bill”的数据,同时试图获取p_name=”tim”的数据; 
此时,两个线程就进入了死锁,谁也无法获取自己想要获取的资源,进入无线等待中,直到超时!

对于死锁,数据库一般通过死锁监测、死锁超时机制解决;通常会执行回滚,打破死锁状态,然后再次执行之前死锁的事务即可。

MySQL中的事务

自动提交(AutoCommit)

mysql默认采用AutoCommit模式,也就是每个sql都是一个事务,并不需要显示的执行事务

多版本并发控制-MVCC

MVCC是个行级锁的变种,它在很多情况下避免了加锁操作,因此开销更低。虽然实现不同,但通常都是实现非阻塞读,对于写操作只锁定必要的行。

通常MVCC实现有乐观并发控制与悲观并发控制,INNODB的MVCC通常是通过在每行数据后边保存两个隐藏的列来实现,一个保存了行的创建时 间,另一个保存了行的删除时间。当然存储的并不是实际的时间值,而是系统版本号,每个事务开始,系统版本号就会递增!,每个事务开始时刻的版本号也会作为 这个事务的版本号,用来和查询到的每行版本号做比较。下边在Mysql默认的Repeatable Read隔离级别下,具体看看MVCC操作:

Select: 
a.InnoDB只查找版本号早于当前版本号的数据行,这样保证了读取的数据要么实在这个事务开始之前就已经commit了的(早于当前版本号),要么是在这个事务自身中执行操作的数据(等于当前版本号)。 
b.行的删除版本号要么未定义,要么早于当前的版本号,这样保证了事务读取到的数据在事务开始之前未被删除。

Insert

InnoDB为这个事务中新插入的行,保存当前事务版本号的行(作为行的版本号)。

Delete 
InnoDB为每一个删除的行保存当前事务版本号,最为行的删除标记。

Update

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

推荐阅读更多精彩内容