mysql常用引擎有MYISAM和InnoDB,而InnoDB是mysql默认的引擎。MYISAM不支持行锁,而InnoDB支持行锁和表锁。
1.行锁和表锁 2.行锁的类型 3.行锁的实现
在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索引锁住的行有重复。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时或者程序结束时,会释放锁。
原文:https://blog.csdn.net/u014453898/article/details/56068841?biz_id=102&utm_term=mysql%20%E5%BC%95%E6%93%8E%E8%A1%8C%E9%94%81%20%E5%AE%9E%E7%8E%B0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-3-56068841&spm=1018.2118.3001.4187
