mysql优化-锁机制

目的

解决因资源共享而造成的并发问题。

示例:买最后一件衣服X

A:X买:X加锁->试衣服...下单..付款..打包->X解锁
B:X买:发现X已被加锁,等待X解锁,X已售空

分类:

操作类型:
a.读锁(共享锁):对同一个数据(衣服),多个读操作可以同时进行,互不干扰。
b.写锁(互斥锁):如果当前写操作没有完毕(买衣服的一系列操作),则无法进行其他的读操作、写操作

操作范围:
a.表锁:一次性对一张表整体加锁。如MyISAM存储引擎使用表锁,开销小、加锁快;无死锁;但锁的范围大,容易发生锁冲突、并发度低。
b.行锁:一次性对一条数据加锁。如InnoDB存储引擎使用行锁,开销大,加锁慢;容易出现死锁;锁的范围较小,不易发生锁冲突,并发度高(很小概率发生高并发问题:脏读、幻读、不可重复度、丢失更新等问题)。
c.页锁

示例:

(1)表锁:--自增操作MYSQL/SQLSERVER支持;oracle需要借助于序列来实现自增
createtabletablelock
(
idintprimarykeyauto_increment,
namevarchar(20)
)enginemyisam;

insertintotablelock(name)values('a1');
insertintotablelock(name)values('a2');
insertintotablelock(name)values('a3');
insertintotablelock(name)values('a4');
insertintotablelock(name)values('a5');
commit;

增加锁:
locaktable表1read/write,表2read/write,...

查看加锁的表:
showopentables;

会话:session:每一个访问数据的dos命令行、数据库客户端工具都是一个会话

===加读锁:
会话0:
locktabletablelockread;
select*fromtablelock;--读(查),可以
deletefromtablelockwhereid=1;--写(增删改),不可以

select*fromemp;--读,不可以
deletefromempwhereeid=1;--写,不可以
结论1:
--如果某一个会话对A表加了read锁,则该会话可以对A表进行读操作、不能进行写操作;且该会话不能对其他表进行读、写操作。
--即如果给A表加了读锁,则当前会话只能对A表进行读操作。

会话1(其他会话):
select*fromtablelock;--读(查),可以
deletefromtablelockwhereid=1;--写,会“等待”会话0将锁释放

会话1(其他会话):
select*fromemp;--读(查),可以
deletefromempwhereeno=1;--写,可以
结论2:
--总结:
会话0给A表加了锁;其他会话的操作:a.可以对其他表(A表以外的表)进行读、写操作
b.对A表:读-可以;写-需要等待释放锁。
释放锁:unlocktables;

===加写锁:
会话0:
locktabletablelockwrite;

当前会话(会话0)可以对加了写锁的表进行任何操作(增删改查);但是不能操作(增删改查)其他表
其他会话:
对会话0中加写锁的表可以进行增删改查的前提是:等待会话0释放写锁

MySQL表级锁的锁模式
MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,
在执行更新操作(DML)前,会自动给涉及的表加写锁。
所以对MyISAM表进行操作,会有以下情况:
a、对MyISAM表的读操作(加读锁),不会阻塞其他进程(会话)对同一表的读请求,
但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其它进程的写操作。
b、对MyISAM表的写操作(加写锁),会阻塞其他进程(会话)对同一表的读和写操作,
只有当写锁释放后,才会执行其它进程的读写操作。

分析表锁定:
查看哪些表加了锁:showopentables;1代表被加了锁
分析表锁定的严重程度:showstatuslike'table%';
Table_locks_immediate:即可能获取到的锁数
Table_locks_waited:需要等待的表锁数(如果该值越大,说明存在越大的锁竞争)
一般建议:
Table_locks_immediate/Table_locks_waited>5000,建议采用InnoDB引擎,否则MyISAM引擎

(2)行表(InnoDB)
createtablelinelock(
idint(5)primarykeyauto_increment,
namevarchar(20)
)engine=innodb;
insertintolinelock(name)values('1');
insertintolinelock(name)values('2');
insertintolinelock(name)values('3');
insertintolinelock(name)values('4');
insertintolinelock(name)values('5');

