欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

记录所有语 CAD加密 句和指令

点击: 次  来源:宝鼎软件 时间:2017-11-25

原文出处: xrzs

最近线上 MySQL 接连产生了几起数据异常,都是在破晓发作,由于业务场景属于典范的数据客栈型应用,白日压力较小无法复现。甚至有些异常还较量诡异,最后 root cause 阐明颇费周折。那实际业务傍边咱们如何能快速的定位线上 MySQL 问题,修复异常呢?下文我会按照两个实际 case,分享下相关的履历与要领。

1、Case1:部门数据更新失败

某天渠道同学反馈某报表极个体渠道数据为 0,大部门渠道数据正常。这个数据是由一个统计措施天天破晓例行更新的,按理来说,要么全部正常,要么全部失败,那会是什么原因导致极个体数据异常呢?

首先我们能想到的自然是按照统计任务日志来看了,可是看了统计措施打印的日志没有发明诸如 SQL update 失败的异常描写,那其时的数据库毕竟产生了什么呢?在查察 MySQL-server 日志之前,习惯性的看了下数据库状态:

SHOW ENGINE INNODB STATUS\G

刚悦目到了破晓这个 update 产生了死锁:

------------------------
LATEST DETECTED DEADLOCK
------------------------
2017-07-17 04:09:01 0x7f6de03c8700
*** (1) TRANSACTION:
TRANSACTION 215208479, ACTIVE 0 sec fetching rows
mysql tables in use 3, locked 3
LOCK WAIT 5 lock struct(s), heap size 1136, 3 row lock(s)
MySQL thread id 27844824, OS thread handle 140092183037696, query id 412503674 10.126.95.84 zeye Searching rows for update
update t_channel_final_datas set nr_register=133,nr_add_goods=29,nr_order_normal=11,nr_pay_normal=8,nr_order_special=0,nr_pay_special=0,n_add_user_num=16 where count_date='2017-07-16' and channel_id='16' and channel_type='10' and terminal='26'
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 464 page no 5459 n bits 392 index index_countdate_type_terminal of table `db_zz_flow`.`t_channel_final_datas` trx id 215208479 lock_mode X locks rec but not gap waiting
Record lock, heap no 304 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 10; hex 323031372d30372d3136; asc 2017-07-16;;
 1: len 1; hex 30; asc 0;;
 2: len 4; hex 80000010; asc     ;;
 3: len 4; hex 8009055e; asc    ^;;

*** (2) TRANSACTION:
TRANSACTION 215208474, ACTIVE 0 sec fetching rows
mysql tables in use 3, locked 3
6 lock struct(s), heap size 1136, 7 row lock(s)
MySQL thread id 27844825, OS thread handle 140109890225920, query id 412503669 10.135.6.41 zeye Searching rows for update
update t_channel_final_datas set nr_register=24,nr_add_goods=32,nr_order_normal=0,nr_pay_normal=0,nr_order_special=0,nr_pay_special=0,n_add_user_num=11 where count_date='2017-07-16' and channel_id='114' and channel_type='10' and terminal='116'
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 464 page no 5459 n bits 392 index index_countdate_type_terminal of table `db_zz_flow`.`t_channel_final_datas` trx id 215208474 lock_mode X locks rec but not gap
Record lock, heap no 304 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 10; hex 323031372d30372d3136; asc 2017-07-16;;
 1: len 1; hex 30; asc 0;;
 2: len 4; hex 80000010; asc     ;;
 3: len 4; hex 8009055e; asc    ^;;

...

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 464 page no 4743 n bits 264 index PRIMARY of table `db_zz_flow`.`t_channel_final_datas` trx id 215208474 lock_mode X locks rec but not gap waiting
Record lock, heap no 168 PHYSICAL RECORD: n_fields 32; compact format; info bits 0
 0: len 4; hex 80090569; asc    i;;
 1: len 6; hex 00000cd3b9d0; asc       ;;
...

*** WE ROLL BACK TRANSACTION (1)

篇幅所限,上下文我这里省略了许多,从这段日志里可以看到,昆山软件开发,TRANSACTION 1 和 TRANSACTION 2 别离持有必然数量的行锁,然后又期待对方的锁,最后 MySQL 检测到 deadlock ,昆山软件开发,然后选择回滚了 TRANSACTION 1:Innodb今朝处理惩罚死锁的要领是将持有最少行级排他锁的事务举办回滚。

那这里就有 3 个问题了:

(1)innodb 行锁不是只锁一行?

因为这张表是 innodb 引擎的,InnoDB 支持行锁和表锁。而InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle差异,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才利用行级锁,不然,InnoDB将利用表锁,会把所有扫描过的行都锁定!在实际应用中,要出格留意InnoDB行锁的这一特性,否则的话,大概导致大量的锁斗嘴,从而影响并发机能。由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以固然是会见差异行的记录,可是假如是利用沟通的索引键,是会呈现锁斗嘴的。当我们用范畴条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给切合条件的已有数据记录的索引项加锁;别的间隙锁也会锁多行,InnoDB除了通过范畴条件加锁时利用间隙锁外,假如利用相等条件请求给一个不存在的记录加锁,InnoDB也会利用间隙锁!