mysql怎么写事务 mysql怎么实现的事务( 四 )


如果一个线程在一个表上得到一个 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=https://www.04ip.com/post/sum_from_previous_statement
-WHERE customer_id=some_id;
mysql UNLOCK TABLES;
不使用 LOCK TABLES,将可能发生在 SELECT 和 UPDATE 语句执行期间有另外一个线程可能在 trans 表中插入一行新记录 。
通过使用递增更新 (UPDATE customer SET value=https://www.04ip.com/post/value+new_value) 或 LAST_INSERT_ID() 函数,你可以在很多情况下避免使用 LOCK TABLES 。

推荐阅读