行锁顾名思义,就是针对单行数据加锁,在mysql中,锁的实现是由引擎层实现的,MyISAM引擎就不支持行锁不支持行锁就意味着并发控制只能使用表锁,也就是说同一时间,在这个表上只能有一个更新在执行,这就会影响到业务的并发度。InnoDB是支持行锁的,这也是MyISAM被InnoDB替代的重要原因之一。 两阶段锁协议
先举个例子,事务B的语句执行的时候会发生什么现象?这取决于事务A在执行完两条语句后持有那些锁,以及在什么时候释放?大家可以自己做个实验,是这样的,事务B在执行这条语句时会被阻塞,大家会不会有疑惑,前面两条语句不是执行完了吗?为什么还会阻塞?其实事务A的加锁时机是执行第一条语句的时候,释放锁的时候是commit完以后但是事务B是在事务A commit前执行的这个时候事务A还持有id=1这行数据的锁,所以事务B会被阻塞。 知道了这个原理对于我们有什么启示呢?既然知道了锁的释放是在commit之后那么我们就可以把最可能造成锁冲突最可能影响并发度的锁尽量往后放举个例子:业务:顾客A要在影院B买一张电影票操作:1.从顾客A的账户余额中减掉电影票的价格2.将影院B的账户余额增加这张电影票价3.增加一条操作日志 大家想想看,这三个操作,那个最容易影响到并发度会造成锁冲突很明显是第二个操作,为啥呢?想想看操作1中只是锁了这个用户的这行数据,只对他自己有影响,这个时候如果有个顾客C也买了电影票,那么这个时候的冲突就是操作2了,因为人家也需要更新影院的账户余额,所以我们要把操作2放在最后执行,因为这样对操作2涉及的行锁,锁住时间就会少一点,最大程度的减少了事务之间的等待提升了并发度。 死锁和死锁检测如图所示,事务A在等待事务B释放id=2的锁,事务B在等待事务A释放id=1的锁这种情况就是死锁发生死锁有两种方法解决1.直接进入等待,直到超时。这个超时时间可以通过参数innodb_lock_wait_timeout来设置2.发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以执行。 将参数innodb_deadlock_detect设置为on,表示开启这个逻辑在innodb中,innodb_lock_wait_timeout的值默认是50s,以为着如果使用第一种方法,第一个被锁住的线程要过50s才会超时退出,然后其他线程才有可能继续执行。对于在线服务来说,这个等待时间往往是无法接受的。 但是我们又不能把这个时间设置的很小,比如1s,如果这个时候不是死锁,而是正常的锁等待呢这样就会造成很多误伤,所以我们还是使用死锁检测好一些,好在innodb_deadlock_detect默认就是on 其实死锁检测也是会占用很多cpu资源的,当事务被锁住的时候,就要看看它锁依赖的线程有没有被别人锁住如此循环,最后判断是否出现了循环等待,也就是死锁
先举个例子,事务B的语句执行的时候会发生什么现象?这取决于事务A在执行完两条语句后持有那些锁,以及在什么时候释放?大家可以自己做个实验,是这样的,事务B在执行这条语句时会被阻塞,大家会不会有疑惑,前面两条语句不是执行完了吗?为什么还会阻塞?其实事务A的加锁时机是执行第一条语句的时候,释放锁的时候是commit完以后但是事务B是在事务A commit前执行的这个时候事务A还持有id=1这行数据的锁,所以事务B会被阻塞。 知道了这个原理对于我们有什么启示呢?既然知道了锁的释放是在commit之后那么我们就可以把最可能造成锁冲突最可能影响并发度的锁尽量往后放举个例子:业务:顾客A要在影院B买一张电影票操作:1.从顾客A的账户余额中减掉电影票的价格2.将影院B的账户余额增加这张电影票价3.增加一条操作日志 大家想想看,这三个操作,那个最容易影响到并发度会造成锁冲突很明显是第二个操作,为啥呢?想想看操作1中只是锁了这个用户的这行数据,只对他自己有影响,这个时候如果有个顾客C也买了电影票,那么这个时候的冲突就是操作2了,因为人家也需要更新影院的账户余额,所以我们要把操作2放在最后执行,因为这样对操作2涉及的行锁,锁住时间就会少一点,最大程度的减少了事务之间的等待提升了并发度。 死锁和死锁检测如图所示,事务A在等待事务B释放id=2的锁,事务B在等待事务A释放id=1的锁这种情况就是死锁发生死锁有两种方法解决1.直接进入等待,直到超时。这个超时时间可以通过参数innodb_lock_wait_timeout来设置2.发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以执行。 将参数innodb_deadlock_detect设置为on,表示开启这个逻辑在innodb中,innodb_lock_wait_timeout的值默认是50s,以为着如果使用第一种方法,第一个被锁住的线程要过50s才会超时退出,然后其他线程才有可能继续执行。对于在线服务来说,这个等待时间往往是无法接受的。 但是我们又不能把这个时间设置的很小,比如1s,如果这个时候不是死锁,而是正常的锁等待呢这样就会造成很多误伤,所以我们还是使用死锁检测好一些,好在innodb_deadlock_detect默认就是on 其实死锁检测也是会占用很多cpu资源的,当事务被锁住的时候,就要看看它锁依赖的线程有没有被别人锁住如此循环,最后判断是否出现了循环等待,也就是死锁
解决方案 »
- 出现错误信息 #1054 - Unknown column 's.t_star_k' in 'on clause',请高手帮忙
- 如何让一个非空字段插入null的时候,提示错误,不让其插入。
- mysql_query阻塞怎么解决?
- 类似REGEXP通配符规则 扩展号码
- 为提高性能,但Mysql分区语句怎么不能用?
- webwork中使用mysql老是报这个错误~~
- 使用sql语句如何知道一张表的表结构 sql 语句该如何写
- mysql4.1.4字符集问题???怎么修改
- 两个表中数据分类汇总合并的问题
- 每分钟请求 两万到五万次接口时,出现程序链接不上数据库
- mysql 5.7.17老版本binlog恢复出的sql无法导入数据库问题
- 创建数据表时出现提示:语法错误
1. 加一个冗余列
2. 事务一开始就同时更新这两条记录的冗余列,条件用 id IN(1,2),这样就把两条记录一起锁定了。
但是性能会低。