草庐IT

php - mysql CREATE临时表+事务导致死锁

coder 2023-06-11 原文

我有一个复杂的查询,它创建了一个可能需要 5 秒或更长时间才能运行的临时表。当同时在类似表上运行另一个事务时,这似乎会导致死锁。我无法在本地复制,但在生产中,我可以每隔几天让它发生 1 次。 (我记录了 mysql 错误)

查询非常复杂(显示在页面底部);但你不需要理解逻辑;只是它从一堆表和连接中进行选择,并且可能需要一段时间才能运行。

我还有一个事务可以插入到许多相同的表中。我偶尔会收到 mysql 错误 1213: Deadlock found when trying to get lock;尝试重启事务。

这是交易的伪代码

START TRANSACTION
INSERT INTO phppos_sales
INSERT MANY RECORDS INTO phppos_sales_items
INSERT MANY RECORDS INTO phppos_sales_items_taxes
INSERT MANY RECORDS INTO phppos_sales_payments
END TRANSACTION

我该如何解决这个死锁?我尝试将 isolation level 更改为 READ UNCOMMITTED 但 mysql 设置不允许这样做;而且我需要在我无法控制服务器的各种环境中进行这项工作。

更改隔离级别时出错:

Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.

INNODB 引擎状态:

mysql> SHOW ENGINE INNODB STATUS;
| Type   | Name | Status                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| InnoDB |      | 
=====================================
140520 12:00:17 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 15 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 1766819 1_second, 1766816 sleeps, 167043 10_second, 100947 background, 100945 flush
srv_master_thread log flush and writes: 1776023
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 236559, signal count 288374
Mutex spin waits 546890, rounds 1796579, OS waits 33216
RW-shared spins 205374, rounds 5519210, OS waits 176937
RW-excl spins 5661, rounds 841678, OS waits 23933
Spin rounds per wait: 3.29 mutex, 26.87 RW-shared, 148.68 RW-excl
------------------------
LATEST FOREIGN KEY ERROR
------------------------
140520 11:27:44 Transaction:
TRANSACTION 86D125F, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
15 lock struct(s), heap size 3112, 6 row lock(s), undo log entries 2
MySQL thread id 1910245, OS thread handle 0x7fbf0042e700, query id 56114114 php-pos-web 10.181.16.33 phppoint update
INSERT INTO `phppos_sales_items_taxes` (`sale_id`, `item_id`, `line`, `name`, `percent`, `cumulative`) VALUES (11763, 1115, 3, 'PST', '8.000', '0')
Foreign key constraint fails for table `phppoint_fatpanda`.`phppos_sales_items_taxes`:
,
  CONSTRAINT `phppos_sales_items_taxes_ibfk_1` FOREIGN KEY (`sale_id`) REFERENCES `phppos_sales_items` (`sale_id`)
Trying to add in child table, in index `PRIMARY` tuple:
DATA TUPLE: 8 fields;
 0: len 4; hex 80002df3; asc   - ;;
 1: len 4; hex 8000045b; asc    [;;
 2: len 4; hex 80000003; asc     ;;
 3: len 3; hex 505354; asc PST;;
 4: len 8; hex 8000000000080000; asc         ;;
 5: len 6; hex 0000086d125f; asc    m _;;
 6: len 7; hex 00000000000000; asc        ;;
 7: len 4; hex 80000000; asc     ;;

But in parent table `phppoint_fatpanda`.`phppos_sales_items`, in index `PRIMARY`,
the closest match we can find is record:
PHYSICAL RECORD: n_fields 11; compact format; info bits 0
 0: len 4; hex 80002df1; asc   - ;;
 1: len 4; hex 8000049a; asc     ;;
 2: len 4; hex 80000001; asc     ;;
 3: len 6; hex 0000086cfd29; asc    l );;
 4: len 7; hex f400000216012c; asc       ,;;
 5: len 0; hex ; asc ;;
 6: len 0; hex ; asc ;;
 7: len 11; hex 8000000000010000000000; asc            ;;
 8: len 11; hex 8000000000100000000000; asc            ;;
 9: len 11; hex 80000000002d0000000000; asc      -     ;;
 10: len 4; hex 80000000; asc     ;;

------------------------
LATEST DETECTED DEADLOCK
------------------------
140520 11:27:44
*** (1) TRANSACTION:
TRANSACTION 86D11A3, ACTIVE 2 sec fetching rows
mysql tables in use 9, locked 9
LOCK WAIT 364 lock struct(s), heap size 47544, 80177 row lock(s)
MySQL thread id 1910243, OS thread handle 0x7fbeb2090700, query id 56113840 10.181.26.42 phppoint Copying to tmp table

