今天接到一个朋友的问题,sql server报由于文件组 default 中的磁盘空间不足,无法为数据库 tempdb 分配新页,按照错误提示应该是tempdb空间不足,让其查看tempdb对应数据库文件大小为不到4g,查看其对应文件为自增长,硬盘空间还有40g多点,那应该没有问题
今天接到一个朋友的问题,sql server报“由于文件组 ‘default’ 中的磁盘空间不足,无法为数据库 ‘tempdb’ 分配新页”,按照错误提示应该是tempdb空间不足,让其查看tempdb对应数据库文件大小为不到4g,查看其对应文件为自增长,,硬盘空间还有40g多点,那应该没有问题。后来她说该文件所处位置的盘是fat32的,那问题确定是fat32最大支持文件大小是4g。解决办法:
1、让tempdb中的文件恢复默认值,设置其最大值
1)重启sql server服务,tempdb一般会自动变为初始化大小
2)如果1)失败,使用下面语句
dbcc shrinkfile (tempdev, 10)
dbcc shrinkfile (templog, 10)
2)然后设置tempdev和templog的最大大小为4000m
2、添加数据文件和日志文件,并设置其最大值为4000m
3、修改程序,从根源上解决问题
分析产生该问题原因
询问朋友后,原来是她对一个6kw的表和1kw的表进行关联,然后取得需要的数据插入到另一张表中,因为涉及的数据量非常大,所有导致tempdb数据库飞速增大,超过系统文件大小限制。导致文章开始的错误,光添加文件,对于这么大数据量的程序来说还是不能解决问题。应该在程序上去优化,而不是靠添加tempdb中文件的大小和数量来解决问题。
添加程序的提交次数,而不是所有数据一次提交,放在一个事物中。
我根据程序需求模拟的写了两种处理过程的方法
模拟环境:
--创建模拟表
select id,name into t_1 from sys.sysobjects;
select object_id id,name into t_2 from sys.columns;
--创建跟踪表
create table t_s (id int default 0,date datetime default getdate());
insert into t_s values(0,getdate());
--创建需要插入数据表
select t1.name n1,
t2.name n2,
t1.id
into test_1
from t_1 t1,
t_2 t2
where t1.id = t2.id
and 1=2;
方法一:
特点:1、优点执行效率比较高,无需排序和插入跟踪表
2、缺点:不能查看程序执行进度,如果异常终止,必须重新执行
create procedure [dbo].[insert_d_1]
as
declare @name1 varchar(4000)
declare @name2 varchar(4000)
declare @id int
declare c1 cursor
for
select t1.name,
t2.name,
t1.id
from t_1 t1,
t_2 t2
where t1.id = t2.id
order by
t1.id
open c1
fetch next from c1 into @name1,@name2,@id
while @@fetch_status=0
begin
insert into test_1 values(@name1,@name2,@id)
fetch next from c1 into @name1,@name2,@id
end
close c1
deallocate c1
方法二:
特点:1、可以跟踪程序的执行进度查询t_s表,如果异常终止可以写其他程序继续
2、程序使用二重游标,执行效率比较低
create procedure [dbo].[insert_d_2]
as
declare @name1 varchar(4000)
declare @name2 varchar(4000)
declare @id int
declare c1 cursor
for
select t1.name,
t1.id
from t_1 t1
order by t1.id
open c1
fetch next from c1 into @name1,@id
while @@fetch_status=0
begin
--二重循环
declare c2 cursor for
select t2.name from t_2 t2 where t2.id=@id
open c2
fetch next from c2 into @name2
while @@fetch_status=0
begin
insert into test_1 values(@name1,@name2,@id)
update t_s set id=@id,date=getdate()
fetch next from c2 into @name2
end
close c2
deallocate c2
fetch next from c1 into @name1,@id
end
close c1
deallocate c1
