MySQL的锁有以下几种形式:
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。MyISAM引擎属于这种类型。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生所冲突的概率最低,并发度高。InnoDB引擎属于这种类型。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。NDB引擎属于这种类型。
MyISAM只支持表锁,所以对MyISAM表进行操作,会存在以下情况:
对MyISAM表的读操作(加读锁),不会阻塞其他进程对同一表的读操作,但会阻塞对同一表的写操作。只有读锁释放后,才会执行其他进程的写操作。
对MyISAM表的写操作(加写锁),会阻塞其它进程对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作。
InnoDB存储引擎是通过给索引项加锁来实现的,这就意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。
在并发访问比较高的情况下,如果大量事务因无法立即获得所需的锁而挂起,会占用大量计算机资源,造成严重的性能问题,甚至拖跨数据库,这时需要通过设置合适的锁等待超时阈值参数innodb_lock_wait_timeout来解决,一般设置为100秒即可。
死锁
两个事务都要获得对方持有的排他锁才能继续完成事务,这种循环锁等待就是典型的死锁。
发生死锁后,InnoDB一般都能自动检测到,它会让一个事务释放锁并回退,另一个事务则获得锁,继续完成事务。死锁是无法避免的,我们可以通过调整的业务逻辑来尽量减少死锁出现的概率。