MySQL数据库锁机制之MyISAM引擎表锁和InnoDB行锁详解

MySQL中的锁概念

Mysql中不同的存储引擎支持不同的锁机制。比如MyISAM和MEMORY存储引擎采用的表级锁,BDB采用的是页面锁,也支持表级锁,InnoDB存储引擎既支持行级锁,也支持表级锁,默认情况下采用行级锁。

Mysql3中锁特性如下:

表级锁:开销小,加锁块;不会出现死锁,锁定粒度大,发生锁冲突的概率最高,并发度最低。

行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发性也最高。

页面锁:开销和加锁界于表锁和行锁之间,会出现死锁;锁定粒度界与表锁和行锁之间,并发一般。

MyISAM表索

1.查询表级锁争用情况

通过检查table_locks_waited和table_locks_immediate状态变量分析系统上表锁争夺情况


table_locks_waited锁定等待时间越长,则说明存在较严重的表级别锁争用情况。

2.锁模式

mysql的表锁有两种模式:表共享读锁(table read lock)和表独占写锁(table write lock)


说明 1.myISAM表的读操作,不会阻塞其他用户对同一个表的读请求,但会阻塞对同一个表的写请求。

    2.myISAM表的写操作,会阻塞其他用户对同一个表的读和写操作。

        3.myISAM表的读、写操作之间、以及写操作之间是串行的。

实例如下,打开了两个会话,当t3处于读锁定时候,会话二可以检索t3数据。当t3处于写锁定时候,会话二只有等到解锁后,才能显示数据(可以对比检索时间)。


3.加表锁

MyISAM在执行查询前,会自动执行表的加锁、解锁操作,一般情况下不需要用户手动加、解锁,但是有的时候也需要显示加锁。

比如:检索某一个时刻t1,t2表中数据数量。

常用代码如下:

select count(t1.id1) as 'sum' from t1;

select count(t2.id1) as 'sum' from t2;

其实这是不正确的,很有可能当你在检索t1的那个时间点,t2的数据已经发生了变化,也就是说你检查出的t1和t2数据结果不是在同一个时间点上。

正确的做法是:

lock table t1read, t2read;select count(t1.id1) as'sum'from t1;select count(t2.id1) as'sum'from t2;unlock tables;

当然也可使用union,这样写:

SELECT  COUNT(t1.`id1`) AS dadasum,'t1'AS tablenameFROM  t1UNIONALL SELECT  COUNT(t2.`id1`)AS dadasum ,'t2'AS tablenameFROM  t2 ;

注意事项

1.在锁定表时候,如果加上关键字local,满足myISAM表的并发插入问题。eg: lock table t3 read local;

2.使用locak tables 给表加锁时候,必须同时给所有涉及到的表加锁,因为加锁之后,当前会话,就不能操作没有加锁的表。

4.并发插入问题

myISAM存储引擎有一个系统变量,concurrent_insert,专门用来控制并发插入行为的,值可以为0,1,2.

concurrent_insert为0时候,不允许插入

concurrent_insert为1时候,如果mysql没有空洞(中间没有被删除的行),myISAM运行一个进程读表的时候,另一个进程从表尾插入记录,这也是mysql默认设置。

concurrent_insert为2时候,无论MyISAM表中有没有空洞,都允许在表尾并行的插入。

5.myISAM锁调度问题

MyISAM存储引擎的读锁和写锁是互斥的,读写操作室串行的,那么如果读写两个进程同时请求同一张表,Mysql将会使写进程先获得锁。不仅仅如此,即使读请求先到达锁等待队列,写锁后到达,写锁也会先执行。因为mysql因为写请求比读请求更加重要。这也正是MyISAM不适合含有大量更新操作和查询操作应用的原因。

调节办法:

1)通过指定启动参数low-priority-updates,使MyISAM引擎默认给与读请求优先的权限

2)通过执行set low_PRIORITY_UPDATES=1,降低更新请求的优先级。

3)指定INSERT、UPDATE、DELETE语句的LOW_PRIORITY属性。

InnoDB锁

1.InnoDB与MyISAM最大不同有两点:

1).支持事务

2).采用行级锁

2.查看InnoDB行锁争用情况


>need-to-insert-img

3.innodb行锁模式以及加锁方法

innoDB实现了以先两种类型的行锁:

共享锁(S):允许一个事务去读一行,阻止其他事务获取相同数据集的排他锁。

排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。

先两种意向表锁:

意向同享锁

意向排他锁


如果一个事务请求的锁模式与当前的锁模式兼容,innodb就将请求的锁授予该事务;反之,如果两者不兼容,该事务就要等待锁释放。意向锁是Innodb自动加的,不需要用户干预。对于UPDATE、DELETE、INSERT语句,Innodb会自动给涉及的数据集加排他锁(X);对于普通SELECT语句,Innodb不会加任何锁。

显示添加锁

共享锁(S) : SELECT * FROM table_name WHERE .... LOCK IN SHARE MODE

排他锁(X):  SELECT * FROM table_name WHERE .... FOR UPDATE.

使用select ... in share mode获取共享锁,主要用在需要数据依存关系时,确认某行记录是否存在,并确保没有人对这个记录进行update或者delete。

4.InnoDB行锁实现方式

InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过再数据块中,对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,innoDB才使用行级锁,否则InnoDB将使用表锁,在实际开发中应当注意。

实例一:

建立t1表如下:

CREATE TABLE `t1` (  `id1` int(5) DEFAULT NULL,  `id2` int(3) unsigned zerofill NOT NULL DEFAULT'000') ENGINE=InnoDB DEFAULT CHARSET=utf8

insert into t1 valuses(1,1),(2,2);


因为没有创建索引,当给第一个会话添加索引时候,其实添加的是表索引,而非行索引,因为第二会话在查询其他信息时候,一直处于等待状态,最后超时,直到第一个会话事务提交后,方可查询。(需要先设置 set autocommit=0)

实例二:

修改上面t1表中数据,数据如下


给id1添加索引ALTER TABLE t1 ADD INDEX id1(id1);


有此可以看出此时,mysql使用的是行索引。

但是还有一个需要我们注意


很明显两个会话查询的不是同一行记录,为什么会话2仍然需要等待会话1提交之后才能查询呢?还是因为Mysql行锁是针对索引加的锁,不是针对记录加的锁,索引虽然访问不同的记录,但是他们的索引相同,是会出现冲突的,在设计数据库时候需要注意这一点。上面只有将字段id2,也添加上索引才能解决冲突问题。这也是mysql效率低的一个原因。

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

推荐阅读更多精彩内容