What is an LSN: Log Sequence Number

本文详细解释了SQL Server中日志序列号(LSN)的概念,包括其在事务日志记录中的唯一标识作用,如何通过不同的SQL Server表和函数获取LSN,以及LSN在备份和恢复过程中的应用。同时,文章还深入探讨了LSN的结构,如何从`fn_dblog`函数输出中解析LSN,并展示了如何通过LSN分析SQL Server的日志行为,识别潜在的应用性能问题。
January 17th, 2012

LSNs, or Log Sequence Numbers, are explained on MSDN at Introduction to Log Sequence Numbers:

Every record in the SQL Server transaction log is uniquely identified by a log sequence number (LSN). LSNs are ordered such that if LSN2 is greater than LSN1, the change described by the log record referred to by LSN2 occurred after the change described by the log record LSN.

There are several places where LSNs are exposed. For examplesys.database_recovery_status has the columns last_log_backup_lsn andfork_point_lsnsys.database_mirroring has the mirroring_failover_lsn column and the msdb table backupset contains first_lsnlast_lsncheckpoint_lsn,database_backup_lsnfork_point_lsn and differential_base_lsn. Not surprisingly all these places where LSNs are exposed are related to backup and recovery (mirroring is a form of recovery). The LSN is exposed a numeric(25,0) value that can be compared: a bigger LSN number value means a later log sequence number and therefore it can indicate if more log needs to be backed up or recovered.

Yet we can dig deeper. Look at the LSN as exposed by the fn_dblog function:


select * from fn_dblog(null, null);
  
Current LSNOperationContextTransaction ID...
00000014:00000061:0001LOP_BEGIN_XACTLCX_NULL0000:000001e4 
00000014:00000061:0002LOP_INSERT_ROWSLCX_NULL0000:000001e4 
...    
00000014:00000061:02eaLOP_INSERT_ROWSLCX_NULL0000:000001e4 
00000014:000000d9:0001LOP_INSERT_ROWSLCX_NULL0000:000001e4 
00000014:000000d9:0002LOP_INSERT_ROWSLCX_NULL0000:000001e4 
...    
00000014:00000153:021eLOP_INSERT_ROWSLCX_NULL0000:000001e4 
00000014:00000153:021fLOP_COMMIT_XACTLCX_NULL0000:000001e4 
00000014:000001ab:0001LOP_BEGIN_XACTLCX_NULL0000:000001ea 
...    
00000014:000001ab:01acLOP_INSERT_ROWSLCX_NULL0000:000001ea 
00000015:00000010:0001LOP_INSERT_ROWSLCX_NULL0000:000001ea 

The LSN is shown as a three part structure. The first part seems to stay the same (the 14), the middle part apparently has some erratic increases and the last part seems to increase monotonically but it resets back to 0 when the middle part changes. It is much easier to understand what’s happening when you know what the three parts are:

  • the first part is the VLF sequence number.
  • the middle part is the offset to the log block
  • the last part is the slot number inside the log block

Virtual Log files

SQL Server manages the log by splitting into regions called VLFs, Virtual Log Files, as explained in the Transaction Log Physical Architecture. We can inspect the VLFs of a database using DBCC LOGINFO:


FileId FileSize    StartOffset  FSeqNo  Status      Parity CreateLSN
------ ----------- -------------------------------- ------ -----------------
2      253952      8192         20      2           64     0
2      253952      262144       21      2           64     0
2      270336      516096       22      2           64     20000000021700747
2      262144      786432       23      2           64     21000000013600747
2      262144      1048576      24      2           64     22000000024900748
...
2      393216      16973824     75      2           64     74000000013600748
2      393216      17367040     0       0           0      74000000013600748
2      393216      17760256     0       0           0      74000000013600748
2      524288      18153472     0       0           0      74000000013600748

(59 row(s) affected)

So back to our fn_dblog result: the Current LSN value of 00000014:00000061:0001 means the following log record:

  • the VLF sequence number 0×14 (20 decimal)
  • in the log block starting at offset 0×61 in the VLF (measured in units of 512 bytes)
  • the slot number 1

From the DBCC LOGINFO output we know that the VLF with sequence number 0×14 is starting at offset 8192 in the LDF file and has a size of 253952. It is the first VLF in the log file. the next LSNs increase the slot number until the LSN 00000014:00000061:02ea and then the LSN changes to 00000014:000000d9:0001. This means that the block that starts at offset 0×61 has filled up and the next block, from offset 0xd9, started to be used. If we do the math, 0xd9-0×61 is 0×78 (or 120 decimal), which is exactly 60Kb. You may remember that the maximum SQL Server log block size is 60Kb.

Our transaction continued to insert records until the LSN 00000014:00000153:021e then at the next LSN we have a commit operation (LOP_COMMIT_XACT). The next LSN, which is for the next transaction start, is at LSN 00000014:000001ab:0001. What does this tell us? The transaction terminated with the INSERT operation at LSN 00000014:00000153:021e and then it issued a COMMIT. The commit operation generated one more log record, the one at LSN 00000014:00000153:021f and then asked for the commit LSN to be hardened. This causes the log block containing this LSN (the log block starting at offset 0×153 in the VFL 0×14) to be closed and written to disk (along with any other not-yet-written log-block that isahead of this block). The next block can start immediately after this block, so the next operation will have the LSN 00000014:000001ab:0001. If we do the math we can see that 0x1ab-0×153 is 0×58 (decimal 88) so this last log block had 44Kb.

