在日常开发工作中,我们几乎需要天天与数据库打交道,作为一名只会CRUD的SQLBOY,除了每天用mybatis-generator自动生成DAO层代码之外,我们几乎不用去care数据库中如何处理并发请求,但是突然某一天MYSQL数据库告警了,出现了死锁,我们的内心慌的一匹,不禁想问:这不就是个普通查询吗,咋还锁起来了?
为了避免慌乱的表情被主管捕捉到,我们需要提前了解一下数据库中到底有哪些锁。
在MySQL中,其实将锁分成了两类:锁类型(lock_type)和锁模式(lock_mode)。
锁类型描述的锁的粒度,也就是把锁具体加在什么地方;而锁模式描述的是到底加的是什么锁,是读锁还是写锁。锁模式通常和锁类型结合使用。
按锁的模式分?读锁读锁,又叫共享锁/S锁/sharelocks。读锁是某个事务(比如事务A)在进行读取操作(比如读一张表或者读取某一行)时创建出来的锁,其他的事务可以并发地读取这些数据(被加了锁的),但是不能修改这些数据(除非持有锁的用户已经释放锁)。事务A对数据加上读锁之后,其他事务依然可以对其添加读锁(共享),但是不能添加写锁。在记录上加读锁InnoDB支持表锁和行锁,在行(也就是记录)上加锁,并不是锁住该条记录,而是在记录对应的索引上加锁。如果where条件中不走索引,则会对所有的记录加锁。
显式加锁语句为:
select*from{tableName}where{condition}lockinsharemode;
注意:这里所说的读,是指当前读,快照读是无需加锁的。普通select读一般都是快照读,除了select...lockinsharemode这样的显式加锁语句下会变成当前读,在InnoDB引擎的serializable级别下,普通select读也会变成快照读。
另外需要注意,对于行锁的加锁过程分析,要根据事务隔离级别、是否使用索引(哪种类型的索引)、记录是否存在等因素结合分析,才能判断在哪里加上了锁。
innodb引擎中的加读锁的几种情形普通查询在隔离级别为serializable会给记录加S锁。但这也取决于场景:非事务读(auto-