- if the database has option 'truncate on checkpoint', whenever transaction has been finished, after a CHECKPOINT, when all the modified by this transaction pages have been saved in the database, the log entries are not longer required
- if the option is not set, then first a backup of the log needs to be taken. After transaction has finished, and dbo has performed the backup of the log, the space in the log can be released.
Let's consider following example:
CREATE DATABASE Beta ON BetaDataDev='10M' LOG ON BetaLogDev='5M' GO USE Beta GO CREATE TABLE TestTran (ID INT IDENTITY PRIMARY KEY, SomeText NVARCHAR(1000)) GO BEGIN TRAN WHILE(1=1) BEGIN DECLARE @info VARCHAR(100) INSERT TestTran VALUES(@info) SET @info = Convert(VARCHAR(100),GETDATE()) PRINT @info END
- database Beta has been created, it has small data segment (10MB) and also small log (5MB) - we are asking for problems
- In the database a new table has been created
- Next a BIG transaction starts, there is no COMMIT or ROLLBACK statement here, just a never-ending WHILE adding rows into the table
After some seconds of execution something needs to fill up. In my case it was the log segment. In the error log following entry could be found (and it was repeated every minute):
00:0006:00000:00007:2017/03/19 12:49:44.92 server 1 task(s) are sleeping waiting for space to become available in the log segment for database Beta.
00:0006:00000:00007:2017/03/19 12:50:44.92 server 1 task(s) are sleeping waiting for space to become available in the log segment for database Beta.
That is the default behaviour, as by default databases don't have the option ABORT TRAN ON LOG FULL enabled. The default is FREEZE TRAN ON LOG FULL, what is the case here.
The space available in the log can be monitored by hand using following commands:
USE Beta GO EXEC sp_helpsegment logsegment GO
Probably the last one table gives us the best information here. Free pages count is very low here! The same result would be returned when using:
EXEC sp_spaceused syslogs
or
dbcc checktable(syslogs)
What to do to unfreeze the transactions? For example more space could be added to the log like this:
USE master GO ALTER DATABASE Beta LOG ON BetaLogDev='3M' GO
Remember that command like this ADDS given amount of disk space to the database's log. So taking look to our database, we have now 5+3=8 MB for the log. Immediately after adding more space, the transaction started again:
Mar 19 2017 12:06PM
1 row(s) affected
1 row(s) affected
Mar 19 2017 12:06PMSpace available in segment 'logsegment' has fallen critically low in database 'Beta'. All future modifications to this database will be suspended until the transaction log is successfully dumped and space becomes available.
The transaction log in database Beta is almost full. Your transaction is being suspended until space is made available in the log.
1 row(s) affected
1 row(s) affected
Mar 19 2017 6:40PM1 row(s) affected
1 row(s) affected
1 row(s) affected
Mar 19 2017 12:06PMSpace available in segment 'logsegment' has fallen critically low in database 'Beta'. All future modifications to this database will be suspended until the transaction log is successfully dumped and space becomes available.
The transaction log in database Beta is almost full. Your transaction is being suspended until space is made available in the log.
1 row(s) affected
1 row(s) affected
Mar 19 2017 6:40PM1 row(s) affected
For example here the transaction was frozen at 12:06, but administrator has added more disk space to log around 6:40. At this moment the transaction was started again
Information like this can be also found in errorlog:
00:0006:00000:00007:2017/03/19 18:40:44.92 server 1 task(s) are sleeping waiting for space to become available in the log segment for database Beta.
00:0006:00000:00033:2017/03/19 18:41:43.31 server Space available in segment 'logsegment' has fallen critically low in database 'Beta'. All future modifications to this database will be suspended until the transaction log is successfully dumped and space becomes available.
00:0006:00000:00036:2017/03/19 18:41:43.31 server Error: 2812, Severity: 16, State: 5
00:0006:00000:00036:2017/03/19 18:41:43.31 server Stored procedure 'sp_thresholdaction' not found. Specify owner.objectname or use sp_help to check whether the object exists (sp_help may produce lots of output).
00:0006:00000:00007:2017/03/19 18:41:44.92 server 1 task(s) are sleeping waiting for space to become available in the log segment for database Beta.
Transaction were suspended, then some more space has been added, but the space was shortly again exhausted and the transactions were frozen again.
The other solution could be stopping the transaction. As you see in this example the transaction will never stop! So killing it is the only solution!
First of all we need to determine who causes the log being filled up. There may be also different reasons for filling up the log:
First of all we need to determine who causes the log being filled up. There may be also different reasons for filling up the log:
- A lot of small transactions were started, but one of them was not finished, so the log cannot be overwritten. Try to find the oldest transaction:
SELECT * FROM master..syslogshold
- One heavy session has generated the biggest transaction, that consumed all the space in the log. Note the number of opened and committed/rolled back transactions. Generally those amounts should be equal. Here, the session 33 has opened one transaction that is not finished and this transaction has sent ~5MB of data:
SELECT TOP 5 SPID, ULCBytesWritten, Transactions, Commits, Rollbacks FROM master..monProcessActivity ORDER BY ULCBytesWritten DESC GO
- To find the heavy session also following query can be used. It searches for records in syslogs table assigned to one session. (the idea is that column xactid is composed as session number concatenated with page number and row number in hex). Having it we can note which session has created the biggest amount of entries in syslogs. The last column is just a dbcc command that can be started to analyze the situation deeper and finally find the session spid:
SELECT TOP 5 xactid, convert(int,substring(xactid,1,4)) as logpage, convert(smallint,substring(xactid,5,2)) as logrow, count(*) as records_in_xact, 'dbcc log( ' + db_name() + ',1, ' + str(convert(int,xactid),10,0) + ', ' + str(convert(smallint, substring(xactid,5,2)),10,0) + ', 1, 0)' as 'dbcc command' FROM syslogs GROUP BY xactid ORDER BY count(*) desc GO
set switch on 3604 -- this returns results to the client dbcc log( Beta,1, 2572, 10, 1, 0)
Execution time: 0.002 seconds
LOG SCAN DEFINITION:
Database id : 8
log records for session id (2572,10)
Log operation type BEGINXACT (0)
Forward scan: starting at beginning of log for 1 records
Maximum of 1 log records.
LOG RECORDS: (0 records did not qualify so far.)
BEGINXACT (2572,10) sessionid=2572,10
attcnt=1 rno=10 op=0 padlen=5 len=80
odc_stat=0x0000 (0x0000)
loh_status: 0x0 (0x00000000)
masterxsid=(invalid sessionid)
xstat=XBEG_ENDXACT,
spid=33 suid=1 uid=1 masterdbid=0 dtmcord=0
name=$user_transaction time=Mar 19 2017 12:06:45:850PM
Total number of log records 1 qualified out of 1 scanned.
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role.
Execution time: 0.002 seconds
SELECT TOP 5 xactid, convert(int,substring(xactid,1,4)) as logpage, convert(smallint,substring(xactid,5,2)) as logrow, count(*) as records_in_xact, 'dbcc log( ' + db_name() + ',1, ' + str(convert(int,xactid),10,0) + ', ' + str(convert(smallint, substring(xactid,5,2)),10,0) + ', 1, 0)' as 'dbcc command' FROM syslogs GROUP BY xactid, convert(int,substring(xactid,1,4)),convert(smallint,substring(xactid,5,2)) HAVING xactid NOT IN ( SELECT xactid FROM syslogs WHERE op = 17 --checkpoint is atomic, no commit OR op = 30 ---commit tran ) ORDER BY count(*)
Resuming, when a session causing log being full has been found and when no other solution can be implemented, this session could be killed:
kill 33
This causes the transaction to be rolled back but this may still not release the space in the log! What needs to be done is just starting a log backup. One of following commands can be used:
DUMP TRAN Beta to dumpsdev
or
DUMP TRAN Beta WITH TRUNCATE_ONLY
or
DUMP TRAN Beta WITH NO_LOG
BTW: For the first command to work a database dump must be created first! Database backup can be done issuing following command:
DUMP DATABASE Beta to dumpsdev
The next above two DUMP LOG commands cause just emptying the log. The difference between them is:
- TRUNCATE_ONLY will try to release the inactive part of the log, but will need a small amount of free space in the log to write information about the log being truncated. If there is no space in the log it may fail
- NO_LOG will also try to release the inactive portion of the log but will not record any information in log, so it has bigger chances to succeed
Anyway, always after using TRUNCATE_ONLY or after NO_LOG, the database should have a new normal backup started. Without it, you may finally not have a valid backups (backup files chain may be broken). Below result of command
EXEC sp_spaceused syslogs
just after a DUMP TRAN:
Well, at this moment the log contains again a lot of free pages and the transactions can be started in the database again
Some articles, forum discussions related to the topic:
- https://archive.sap.com/discussions/thread/3360105 - determining the remaining log space
- https://blogs.sap.com/2013/06/05/ase-faq-my-transaction-log-filled-which-process-filled-up-the-log/ - finding blocking transactions
- http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc36272.1570/html/commands/X47924.htm - the DUMP command help
No comments:
Post a Comment