面试题答案
一键面试1. 使用 SQLite 事务机制确保操作原子性
在 SQLite 中,要确保操作 A(插入订单记录)和操作 B(更新订单状态)的原子性,可以按以下步骤操作:
- 开始事务:在执行操作 A 之前,使用
BEGIN TRANSACTION;
语句开始一个事务。这会告诉 SQLite 接下来的操作都在同一个事务中。 - 执行操作 A:执行插入订单记录的 SQL 语句,例如
INSERT INTO orders (order_info) VALUES ('具体订单信息');
- 执行操作 B:在操作 A 成功后,执行更新订单状态的 SQL 语句,例如
UPDATE orders SET status = '已更新状态' WHERE order_id = 刚刚插入记录的ID;
- 提交事务:如果操作 A 和操作 B 都成功执行,使用
COMMIT;
语句提交事务。这会将所有操作永久保存到数据库中。 - 异常处理:如果在执行操作 A 或操作 B 时发生错误,使用
ROLLBACK;
语句回滚事务,撤销之前的所有操作,以确保数据库状态保持不变。
示例代码(以 Python 为例):
import sqlite3
conn = sqlite3.connect('test.db')
cursor = conn.cursor()
try:
cursor.execute('BEGIN TRANSACTION;')
cursor.execute("INSERT INTO orders (order_info) VALUES ('具体订单信息');")
last_row_id = cursor.lastrowid
cursor.execute("UPDATE orders SET status = '已更新状态' WHERE order_id =?", (last_row_id,))
cursor.execute('COMMIT;')
except Exception as e:
cursor.execute('ROLLBACK;')
print(f"事务执行失败: {e}")
finally:
conn.close()
2. SQLite 处理并发访问避免数据冲突
SQLite 使用以下机制处理并发访问:
- 锁机制:SQLite 使用锁来控制并发访问。SQLite 有多种类型的锁,如 SHARED(共享锁)、RESERVED(保留锁)和 EXCLUSIVE(排他锁)。
- SHARED 锁:当一个连接读取数据时,会获取 SHARED 锁。多个连接可以同时持有 SHARED 锁,以实现并发读。
- RESERVED 锁:当一个连接准备写入数据时,首先获取 RESERVED 锁。持有 RESERVED 锁的连接可以继续读取数据,但不能写入,直到获取 EXCLUSIVE 锁。
- EXCLUSIVE 锁:当一个连接准备写入数据并获取 RESERVED 锁后,会尝试获取 EXCLUSIVE 锁。只有在没有其他连接持有 SHARED 锁或 RESERVED 锁时,才能获取 EXCLUSIVE 锁。持有 EXCLUSIVE 锁的连接可以进行写入操作,并且会阻止其他连接获取任何类型的锁,从而避免数据冲突。
- 写时复制(Copy - on - Write):SQLite 在写入数据时,会在内存中创建一份数据库文件的副本进行修改,而不是直接在原始文件上操作。只有在事务提交时,才会将修改后的副本写回原始文件。这种机制减少了写入操作对读取操作的影响,提高了并发性能。
3. 高并发场景下 SQLite 的性能瓶颈及优化策略
性能瓶颈:
- 锁竞争:在高并发写入场景下,由于 SQLite 使用排他锁进行写入操作,多个写入操作可能会竞争锁,导致性能下降。
- I/O 开销:SQLite 将数据库存储在文件中,频繁的读写操作会导致大量的 I/O 开销,特别是在高并发场景下,I/O 可能成为瓶颈。
- 事务处理:复杂的事务操作在高并发环境下可能会导致锁的持有时间变长,进一步加剧锁竞争。
优化策略:
- 批量操作:尽量将多个操作合并为一个事务,减少事务的数量,从而减少锁的获取和释放次数。例如,将多个插入或更新操作在一个事务中执行。
- 优化 I/O:
- 使用 WAL 模式:SQLite 支持 WAL(Write - Ahead Logging)模式,与默认的回滚日志模式相比,WAL 模式允许多个连接同时进行读写操作,减少 I/O 争用。可以通过
PRAGMA journal_mode = WAL;
启用 WAL 模式。 - 增加缓存:合理配置 SQLite 的缓存大小,通过
PRAGMA cache_size = n;
(n 为页面数)来增加缓存,减少磁盘 I/O。
- 使用 WAL 模式:SQLite 支持 WAL(Write - Ahead Logging)模式,与默认的回滚日志模式相比,WAL 模式允许多个连接同时进行读写操作,减少 I/O 争用。可以通过
- 减少锁持有时间:尽量缩短事务的执行时间,避免在事务中进行长时间的计算或其他与数据库无关的操作。
- 读写分离:如果应用场景允许,可以采用读写分离的策略。将读操作分散到多个副本上执行,减轻主数据库的负载。
- 索引优化:确保在频繁查询和更新的字段上创建合适的索引,以提高查询性能,减少查询时间,从而间接减少锁的持有时间。