首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

Mysql 事务管理

2023-11-13 来源:花图问答

Mysql 和其它的数据库产品有一个很大的不同就是事务由存储引擎所决定,例如 MYISAM,MEMORY,ARCHIVE 都不支持事务,事务就是为了解决一组查询要么全部执行成功,要么全部执行失败。

Mysql 事务默认是采取自动提交的模式,除非显示开始一个事务

MariaDB [(none)]> show variables like ‘autocommit‘;+---------------+-------+| Variable_name | Value |+---------------+-------+| autocommit | ON |+---------------+-------+1 row in set (0.00 sec)

修改自动提交模式:0=OFF,1=ON

注意:修改自动提交对非事务类型的表是无效的,因为它们本身就没有提交和回滚的概念,还有一些命令是会强制自动提交的,比如DLL命令、lock tables等。

SET AUTOCOMMIT=OFF或SET AUTOCOMMIT=0

事务的 ACID 特性:原子性,一致性,隔离性,持久性。

原子性:事务是不可分割的最小工作单元,整个事务要么全部提交要么全部回滚失败。

一致性:数据库总是从一个一致性状态转换到另一个一致性的状态。

隔离性: 一个事务所做的更改在最终提交之前其它事务是不可见的。

持久性:事务一旦提交所做的修改就会永久保存在数据库中,即使系统崩溃,数据也不会丢失。

Mysql 事务管理

标签:l命令   mysql 事务   强制   数据库   table   数据   value   回滚   一个   

小编还为您整理了以下内容,可能对您也有帮助:

Mysql数据库中,事务是指什么?如何使用该功能?

MySQL 事务

什么是事务?

MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!

在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。

事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。

事务用来管理 insert,update,delete 语句

一般来说,事务是必须满足4个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称性)、持久性(Durability)。

原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。

隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。

from 树懒学堂 - 一站式数据知识平台

事务操作对应于数据库怎么管理?

事务操作是对于一系列数据库操作行为进行管理的过程,当多用户同时访问或修改同一数据资源时,如不进行事务控制,可能会造成一个用户的行为结果导致另一个用户使用的数据无效的问题,因此需要根据实际情况对关系数据库的事务进行适当的干预与调整。

2.2.1隔离级别设置绝大多数主流的数据库服务器的默认事务隔离级别是提交读(ReadCommitted),轻巧型开源数据库MySQL则不在此范围之列,MySQL默认的事务隔离级别是可重复读(RepeatableRead)。在实际应用中,数据库的事务隔离级别是可以修改的,也往往需要根据实际场景进行查询、变更等操作。

1.查询事务隔离级别全局事务隔离级别(整个数据库)的查询语法是:SELECT@@global.tx_isolation在命令行输入以上命令便可以查询看到数据库的事务隔离级别为REPEATABLE−READ,前面提到,关系数据库的事务模型有显式事务、隐式事务和自动事务三种类型,当使用显式事务模型进行事务控制时,需手动开启、提交、回滚事务。显式事务能够更灵活地根据实际需要对关系数据库进行底层的操作控制,更有利于实现复杂、细粒度的功能需求。

1.语法命令((1)开启事务MySQL开启一个事务的语法是:方式一:starttransaction方式二:begin(2)提交事务MySQL提交一个事务的语法是:commit)回滚事务MySQL回滚一个事务的语法是:rollback

user数据表

user.sql

user.sql续

(2)第一个MySQL客户端连接到数据库服务器,手动开启事务,进行一个update操作,但未提交或回滚事务,如图2−4所示。

客户端1更新操作

(3)第二个MySQL客户端连接到数据库服务器,检索上面被更新的记录,可以看到数据还是未做update操作前的数据,如图2−5所示。

