MySQL/InnoDB锁——乐观锁、悲观锁……

  • 为什么要引入锁这个东西——(并发控制)?
      在多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突,这就是典型的并发性问题。典型的冲突有:

丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。例如:用户A把值从6改为2,用户B把值从2改为3,则用户A丢失了他的更新。

脏读:当一个事务读取其它完成一半事务的记录时,就会发生脏读取。例如:用户A,B看到的值都是6,用户B把值改为2,用户A读到的值仍为6。

为了解决这些并发带来的问题,我们需要引入并发控制机制,看下面案例:

基本SQL语句:

DROP TABLE IF EXISTS `t_letou`;
CREATE TABLE `t_letou` (
  `le_qihao` varchar(10) NOT NULL COMMENT '期号',
  `hong_one` varchar(10) NOT NULL COMMENT '红球1',
  `hong_two` varchar(10) NOT NULL COMMENT '红球2',
  `hong_three` varchar(10) NOT NULL COMMENT '红球3',
  `hong_four` varchar(10) NOT NULL COMMENT '红球4',
  `hong_five` varchar(10) NOT NULL COMMENT '红球5',
  `lan_one` varchar(10) NOT NULL COMMENT '蓝球1',
  `lan_two` varchar(10) NOT NULL COMMENT '蓝球2',
  PRIMARY KEY (`le_qihao`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `t_letou` VALUES ('18122', '08', '09', '21', '30', '31', '05', '12');

我们都知道,多线程访问某统一数据时,一般都要加锁,数据库中,同样有锁机制。那么,什么是锁呢?
锁可以简单理解为保证数据并发访问的一致性、有效性的关键机制,就比如是保证钱不轻易被偷走的安全柜锁。
本文主讲针对基于InnoDB存储引擎的MySQL,查看是什么引擎,可用如下命令:

SHOW ENGINES

1) 乐观锁
乐观锁其实不上锁,只是用数据版本(Version)记录机制实现,一般通过 “version” 字段来实现。当读取数据时,将version的值一同读出,数据每更新一次,就对version值加1。当Update时候,判断当前版本信息与第一次取出来的version值进行比对,值相等认为一致,则予以更新,否则认为是过期数据,不给予更新。

假设有表,有三字段:id,value、version
select id,value,version from TABLE where id=#{id}

update TABLE
set value=2,version=version+1
where id=#{id} and version=#{version};

2)悲观锁
可以这么理解,悲观锁就是天生悲观,认为别人每次拿数据的时候都会修改数据,所以在每次拿的时候都给数据上锁。其他线程想要拿数据,就会阻塞,直到给数据上锁的线程将事务提交或者回滚。

说到悲观锁,就要先理解——共享锁与排它锁。共享锁和排它锁是悲观锁的不同实现,都属于悲观锁。
要使用悲观锁,必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式:

set autocommit=0;

# 取消自动提交后,就可以执行正常业务了,具体如下:

1. 开始事务
begin;/begin work;/start transaction; (三者选一就可以)

2. 查询表信息
select status from TABLE where id=1 for update;

3. 插入一条数据
insert into TABLE (id,value) values (2,2);

 4. 修改数据为
update TABLE set value=2 where id=1;

 5. 提交事务
commit;/commit work;

3)共享锁
一个线程给数据加上共享锁后,其他线程只能读,不能改。

先加一个共享锁
begin;/begin work;/start transaction;  (三者选一就可以)

SELECT * from t_letou where le_qihao='18122'  lock in share mode;
另一个窗口执行UPDATE语句:(另一线程)
UPDATE t_letou SET hong_one="01" where le_qihao='18122'

一执行,好了,卡顿,过了设置超时时间,提示错误信息

在查询语句后面增加** LOCK IN SHARE MODE**,Mysql会对查询结果中的每行都加共享锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。
PS:加上共享锁后,对于update,insert,delete语句会自动加排它锁。

4)排它锁
排他锁又称为写锁,和共享锁的区别在于,其他线程既不能读也不能改。

5)行锁
行锁只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突,其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁和排他锁。

6)表锁
表级锁是 MySQL 中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分 MySQL 引擎支持。最常使用的 MyISAM 与 InnoDB 都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。

7)页锁
页级锁是 MySQL 中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。因此,采取了折衷的页级锁,一次锁定相邻的一组记录。BDB 支持页级锁。

8)死锁(Deadlock)
所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。可以理解为拔河时两边持平,都拿不到挂在中间的香蕉。
解除死锁状态方法有:

第一种:
1.查询是否锁表
show OPEN TABLES where In_use > 0;

2.查询进程(如果您有SUPER权限,您可以看到所有线程。否则,您只能看到您自己的线程)
show processlist

3.杀死进程id(就是上面命令的id列)
kill id

第二种:
1:查看当前的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

2:查看当前锁定的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

3:查看当前等锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; 

4.杀死进程
kill 线程ID

产生死锁的四个必要条件:
1) 互斥条件:一个资源每次只能被一个进程使用。
2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

虽然不能完全避免死锁,但可以使死锁的数量减至最少。
将死锁减至最少可以增加事务的吞吐量并减少系统开销,因为只有很少的事务回滚,而回滚会取消事务执行的所有工作。由于死锁时回滚而由应用程序重新提交。

下列方法有助于最大限度地降低死锁:
1)按同一顺序访问对象。
2)避免事务中的用户交互。
3)保持事务简短并在一个批处理中。
4)使用低隔离级别。
5)使用绑定连接。

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

推荐阅读更多精彩内容