sqlserver读书笔记

来源:互联网 发布:客户端设计美工招聘 编辑:程序博客网 时间:2024/03/28 23:29

数据库日志管理

1 日志的管理

SQL SERVER的日志达到一定程度时,会阻塞其它事务的处理,引起日志溢出的主要原因有:

1:系统管理人员没有及时清除日志。SQL SERVER在缺省值下,必须定期备份数据和日志,日志不能自动的清除。

2:由于执行非法的语句,如执行一条update语句,由于条件出错,导致无限量的产生日志,直到系统死机。
针对不同的错误原因,错误的严重性,采取不同的解决办法:

1:由小的事务引起日志溢出,系统能正常启动。
解决办法:
1.
扩大数据库日志空间:
alter database
数据库名 on 设备名=数量(M为单位)
sp_logdevice
数据库名,设备名

2.清除日志
dump transaction 数据库名 with no_log(no_truncate)

2:由大的事物引起日志溢出,系统较长时间内无法正常启动或数据库无法恢复
解决办法:
1.
等待。
较长的事务恢复时间较长,在无锡,有一次由于用户执行一条更新用户信息的SQL语句,由于使用错误的关联条件,导致日志溢出,恢复日志花了14小时。日志恢复完成后,一般系统就可正常运行。

2.强行清空日志。
在实在无法恢复数据库或有近期备份的情况下,可采用强行清空日志的方法。采取这种方法的后果有可能彻底破坏数据库。执行步骤如下:

-v 方式启动SQL SERVER(不检测日志)
修改数据库状态为-32768(阻塞状态)
update sysdatabases set status=-32768 where name=
数据库名
授权sybase_ts_role权限(sybase_ts_roleSQL SERVER特殊管理员权限,在日常的数据库管理中,不需要这个角色)
sp_role “grant”,”sybase_ts_role”,sa
set role “sybase_ts_role”
清除日志
dbcc rebuild_log(
数据库名,11)

完成以上步骤后,重新启动SQL SERVER即可。如果数据库能正常启动,数据库就恢复完成;如果无法启动,只能重新创建数据库。 

避免产生日志溢出的方法有:人工方法和自动方法。

人工方法:根据执行任务量的不同,定期备份日志和清除无用的日志,尽量增加日志可用的空间。优点:安全,数据库被破坏时,能恢复到上次备份的日志时为止。缺点:需人工操作,长时间不备份日志或执行非法的语句,有可能导致日志溢出。

自动方法:通过数据的阀值,可实时控制日志的溢出。优点:不会产生日志溢出。缺点:日志有可能会丢失,增大数据库处理的负担。阀值创建方法如下:
1
:创建段
sp_addsegment
段名,数据库名,设备名
相关过程:sp_helpsegment,sp_dropsegment

2:创建阀值
sp_addthreshold
数据库名,段名,空闲空间,执行过程名
相关过程:sp_helpthreshold,sp_modifythreshold,sp_dropthreshold

创建阀值之后,当日志空闲空间达到阀值定义的空闲空间时,SERVER自动激活阀值定义的存储过程名。该存储过程对日志进行处理。以下以最简单的处理过程为例说明。
Create procedure sp_thresholdaction
@dbname varchar(30),
@segmentname varchar(30),
@space_left int,
@status int
as
dump transaction @dbname to tapedump1
print “LOG DUMP:’%1!’ for ‘%2!’ dumped”,@segmentname,@dbname

/* 备份日志到磁带,然后打印备份的段名,数据库名 */

一致性的检测

数据库如果经常非正常的shutdown可能引起数据的错误;长时间的运行有可能导致索引等错误。直接后果是运行速度明显下降、无法利用BCP备份数据(BCP执行结果错误)。此外还会影响物理空间的分配。数据库的检测可采用数据库提供的过程执行,最重要的一个过程如下:

1dbcc checkcatalog(数据库名)
检查系统数据表中数据的一致性问题,如验证syscolumns表中的某个类型包含systypes表中的一行等。

2dbcc checkdb(数据库名,skip_ncindex)
检查数据库中的每个表的空间分配情况,在数据转储时,可采用带skip_ncindex参数的方法加快表的检查速度。

