数据库性能优化4
作者:互联网
概述
隔离级别
锁
事务
总结
In-Memoery Database(内存数据库)
分库分表
1,锁和事务
隔离级别:是事务实现的前提,隔离级别影响锁的行为,从而影响事务的并发性;
),隔离级别只对当前链接有效;在会话中,是可以修改隔离级别的
),隔离级别分成四个等级;由低到高分别为Read uncommitted 、Read committed 、Repeatable read 、Serializable
1),Read uncommitted(读未提交):一个事务可以读取其他未提交事务的数据;
它的优势是执行效率最快,避免大量阻塞,它的劣势会产生脏读问题
适用的场景:在一些不重要的查询显示中使用它可以提高并发,比如未读信息;待办信息记录等
示例:事务A读取a字段,事务B修改a字段;事务B已修改a字段的数据,
但是事务B未提交(事务B随时有可能会回滚的可能性);事务A读取了事务B修改的a字段数据;
如果事务B正常提交,事务A读取到的数据也不是预期的;如果事务B回滚,那么事务A读取的数据就是不存在的;
脏读:事务A读到了事务B还没有提交的数据
示例:事务A先启动,事务A设置隔离级别为Read uncommitted;第一次读取[Description]字段后,等待4秒;再去读[Description]字段
事务B后启动,在事务A结束之前启动;负责修改记录的字段值,延迟9秒,最后选择回滚;并查询回滚后的记录值
------脏读事务A,先启动它 begin transaction SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED select [Description] from Company4 where Id='C13192' waitfor delay '00:00:04:000' select [Description] from Company4 where Id='C13192' commit
---脏读事务B,在事务A启动之后,在事务A结束之前启动 begin transaction update Company4 set [Description]='贝蒂哈使' where Id='C13192' waitfor delay '00:00:09:000' rollback select [Description] from Company4 where Id='C13192'
2),Read Committed(读提交):读已提交,一个事务要等另一个事务提交后才能读取数据;
它的优势是可以解决脏读问题,它的劣势是仍然会产生重复读和幻读的问题
示例:事务B在对a进行更新(UPDATE)操作时,事务A要等待事务B这个更新操作事务提交后才能读取a
重复读:在一个事务里面读取了两次某个数据,读出来的数据不一致;不可重复读对应的是修改,即UPDATE操作
示例:company4表,在sql server中开启两个事务,事务A先启动,事务A会在第一个读取后等待9秒;事务B后启动;事务B等待4秒,第二次事务A读到的同数据和第一次读到同一的数据已经发生了变化;这是一个【重复读】
------重复读演示事务A,先启动它 begin transaction select [Description] from Company4 where Id='C13192' waitfor delay '00:00:09:000' select [Description] from Company4 where Id='C13192' commit
------重复读事务B,在事务A启动后再启动它 ,但要在事务A等待9秒之前启动它 begin transaction update Company4 set [Description]='你好' where Id='C13192' waitfor delay '00:00:04:000' commit
3),Repeatable read(可重复读):在数据读出来之后加锁,类似"select * from XXX for update",明确数据读取出来就是为了更新用的,所以要加一把锁,防止别人修改它。
在这个隔离级别上;读取了一条数据,这个事务不结束,别的事务就不可以改这条记录;事务提交之后才会释放共享锁
它的优势是可以解决脏读,重复读问题,它的劣势是仍然会产生幻读的问题
适用场景:不要在更新时间长的场景下使用此隔离级别
幻读:在一个事务里面的操作中发现了未被操作的数据;幻读出现的前提是并发的事务中有事务发生了插入、删除操作;实际上更新操作也可以造成幻读
示例:storeusers表,在sql server中开启两个事务,事务A先启动,事务A会在第一个读取后等待9秒;事务B后启动;事务B等待4秒,相同过滤条件下事务A前后两次读取的数据量发生了变化;这是一个【幻读】
--------幻读演示事务A begin transaction select age from SortUsers where age>8998; waitfor delay '00:00:09:000' select age from SortUsers where age>8998; commit
----幻读演示事务B begin transaction select age from SortUsers where age>8998; INSERT INTO [dbo].[SortUsers]([Id],[Name],[Code],[Desciption],[Age],[UserId]) VALUES('C19000','C19000','C19000','C19000',9000,'C19000') waitfor delay '00:00:04:000' commit select age from SortUsers where age>8998;
4),Serializabale(序列化):将数据库中所有事务以串联的方式连接起来执行,防止一个事务影响其他事务
这个隔离级别使用的是[区间锁]的原理来实现的;对某个区域的数据进行加锁
它的优势是可以解决脏读,重复读,幻读问题;其保证了一个事务不会读到另一个并行事务已修改但未提交的数据,它的劣势是没有并发事务;性能差,并发差
适用场景:罕见
5),默认隔离级别:SQLServer默认使用Read Committed;Mysql默认使用Repeatable read
6),SnapShot:使用快照,快照使用的是乐观锁机制,使用TempDB来实现,将要操作的数据创建副本,从而数据隔离开来
从而避免脏读,幻读,重复读;
它的优势是有很好的隔离性,仍然有并发性,它的劣势是因为使用TempDB,IO性能将会下降;对并发性的支持也是有瓶颈
事务:可以认为是一组操作的集合,事务的具有ACID四个特性
持久性(durability);事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响
一致性(consistency);事务必须是使数据库从一个一致性状态变到另一个一致性状态,并且不违反任何一致性约束
原子性(atomicity):一个事务是一个不可分割的工作单位,事务中的操作要么都做,要么都不做;
隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰
锁:事务使用锁和隔离级别来实现事务的四个特性;但是锁的特性也影响到事务的性能和并发性;事务执行中的死锁,并发问题是锁常见的问题
会话:一个数据库链接就是一个会话;每一个会话都有一个唯一的SessionID;事务是和会话相关联的;会话在成功接入sqlserver之后,事务就会在某个隔离级别上运行
阻塞:阻塞指的是至少两个事务中,一个事务被另一个事务阻塞的现象
锁:
行锁:粒度最小的锁级别,行锁是针对指定的行进行加锁;根据行是否有聚集索引,行锁可以分为键值锁和行标识锁
页锁:针对数据页的加锁,查询使用了行锁时,不会对数据使用页锁;使用页锁时,也不会使用行锁
表锁:对整个表加锁,表锁包含的数据页和数据行上此时都无法加锁
锁的模式:
排他锁,也称X锁;写操作,增删改会对受影响的行加X锁,同一时刻只有一个事务能持有对统一对象的X锁;其他事务需要等待
X锁的释放才能操作;事务的隔离级别不影响X锁的行为
共享锁,也称S锁;读操作,多个事务可以同时访问S锁上的资源,共享锁是受事务隔离级别的影响
意向锁,也称I锁;放置在资源层次结构的一个级别上的锁,以保护较低级别资源上的共享锁或排他锁
更新锁,也称U锁,在数据修改中,可能需要先查询再更新,使用U锁对查询出来的数据进行加锁,告诉其他事务这些数据即将被更新;
加锁成功之后,再将U锁升级到X锁,然后再执行更新
锁的兼容性:锁是否兼容,会影响事务之间的阻塞;兼容的锁,事务之间的操作不会阻塞,典型的S锁;不兼容的锁,则会造成事务之间的阻塞
典型的X锁,X锁和任何锁都不兼容
锁的兼容性图
运行时查看当前锁状况:sqlserver中,使用系统函数sp_lock查看锁的状况
自定义查看某个事务的锁:
-----在目标数据库创建一个名叫DBlocks的视图用于查看引擎中的锁 Use Foundation---你的数据库名字 go IF EXISTS ( SELECT 1 FROM sys.views WHERE name = 'DBlocks' ) DROP VIEW DBlocks ; GO CREATE VIEW DBlocks AS SELECT request_session_id AS spid , DB_NAME(resource_database_id) AS dbname , CASE WHEN resource_type = 'OBJECT' THEN OBJECT_NAME(resource_associated_entity_id) WHEN resource_associated_entity_id = 0 THEN 'N/A' ELSE OBJECT_NAME(p.object_id) END AS entity_name , index_id , resource_type AS resource , resource_description AS description , request_mode AS mode , request_status AS status FROM sys.dm_tran_locks t LEFT JOIN sys.partitions p ON p.partition_id = t.resource_associated_entity_id WHERE resource_database_id = DB_ID() AND resource_type <> 'DATABASE' ;
在建立DBBlocks视图后,就可以在DBBlocks查看引擎中的锁状况;如下是查询当前执行的事务的锁
阻塞:当一个事务的执行需要等待另一个事务执行释放资源时,便是阻塞
示例:Company4表,一个事务执行对指定行进行更新,但是这个事务就是不提交也不回滚;此时另外一个查询窗口去查询这行数据时,就会一直在等待
定位阻塞事务的锁
示例:
1,先启动引起阻塞的事务A
2,启动查询B查询被A阻塞的资源,启动后,查询B一直处于执行状态
3,启动脚本[前面所创建的DBBlocks视图]查询当前查询B的会话Id(查询B是一个S锁);再查询查询B的阻塞信息
下面这个图演示了会话53被会话52给阻塞了,X锁不兼容S锁(X锁不兼容任何锁)
------第一步:事务A,启动后不提交也不回滚 begin transaction update Company4 set [Description]='贝蒂哈使' where Id='C13192'
-----第二步,启动查询B查询被A阻塞的资源,启动后,查询B一直处于执行状态
select [Description] from Company4 where Id='C13192'
----查询实时的阻塞情况 -- 实时侦测阻塞 select * from DBlocks; -- 锁申请及其状态 select session_id,wait_time,wait_type,blocking_session_id from sys.dm_exec_requests where session_id=53;----53是当前被阻塞会话ID select session_id,wait_duration_ms,wait_type, blocking_session_id,resource_description from sys.dm_os_waiting_tasks where session_id=53;----53是当前被阻塞会话ID
你也可以使用以下语句来查看当前系统所有的更多的阻塞信息(包括执行脚本和执行计划等);而且也无需知道会话的Id
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)
总结:
1,阻塞发生再多个会话/事务的资源争夺
2,如果没有索引;即使是更新一行数据,可能会导致锁升级,也可能导致锁定大量的数据
3,确保事务及时提交,X锁总是在事务结束后才释放,缩短事务执行时间
4,更新操作尽可能靠近事务的结尾
5,避免在一个事务中多次更新相同的数据,如多个Update更新相同数据的不同字段,这会增加锁的数量和开销
6,监控锁升级
7,同一个事务中,不要混用DML和DDL;如DDL修改表结构,会导致部分sql重新编译,统计信息无效,执行计划重新编译,执行缓存清楚
8,不要疯狂使用with nolock;with nolock不一定能够解决写操作导致的阻塞;同时可能脏读脏到用户无法接受的程度
9,事务和锁并没有大大的提升数据库性能
10,数据库本身不是为了性能而存在,数据库的一致性才是数据库的事务的前提
In-Memory(IMDB)简介:sql server2014+版本
在计算机中,
网络的IO速度慢于磁盘的IO速度,
磁盘的IO速度慢于内存的访问速度,
内存的访问速度慢于cpu三级缓存的访问速度
cpu三级缓存访问速度慢于cpu二级缓存的访问速度
cpu二级缓存访问速度慢于cpu一级缓存的访问速度
cpu一级缓存访问速度慢于cpu计算速度
传统的关系数据库和现在的redis,mecached等缓存技术相比;
传统的关系型数据库大部分是磁盘IO;它们通过将访问的数据加载到内存中进行查询匹配等操作,当内存不足时,则将大量的内存中所需的数据转移到磁盘上的TempDB(这是典型的内存磁盘数据交换)
而磁盘的IO速度是远远不如内存;这就是磁盘表和内存表
redis,mecached等缓存技术则更多是运行在内存中,内存IO的速度是远远高于磁盘IO的
In-Mempory Database;即内存数据库,是一种依赖于主存作为数据存储介质的一种数据库管理系统;
内存优化表,存储在内存中的表,它也有索引,包括散列索引和范围索引,而且至少要有一个索引;最多8个索引;除主键外没有唯一索引;
创建之后不可以修改;建表的时候就要定义所有的索引
默认情况下,内存优化表具有完全持久性。与(传统)基于磁盘的表上的事务一样,内存优化表上的事务具有完全原子性、一致性、隔离性和持久性 (ACID)。
内存优化表和本机编译的存储过程仅支持一部分 Transact-SQL 功能
分库分表属于架构级的,在此不讨论
标签:事务,resource,where,数据库,性能,tl1,优化,id,select 来源: https://www.cnblogs.com/cmliu/p/13661783.html