通过本文我们将了解以下几个问题?
一、思考
问题一:多线程下,MYSQL是如何同步的?
比如多个线程同时要更新某一行数据,这时候MYSQL的处理机制是什么?
问题二:MYSQL中有哪些锁?其作用都是什么?
相比大家听说过行锁、表锁、乐观锁、悲观锁、间隙锁、死锁、共享锁、排它锁这些概念,本文将探索这些锁是干嘛的。
二、分析
接下来我们将一一揭开MYSQL中各种锁的面纱。
2.1行锁和表锁
针对锁粒度的不同,分别有行锁和表锁之分,表锁针对的是整个表,而行锁针对的是数据行。MYSIAM采用表锁机制,而InnoDB默认采用行锁机制,但是InnoDB也支持表锁。
行级锁和表级锁比较:
表级锁
优点
- 加锁速度更快,开销更小。
- 不会产生死锁情况。
缺点
- 因为其针对整个表加锁,所以锁粒度更大,并发情况下竞争锁时冲突概率更高,即并发度更低。
行级锁
优点
- 锁粒度更小,并发情况下竞争锁时冲突概率更低,即并发度更高。
缺点
- 加锁速度慢,开销大。
- 可能产生死锁。
这里为什么表锁不会产生死锁呢,假如一个线程获取锁的顺序是A表,B表,另一线程是B表,A表,不是仍然可能死锁吗?
这是因为MyISAM存储引擎通过总是一次性同时获取所有需要的锁以及总是按相同的顺序获取表锁来避免死锁。
MySIAM中表级锁的实现模式:
表共享读锁:当查询某个表,MySIAM会给此表加读锁,允许其他线程对该表的读操作,阻塞对该表的写操作。
表独占写锁:当更新某个表数据时,MySIAM会给该表加写锁,阻塞其他线程对该表的读和写。
MyISAM存储引擎中默认写锁的优先级会高于读锁。但是也可以通过以下参数降低更新操作的优先级,避免查询时间太长,导致查询线程饿死情况。具体操作请参考博文:https://www.cnblogs.com/zhoujinyi/p/3337347.html。
如何加表锁:
MySIAM存储引擎在读取数据时,会自动为表加共享读锁,更新数据时为表加独占写锁,因此一般情况下不需要手动加表锁。那如何采用手动方式加表锁呢?可以通过如下方式:
加共享读锁:lock tables t read/read local;read和read local的区别在于对于read local这种共享读锁,不会阻塞其它线程的插入操作,但是更新操作依然阻塞。
加独占写锁:lock tables t write;