CREATE TEMPORARY TABLE phppos_sales_items_temp
        (SELECT phppos_sales.deleted as deleted,phppos_sales.deleted_by as deleted_by, sale_time, date(sale_time) as sale_date, phppos_sales_items.sale_id, comment,payment_type, customer_id, employee_id, 
        phppos_items.item_id, NULL as item_kit_id, supplier_id, quantity_purchased, item_cost_price, item_unit_price, category, 
        discount_percent, (item_unit_price*quantity_purchased-item_unit_price*quantity_purchased*discount_percent/100) as subtotal,
        phppos_sales_items.line as line, serialnumber, phppos_sales_items.description as description,
        (item_unit_price*quantity_purchased-item_unit_price*quantity_purchased*discount_percent/100)+(item_unit_price*quantity_purchased-item_unit_price*quantity_purchased*discount_percent/100)*(SUM(CASE WHEN cumulative != 1 THEN percent ELSE 0 END)/100) 
        +(((item_unit_price*quantity_purchased-item_unit_price*quanti
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 454941 page no 114 n bits 408 index `location_id` of table `phppoint_fatpanda`.`phppos_sales` trx id 86D11A3 lock mode S waiting
Record lock, heap no 335 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80002df3; asc   - ;;

*** (2) TRANSACTION:
TRANSACTION 86D125D, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
23 lock struct(s), heap size 3112, 12 row lock(s), undo log entries 10
MySQL thread id 1910245, OS thread handle 0x7fbf0042e700, query id 56114091 php-pos-web 10.181.16.33 phppoint update

INSERT INTO `phppos_sales_items_taxes` (`sale_id`, `item_id`, `line`, `name`, `percent`, `cumulative`) VALUES (11763, 1178, 2, 'GST', '5.000', '0')
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 454941 page no 114 n bits 408 index `location_id` of table `phppoint_fatpanda`.`phppos_sales` trx id 86D125D lock_mode X locks rec but not gap
Record lock, heap no 335 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80002df3; asc   - ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 454945 page no 386 n bits 288 index `PRIMARY` of table `phppoint_fatpanda`.`phppos_sales_items_taxes` trx id 86D125D lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

*** WE ROLL BACK TRANSACTION (2)
------------
TRANSACTIONS
------------
Trx id counter 86E47F7
Purge done for trx's n:o < 86E45C0 undo n:o < 0
History list length 1418
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 86E47F6, not started
MySQL thread id 1913171, OS thread handle 0x7fbeb2090700, query id 56205829 10.181.26.42 phppoint
---TRANSACTION 0, not started
MySQL thread id 1913095, OS thread handle 0x7fbf005b4700, query id 56205830 localhost root
SHOW ENGINE INNODB STATUS
--------
FILE I/O
--------
I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
I/O thread 1 state: waiting for completed aio requests (log thread)
I/O thread 2 state: waiting for completed aio requests (read thread)
I/O thread 3 state: waiting for completed aio requests (read thread)
I/O thread 4 state: waiting for completed aio requests (read thread)
I/O thread 5 state: waiting for completed aio requests (read thread)
I/O thread 6 state: waiting for completed aio requests (write thread)
I/O thread 7 state: waiting for completed aio requests (write thread)
I/O thread 8 state: waiting for completed aio requests (write thread)
I/O thread 9 state: waiting for completed aio requests (write thread)
Pending normal aio reads: 0 [0, 0, 0, 0] , aio writes: 0 [0, 0, 0, 0] ,
 ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 0; buffer pool: 0
3599456 OS file reads, 9300371 OS file writes, 3988632 OS fsyncs
0.27 reads/s, 16384 avg bytes/read, 13.07 writes/s, 7.27 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 84, seg size 86, 55915 merges
merged operations:
 insert 68506, delete mark 4761, delete 38
discarded operations:
 insert 0, delete mark 0, delete 0
Hash table size 2212699, node heap has 751 buffer(s)
5050.86 hash searches/s, 624.09 non-hash searches/s
---
LOG
---
Log sequence number 184365806376
Log flushed up to   184365806376
Last checkpoint at  184365791715
0 pending log writes, 0 pending chkp writes
2149282 log i/o's done, 3.47 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 1098907648; in additional pool allocated 0
Dictionary memory allocated 62951505
Buffer pool size   65536
Free buffers       1
Database pages     64784
Old database pages 23894
Modified db pages  88
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 4073451, not young 0
0.07 youngs/s, 0.00 non-youngs/s
Pages read 3592230, created 1542046, written 6130789
0.27 reads/s, 18.00 creates/s, 6.40 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 64784, unzip_LRU len: 0
I/O sum[382]:cur[0], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
1 read views open inside InnoDB
Main thread process no. 15866, id 140457065543424, state: sleeping
Number of rows inserted 77431960, updated 1673031, deleted 160450, read 4825684197
1103.93 inserts/s, 2.53 updates/s, 0.00 deletes/s, 7772.15 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================
 |
+-------

查询这是死锁的一部分:(连同上面的交易)

CREATE temporary TABLE phppos_sales_items_temp 
  (SELECT 
  phppos_sales.deleted                                              AS deleted, 
          phppos_sales.deleted_by                                   AS deleted_by, 
          sale_time, 
          Date(sale_time)                                           AS sale_date, 
          phppos_sales_items.sale_id, 
          comment, 
          payment_type, 
          customer_id, 
          employee_id, 
          phppos_items.item_id, 
          NULL                                                       AS item_kit_id, 
          supplier_id, 
          quantity_purchased, 
          item_cost_price, 
          item_unit_price, 
          category, 
          discount_percent, 
          ( item_unit_price * quantity_purchased - 
            item_unit_price * quantity_purchased * 
            discount_percent / 100 ) AS subtotal, 
          phppos_sales_items.line                                     AS line, 
          serialnumber, 
          phppos_sales_items.description                              AS description, 
          ( item_unit_price * quantity_purchased - 
            item_unit_price * quantity_purchased * 
            discount_percent / 100 ) + ( 
          item_unit_price * quantity_purchased - 
          item_unit_price * quantity_purchased * 
          discount_percent 
          / 100 ) * ( Sum(CASE 
                            WHEN cumulative != 1 THEN percent 
                            ELSE 0 
                          end) / 100 ) + ( ( ( 
          item_unit_price * quantity_purchased 
          - 
          item_unit_price * quantity_purchased 
          * 
          discount_percent / 100 ) * ( 
                                           Sum(CASE 
                                                 WHEN cumulative != 1 THEN 
                                                 percent 
                                                 ELSE 0 
                                               end) / 100 ) + ( 
                                           item_unit_price * quantity_purchased 
                                           - 
                                                            item_unit_price * 
                                                            quantity_purchased 
                                                            * 
                                                            discount_percent / 
                                                            100 
                                                              ) 
                                     ) 
                                           * ( Sum(CASE 
                                                                            WHEN 
                                                   cumulative = 1 THEN percent 
                                                                            ELSE 
                                                   0 
                                                                            end) 
                                             ) 
                                           / 100 ) 
                                                                       AS total, 
          ( item_unit_price * quantity_purchased - 
            item_unit_price * quantity_purchased * 
            discount_percent / 100 ) * ( 
          Sum(CASE 
                WHEN cumulative != 1 THEN percent 
                ELSE 0 
              end) / 100 ) + ( ( ( item_unit_price * quantity_purchased - 
                                   item_unit_price * quantity_purchased * 
                                   discount_percent / 100 ) * ( Sum( 
                                                        CASE 
                                                          WHEN cumulative != 1 
                                                        THEN 
                                                          percent 
                                                          ELSE 0 
                                                        end) / 100 ) + ( 
                                 item_unit_price * quantity_purchased 
                                 - 
                                 item_unit_price * quantity_purchased 
                                 * 
                                 discount_percent / 100 ) ) * ( Sum( 
                                 CASE 
                                 WHEN cumulative = 1 THEN percent 
                                 ELSE 0 
                                 end) ) / 100 )          AS tax, 
          ( item_unit_price * quantity_purchased - 
            item_unit_price * quantity_purchased * 
            discount_percent / 100 ) - ( 
          item_cost_price * quantity_purchased )                      AS profit 
   FROM   phppos_sales_items 
          INNER JOIN phppos_sales 
                  ON phppos_sales_items.sale_id = phppos_sales.sale_id 
          INNER JOIN phppos_items 
                  ON phppos_sales_items.item_id = phppos_items.item_id 
          LEFT OUTER JOIN phppos_suppliers 
                       ON phppos_items.supplier_id = phppos_suppliers.person_id 
          LEFT OUTER JOIN phppos_sales_items_taxes 
                       ON phppos_sales_items.sale_id = 
                          phppos_sales_items_taxes.sale_id 
                          AND phppos_sales_items.item_id = 
                              phppos_sales_items_taxes.item_id 
                          AND phppos_sales_items.line = 
                              phppos_sales_items_taxes.line 
   WHERE  sale_time BETWEEN "2014-04-01 00:00:00" AND "2014-04-30 23:59:59" 
          AND phppos_sales.location_id = '1' 
          AND phppos_sales.store_account_payment = 0 
   GROUP  BY sale_id, 
             item_id, 
             line) 
  UNION ALL 
  (SELECT phppos_sales.deleted 
          AS 
          deleted 
          , 
          phppos_sales.deleted_by 
          AS deleted_by, 
          sale_time, 
          Date(sale_time) 
          AS 
          sale_date, 
          phppos_sales_item_kits.sale_id, 
          comment, 
          payment_type, 
          customer_id, 
          employee_id, 
          NULL 
          AS 
          item_id, 
          phppos_item_kits.item_kit_id, 
          '' 
          AS 
          supplier_id, 
          quantity_purchased, 
          item_kit_cost_price, 
          item_kit_unit_price, 
          category, 
          discount_percent, 
          ( item_kit_unit_price * quantity_purchased - 
            item_kit_unit_price * quantity_purchased * discount_percent / 100 ) 
          AS 
          subtotal, 
          phppos_sales_item_kits.line 
          AS 
          line, 
          '' 
          AS 
          serialnumber, 
          phppos_sales_item_kits.description 
          AS 
          description, 
          ( item_kit_unit_price * quantity_purchased - 
            item_kit_unit_price * quantity_purchased * discount_percent / 100 ) 
          + 
          ( item_kit_unit_price * quantity_purchased - 
            item_kit_unit_price * quantity_purchased * discount_percent / 100 ) *
       ( Sum(  CASE   WHEN  cumulative != 1 THEN percent    ELSE 0  end) / 100 ) 
+ ( ( (  item_kit_unit_price * quantity_purchased  - 
item_kit_unit_price * quantity_purchased * discount_percent / 100 ) *
( Sum(CASE 
WHEN cumulative != 1 THEN percent 
ELSE 0 
      end) 
  / 
  100 ) + ( item_kit_unit_price * quantity_purchased - 
                      item_kit_unit_price * quantity_purchased * 
                      discount_percent / 100 ) ) * ( 
Sum( 
                               CASE 
                                 WHEN cumulative = 1 THEN percent 
                                 ELSE 0 
                               end) ) / 100 )                         AS total, 
( item_kit_unit_price * quantity_purchased - 
  item_kit_unit_price * quantity_purchased * discount_percent / 100 ) * ( Sum( 
CASE 
WHEN cumulative != 1 THEN percent 
ELSE 0 
end) / 100 ) + ( ( ( item_kit_unit_price * quantity_purchased - 
                                        item_kit_unit_price * quantity_purchased 
                                        * 
                                        discount_percent 
                                        / 100 ) * ( Sum( 
                   CASE 
                     WHEN cumulative != 1 THEN percent 
                     ELSE 0 
                   end) / 100 ) + ( 
                                      item_kit_unit_price * quantity_purchased 
                                      - 
                                                 item_kit_unit_price * 
                                                 quantity_purchased 
                                                 * discount_percent / 100 ) ) * 
                 ( 
                                  Sum(CASE 
                                        WHEN cumulative = 1 THEN percent 
                                        ELSE 0 
                                      end) ) / 100 )                  AS tax, 
( item_kit_unit_price * quantity_purchased - 
  item_kit_unit_price * quantity_purchased * discount_percent / 100 ) - ( 
item_kit_cost_price * quantity_purchased )                            AS profit 
 FROM   phppos_sales_item_kits 
        INNER JOIN phppos_sales 
                ON phppos_sales_item_kits.sale_id = phppos_sales.sale_id 
        INNER JOIN phppos_item_kits 
                ON phppos_sales_item_kits.item_kit_id = 
                   phppos_item_kits.item_kit_id 
        LEFT OUTER JOIN phppos_sales_item_kits_taxes 
                     ON phppos_sales_item_kits.sale_id = 
                        phppos_sales_item_kits_taxes.sale_id 
                        AND phppos_sales_item_kits.item_kit_id = 
                            phppos_sales_item_kits_taxes.item_kit_id 
                        AND phppos_sales_item_kits.line = 
                            phppos_sales_item_kits_taxes.line 
 WHERE  sale_time BETWEEN "2014-04-01 00:00:00" AND "2014-04-30 23:59:59" 
        AND phppos_sales.location_id = '1' 
        AND phppos_sales.store_account_payment = 0 
 GROUP  BY sale_id, 
           item_kit_id, 
           line) 
ORDER  BY sale_id, 
          line; 

最佳答案

根本原因

当您将 SELECT 与写入语句(例如 INSERT INTO...CREATE TABLE AS... 结合使用时,则 MySQL必须在 SELECT 中涉及的表上建立共享锁

您有另一个并发事务 (2) 对表 phppos_sales 持有独占锁,因此事务 (1) 无法获得其 S 锁,并且事务 (1) 等待。

然后事务 (2) 请求对故事 phppos_sales_items_taxes 进行 X 锁定。但是事务 (1) 已经在队列中以获得对该表的 S 锁,事务 (2) 必须在队列中等待它。

因此事务 (2) 正在等待事务 (1),而事务 (1) 正在等待事务 (2)。这是一个典型的僵局。

这只每隔几天发生一次,因为它取决于事务 (2) 在事务 (1) 开始其 SELECT 之前获取其对 phppos_sales 的第一个锁定。然后事务 (2) 尝试在事务 (1) 的 S 锁请求排队后获取它在 phppos_sales_items_taxes 上的第二个锁。

换句话说,这是一个竞争条件,而且很难重现。

补救措施

如果事务 (2) 请求锁定它需要的所有表作为一个原子操作,那么事务 (1) 将无法在锁定请求之间潜入。

您可以通过显式使用 LOCK TABLES 实现此目的:

START TRANSACTION
LOCK TABLES phppos_sales WRITE, phppos_sales_items WRITE, 
    phppos_sales_items_taxes WRITE, ...other table(s)...
INSERT INTO phppos_sales
INSERT MANY RECORDS INTO phppos_sales_items
INSERT MANY RECORDS INTO phppos_sales_items_taxes
INSERT MANY RECORDS INTO phppos_sales_payments
UNLOCK TABLES;
COMMIT;

这确实意味着执行长时间运行的 SELECT 的事务 (1) 必须等待事务 (2) 完成其 INSERT 并解锁其表。

否则,如果 SELECT 先进行,则意味着事务 (2) 必须等待它完成。

解决方法

如果避免使用 CREATE TABLE...SELECTINSERT INTO...SELECT,则可以在没有锁争用的情况下填充临时表。也就是说,将 SELECT 的结果集取回您的应用程序,然后将这些行INSERT 到临时表中。这样 SELECT 就不需要任何 S 锁。

您可以在存储过程中使用游标来做同样的事情。

另一种解决方法

正如@BrendanF 评论的那样,您还可以将事务隔离级别更改为 READ-COMMITTED,而不是默认的 REPEATABLE-READ。您可以全局更改默认事务隔离级别,也可以逐个 session 更改隔离级别。这会稍微改变交易的语义,因此您应该了解这些差异。

但它确实消除了在插入/选择操作期间从表中读取时 SELECT 执行 S 锁的需要。

关于php - mysql CREATE临时表+事务导致死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23768456/

有关php - mysql CREATE临时表+事务导致死锁的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  3. ruby - 分布式事务和队列,ruby,erlang,scala - 2

    我有一个涉及多台机器、消息队列和事务的问题。因此,例如用户点击网页,点击将消息发送到另一台机器,该机器将付款添加到用户的帐户。每秒可能有数千次点击。事务的所有方面都应该是容错的。我以前从未遇到过这样的事情,但一些阅读表明这是一个众所周知的问题。所以我的问题。我假设安全的方法是使用两阶段提交,但协议(protocol)是阻塞的,所以我不会获得所需的性能,我是否正确?我通常写Ruby,但似乎Redis之类的数据库和Rescue、RabbitMQ等消息队列系统对我的帮助不大——即使我实现某种两阶段提交,如果Redis崩溃,数据也会丢失,因为它本质上只是内存。所有这些让我开始关注erlang和

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  6. Ruby 守护进程导致 ActiveRecord 记录器 IOError - 2

    我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame

  7. ruby - 从另一个私有(private)方法中使用 self.xxx() 调用私有(private)方法 xxx,导致错误 "private method ` xxx' called” - 2

    我正在尝试获得良好的Ruby编码风格。为防止意外调用具有相同名称的局部变量,我总是在适当的地方使用self.。但是现在我偶然发现了这个:classMyClass上面的代码导致错误privatemethodsanitize_namecalled但是当删除self.并仅使用sanitize_name时,它会起作用。这是为什么? 最佳答案 发生这种情况是因为无法使用显式接收器调用私有(private)方法,并且说self.sanitize_name是显式指定应该接收sanitize_name的对象(self),而不是依赖于隐式接收器(也是

  8. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  9. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

    我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

  10. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

随机推荐