Innodb_锁(一)


  MySql——Innodb 是主流存储引擎

  所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁。 一种情形,此时执行程序中两个或多个线程发生永久堵塞(等待),每个线程都在等待被其他线程占用并堵塞了的资源。例如,如果线程A锁住了记录1并等待记录 2,而线程B锁住了记录2并等待记录1,这样两个线程就发生了死锁现象。计算机系统中,如果系统的资源分配策略不当,更常见的可能是程序员写的程序有错误等,则会导致进程因竞争资源不当而产生死锁的现象。锁有多种实现方式,比如意向锁,共享-排他锁,锁表,树形协议,时间戳协议等等。锁还有多种粒度,比如可以在表上加锁,也可以在记录上加锁。

  产生死锁的四个必要条件:

  (1) 互斥条件:一个资源每次只能被一个进程使用。

  (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

  (3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

  (4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

  这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

  死锁的预防和解除:

  理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的情况下占用资源,在系统运行过程中,对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,若分配后系统可能发生死锁,则不予分配,否则予以分配 。因此,对资源的分配要给予合理的规划。

  如何将死锁减至最少

  虽然不能完全避免死锁,但可以使死锁的数量减至最少。将死锁减至最少可以增加事务的吞吐量并减少系统开销,因为只有很少的事务回滚,而回滚会取消事务执行的所有工作。由于死锁时回滚而由应用程序重新提交。

  下列方法有助于最大限度地降低死锁:

  (1)按同一顺序访问对象

  (2)避免事务中的用户交互

  (3)保持事务简短并在一个批处理中

  (4)使用低隔离级别

  (5)使用绑定连接

  按同一顺序访问对象

  如果所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。例如,如果两个并发事务获得 Supplier 表上的锁,然后获得 Part 表上的锁,则在其中一个事务完成之前,另一个事务被阻塞在 Supplier 表上。第一个事务提交或回滚后,第二个事务继续进行。不发生死锁。将存储过程用于所有的数据修改可以标准化访问对象的顺序。

  避免事务中的用户交互

  避免编写包含用户交互的事务,因为运行没有用户交互的批处理的速度要远远快于用户手动响应查询的速度,例如答复应用程序请求参数的提示。例如,如果事务正在等待用户输入,而用户去吃午餐了或者甚至回家过周末了,则用户将此事务挂起使之不能完成。这样将降低系统的吞吐量,因为事务持有的任何锁只有在事务提交或回滚时才会释放。即使不出现死锁的情况,访问同一资源的其它事务也会被阻塞,等待该事务完成。

  保持事务简短并在一个批处理中

  在同一数据库中并发执行多个需要长时间运行的事务时通常发生死锁。事务运行时间越长,其持有排它锁或更新锁的时间也就越长,从而堵塞了其它活动并可能导致死锁。

  保持事务在一个批处理中,可以最小化事务的网络通信往返量,减少完成事务可能的延迟并释放锁。

  使用低隔离级别

  确定事务是否能在更低的隔离级别上运行。执行提交读允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。使用较低的隔离级别(例如提交读)而不使用较高的隔离级别(例如可串行读)可以缩短持有共享锁的时间,从而降低了锁定争夺。

  使用绑定连接

  使用绑定连接使同一应用程序所打开的两个或多个连接可以相互合作。次级连接所获得的任何锁可以象由主连接获得的锁那样持有,反之亦然,因此不会相互阻塞。

 

  1,mysql>;; select * FROM INFORMATION_SCHEMA.INNODB_TRX\G --表记录当前运行的所有事务!

  *************************** 1. row ***************************

  下面对 innodb_trx 表的每个字段进行解释:

  trx_id:事务ID。

  trx_state:事务状态,有以下几种状态:RUNNING、LOCK WAIT、ROLLING BACK 和 COMMITTING。

  trx_started:事务开始时间。

  trx_requested_lock_id:事务当前正在等待锁的标识,可以和 INNODB_LOCKS 表 JOIN 以得到更多详细信息。

  trx_wait_started:事务开始等待的时间。

  trx_weight:事务的权重。

  trx_mysql_thread_id:事务线程 ID,可以和 PROCESSLIST 表 JOIN。

  trx_query:事务正在执行的 SQL 语句。

  trx_operation_state:事务当前操作状态。

  trx_tables_in_use:当前事务执行的 SQL 中使用的表的个数。

  trx_tables_locked:当前执行 SQL 的行锁数量。

  trx_lock_structs:事务保留的锁数量。

  trx_lock_memory_bytes:事务锁住的内存大小,单位为 BYTES。

  trx_rows_locked:事务锁住的记录数。包含标记为 DELETED,并且已经保存到磁盘但对事务不可见的行。

  trx_rows_modified:事务更改的行数。

  trx_concurrency_tickets:事务并发票数。

  trx_isolation_level:当前事务的隔离级别。

  trx_unique_checks:是否打开唯一性检查的标识。

  trx_foreign_key_checks:是否打开外键检查的标识。

  trx_last_foreign_key_error:最后一次的外键错误信息。

  trx_adaptive_hash_latched:自适应散列索引是否被当前事务锁住的标识。

  trx_adaptive_hash_timeout:是否立刻放弃为自适应散列索引搜索 LATCH 的标识。

 

  2,mysql>;; select * from information_schema.INNODB_LOCKS\G --记录当前出现的锁!

  *************************** 1. row ***************************

  下面对 innodb_locks 表的每个字段进行解释:

  lock_id:锁 ID。

  lock_trx_id:拥有锁的事务 ID。可以和 INNODB_TRX 表 JOIN 得到事务的详细信息。

  lock_mode:锁的模式。有如下锁类型:行级锁包括:S、X、IS、IX,分别代表:共享锁、排它锁、意向共享锁、意向排它锁。表级锁包括:S_GAP、X_GAP、IS_GAP、IX_GAP 和 AUTO_INC,分别代表共享间隙锁、排它间隙锁、意向共享间隙锁、意向排它间隙锁和自动递增锁。

  lock_type:锁的类型。RECORD 代表行级锁,TABLE 代表表级锁。

  lock_table:被锁定的或者包含锁定记录的表的名称。

  lock_index:当 LOCK_TYPE=’RECORD’ 时,表示索引的名称;否则为 NULL。

  lock_space:当 LOCK_TYPE=’RECORD’ 时,表示锁定行的表空间 ID;否则为 NULL。

  lock_page:当 LOCK_TYPE=’RECORD’ 时,表示锁定行的页号;否则为 NULL。

  lock_rec:当 LOCK_TYPE=’RECORD’ 时,表示一堆页面中锁定行的数量,亦即被锁定的记录号;否则为 NULL。

  lock_data:当 LOCK_TYPE=’RECORD’ 时,表示锁定行的主键;否则为NULL。

 

  3,mysql>;; select * from information_schema.INNODB_LOCK_WAITS\G --表记录锁等待的对应关系!

  *************************** 1. row ***************************

  下面对 innodb_lock_waits 表的每个字段进行解释:

  requesting_trx_id:请求事务的 ID。

  requested_lock_id:事务所等待的锁定的 ID。可以和 INNODB_LOCKS 表 JOIN。

  blocking_trx_id:阻塞事务的 ID。

  blocking_lock_id:某一事务的锁的 ID,该事务阻塞了另一事务的运行。可以和 INNODB_LOCKS 表 JOIN。

 

  *************************** (MySQL简单粗暴查询命令句)***************************

  show engine innodb status\G; ——-查看造成死锁的sql命令语句,

  mysql>; mysql -uroot -phuimin09***; -----------#数据库,用户名,密码,登录密码

  mysql>; show processlist; ---------#查看查看当前连接线程 (show full processlist;查看全部)

  mysql>; kill id --------#杀死sql进程;

 --------------------------------查看死锁的SQL语句

  SELECT /*+ rule */ s.username,decode(l.type,'TM','TABLE LOCK','TX','ROW LOCK',NULL) LOCK_LEVEL,o.owner,o.object_name,o.object_type,s.sid,s.serial#,s.terminal,s.machine,s.program,s.osuserFROM v$session s,v$lock l,dba_objects oWHERE l.sid = s.sidAND l.id1 = o.object_id(+)

  AND s.username is NOT NULL

  ----------解决死锁的语句

  alter system kill session s.sid,s.serial#-----将s.sid,s.serial#字段处的数字复制过来,执行这条语句。

  ******************************************************