3

Running this code:

ALTER TABLE npidata
ALTER COLUMN npi varchar(20)

Gives this error:

Msg 9002, Level 17, State 4, Line 2
The transaction log for database 'SalesDWH' is full. To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.databases

I am changing the NPI column's data type from varchar(80) to varchar(20).

The following code gives me the same error message:

insert into npidata1 select * from npidata
  • log_reuse_wait_desc shows NOTHING
  • The recovery mode is SIMPLE
  • autogrowth is set to NONE
  • autoshrink is set to true

What else can I do? My understanding is the logs should just be truncating every time they get too big. What am I doing wrong?

3 Answers 3

1

Try to set your log file to autogrow or temporarily add some extra log files which can handle such an operation

BUT

it may be simplier and faster to do something like this:

use SalesDWH
go
ALTER TABLE npidata ADD npiNew varchar(20)
GO
UPDATE npidata SET
  npiNew = SUBSTRING(npi, 1, 20)
GO
ALTER TABLE npidata DROP COLUMN npi
GO
EXEC sp_rename 'npidata.npiNew', 'npidata.npi', 'COLUMN'
GO
DBCC CLEANTABLE(0, 'npidata', 100)

In this case log file usage can be controlled by UPDATE statement, you may perform this by small chunks like:

use SalesDWH
go
ALTER TABLE npidata ADD npiNew varchar(20), ready bit
GO
WHILE 1 = 1
BEGIN
  UPDATE TOP (100) npidata SET
    npiNew = SUBSTRING(npi, 1, 20),
    ready=1
  WHERE ready is null

  IF @@ROWCOUNT = 0 BREAK
END
GO
ALTER TABLE npidata DROP COLUMN npi
GO
ALTER TABLE npidata DROP COLUMN ready
GO
EXEC sp_rename 'npidata.npiNew', 'npidata.npi', 'COLUMN'
GO
DBCC CLEANTABLE(0, 'npidata', 100)

For better performance, in case when the table is big - you may apply temporary index on column ready

OH, YES!!!

Like @RemusRusanu said - TURN OFF THE AUTOSHRINK

0
5

the very first thing you have to do is to change AUTOSHRINK to false. There is absolutely no reason to ever have it true. See AUTOSHRINK: Turn it OFF!.

Both operations you are attempting require a size-of-data update in a single transaction. A single transaction requires that much log, irrelevant of the recovery model. You must increase the log size to accommodate your transaction.

1
  • Hi @Remus, just chaning from resizing from high to a small value, this requires SQL server rewrite something on log? For example, changing from varchar(30) to varchar(20), I guess SQL server just need scan to confirm that dont exists rows with column size more than 20 chars... If it finds, just throw errros... What the reason SQL would need write this change to log, in addition metadata changes?
    – Rodrigo
    Mar 26, 2021 at 0:09
3

Even with SIMPLE recovery mode, the log still needs enough room to write the changes related to the transactions that happen between checkpoints.

Running with a fixed-size log is always risky, for this very reason.

The fix is to increase the size of the log, and/or enable auto-growth.

You can try forcing a checkpoint before you run the other commands, but it's a very hit-or-miss thing. The command is:

CHECKPOINT

Also, turn off autoshrink. Shrinking your log except under very unusual circumstances is a bad, bad idea -- much less doing it on a regular basis.

2
  • thanks so much. when should i run checkpoint?
    – I__
    Jan 3, 2012 at 4:29
  • right before the commands that are likely to fill up the log (update, insert or delete many rows or make schema changes). How do you know which ones those are? Your guess is as good as mine.
    – RickNZ
    Jan 3, 2012 at 4:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.