话都说到这了,那就看下咱们营业表的索引情况:
show INDEX from `db_zz_flow`.`t_channel_final_datas`;+-----------------------+--------------+-------------------------------+----------------+-------------+----------+--------+--------------+-----------+-----------------+| Table | Non_unique | Key_name | Seq_in_index | Column_namt | Packed | Null | Index_type | Comment | Index_comment ||-----------------------+--------------+-------------------------------+----------------+-------------+----------+--------+--------------+-----------+-----------------|| t_channel_final_datas | 0 | PRIMARY | 1 | id > | <null> | | BTREE | | || t_channel_final_datas | 1 | index_countdate_type_terminal | 1 | count_date> | <null> | YES | BTREE | | || t_channel_final_datas | 1 | index_countdate_type_terminal | 2 | channel_ty> | <null> | YES | BTREE | | || t_channel_final_datas | 1 | index_countdate_type_terminal | 3 | terminal > | <null> | YES | BTREE | | || t_channel_final_datas | 1 | index_countdate_channelid | 1 | count_date> | <null> | YES | BTREE | | || t_channel_final_datas | 1 | index_countdate_channelid | 2 | channel_id> | <null> | YES | BTREE | | |+-----------------------+--------------+-------------------------------+----------------+-------------+----------+--------+--------------+-----------+-----------------+
知道道理后,咱们再精心构建一个四字段的组合索引即可让 update 精准的走 innodb 索引,实际上,我们更新索引后,这个逝世锁问题即获得懂得决。
注:innodb不仅会打印出事务和事务持有和等待的锁,并且还有记录本身,不幸的是,它可能跨越innodb为输出结不雅预留的长度(只能打印1M的内容且只能保存比来一次的逝世锁信息),如不雅你无法看到完全的输出,此时可以在随便率性库下创建innodb_monitor或innodb_lock_monitor表,如许innodb status信息会完全且每15s一次被记录到缺点日记中。如:create table innodb_monitor(a int)engine=innodb;,不须要记录到缺点日记中时就删掉履┞封个表即可。
(2)回滚的话,为什么只有部分 update 语句掉败,而不是全部事务里的所有 update 都掉败?
show variables like 'autocommit';+-----------------+---------+| Variable_name | Value ||-----------------+---------|| autocommit |>(3)如何降低 innodb 逝世锁几率?逝世锁在行锁及事务场景下很难完全清除,但可以经由过程表设计和SQL调剂等办法削减锁冲突和逝世锁,包含:
- 尽量应用较低的隔离级别,比如如不雅产生了间隙锁,你可以把会话或者事务的事务隔离级别更改为 RC(read committed)级别来避免,但此时须要把 binlog_format 设置成 row 或者 mixed 格局
- 精心设计索引,并尽量应用索引拜访数据,使加锁更精确,大年夜而削减锁冲突的机会;
- 选择合理的事务大年夜小,小事务产生锁冲突的几率也更小;
- 给记录集显示加锁时,最好一次性请求足够级其余锁。比如要修改数据的话,最好直接申请排他锁,而不是先申请共享锁,修改时再请求排他锁,如许轻易产逝世活锁;
- 不合的法度榜样拜访一组表时,应尽量商定以雷同的次序拜访各表,对一个表而言,尽可能以固定的次序存取表中的行。如许可以大年夜大年夜削减逝世锁的机会;
- 尽量用相等前提拜访数据,如许可以避免间隙锁对并发插入的影响;
- 不要申请跨越实际须要的锁级别;除非必须,萌芽时不要显示加锁;
- 对于一些特定的事务,可以应用表锁来进步处理速度或削减逝世锁的可能。
2、Case2:诡异的 Lock wait timeout
持续几天凌晨6点和早上8点 都分别有一个义务掉败,load data local infile 的时刻报 Lock wait timeout exceeded try restarting transaction innodb 的 Java SQL 异常,和平台的同窗沟通得知,这是我们本身的营业数据库的 Lock 时光太短或者锁冲突的问题。然则回头一想不该该啊?这不一向好好的吗?并且根本都是单表单义务,不存在多人冲突。
甭管谁的问题,那咱们照样先看本身的数据库有没有问题:
show variables like 'innodb_lock_wait_timeout';+--------------------------+---------+| Variable_name | Value ||--------------------------+---------|| innodb_lock_wait_timeout | 50 |+--------------------------+---------+
默认 lock 超不时光 50s,这个时光┞锋心不短了,估计调了也没用,事实上确切逝世马当活马医的试了下没用。。。
可以看到这张表的索引极不合理:有3个索引,然则 update 却没有完全的用上索引,导致 update 没有精确的用上索引,须要锁定多行范围数据,大年夜而激发逝世锁。
并且此次 SHOW ENGINE INNODB STATUS\G 也没出现任何逝世锁信息,然后又将眼光转向 MySQL-server 日记,欲望能大年夜日记里看一看那个时刻前后数据毕竟在做什么操作。这里先简单的介绍下MySQL日记文件体系的构成:
(a) error 日记:记录启动、运行或停止 mysqld 时出现的问题,默认开启。
(b) general 日记:通用萌芽日记,记录所有语句和指令,开启数据库会有 5% 阁下机能损掉。
推荐阅读
环卫工人清洗垃圾桶清扫保洁二组,收到请答复?”“保洁二组收到。”“娱乐中间有大年夜片的烟头,垃圾桶外有裸露的垃圾,通知该组保洁人员尽快处理。”7月21日上>>>详细阅读
本文标题:MySQL死锁与日志相关经验分享
地址:http://www.17bianji.com/lsqh/36448.html
1/2 1

网友点评
精彩导读
科技快报
品牌展示