I hope by now is clear what happened next in the fn_dblogoutput I shown: the transaction continues to insert records generating more LSNs. The entry at 00000014:000001ab:01ac is not only the last one in the current log block, but is also the last one in the current VLF. The next LSN is 00000015:00000010:0001, the LSN at slot 1 in the first log block (offset 0×10) of the VLF with sequence number 0×15.

Decimal LSNs

What about those LSN numbers like the 20000000021700747 CreateLSN value shown in DBCC LOGINFO output? They are still three part LSNs, but the values are represented in decimal. 20000000021700747 would be the LSN 00000014:000000d9:02eb.

Log flush waits

Look at the following fn_dblog output:


...
00000016:0000003c:0001  LOP_BEGIN_XACT      LCX_NULL    0000:0000057f 
00000016:0000003c:0002  LOP_INSERT_ROWS     LCX_HEAP    0000:0000057f 
00000016:0000003c:0003  LOP_COMMIT_XACT     LCX_NULL    0000:0000057f 
00000016:0000003d:0001  LOP_BEGIN_XACT      LCX_NULL    0000:00000580 
00000016:0000003d:0002  LOP_INSERT_ROWS     LCX_HEAP    0000:00000580 
00000016:0000003d:0003  LOP_COMMIT_XACT     LCX_NULL    0000:00000580 
00000016:0000003e:0001  LOP_BEGIN_XACT      LCX_NULL    0000:00000581 
00000016:0000003e:0002  LOP_INSERT_ROWS     LCX_HEAP    0000:00000581 
00000016:0000003e:0003  LOP_COMMIT_XACT     LCX_NULL    0000:00000581 
00000016:0000003f:0001  LOP_BEGIN_XACT      LCX_NULL    0000:00000582 
00000016:0000003f:0002  LOP_INSERT_ROWS     LCX_HEAP    0000:00000582 
00000016:0000003f:0003  LOP_COMMIT_XACT     LCX_NULL    0000:00000582 
...

Can you spot the problem? Notice how the LSN slot number stays at at 1,2,3 and the log block number grows very frequently: 3c, 3d, 3e, 3f… This is the log signature of a sequence of single row inserts that each committed individually. After each INSERT the application had to wait for the log block to be flushed to disk. The logs blocks were all of minimal size, 512 bytes.

Here is how I generated this log:


set nocount on;
declare @i int = 0;
while @i < 1000
begin
	insert into t (filler) values ('A');
	set @i += 1;
end
go

Had the application used a batch commit it would had solved several issues:

  • only wait for one or few commits to flush the log.
  • write less log, since every transaction generates an LOP_BEGIN_XACT and an LOP_COMMIT_XACT (they add up!).
  • write the operations in few large IO requests as opposed to a lot of small IO requests.

So lets add batch commits to our test script:


set nocount on;
declare @i int = 0;
begin transaction
while @i < 1000
begin
	insert into t (filler) values ('A');
	set @i += 1;
	if @i % 100 = 0
	begin
		commit;
		begin transaction;
	end
end
commit
go

and then lets look at the log:


00000016:0000011d:0001  LOP_BEGIN_XACT     LCX_NULL   0000:000005d9
00000016:0000011d:0002  LOP_INSERT_ROWS    LCX_HEAP   0000:000005d9
00000016:0000011d:0003  LOP_INSERT_ROWS    LCX_HEAP   0000:000005d9
...
00000016:0000011d:006f  LOP_INSERT_ROWS    LCX_HEAP   0000:000005d9
00000016:0000011d:0070  LOP_COMMIT_XACT    LCX_NULL   0000:000005d9
00000016:00000136:0001  LOP_BEGIN_XACT     LCX_NULL   0000:000005db
00000016:00000136:0002  LOP_INSERT_ROWS    LCX_HEAP   0000:000005db
...
00000016:00000136:0064  LOP_INSERT_ROWS    LCX_HEAP   0000:000005db
00000016:00000136:0065  LOP_INSERT_ROWS    LCX_HEAP   0000:000005db
00000016:00000136:0066  LOP_COMMIT_XACT    LCX_NULL   0000:000005db
00000016:0000014d:0001  LOP_BEGIN_XACT     LCX_NULL   0000:000005dc
00000016:0000014d:0002  LOP_INSERT_ROWS    LCX_HEAP   0000:000005dc
00000016:0000014d:0003  LOP_INSERT_ROWS    LCX_HEAP   0000:000005dc
...
00000016:0000014d:0066  LOP_INSERT_ROWS    LCX_HEAP   0000:000005dc
00000016:0000014d:0067  LOP_COMMIT_XACT    LCX_NULL   0000:000005dc

We can see how the batch commit has created fewer, larger, log blocks. The application had to wait fewer times for the log to harden, and on each wait it issued a larger IO request. The log blocks are also more densely filled with LOP_INSERT_ROWS operations and do not have the overhead of having to log the LOP_BEGIN_XACT/LOP_COMMIT_XACT for every row inserted.

Conclusion

This little example shows not only how to understand the LSN structure, but it also shows how to read into the fn_dblog output. I also wanted to show the typical log signature of a commit operation: the LOP_COMMIT_XACT operation is recorded in the log and the log block is closed and flushed to disk. The next LSN will usually have slot 1 in the next block. The last example even shows how reading the log can spot potential application performance problems.

