MST

星途 面试题库

面试题:MySQL专家级查询性能剖析:多表关联与锁机制对性能影响

在一个复杂的金融系统中有客户表customers、账户表accounts、交易表transactions 。客户可以有多个账户,账户可进行多次交易。现有需求是在高并发场景下查询某个客户在过去一周内的所有交易记录,同时保证数据一致性。请详细阐述SQL查询设计思路、可能用到的索引策略、如何处理锁机制以避免性能瓶颈,并说明不同隔离级别对该查询性能的影响。
26.9万 热度难度
数据库MySQL

知识考点

AI 面试

面试题答案

一键面试

SQL查询设计思路

  1. 关联表:通过 customers 表的主键(如 customer_id)与 accounts 表的 customer_id 建立关联,再通过 accounts 表的主键(如 account_id)与 transactions 表的 account_id 建立关联。
  2. 时间筛选:在 transactions 表中,通过时间字段(如 transaction_date)筛选出过去一周内的交易记录。假设当前日期可以通过数据库函数获取(如 MySQL 的 CURRENT_DATE),则筛选条件可以是 transaction_date >= CURRENT_DATE - INTERVAL 7 DAY。 示例 SQL(以 MySQL 为例):
SELECT t.*
FROM customers c
JOIN accounts a ON c.customer_id = a.customer_id
JOIN transactions t ON a.account_id = t.account_id
WHERE c.customer_id =? -- 传入具体客户ID
  AND t.transaction_date >= CURRENT_DATE - INTERVAL 7 DAY;

索引策略

  1. customers表:在 customer_id 字段上创建索引,加速 customers 表与 accounts 表的连接。
CREATE INDEX idx_customers_customer_id ON customers(customer_id);
  1. accounts表:在 customer_idaccount_id 字段上分别创建索引。customer_id 索引用于连接 customers 表,account_id 索引用于连接 transactions 表。
CREATE INDEX idx_accounts_customer_id ON accounts(customer_id);
CREATE INDEX idx_accounts_account_id ON accounts(account_id);
  1. transactions表:在 account_idtransaction_date 字段上创建复合索引。该复合索引能同时加速连接 accounts 表和筛选过去一周的交易记录。
CREATE INDEX idx_transactions_account_date ON transactions(account_id, transaction_date);

锁机制处理

  1. 行级锁:在高并发场景下,应尽量使用行级锁而非表级锁。因为行级锁只锁定需要操作的行,对其他行的并发操作影响较小。以 MySQL 为例,默认的 InnoDB 存储引擎在执行 SELECT... FOR UPDATE 语句时会对选中的行加行级锁。
SELECT t.*
FROM customers c
JOIN accounts a ON c.customer_id = a.customer_id
JOIN transactions t ON a.account_id = t.account_id
WHERE c.customer_id =?
  AND t.transaction_date >= CURRENT_DATE - INTERVAL 7 DAY
FOR UPDATE;
  1. 减少锁持有时间:尽快完成事务,释放锁资源。在获取到所需数据后,应立即提交事务,避免长时间持有锁导致其他事务等待。

不同隔离级别对查询性能的影响

  1. 读未提交(Read Uncommitted)
    • 优点:查询性能最高,因为不会对数据加锁,能快速获取数据。
    • 缺点:可能会读到未提交的数据(脏读),无法保证数据一致性,在金融系统中不可接受。
  2. 读已提交(Read Committed)
    • 优点:避免了脏读,能保证读到的数据都是已提交的。在这种隔离级别下,查询只会锁定当前读取的行,其他事务可以继续对未读取的行进行操作。
    • 缺点:可能会出现不可重复读的情况,即同一事务内多次读取同一数据可能会得到不同结果,因为其他事务可能在两次读取之间修改并提交了数据。性能相比读未提交略低,因为需要加锁。
  3. 可重复读(Repeatable Read)
    • 优点:在同一事务内多次读取同一数据时,能保证读取结果一致,避免了不可重复读。MySQL 的 InnoDB 存储引擎在可重复读隔离级别下,通过 MVCC(多版本并发控制)机制实现高并发下的数据一致性,对于查询操作性能影响相对较小。
    • 缺点:可能会出现幻读,即同一事务内多次查询,由于其他事务插入新数据,导致查询结果集发生变化。性能略低于读已提交,因为需要维护更多的版本信息。
  4. 串行化(Serializable)
    • 优点:完全保证数据一致性,通过对所有操作加锁,将并发操作串行化。
    • 缺点:性能最低,因为所有事务都只能串行执行,会导致大量的锁等待,严重影响系统并发性能,在高并发金融系统中很少使用。