Sql调优2

本文介绍了数据库并发时的锁机制,包括脏读、不可重复读和幻读问题,以及不同级别的事务隔离。详细阐述了锁的类型如行锁、页锁和表锁,以及排他锁、共享锁等模式。同时讨论了如何减少锁冲突和优化事务,如缩短事务运行时间和避免多次更新。还提到了Inmemory技术,包括内存优化表和其特性。最后,探讨了数据库的高可用性方案,如读写分离和分库分表策略。
摘要由CSDN通过智能技术生成

锁和事务

锁解决的问题,发生在数据库并发时

  • 脏读: read uncommitted,在事务还没有提交时候读取,事务可能回滚, 并发性最好
  • 不可重复读:read commited ,默认级别,
  • 幻读
  • 可重复读: 同一个事务里面发生不一致
    Repeatable read, 共享锁持有时间长,阻塞相对多,
    Serizable
    以上都由悲观锁实现
    Snapshot:乐观锁

锁的大小

  • 行锁,粒度最小的锁级别
  • 页锁,
  • 表锁

锁的模式

  • 排他锁,X锁,在写操作时使用,更新或者插入,事务结束后才释放
  • 共享锁,S锁,读操作
  • 意向锁,I锁,
  • 更新锁,U锁,

各种锁有兼容情况

阻塞
降低锁数量,减少锁的持有时间
建议

  • 缩短事务运行时间(范围,持续时间)
  • 更新修改操作应尽可能靠近事务的结尾
  • 避免多次更新相同的数据,不要在同一个事务中,多次更新数据
  • 监控锁升级
  • 同一个事务中,不要混用DML和DDL
  • 业务代码应该有错误捕捉和处理逻辑

事务和锁对性能没有太大提升,数据库系统并不是为了性能存在,主要是以数据一致性未前提

查看事务和阻塞

select 
    tl1.resource_type as [Resource Type] 
    ,db_name(tl1.resource_database_id) as [DB Name] 
    ,case tl1.resource_type 
when  'OBJECT' then object_name(tl1.resource_associated_entity_id
,tl1.resource_database_id) 
        when 'DATABASE' then 'DB' 
        else 
            case when tl1.resource_database_id = db_id() 
                then 
                     (  select object_name(object_id, tl1.resource_database_id) 
                        from sys.partitions 
                        where hobt_id = tl1.resource_associated_entity_id ) 
                else '(Run under DB context)' 
            end 
    end as [Object] 
    ,tl1.resource_description as [Resource] 
    ,tl1.request_session_id as [Session] 
    ,tl1.request_mode as [Mode] 
    ,tl1.request_status as [Status] 
    ,wt.wait_duration_ms as [Wait (ms)] 
	   ,qi.sql 
    ,qi.query_plan 
from 
    sys.dm_tran_locks tl1 with (nolock) join sys.dm_tran_locks tl2 with (nolock) on 
        tl1.resource_associated_entity_id = tl2.resource_associated_entity_id 
    left outer join sys.dm_os_waiting_tasks wt with (nolock) on 
        tl1.lock_owner_address = wt.resource_address and tl1.request_status = 'WAIT' 
    outer apply 
    ( 
        select 
            substring(s.text, (er.statement_start_offset / 2) + 1, 
                 ((  case er.statement_end_offset 
                            when -1 
                            then datalength(s.text) 
                            else er.statement_end_offset 
                      end - er.statement_start_offset) / 2) + 1) as sql 
            , qp.query_plan 
        from 
            sys.dm_exec_requests er with (nolock) 
                cross apply sys.dm_exec_sql_text(er.sql_handle) s 
                outer apply sys.dm_exec_query_plan(er.plan_handle) qp 
        where 
            tl1.request_session_id = er.session_id 
    ) qi 
where 
    tl1.request_status <> tl2.request_status and 
    ( 
        tl1.resource_description = tl2.resource_description or 
        ( tl1.resource_description is null and tl2.resource_description is null ) 
    ) 
option (recompile)

In memory 技术

  • 磁盘表: 传统表
  • 内存优化表:内存表,不与缓存在一起,散列索引,必须有一个索引,单表最多8个索引,包含主键索引,除主键外,没有唯一索引,创建表时候就需要定义所有索引,
  • Interop:解析引用内存优化表的T-sql
  • Natively Compliled :纯In memory对象

-- 检查数据库是否可以包含内存表
EXEC sp_MSforeachdb 'USE ? IF EXISTS (SELECT 1 FROM sys.filegroups FG 
JOIN sys.database_files F
ON FG.data_space_id = F.data_space_id
WHERE FG.type = ''FX'' AND F.type = 2) 
PRINT ''?'' + '' can contain memory-optimized tables.'' ';
GO

-- 查看内存表
select name,durability_desc 
from sys.tables where is_memory_optimized =1

传统表迁移内存优化表条件

  • 数据库支持in-memory
  • 仅对核心表,热点表迁移

优先级:分区表-》读写分离-》分库

分表,物理分表,逻辑上仍然是一个表

水平分表, 大表由若干个小表组成
按照时间,比如按年分表
查询时最好加上分区字段,避免全表扫描

sqlserver自带分区向导

数据库的高可用
读写分离
只读库,读写库,

分库

纵向分割

Sqlserver读写分离
Sqlserver 主从同步,使用订阅发布完成同步

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值