3dbcc checktable(表名)
检查每个表的分配信息,包含如下内容:页面连接、索引排序、指针的一致性、每页上的数据行在对象分配映射(OAM)页的入口。

4dbcc checkalloc(表名|数据库名,full,nofix)
检查核实是否所有的页都被正确的分配,未分配的页是否也不是页面链的一部分,以及不属于页面链部分的页是否也未标记被分配了。除了对已分配的页面进行检查外,checkalloc也检查数据库中所有分配页,以确保它们包含有效的信息。

数据库损坏

SQL SERVER 6.5:

update sysdatabases set status = -32768 where name = ‘数据库名

update sysdatabases set status = 12 where name = ‘数据库名

dbcc checkdb(‘数据库名’)

dump transaction 数据库名 with no_log

数据库重启

 

SQL SERVER 7.0:

解决办法:

这是最简单的办法是有数据库的全备份,然后恢复即可.

步骤:

1. 删除原始的数据库:

     USE MASTER

     GO

     DROP DATABASE DB_SUEPECT    

2.建立同名的数据库:

        USE master

       GO

       CREATE DATABASE DB_SUSPECT

        ON

         ( NAME = DBNAME_DAT,

           FILENAME = 'C:',

           SIZE = 10,

            FILEGROWTH = 5 )

           LOG ON

          ( NAME = 'DBNAME_LOG',

           FILENAME = 'g:',

           SIZE = 5MB,

           FILEGROWTH = 5MB )

           GO   

3.恢复数据库:

      RESTORE DATABASE DB_SUSPECT

     FROM DBNAME_BACKUP.DAT 

4.数据库完整性检测:

       DBCC CHECKDB('DB_SUSPECT')

5.重新启动MSSQLSERVER服务.

如果没有全备份,那就要用一些特殊的方法:

1.设置数据库为紧急模式

       Use Master

       GO

       sp_configure 'allow updates', 1

       reconfigure with override

      GO

      UPDATE sysdatabases SET status = 32768 where name = 'DB_SUSPECT'

      GO

2.停掉SQL Server服务:

     NET STOP MSSQLSERVER

3.把原始数据库的数据文件DBNAME_DAT.MDF,DBNAME_LOG.LDF移走:

4.启动SQL Server服务:

      NET START MSSQLSERVER

5.重新建立一个同名的数据库DB_SUSPECT

       USE master

       GO

       CREATE DATABASE DB_SUSPECT

        ON

         ( NAME = DBNAME_DAT,

           FILENAME = 'C:',

           SIZE = 10,

            FILEGROWTH = 5 )

           LOG ON

          ( NAME = 'DBNAME_LOG',

           FILENAME = 'g:',

           SIZE = 5MB,

           FILEGROWTH = 5MB )

           GO

6.设置数据库运行在单用户的模式:

         USE MASTER

        GO

        ALTER DATABASE DB_SUSPECT SET SINGLE_USER

        GO

7.停掉SQL服务:

     NET STOP MSSQLSERVER

8.把原来的数据文件再覆盖回来:

 

9.启动SQL Server服务:

      NET START MSSQLSERVER

10.重新设置SQLSERVER的状态:

         USE MASTER

        GO

        EXEC sp_resetstatus "DB_SUSPECT"

11.数据库完整性检测:

        DBCC CHECKDB('DB_SUSPECT')

12.恢复数据库为多用户模式:

        USE MASTER

        GO

        ALTER DATABASE DB_SUSPECT SET MULTI_USER

       GO

13.恢复SQLSERVER原始的配置:

      USE MATER

    GO     

    UPDATE sysdatabases SET status = 4194320 where name = 'DB_SUSPECT'

    GO

14.配置SQLSERVER不允许更新系统表:

      USE MASTER

     GO

      sp_configure 'allow updates', 0

      reconfigure with override

     GO

15.重新启动MSSQLSERVER服务:

     最好重新启动操作系统

16.备份数据库:

   可以通过SQLSERVER企业管理器或T-SQL.需要备份MASTERDB_SUSPECT

ISQL奇怪现象

采用sqlserver 7.0 isql SQLSERVER 6.5服务器上使用:

isql –S –P –U –ixxx.sql

会存在执行脚本没完成,需手工按ctrl+c才能继续下去,加上 –c参数有些机器能解决,有些又不能。

