大家都知道java里面的synchronized,对象锁。(这里不扯什么类锁,对象锁,类锁其实就是Class对象的对象锁)
A线程拿o对象的锁之后,其他的线程访问o对象的锁都需等待。
那MySQL的表锁就是针对于表的。(行锁就是行的呗)
MySQL锁是啥?
锁顾名思义,解决因资源共享,而造成的并发问题。
1,表锁
MyISAM 存储引擎默认为表锁。不想解释太多上例子大家都懂了。
第一个客户端,为了好举例子先开一个事务,不然看不到效果,然后修改job表,修改完之后先不提交,看第二个客户端。
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update job set jobName= 'Java开发工程师' where jobName = 'Java开发工程师';
Query OK, 0 rows affected (0.28 sec)
Rows matched: 3872 Changed: 0 Warnings: 0
mysql>
第二个客户端,依然修改这个表,一样的执行一个update语句,发现这个时候卡住不动了?
不要以为你dos卡了😅,这个时候是你的第一个客户端获取了job 表的锁,但是并没有提交事务也就是没有释放锁所导致的
mysql> update job set jobName = '.net工程师' where jobName = '.net工程师';
........等待中
那么接下来给一个客户端commit 试试。
mysql> update job set jobName = '.net工程师' where jobName = '.net工程师';
Query OK, 0 rows affected (33.14 sec)
Rows matched: 1286 Changed: 0 Warnings: 0
这时候看到了吧,你的第一个客户端一提交事务,你的第二个客户端马上执行成功了,这个时候就是你的第一个客户端释放锁之后,第二个客户端就拿到锁去执行语句啦,这样就非常好理解啦。
2,行锁
InnoDB 默认使用行锁,既然知道了表锁,那么行锁的概念也很好理解,粒度更加细的一个锁。
行锁的一个大前提需要知道的就是对于行的条件必须是索引列,如果不是索引列则上升为表锁(划重点)
那么也举一个例子同上
先是修改job 表的某条数据,首先你的serialNo必须是索引列,否则会上升为表锁
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update job set serialNo = '116004626' where serialNo = '116004626';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
mysql>
继续第二个客户端看
mysql> update job set serialNo = '116004626' where serialNo = '116004627';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0 Changed: 0 Warnings: 0
mysql>
这时候看,其实行锁已经生效了,因为我第二个客户端和第一个客户端修改的同一张表,但第二个客户端并没有进入等待。
说明第一个客户端只在 serialNo = '116004626' 这条记录上加锁了。
那么继续看如果我们在第二个客户端继续修改serialNo = '116004626' 这条记录,会怎么样?
mysql> update job set serialNo = '116004626' where serialNo = '116004626';
........等待中
可以看到情况跟上面表锁是一样的。进入等待了,这时候我们依然继续commit第一个客户端的事务
mysql> update job set serialNo = '116004626' where serialNo = '116004626';
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> update job set serialNo = '116004626' where serialNo = '116004626';
Query OK, 0 rows affected (0.00 sec)
😅不好意思超时了,重新执行一下可以看到成功了,虽然超时了但是也是在commit 之后出现的,只要第一个客户端的事务不提交那么其他客户端对这条数据的写操作都会进行等待。