Bulk Update Lock Mode (BU)
Bulk Update first appeared in SQL
Server 2005. It is designed to allow multiple table-level locks on a
single heap while using the Bulk API. This is important for parallel
loading in data warehousing. However, in order to see it, you need to
be loading into a heap and you must have specified a Tablock on the target table. The Tablock
is a hint to say you’ll take a table lock, but SQL Server sees that the
Bulk API is making the assertion. So a BU lock is issued instead.
Because multiple BU locks are permitted on the same table, you are
therefore empowered to perform parallel loading into the heap, as each
loader will take its own compatible BU lock. Note that dirty reads are
also permitted against the target table.
NOTE
If you do not specify a Tablock hint
when bulk loading data into a heap, then you will see exclusive page
locks instead. If the target table has a clustered index, then use
trace flag 610 and you will also see page locks on the bulk insert. See
the Data Loading Performance Guide (http://msdn.microsoft.com/en-us/library/dd425070.aspx) from the SQLCAT team for further details.
The following SQL code example is using the BULK INSERT statement to load into a replica heap of the dbo.factinternetsales table. Notice that a Tablock hint has also been used. You can see the BU lock that is issued as a result in Figure 5 by querying sys.dm_tran_locks in a separate session as before. You’ll have to be quick though! The sample data files contain only 60,398 rows (code file Ch6BulkUpdateLockMode.sql).
USE AdventureWorksDW2012;
CREATE TABLE [dbo].[TestFactInternetSales](
[ProductKey] [int] NOT NULL,
[OrderDateKey] [int] NOT NULL,
[DueDateKey] [int] NOT NULL,
[ShipDateKey] [int] NOT NULL,
[CustomerKey] [int] NOT NULL,
[PromotionKey] [int] NOT NULL,
[CurrencyKey] [int] NOT NULL,
[SalesTerritoryKey] [int] NOT NULL,
[SalesOrderNumber] [nvarchar](20) NOT NULL,
[SalesOrderLineNumber] [tinyint] NOT NULL,
[RevisionNumber] [tinyint] NOT NULL,
[OrderQuantity] [smallint] NOT NULL,
[UnitPrice] [money] NOT NULL,
[ExtendedAmount] [money] NOT NULL,
[UnitPriceDiscountPct] [float] NOT NULL,
[DiscountAmount] [float] NOT NULL,
[ProductStandardCost] [money] NOT NULL,
[TotalProductCost] [money] NOT NULL,
[SalesAmount] [money] NOT NULL,
[TaxAmt] [money] NOT NULL,
[Freight] [money] NOT NULL,
[CarrierTrackingNumber] [nvarchar](25) NULL,
[CustomerPONumber] [nvarchar](25) NULL) ON [PRIMARY];
BULK INSERT dbo.TestFactInternetSales
FROM 'C:\factinternetsales.txt'
WITH (TABLOCK
,FORMATFILE = 'C:\formatFIS.txt'
);
/* SESSION 2 */
SELECT resource_type
,resource_subtype
,resource_description
,resource_associated_entity_id
,request_mode
,request_status
FROM sys.dm_tran_locks
where request_session_id= <insert your session spid here,int, 0>