后更换 sqlserver 6.5版本的isql.exe文件就可以成功。

SQL语句导入导出大全

导出到excel

EXEC master..xp_cmdshell 'bcp northwind.dbo.region out c:/temp1.xls -c -q –S"GNETDATA/GNETDATA" -U"sa" -P""'

 

导入Excel

SELECT *

FROM OpenDataSource( 'Microsoft.Jet.OLEDB.4.0',

  'Data Source="c:/test.xls";User ID=Admin;Password=;Extended properties=Excel 5.0')...xactions

 

/*动态文件名

declare @fn varchar(20),@s varchar(1000)

set @fn = 'c:/test.xls'

set @s ='''Microsoft.Jet.OLEDB.4.0'',

''Data Source="'+@fn+'";User ID=Admin;Password=;Extended properties=Excel 5.0'''

set @s = 'SELECT * FROM OpenDataSource ('+@s+')...sheet1$'

exec(@s)

*/

 

SELECT cast(cast(科目编号 as numeric(10,2)) as nvarchar(255))+' ' 转换后的别名

FROM OpenDataSource( 'Microsoft.Jet.OLEDB.4.0',

  'Data Source="c:/test.xls";User ID=Admin;Password=;Extended properties=Excel 5.0')...xactions

 

EXCEL导到远程SQL

insert OPENDATASOURCE(

         'SQLOLEDB',

         'Data Source=远程ip;User ID=sa;Password=密码'

         ).库名.dbo.表名 (列名1,列名2)

SELECT 列名1,列名2

FROM OpenDataSource( 'Microsoft.Jet.OLEDB.4.0',

  'Data Source="c:/test.xls";User ID=Admin;Password=;Extended properties=Excel 5.0')...xactions

 

导入文本文件

EXEC master..xp_cmdshell 'bcp dbname..tablename in c:/DT.txt -c -Sservername -Usa -Ppassword'

 

导出文本文件

EXEC master..xp_cmdshell 'bcp dbname..tablename out c:/DT.txt -c -Sservername -Usa -Ppassword'

EXEC master..xp_cmdshell 'bcp "Select * from dbname..tablename" queryout c:/DT.txt -c -Sservername -Usa -Ppassword'

导出到TXT文本,用逗号分开

exec master..xp_cmdshell 'bcp "库名..表名" out "d:/tt.txt" -c -t ,-U sa -P password'

 

dBase IV文件

select * from

OPENROWSET('MICROSOFT.JET.OLEDB.4.0'

,'dBase IV;HDR=NO;IMEX=2;DATABASE=C:/','select * from [客户资料4.dbf]')

 

dBase III文件

select * from

OPENROWSET('MICROSOFT.JET.OLEDB.4.0'

,'dBase III;HDR=NO;IMEX=2;DATABASE=C:/','select * from [客户资料3.dbf]')

 

FoxPro 数据库

select * from openrowset('MSDASQL',

'Driver=Microsoft Visual FoxPro Driver;SourceType=DBF;SourceDB=c:/',

'select * from [aa.DBF]')

 

导入DBF文件

select * from openrowset('MSDASQL',

'Driver=Microsoft Visual FoxPro Driver;

SourceDB=e:/VFP98/data;

SourceType=DBF',

'select * from customer where country != "USA" order by country')

go

 

导出到DBF

如果要导出数据到已经生成结构(即现存的)FOXPRO表中,可以直接用下面的SQL语句

insert into openrowset('MSDASQL',

'Driver=Microsoft Visual FoxPro Driver;SourceType=DBF;SourceDB=c:/',

'select * from [aa.DBF]')

select * from

说明:

SourceDB=c:/  指定foxpro表所在的文件夹

aa.DBF        指定foxpro表的文件名.

 

导出到Access

insert into openrowset('Microsoft.Jet.OLEDB.4.0',

   'x:/A.mdb';'admin';'',A) select * from 数据库名..B

 

导入Access

insert into B selet * from openrowset('Microsoft.Jet.OLEDB.4.0',

   'x:/A.mdb';'admin';'',A)

 

文件名为参数

declare @fname varchar(20)

set @fname = 'd:/test.mdb'

