Magento 1.9.1 gửi nhiều email


7

Tôi đã thiết lập cửa hàng của mình và sẵn sàng làm việc với nó. Khi tôi sắp đặt hàng thử nghiệm, tôi nhận thấy Magento đang gửi email xác nhận nhiều lần, không dừng gửi. Tôi đang nhận được hai email.

Và tôi đã nhận thấy rằng một ngoại lệ đang được ném vào exception.log:

Next exception 'Zend_Db_Statement_Exception' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE (message_id='3')' at line 1, query was: UPDATE `core_email_queue` SET  WHERE (message_id='3')' in /home/newolders/public_html/store/lib/Zend/Db/Statement/Pdo.php:235
Stack trace:
#0 /home/newolders/public_html/store/lib/Varien/Db/Statement/Pdo/Mysql.php(110): Zend_Db_Statement_Pdo->_execute(Array)
#1 /home/newolders/public_html/store/app/code/core/Zend/Db/Statement.php(291): Varien_Db_Statement_Pdo_Mysql->_execute(Array)
#2 /home/newolders/public_html/store/lib/Zend/Db/Adapter/Abstract.php(480): Zend_Db_Statement->execute(Array)
#3 /home/newolders/public_html/store/lib/Zend/Db/Adapter/Pdo/Abstract.php(238): Zend_Db_Adapter_Abstract->query('UPDATE `core_em...', Array)
#4 /home/newolders/public_html/store/lib/Varien/Db/Adapter/Pdo/Mysql.php(428): Zend_Db_Adapter_Pdo_Abstract->query('UPDATE `core_em...', Array)
#5 /home/newolders/public_html/store/lib/Zend/Db/Adapter/Abstract.php(635): Varien_Db_Adapter_Pdo_Mysql->query('UPDATE `core_em...', Array)
#6 /home/newolders/public_html/store/app/code/core/Mage/Core/Model/Resource/Db/Abstract.php(433): Zend_Db_Adapter_Abstract->update('core_email_queu...', Array, 'message_id='3'')
#7 /home/newolders/public_html/store/app/code/core/Mage/Core/Model/Abstract.php(318): Mage_Core_Model_Resource_Db_Abstract->save(Object(Mage_Core_Model_Email_Queue))
#8 /home/newolders/public_html/store/app/code/core/Mage/Core/Model/Email/Queue.php(244): Mage_Core_Model_Abstract->save()
#9 [internal function]: Mage_Core_Model_Email_Queue->send(Object(Mage_Cron_Model_Schedule))
#10 /home/newolders/public_html/store/app/code/core/Mage/Cron/Model/Observer.php(325): call_user_func_array(Array, Array)
#11 /home/newolders/public_html/store/app/code/core/Mage/Cron/Model/Observer.php(72): Mage_Cron_Model_Observer->_processJob(Object(Mage_Cron_Model_Schedule), Object(Mage_Core_Model_Config_Element))
#12 /home/newolders/public_html/store/app/code/core/Mage/Core/Model/App.php(1338): Mage_Cron_Model_Observer->dispatch(Object(Varien_Event_Observer))
#13 /home/newolders/public_html/store/app/code/core/Mage/Core/Model/App.php(1317): Mage_Core_Model_App->_callObserverMethod(Object(Mage_Cron_Model_Observer), 'dispatch', Object(Varien_Event_Observer))
#14 /home/newolders/public_html/store/app/Mage.php(448): Mage_Core_Model_App->dispatchEvent('default', Array)
#15 /home/newolders/public_html/store/cron.php(76): Mage::dispatchEvent('default')
#16 {main}

Có ai giúp tôi không?


Phiên bản magento nào, bạn đang sử dụng?
Amit Bera

Ông trả lời trong tiêu đề. Tính năng này chỉ xuất hiện trong 1.9.1.x
zhartaunik

YEAH thật tuyệt! Tôi có cùng một vấn đề. Và trong khi gửi đầu ra nhật ký của tôi dưới dạng câu trả lời (vì không có khoảng trống trong bình luận) thì không đúng (được một số mod đề cập) nhưng việc chỉnh sửa câu hỏi và thêm nhật ký cũng bị bất kỳ ai từ chối. vậy wtf. với bạn đó là điều dối trá?! một lần nữa nhật ký hiển thị rằng thuộc tính được xử lý đã được điền chính xác nhưng truy vấn cập nhật bị xây dựng sai. Sry nhưng tôi không thể cho bạn xem nhật ký vì một số người thực sự đáng sợ quanh đây. -, - nuff nói
Manuel Richarz

