锁的概念
锁定机制用于管理共享资源的并发访问。InnoDB存储引擎将锁定行级数据。数据库使用锁来支持共享资源的并发访问,并提供数据的完整性和一致性。
lock 与 latchlatch 它通常被称为锁(轻量级锁),因为它需要很短的时间才能锁定。在innoDB存储引擎中,latch可分为mutex(相互排斥)和rwlock(读写锁),以确保并发线程操作的临界资源的正确性。
lock的对象是用来锁定数据库的对象,如表、页、行。而一般lock的对象只在事务commit或rollback后释放。lock有死锁机制。
锁的类型Mysql可分为表锁、行锁、页锁,不同的存储引擎锁具有不同的特性。
行锁行锁就是在数据行上加锁,费用大,加锁慢,可能会出现死锁,颗粒小,发生锁冲突的概率低,并发度高。
两种类型的行锁实现在innoDB存储引擎中:
- 共享锁(s):也叫读锁。允许一个事务读一行。如果事务T将S锁添加到数据对象A中, 事务T可以读A,但不能修改A,其他事务只能加S锁,不能加X锁。
- 排他锁(X): 又称写锁,允许获取排他锁的事务更新数据,防止其他事务共享读锁和排他锁。
页锁是在每一页加锁,开销在行锁和表锁之间,会出现死锁,锁定粒度介于表锁和行锁之间,并发度一般。
表锁表锁是在表级加锁,加锁快,开销小,无死锁;锁粒度大,所以锁冲突概率高,并发度最低。
意向锁为了允许行锁和表锁共享,实现多粒度锁机制,InnoDB引入了意向锁。意向锁由InnoDB自动添加,无需用户干预,因此有意向共享锁和意向排他锁。这两种意向锁在InnoDB内部使用,属于表锁。
如果没有意向锁,会有什么问题?
如果事务A在某一行上加锁,事务B在整个表上加锁,在整个表上加锁的概念是可以随意修改表中的任何一行,但事务A已经持有了某一行的锁,这与锁发生了冲突。为了避免这种冲突,有意向锁。事务A在锁定某一行之前会在表中加入意向排他锁,所以如果事务B想锁定整个行,只能等事务A释放锁才能加。
如果一些资源想在某一行添加排他锁或共享锁,则必须首先在表中添加意向共享锁或意向排他锁。只有成功添加,才能进一步锁定所需的行。如果没有成功添加,则表明有事务在整个表中添加锁。
- 意向共享锁(IS): 事务计划为数据行共享锁,事务必须在给数据行添加共享锁之前获得表中的IS锁。
- 意向排他锁(IX): 事务计划为数据行加排他锁,事务必须在给数据行加排他锁之前获得表的IS锁。
以下是Innnodb在可重复读提交下为解决幻读问题而引入的锁机制,例如排队,a,b,c,这个时候D也来排队,但是d不能排在b旁边。怎么才能不让d排在b旁边?也就是ab和bc之间加锁,让它无法插入,相当于间隙锁。
当我们使用范围条件而不是相等条件检索数据并要求共享或排他锁时,InnoDB将锁定符合条件的现有数据记录的索引项。对于键值在条件范围内但不存在的记录,称为间隙。InnoDB还将锁定此间隙。这种锁机制称为间隙锁,除了通过范围条件锁定外,间隙锁可以使用,如果使用相等条件要求锁定不存在的记录,InnoDB也会使用间隙锁,这样就不会产生幻读。
死锁死锁是指执行过程中两个或两个以上的事务
死锁可能发生在不同的事务上,锁定多个相同的表和相同的行,但表的操作顺序不同。
解决死锁的方法- 加班机制,当两个事务相互等待,当一个等待时间超过设定的阈值时,一个事务回滚,另一个事务可以继续等待。在InnoDB存储引擎中,参数innodb_lock_wait_timeout用于设置超时时间。
- wait-for graph用于死锁检测。这是一种更活跃的死锁检测机制。当每个事务请求发生并发生等待时,它将判断是否有电路。如果有,就会有死锁。通常,innoDB存储引擎选择最小的回滚undo。
悲观并发控制(又称“悲观锁”,在关系数据库管理系统中,Pessimistic Concurrency Control,缩写“PCC)并发控制是一种方法。它可以阻止一个事务以影响其他用户的方式修改数据。如果一个事务执行的操作都是一行数据应用锁,那么只有当事务释放锁时,其他事务才能执行与锁冲突的操作。悲观并发控制主要用于数据竞争激烈的环境,并发冲突时使用锁保护数据的成本低于回滚事务的成本。
也就是说,对数据冲突采取悲观的态度,也就是说,假设数据肯定会发生冲突,所以在数据开始读取时锁定数据。
执行过程中的悲观锁在修改任何记录之前,首先尝试在记录中添加排他锁(exclusive locking)。若加锁失败,说明