exec('SELECT a.* FROM opendatasource(''Microsoft.Jet.OLEDB.4.0'',

    '''+@fname+''';''admin'';'''', topics) as a ')

 

SELECT *

FROM OpenDataSource( 'Microsoft.Jet.OLEDB.4.0',

  'Data Source="f:/northwind.mdb";Jet OLEDB:Database Password=123;User ID=Admin;Password=;')...产品

 

导入 xml 文件

DECLARE @idoc int

DECLARE @doc varchar(1000)

--sample XML document

SET @doc ='

<root>

  <Customer cid= "C1" name="Janine" city="Issaquah">

      <Order oid="O1" date="1/20/1996" amount="3.5" />

      <Order oid="O2" date="4/30/1997" amount="13.4">Customer was very satisfied

      </Order>

   </Customer>

   <Customer cid="C2" name="Ursula" city="Oelde" >

      <Order oid="O3" date="7/14/1999" amount="100" note="Wrap it blue

             white red">

            <Urgency>Important</Urgency>

            Happy Customer.

      </Order>

      <Order oid="O4" date="1/20/1996" amount="10000"/>

   </Customer>

</root>

'

-- Create an internal representation of the XML document.

EXEC sp_xml_preparedocument @idoc OUTPUT, @doc

 

-- Execute a SELECT statement using OPENXML rowset provider.

SELECT *

FROM OPENXML (@idoc, '/root/Customer/Order', 1)

      WITH (oid     char(5),

            amount  float,

            comment ntext 'text()')

EXEC sp_xml_removedocument @idoc

 

导整个数据库

bcp实现的存储过程

实现数据导入/导出的存储过程,根据不同的参数,可以实现导入/导出整个数据库/单个表

调用示例:

--导出调用示例

----导出单个表

exec file2table 'zj','','','xzkh_sa..地区资料','c:/zj.txt',1

----导出整个数据库

exec file2table 'zj','','','xzkh_sa','C:/docman',1

 

--导入调用示例

----导入单个表

exec file2table 'zj','','','xzkh_sa..地区资料','c:/zj.txt',0

----导入整个数据库

exec file2table 'zj','','','xzkh_sa','C:/docman',0

 

*/

if exists(select 1 from sysobjects where name='File2Table' and objectproperty(id,'IsProcedure')=1)

 drop procedure File2Table

go

create procedure File2Table

@servername varchar(200)  --服务器名

,@username varchar(200)   --用户名,如果用NT验证方式,则为空''

,@password varchar(200)   --密码

,@tbname varchar(500)   --数据库.dbo.表名,如果不指定:.dbo.表名,则导出数据库的所有用户表

,@filename varchar(1000)  --导入/导出路径/文件名,如果@tbname参数指明是导出整个数据库,则这个参数是文件存放路径,文件名自动用表名.txt

,@isout bit      --1为导出,0为导入

as

declare @sql varchar(8000)

 

if @tbname like '%.%.%' --如果指定了表名,则直接导出单个表

begin

 set @sql='bcp '+@tbname

  +case when @isout=1 then ' out ' else ' in ' end

  +' "'+@filename+'" /w'

  +' /S '+@servername

  +case when isnull(@username,'')='' then '' else ' /U '+@username end

  +' /P '+isnull(@password,'')

 exec master..xp_cmdshell @sql

end

else

begin --导出整个数据库,定义游标,取出所有的用户表

 declare @m_tbname varchar(250)

 if right(@filename,1)<>'/' set @filename=@filename+'/'

 

 set @m_tbname='declare #tb cursor for select name from '+@tbname+'..sysobjects where xtype=''U'''

 exec(@m_tbname)

 open #tb

 fetch next from #tb into @m_tbname

 while @@fetch_status=0

 begin

  set @sql='bcp '+@tbname+'..'+@m_tbname

   +case when @isout=1 then ' out ' else ' in ' end

   +' "'+@filename+@m_tbname+'.txt " /w'

   +' /S '+@servername

   +case when isnull(@username,'')='' then '' else ' /U '+@username end

   +' /P '+isnull(@password,'')

  exec master..xp_cmdshell @sql

  fetch next from #tb into @m_tbname

 end

 close #tb

 deallocate #tb

end

go