--mysql默认自动commit;oracle默认不会自动commit;

为了研究行锁,暂时将自动commit关闭;setautocommit=0;以后需要通过commit

会话0:写操作
insertintolinelockvalues('a6');

会话1:写操作同样的数据
updatelinelocksetname='ax'whereid=6;

对行锁情况:
1.如果会话x对某条数据a进行DML操作(研究时:关闭了自动commit的情况下),则其他会话必须等待会话x结束事务(commit/rollback)后才能对数据a进行操作。
2.表锁是通过unlocktables,也可以通过事务解锁;行锁是通过事务解锁。

行锁,操作不同数据:

会话0:写操作

insertintolinelockvalues(8,'a8');
会话1:写操作,不同的数据
updatelinelocksetname='ax'whereid=5;
行锁,一次锁一行数据;因此如果操作的是不同数据,则不干扰。

行锁的注意事项:
a.如果没有索引,则行锁会转为表锁
showindexfromlinelock;
altertablelinelockaddindexidx_linelock_name(name);

会话0:写操作
updatelinelocksetname='ai'wherename='3';

会话1:写操作,不同的数据
updatelinelocksetname='aiX'wherename='4';

会话0:写操作
updatelinelocksetname='ai'wherename=3;

会话1:写操作,不同的数据
updatelinelocksetname='aiX'wherename=4;

--可以发现,数据被阻塞了(加锁)
--原因:如果索引类发生了类型转换,则索引失效。因此此次操作,会从行锁转为表锁。

b.行锁的一种特殊情况:间隙锁:值在范围内,但却不存在
--此时linelock表中没有id=7的数据
updatelinelocksetname='x'whereid>1andid<9;--即在此where范围中,没有id=7的数据,则id=7的数据成为间隙。
间隙:Mysql会自动给间隙加索->间隙锁。即本题会自动给id=7的数据加间隙锁(行锁)。
行锁:如果有where,则实际加索的范围就是where后面的范围(不是实际的值)

如何仅仅是查询数据,能否加锁?可以forupdate
研究学习时,将自动提交关闭:
setautocommit=0;
starttransaction;
begin;
select*fromlinelockwhereid=2forupdate;

通过forupdate对query语句进行加锁。

行锁:
InnoDB默认采用行锁;
缺点:比表锁性能损耗大。
优点:并发能力强,效率高。
因此建议,高并发用InnoDB,否则用MyISAM。

行锁分析:
showstatuslike'%innodb_row_lock%';
Innodb_row_lock_current_waits:当前正在等待锁的数量
Innodb_row_lock_time:等待总时长。从系统启到现在一共等待的时间
Innodb_row_lock_time_avg:平均等待时长。从系统启到现在平均等待的时间
Innodb_row_lock_time_max:最大等待时长。从系统启到现在最大一次等待的时间
Innodb_row_lock_waits:等待次数。从系统启到现在一共等待的次数

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

推荐阅读更多精彩内容

  • 一、MySQL优化 MySQL优化从哪些方面入手: (1)存储层(数据) 构建良好的数据结构。可以大大的提升我们S...
    宠辱不惊丶岁月静好阅读 2,425评论 1 8
  • MySQL中主要有两种锁:行级锁和表级锁:行级锁(row-level):特点是锁定对象的粒度小,发生锁定资源争用的...
    田真的架构人生阅读 792评论 0 1
  • 锁概述 MySQL的锁机制,就是数据库为了保证数据的一致性而设计的面对并发场景的一种规则。 最显著的特点是不同的存...
    胡一巴阅读 433评论 0 0
  • 锁概述 MySQL的锁机制,就是数据库为了保证数据的一致性而设计的面对并发场景的一种规则。 最显著的特点是不同的存...
    胡一巴阅读 242评论 0 0
  • 姓名 :刘伟 企业:安徽省瀚海新材料股份有限公司。 组别 谦虚二组 【日精进打卡第238天 】 【知~学习 【经典...
    六项精进刘伟阅读 53评论 0 0