mysql常用引擎有MYISAM和InnoDB,而InnoDB是mysql默认的引擎。MYISAM不支持行锁,而InnoDB支持行锁和表锁。


1.行锁和表锁

2.行锁的类型

3.行锁的实现



1.行锁和表锁

在mysql 的 InnoDB引擎支持行锁,与Oracle不同,mysql的行锁是通过索引加载的,即是行锁是加在索引响应的行上的,要是对应的SQL语句没有走索引,则会全表扫描,

行锁则无法实现,取而代之的是表锁。


表锁:不会出现死锁,发生锁冲突几率高,并发低。

行锁:会出现死锁,发生锁冲突几率低,并发高。


锁冲突:例如说事务A将某几行上锁后,事务B又对其上锁,锁不能共存否则会出现锁冲突。(但是共享锁可以共存,共享锁和排它锁不能共存,排它锁和排他锁也不可以)

死锁:例如说两个事务,事务A锁住了1~5行,同时事务B锁住了6~10行,此时事务A请求锁住6~10行,就会阻塞直到事务B施放6~10行的锁,而随后事务B又请求锁住1~5行,事务B也阻塞直到事务A释放1~5行的锁。死锁发生时,会产生Deadlock错误。


锁是对表操作的,所以自然锁住全表的表锁就不会出现死锁。

2.行锁的类型

行锁分 共享锁 和 排它锁。

共享锁又称:读锁。当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,但不允许其进行写操作,也不允许其他事务给这几行上排它锁,但允许上读锁。

排它锁又称:写锁。当一个事务对某几个上写锁时,不允许其他事务写,但允许读。更不允许其他事务给这几行上任何锁。包括写锁。


上共享锁的写法:lock in share mode

例如: select  math from zje where math>60 lock in share mode;


上排它锁的写法:for update

例如:select math from zje where math >60 for update;


3.行锁的实现

注意几点:

1.行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。

2.两个事务不能锁同一个索引,例如:


事务A先执行:
select math from zje where math>60 for update;

事务B再执行:
select math from zje where math<60 for update;
这样的话,事务B是会阻塞的。如果事务B把 math索引换成其他索引就不会阻塞,但注意,换成其他索引锁住的行不能和math索引锁住的行有重复。



3

.insert ,delete , update在事务中都会自动默认加上排它锁。

实现:


会话1:

begin;

select  math  from zje where math>60 for update;


会话2:


begin;

update zje set math=99 where math=68;

阻塞...........

会话相当与用户

如上,会话1先把zje表中math>60的行上排它锁。然后会话2试图把math=68的行进行修改,math=68处于math>60中,所以是已经被锁的,会话2进行操作时,

就会阻塞,等待会话1把锁释放。当commit时或者程序结束时,会释放锁。