全局锁、表锁和行锁

1、全局锁

全局锁就是对整个数据库实例加锁,mysql提供了一个加全局读锁的方法,命令是flush tables with read lock。让你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:
a、数据更新语句
b、数据定义语句
c、更新类事务的提交语句

2、表级锁

mysql里面表级别的锁有两种:一种是表锁,一种是元数据锁
表锁的语法是lock tables …read/write,与ftwrl类似,可以用unlock tables 主动释放锁,也可以在客户端断开的时候自动释放。需要注意,lock tables语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。

3、行锁

1、行锁就是针对数据表中行记录的锁,比如事务A更新了一行,而这时候事务B也要更新一行,则必须等事务A的操作完成后才能进行更新。
2、举例如下所示:
全局锁、表锁和行锁
这个问题的结论取决于事务A在执行完两条update语句后,持有哪些锁,以及在什么时候释放,实际上事务B的update语句会被阻塞,直到事务A执行commit后,事务B才能继续执行。依旧是说,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等事务结束时才释放,这个就是两阶段锁协议。

4、死锁和死锁检测

1、当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态,称为死锁。
2、死锁的示例很简单:
全局锁、表锁和行锁
此时,事务A在等待事务B释放id=2的行锁,而事务B在等待事务A释放id=1的行锁。事务A和事务B在互相等待对方的资源释放,就是进入了死锁状态。当出现死锁以后,有两种策略:
a、一种策略是,直接进入等待,直至超时。这个超时时间可以通过参数innodb_lock_wait_timeout来设置
b、另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行,将参数innodb_deadlock_detect设置为on,表示开启这个逻辑

在Innodb中,innodb_lock_wait_timeout的默认值是50s,意味着如果采用第一个策略,当出现死锁后,第一个被锁住的线程要过50s才会超时退出,然后其他线程才有可能继续执行,对于在线服务来说,这个等待时间往往是无法接受的。但是如果设置为一个很小的值,又很容易误伤。

其实针对这种死锁出现的情况,最好还是从业务逻辑方面来进行处理。