行锁和表锁的理解

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

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

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

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

锁是对表操作的,所以自然锁住全表的表锁就不会出现死锁。
行锁:
共享锁又称:读锁。当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,但不允许其进行写操作,也不允许其他事务给这几行上写锁。(读写锁不能共存,读的时候不能让其它事务进行写操作,更不能上写锁,如果其其它事务对同一行上读锁的话会造成该事务的阻塞)。
排它锁又称:写锁。当一个事务对某几行上写锁时,不允许其他事务写,但允许读(如果读也就是查,不上读锁可能是脏读,上读锁之后等待对应事务提交或者回滚后方可读到实时数据)。更不允许其他事务给这几行上任何锁(读锁会阻塞)。包括写锁。

上共享锁的写法: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;

注意几点:
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索引锁住的行有重复

insert ,delete , update在事务中都会自动默认加上排它锁(写)。
会话1:select math from zje where math>60 for update;
会话2:update zje set math=99 where math=68;阻塞…
如上,会话1先把zje表中math>60的行上排它锁。然后会话2试图把math=68的行进行修改,math=68处于math>60中,所以是已经被锁的,会话2进行操作时,
就会阻塞,等待会话1把锁释放。当commit时或者程序结束时,会释放锁。

猜你喜欢

转载自blog.csdn.net/qq_40826106/article/details/83143981