wordpress代码实现网站地图,建站公司兴田德润,如何做购物网站的后台,置顶 wordpress今天在开发测试时候出现了锁表#xff0c;原因是因为我在本地开启了事务#xff0c;代码中打了断点#xff0c;然后测试同学测试时候出现了锁表#xff0c;我去排查了问题#xff0c;然后找到相关的资料了解下#xff0c;
总结#xff1a;原因的表没有加索引#xff0…今天在开发测试时候出现了锁表原因是因为我在本地开启了事务代码中打了断点然后测试同学测试时候出现了锁表我去排查了问题然后找到相关的资料了解下
总结原因的表没有加索引所以走了全表扫描这时候开启了事务没有commit。这时候另一个人想写表发现表被锁了然后测试同学说mysql是行锁mysql确实支持行锁但是前提条件是要走索引不然就锁表
一、前言
对于行锁和表锁的含义区别在面试中应该是高频出现的我们应该对MySQL中的锁有一个系统的认识更详细的需要自行查阅资料本篇为概括性的总结回答。
MySQL常用引擎有MyISAM和InnoDB而InnoDB是mysql默认的引擎。MyISAM不支持行锁而InnoDB支持行锁和表锁。
如何加锁
MyISAM在执行查询语句SELECT前会自动给涉及的所有表加读锁在执行更新操作UPDATE、DELETE、INSERT等前会自动给涉及的表加写锁这个过程并不需要用户干预因此用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。
显式加锁
上共享锁读锁的写法lock in share mode例如
select math from zje where math60 lock in share mode上排它锁写锁的写法for update例如
select math from zje where math 60 for update
二、表锁
不会出现死锁发生锁冲突几率高并发低。
MyISAM引擎
MyISAM在执行查询语句select前会自动给涉及的所有表加读锁在执行增删改操作前会自动给涉及的表加写锁。
MySQL的表级锁有两种模式 表共享读锁 表独占写锁
读锁会阻塞写写锁会阻塞读和写 对MyISAM表的读操作不会阻塞其它进程对同一表的读请求但会阻塞对同一表的写请求。只有当读锁释放后才会执行其它进程的写操作。 对MyISAM表的写操作会阻塞其它进程对同一表的读和写操作只有当写锁释放后才会执行其它进程的读写操作。
MyISAM不适合做写为主表的引擎因为写锁后其它线程不能做任何操作大量的更新会使查询很难得到锁从而造成永远阻塞
三、行锁
会出现死锁发生锁冲突几率低并发高。
在MySQL的InnoDB引擎支持行锁与Oracle不同MySQL的行锁是通过索引加载的也就是说行锁是加在索引响应的行上的要是对应的SQL语句没有走索引则会全表扫描行锁则无法实现取而代之的是表锁此时其它事务无法对当前表进行更新或插入操作。 CREATE TABLE user (name VARCHAR(32) DEFAULT NULL,count INT(11) DEFAULT NULL,id INT(11) NOT NULL AUTO_INCREMENT,PRIMARY KEY (id)
) ENGINEINNODB AUTO_INCREMENT7 DEFAULT CHARSETutf8-- 这里我们建一个user表主键为id-- A通过主键执行插入操作但事务未提交
update user set count10 where id1;
-- B在此时也执行更新操作
update user set count10 where id2;
-- 由于是通过主键选中的为行级锁A和B操作的不是同一行B执行的操作是可以执行的-- A通过name执行插入操作但事务未提交
update user set count10 where namexxx;
-- B在此时也执行更新操作
update user set count10 where id2;-- 由于是通过非主键或索引选中的升级为为表级锁-- B则无法对该表进行更新或插入操作只有当A提交事务后B才会成功执行
for update
如果在一条select语句后加上for update则查询到的数据会被加上一条排它锁其它事务可以读取但不能进行更新和插入操作
-- A用户对id1的记录进行加锁
select * from user where id1 for update;-- B用户无法对该记录进行操作
update user set count10 where id1;-- A用户commit以后则B用户可以对该记录进行操作行锁的实现需要注意 行锁必须有索引才能实现否则会自动锁全表那么就不是行锁了。 两个事务不能锁同一个索引。 insertdeleteupdate在事务中都会自动默认加上排它锁。
行锁场景
A用户消费service层先查询该用户的账户余额若余额足够则进行后续的扣款操作这种情况查询的时候应该对该记录进行加锁。 否则B用户在A用户查询后消费前先一步将A用户账号上的钱转走而此时A用户已经进行了用户余额是否足够的判断则可能会出现余额已经不足但却扣款成功的情况。 为了避免此情况需要在A用户操作该记录的时候进行for update加锁
扩展间隙锁
当我们用范围条件而不是相等条件检索数据并请求共享或排他锁时InnoDB会给符合条件的已有数据记录的索引项加锁对于键值在条件范围内并不存在的记录叫做间隙
InnoDB也会对这个间隙加锁这种锁机制就是所谓的间隙锁
-- 用户A
update user set count8 where id2 and id6-- 用户B
update user set count10 where id5;如果用户A在进行了上述操作后事务还未提交则B无法对2~6之间的记录进行更新或插入记录会阻塞当A将事务提交后B的更新操作会执行。
建议 尽可能让所有数据检索都通过索引来完成避免无索引行锁升级为表锁 合理设计索引尽量缩小锁的范围 尽可能减少索引条件避免间隙锁 尽量控制事务大小减少锁定资源量和时间长度