sofard

导航

MYSQL性能优化(3)

优化数据库对象

1.优化表的数据类型

  select * from tbl1 procedure analyse(16,256) ,会输出优化建议,结合情况优化

2.拆分表(仅Myisam)

 2.1 纵向拆分

  按照访问频率,将经常访问的字段和不常访问的字段拆分开来,经常访问的尽量定长

  2.2 横向拆分

  根据应用情况,将数据分为几个表,或者分到不同区中,可以避免读取与更新导致的锁问题

3  逆规范化

 冗余越少 带来的联查越多,会降低效率

 其实就是空间与时间的平衡

4. 使用冗余统计表

  create temporary table 建的是session表,数据保存在内存,

  统计的时候效率高

5.更改合适表类型

 锁冲突严重,考虑使用innodb

 查询多,对事务完整性不严格,考虑使用Myisam

 

 

锁问题
 
 show status like ‘Table%’

  查看表锁定争夺情况

  show status like ‘innodb_row_lock%’

  查看行锁争夺情况

 

行锁的优点:

1.多线程访问不同行

2.回滚只有少量的更改

3.可以长时间锁定单一的行

行锁的缺点:

1.比页级或者表级锁占用更多的时间

2.当操作表中的大部分数据时,需要获取更多的锁,速度慢

3.粒度太细

 

insert ...select ...问题

若select的表是innodb,那么会一直锁定相关行,主要是为了保证主从一致

推荐使用 select ..into outfile  和 load data infile组合来实现

 

next-key锁问题(下面所有的待研究)

  防止'幽灵问题",会额外锁定不存在的东西

 

 隔离级别对并发插入的影响
  REPEATABLE READ 是 InnoDB 的默认隔离级别。
  带唯一搜索条件使用唯一索引的 SELECT ... FOR UPDATE, SELECT ... LOCK IN SHARE MODE, UPDATE 和 DELETE 语 句只锁定找到的索引记录, 而 不锁定记录前的间隙。 用 其它搜索条件, 这 些操作采用 next-key 锁定,用 next-key 锁定或者间隙锁定锁住搜索的索引范围,并且阻止其它 用户的新插入。在持续读中,有一个与 READ COMMITTED 隔离级别重要的差别:在这个级别,在 同一事务内所有持续读读取由第一次读所确定的同一快照。 这个惯例意味着如果你在 同一事务内发出数个无格式 SELECT 语句,这些 SELECT 语句对相互之间也是持续的。READ COMMITTED 隔离级别是一个有些象 Oracle 的隔离级别。所有 SELECT ... FOR UPDATE 和 SELECT ... LOCK IN SHARE MOD 语句仅锁定索引记录,而不锁定记录 前的间隙,因而允许随意紧挨着已锁定的记录插入新记录。UPDATE 和 DELETE 语句使 用一个带唯一搜索条件的唯一的索引仅锁定找到的索引记录,而不包括记录前的间 隙。
在范围类型 UPDATE 和 DELETE 语句, InnoDB 必须对范围覆盖的间隙设置 next-key 锁定或间隙锁定以及其它用户做的块插入。 这 是很必要的, 因 为要让MySQL 复制和恢复起作用, “幽灵行”必须被阻止掉。如果应用是从基于 ORACLE 的应用迁移到 MYSQL 数据库的,那么建议使用该隔离级别提供数据库服务,因为该隔离级别是最接近 ORACLE 的默认隔离级别的,迁移可 能遇到的锁问题最小。
 
如何减少锁冲突
1.对 Myisam 类型的表
1)可以考虑通过改成 Innodb 类型的表来减少锁冲突。
2) 根据应用的情况,尝试横向拆分成多个表或者改成 Myisam 分区对减少锁冲突也会
索引访问,那么即便你只是要更新其中的一行纪录,也是全表锁定的。要确保sql 是使用索引来访问纪录的,必要的时候,请使用explain 检查 sql 的执行计划,判 断是否按照预期使用了索引。
2) 由于 mysql 的行锁是针对索引加的锁, 不 是针对纪录加的锁, 所 以虽然是访问不同 行的纪录,但是如果是相同的索引键,是会被加锁的。应用设计的时候也要注意, 这里和 Oracle 有比较大的不同。
3) 当表有多个索引的时候, 不 同的事务可以使用不同的索引锁定不同的行, 当 表有主 键或者唯一索引的时候, 不 是必须使用主键或者唯一索引锁定纪录, 其 他普通索引 同样可以用来检索纪录,并只锁定符合条件的行。
4) 用 SHOW INNODB STATUS 来确定最后一个死锁的原因。查询的结果中,包括死锁的 事务的详细信息,包括执行的SQL 语句的内容,每个线程已经获得了什么锁,在等 待什么锁, 以 及最后是哪个线程被回滚。 详 细的分析死锁产生的原因, 可 以通过改 进程序有效的避免死锁的产生。
5) 如果应用并不介意死锁的出现,那么可以在应用中对发现的死锁进行处理。
6) 确定更合理的事务大小,小事务更少地倾向于冲突。
7) 如果你正使用锁定读, (SELECT ... FOR UPDATE 或 ... LOCK IN SHARE MODE),
试着用更低的隔离级别,比如 READ COMMITTED。
1) 首先要确认, 在 对表获取行锁的时候, 要 尽量的使用索引检索纪录, 如 果没有使用
8) 以固定的顺序访问你的表和行。则事务形成良好定义的查询并且没有死锁 

 

posted on 2018-11-06 16:58  sofard  阅读(119)  评论(0编辑  收藏  举报