InnoDB引擎的行锁和表锁
mysql常用引擎有MYISAM和InnoDB,MYISAM不支持行锁,InnoDB支持行锁和表锁。mysql的行锁是通过索引加载的,所以说行锁是加在索引行上的。要是对应的SQL语句没有走索引,则会全表扫描,行锁则无法实现,取而代之的是表锁。
- 表锁不会出现死锁,发生锁冲突几率高,并发低。
行锁会出现死锁,发生锁冲突几率低,并发高。
锁冲突
比如事务A将某几行上锁后,事务B又对其上锁,锁不能共存否则会出现锁冲突。(共享锁可以共存,共享锁和排它锁不能共存,排它锁和排他锁也不可以)
- 死锁
比如两个事务,事务A锁住了15行,同时事务B锁住了610行,此时事务A请求锁住610行,就会阻塞直到事务B施放610行的锁,而随后事务B又请求锁住15行,事务B也阻塞直到事务A释放15行的锁。死锁发生时,会产生Deadlock错误。(表锁是对表操作的,所以自然锁住全表的表锁就不会出现死锁)
- 行锁的类型
行锁分 共享锁 和 排它锁。
-
- 共享锁(读锁) 当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,但不允许其进行写操作,也不允许其他事务给这几行上排它锁,但允许上读锁。
例:select a1 from test where a1>1 lock in share mode;
-
- 排它锁(写锁)
当一个事务对某几个上写锁时,不允许其他事务写,但允许读。更不允许其他事务给这几行上任何锁。包括写锁。
例:select a1 from test where a1 >1 for update;
- 行锁的实现要注意
-
- 行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。
-
- 两个事务不能锁同一个索引 如: 1、select a1 from test where a1>2 for update; 2、select a1 from test where a2<2 for update; 要是1先执行2接着执行2就会阻塞但是把索引字段换成其他的就不会阻塞了(换成其他索引锁住的行不能和1索引锁住的行有重复)
-
3.insert ,delete , update在事务中都会自动默认加上排它锁。