@Elias Soares: Bạn có chạy tiện ích mở rộng AOE_Scheduler không?
Manuel Richarz

Câu trả lời:


2

Tôi không chắc liệu bạn có tìm thấy giải pháp trong thời gian đó không, nhưng gần đây tôi đã gặp vấn đề tương tự trên máy chủ của khách hàng.

Điều đã xảy ra thực sự giống nhau, công việc cron core_email_queue_send_all đã gửi cùng một email nhiều lần và mỗi lần ngoại lệ giống như bạn tìm thấy đã được thêm vào nhật ký ngoại lệ.

Công việc định kỳ đã gửi cùng một email nhiều lần vì processed_attrường không được lưu trong core_email_queuebảng cho các thư tương ứng.

Tôi đã thêm một số nhật ký vào mã và xem xét cách truy vấn lưu core_email_queuetin nhắn được xây dựng và lý do tại sao nó thiếu phần SET của nó (cần chứa các cột cần cập nhật):

UPDATE `core_email_queue` SET  WHERE (message_id='3')'

Trong Magento, trước khi xây dựng các truy vấn cơ sở dữ liệu, các cột được sử dụng trong truy vấn sẽ được kiểm tra đối với các mô tả cột cho bảng tương ứng bên trong Mage_Core_Model_Resource_Abstract::_prepareDataForTablephương thức bằng cách gọi:

$fields = $this->_getWriteAdapter()->describeTable($table);

Để không thực hiện truy vấn MÔ TẢ mỗi lần, Magento lưu trữ thông tin DDL cho các bảng. Bên trong Varien_Db_Adapter_Pdo_Mysql::describeTablephương thức bộ đệm được kiểm tra đầu tiên:

public function describeTable($tableName, $schemaName = null)
{
    $cacheKey = $this->_getTableName($tableName, $schemaName);
    $ddl = $this->loadDdlCache($cacheKey, self::DDL_DESCRIBE);
    if ($ddl === false) {
        $ddl = array_map(
            array(
                $this,
                'decorateTableInfo'
            ),
            parent::describeTable($tableName, $schemaName)
        );
        /**
        * Remove bug in some MySQL versions, when int-column without default value is described as:
        * having default empty string value
        */
        $affected = array('tinyint', 'smallint', 'mediumint', 'int', 'bigint');
        foreach ($ddl as $key => $columnData) {
            if (($columnData['DEFAULT'] === '') && (array_search($columnData['DATA_TYPE'], $affected) !== FALSE)) {
                $ddl[$key]['DEFAULT'] = null;
            }
        }
        $this->saveDdlCache($cacheKey, self::DDL_DESCRIBE, $ddl);
    }

    return $ddl;
}

Tôi thấy rằng các cột nhận được từ bộ nhớ cache cho các core_email_queuebảng, không phải là những người mong đợi, thay vì đôi khi họ là: data, lifetime, expirepriority.

Điều này chỉ ra một vấn đề về bộ đệm và tôi thấy rằng việc Zend_Cache_Corelưu dữ liệu vào các tệp bộ đệm DDL, đôi khi bằng cách gọi Zend_Cache_Backend_File::save()trực tiếp và đôi khi bằng cách gọi Zend_Cache_Backend_TwoLevels::save().

Bộ đệm hai cấp độ từ Zend sử dụng _prepareDataphương pháp để xây dựng một mảng được tuần tự hóa để lưu trữ dữ liệu và thông tin siêu dữ liệu:

private function _prepareData($data, $lifetime, $priority)
{
    $lt = $lifetime;
    if ($lt === null) {
        $lt = 9999999999;
    }
    return serialize(array(
        'data' => $data,
        'lifetime' => $lifetime,
        'expire' => time() + $lt,
        'priority' => $priority
    ));
}

Cuối cùng, vấn đề là cron (đã gửi email) được gọi từ dòng lệnh. So sánh một yêu cầu từ trình duyệt với một yêu cầu dòng lệnh, tôi thấy rằng Mage_Core_Model_Cache::getBackendOptionsđã trả về các tùy chọn khác nhau. Máy chủ này được thiết lập để sử dụng bộ đệm APC, tuy nhiên khi cron đang chạy ini_get(‘apc.enabled’)là sai.

