mysql行级锁怎么加 mysql行锁语句( 五 )


InnoDB行锁实现方式
InnoDB行锁是通过索引上的索引项来实现的,这一点MySQL与Oracle不同,后者是通过在数据中对相应数据行加锁来实现的 。InnoDB这种行锁实现特点意味者:只有通过索引条件检索数据,InnoDB才会使用行级锁,否则,InnoDB将使用表锁!
在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突 , 从而影响并发性能 。
什么时候使用表锁
对于InnoDB表,在绝大部分情况下都应该使用行级锁,因为事务和行锁往往是我们之所以选择InnoDB表的理由 。但在个另特殊事务中,也可以考虑使用表级锁 。
第一种情况是:事务需要更新大部分或全部数据,表又比较大,如果使用默认的行锁,不仅这个事务执行效率低,而且可能造成其他事务长时间锁等待和锁冲突,这种情况下可以考虑使用表锁来提高该事务的执行速度 。
第二种情况是:事务涉及多个表 , 比较复杂,很可能引起死锁,造成大量事务回滚 。这种情况也可以考虑一次性锁定事务涉及的表,从而避免死锁、减少数据库因事务回滚带来的开销 。
当然,应用中这两种事务不能太多 , 否则,就应该考虑使用MyISAM表 。
在InnoDB下,使用表锁要注意以下两点 。
(1)使用LOCK TALBES虽然可以给InnoDB加表级锁,但必须说明的是,表锁不是由InnoDB存储引擎层管理的,而是由其上一层MySQL Server负责的,仅当autocommit=0、innodb_table_lock=1(默认设置)时 , InnoDB层才能知道MySQL加的表锁,MySQL Server才能感知InnoDB加的行锁,这种情况下,InnoDB才能自动识别涉及表级锁的死锁;否则,InnoDB将无法自动检测并处理这种死锁 。
(2)在用LOCAK TABLES对InnoDB锁时要注意,要将AUTOCOMMIT设为0,否则MySQL不会给表加锁;事务结束前 , 不要用UNLOCAK TABLES释放表锁,因为UNLOCK TABLES会隐含地提交事务;COMMIT或ROLLBACK产不能释放用LOCAK TABLES加的表级锁 , 必须用UNLOCK TABLES释放表锁,正确的方式见如下语句 。
关于死锁
MyISAM表锁是deadlock free的 , 这是因为MyISAM总是一次性获得所需的全部锁,要么全部满足,要么等待,因此不会出现死锁 。但是在InnoDB中,除单个SQL组成的事务外,锁是逐步获得的,这就决定了InnoDB发生死锁是可能的 。
发生死锁后,InnoDB一般都能自动检测到,并使一个事务释放锁并退回,另一个事务获得锁 , 继续完成事务 。但在涉及外部锁 , 或涉及锁的情况下,InnoDB并不能完全自动检测到死锁 , 这需要通过设置锁等待超时参数innodb_lock_wait_timeout来解决 。需要说明的是 , 这个参数并不是只用来解决死锁问题 , 在并发访问比较高的情况下,如果大量事务因无法立即获取所需的锁而挂起 , 会占用大量计算机资源,造成严重性能问题,甚至拖垮数据库 。我们通过设置合适的锁等待超时阈值,可以避免这种情况发生 。
通常来说,死锁都是应用设计的问题,通过调整业务流程、数据库对象设计、事务大小、以及访问数据库的SQL语句 , 绝大部分都可以避免 。下面就通过实例来介绍几种死锁的常用方法 。
(1)在应用中,如果不同的程序会并发存取多个表,应尽量约定以相同的顺序为访问表,这样可以大大降低产生死锁的机会 。如果两个session访问两个表的顺序不同 , 发生死锁的机会就非常高!但如果以相同的顺序来访问 , 死锁就可能避免 。
(2)在程序以批量方式处理数据的时候 , 如果事先对数据排序,保证每个线程按固定的顺序来处理记录,也可以大大降低死锁的可能 。

推荐阅读