存储引擎如InnoDB、BDB才支持事务处理。
??每个事务(transaction)的处理必须满足ACID原则:
flush tables
命令前进行的变化都会存盘。语法 | 说明 |
---|---|
start commit | begin |
开始一项新的事务 |
commit [and [no] chain] [[no] release] |
提交事务 |
rollback [and [no] chain] [[no] release] |
回滚事务 |
set autocommit={0|1} |
设置是否自动提交事务 |
chain
表示提交或回滚一个事务后立即启动一个新事务realease
表示提交或回滚一个事务后断开与客户端的连接
??每一个事务都有一个隔离级,它定义了用户之间隔离和交互的程度。显然,在但用户环境中,它起不到独特的作用,但在多用户环境中,若不保证事务隔离,数据基本上会受到其他事务的影响,这将导致不一致性。
??基于ANSI/ISO SQL规范,MySQL定义了4种隔离级别,如下表所示,按照隔离级别逐渐降低排列。
隔离级别 | 名称 | 说明 |
---|---|---|
serializable | 序列化 | 用户之间会按顺序执行事务 |
repeatable read | 可重复读 | 事务不会被看成是序列,即同个事务执行多个select语句结果都是相同的 |
read committed | 提交读 | 若多个事务修改相应的表,那么同个事务执行多个select语句结果会不同 |
read uncommitted | 未提交读 | 当前级别的事务可以读取到为提交的数据 |
set [global | session] transaction isolation level
{serializable | repeatable read | read committed | read uncommitted};
global
表示定义的隔离级别适用于所有的用户session
表示定义的隔离级别只适用于当前允许的会话和连接-- 方法一:
select @@tx_isolation;
-- 方法二:
show variables like ‘tx_isolation‘;
??当多个用户并发地存取数据库的同一个数据时,若不加控制可能会导致存取和存储不正确的数据。
??当两个或多个事务同时更新同一行数据时,最后的更新会覆盖其他事务所作的更新,这种问题就叫丢失更新问题。
??在完成并提交一个事务之前,其他事务不能访问统一文件或资源,这样可以避免这种问题的出现。
??一个事务正在对一条记录做修改,在这个事务完成并提交之前,这条记录的数据处于不一致的状态,若这是另一个事务也读取这条记录的数据,则这种现象就称为“脏读”。
??当一个事务访问数据时,其他事务也访问该数据并对其进行修改,这会导致第一个事务两次读取到的数据不一样,这种情况就是不可重复读问题。
??当一个事务对某行数据进行插入或删除操作时,若其他事务也对这部分数据进行读取操作,则这个事务前后读取的内容可能会不同,这种情况就是幻读问题。
??当用户对数据库并发访问时,为了确保事务完整性和数据库的一致性,需要对其进行锁定,它是实现数据库并发控制的主要手段。锁是一种用来防止多个客户端同时访问数据时产生问题的机制。具体地说,锁可以防止出现上述并发导致的四种问题。
对于MySQL数据库而言,最显著的特点是不同的存储引擎支持的锁机制不同。
锁机制 | 存储引擎 | 特点 |
---|---|---|
表级锁(table-level locking) | MyISAM、MEMORY、BDB、InnoDB | 开销小,加锁快;不会出现死锁;锁定力度大,发生锁冲突概率高,并发度低 |
页面锁(page-level locking) | BDB | 开销中,加锁中;会出现死锁;锁定力度中,并发度中 |
行级锁(row-level locking) | InnoDB | 开销大,加锁慢;会出现死锁;锁定力度小,发生锁冲突概率低,并发度高 |
??通常来说,死锁都是应用设计的问题,可通过调整业务流程、数据库对象设计、事务大小及访问数据库的SQL语句。
select
),会自动给涉及的表加读锁。
update
、delete
、insert
),会自动给涉及的表加写锁。
lock tables
命令显式为表加锁。show status like ‘table_locks%‘;
MySQL的表级锁有两种模式:表共享读锁(table read lock)、表独占写锁(table write lock)。
lock tables
tb_name [[as] new_tb_name] read [local] | [low_priority] write
...
unlock tables
as
子句为表定义一个别名new_tb_name
。read
为读锁定,确保用户可以读表,但不能修改表。加上local
表示允许表锁定后,用户可以进行非冲突的insert操作。write
为写锁定,只有锁定该表的用户可以修改表,其他用户无法访问该表。加上low_priority
表示允许其他用户读表。drop table
。autocommit
必须设置为0,否则在执行lock tables
之后就会立即释放表锁定,很容易形成死锁。??InnoDB行锁是通过给索引上的索引项加锁来实现的,这意味着,只有通过索引条件检索诗句,InnoDB才使用行级锁,否则,InnoDB使用表级锁。与MySQL不同,Oracle是通过数据块中对相应数据行加锁来实现的。
select
),InnoDB不会加任何锁。update
、delete
、insert
),会自动给涉及的数据集加排他锁(即写锁)。show status like ‘innoDB_row_lock%‘;
InnoDB有两种类型的行锁:
另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁为表锁。意向锁是InnoDB自动加的,不需要用户干预。
若一个事务请求的锁模式与当前的锁兼容,InnoDB就将请求的锁授予该事务,否则该事务需要等待相应的锁释放。
-- 添加共享锁(S)
select * from tb_name where子句 ... lock in share mode;
-- 添加排他锁(X)
select * from tb_name where子句 ... for update;
原文:https://www.cnblogs.com/bpf-1024/p/14145668.html