Trên máy chủ này có 2 tệp cấu hình php fpm / php.ini trong đó apc.enables1cli / php.ini trong đó apc.enables0 . Do đó, phiên bản Magento được chạy từ dòng lệnh không thể sử dụng bộ đệm APC, do đó nó không sử dụng bộ đệm hai cấp, dẫn đến việc nó không biết cách đọc chính xác dữ liệu từ các tệp bộ đệm.

Các fpm Magento dụ sử dụng APC và mức độ bộ nhớ cache hai và được lưu dữ liệu DDL vào var / cache thư mục kèm theo trong một mảng với data, lifetime, expireprioritycác phím. Khi ran cron và đọc các file DDL cache, nó được sử dụng tìm thấy dữ liệu đó và về cơ bản xem xét cho từng bảng, rằng các cột là data, lifetime, expirepriority.

Việc thay đổi apc.enables thành 1 trong tệp cấu hình cli / php.ini đã thực hiện thủ thuật và giải quyết vấn đề.

Nếu bạn quan tâm đến việc đọc thêm về cách tôi gỡ lỗi vấn đề này, bạn có thể xem qua phần giải thích chi tiết hơn mà tôi đã viết cho một bài đăng trên blog: http://ayg.ro/magento-cron-twolevel-cache-su-pdoexception- sqlstate-42s22-và-sqlstate-42000


Tôi đã giải quyết điều này theo một cách khác mà tôi không nhắc nữa. NHƯNG, giải pháp của bạn được giải thích rất tốt và có ý nghĩa với tôi, vì vậy tôi sẽ đánh dấu là câu trả lời đúng, vì điều này có thể giúp nhiều người có vấn đề tương tự!
Elias Soares

4

Vấn đề này phải liên quan đến hệ thống Hàng đợi Email Magento mới, để lại các bản ghi mồ côi trên bảng Người nhận. Nếu đây là vấn đề của bạn, tôi gửi cho bạn một sửa chữa.

Hệ thống hàng đợi email Magento mới quản lý hai bảng này: core_email_queuecore_email_queue_reciprons . Cái trước xử lý các Tin nhắn email, và cái sau, Người nhận các tin nhắn này.

Bảng core_email_queue được xóa sạch khi các email trên Hàng đợi email Magento được gửi. Việc dọn dẹp này được thực hiện bởi một công việc tab cron có tên core_email_queue_clean_up , được xác định bên trong tệp cấu hình app / code / core / Mage / Core / etc / config.xm l. Mã thực hiện việc dọn dẹp được xác định trên hàm removeSentMessages trong lớp Mage_Core_Model_Resource_Email_Queue :

/**
 * Remove already sent messages
 *
 * @return Mage_Core_Model_Resource_Email_Queue
 */
public function removeSentMessages()
{
    $this->_getWriteAdapter()->delete($this->getMainTable(), 'processed_at IS NOT NULL');
    return $this;
}

Đoạn mã trên được thực thi mỗi ngày một lần bởi tác vụ cron.

Nhưng điều đó xảy ra là bảng core_email_queue_reciprons (bảng chứa Người nhận email và được liên kết với bảng core_email_queue bởi trường message_id ), không được làm sạch cùng với bảng core_email_queue (bảng giữ các bản ghi email) mà bảng Người nhận khi đó Bảng tin được xóa sạch.

Vấn đề được mô tả ở đây phát sinh khi bảng core_email_queue (Tin nhắn) được đặt lại và trường message_id tự động trên bảng này được khởi tạo lại thành 1.

Vì bảng core_email_queue_reciprons (Người nhận) chưa được làm sạch tương ứng, khi các email mới được thêm vào Hàng đợi email Magento, các bản ghi mới được tạo trên bảng core_email_queue (với message_id bắt đầu lại từ 1), đồng thời các bản ghi mới được tạo lại từ 1) trên bảng core_email_queue_reciprons có cùng các id này (bắt đầu lại từ 1).

Vấn đề là những id này có thể đã tồn tại trên bảng Người nhận dưới dạng bản ghi mồ côi (do các thông báo email trước đó). Các id mesage mới này sau đó được lặp lại bên trong bảng core_email_queue_reciprons . Cuối cùng, các Tin nhắn email khác nhau được liên kết với Người nhận tương ứng của họ bởi message_id , nhưng chúng cũng được liên kết sai với những người nhận trước đó được gán cùng một message_id từ các email trước đó.

Do đó, khi người nhận được tìm kiếm để gửi một tin nhắn nhất định, bên cạnh người nhận thích hợp, những người nhận sai khác có thể phát sinh.

May mắn là sửa chữa cho vấn đề này là dễ dàng để thực hiện.