客户端2查询操作((1)

(4)再回到第一个MySQL客户端,手动提交事务,如图2−6所示。

客户端1提交事务操作

(5)回到第二个MySQL客户端,重新检索上面被更新的记录,可以看到数据已经是update操作后的数据,如图2−7所示。

客户端2查询操作(2)

由于数据库的事务隔离级别是提交读(ReadCommitted),一个事务对数据资源的操作只有提交后才能被其他事务读取到;所以步骤(3)所读取的数据还是旧数据,步骤(5)所读取的数据则是新数据。

事务操作对应于数据库怎么管理?

事务操作是对于一系列数据库操作行为进行管理的过程,当多用户同时访问或修改同一数据资源时,如不进行事务控制,可能会造成一个用户的行为结果导致另一个用户使用的数据无效的问题,因此需要根据实际情况对关系数据库的事务进行适当的干预与调整。

2.2.1隔离级别设置绝大多数主流的数据库服务器的默认事务隔离级别是提交读(ReadCommitted),轻巧型开源数据库MySQL则不在此范围之列,MySQL默认的事务隔离级别是可重复读(RepeatableRead)。在实际应用中,数据库的事务隔离级别是可以修改的,也往往需要根据实际场景进行查询、变更等操作。

1.查询事务隔离级别全局事务隔离级别(整个数据库)的查询语法是:SELECT@@global.tx_isolation在命令行输入以上命令便可以查询看到数据库的事务隔离级别为REPEATABLE−READ,前面提到,关系数据库的事务模型有显式事务、隐式事务和自动事务三种类型,当使用显式事务模型进行事务控制时,需手动开启、提交、回滚事务。显式事务能够更灵活地根据实际需要对关系数据库进行底层的操作控制,更有利于实现复杂、细粒度的功能需求。

1.语法命令((1)开启事务MySQL开启一个事务的语法是:方式一:starttransaction方式二:begin(2)提交事务MySQL提交一个事务的语法是:commit)回滚事务MySQL回滚一个事务的语法是:rollback

user数据表

user.sql

user.sql续

(2)第一个MySQL客户端连接到数据库服务器,手动开启事务,进行一个update操作,但未提交或回滚事务,如图2−4所示。

客户端1更新操作

(3)第二个MySQL客户端连接到数据库服务器,检索上面被更新的记录,可以看到数据还是未做update操作前的数据,如图2−5所示。

客户端2查询操作((1)

(4)再回到第一个MySQL客户端,手动提交事务,如图2−6所示。

客户端1提交事务操作

(5)回到第二个MySQL客户端,重新检索上面被更新的记录,可以看到数据已经是update操作后的数据,如图2−7所示。

客户端2查询操作(2)

由于数据库的事务隔离级别是提交读(ReadCommitted),一个事务对数据资源的操作只有提交后才能被其他事务读取到;所以步骤(3)所读取的数据还是旧数据,步骤(5)所读取的数据则是新数据。

Mysql什么时候用到事务处理

事务处理在各种管理系统中都有着广泛的应用,比如人员管理系统,很多同步数据库操作大都需要用到事务处理。比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务! 删除的SQL语句
delete from userinfo where ~~~
delete from mail where ~~
delete from article where~~
~~
如果没有事务处理,在你删除的过程中,假设出错了,只执行了第一句,那么其后果是难以想象的!
但用事务处理。如果删除出错,你只要rollback就可以取消删除操作(其实是只要你没有commit你就没有确实的执行该删除操作)

一般来说,在商务级的应用中,都必须考虑事务处理的!

事务处理,用的也比较广泛,比如你有任务A,任务B,要求执行A,B均成功后才能进行下一步,就要用到事务处理。如果A或者B有一个没成功,那所有的数据回滚到未执行之前的状态。

MYSQL的事务处理主要有两种:
1、用begin,rollback,commit来实现
begin 开始一个事务
rollback 事务回滚
commit 事务确认
2、直接用set来改变mysql的自动提交模式
set autocommit=0 禁止自动提交
set autocommit=1 开启自动提交

Mysql什么时候用到事务处理

事务处理在各种管理系统中都有着广泛的应用,比如人员管理系统,很多同步数据库操作大都需要用到事务处理。比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务! 删除的SQL语句
delete from userinfo where ~~~
delete from mail where ~~
delete from article where~~
~~
如果没有事务处理,在你删除的过程中,假设出错了,只执行了第一句,那么其后果是难以想象的!
但用事务处理。如果删除出错,你只要rollback就可以取消删除操作(其实是只要你没有commit你就没有确实的执行该删除操作)

一般来说,在商务级的应用中,都必须考虑事务处理的!

事务处理,用的也比较广泛,比如你有任务A,任务B,要求执行A,B均成功后才能进行下一步,就要用到事务处理。如果A或者B有一个没成功,那所有的数据回滚到未执行之前的状态。

MYSQL的事务处理主要有两种:
1、用begin,rollback,commit来实现
begin 开始一个事务
rollback 事务回滚
commit 事务确认
2、直接用set来改变mysql的自动提交模式
set autocommit=0 禁止自动提交
set autocommit=1 开启自动提交

mysql的事务四个特性以及事务的四个隔离级别

由低到高依次为Read uncommitted(未授权读取、读未提交)、Read committed(授权读取、读提交)、Repeatable read(可重复读取)、Serializable(序列化),这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。

mysql的事务四个特性以及事务的四个隔离级别

由低到高依次为Read uncommitted(未授权读取、读未提交)、Read committed(授权读取、读提交)、Repeatable read(可重复读取)、Serializable(序列化),这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。

mysql命令行什么时候需要手动开启事务?

MySQL的事务如果不在任何修改,默认是自动提交的,也就是你只要执行一个SQL,回车之后这个SQL语句如果没有任何问题,只需完成后是自动提交的。
控制这个功能的参数是:autocommit。如果这个参数的值是on或者1,那么就是上面我说的那种现象。如果是off或者0,则表示不会自动提交事务。需要你显示的去提交事务。否则锁执行的SQL不会不会永久生效,只会对你当前命令行的session有效,退出MySQL后,执行的SQL语句将会别回滚。
当你需要两个SQL语句同时成功或者同时失败的时候,你可以手动地开启一个事务。比如下面的场景:
你想向订单表order_info表中插入一条新的订单记录,同时要想支付信息表payment_info中插入一条支付信息记录,这个时候从业务的角度上来看,这两个表中的插入操作,需要保持原子性(也就是事务的四大特性之一),也就是要么都插入成功,要么都插入失败,不能存在订单插入成功,支付插入失败,反之也不可以。
要满足上面的需求,你就需要手动的去开启一个事务,在这个事务中去插入两个表中的数据。然后再提交这个事务。如果这两个表的插入操作,你不手动的开启事务,MySQL自己会把两个SQL语句分开放在两个单独的事务中。执行一个插入,就会自动提交一个事务,然后在执行另外一个插入,再自动提交另外一个事务。
在MySQL看来,这是两个分别向两个表中插入的SQL语句而已,它不会从业务上考虑这两个SQL实际的业务逻辑背景是什么。所以此时他会看成是两个SQL语句,也就是两个事务。
这样的情况下就需要手动的开启事务。

mysql命令行什么时候需要手动开启事务?

MySQL的事务如果不在任何修改,默认是自动提交的,也就是你只要执行一个SQL,回车之后这个SQL语句如果没有任何问题,只需完成后是自动提交的。
控制这个功能的参数是:autocommit。如果这个参数的值是on或者1,那么就是上面我说的那种现象。如果是off或者0,则表示不会自动提交事务。需要你显示的去提交事务。否则锁执行的SQL不会不会永久生效,只会对你当前命令行的session有效,退出MySQL后,执行的SQL语句将会别回滚。
当你需要两个SQL语句同时成功或者同时失败的时候,你可以手动地开启一个事务。比如下面的场景:
你想向订单表order_info表中插入一条新的订单记录,同时要想支付信息表payment_info中插入一条支付信息记录,这个时候从业务的角度上来看,这两个表中的插入操作,需要保持原子性(也就是事务的四大特性之一),也就是要么都插入成功,要么都插入失败,不能存在订单插入成功,支付插入失败,反之也不可以。
要满足上面的需求,你就需要手动的去开启一个事务,在这个事务中去插入两个表中的数据。然后再提交这个事务。如果这两个表的插入操作,你不手动的开启事务,MySQL自己会把两个SQL语句分开放在两个单独的事务中。执行一个插入,就会自动提交一个事务,然后在执行另外一个插入,再自动提交另外一个事务。
在MySQL看来,这是两个分别向两个表中插入的SQL语句而已,它不会从业务上考虑这两个SQL实际的业务逻辑背景是什么。所以此时他会看成是两个SQL语句,也就是两个事务。
这样的情况下就需要手动的开启事务。

如何在mysql 的存储过程中使用事务

6.7 MySQL 事务与锁定命令
6.7.1 BEGIN/COMMIT/ROLLBACK 句法
缺省的,MySQL 运行在 autocommit 模式。这就意味着,当你执行完一个更新时,MySQL 将立刻将更新存储到磁盘上。
如果你使用事务安全表 (例如 InnoDB、BDB),通过下面的命令,你可以设置 MySQL 为非 autocommit 模式:
SET AUTOCOMMIT=0
在此之后,你必须使用 COMMIT 来存储你的更改到磁盘上,或者使用 ROLLBACK ,如果你希望忽略从你的事务开始所做的更改。
如果你希望为一系列语句从 AUTOCOMMIT 模式转换,你可以使用 START TRANSACTION 或 BEGIN 或 BEGIN WORK 语句:
START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summmary=@A WHERE type=1;
COMMIT;
START TRANSACTION 在 MySQL 4.0.11 中被加入;这是被推荐的开始一个特别(ad-hoc)事务的方式,因为这是 ANSI SQL 句法。
注意,如果你使用的是一个非事务安全表,更改会立刻被存储,不受 autocommit 模式状态的约束。
当你更新了一个非事务表后,如果你执行一个 ROLLBACK,你将得到一个错误 (ER_WARNING_NOT_COMPLETE_ROLLBACK) 作为一个警告。所有事务安全表将被恢复,但是非事务安全表将不会改变。
如果你使用 START TRANSACTION 或 SET AUTOCOMMIT=0,你应该使用 MySQL
二进制日志做备份以代替老的更新日志。事务处理被以一个大块形式存储在二进制日志中,在 COMMIT
上面,为了保护回滚的事务,而不是被存储的。查看章节 4.9.4 二进制日志。 如果您使用起动事务处理或集AUTOCOMMIT=0
,您应该使用MySQL 二进制日志为备份代替更旧的更新日志。 事务处理存储在二进制登录一大块,做,保证, 滚的事务处理不存储。 参见部分4
。9.4 二进制日志。
下列命令自动的结束一个事务 (就好像你在执行这个命令之前,做了一个 COMMIT):
命令 命令 命令
ALTER TABLE BEGIN CREATE INDEX
DROP DATABASE DROP TABLE RENAME TABLE
TRUNCATE
你可以使用 SET TRANSACTION ISOLATION LEVEL ... 改变事务的隔离级。查看章节 6.7.3 SET TRANSACTION 句法。
6.7.2 LOCK TABLES/UNLOCK TABLES 句法
LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
[, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...]
...
UNLOCK TABLES
LOCK TABLES 为当前线程锁定表。UNLOCK TABLES 释放当前线程拥有的所有锁定。当线程发出另一个 LOCK TABLES,或当与服务器的连接被关闭时,被当前线程锁定的所有表将被自动地解锁。
为了在 MySQL 4.0.2 使用 LOCK TABLES ,你必须拥有一个全局的 LOCK TABLES 权限和一个在相关表上的
SELECT 权限。在 MySQL 3.23 中,你对该表需要有 SELECT、insert、DELETE 和 UPDATE 权限。
使用 LOCK TABLES 的主要原因是,仿效事务处理或在更新表时得到更快的速度。此后会有更详细的描述。
如果一个线程在一个表上得到一个 READ 锁,该线程 (和所有其它线程) 只能从表中读取。如果一个线程在一个表上得到一个 WRITE 锁,那么只有拥有这个锁的线程可以从表中读取和写表。其它的线程被阻塞。
READ LOCAL 和 READ 之间的不同就在于,当锁被加载时,READ LOCAL 允许非冲突(non-conflicting) INSERT 语句执行。如果当你加载着锁时从 MySQL 外部操作数据库文件,这将仍不能被使用。
当你使用 LOCK TABLES 是地,你必须锁定所有你将使用的表,并且必须使用与你的查询中将使用的别名相同!如果你在一个查询中多次使用一个表(用别名),你必须为每一个别名获得一个锁。
WRITE 锁通过比 READ 锁有更高的权限,以确保更新被尽快地处理。这就意味着,如果一个线程获得一个 READ
锁,而同时另外一个线程请求一个 WRITE 锁,并发的 READ 锁请求将等待直到 WRITE 线程得到了锁并释放了它。你可以使用
LOW_PRIORITY WRITE 锁,当该线程在等待 WRITE 锁时,它将允许其它的线程获得 READ 锁。 你应该只使用
LOW_PRIORITY WRITE 锁,如果你确信这将是最后一次,当没有线程将拥有 READ 锁。
LOCK TABLES 工作如下:
以内部定义的次序排序所有被锁定的表 (从用户立场说,该次序是不明确的)。
如果一个表被以一个读锁和一个写锁锁定,将写锁放在读锁之前。
一次只锁定一个表,只到线程得到所有的锁定。
这个方案是为了确保,表锁定死锁释放。 对于这个模式你仍然有些其它事情需要知道:
如果你对一个表使用一个 LOW_PRIORITY WRITE 锁定,这就意味着,MySQL 将等待这个锁,直到没有线程请求一个 READ
锁。当线程得到了 WRITE 锁,并等待获得锁定表列表中的下一个表的锁定时,其它所有的线程将等待 WRITE
锁被释放。如果这在你的应用程序中会引起一个严重的问题,你应该考虑将你的某些表转换为事务安全表。
你可以使用 KILL 安全地杀死一个正在表锁定的线程。查看章节 4.5.5 KILL 句法。
注意,你不应该 锁定你正在对其使用 INSERT DELAYED 的表。这是因为,在这种情况下,INSERT 是通过单独的线程完成的。
通常,你不需要锁定任何表,因为所有单 UPDATE 语句都是原子的;其它的线程无法干扰当前执行的 SQL 语句。当你无论如何希望锁定表时,这里有一些情况:
如果你在一束表上运行许多操作,锁定你将要使用的表,这会更快一些。当然有不利的方面,其它线程将不能更新一个 READ
锁的表,并且没有其它线程要以读取一个 WRITE 锁的表。 在 LOCK TABLES 下,某些事运行得更快一些的原因是,MySQL
将不会转储清除被锁定表键高速缓冲,直到 UNLOCK TABLES 被调用 (通常键高速缓冲在每个 SQL 语句后都会被转储清除)。这将加速在
MyISAM 表上的插入、更新、删除。
如果你在 MySQL 中正在使用一个不支持事务的存储引擎,如果你希望能确保没有其它的线程会出现在一个 SELECT 和 一个 UPDATE 之间,你必须使用 LOCK TABLES 。下面的示例显示为了安全地执行,这里需要LOCK TABLES :
mysql> LOCK TABLES trans READ, customer WRITE;
mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;
mysql> UPDATE customer SET total_value=sum_from_previous_statement
-> WHERE customer_id=some_id;
mysql> UNLOCK TABLES;
不使用 LOCK TABLES,将可能发生在 SELECT 和 UPDATE 语句执行期间有另外一个线程可能在 trans 表中插入一行新记录。
通过使用递增更新 (UPDATE customer SET value=value+new_value) 或 LAST_INSERT_ID() 函数,你可以在很多情况下避免使用 LOCK TABLES。
你也可以使用用户级锁定函数 GET_LOCK() 和 RELEASE_LOCK() 解决一些情况,这些锁被保存在服务器上的一个哈希表中,并以
pthread_mutex_lock() 和 pthread_mutex_unlock() 实现以获得高速度。查看章节 6.3.6.2
辅助功能函数。
查看章节 5.3.1 MySQL 如何锁定表,以获取关于锁定方案的更多信息。
你可以使用 FLUSH TABLES WITH READ LOCK 命令以读锁锁定所有数据库中的所有表。查看章节 4.5.3 FLUSH 句法。如果你有一个可以及时建立文件快照的文件系统,例如 Veritas,这将是得到备份的非常方便方式。
注意:LOCK TABLES 不是事务安全的,在尝试锁定一个表之前,将自动地提交所有的活动事务。
6.7.3 SET TRANSACTION 句法
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
设置全局的、整个会话或下一个事务的事务隔离级。
缺省行为是设置下一个(未启动的)事务的隔离级。如果你使用 GLOBAL
关键词,语句为所有在那个点上建立的新连接设置默认的全局事务隔离级。为了这样做,你需要有 SUPER 权限。使用 SESSION
关键词为当前连接所有将来执行的事务设置默认的事务隔离级。
你可以使用 --transaction-isolation=... 为 mysqld 设置默认的全局隔离级。查看章节 4.1.1 mysqld 命令行选项

如何在mysql 的存储过程中使用事务

6.7 MySQL 事务与锁定命令
6.7.1 BEGIN/COMMIT/ROLLBACK 句法
缺省的,MySQL 运行在 autocommit 模式。这就意味着,当你执行完一个更新时,MySQL 将立刻将更新存储到磁盘上。
如果你使用事务安全表 (例如 InnoDB、BDB),通过下面的命令,你可以设置 MySQL 为非 autocommit 模式:
SET AUTOCOMMIT=0
在此之后,你必须使用 COMMIT 来存储你的更改到磁盘上,或者使用 ROLLBACK ,如果你希望忽略从你的事务开始所做的更改。
如果你希望为一系列语句从 AUTOCOMMIT 模式转换,你可以使用 START TRANSACTION 或 BEGIN 或 BEGIN WORK 语句:
START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summmary=@A WHERE type=1;
COMMIT;
START TRANSACTION 在 MySQL 4.0.11 中被加入;这是被推荐的开始一个特别(ad-hoc)事务的方式,因为这是 ANSI SQL 句法。
注意,如果你使用的是一个非事务安全表,更改会立刻被存储,不受 autocommit 模式状态的约束。
当你更新了一个非事务表后,如果你执行一个 ROLLBACK,你将得到一个错误 (ER_WARNING_NOT_COMPLETE_ROLLBACK) 作为一个警告。所有事务安全表将被恢复,但是非事务安全表将不会改变。
如果你使用 START TRANSACTION 或 SET AUTOCOMMIT=0,你应该使用 MySQL
二进制日志做备份以代替老的更新日志。事务处理被以一个大块形式存储在二进制日志中,在 COMMIT
上面,为了保护回滚的事务,而不是被存储的。查看章节 4.9.4 二进制日志。 如果您使用起动事务处理或集AUTOCOMMIT=0
,您应该使用MySQL 二进制日志为备份代替更旧的更新日志。 事务处理存储在二进制登录一大块,做,保证, 滚的事务处理不存储。 参见部分4
。9.4 二进制日志。
下列命令自动的结束一个事务 (就好像你在执行这个命令之前,做了一个 COMMIT):
命令 命令 命令
ALTER TABLE BEGIN CREATE INDEX
DROP DATABASE DROP TABLE RENAME TABLE
TRUNCATE
你可以使用 SET TRANSACTION ISOLATION LEVEL ... 改变事务的隔离级。查看章节 6.7.3 SET TRANSACTION 句法。
6.7.2 LOCK TABLES/UNLOCK TABLES 句法
LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
[, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...]
...
UNLOCK TABLES
LOCK TABLES 为当前线程锁定表。UNLOCK TABLES 释放当前线程拥有的所有锁定。当线程发出另一个 LOCK TABLES,或当与服务器的连接被关闭时,被当前线程锁定的所有表将被自动地解锁。
为了在 MySQL 4.0.2 使用 LOCK TABLES ,你必须拥有一个全局的 LOCK TABLES 权限和一个在相关表上的
SELECT 权限。在 MySQL 3.23 中,你对该表需要有 SELECT、insert、DELETE 和 UPDATE 权限。
使用 LOCK TABLES 的主要原因是,仿效事务处理或在更新表时得到更快的速度。此后会有更详细的描述。
如果一个线程在一个表上得到一个 READ 锁,该线程 (和所有其它线程) 只能从表中读取。如果一个线程在一个表上得到一个 WRITE 锁,那么只有拥有这个锁的线程可以从表中读取和写表。其它的线程被阻塞。
READ LOCAL 和 READ 之间的不同就在于,当锁被加载时,READ LOCAL 允许非冲突(non-conflicting) INSERT 语句执行。如果当你加载着锁时从 MySQL 外部操作数据库文件,这将仍不能被使用。
当你使用 LOCK TABLES 是地,你必须锁定所有你将使用的表,并且必须使用与你的查询中将使用的别名相同!如果你在一个查询中多次使用一个表(用别名),你必须为每一个别名获得一个锁。
WRITE 锁通过比 READ 锁有更高的权限,以确保更新被尽快地处理。这就意味着,如果一个线程获得一个 READ
锁,而同时另外一个线程请求一个 WRITE 锁,并发的 READ 锁请求将等待直到 WRITE 线程得到了锁并释放了它。你可以使用
LOW_PRIORITY WRITE 锁,当该线程在等待 WRITE 锁时,它将允许其它的线程获得 READ 锁。 你应该只使用
LOW_PRIORITY WRITE 锁,如果你确信这将是最后一次,当没有线程将拥有 READ 锁。
LOCK TABLES 工作如下:
以内部定义的次序排序所有被锁定的表 (从用户立场说,该次序是不明确的)。
如果一个表被以一个读锁和一个写锁锁定,将写锁放在读锁之前。
一次只锁定一个表,只到线程得到所有的锁定。
这个方案是为了确保,表锁定死锁释放。 对于这个模式你仍然有些其它事情需要知道:
如果你对一个表使用一个 LOW_PRIORITY WRITE 锁定,这就意味着,MySQL 将等待这个锁,直到没有线程请求一个 READ
锁。当线程得到了 WRITE 锁,并等待获得锁定表列表中的下一个表的锁定时,其它所有的线程将等待 WRITE
锁被释放。如果这在你的应用程序中会引起一个严重的问题,你应该考虑将你的某些表转换为事务安全表。
你可以使用 KILL 安全地杀死一个正在表锁定的线程。查看章节 4.5.5 KILL 句法。
注意,你不应该 锁定你正在对其使用 INSERT DELAYED 的表。这是因为,在这种情况下,INSERT 是通过单独的线程完成的。
通常,你不需要锁定任何表,因为所有单 UPDATE 语句都是原子的;其它的线程无法干扰当前执行的 SQL 语句。当你无论如何希望锁定表时,这里有一些情况:
如果你在一束表上运行许多操作,锁定你将要使用的表,这会更快一些。当然有不利的方面,其它线程将不能更新一个 READ
锁的表,并且没有其它线程要以读取一个 WRITE 锁的表。 在 LOCK TABLES 下,某些事运行得更快一些的原因是,MySQL
将不会转储清除被锁定表键高速缓冲,直到 UNLOCK TABLES 被调用 (通常键高速缓冲在每个 SQL 语句后都会被转储清除)。这将加速在
MyISAM 表上的插入、更新、删除。
如果你在 MySQL 中正在使用一个不支持事务的存储引擎,如果你希望能确保没有其它的线程会出现在一个 SELECT 和 一个 UPDATE 之间,你必须使用 LOCK TABLES 。下面的示例显示为了安全地执行,这里需要LOCK TABLES :
mysql> LOCK TABLES trans READ, customer WRITE;
mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;
mysql> UPDATE customer SET total_value=sum_from_previous_statement
-> WHERE customer_id=some_id;
mysql> UNLOCK TABLES;
不使用 LOCK TABLES,将可能发生在 SELECT 和 UPDATE 语句执行期间有另外一个线程可能在 trans 表中插入一行新记录。
通过使用递增更新 (UPDATE customer SET value=value+new_value) 或 LAST_INSERT_ID() 函数,你可以在很多情况下避免使用 LOCK TABLES。
你也可以使用用户级锁定函数 GET_LOCK() 和 RELEASE_LOCK() 解决一些情况,这些锁被保存在服务器上的一个哈希表中,并以
pthread_mutex_lock() 和 pthread_mutex_unlock() 实现以获得高速度。查看章节 6.3.6.2
辅助功能函数。
查看章节 5.3.1 MySQL 如何锁定表,以获取关于锁定方案的更多信息。
你可以使用 FLUSH TABLES WITH READ LOCK 命令以读锁锁定所有数据库中的所有表。查看章节 4.5.3 FLUSH 句法。如果你有一个可以及时建立文件快照的文件系统,例如 Veritas,这将是得到备份的非常方便方式。
注意:LOCK TABLES 不是事务安全的,在尝试锁定一个表之前,将自动地提交所有的活动事务。
6.7.3 SET TRANSACTION 句法
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
设置全局的、整个会话或下一个事务的事务隔离级。
缺省行为是设置下一个(未启动的)事务的隔离级。如果你使用 GLOBAL
关键词,语句为所有在那个点上建立的新连接设置默认的全局事务隔离级。为了这样做,你需要有 SUPER 权限。使用 SESSION
关键词为当前连接所有将来执行的事务设置默认的事务隔离级。
你可以使用 --transaction-isolation=... 为 mysqld 设置默认的全局隔离级。查看章节 4.1.1 mysqld 命令行选项

如何用java开启mysql事务,要求详细

如何用java开启mysql事务,要求详细

看你是什么事务,jdbc事务,还是分布式事务,还是容器事务

1,编程式事务管理(jdbc的事务是绑定在connection上的)

Connection conn = null;

try

{

Class.forName("com.mysql.jdbc.Driver");

conn = DriverManager.getConnection("jdbc:oracle:thin:@host:1521:SID","username","password");

conn.setAutoCommit(false); //取消自动提交

PreparedStatement ps = conn.prepareCall("update something");

ResultSet rs = ps.executeQuery();

conn.commit(); //手动提交

}

catch (Exception e)

{

conn.rollback();

e.printStackTrace();

}

finally

{

conn.close();

}

2,声明式事务

先在工程的application.xml配置文件中添加如下代码,开启事务

<!-- 声明式事务控制配置 -->

<tx:annotation-driven transaction-manager="txManager"/>

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="datasource" ref="bassDataSource"></property>

</bean>

然后在你需要开启事务的接口前面添加注解

@Transactional(rollbackFor = IOException.class)

public void add(String name) throws IOException

{

System.out.println("可以再类里和方法里面添加事务注解0~0");

throw new IOException();

}

直接调用接口方法就好

分布式事务处理(mysql貌似在5.X之后才支持) 的话,

1.可以直接使用spring+atomikos框架进行管理

参考:http://blog.chinaunix.net/uid-21162795-id-3424973.html

就不贴测试代码了,自己看着配置吧

2,使用JTA(Java Transaction API)进行分布式事务管理(测试代码如下)

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.SQLException;

import javax.naming.InitialContext;

import javax.sql.DataSource;

import javax.transaction.SystemException;

import javax.transaction.UserTransaction;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

//分布式事务处理

public class transferAccount

{

@SuppressWarnings("null")

public void testTransferAccount()

{

UserTransaction userts = null;

Connection connA = null;

PreparedStatement psA = null;

InitialContext context = null;

Connection connB = null;

PreparedStatement psB = null;

try

{

//获得事务管理对象

userts = (UserTransaction) context.lookup("java:comp/UserTransaction");

//获取两个数据库

connA = getDataSourceA().getConnection();

connB = getDataSourceB().getConnection();

//开启事务

userts.begin();

//sql语句

psA = connA.prepareStatement("我加1");

psB = connB.prepareStatement("我减1");

//执行sql

psA.executeUpdate();

psB.executeUpdate();

//事务提交

userts.commit();

} catch (Exception e)

{

try

{

userts.rollback();

} catch (IllegalStateException | SecurityException

| SystemException e1)

{

e1.printStackTrace();

}

e.printStackTrace();

}

finally

{

try

{

psA.close();

psB.close();

connA.close();

connB.close();

} catch (SQLException e)

{

e.printStackTrace();

}

}

}

public DataSource getDataSourceA()

{

MysqlDataSource dataSource = new MysqlDataSource();

dataSource.setDatabaseName("mysql");

dataSource.setServerName("server");

dataSource.setPortNumber(1433);

dataSource.setUser("test");

dataSource.setPassword("test");

return dataSource;

}

public DataSource getDataSourceB()

{

MysqlDataSource dataSource = new MysqlDataSource();

dataSource.setDatabaseName("mysql");

dataSource.setServerName("server");

dataSource.setPortNumber(1435);

dataSource.setUser("test1");

dataSource.setPassword("test1");

return dataSource;

}

}

mysql如何用事务和锁 锁住某一行数据,使得不允许两个用户同时读取一行数据!!

1、在mysql数据库中如何锁定一行数据,保证不被其他的操作影响。

2、从对数据的操作类型分为读锁和写锁。从对数据操作的粒度来分:表锁和行锁。

3、现在我们建立一个表来演示数据库的行锁讲解。

4、行锁基本演示如下图所示。

5、如果两个会话操作的是不同的行,就不会互相阻塞了。

显示全文