170 lines
11 KiB
Markdown
170 lines
11 KiB
Markdown
### 在 Entity Framework (EF) 中,开启事务的方式主要有以下几种:
|
||
1. 使用 SaveChanges 时自动管理事务
|
||
2. 显式使用 DbContext.Database.BeginTransaction
|
||
3. 使用 TransactionScope 来管理事务 TransactionScope 是 .NET 提供的一种跨多个数据库操作的事务管理方法。它适用于不同数据库之间的事务,但需要注意,它会使用 System.Transactions 命名空间,因此需要引用相应的程序集。
|
||
### 事务隔离级别 (Transaction Isolation Levels)
|
||
事务的隔离级别决定了事务范围内操作的可见性以及对并发操作的控制。常见的隔离级别包括:
|
||
• Read Uncommitted:允许读取未提交的数据。不会对读取的数据加锁,可能导致“脏读”。
|
||
• Read Committed:只允许读取已提交的数据。会对读取的数据加共享锁,防止脏读,但可能会导致不可重复读。
|
||
• Repeatable Read:保证读取的数据在事务期间不变。会对读取的数据加共享锁,防止脏读和不可重复读,但可能会导致幻读。
|
||
• Serializable:保证事务之间完全隔离,避免任何并发问题。会对读取的数据加范围锁,防止脏读、不可重复读和幻读,是最严格的隔离级别。
|
||
### Sql server的锁级别
|
||
1. 行级锁 (Row Locks)
|
||
行级锁是锁定单一行数据的最细粒度的锁。它能够允许对同一表中的不同行进行并发操作,从而提高并发性。行级锁是 SQL Server 在默认情况下对修改数据(如 UPDATE、DELETE 或 INSERT)时所使用的锁类型。
|
||
• 适用场景:当多个事务需要访问同一表的不同数据行时,行级锁可以有效减少锁的竞争。
|
||
• 示例:UPDATE 语句会锁定更新的行,而不会影响到其他行。
|
||
2. 页级锁 (Page Locks)
|
||
页级锁是锁定数据库中单个数据页(通常是 8KB 的数据页)。当数据页上的多个行被访问时,SQL Server 会使用页级锁。虽然页级锁的锁粒度大于行级锁,但它比表级锁的粒度要小,因此能够在一定程度上提高并发性。
|
||
• 适用场景:当多行数据位于同一个数据页上时,SQL Server 可能会使用页级锁。
|
||
• 示例:当查询或更新的数据行分布在同一页中时,SQL Server 会对整个数据页加锁。
|
||
3. 表级锁 (Table Locks)
|
||
表级锁是锁定整个数据表的锁。它是最粗粒度的锁,通常在以下情况使用:当 SQL Server 执行 SELECT、UPDATE、DELETE 或 INSERT 操作时,如果表中的数据量较大或涉及整个表的数据操作,SQL Server 会考虑使用表级锁。虽然表级锁减少了并发性,但它对事务的完整性保护更强。
|
||
• 适用场景:对整个表进行操作时,如在没有指定索引的情况下进行全表扫描。
|
||
• 示例:DELETE 语句在没有索引优化的情况下可能会锁定整个表。
|
||
3. 键范围锁 (Key-Range Locks)
|
||
### SQL Server 中的索引是什么?它的类型有哪些?
|
||
答案: 索引是数据库管理系统中提高查询效率的一种数据结构。它允许数据库引擎快速找到某些列的数据,而不需要扫描整个表。SQL Server 支持多种类型的索引:
|
||
• 聚集索引(Clustered Index):数据表的行数据按照索引键的顺序存储在磁盘中,表只能有一个聚集索引。默认情况下,主键约束会创建聚集索引。
|
||
• 非聚集索引(Non-Clustered Index):索引和数据存储在不同的地方。一个表可以有多个非聚集索引。
|
||
• 唯一索引(Unique Index):确保索引列中的值是唯一的。
|
||
• 全文索引(Full-Text Index):用于优化文本数据的查询,允许对大量文本数据进行复杂的查询(例如,LIKE 查询)。
|
||
• 空间索引(Spatial Index):用于处理空间数据(如地理信息数据)。
|
||
|
||
## SQL Server 中的死锁(Deadlock)是什么?如何解决死锁问题?
|
||
死锁是指两个或多个事务在执行过程中互相等待对方释放资源,导致它们永远无法完成操作。SQL Server 会自动检测死锁,并选择其中一个事务回滚以解锁资源。
|
||
解决死锁的策略包括:
|
||
1. 最小化事务的锁定范围:尽量减少事务锁定的资源和时间。
|
||
2. 避免循环依赖:确保事务的操作顺序是一致的,避免事务之间的资源依赖循环。
|
||
3. 使用适当的隔离级别:选择合适的隔离级别来平衡并发和一致性。
|
||
4. 优化查询:通过索引优化查询,减少锁的争用。
|
||
5. 使用 SET DEADLOCK_PRIORITY:设置事务的死锁优先级,确保某些事务优先被回滚。
|
||
|
||
### 如何在 SQL Server 中优化查询性能?
|
||
1. 使用合适的索引:为常用的查询列创建适当的索引,避免全表扫描。
|
||
2. **避免使用 SELECT * **:只选择需要的列,减少 I/O 和数据传输。
|
||
3. 避免在 WHERE 子句中使用函数:尽量避免在 WHERE 子句中对列进行计算或使用函数,这样会导致索引无法使用。
|
||
4. 使用连接而不是子查询:在可能的情况下,使用 JOIN 替代子查询,以减少查询的复杂性和执行时间。
|
||
5. 分区表:使用分区表将数据分割成更小的部分,从而提高查询效率。
|
||
6. 查询计划分析:使用 SET STATISTICS IO ON 和 SET STATISTICS TIME ON 分析查询的执行计划,找到性能瓶颈。
|
||
7. 缓存优化:使用 WITH (NOLOCK) 提高查询速度,但要小心脏读问题。
|
||
### SQL Server 中的 JOIN 类型及其作用是什么?
|
||
答案: JOIN 用于将两个或多个表中的数据根据一定的条件进行合并。常见的 JOIN 类型包括:
|
||
1. INNER JOIN:返回两个表中符合条件的行。当两个表中有匹配的数据时才返回结果。
|
||
2. LEFT JOIN(LEFT OUTER JOIN):返回左表的所有行,即使右表没有匹配的数据。右表没有匹配数据的行会以 NULL 填充。
|
||
3. RIGHT JOIN(RIGHT OUTER JOIN):返回右表的所有行,即使左表没有匹配的数据。左表没有匹配数据的行会以 NULL 填充。
|
||
4. FULL JOIN(FULL OUTER JOIN):返回左右表的所有行,若某一表没有匹配的数据,则使用 NULL 填充。
|
||
5. CROSS JOIN:返回两个表的笛卡尔积,即每个左表的行都会与右表的每一行配对。
|
||
### SQL Server 中的存储过程(Stored Procedure)和触发器(Trigger)的区别是什么?
|
||
1. 存储过程:是一组预编译的 SQL 语句,可以通过调用存储过程来执行。存储过程可以接受参数,并且可以返回值。通常用于封装一系列的操作,便于复用。
|
||
2. 触发器:是一种特殊的存储过程,它在某些数据库事件(如 INSERT、UPDATE、DELETE)发生时自动执行。触发器不能被直接调用,只能由数据操作触发。
|
||
区别:
|
||
存储过程是显式调用的,而触发器是隐式触发的。
|
||
存储过程一般用于业务逻辑处理,而触发器用于自动执行某些操作,如数据验证、审计等。
|
||
### 什么是视图(View)?SQL Server 中视图的作用是什么?
|
||
视图是一个虚拟表,它并不存储数据,而是存储查询的 SQL 语句。视图可以简化复杂的查询,提供不同的数据显示层次,或者作为数据的抽象层来实现安全控制。
|
||
### 什么是 SQL Server 中的事务(Transaction)?
|
||
答案: 事务是一个逻辑工作单元,由一组 SQL 语句组成,这些语句要么全部成功,要么全部失败。事务保证了数据库操作的原子性、隔离性、一致性和持久性(ACID 属性)。
|
||
1. 原子性:事务中的所有操作要么全部成功,要么全部失败。
|
||
2. 一致性:事务使数据库从一个一致的状态转换到另一个一致的状态。
|
||
3. 隔离性:事务执行时,其内部的操作对外部事务是不可见的。
|
||
4. 持久性:一旦事务提交,结果是永久性的。
|
||
### SQL Server 中的 NULL 和空字符串 ('') 有什么区别?
|
||
1. NULL:表示未知或不存在的值。NULL 不等于任何值,包括空字符串、零等。
|
||
2. 空字符串 (''):表示一个长度为 0 的字符串,是一个有效的值,但它并不等于 NULL。
|
||
在查询中,NULL 需要使用 IS NULL 或 IS NOT NULL 来判断,而空字符串则可以直接与其他字符串进行比较。
|
||
|
||
### sql server 开启事务
|
||
```sql
|
||
BEGIN TRANSACTION; -- 开始事务
|
||
|
||
-- 你的 SQL 操作
|
||
INSERT INTO Employees (Name, Age) VALUES ('John Doe', 30);
|
||
UPDATE Employees SET Age = 31 WHERE Name = 'John Doe';
|
||
|
||
-- 如果操作成功,提交事务
|
||
COMMIT;
|
||
|
||
-- 如果发生错误,回滚事务
|
||
-- ROLLBACK;
|
||
```
|
||
#### 扩展
|
||
在 SQL Server 中,锁用于确保数据库中的并发访问是安全的,避免数据不一致或损坏。SQL Server 提供了多种锁类型,包括 行级锁、表级锁 和 页级锁。这些锁决定了事务访问数据时可以选择锁定的数据级别。下面将详细讲解如何使用这些不同的锁。
|
||
你可以通过 WITH (ROWLOCK) 提示强制 SQL Server 在执行查询时使用行级锁。这样可以确保对特定数据行的访问不会被其他事务锁定的页或表干扰。
|
||
```sql
|
||
BEGIN TRANSACTION;
|
||
|
||
-- 强制使用行级锁
|
||
SELECT *
|
||
FROM Employees
|
||
WITH (ROWLOCK)
|
||
WHERE EmployeeID = 1;
|
||
|
||
-- 提交事务
|
||
COMMIT;
|
||
|
||
```
|
||
表级锁锁定整个表,因此表中的所有行在事务执行期间都将被锁定,其他事务无法对该表进行修改或查询(如果使用了 TABLOCKX 锁的话)。表级锁通常用于批量操作,或当锁定整个表的数据时使用。
|
||
|
||
使用表级锁的场景:
|
||
批量操作:在大规模更新、删除或插入操作中,SQL Server 通常会使用表级锁。
|
||
显式指定:可以通过 WITH (TABLOCK) 提示来强制使用表级锁。
|
||
```sql
|
||
BEGIN TRANSACTION;
|
||
|
||
-- 强制使用表级锁
|
||
UPDATE Employees
|
||
WITH (TABLOCK)
|
||
SET Age = 30
|
||
WHERE Department = 'Sales';
|
||
|
||
COMMIT;
|
||
|
||
```
|
||
强制使用表级锁:
|
||
你可以使用 WITH (TABLOCK) 提示来显式要求 SQL Server 在操作时使用表级锁。
|
||
```sql
|
||
BEGIN TRANSACTION;
|
||
|
||
-- 强制使用表级锁
|
||
DELETE FROM Employees
|
||
WITH (TABLOCK)
|
||
WHERE Age < 25;
|
||
|
||
COMMIT;
|
||
|
||
```
|
||
页级锁是介于行级锁和表级锁之间的一种锁类型。页级锁通常会锁定数据库页(通常每页包含 8KB 的数据),如果一个查询或操作锁定了某个页中的一行,那么该页上的所有其他行也将被锁定。页级锁通常在以下情况中使用:
|
||
|
||
当多个行在同一个页上并且一个事务对其中一个行进行了修改时,SQL Server 可能会使用页级锁。
|
||
显式控制:你不能直接强制使用页级锁,但可以通过使用 WITH (PAGLOCK) 提示来请求它。
|
||
```sql
|
||
BEGIN TRANSACTION;
|
||
|
||
-- 强制使用页级锁
|
||
UPDATE Employees
|
||
WITH (PAGLOCK)
|
||
SET Age = 30
|
||
WHERE EmployeeID = 10;
|
||
|
||
COMMIT;
|
||
|
||
```
|
||
|
||
|
||
APP渠道号:
|
||
phone system,缩写为 ps_001
|
||
|
||
车机渠道号:
|
||
car system,缩写为 cs_001
|
||
|
||
TV渠道号:
|
||
tv system,缩写为 ts_001
|
||
|
||
|
||
android
|
||
ios
|
||
tv
|
||
car
|
||
|
||
会员
|
||
2 |