mysql 表读锁、表写锁、行锁以及mybatis中实现行写锁

本文深入解析MYSQL中的表级锁和行级锁机制,包括表共享锁、表排他锁、共享锁和排他锁的使用场景及加锁方法。特别介绍了InnoDB存储引擎下行锁的实现方式和在MyBatis中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MYSQL的表级锁的锁模式

表共享锁(表读锁):持有表A读锁的session可以读表A,但不能更新表A,同时不能对其他表进行任何查询、更新操作。
其他session可以读取表A,但是不能更新表A。

表排他锁(表写锁):拥有表A写锁的session,可以对表A进行查询、更新操作。同时具有排他性,其他session不能对表A进行查询、更新操作。

 

如何加表锁:

锁定表:LOCK TABLES tbl_name {READ | WRITE},[ tbl_name {READ | WRITE},…] 


 
解锁表:UNLOCK TABLES 

 

表解锁前,其他窗口可以查询表b_incr,不能修改表数据。

对表加写锁、解锁:

 

 

 MYSQL:InnoDB的行锁模式及加锁方法

共享锁:允许一个事务度一行,阻止其他事务获取相同数据集的排他锁。

SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE

排他锁:允许获取排他锁的事务更新数据,阻止其他事务获取相同的数据集共享读锁和排他写锁。

SELECT * FROM table_name WHERE ... FOR UPDATE

InnoDB行锁实现方式

    InnoDB行锁是通过索引上的索引项来实现的,这一点MySQL与Oracle不同,后者是通过在数据中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味者:只有通过索引条件检索数据,InnoDB才会使用行级锁,否则,InnoDB将使用表锁!。

 

------------------------------------------------------------------------------------------------

下面是在MyBatis中如何实现行级锁。

1.首先需要在使用行级锁的实现层(ServiceImpl)加上事务,

serviceImple层:使用for update 一定要在方法上加上@Transactional(isolation = Isolation.READ_COMMITTED),当事务处理完后,for update 才会将行级锁解除。

 

执行此方法时进行加锁,当整个方法将事务提交后,才会解锁。

2.Mapper,SQL使用for update 加行锁。

经测试运行无误。