Tất cả những gì cần thiết là làm sạch tất cả các id tin nhắn lặp lại trên bảng core_email_queue_reciprons và đảm bảo rằng khi một Tin nhắn bị xóa trên bảng core_email_queue , đồng thời, những Người nhận tương ứng của nó sẽ bị xóa trên bảng core_email_queue_reciprons .

Cách tốt nhất để đạt được điều này là tạo một khóa ngoại liên kết các bản ghi này và xóa chúng trên tầng (nhưng bạn cần thực hiện một số thao tác dọn dẹp trước khi bạn có thể làm điều đó).

Đây là thủ tục để khắc phục sự cố:

1) Thực hiện hai truy vấn SQL đang theo dõi để xóa bảng core_email_queue_reciprons khỏi các bản ghi mồ côi và id tin nhắn lặp lại:

DELETE FROM core_email_queue_recipients WHERE message_id NOT IN (SELECT message_id FROM core_email_queue);
DELETE FROM core_email_queue_recipients WHERE recipient_id < (SELECT recipient_id FROM (SELECT recipient_id FROM core_email_queue_recipients ORDER BY message_id ASC, recipient_id DESC LIMIT 1) AS r);

Truy vấn đầu tiên xóa các bản ghi mồ côi và truy vấn thứ hai xóa các bản ghi cũ không còn hiệu lực.

2) Tạo khóa ngoại trên bảng core_email_queue_reciprons để xóa các bản ghi Người nhận trên tầng. Truy vấn SQL để tạo khóa ngoại này là:

ALTER TABLE core_email_queue_recipients ADD FOREIGN KEY(message_id) REFERENCES core_email_queue(message_id) ON DELETE CASCADE;

Bằng cách sử dụng khóa ngoại mới này, sẽ không còn bản ghi mồ côi nào trên bảng core_email_queue_reciprons khi làm sạch bảng core_email_queue và sẽ không gửi tin nhắn trùng lặp đến người nhận sai trong tương lai.


1

Như bạn có thể thấy truy vấn của bạn

UPDATE `core_email_queue` SET  WHERE (message_id='3')'

không có gì để thiết lập. Tôi nghĩ ở đây magento đang cố gắng thiết lập một số trạng thái có nghĩa là 'thư đã được gửi'. Tôi không chắc chắn, có thể cập nhật trườngprocessed_at

cập nhật.1

Có vẻ như ý tưởng đã đúng. Trước khi lưu, chúng tôi có cái này (Mage / Core / Model / Email / Queue.php (244)):

$message->setProcessedAt(Varien_Date::formatDate(true));

Bạn có thể sau này

Mage::log(Varien_Date::formatDate(true));
Mage::log($message->getData());

Và cho chúng tôi thấy kết quả.

cập nhật.2

Tôi đã không tái tạo vấn đề được mô tả. Tôi có

Ubuntu 14.04.2 LTS

phiên bản nginx: nginx / 1.4.6 (Ubuntu)

Phiên bản PHP 5.5.9-1ubfox4.9

Phiên bản máy chủ MySQL 5.6.19

Magento ver. 1.9.1.0

Cấu hình của bạn là gì?


Có, nhưng tôi không thể tìm thấy nơi sửa nó trong mã magento ...: /
Elias Soares

Tôi đang xem nó .. Bạn có thể đưa vào bài đăng đầu tiên của mình vài bước làm thế nào để kích hoạt tính năng này để xuất hiện một số hàng trong bảng này không? Hoặc cho chúng tôi xem bảng này
zhartaunik

Chờ đợi thông tin chi tiết từ bạn
zhartaunik

Chỉ cần cài đặt mới Magento 1.9.1 và các lỗi xảy ra. Tạo một ví dụ đặt hàng và vấn đề sẽ xảy ra khi nó cố gắng gửi thư xác nhận đơn hàng.
Elias Soares

1
như đã đề cập trong bình luận ở trên: Xử lý được đặt chính xác. tôi đã cố gắng đào sâu hơn và thấy rằng đôi khi : $ this -> _ getWriteAd Module () -> descriptionTable ($ bảng); kết quả trong mô tả bảng sai. Nó trả về không phải là các cột của email_queue. nó sẽ trả về cột như thế này: dữ liệu, cuộc đời, hết hạn, ưu tiên Và đôi khi các cột bên phải: message_id, ENTITY_ID, ENTITY_TYPE, MESSAGE_BODY, ..., processed_at
Manuel Richarz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.