2025-12-19T05:34:37.849417Z 0 [Warning] 'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and 'ERROR_FOR_DIVISION_BY_ZERO' sql modes should be used with strict mode. They will be merged with strict mode in a future release. 2025-12-19T05:34:37.849496Z 0 [Note] --secure-file-priv is set to NULL. Operations related to importing and exporting data are disabled 2025-12-19T05:34:37.849866Z 0 [Note] C:\BtSoft\mysql\MySQL5.7\bin\mysqld.exe (mysqld 5.7.38-log) starting as process 8348 ... 2025-12-19T05:34:37.868526Z 0 [Note] InnoDB: Mutexes and rw_locks use Windows interlocked functions 2025-12-19T05:34:37.869014Z 0 [Note] InnoDB: Uses event mutexes 2025-12-19T05:34:37.869267Z 0 [Note] InnoDB: _mm_lfence() and _mm_sfence() are used for memory barrier 2025-12-19T05:34:37.869618Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11 2025-12-19T05:34:37.870357Z 0 [Note] InnoDB: Number of pools: 1 2025-12-19T05:34:37.870807Z 0 [Note] InnoDB: Not using CPU crc32 instructions 2025-12-19T05:34:37.873342Z 0 [Note] InnoDB: Initializing buffer pool, total size = 256M, instances = 1, chunk size = 128M 2025-12-19T05:34:37.890813Z 0 [Note] InnoDB: Completed initialization of buffer pool 2025-12-19T05:34:37.928888Z 0 [Note] InnoDB: Highest supported file format is Barracuda. 2025-12-19T05:34:37.935781Z 0 [Note] InnoDB: Log scan progressed past the checkpoint lsn 47795629696 2025-12-19T05:34:37.936452Z 0 [Note] InnoDB: Doing recovery: scanned up to log sequence number 47795678803 2025-12-19T05:34:37.956276Z 0 [Note] InnoDB: Database was not shutdown normally! 2025-12-19T05:34:37.956614Z 0 [Note] InnoDB: Starting crash recovery. 2025-12-19T05:34:38.334975Z 0 [Note] InnoDB: 1 transaction(s) which must be rolled back or cleaned up in total 0 row operations to undo 2025-12-19T05:34:38.335541Z 0 [Note] InnoDB: Trx id counter is 101645056 2025-12-19T05:34:38.336142Z 0 [Note] InnoDB: Starting an apply batch of log records to the database... InnoDB: Progress in percent: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 2025-12-19T05:34:38.853689Z 0 [Note] InnoDB: Apply batch completed 2025-12-19T05:34:38.854109Z 0 [Note] InnoDB: Last MySQL binlog file position 0 55386, file name mysql-bin.000051 2025-12-19T05:34:38.961866Z 0 [Note] InnoDB: Cleaning up trx with id 101609997 2025-12-19T05:34:39.294080Z 0 [ERROR] InnoDB: In file '.\20251107_092631\auth.ibd', tablespace id and flags are 828 and 33, but in the InnoDB data dictionary they are 122 and 33. Have you moved InnoDB .ibd files around without using the commands DISCARD TABLESPACE and IMPORT TABLESPACE? Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting-datadict.html for how to resolve the issue. 2025-12-19T05:34:39.295376Z 0 [ERROR] InnoDB: Operating system error number 203 in a file operation. 2025-12-19T05:34:39.295740Z 0 [Note] InnoDB: Some operating system error numbers are described at http://dev.mysql.com/doc/refman/5.7/en/operating-system-error-codes.html 2025-12-19T05:34:39.296279Z 0 [ERROR] InnoDB: Could not find a valid tablespace file for `20251107_092631/auth`. Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting-datadict.html for how to resolve the issue. 2025-12-19T05:34:39.296984Z 0 [Warning] InnoDB: Ignoring tablespace `20251107_092631/auth` because it could not be opened. 2025-12-19T05:34:39.379037Z 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1" 2025-12-19T05:34:39.379567Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables 2025-12-19T05:34:39.380394Z 0 [Note] InnoDB: Setting file 'D:\MySQL\Data\ibtmp1' size to 12 MB. Physically writing the file full; Please wait ... 2025-12-19T05:34:39.435030Z 0 [Note] InnoDB: File 'D:\MySQL\Data\ibtmp1' size is now 12 MB. 2025-12-19T05:34:39.455825Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active. 2025-12-19T05:34:39.456485Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active. 2025-12-19T05:34:39.457305Z 0 [Note] InnoDB: Waiting for purge to start 2025-12-19T05:34:39.509818Z 0 [Note] InnoDB: 5.7.38 started; log sequence number 47795678803 2025-12-19T05:34:39.510836Z 0 [Note] Plugin 'FEDERATED' is disabled. 2025-12-19T05:34:39.514400Z 0 [Note] InnoDB: Loading buffer pool(s) from D:\MySQL\Data\ib_buffer_pool 2025-12-19T05:34:39.522762Z 0 [Note] Recovering after a crash using mysql-bin 2025-12-19T05:34:39.523590Z 0 [Note] Starting crash recovery... 2025-12-19T05:34:39.523929Z 0 [Note] Crash recovery finished. 2025-12-19T05:34:39.569369Z 0 [Note] Found ca.pem, server-cert.pem and server-key.pem in data directory. Trying to enable SSL support using them. 2025-12-19T05:34:39.569953Z 0 [Note] Skipping generation of SSL certificates as certificate files are present in data directory. 2025-12-19T05:34:39.570390Z 0 [Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher. 2025-12-19T05:34:39.570890Z 0 [Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher. 2025-12-19T05:34:39.572758Z 0 [Warning] CA certificate ca.pem is self signed. 2025-12-19T05:34:39.573483Z 0 [Note] Skipping generation of RSA key pair as key files are present in data directory. 2025-12-19T05:34:39.574195Z 0 [Note] Server hostname (bind-address): '*'; port: 3306 2025-12-19T05:34:39.574741Z 0 [Note] IPv6 is available. 2025-12-19T05:34:39.575017Z 0 [Note] - '::' resolves to '::'; 2025-12-19T05:34:39.575349Z 0 [Note] Server socket created on IP: '::'. 2025-12-19T05:34:39.604561Z 0 [Note] Failed to start slave threads for channel '' 2025-12-19T05:34:39.619077Z 0 [ERROR] InnoDB: Page [page id: space=572, page number=3] log sequence number 47818895373 is in the future! Current system log sequence number 47795679298. 2025-12-19T05:34:39.619873Z 0 [ERROR] InnoDB: Your database may be corrupt or you may have copied the InnoDB tablespace but not the InnoDB log files. Please refer to http://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.html for information about forcing recovery. 2025-12-19T05:34:39.633764Z 0 [Note] Event Scheduler: Loaded 0 events 2025-12-19T05:34:39.634297Z 0 [Note] C:\BtSoft\mysql\MySQL5.7\bin\mysqld.exe: ready for connections. Version: '5.7.38-log' socket: '' port: 3306 MySQL Community Server (GPL) 2025-12-19 13:34:42 0x5d18 InnoDB: Assertion failure in thread 23832 in file fsp0fsp.cc line 3880 InnoDB: Failing assertion: xdes_mtr_get_bit(descr, XDES_FREE_BIT, header_page % FSP_EXTENT_SIZE, mtr) == FALSE InnoDB: We intentionally generate a memory trap. InnoDB: Submit a detailed bug report to http://bugs.mysql.com. InnoDB: If you get repeated assertion failures or crashes, even InnoDB: immediately after the mysqld startup, there may be InnoDB: corruption in the InnoDB tablespace. Please refer to InnoDB: http://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.html InnoDB: about forcing recovery. 05:34:42 UTC - mysqld got exception 0x80000003 ; This could be because you hit a bug. It is also possible that this binary or one of the libraries it was linked against is corrupt, improperly built, or misconfigured. This error can also be caused by malfunctioning hardware. Attempting to collect some information that could help diagnose the problem. As this is a crash and something is definitely wrong, the information collection process might fail. key_buffer_size=134217728 read_buffer_size=131072 max_used_connections=4 max_threads=300 thread_count=4 connection_count=4 It is possible that mysqld could use up to key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 403530 K bytes of memory Hope that's ok; if not, decrease some variables in the equation. Thread pointer: 0x23a27e14790 Attempting backtrace. You can use the following information to find out where mysqld died. If you see no messages after this, something went terribly wrong... 7ff63abcb302 mysqld.exe!my_errno() 7ffc6838ee1d MSVCR120.dll!raise() 7ffc68394a14 MSVCR120.dll!abort() 7ff63ace7434 mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff63acfab30 mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff63ac64cdf mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff63ac673e6 mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff63ac66f29 mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff63ac63e9a mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff63ac2a36e mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff63ac2e5ac mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ffc7f294cb0 KERNEL32.DLL!BaseThreadInitThunk() 7ffc8077edcb ntdll.dll!RtlUserThreadStart() Trying to get some variables. Some pointers may be invalid and cause the dump to abort. Query (0): Connection ID (thread ID): 0 Status: NOT_KILLED The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains information that should help you find out what is causing the crash. 2025-12-19T05:34:42.715725Z 0 [Note] InnoDB: Buffer pool(s) load completed at 251219 13:34:42
最新发布
12-20
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains information that should help you find out what is causing the crash. 2025-09-15T07:56:29.816069Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details). 2025-09-15T07:56:29.816120Z 0 [Warning] 'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and 'ERROR_FOR_DIVISION_BY_ZERO' sql modes should be used with strict mode. They will be merged with strict mode in a future release. 2025-09-15T07:56:29.817337Z 0 [Note] D:\work\w\sql\mysql\mysql-5.7.29.0\exe\MySQL Server 5.7\bin\mysqld.exe (mysqld 5.7.29-log) starting as process 11660 ... 2025-09-15T07:56:29.820886Z 0 [Note] InnoDB: Mutexes and rw_locks use Windows interlocked functions 2025-09-15T07:56:29.821179Z 0 [Note] InnoDB: Uses event mutexes 2025-09-15T07:56:29.821378Z 0 [Note] InnoDB: _mm_lfence() and _mm_sfence() are used for memory barrier 2025-09-15T07:56:29.821652Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11 2025-09-15T07:56:29.821885Z 0 [Note] InnoDB: Adjusting innodb_buffer_pool_instances from 8 to 1 since innodb_buffer_pool_size is less than 1024 MiB 2025-09-15T07:56:29.822459Z 0 [Note] InnoDB: Number of pools: 1 2025-09-15T07:56:29.822749Z 0 [Note] InnoDB: Not using CPU crc32 instructions 2025-09-15T07:56:29.835860Z 0 [Note] InnoDB: Initializing buffer pool, total size = 8M, instances = 1, chunk size = 8M 2025-09-15T07:56:29.836530Z 0 [Note] InnoDB: Completed initialization of buffer pool 2025-09-15T07:56:29.858200Z 0 [Note] InnoDB: Highest supported file format is Barracuda. 2025-09-15T07:56:29.859706Z 0 [Note] InnoDB: Log scan progressed past the checkpoint lsn 235659587 2025-09-15T07:56:29.885430Z 0 [Note] InnoDB: Doing recovery: scanned up to log sequence number 236694974 2025-09-15T07:56:29.886519Z 0 [Note] InnoDB: Database was not shutdown normally! 2025-09-15T07:56:29.886759Z 0 [Note] InnoDB: Starting crash recovery. 2025-09-15T07:56:29.930740Z 0 [Note] InnoDB: Starting an apply batch of log records to the database... InnoDB: Progress in percent: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 2025-09-15T07:56:30.487147Z 0 [Note] InnoDB: Apply batch completed 2025-09-15T07:56:30.492928Z 0 [Note] InnoDB: Doing recovery: scanned up to log sequence number 236694974 2025-09-15T07:56:30.592739Z 0 [Note] InnoDB: Starting an apply batch of log records to the database... InnoDB: Progress in percent: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 2025-09-15T07:56:31.103937Z 0 [Note] InnoDB: Apply batch completed 2025-09-15T07:56:31.312631Z 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1" 2025-09-15T07:56:31.312965Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables 2025-09-15T07:56:31.313350Z 0 [Note] InnoDB: Setting file '.\ibtmp1' size to 12 MB. Physically writing the file full; Please wait ... 2025-09-15T07:56:31.338641Z 0 [Note] InnoDB: File '.\ibtmp1' size is now 12 MB. 2025-09-15T07:56:31.339627Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active. 2025-09-15T07:56:31.339952Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active. 2025-09-15T07:56:31.340353Z 0 [Note] InnoDB: Waiting for purge to start 2025-09-15 15:56:31 0x948 InnoDB: Assertion failure in thread 2376 in file fut0lst.ic line 93 InnoDB: Failing assertion: addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA InnoDB: We intentionally generate a memory trap. InnoDB: Submit a detailed bug report to http://bugs.mysql.com. InnoDB: If you get repeated assertion failures or crashes, even InnoDB: immediately after the mysqld startup, there may be InnoDB: corruption in the InnoDB tablespace. Please refer to InnoDB: http://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.html InnoDB: about forcing recovery. 07:56:31 UTC - mysqld got exception 0x80000003 ; This could be because you hit a bug. It is also possible that this binary or one of the libraries it was linked against is corrupt, improperly built, or misconfigured. This error can also be caused by malfunctioning hardware. Attempting to collect some information that could help diagnose the problem. As this is a crash and something is definitely wrong, the information collection process might fail. key_buffer_size=8388608 read_buffer_size=65536 max_used_connections=0 max_threads=151 thread_count=0 connection_count=0 It is possible that mysqld could use up to key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 58352 K bytes of memory Hope that's ok; if not, decrease some variables in the equation. Thread pointer: 0x1a9fc88f6f0 Attempting backtrace. You can use the following information to find out where mysqld died. If you see no messages after this, something went terribly wrong... 2025-09-15T07:56:31.391164Z 0 [Note] InnoDB: 5.7.29 started; log sequence number 236694974 2025-09-15T07:56:31.391917Z 0 [Note] InnoDB: Loading buffer pool(s) from D:\work\w\sql\mysql\mysql-5.7.29.0\exe\data\Data\ib_buffer_pool 2025-09-15T07:56:31.391988Z 0 [Note] Plugin 'FEDERATED' is disabled. 2025-09-15T07:56:31.401557Z 0 [Note] Found ca.pem, server-cert.pem and server-key.pem in data directory. Trying to enable SSL support using them. 2025-09-15T07:56:31.401962Z 0 [Note] Skipping generation of SSL certificates as certificate files are present in data directory. 2025-09-15T07:56:31.402887Z 0 [Warning] CA certificate ca.pem is self signed. 2025-09-15T07:56:31.403175Z 0 [Note] Skipping generation of RSA key pair as key files are present in data directory. 2025-09-15T07:56:31.403618Z 0 [Note] Server hostname (bind-address): '*'; port: 3306 2025-09-15T07:56:31.403978Z 0 [Note] IPv6 is available. 2025-09-15T07:56:31.404161Z 0 [Note] - '::' resolves to '::'; 2025-09-15T07:56:31.404393Z 0 [Note] Server socket created on IP: '::'. 2025-09-15T07:56:31.404942Z 0 [Note] InnoDB: Buffer pool(s) load completed at 250915 15:56:31 2025-09-15T07:56:31.421205Z 0 [Note] Failed to start slave threads for channel '' 2025-09-15T07:56:31.427275Z 0 [Note] Event Scheduler: Loaded 0 events 2025-09-15T07:56:31.427607Z 0 [Note] D:\work\w\sql\mysql\mysql-5.7.29.0\exe\MySQL Server 5.7\bin\mysqld.exe: ready for connections. Version: '5.7.29-log' socket: '' port: 3306 MySQL Community Server (GPL) 7ff7bf8beeb2 mysqld.exe!my_errno() 7ffc8fbaec9d MSVCR120.dll!raise() 7ffc8fbb4874 MSVCR120.dll!abort() 7ff7bf9da744 mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff7bf98298c mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff7bf981be4 mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff7bf98119c mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff7bf980ae2 mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff7bf91dd6e mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ff7bf921f8c mysqld.exe!?reserve@?$vector@EV?$allocator@E@std@@@std@@QEAAX_K@Z() 7ffca5217034 KERNEL32.DLL!BaseThreadInitThunk() 7ffca62bcec1 ntdll.dll!RtlUserThreadStart() Trying to get some variables. Some pointers may be invalid and cause the dump to abort. Query (0): Connection ID (thread ID): 0 Status: NOT_KILLED The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains information that should help you find out what is causing the crash.
09-16
2025-10-28T20:39:45.659482+08:00 15 [ERROR] InnoDB: Operating system error number 32 in a file operation. 2025-10-28T20:39:45.660451+08:00 15 [ERROR] InnoDB: The error means that another program is using InnoDB's files. This might be a backup or antivirus software or another instance of MySQL. Please close it to get rid of this error. 2025-10-28 20:39:55 0x740c InnoDB: Assertion failure in thread 29708 in file handler0alter.cc line 7404 InnoDB: Failing assertion: error == DB_SUCCESS InnoDB: We intentionally generate a memory trap. InnoDB: Submit a detailed bug report to http://bugs.mysql.com. InnoDB: If you get repeated assertion failures or crashes, even InnoDB: immediately after the mysqld startup, there may be InnoDB: corruption in the InnoDB tablespace. Please refer to InnoDB: http://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.html InnoDB: about forcing recovery. 2025-10-28T20:39:55.663376+08:00 0 [Note] InnoDB: page_cleaner: 1000ms intended loop took 9553ms. The settings might not be optimal. (flushed=0 and evicted=0, during the time.) 12:39:55 UTC - mysqld got exception 0x80000003 ; This could be because you hit a bug. It is also possible that this binary or one of the libraries it was linked against is corrupt, improperly built, or misconfigured. This error can also be caused by malfunctioning hardware. Attempting to collect some information that could help diagnose the problem. As this is a crash and something is definitely wrong, the information collection process might fail. key_buffer_size=536870912 read_buffer_size=131072 max_used_connections=51 max_threads=600 thread_count=50 connection_count=50 It is possible that mysqld could use up to key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 761977 K bytes of memory Hope that's ok; if not, decrease some variables in the equation. Thread pointer: 0x26ebec94ce0 Attempting backtrace. You can use the following information to find out where mysqld died. If you see no messages after this, something went terribly wrong... 7ff754c49812 mysqld.exe!my_sigabrt_handler()[my_thr_init.c:449] 7ff754fee349 mysqld.exe!raise()[winsig.c:587] 7ff754fed240 mysqld.exe!abort()[abort.c:82] 7ff754d49b08 mysqld.exe!ut_dbg_assertion_failed()[ut0dbg.cc:67] 7ff754e2f72f mysqld.exe!ha_innobase::commit_inplace_alter_table()[handler0alter.cc:8275] 7ff7545c1443 mysqld.exe!mysql_inplace_alter_table()[sql_table.cc:7449] 7ff7545bf17a mysqld.exe!mysql_alter_table()[sql_table.cc:9538] 7ff7546e565e mysqld.exe!Sql_cmd_alter_table::execute()[sql_alter.cc:316] 7ff754546aa5 mysqld.exe!mysql_execute_command()[sql_parse.cc:3521] 7ff75454938a mysqld.exe!mysql_parse()[sql_parse.cc:5525] 7ff75454239d mysqld.exe!dispatch_command()[sql_parse.cc:1432] 7ff7545433aa mysqld.exe!do_command()[sql_parse.cc:999] 7ff7545081e4 mysqld.exe!handle_connection()[connection_handler_per_thread.cc:301] 7ff754f2cd92 mysqld.exe!pfs_spawn_thread()[pfs.cc:2191] 7ff754c4967b mysqld.exe!win_thread_start()[my_thread.c:38] 7ff754feddbf mysqld.exe!_callthreadstartex()[threadex.c:376] 7ff754fee00a mysqld.exe!_threadstartex()[threadex.c:354] 7ffaba1f84d4 KERNEL32.DLL!BaseThreadInitThunk() 7ffabc6ee871 ntdll.dll!RtlUserThreadStart() Trying to get some variables. Some pointers may be invalid and cause the dump to abort. Query (26ebece8580): ALTER TABLE formmain_0495 DROP COLUMN field0028 Connection ID (thread ID): 15 Status: NOT_KILLED The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains information that should help you find out what is causing the crash. 2025-10-28T20:43:23.759825+08:00 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details). 2025-10-28T20:43:23.759825+08:00 0 [Warning] Insecure configuration for --secure-file-priv: Current value does not restrict location of generated files. Consider setting it to a valid, non-empty path. 2025-10-28T20:43:23.760771+08:00 0 [Note] D:\newmysql\mysql-5.7.12-winx64\bin\mysqld (mysqld 5.7.12-log) starting as process 39684 ... 2025-10-28T20:43:23.818393+08:00 0 [Note] InnoDB: Mutexes and rw_locks use Windows interlocked functions 2025-10-28T20:43:23.819370+08:00 0 [Note] InnoDB: Uses event mutexes 2025-10-28T20:43:23.819370+08:00 0 [Note] InnoDB: _mm_lfence() and _mm_sfence() are used for memory barrier 2025-10-28T20:43:23.820343+08:00 0 [Note] InnoDB: Compressed tables use zlib 1.2.3 2025-10-28T20:43:23.821322+08:00 0 [Note] InnoDB: Number of pools: 1 2025-10-28T20:43:23.822294+08:00 0 [Note] InnoDB: Not using CPU crc32 instructions 2025-10-28T20:43:23.866243+08:00 0 [Note] InnoDB: Initializing buffer pool, total size = 8G, instances = 8, chunk size = 128M 2025-10-28T20:43:24.265683+08:00 0 [Note] InnoDB: Completed initialization of buffer pool 2025-10-28T20:43:24.414092+08:00 0 [Note] InnoDB: Highest supported file format is Barracuda. 2025-10-28T20:43:24.508818+08:00 0 [Note] InnoDB: Log scan progressed past the checkpoint lsn 933908534 2025-10-28T20:43:24.633818+08:00 0 [Note] InnoDB: Doing recovery: scanned up to log sequence number 933994745 2025-10-28T20:43:24.639683+08:00 0 [Note] InnoDB: Ignoring data file '.\oa\formmain_0495.ibd' with space ID 1585. Another data file called .\oa\#sql-ib1600-4242521553.ibd exists with the same space ID. 2025-10-28T20:43:24.641629+08:00 0 [Note] InnoDB: Ignoring data file '.\oa\formmain_0495.ibd' with space ID 1583. Another data file called .\oa\#sql-ib1602-4242521554.ibd exists with the same space ID. 2025-10-28T20:43:24.643587+08:00 0 [Note] InnoDB: Ignoring data file '.\oa\formmain_0495.ibd' with space ID 1585. Another data file called .\oa\#sql-ib1600-4242521553.ibd exists with the same space ID. 2025-10-28T20:43:24.647490+08:00 0 [Note] InnoDB: Ignoring data file '.\oa\formmain_0495.ibd' with space ID 1583. Another data file called .\oa\#sql-ib1602-4242521554.ibd exists with the same space ID. 2025-10-28T20:43:24.661159+08:00 0 [Note] InnoDB: Database was not shutdown normally! 2025-10-28T20:43:24.661159+08:00 0 [Note] InnoDB: Starting crash recovery. 2025-10-28T20:43:24.844755+08:00 0 [Note] InnoDB: 1 transaction(s) which must be rolled back or cleaned up in total 47 row operations to undo 2025-10-28T20:43:24.845734+08:00 0 [Note] InnoDB: Trx id counter is 14848 2025-10-28T20:43:24.859405+08:00 0 [Note] InnoDB: Starting an apply batch of log records to the database... InnoDB: Progress in percent: 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 2025-10-28T20:43:25.704135+08:00 0 [Note] InnoDB: Apply batch completed 2025-10-28T20:43:32.680689+08:00 0 [Note] InnoDB: Starting in background the rollback of uncommitted transactions 2025-10-28T20:43:32.681665+08:00 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1" 2025-10-28T20:43:32.681665+08:00 0 [Note] InnoDB: Rolling back trx with id 14454, 47 rows to undo 2025-10-28T20:43:32.682647+08:00 0 [Note] InnoDB: Creating shared tablespace for temporary tables 2025-10-28T20:43:32.684595+08:00 0 [Note] InnoDB: Setting file '.\ibtmp1' size to 12 MB. Physically writing the file full; Please wait ... 2025-10-28T20:43:32.695334+08:00 0 [Note] InnoDB: Rollback of trx with id 14454 completed 2025-10-28T20:43:32.696312+08:00 0 [Note] InnoDB: Rollback of non-prepared transactions completed 2025-10-28T20:43:32.732452+08:00 0 [Note] InnoDB: File '.\ibtmp1' size is now 12 MB. 2025-10-28T20:43:32.757857+08:00 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active. 2025-10-28T20:43:32.758821+08:00 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active. 2025-10-28T20:43:32.760764+08:00 0 [Note] InnoDB: Waiting for purge to start 2025-10-28T20:43:32.812522+08:00 0 [Note] InnoDB: 5.7.12 started; log sequence number 933994745 2025-10-28T20:43:32.812522+08:00 0 [Note] InnoDB: page_cleaner: 1000ms intended loop took 8438ms. The settings might not be optimal. (flushed=0 and evicted=0, during the time.) 2025-10-28T20:43:32.813529+08:00 0 [Note] Plugin 'FEDERATED' is disabled. 2025-10-28T20:43:32.813529+08:00 0 [Note] InnoDB: Loading buffer pool(s) from D:\newmysql\mysql-5.7.12-winx64\data\ib_buffer_pool 2025-10-28T20:43:32.830109+08:00 0 [Warning] Failed to set up SSL because of the following SSL library error: SSL context is not usable without certificate and private key 2025-10-28T20:43:32.832067+08:00 0 [Note] Server hostname (bind-address): '*'; port: 3306 2025-10-28T20:43:32.834022+08:00 0 [Note] IPv6 is available. 2025-10-28T20:43:32.834022+08:00 0 [Note] - '::' resolves to '::'; 2025-10-28T20:43:32.835011+08:00 0 [Note] Server socket created on IP: '::'. 2025-10-28T20:43:32.854535+08:00 0 [Note] InnoDB: Buffer pool(s) load completed at 251028 20:43:32 2025-10-28T20:43:32.904319+08:00 0 [Note] Event Scheduler: Loaded 0 events 2025-10-28T20:43:32.905296+08:00 0 [Note] D:\newmysql\mysql-5.7.12-winx64\bin\mysqld: ready for connections. Version: '5.7.12-log' socket: '' port: 3306 MySQL Community Server (GPL)
10-29
<think>我们正在讨论Redo LogLSN机制如何保证日志完整性的原理。根据引用内容,LSNLog Sequence Number)是一个单调递增的序列号,用于标识redo log的写入位置。每次写入redo log时,LSN都会增加相应的长度。LSN不仅存在于redo log中,还存在于每个数据页的头部(FIL_PAGE_LSN),记录了该数据页最后一次被修改时的LSN值。 原理分析: 1. **写入一致性**:当修改数据页时,首先在内存中修改,并将修改操作记录到redo log buffer,同时生成一个LSN。这个LSN也会写入到数据页头部的FIL_PAGE_LSN字段(此时数据页仍在内存中)。这样,数据页和redo log都记录了相同的LSN,表示这个修改的日志点。 2. **崩溃恢复**:在崩溃恢复时,系统会扫描redo log,并比较redo log中的LSN和数据页中的LSN: - 如果数据页的LSN小于redo log中某个修改的LSN,说明这个修改还没有刷到磁盘数据页上,需要重做(redo)这个操作。 - 如果数据页的LSN大于或等于redo log中的LSN,说明这个修改已经写入到数据页,无需重做。 3. **检查点(Checkpoint)机制**:检查点记录了一个LSN值(last checkpoint at),表示在这个LSN之前的所有修改都已经刷到了磁盘数据页上。这样,在恢复时只需要从检查点对应的LSN开始重做后续的redo log即可,避免扫描整个redo log。 4. **防止重复应用**:由于每个数据页都记录了它最后一次被修改的LSN,在恢复过程中,如果一个redo log记录的LSN小于或等于数据页的LSN,说明这个修改已经持久化,跳过该日志,从而避免重复应用日志导致的数据错误。 因此,LSN机制通过全局唯一的序列号将数据页和redo log关联起来,确保在崩溃恢复时能够准确地重做或跳过某些操作,从而保证日志的完整性和数据的一致性。 参考引用内容: - 引用[1]说明LSN是单调递增的,每次写入redo log都会增加,并且会写入数据页。 - 引用[2]提到几个关键的LSN位置:当前redo log buffer的LSN、刷到磁盘的redo logLSN、数据页刷到磁盘的LSN、上一次检查点的LSN。 - 引用[3]详细描述了通过比较数据页LSN和redo log LSN来决定是否需要恢复。 - 引用[5]再次强调了LSN在数据页和redo log中的存在,以及checkpoint的LSN记录。 现在,我们按照要求组织回答: </think>### Redo LogLSN 机制保证日志完整性的原理 LSNLog Sequence Number)是 MySQL InnoDB 引擎中**全局唯一且单调递增的日志序列号**,通过多级协同机制保障事务日志的完整性和崩溃恢复的准确性,其核心原理分为以下四个层面: --- #### **1. LSN 生成与写入机制** - **全局单调递增**: 每次向 Redo Log Buffer 写入长度为 $length$ 的日志记录时,LSN 的值按增量更新: $$LSN_{new} = LSN_{current} + length$$ 确保每个日志条目都有唯一标识,避免日志覆盖或丢失[^1][^4]。 - **双写锚点**: - Redo Log 中记录写入点的 LSN - 数据页头部(`FIL_PAGE_LSN`)记录**最后一次修改该页的 LSN** ``` | 数据页结构 | |----------------------------| | FIL_PAGE_LSN (8字节) | ← 记录修改此页的LSN | 数据内容... | ``` 形成 "日志-数据" 的双重标记[^3][^5]。 --- #### **2. 崩溃恢复时的完整性校验** 在崩溃恢复阶段,通过 **LSN 三级比对**确保数据一致性: 1. **检查点定位**: 从 `last checkpoint at`(持久化的检查点 LSN)开始扫描 Redo Log[^2][^4]。 2. **页面恢复决策**: 对每个数据页,比较: - 数据页的 `FIL_PAGE_LSN`(磁盘中该页的修改记录) - Redo Log 条目的 LSN(日志中该修改的记录) $$Recovery\_Action = \begin{cases} \text{跳过} & \text{if } Page\_LSN \geq Log\_LSN \\ \text{重做} & \text{if } Page\_LSN < Log\_LSN \end{cases}$$ 仅重做尚未刷盘的修改,避免重复应用日志[^3][^5]。 3. **事务状态验证**: 结合 Undo LogLSN 回滚未提交事务,确保原子性。 --- #### **3. 检查点(Checkpoint)的协同控制** 关键 LSN 坐标通过**四元组**实现全局同步[^2][^4]: | **LSN 类型** | **含义** | **作用** | |----------------------|-----------------------------------|------------------------------| | `log sequence number` | 当前 Redo Log Buffer 中的 LSN | 日志写入进度指针 | | `log flushed up to` | 已刷盘到 Redo Log File 的 LSN | 持久化保证点 | | `pages flushed up to` | 已刷到磁盘数据页的最大 LSN | 数据页持久化状态 | | `last checkpoint at` | 上一次检查点位置的 LSN | 崩溃恢复的起始点 | - **检查点推进**: 后台线程定期将内存中已持久化的最大 LSN 更新为 `last checkpoint at`,回收早于此点的 Redo Log 空间[^4]。 --- #### **4. 闭环验证流程** ```mermaid graph TB A[事务提交] --> B[写Redo Log Buffer<br>更新LSN] B --> C[同步LSN到数据页头部] C --> D{崩溃发生?} D -->|否| E[正常刷盘] D -->|是| F[恢复流程启动] F --> G[加载last checkpoint at] G --> H[扫描Redo Log] H --> I[对比Page_LSNLog_LSN] I -->|Page_LSN < Log_LSN| J[重做修改] I -->|Page_LSNLog_LSN| K[跳过此日志] J --> L[更新Page_LSN] K --> L L --> M[完成恢复] ``` > **关键设计**:LSN 在日志、数据页、检查点之间形成**闭环校验链**,确保: > - 已持久化的修改不会被重复重做(通过 Page_LSNLog_LSN 跳过) > - 未持久的修改必定被恢复(通过 Page_LSN < Log_LSN 重做) > - 日志空间可安全回收(检查点推进机制)[^1][^3][^5] --- #### **故障场景验证** | **场景** | **LSN 机制应对措施** | |------------------------|--------------------------------------------------------------------------------------| | **事务提交后崩溃** | Redo LogLSN > Page_LSN → 重做未刷盘数据 | | **日志写入中断** | 下次启动时从 last checkpoint at 继续扫描 → 修复不完整写入 | | **数据页部分刷盘** | Page_LSNLog_LSN 不一致 → 仅修复缺失修改 | | **长事务阻塞检查点** | last checkpoint at 停滞 → 保留所需日志直至事务提交 | 通过 LSN 的全局单调性、数据页锚点、检查点协同和崩溃恢复时的交叉验证,Redo Log 实现了崩溃场景下的**零数据丢失**和**操作幂等性**,从根本上保障了事务持久性[^1][^3][^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值