<think>好的,用户现在的问题是关于在代码中对多个的数据。之前他们询问过使用数据库处理并发的问题,现在可能在实际开发中遇到了更复杂的情况,需要跨多个。我需要先回顾之前的对话,确保回答的一致性和扩展性。 首先,用户之前了解了如何使用SELECT FOR UPDATE对单,现在扩展到多,可能需要类似的机制,但需要考虑多之间的顺序和事务管理。需要明确几个关键点: 1. **的获取顺序**:跨多时,必须按照固定的顺序获取,避免死。比如按名的字母顺序或预先定义的顺序来定,这样所有事务都遵循同样的顺序,减少死可能性。 2. **事务的范围**:确保所有操作在同一个事务中,这样会保持到事务提交或回滚。需要提醒用户注意事务的隔离级别,尤其是不同隔离级别对的影响,比如可重复已提交的区别。 3. **的类型**:明确排他和共享的使用场景。在需要修改数据时使用FOR UPDATE,如果只是取可以使用LOCK IN SHARE MODE,但可能根据具体情况调整。 4. **死处理**:虽然按顺序加可以减少死,但仍有发生的可能。需要提供检测和处理死的方法,比如设置超时、重试机制,或者数据库自带的死检测机制。 接下来,用户可能的实际场景可能涉及多个的关联操作,比如订单和库存,或者用户账户和交易记录。需要给出具体的SQL示例和代码结构,帮助用户理解如何实现。 另外,需要注意不同数据库对多的支持情况,比如MySQL的InnoDB引擎是否支持跨FOR UPDATE,可能需要明确说明。同时,ORM框架(如Hibernate)中的处理方式,比如在JPA中如何使用悲观。 还需要提到性能方面的考虑,比如的粒度、持有时间,以及在高并发下可能出现的瓶颈。建议用户尽量减少的范围和时间,避免长时间阻塞其他事务。 最后,可能的相关问题包括分布式、数据库的类型比较,这些可以在最后的相关问题中引导用户进一步探索,但当前需要专注于多的具体实现。</think>在代码中对多个的数据时,需要确保的获取顺序一致、事务范围明确,且遵循数据库的机制,避免死和性能问题。以下是详细的实现思路和示例: --- ### **1. 核心原则** - **固定顺序**:所有事务必须按照**相同的顺序**对多(例如按名字母顺序或业务优先级),避免循环依赖导致的死。 - **最小化持有时间**:应在事务内尽早获取、尽早释放。 - **显式定**:使用数据库提供的语法(如 `SELECT ... FOR UPDATE`)显式声明需要定的。 --- ### **2. 具体实现方法** #### **场景示例** 假设需要同时操作 `orders`(订单)和 `inventory`(库存),确保订单创建时定相关库存。 #### **SQL 实现(以 MySQL 为例)** ```sql BEGIN; -- 按固定顺序:先 inventory,再 orders -- 定库存 SELECT * FROM inventory WHERE product_id = 100 FOR UPDATE; -- 定订单(假设需要更新某历史订单) SELECT * FROM orders WHERE order_id = 200 FOR UPDATE; -- 执业务操作(扣减库存、创建订单) UPDATE inventory SET stock = stock - 1 WHERE product_id = 100; INSERT INTO orders (...) VALUES (...); COMMIT; ``` #### **在代码中的关键点** 1. **事务边界**:确保所有操作在同一个数据库事务中。 2. **ORM 框架支持**:若使用 ORM(如 Hibernate、MyBatis),需显式调用方法: ```java // JPA 示例 @Transactional public void placeOrder(Long productId, Long orderId) { // 按顺序加:先库存,后订单 Inventory inventory = entityManager.find( Inventory.class, productId, LockModeType.PESSIMISTIC_WRITE ); Order order = entityManager.find( Order.class, orderId, LockModeType.PESSIMISTIC_WRITE ); // 业务操作 inventory.setStock(inventory.getStock() - 1); order.setStatus("PAID"); } ``` --- ### **3. 避免死的策略** - **全局顺序**:定义所有的加顺序(如按名排序,主键排序)。 - **超时机制**:设置等待超时(如 MySQL 的 `innodb_lock_wait_timeout`)。 - **重试逻辑**:代码中捕获死异常(如 MySQL 的 `Error 1213`)并重试。 ```java // Java 伪代码示例(重试3次) int retries = 3; while (retries > 0) { try { placeOrder(productId, orderId); break; } catch (DataAccessException e) { if (e.getCause() instanceof MySQLTransactionRollbackException) { retries--; Thread.sleep(100); // 等待后重试 } else { throw e; } } } ``` --- ### **4. 多关联场景的特殊处理** 若操作涉及**跨关联查询**,需确保关联条件涉及的字段均被定: ```sql BEGIN; -- 定关联(例如:通过订单关联用户) SELECT u.* FROM users u JOIN orders o ON u.id = o.user_id WHERE o.id = 200 FOR UPDATE; -- 继续其他操作... COMMIT; ``` --- ### **5. 性能与注意事项** - **粒度**:更高效,但需确保索引命中(否则可能退化为)。 - **隔离级别**:默认使用 `READ COMMITTED` 或 `REPEATABLE READ`,高隔离级别可能导致更多竞争。 - **分布式系统限制**:单数据库的无法跨多个数据库实例,需改用分布式(如 Redis 或 ZooKeeper)。 --- ### **总结** 对多数据的核心是: 1. **固定顺序**避免死 2. **显式定**关键 3. **短事务**减少竞争 4. **重试机制**处理异常 --- **相关问题延伸**: 1. 如何在分布式系统中实现跨服务的? 2. 不同数据库(如 PostgreSQL、Oracle)的机制有何差异? 3. 无编程(如乐观)与悲观的适用场景对比?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值